sys/mman.h: guard mmapobj() with __UNLEASHED_VISIBLE
[unleashed.git] / usr / src / cmd / sgs / tsort / common / tsort.c
blob3b97f075fb313d935cdc0fcf3eb9544a75769cba
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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"
34 * topological sort
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
41 #include "errmsg.h"
42 #include "stdio.h"
43 #include "string.h"
44 #include <locale.h>
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() */
55 #define STR(X) #X
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. */
60 static
61 struct nodelist {
62 struct nodelist *nextnode;
63 struct predlist *inedges;
64 char *name;
65 int live;
66 } firstnode = {NULL, NULL, NULL, DEAD};
69 * a predecessor list tells all the immediate
70 * predecessors of a given node
72 struct predlist {
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
87 int
88 main(int argc, char **argv)
90 struct predlist *t;
91 FILE *input = stdin;
92 struct nodelist *i, *j;
93 int x;
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 */
99 #endif
100 (void) textdomain(TEXT_DOMAIN);
102 errprefix("UX");
103 errsource(*argv);
104 errverb("notag,notofix");
105 switch (argc) {
106 case 1:
107 break;
108 case 2:
109 if (strcmp(argv[1], "-") == 0)
110 break;
111 if (strcmp(argv[1], "--") == 0)
112 break;
113 input = zfopen(EERROR, argv[1], "r");
114 break;
115 case 3:
116 if (strcmp(argv[1], "--") != 0)
117 errusage(gettext("[ file ]"));
118 input = zfopen(EERROR, argv[2], "r");
119 break;
120 default:
121 errusage("[ file ]");
123 for (;;) {
124 x = fscanf(input, FORMAT, precedes, follows);
125 if (x == EOF)
126 break;
127 if (x != 2)
128 errmsg(EERROR, gettext("odd data"));
129 i = index(precedes);
130 j = index(follows);
131 if (i == j || present(i, j))
132 continue;
133 t = (struct predlist *)
134 zmalloc(EERROR, sizeof (struct predlist));
135 t->nextpred = j->inedges;
136 t->pred = i;
137 j->inedges = t;
139 for (;;) {
140 x = 0; /* anything LIVE on this sweep? */
141 for (i = &firstnode; i->nextnode != NULL; i = i->nextnode) {
142 if (i->live == LIVE) {
143 x = 1;
144 if (!anypred(i))
145 break;
148 if (x == 0)
149 break;
150 if (i->nextnode == NULL)
151 i = findloop();
152 (void) puts(i->name);
153 i->live = DEAD;
155 return (0); /* Ensure zero return on normal termination */
159 * is i present on j's predecessor list?
161 static int
162 present(struct nodelist *i, struct nodelist *j)
164 struct predlist *t;
165 for (t = j->inedges; t != NULL; t = t->nextpred)
166 if (t->pred == i)
167 return (1);
168 return (0);
172 * is there any live predecessor for i?
174 static int
175 anypred(struct nodelist *i)
177 struct predlist *t;
178 for (t = i->inedges; t != NULL; t = t->nextpred)
179 if (t->pred->live == LIVE)
180 return (1);
181 return (0);
185 * turn a string into a node pointer
187 static struct nodelist *
188 index(char *s)
190 struct nodelist *i;
191 char *t;
192 for (i = &firstnode; i->nextnode != NULL; i = i->nextnode)
193 if (strcmp(s, i->name) == 0)
194 return (i);
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));
199 i->name = t;
200 i->live = LIVE;
201 i->nextnode->nextnode = NULL;
202 i->nextnode->inedges = NULL;
203 i->nextnode->live = DEAD;
204 while (*t++ = *s++);
205 return (i);
209 * given that there is a cycle, find some
210 * node in it
212 static struct nodelist *
213 findloop(void)
215 struct nodelist *i, *j;
217 for (i = &firstnode; i->nextnode != NULL; i = i->nextnode)
218 if (i->live == LIVE)
219 break;
220 errmsg(EINFO, "cycle in data");
221 i = mark(i);
222 if (i == NULL)
223 errmsg(EHALT, gettext("program error"));
224 for (j = &firstnode; j->nextnode != NULL; j = j->nextnode)
225 if (j->live == VISITED)
226 j->live = LIVE;
227 return (i);
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)
239 struct nodelist *j;
240 struct predlist *t;
242 if (i->live == DEAD)
243 return (NULL);
244 if (i->live == VISITED)
245 return (i);
246 i->live = VISITED;
247 for (t = i->inedges; t != NULL; t = t->nextpred) {
248 j = mark(t->pred);
249 if (j != NULL) {
250 (void) fprintf(stderr, "\t%s\n", i->name);
251 return (j);
254 return (NULL);