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