Introduction
Introduction Statistics Contact Development Disclaimer Help
tsort.c - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
tsort.c (3727B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <ctype.h>
6
7 #include "util.h"
8
9 enum { WHITE = 0, GREY, BLACK };
10
11 struct vertex;
12
13 struct edge {
14 struct vertex *to;
15 struct edge *next;
16 };
17
18 struct vertex {
19 char *name;
20 struct vertex *next;
21 struct edge edges;
22 size_t in_edges;
23 int colour;
24 };
25
26 static struct vertex graph;
27
28 static void
29 find_vertex(const char *name, struct vertex **it, struct vertex **prev)
30 {
31 for (*prev = &graph; (*it = (*prev)->next); *prev = *it) {
32 int cmp = strcmp(name, (*it)->name);
33 if (cmp > 0)
34 continue;
35 if (cmp < 0)
36 *it = 0;
37 return;
38 }
39 }
40
41 static void
42 find_edge(struct vertex *from, const char *to, struct edge **it, struct …
43 {
44 for (*prev = &(from->edges); (*it = (*prev)->next); *prev = *it)…
45 int cmp = strcmp(to, (*it)->to->name);
46 if (cmp > 0)
47 continue;
48 if (cmp < 0)
49 *it = 0;
50 return;
51 }
52 }
53
54 static struct vertex *
55 add_vertex(char *name)
56 {
57 struct vertex *vertex;
58 struct vertex *prev;
59
60 find_vertex(name, &vertex, &prev);
61 if (vertex)
62 return vertex;
63
64 vertex = encalloc(2, 1, sizeof(*vertex));
65 vertex->name = name;
66 vertex->next = prev->next;
67 prev->next = vertex;
68
69 return vertex;
70 }
71
72 static struct edge *
73 add_edge(struct vertex *from, struct vertex* to)
74 {
75 struct edge *edge;
76 struct edge *prev;
77
78 find_edge(from, to->name, &edge, &prev);
79 if (edge)
80 return edge;
81
82 edge = encalloc(2, 1, sizeof(*edge));
83 edge->to = to;
84 edge->next = prev->next;
85 prev->next = edge;
86 to->in_edges += 1;
87
88 return edge;
89 }
90
91 static void
92 load_graph(FILE *fp)
93 {
94 #define SKIP(VAR, START, FUNC) for (VAR = START; FUNC(*VAR) && *VAR; VA…
95 #define TOKEN_END(P) do { if (*P) *P++ = 0; else P = 0; } whi…
96
97 char *line = 0;
98 size_t size = 0;
99 ssize_t len;
100 char *p;
101 char *name;
102 struct vertex *from = 0;
103
104 while ((len = getline(&line, &size, fp)) != -1) {
105 if (line[len - 1] == '\n')
106 line[--len] = 0;
107 for (p = line; p;) {
108 SKIP(name, p, isspace);
109 if (!*name)
110 break;
111 SKIP(p, name, !isspace);
112 TOKEN_END(p);
113 if (!from) {
114 from = add_vertex(enstrdup(2, name));
115 } else if (strcmp(from->name, name)) {
116 add_edge(from, add_vertex(enstrdup(2, na…
117 from = 0;
118 } else {
119 from = 0;
120 }
121 }
122 }
123
124 free(line);
125
126 if (from)
127 enprintf(2, "odd number of tokens in input\n");
128 }
129
130 static int
131 sort_graph_visit(struct vertex *u)
132 {
133 struct edge *e = &(u->edges);
134 struct vertex *v;
135 int r = 0;
136 u->colour = GREY;
137 printf("%s\n", u->name);
138 while ((e = e->next)) {
139 v = e->to;
140 if (v->colour == WHITE) {
141 v->in_edges -= 1;
142 if (v->in_edges == 0)
143 r |= sort_graph_visit(v);
144 } else if (v->colour == GREY) {
145 r = 1;
146 fprintf(stderr, "%s: loop detected between %s an…
147 argv0, u->name, v->name);
148 }
149 }
150 u->colour = BLACK;
151 return r;
152 }
153
154 static int
155 sort_graph(void)
156 {
157 struct vertex *u, *prev;
158 int r = 0;
159 size_t in_edges;
160 for (in_edges = 0; graph.next; in_edges++) {
161 for (prev = &graph; (u = prev->next); prev = u) {
162 if (u->colour != WHITE)
163 goto unlist;
164 if (u->in_edges > in_edges)
165 continue;
166 r |= sort_graph_visit(u);
167 unlist:
168 prev->next = u->next;
169 u = prev;
170 }
171 }
172 return r;
173 }
174
175 static void
176 usage(void)
177 {
178 enprintf(2, "usage: %s [file]\n", argv0);
179 }
180
181 int
182 main(int argc, char *argv[])
183 {
184 FILE *fp = stdin;
185 const char *fn = "<stdin>";
186 int ret = 0;
187
188 ARGBEGIN {
189 default:
190 usage();
191 } ARGEND
192
193 if (argc > 1)
194 usage();
195 if (argc && strcmp(*argv, "-"))
196 if (!(fp = fopen(fn = *argv, "r")))
197 enprintf(2, "fopen %s:", *argv);
198
199 memset(&graph, 0, sizeof(graph));
200 load_graph(fp);
201 enfshut(2, fp, fn);
202
203 ret = sort_graph();
204
205 if (fshut(stdout, "<stdout>") | fshut(stderr, "<stderr>"))
206 ret = 2;
207
208 return ret;
209 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.