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