|
|
1.1 root 1: #ifndef lint
2: static char *sccsid = "@(#)dfn.c 1.3 (Berkeley) 1/15/83";
3: #endif lint
4:
5: #include <stdio.h>
6: #include "gprof.h"
7:
8: #define DFN_DEPTH 100
9: struct dfnstruct {
10: nltype *nlentryp;
11: int cycletop;
12: };
13: typedef struct dfnstruct dfntype;
14:
15: dfntype dfn_stack[ DFN_DEPTH ];
16: int dfn_depth = 0;
17:
18: int dfn_counter = DFN_NAN;
19:
20: /*
21: * given this parent, depth first number its children.
22: */
23: dfn( parentp )
24: nltype *parentp;
25: {
26: arctype *arcp;
27:
28: # ifdef DEBUG
29: if ( debug & DFNDEBUG ) {
30: printf( "[dfn] dfn(" );
31: printname( parentp );
32: printf( ")\n" );
33: }
34: # endif DEBUG
35: /*
36: * if we're already numbered, no need to look any furthur.
37: */
38: if ( dfn_numbered( parentp ) ) {
39: return;
40: }
41: /*
42: * if we're already busy, must be a cycle
43: */
44: if ( dfn_busy( parentp ) ) {
45: dfn_findcycle( parentp );
46: return;
47: }
48: /*
49: * visit yourself before your children
50: */
51: dfn_pre_visit( parentp );
52: /*
53: * visit children
54: */
55: for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
56: dfn( arcp -> arc_childp );
57: }
58: /*
59: * visit yourself after your children
60: */
61: dfn_post_visit( parentp );
62: }
63:
64: /*
65: * push a parent onto the stack and mark it busy
66: */
67: dfn_pre_visit( parentp )
68: nltype *parentp;
69: {
70:
71: dfn_depth += 1;
72: if ( dfn_depth >= DFN_DEPTH ) {
73: fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" );
74: exit( 1 );
75: }
76: dfn_stack[ dfn_depth ].nlentryp = parentp;
77: dfn_stack[ dfn_depth ].cycletop = dfn_depth;
78: parentp -> toporder = DFN_BUSY;
79: # ifdef DEBUG
80: if ( debug & DFNDEBUG ) {
81: printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth );
82: printname( parentp );
83: printf( "\n" );
84: }
85: # endif DEBUG
86: }
87:
88: /*
89: * are we already numbered?
90: */
91: bool
92: dfn_numbered( childp )
93: nltype *childp;
94: {
95:
96: return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
97: }
98:
99: /*
100: * are we already busy?
101: */
102: bool
103: dfn_busy( childp )
104: nltype *childp;
105: {
106:
107: if ( childp -> toporder == DFN_NAN ) {
108: return FALSE;
109: }
110: return TRUE;
111: }
112:
113: /*
114: * MISSING: an explanation
115: */
116: dfn_findcycle( childp )
117: nltype *childp;
118: {
119: int cycletop;
120: nltype *cycleheadp;
121: nltype *tailp;
122: int index;
123:
124: for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) {
125: cycleheadp = dfn_stack[ cycletop ].nlentryp;
126: if ( childp == cycleheadp ) {
127: break;
128: }
129: if ( childp -> cyclehead != childp &&
130: childp -> cyclehead == cycleheadp ) {
131: break;
132: }
133: }
134: if ( cycletop <= 0 ) {
135: fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" );
136: exit( 1 );
137: }
138: # ifdef DEBUG
139: if ( debug & DFNDEBUG ) {
140: printf( "[dfn_findcycle] dfn_depth %d cycletop %d " ,
141: dfn_depth , cycletop );
142: printname( cycleheadp );
143: printf( "\n" );
144: }
145: # endif DEBUG
146: if ( cycletop == dfn_depth ) {
147: /*
148: * this is previous function, e.g. this calls itself
149: * sort of boring
150: */
151: dfn_self_cycle( childp );
152: } else {
153: /*
154: * glom intervening functions that aren't already
155: * glommed into this cycle.
156: * things have been glommed when their cyclehead field
157: * points to the head of the cycle they are glommed into.
158: */
159: for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) {
160: /* void: chase down to tail of things already glommed */
161: # ifdef DEBUG
162: if ( debug & DFNDEBUG ) {
163: printf( "[dfn_findcycle] tail " );
164: printname( tailp );
165: printf( "\n" );
166: }
167: # endif DEBUG
168: }
169: /*
170: * if what we think is the top of the cycle
171: * has a cyclehead field, then it's not really the
172: * head of the cycle, which is really what we want
173: */
174: if ( cycleheadp -> cyclehead != cycleheadp ) {
175: cycleheadp = cycleheadp -> cyclehead;
176: # ifdef DEBUG
177: if ( debug & DFNDEBUG ) {
178: printf( "[dfn_findcycle] new cyclehead " );
179: printname( cycleheadp );
180: printf( "\n" );
181: }
182: # endif DEBUG
183: }
184: for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) {
185: childp = dfn_stack[ index ].nlentryp;
186: if ( childp -> cyclehead == childp ) {
187: /*
188: * not yet glommed anywhere, glom it
189: * and fix any children it has glommed
190: */
191: tailp -> cnext = childp;
192: childp -> cyclehead = cycleheadp;
193: # ifdef DEBUG
194: if ( debug & DFNDEBUG ) {
195: printf( "[dfn_findcycle] glomming " );
196: printname( childp );
197: printf( " onto " );
198: printname( cycleheadp );
199: printf( "\n" );
200: }
201: # endif DEBUG
202: for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) {
203: tailp -> cnext -> cyclehead = cycleheadp;
204: # ifdef DEBUG
205: if ( debug & DFNDEBUG ) {
206: printf( "[dfn_findcycle] and its tail " );
207: printname( tailp -> cnext );
208: printf( " onto " );
209: printname( cycleheadp );
210: printf( "\n" );
211: }
212: # endif DEBUG
213: }
214: } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) {
215: fprintf( stderr ,
216: "[dfn_busy] glommed, but not to cyclehead\n" );
217: }
218: }
219: }
220: }
221:
222: /*
223: * deal with self-cycles
224: * for lint: ARGSUSED
225: */
226: dfn_self_cycle( parentp )
227: nltype *parentp;
228: {
229: /*
230: * since we are taking out self-cycles elsewhere
231: * no need for the special case, here.
232: */
233: # ifdef DEBUG
234: if ( debug & DFNDEBUG ) {
235: printf( "[dfn_self_cycle] " );
236: printname( parentp );
237: printf( "\n" );
238: }
239: # endif DEBUG
240: }
241:
242: /*
243: * visit a node after all its children
244: * [MISSING: an explanation]
245: * and pop it off the stack
246: */
247: dfn_post_visit( parentp )
248: nltype *parentp;
249: {
250: nltype *memberp;
251:
252: # ifdef DEBUG
253: if ( debug & DFNDEBUG ) {
254: printf( "[dfn_post_visit]\t%d: " , dfn_depth );
255: printname( parentp );
256: printf( "\n" );
257: }
258: # endif DEBUG
259: /*
260: * number functions and things in their cycles
261: * unless the function is itself part of a cycle
262: */
263: if ( parentp -> cyclehead == parentp ) {
264: dfn_counter += 1;
265: for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) {
266: memberp -> toporder = dfn_counter;
267: # ifdef DEBUG
268: if ( debug & DFNDEBUG ) {
269: printf( "[dfn_post_visit]\t\tmember " );
270: printname( memberp );
271: printf( " -> toporder = %d\n" , dfn_counter );
272: }
273: # endif DEBUG
274: }
275: } else {
276: # ifdef DEBUG
277: if ( debug & DFNDEBUG ) {
278: printf( "[dfn_post_visit]\t\tis part of a cycle\n" );
279: }
280: # endif DEBUG
281: }
282: dfn_depth -= 1;
283: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.