BSD 4_4 release
[unix-history] / usr / src / usr.bin / struct / struct / 2.dfs.c
CommitLineData
0fc6e47b 1/*-
ad787160
C
2 * This module is believed to contain source code proprietary to AT&T.
3 * Use and redistribution is subject to the Berkeley Software License
4 * Agreement and your Software Agreement with AT&T (Western Electric).
0fc6e47b
KB
5 */
6
89b0e8d6 7#ifndef lint
ad787160 8static char sccsid[] = "@(#)2.dfs.c 8.1 (Berkeley) 6/6/93";
0fc6e47b 9#endif /* not lint */
89b0e8d6
RH
10
11#include <stdio.h>
12#
13/* depth-first search used to identify back edges, unreachable nodes;
14 each node v entered by back edge replaced by
15 LOOPVX ->ITERVX -> v,
16 so that back edges entering v now enter the ITERVX,
17 and other edges entering v now enter the LOOPVX.
18 Nodes are numbered according to depth-first search:
19 before numbering- ntobef[v] = i => node numbered v is i'th
20 node in order of first visit during the search;
21 after numbering- ntoaft[v] = i => node numbered v is i'th
22 node visited in order of last visit during the search.
23 Also, in this case after[i] = v.
24*/
25
26#include "def.h"
27#include "2.def.h"
28
29#define MAXINS 3 /* spacing needed between numbers generated during depth first search */
30
31int *status;
32int befcount, aftcount;
33/* following defines used to mark back edges and nodes entered by back edges */
34#define UNPROCESSED 0
35#define STACKED 1
36#define FINISHED 2
37#define MARK(v) {REACH(v) = 1; } /* mark node v */
38#define UNMARK(v) {REACH(v) = 0; }
39#define MARKED(v) (REACH(v))
40#define MKEDGE(e) {if (e >= -1) e = -(e+3); } /* mark edge e */
41#define UNMKEDGE(e) {if (e < -1) e = -(e+3); }
42#define BACKEDGE(e) (e < -1)
43
44
45dfs(v) /* depth first search */
46VERT v;
47 {
48 int i; VERT w;
49 accessnum = 0;
50 status = challoc(sizeof(*status) * nodenum);
51 for (w = 0; w < nodenum; ++w)
52 {
53 status[w] = UNPROCESSED;
54 UNMARK(w);
55 }
56 search(v);
57 chreach();
58 chfree(status, sizeof(*status) * nodenum);
59 addloop();
60 after = challoc(sizeof(*after) * accessnum);
61 for (i = 0; i < accessnum; ++i)
62 after[i] = UNDEFINED;
63 ntoaft = challoc(sizeof(*ntoaft) * nodenum);
64 ntobef = challoc(sizeof(*ntobef) * nodenum);
65 for (w = 0; w < nodenum; ++w)
66 ntobef[w] = ntoaft[w] = UNDEFINED;
67 befcount = 0;
68 aftcount = 0;
69 repsearch(v);
70 }
71
72
73search(v)
74 /* using depth first search, mark back edges using MKEDGE, and nodes entered by back
75 edges using MARK */
76VERT v;
77 {
78 VERT adj; int i;
79 status[v] = STACKED;
80 for(i = 0; i < ARCNUM(v); ++i)
81 {
82 adj = ARC(v,i);
83 if (!DEFINED(adj)) continue;
84 else if (status[adj] == UNPROCESSED)
85 search(adj);
86 else if (status[adj] == STACKED)
87 {
88 MARK(adj); /* mark adj as entered by back edge */
89 MKEDGE(ARC(v,i)); /* mark edge ARC(v,i) as being back edge */
90 }
91 }
92 status[v] = FINISHED;
93 ++accessnum;
94 }
95
96chreach() /* look for unreachable nodes */
97 {
98 VERT v;
99 LOGICAL unreach;
100 unreach = FALSE;
101 for (v = 0; v < nodenum; ++v)
102 if (status[v] == UNPROCESSED && NTYPE(v) != FMTVX
103 && NTYPE(v) != STOPVX && NTYPE(v) != RETVX)
104 {
105 unreach = TRUE;
106 if (debug)
107 fprintf(stderr,"node %d unreachable\n",v);
108 }
109 if (unreach)
110 error(": unreachable statements - ","will be ignored","");
111 }
112
113
114addloop() /* add LOOPVX, ITERVX at nodes entered by back edges, and adjust edges */
115 {
116 VERT v, adj;
117 int j, oldnum;
118 for (v = 0, oldnum = nodenum; v < oldnum; ++v) /* insloop increases nodenum */
119 if (MARKED(v))
120 {
121 UNMARK(v); /* remove mark indicating v entered by back edge */
122 if (NTYPE(v) != ITERVX) /* DO loops already have ITERVX */
123 insloop(v); /* add LOOPVX, ITERVX since v entered by back edge*/
124 }
125 /* arcs which used to enter v now enter LOOPVX; must make back edges enter ITERVX */
126 for (v = 0; v < nodenum; ++v)
127 for (j = 0; j < ARCNUM(v); ++j)
128 {
129 if (BACKEDGE(ARC(v,j)))
130 {
131 UNMKEDGE(ARC(v,j)); /* return edge to normal value */
132 adj = ARC(v,j);
133 if (NTYPE(adj) == ITERVX) continue;
134 ASSERT(NTYPE(adj) == LOOPVX,addloop);
135 ARC(v,j) = ARC(adj,0); /* change arc to point to ITERVX */
136 ASSERT(NTYPE(ARC(v,j)) == ITERVX,addloop);
137 }
138 }
139 }
140
141insloop(v) /* insert LOOPVX, ITERVX at node number v */
142VERT v;
143 {
144 VERT loo, iter;
145 loo = create(LOOPVX, 1);
146 iter = create(ITERVX,1);
147 accessnum += 2;
148 /* want LOOPVX to take on node number v, so that arcs other than back arcs
149 entering v will enter the LOOPVX automatically */
150 exchange(&graph[v], &graph[loo]);
151 exchange(&v, &loo);
152 ARC(loo,0) = iter;
153 ARC(iter,0) = v;
154 FATH(iter) = UNDEFINED; /* will be defined later along with FATH for DOVX */
155 }
156
157exchange(p1,p2) /* exchange values of p1,p2 */
158int *p1,*p2;
159 {
160 int temp;
161 temp = *p1;
162 *p1 = *p2;
163 *p2 = temp;
164 }
165
166
167repsearch(v) /* repeat df search in order to fill in after, ntoaft, ntobef tables */
168VERT v;
169 {
170 VERT adj; int i,temp;
171 ntobef[v] = befcount;
172 ++befcount;
173 for(i = 0; i < ARCNUM(v); ++i)
174 {
175 adj = ARC(v,i);
176 if (DEFINED(adj) && ntobef[adj] == UNDEFINED)
177 repsearch(adj);
178 }
179 ++aftcount;
180 temp = accessnum - aftcount;
181 after[temp] = v;
182 ntoaft[v] = temp;
183 }