Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/std/tsort.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1989-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
static const char usage[] =
23
"[-?\n@(#)$Id: tsort (AT&T Research) 2000-03-23 $\n]"
24
USAGE_LICENSE
25
"[+NAME?tsort - topological sort]"
26
"[+DESCRIPTION?\btsort\b writes to the standard output a totally ordered"
27
" list of items consistent with a partial ordering of items contained"
28
" in the input \afile\a. If \afile\a is omitted then the standard"
29
" input is read.]"
30
"[+?The input consists of pairs of items (non-empty strings) separated by"
31
" blanks. Pairs of different items indicate ordering. Pairs of"
32
" identical items indicate presence, but not ordering.]"
33
34
"\n"
35
"\n[ file ]\n"
36
"\n"
37
38
"[+SEE ALSO?\bcomm\b(1), \bsort\b(1), \buniq\b(1)]"
39
;
40
41
#include <ast.h>
42
#include <error.h>
43
#include <hash.h>
44
45
#define NODE_INIT 0
46
#define NODE_CYCLE 1
47
#define NODE_DONE 2
48
49
struct List_s;
50
51
typedef struct Node_s
52
{
53
HASH_HEADER;
54
struct List_s* prereqs;
55
int state;
56
} Node_t;
57
58
typedef struct List_s
59
{
60
struct List_s* next;
61
Node_t* node;
62
} List_t;
63
64
static int
65
visit(register Node_t* x)
66
{
67
register List_t* p;
68
int cycle = 0;
69
70
switch (x->state)
71
{
72
case NODE_CYCLE:
73
error(1, "cycle in data");
74
cycle = 1;
75
break;
76
case NODE_INIT:
77
x->state = NODE_CYCLE;
78
for (p = x->prereqs; p; p = p->next)
79
if (visit(p->node))
80
{
81
cycle = 1;
82
error(2, " %s", hashname((Hash_bucket_t*)x));
83
break;
84
}
85
x->state = NODE_DONE;
86
sfputr(sfstdout, hashname((Hash_bucket_t*)x), '\n');
87
break;
88
}
89
return cycle;
90
}
91
92
static void
93
tsort(Sfio_t* ip)
94
{
95
register int c;
96
register char* s;
97
register char* b;
98
Node_t* head = 0;
99
Node_t* x;
100
List_t* p;
101
Hash_table_t* tab;
102
Hash_position_t* pos;
103
104
if (!(tab = hashalloc(NiL, HASH_set, HASH_ALLOCATE, 0)))
105
error(ERROR_exit(1), "out of space [hash table]");
106
while (s = sfgetr(ip, '\n', 1))
107
{
108
do
109
{
110
while (*s == ' ' || *s == '\t')
111
s++;
112
if (*s == 0)
113
break;
114
for (b = s; (c = *s) && c != ' ' && c != '\t'; s++);
115
*s++ = 0;
116
if (!(x = (Node_t*)hashlook(tab, b, HASH_CREATE|HASH_SIZE(sizeof(Node_t)), 0)))
117
error(ERROR_exit(1), "out of space [hash entry]");
118
if (head)
119
{
120
if (head != x)
121
{
122
if (!(p = newof(0, List_t, 1, 0)))
123
error(ERROR_exit(1), "out of space [hash list]");
124
p->node = head;
125
p->next = x->prereqs;
126
x->prereqs = p;
127
}
128
head = 0;
129
}
130
else
131
head = x;
132
} while (c);
133
}
134
if (sfvalue(ip))
135
error(ERROR_warn(1), "last line incomplete");
136
if (head)
137
error(ERROR_exit(1), "odd data");
138
if (pos = hashscan(tab, 0))
139
{
140
while (hashnext(pos))
141
visit((Node_t*)pos->bucket);
142
hashdone(pos);
143
}
144
else
145
error(ERROR_exit(1), "hash error");
146
hashfree(tab);
147
}
148
149
int
150
main(int argc, char** argv)
151
{
152
Sfio_t* ip;
153
154
NoP(argc);
155
error_info.id = "tsort";
156
for (;;)
157
{
158
switch (optget(argv, usage))
159
{
160
case ':':
161
error(2, "%s", opt_info.arg);
162
break;
163
case '?':
164
error(ERROR_usage(2), "%s", opt_info.arg);
165
break;
166
}
167
break;
168
}
169
argv += opt_info.index;
170
if (error_info.errors)
171
error(ERROR_usage(2), "%s", optusage(NiL));
172
if (!*argv || streq(*argv, "-") || streq(*argv, "/dev/stdin"))
173
ip = sfstdin;
174
else if (!(ip = sfopen(NiL, *argv, "r")))
175
error(ERROR_system(1), "%s cannot open", *argv);
176
tsort(ip);
177
if (ip != sfstdin)
178
sfclose(ip);
179
return error_info.errors != 0;
180
}
181
182