don't need dir.h
[unix-history] / usr / src / usr.bin / gprof / dfn.c
CommitLineData
c0bc4ef7
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
ddb85eed
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
2124b336
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
c0bc4ef7
DF
16 */
17
4f1db472 18#ifndef lint
2124b336 19static char sccsid[] = "@(#)dfn.c 5.3 (Berkeley) %G%";
ddb85eed 20#endif /* not lint */
4f1db472
PK
21
22#include <stdio.h>
31f0a970 23#include "gprof.h"
4f1db472
PK
24
25#define DFN_DEPTH 100
26struct dfnstruct {
27 nltype *nlentryp;
28 int cycletop;
29};
30typedef struct dfnstruct dfntype;
31
32dfntype dfn_stack[ DFN_DEPTH ];
33int dfn_depth = 0;
34
80ebf400 35int dfn_counter = DFN_NAN;
4f1db472
PK
36
37 /*
38 * given this parent, depth first number its children.
39 */
40dfn( parentp )
41 nltype *parentp;
42{
43 arctype *arcp;
44
45# ifdef DEBUG
46 if ( debug & DFNDEBUG ) {
47 printf( "[dfn] dfn(" );
48 printname( parentp );
49 printf( ")\n" );
50 }
51# endif DEBUG
52 /*
53 * if we're already numbered, no need to look any furthur.
54 */
55 if ( dfn_numbered( parentp ) ) {
56 return;
57 }
58 /*
59 * if we're already busy, must be a cycle
60 */
61 if ( dfn_busy( parentp ) ) {
62 dfn_findcycle( parentp );
63 return;
64 }
65 /*
66 * visit yourself before your children
67 */
68 dfn_pre_visit( parentp );
69 /*
70 * visit children
71 */
72 for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
73 dfn( arcp -> arc_childp );
74 }
75 /*
76 * visit yourself after your children
77 */
78 dfn_post_visit( parentp );
79}
80
81 /*
82 * push a parent onto the stack and mark it busy
83 */
84dfn_pre_visit( parentp )
85 nltype *parentp;
86{
87
88 dfn_depth += 1;
89 if ( dfn_depth >= DFN_DEPTH ) {
90 fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" );
91 exit( 1 );
92 }
93 dfn_stack[ dfn_depth ].nlentryp = parentp;
94 dfn_stack[ dfn_depth ].cycletop = dfn_depth;
95 parentp -> toporder = DFN_BUSY;
96# ifdef DEBUG
97 if ( debug & DFNDEBUG ) {
98 printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth );
99 printname( parentp );
100 printf( "\n" );
101 }
102# endif DEBUG
103}
104
105 /*
106 * are we already numbered?
107 */
108bool
109dfn_numbered( childp )
110 nltype *childp;
111{
112
80ebf400 113 return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
4f1db472
PK
114}
115
116 /*
117 * are we already busy?
118 */
119bool
120dfn_busy( childp )
121 nltype *childp;
122{
123
80ebf400 124 if ( childp -> toporder == DFN_NAN ) {
4f1db472
PK
125 return FALSE;
126 }
127 return TRUE;
128}
129
130 /*
131 * MISSING: an explanation
132 */
133dfn_findcycle( childp )
134 nltype *childp;
135{
136 int cycletop;
137 nltype *cycleheadp;
138 nltype *tailp;
139 int index;
140
141 for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) {
142 cycleheadp = dfn_stack[ cycletop ].nlentryp;
143 if ( childp == cycleheadp ) {
144 break;
145 }
146 if ( childp -> cyclehead != childp &&
147 childp -> cyclehead == cycleheadp ) {
148 break;
149 }
150 }
151 if ( cycletop <= 0 ) {
152 fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" );
153 exit( 1 );
154 }
155# ifdef DEBUG
156 if ( debug & DFNDEBUG ) {
157 printf( "[dfn_findcycle] dfn_depth %d cycletop %d " ,
158 dfn_depth , cycletop );
159 printname( cycleheadp );
160 printf( "\n" );
161 }
162# endif DEBUG
163 if ( cycletop == dfn_depth ) {
164 /*
165 * this is previous function, e.g. this calls itself
166 * sort of boring
167 */
168 dfn_self_cycle( childp );
169 } else {
170 /*
171 * glom intervening functions that aren't already
172 * glommed into this cycle.
173 * things have been glommed when their cyclehead field
174 * points to the head of the cycle they are glommed into.
175 */
176 for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) {
177 /* void: chase down to tail of things already glommed */
178# ifdef DEBUG
179 if ( debug & DFNDEBUG ) {
180 printf( "[dfn_findcycle] tail " );
181 printname( tailp );
182 printf( "\n" );
183 }
184# endif DEBUG
185 }
186 /*
187 * if what we think is the top of the cycle
188 * has a cyclehead field, then it's not really the
189 * head of the cycle, which is really what we want
190 */
191 if ( cycleheadp -> cyclehead != cycleheadp ) {
192 cycleheadp = cycleheadp -> cyclehead;
193# ifdef DEBUG
194 if ( debug & DFNDEBUG ) {
195 printf( "[dfn_findcycle] new cyclehead " );
196 printname( cycleheadp );
197 printf( "\n" );
198 }
199# endif DEBUG
200 }
201 for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) {
202 childp = dfn_stack[ index ].nlentryp;
203 if ( childp -> cyclehead == childp ) {
204 /*
205 * not yet glommed anywhere, glom it
206 * and fix any children it has glommed
207 */
208 tailp -> cnext = childp;
209 childp -> cyclehead = cycleheadp;
210# ifdef DEBUG
211 if ( debug & DFNDEBUG ) {
212 printf( "[dfn_findcycle] glomming " );
213 printname( childp );
214 printf( " onto " );
215 printname( cycleheadp );
216 printf( "\n" );
217 }
218# endif DEBUG
219 for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) {
220 tailp -> cnext -> cyclehead = cycleheadp;
221# ifdef DEBUG
222 if ( debug & DFNDEBUG ) {
223 printf( "[dfn_findcycle] and its tail " );
224 printname( tailp -> cnext );
225 printf( " onto " );
226 printname( cycleheadp );
227 printf( "\n" );
228 }
229# endif DEBUG
230 }
231 } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) {
232 fprintf( stderr ,
233 "[dfn_busy] glommed, but not to cyclehead\n" );
234 }
235 }
236 }
237}
238
239 /*
240 * deal with self-cycles
241 * for lint: ARGSUSED
242 */
243dfn_self_cycle( parentp )
244 nltype *parentp;
245{
246 /*
247 * since we are taking out self-cycles elsewhere
248 * no need for the special case, here.
249 */
250# ifdef DEBUG
251 if ( debug & DFNDEBUG ) {
252 printf( "[dfn_self_cycle] " );
253 printname( parentp );
254 printf( "\n" );
255 }
256# endif DEBUG
257}
258
259 /*
260 * visit a node after all its children
261 * [MISSING: an explanation]
262 * and pop it off the stack
263 */
264dfn_post_visit( parentp )
265 nltype *parentp;
266{
267 nltype *memberp;
268
269# ifdef DEBUG
270 if ( debug & DFNDEBUG ) {
271 printf( "[dfn_post_visit]\t%d: " , dfn_depth );
272 printname( parentp );
273 printf( "\n" );
274 }
275# endif DEBUG
276 /*
277 * number functions and things in their cycles
278 * unless the function is itself part of a cycle
279 */
280 if ( parentp -> cyclehead == parentp ) {
281 dfn_counter += 1;
282 for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) {
283 memberp -> toporder = dfn_counter;
284# ifdef DEBUG
285 if ( debug & DFNDEBUG ) {
286 printf( "[dfn_post_visit]\t\tmember " );
287 printname( memberp );
288 printf( " -> toporder = %d\n" , dfn_counter );
289 }
290# endif DEBUG
291 }
292 } else {
293# ifdef DEBUG
294 if ( debug & DFNDEBUG ) {
295 printf( "[dfn_post_visit]\t\tis part of a cycle\n" );
296 }
297# endif DEBUG
298 }
299 dfn_depth -= 1;
300}