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