|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
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.
16: */
17:
18: #ifndef lint
19: static char sccsid[] = "@(#)dfn.c 5.3 (Berkeley) 6/29/88";
20: #endif /* not lint */
21:
22: #include <stdio.h>
23: #include "gprof.h"
24:
25: #define DFN_DEPTH 100
26: struct dfnstruct {
27: nltype *nlentryp;
28: int cycletop;
29: };
30: typedef struct dfnstruct dfntype;
31:
32: dfntype dfn_stack[ DFN_DEPTH ];
33: int dfn_depth = 0;
34:
35: int dfn_counter = DFN_NAN;
36:
37: /*
38: * given this parent, depth first number its children.
39: */
40: dfn( 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: */
84: dfn_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: */
108: bool
109: dfn_numbered( childp )
110: nltype *childp;
111: {
112:
113: return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
114: }
115:
116: /*
117: * are we already busy?
118: */
119: bool
120: dfn_busy( childp )
121: nltype *childp;
122: {
123:
124: if ( childp -> toporder == DFN_NAN ) {
125: return FALSE;
126: }
127: return TRUE;
128: }
129:
130: /*
131: * MISSING: an explanation
132: */
133: dfn_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: */
243: dfn_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: */
264: dfn_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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.