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