4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 /* Copyright (c) 1988 AT&T */
29 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
35 * input is sequence of pairs of items (blank-free strings)
36 * nonidentical pair is a directed edge in graph
37 * identical pair merely indicates presence of node
38 * output is ordered list of items consistent with
39 * the partial ordering specified by the graph
47 * the nodelist always has an empty element at the end to
48 * make it easy to grow in natural order
49 * states of the "live" field:
51 #define DEAD 0 /* already printed */
52 #define LIVE 1 /* not yet printed */
53 #define VISITED 2 /* used only in findloop() */
56 #define XSTR(X) STR(X)
57 #define FORMAT "%" XSTR(FILENAME_MAX) "s%" XSTR(FILENAME_MAX) "s"
58 /* These should make FORMAT "%1024s%1024s", if FILENAME_MAX is 1024. */
62 struct nodelist
*nextnode
;
63 struct predlist
*inedges
;
66 } firstnode
= {NULL
, NULL
, NULL
, DEAD
};
69 * a predecessor list tells all the immediate
70 * predecessors of a given node
73 struct predlist
*nextpred
;
74 struct nodelist
*pred
;
77 static struct nodelist
*index(char *s
);
78 static struct nodelist
*findloop(void);
79 static struct nodelist
*mark(struct nodelist
*i
);
80 static int present(struct nodelist
*i
, struct nodelist
*j
);
81 static int anypred(struct nodelist
*i
);
84 * the first for loop reads in the graph,
85 * the second prints out the ordering
88 main(int argc
, char **argv
)
92 struct nodelist
*i
, *j
;
94 char precedes
[FILENAME_MAX
+1], follows
[FILENAME_MAX
+1];
96 (void) setlocale(LC_ALL
, "");
97 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
98 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if not previously defined */
100 (void) textdomain(TEXT_DOMAIN
);
104 errverb("notag,notofix");
109 if (strcmp(argv
[1], "-") == 0)
111 if (strcmp(argv
[1], "--") == 0)
113 input
= zfopen(EERROR
, argv
[1], "r");
116 if (strcmp(argv
[1], "--") != 0)
117 errusage(gettext("[ file ]"));
118 input
= zfopen(EERROR
, argv
[2], "r");
121 errusage("[ file ]");
124 x
= fscanf(input
, FORMAT
, precedes
, follows
);
128 errmsg(EERROR
, gettext("odd data"));
131 if (i
== j
|| present(i
, j
))
133 t
= (struct predlist
*)
134 zmalloc(EERROR
, sizeof (struct predlist
));
135 t
->nextpred
= j
->inedges
;
140 x
= 0; /* anything LIVE on this sweep? */
141 for (i
= &firstnode
; i
->nextnode
!= NULL
; i
= i
->nextnode
) {
142 if (i
->live
== LIVE
) {
150 if (i
->nextnode
== NULL
)
152 (void) puts(i
->name
);
155 return (0); /* Ensure zero return on normal termination */
159 * is i present on j's predecessor list?
162 present(struct nodelist
*i
, struct nodelist
*j
)
165 for (t
= j
->inedges
; t
!= NULL
; t
= t
->nextpred
)
172 * is there any live predecessor for i?
175 anypred(struct nodelist
*i
)
178 for (t
= i
->inedges
; t
!= NULL
; t
= t
->nextpred
)
179 if (t
->pred
->live
== LIVE
)
185 * turn a string into a node pointer
187 static struct nodelist
*
192 for (i
= &firstnode
; i
->nextnode
!= NULL
; i
= i
->nextnode
)
193 if (strcmp(s
, i
->name
) == 0)
195 for (t
= s
; *t
; t
++);
196 t
= zmalloc(EERROR
, (unsigned)(t
+ 1 - s
));
197 i
->nextnode
= (struct nodelist
*)
198 zmalloc(EERROR
, sizeof (struct nodelist
));
201 i
->nextnode
->nextnode
= NULL
;
202 i
->nextnode
->inedges
= NULL
;
203 i
->nextnode
->live
= DEAD
;
209 * given that there is a cycle, find some
212 static struct nodelist
*
215 struct nodelist
*i
, *j
;
217 for (i
= &firstnode
; i
->nextnode
!= NULL
; i
= i
->nextnode
)
220 errmsg(EINFO
, "cycle in data");
223 errmsg(EHALT
, gettext("program error"));
224 for (j
= &firstnode
; j
->nextnode
!= NULL
; j
= j
->nextnode
)
225 if (j
->live
== VISITED
)
231 * depth-first search of LIVE predecessors
232 * to find some element of a cycle;
233 * VISITED is a temporary state recording the
234 * visits of the search
236 static struct nodelist
*
237 mark(struct nodelist
*i
)
244 if (i
->live
== VISITED
)
247 for (t
= i
->inedges
; t
!= NULL
; t
= t
->nextpred
) {
250 (void) fprintf(stderr
, "\t%s\n", i
->name
);