Annotation of src/usr.bin/gprof/dfn.c, Revision 1.7
1.7 ! deraadt 1: /* $OpenBSD: dfn.c,v 1.6 2006/03/25 19:06:35 espie Exp $ */
1.1 deraadt 2: /* $NetBSD: dfn.c,v 1.5 1995/04/19 07:15:56 cgd Exp $ */
3:
4: /*
5: * Copyright (c) 1983, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.5 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #include <stdio.h>
34: #include "gprof.h"
35:
36: #define DFN_DEPTH 100
37: struct dfnstruct {
38: nltype *nlentryp;
39: int cycletop;
40: };
41: typedef struct dfnstruct dfntype;
42:
43: dfntype dfn_stack[ DFN_DEPTH ];
44: int dfn_depth;
45:
46: int dfn_counter;
47:
1.3 mickey 48: void
1.1 deraadt 49: dfn_init()
50: {
51:
52: dfn_depth = 0;
53: dfn_counter = DFN_NAN;
54: }
55:
56: /*
57: * given this parent, depth first number its children.
58: */
1.3 mickey 59: void
1.6 espie 60: dfn(nltype *parentp)
1.1 deraadt 61: {
62: arctype *arcp;
63:
64: # ifdef DEBUG
65: if ( debug & DFNDEBUG ) {
66: printf( "[dfn] dfn(" );
67: printname( parentp );
68: printf( ")\n" );
69: }
1.4 danh 70: # endif /* DEBUG */
1.1 deraadt 71: /*
72: * if we're already numbered, no need to look any furthur.
73: */
74: if ( dfn_numbered( parentp ) ) {
75: return;
76: }
77: /*
78: * if we're already busy, must be a cycle
79: */
80: if ( dfn_busy( parentp ) ) {
81: dfn_findcycle( parentp );
82: return;
83: }
84: /*
85: * visit yourself before your children
86: */
87: dfn_pre_visit( parentp );
88: /*
89: * visit children
90: */
91: for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
92: if ( arcp -> arc_flags & DEADARC )
93: continue;
94: dfn( arcp -> arc_childp );
95: }
96: /*
97: * visit yourself after your children
98: */
99: dfn_post_visit( parentp );
100: }
101:
102: /*
103: * push a parent onto the stack and mark it busy
104: */
1.3 mickey 105: void
1.6 espie 106: dfn_pre_visit(nltype *parentp)
1.1 deraadt 107: {
108:
109: dfn_depth += 1;
1.3 mickey 110: if ( dfn_depth >= DFN_DEPTH )
111: errx(1, "[dfn] out of my depth (dfn_stack overflow)" );
1.1 deraadt 112: dfn_stack[ dfn_depth ].nlentryp = parentp;
113: dfn_stack[ dfn_depth ].cycletop = dfn_depth;
114: parentp -> toporder = DFN_BUSY;
115: # ifdef DEBUG
116: if ( debug & DFNDEBUG ) {
117: printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth );
118: printname( parentp );
119: printf( "\n" );
120: }
1.4 danh 121: # endif /* DEBUG */
1.1 deraadt 122: }
123:
124: /*
125: * are we already numbered?
126: */
127: bool
1.6 espie 128: dfn_numbered(nltype *childp)
1.1 deraadt 129: {
130:
131: return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
132: }
133:
134: /*
135: * are we already busy?
136: */
137: bool
1.6 espie 138: dfn_busy(nltype *childp)
1.1 deraadt 139: {
140:
141: if ( childp -> toporder == DFN_NAN ) {
142: return FALSE;
143: }
144: return TRUE;
145: }
146:
147: /*
148: * MISSING: an explanation
149: */
1.3 mickey 150: void
1.6 espie 151: dfn_findcycle(nltype *childp)
1.1 deraadt 152: {
153: int cycletop;
154: nltype *cycleheadp;
155: nltype *tailp;
156: int index;
157:
158: for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) {
159: cycleheadp = dfn_stack[ cycletop ].nlentryp;
160: if ( childp == cycleheadp ) {
161: break;
162: }
163: if ( childp -> cyclehead != childp &&
164: childp -> cyclehead == cycleheadp ) {
165: break;
166: }
167: }
1.3 mickey 168: if ( cycletop <= 0 )
169: errx( 1, "[dfn_findcycle] couldn't find head of cycle");
1.1 deraadt 170: # ifdef DEBUG
171: if ( debug & DFNDEBUG ) {
172: printf( "[dfn_findcycle] dfn_depth %d cycletop %d " ,
173: dfn_depth , cycletop );
174: printname( cycleheadp );
175: printf( "\n" );
176: }
1.4 danh 177: # endif /* DEBUG */
1.1 deraadt 178: if ( cycletop == dfn_depth ) {
179: /*
180: * this is previous function, e.g. this calls itself
181: * sort of boring
182: */
183: dfn_self_cycle( childp );
184: } else {
185: /*
186: * glom intervening functions that aren't already
187: * glommed into this cycle.
188: * things have been glommed when their cyclehead field
189: * points to the head of the cycle they are glommed into.
190: */
191: for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) {
192: /* void: chase down to tail of things already glommed */
193: # ifdef DEBUG
194: if ( debug & DFNDEBUG ) {
195: printf( "[dfn_findcycle] tail " );
196: printname( tailp );
197: printf( "\n" );
198: }
1.4 danh 199: # endif /* DEBUG */
1.1 deraadt 200: }
201: /*
202: * if what we think is the top of the cycle
203: * has a cyclehead field, then it's not really the
204: * head of the cycle, which is really what we want
205: */
206: if ( cycleheadp -> cyclehead != cycleheadp ) {
207: cycleheadp = cycleheadp -> cyclehead;
208: # ifdef DEBUG
209: if ( debug & DFNDEBUG ) {
210: printf( "[dfn_findcycle] new cyclehead " );
211: printname( cycleheadp );
212: printf( "\n" );
213: }
1.4 danh 214: # endif /* DEBUG */
1.1 deraadt 215: }
216: for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) {
217: childp = dfn_stack[ index ].nlentryp;
218: if ( childp -> cyclehead == childp ) {
219: /*
220: * not yet glommed anywhere, glom it
221: * and fix any children it has glommed
222: */
223: tailp -> cnext = childp;
224: childp -> cyclehead = cycleheadp;
225: # ifdef DEBUG
226: if ( debug & DFNDEBUG ) {
227: printf( "[dfn_findcycle] glomming " );
228: printname( childp );
229: printf( " onto " );
230: printname( cycleheadp );
231: printf( "\n" );
232: }
1.4 danh 233: # endif /* DEBUG */
1.1 deraadt 234: for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) {
235: tailp -> cnext -> cyclehead = cycleheadp;
236: # ifdef DEBUG
237: if ( debug & DFNDEBUG ) {
238: printf( "[dfn_findcycle] and its tail " );
239: printname( tailp -> cnext );
240: printf( " onto " );
241: printname( cycleheadp );
242: printf( "\n" );
243: }
1.4 danh 244: # endif /* DEBUG */
1.1 deraadt 245: }
1.3 mickey 246: } else if ( childp -> cyclehead != cycleheadp /* firewall */ )
247: warnx("[dfn_busy] glommed, but not to cyclehead");
1.1 deraadt 248: }
249: }
250: }
251:
252: /*
253: * deal with self-cycles
254: * for lint: ARGSUSED
255: */
1.3 mickey 256: void
1.6 espie 257: dfn_self_cycle(nltype *parentp)
1.1 deraadt 258: {
259: /*
260: * since we are taking out self-cycles elsewhere
261: * no need for the special case, here.
262: */
263: # ifdef DEBUG
264: if ( debug & DFNDEBUG ) {
265: printf( "[dfn_self_cycle] " );
266: printname( parentp );
267: printf( "\n" );
268: }
1.4 danh 269: # endif /* DEBUG */
1.1 deraadt 270: }
271:
272: /*
273: * visit a node after all its children
274: * [MISSING: an explanation]
275: * and pop it off the stack
276: */
1.3 mickey 277: void
1.6 espie 278: dfn_post_visit(nltype *parentp)
1.1 deraadt 279: {
280: nltype *memberp;
281:
282: # ifdef DEBUG
283: if ( debug & DFNDEBUG ) {
284: printf( "[dfn_post_visit]\t%d: " , dfn_depth );
285: printname( parentp );
286: printf( "\n" );
287: }
1.4 danh 288: # endif /* DEBUG */
1.1 deraadt 289: /*
290: * number functions and things in their cycles
291: * unless the function is itself part of a cycle
292: */
293: if ( parentp -> cyclehead == parentp ) {
294: dfn_counter += 1;
295: for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) {
296: memberp -> toporder = dfn_counter;
297: # ifdef DEBUG
298: if ( debug & DFNDEBUG ) {
299: printf( "[dfn_post_visit]\t\tmember " );
300: printname( memberp );
301: printf( " -> toporder = %d\n" , dfn_counter );
302: }
1.4 danh 303: # endif /* DEBUG */
1.1 deraadt 304: }
305: } else {
306: # ifdef DEBUG
307: if ( debug & DFNDEBUG ) {
308: printf( "[dfn_post_visit]\t\tis part of a cycle\n" );
309: }
1.4 danh 310: # endif /* DEBUG */
1.1 deraadt 311: }
312: dfn_depth -= 1;
313: }