Commit | Line | Data |
---|---|---|
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 | 8 | static 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 | ||
31 | int *status; | |
32 | int 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 | ||
45 | dfs(v) /* depth first search */ | |
46 | VERT 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 | ||
73 | search(v) | |
74 | /* using depth first search, mark back edges using MKEDGE, and nodes entered by back | |
75 | edges using MARK */ | |
76 | VERT 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 | ||
96 | chreach() /* 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 | ||
114 | addloop() /* 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 | ||
141 | insloop(v) /* insert LOOPVX, ITERVX at node number v */ | |
142 | VERT 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 | ||
157 | exchange(p1,p2) /* exchange values of p1,p2 */ | |
158 | int *p1,*p2; | |
159 | { | |
160 | int temp; | |
161 | temp = *p1; | |
162 | *p1 = *p2; | |
163 | *p2 = temp; | |
164 | } | |
165 | ||
166 | ||
167 | repsearch(v) /* repeat df search in order to fill in after, ntoaft, ntobef tables */ | |
168 | VERT 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 | } |