xref: /csrg-svn/usr.bin/gprof/dfn.c (revision 62017)
121959Sdist /*
2*62017Sbostic  * Copyright (c) 1983, 1993
3*62017Sbostic  *	The Regents of the University of California.  All rights reserved.
434199Sbostic  *
542683Sbostic  * %sccs.include.redist.c%
621959Sdist  */
721959Sdist 
84509Speter #ifndef lint
9*62017Sbostic static char sccsid[] = "@(#)dfn.c	8.1 (Berkeley) 06/06/93";
1034199Sbostic #endif /* not lint */
114509Speter 
124509Speter #include <stdio.h>
134560Speter #include "gprof.h"
144509Speter 
154509Speter #define	DFN_DEPTH	100
164509Speter struct dfnstruct {
174509Speter     nltype	*nlentryp;
184509Speter     int		cycletop;
194509Speter };
204509Speter typedef struct dfnstruct	dfntype;
214509Speter 
224509Speter dfntype	dfn_stack[ DFN_DEPTH ];
2352651Smckusick int	dfn_depth;
244509Speter 
2552651Smckusick int	dfn_counter;
264509Speter 
dfn_init()2752651Smckusick dfn_init()
2852651Smckusick {
2952651Smckusick 
3052651Smckusick     dfn_depth = 0;
3152651Smckusick     dfn_counter = DFN_NAN;
3252651Smckusick }
3352651Smckusick 
344509Speter     /*
354509Speter      *	given this parent, depth first number its children.
364509Speter      */
dfn(parentp)374509Speter dfn( parentp )
384509Speter     nltype	*parentp;
394509Speter {
404509Speter     arctype	*arcp;
414509Speter 
424509Speter #   ifdef DEBUG
434509Speter 	if ( debug & DFNDEBUG ) {
444509Speter 	    printf( "[dfn] dfn(" );
454509Speter 	    printname( parentp );
464509Speter 	    printf( ")\n" );
474509Speter 	}
484509Speter #   endif DEBUG
494509Speter 	/*
504509Speter 	 *	if we're already numbered, no need to look any furthur.
514509Speter 	 */
524509Speter     if ( dfn_numbered( parentp ) ) {
534509Speter 	return;
544509Speter     }
554509Speter 	/*
564509Speter 	 *	if we're already busy, must be a cycle
574509Speter 	 */
584509Speter     if ( dfn_busy( parentp ) ) {
594509Speter 	dfn_findcycle( parentp );
604509Speter 	return;
614509Speter     }
624509Speter 	/*
634509Speter 	 *	visit yourself before your children
644509Speter 	 */
654509Speter     dfn_pre_visit( parentp );
664509Speter 	/*
674509Speter 	 *	visit children
684509Speter 	 */
694509Speter     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
7052651Smckusick 	    if ( arcp -> arc_flags & DEADARC )
7152651Smckusick 		continue;
724509Speter 	    dfn( arcp -> arc_childp );
734509Speter     }
744509Speter 	/*
754509Speter 	 *	visit yourself after your children
764509Speter 	 */
774509Speter     dfn_post_visit( parentp );
784509Speter }
794509Speter 
804509Speter     /*
814509Speter      *	push a parent onto the stack and mark it busy
824509Speter      */
dfn_pre_visit(parentp)834509Speter dfn_pre_visit( parentp )
844509Speter     nltype	*parentp;
854509Speter {
864509Speter 
874509Speter     dfn_depth += 1;
884509Speter     if ( dfn_depth >= DFN_DEPTH ) {
894509Speter 	fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" );
904509Speter 	exit( 1 );
914509Speter     }
924509Speter     dfn_stack[ dfn_depth ].nlentryp = parentp;
934509Speter     dfn_stack[ dfn_depth ].cycletop = dfn_depth;
944509Speter     parentp -> toporder = DFN_BUSY;
954509Speter #   ifdef DEBUG
964509Speter 	if ( debug & DFNDEBUG ) {
974509Speter 	    printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth );
984509Speter 	    printname( parentp );
994509Speter 	    printf( "\n" );
1004509Speter 	}
1014509Speter #   endif DEBUG
1024509Speter }
1034509Speter 
1044509Speter     /*
1054509Speter      *	are we already numbered?
1064509Speter      */
1074509Speter bool
dfn_numbered(childp)1084509Speter dfn_numbered( childp )
1094509Speter     nltype	*childp;
1104509Speter {
1114509Speter 
11210284Speter     return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
1134509Speter }
1144509Speter 
1154509Speter     /*
1164509Speter      *	are we already busy?
1174509Speter      */
1184509Speter bool
dfn_busy(childp)1194509Speter dfn_busy( childp )
1204509Speter     nltype	*childp;
1214509Speter {
1224509Speter 
12310284Speter     if ( childp -> toporder == DFN_NAN ) {
1244509Speter 	return FALSE;
1254509Speter     }
1264509Speter     return TRUE;
1274509Speter }
1284509Speter 
1294509Speter     /*
1304509Speter      *	MISSING: an explanation
1314509Speter      */
dfn_findcycle(childp)1324509Speter dfn_findcycle( childp )
1334509Speter     nltype	*childp;
1344509Speter {
1354509Speter     int		cycletop;
1364509Speter     nltype	*cycleheadp;
1374509Speter     nltype	*tailp;
1384509Speter     int		index;
1394509Speter 
1404509Speter     for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) {
1414509Speter 	cycleheadp = dfn_stack[ cycletop ].nlentryp;
1424509Speter 	if ( childp == cycleheadp ) {
1434509Speter 	    break;
1444509Speter 	}
1454509Speter 	if ( childp -> cyclehead != childp &&
1464509Speter 	    childp -> cyclehead == cycleheadp ) {
1474509Speter 	    break;
1484509Speter 	}
1494509Speter     }
1504509Speter     if ( cycletop <= 0 ) {
1514509Speter 	fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" );
1524509Speter 	exit( 1 );
1534509Speter     }
1544509Speter #   ifdef DEBUG
1554509Speter 	if ( debug & DFNDEBUG ) {
1564509Speter 	    printf( "[dfn_findcycle] dfn_depth %d cycletop %d " ,
1574509Speter 		    dfn_depth , cycletop  );
1584509Speter 	    printname( cycleheadp );
1594509Speter 	    printf( "\n" );
1604509Speter 	}
1614509Speter #   endif DEBUG
1624509Speter     if ( cycletop == dfn_depth ) {
1634509Speter 	    /*
1644509Speter 	     *	this is previous function, e.g. this calls itself
1654509Speter 	     *	sort of boring
1664509Speter 	     */
1674509Speter 	dfn_self_cycle( childp );
1684509Speter     } else {
1694509Speter 	    /*
1704509Speter 	     *	glom intervening functions that aren't already
1714509Speter 	     *	glommed into this cycle.
1724509Speter 	     *	things have been glommed when their cyclehead field
1734509Speter 	     *	points to the head of the cycle they are glommed into.
1744509Speter 	     */
1754509Speter 	for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) {
1764509Speter 	    /* void: chase down to tail of things already glommed */
1774509Speter #	    ifdef DEBUG
1784509Speter 		if ( debug & DFNDEBUG ) {
1794509Speter 		    printf( "[dfn_findcycle] tail " );
1804509Speter 		    printname( tailp );
1814509Speter 		    printf( "\n" );
1824509Speter 		}
1834509Speter #	    endif DEBUG
1844509Speter 	}
1854509Speter 	    /*
1864509Speter 	     *	if what we think is the top of the cycle
1874509Speter 	     *	has a cyclehead field, then it's not really the
1884509Speter 	     *	head of the cycle, which is really what we want
1894509Speter 	     */
1904509Speter 	if ( cycleheadp -> cyclehead != cycleheadp ) {
1914509Speter 	    cycleheadp = cycleheadp -> cyclehead;
1924509Speter #	    ifdef DEBUG
1934509Speter 		if ( debug & DFNDEBUG ) {
1944509Speter 		    printf( "[dfn_findcycle] new cyclehead " );
1954509Speter 		    printname( cycleheadp );
1964509Speter 		    printf( "\n" );
1974509Speter 		}
1984509Speter #	    endif DEBUG
1994509Speter 	}
2004509Speter 	for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) {
2014509Speter 	    childp = dfn_stack[ index ].nlentryp;
2024509Speter 	    if ( childp -> cyclehead == childp ) {
2034509Speter 		    /*
2044509Speter 		     *	not yet glommed anywhere, glom it
2054509Speter 		     *	and fix any children it has glommed
2064509Speter 		     */
2074509Speter 		tailp -> cnext = childp;
2084509Speter 		childp -> cyclehead = cycleheadp;
2094509Speter #		ifdef DEBUG
2104509Speter 		    if ( debug & DFNDEBUG ) {
2114509Speter 			printf( "[dfn_findcycle] glomming " );
2124509Speter 			printname( childp );
2134509Speter 			printf( " onto " );
2144509Speter 			printname( cycleheadp );
2154509Speter 			printf( "\n" );
2164509Speter 		    }
2174509Speter #		endif DEBUG
2184509Speter 		for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) {
2194509Speter 		    tailp -> cnext -> cyclehead = cycleheadp;
2204509Speter #		    ifdef DEBUG
2214509Speter 			if ( debug & DFNDEBUG ) {
2224509Speter 			    printf( "[dfn_findcycle] and its tail " );
2234509Speter 			    printname( tailp -> cnext );
2244509Speter 			    printf( " onto " );
2254509Speter 			    printname( cycleheadp );
2264509Speter 			    printf( "\n" );
2274509Speter 			}
2284509Speter #		    endif DEBUG
2294509Speter 		}
2304509Speter 	    } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) {
2314509Speter 		fprintf( stderr ,
2324509Speter 			"[dfn_busy] glommed, but not to cyclehead\n" );
2334509Speter 	    }
2344509Speter 	}
2354509Speter     }
2364509Speter }
2374509Speter 
2384509Speter     /*
2394509Speter      *	deal with self-cycles
2404509Speter      *	for lint: ARGSUSED
2414509Speter      */
dfn_self_cycle(parentp)2424509Speter dfn_self_cycle( parentp )
2434509Speter     nltype	*parentp;
2444509Speter {
2454509Speter 	/*
2464509Speter 	 *	since we are taking out self-cycles elsewhere
2474509Speter 	 *	no need for the special case, here.
2484509Speter 	 */
2494509Speter #   ifdef DEBUG
2504509Speter 	if ( debug & DFNDEBUG ) {
2514509Speter 	    printf( "[dfn_self_cycle] " );
2524509Speter 	    printname( parentp );
2534509Speter 	    printf( "\n" );
2544509Speter 	}
2554509Speter #   endif DEBUG
2564509Speter }
2574509Speter 
2584509Speter     /*
2594509Speter      *	visit a node after all its children
2604509Speter      *	[MISSING: an explanation]
2614509Speter      *	and pop it off the stack
2624509Speter      */
dfn_post_visit(parentp)2634509Speter dfn_post_visit( parentp )
2644509Speter     nltype	*parentp;
2654509Speter {
2664509Speter     nltype	*memberp;
2674509Speter 
2684509Speter #   ifdef DEBUG
2694509Speter 	if ( debug & DFNDEBUG ) {
2704509Speter 	    printf( "[dfn_post_visit]\t%d: " , dfn_depth );
2714509Speter 	    printname( parentp );
2724509Speter 	    printf( "\n" );
2734509Speter 	}
2744509Speter #   endif DEBUG
2754509Speter 	/*
2764509Speter 	 *	number functions and things in their cycles
2774509Speter 	 *	unless the function is itself part of a cycle
2784509Speter 	 */
2794509Speter     if ( parentp -> cyclehead == parentp ) {
2804509Speter 	dfn_counter += 1;
2814509Speter 	for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) {
2824509Speter 	    memberp -> toporder = dfn_counter;
2834509Speter #	    ifdef DEBUG
2844509Speter 		if ( debug & DFNDEBUG ) {
2854509Speter 		    printf( "[dfn_post_visit]\t\tmember " );
2864509Speter 		    printname( memberp );
2874509Speter 		    printf( " -> toporder = %d\n" , dfn_counter );
2884509Speter 		}
2894509Speter #	    endif DEBUG
2904509Speter 	}
2914509Speter     } else {
2924509Speter #	ifdef DEBUG
2934509Speter 	    if ( debug & DFNDEBUG ) {
2944509Speter 		printf( "[dfn_post_visit]\t\tis part of a cycle\n" );
2954509Speter 	    }
2964509Speter #	endif DEBUG
2974509Speter     }
2984509Speter     dfn_depth -= 1;
2994509Speter }
300