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