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