xref: /csrg-svn/usr.bin/gprof/arcs.c (revision 34199)
121957Sdist /*
221957Sdist  * 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.
1121957Sdist  */
1221957Sdist 
134508Speter #ifndef lint
14*34199Sbostic static char sccsid[] = "@(#)arcs.c	5.4 (Berkeley) 05/05/88";
15*34199Sbostic #endif /* not lint */
164508Speter 
174561Speter #include "gprof.h"
184508Speter 
194721Speter     /*
204721Speter      *	add (or just increment) an arc
214721Speter      */
224721Speter addarc( parentp , childp , count )
234721Speter     nltype	*parentp;
244721Speter     nltype	*childp;
254721Speter     long	count;
264721Speter {
274750Speter     arctype		*calloc();
284721Speter     arctype		*arcp;
294721Speter 
304721Speter #   ifdef DEBUG
314721Speter 	if ( debug & TALLYDEBUG ) {
324721Speter 	    printf( "[addarc] %d arcs from %s to %s\n" ,
334721Speter 		    count , parentp -> name , childp -> name );
344721Speter 	}
354721Speter #   endif DEBUG
364721Speter     arcp = arclookup( parentp , childp );
374721Speter     if ( arcp != 0 ) {
384721Speter 	    /*
394721Speter 	     *	a hit:  just increment the count.
404721Speter 	     */
414721Speter #	ifdef DEBUG
424721Speter 	    if ( debug & TALLYDEBUG ) {
434721Speter 		printf( "[tally] hit %d += %d\n" ,
444721Speter 			arcp -> arc_count , count );
454721Speter 	    }
464721Speter #	endif DEBUG
474721Speter 	arcp -> arc_count += count;
484721Speter 	return;
494721Speter     }
504750Speter     arcp = calloc( 1 , sizeof *arcp );
514721Speter     arcp -> arc_parentp = parentp;
524721Speter     arcp -> arc_childp = childp;
534721Speter     arcp -> arc_count = count;
544721Speter 	/*
554721Speter 	 *	prepend this child to the children of this parent
564721Speter 	 */
574721Speter     arcp -> arc_childlist = parentp -> children;
584721Speter     parentp -> children = arcp;
594721Speter 	/*
604721Speter 	 *	prepend this parent to the parents of this child
614721Speter 	 */
624721Speter     arcp -> arc_parentlist = childp -> parents;
634721Speter     childp -> parents = arcp;
644721Speter }
654721Speter 
667172Speter     /*
677172Speter      *	the code below topologically sorts the graph (collapsing cycles),
687172Speter      *	and propagates time bottom up and flags top down.
697172Speter      */
707172Speter 
717172Speter     /*
727172Speter      *	the topologically sorted name list pointers
737172Speter      */
747172Speter nltype	**topsortnlp;
757172Speter 
764508Speter topcmp( npp1 , npp2 )
774508Speter     nltype	**npp1;
784508Speter     nltype	**npp2;
794508Speter {
804508Speter     return (*npp1) -> toporder - (*npp2) -> toporder;
814508Speter }
824508Speter 
8316850Smckusick nltype **
844508Speter doarcs()
854508Speter {
8616850Smckusick     nltype	*parentp, **timesortnlp;
874508Speter     arctype	*arcp;
884508Speter     long	index;
894508Speter 
904508Speter 	/*
914508Speter 	 *	initialize various things:
924508Speter 	 *	    zero out child times.
934508Speter 	 *	    count self-recursive calls.
944508Speter 	 *	    indicate that nothing is on cycles.
954508Speter 	 */
964508Speter     for ( parentp = nl ; parentp < npe ; parentp++ ) {
974508Speter 	parentp -> childtime = 0.0;
984508Speter 	arcp = arclookup( parentp , parentp );
994508Speter 	if ( arcp != 0 ) {
1004508Speter 	    parentp -> ncall -= arcp -> arc_count;
1014508Speter 	    parentp -> selfcalls = arcp -> arc_count;
1024508Speter 	} else {
1034508Speter 	    parentp -> selfcalls = 0;
1044508Speter 	}
1057221Speter 	parentp -> propfraction = 0.0;
1067221Speter 	parentp -> propself = 0.0;
1077221Speter 	parentp -> propchild = 0.0;
1087172Speter 	parentp -> printflag = FALSE;
10910284Speter 	parentp -> toporder = DFN_NAN;
1104508Speter 	parentp -> cycleno = 0;
1114508Speter 	parentp -> cyclehead = parentp;
1124508Speter 	parentp -> cnext = 0;
1137172Speter 	if ( cflag ) {
11425713Ssam 	    findcall( parentp , parentp -> value , (parentp+1) -> value );
1157172Speter 	}
1164508Speter     }
1174508Speter 	/*
1184508Speter 	 *	topologically order things
11910284Speter 	 *	if any node is unnumbered,
12010284Speter 	 *	    number it and any of its descendents.
1214508Speter 	 */
1224508Speter     for ( parentp = nl ; parentp < npe ; parentp++ ) {
12310284Speter 	if ( parentp -> toporder == DFN_NAN ) {
1244508Speter 	    dfn( parentp );
1254508Speter 	}
1264508Speter     }
1274508Speter 	/*
1284508Speter 	 *	link together nodes on the same cycle
1294508Speter 	 */
1304508Speter     cyclelink();
1314508Speter 	/*
1324508Speter 	 *	Sort the symbol table in reverse topological order
1334508Speter 	 */
1344508Speter     topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) );
1354508Speter     if ( topsortnlp == (nltype **) 0 ) {
1364508Speter 	fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" );
1374508Speter     }
1384508Speter     for ( index = 0 ; index < nname ; index += 1 ) {
1394508Speter 	topsortnlp[ index ] = &nl[ index ];
1404508Speter     }
1414508Speter     qsort( topsortnlp , nname , sizeof(nltype *) , topcmp );
1424508Speter #   ifdef DEBUG
1434508Speter 	if ( debug & DFNDEBUG ) {
1444508Speter 	    printf( "[doarcs] topological sort listing\n" );
1454508Speter 	    for ( index = 0 ; index < nname ; index += 1 ) {
1464508Speter 		printf( "[doarcs] " );
1474508Speter 		printf( "%d:" , topsortnlp[ index ] -> toporder );
1484508Speter 		printname( topsortnlp[ index ] );
1494508Speter 		printf( "\n" );
1504508Speter 	    }
1514508Speter 	}
1524508Speter #   endif DEBUG
1534508Speter 	/*
1547221Speter 	 *	starting from the topological top,
1557221Speter 	 *	propagate print flags to children.
1567221Speter 	 *	also, calculate propagation fractions.
1577221Speter 	 *	this happens before time propagation
1587221Speter 	 *	since time propagation uses the fractions.
1597221Speter 	 */
1607221Speter     doflags();
1617221Speter 	/*
1624508Speter 	 *	starting from the topological bottom,
1637172Speter 	 *	propogate children times up to parents.
1644508Speter 	 */
1657172Speter     dotime();
16616850Smckusick 	/*
16716850Smckusick 	 *	Now, sort by propself + propchild.
16816850Smckusick 	 *	sorting both the regular function names
16916850Smckusick 	 *	and cycle headers.
17016850Smckusick 	 */
17116850Smckusick     timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
17216850Smckusick     if ( timesortnlp == (nltype **) 0 ) {
17316850Smckusick 	fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
17416850Smckusick     }
17516850Smckusick     for ( index = 0 ; index < nname ; index++ ) {
17616850Smckusick 	timesortnlp[index] = &nl[index];
17716850Smckusick     }
17816850Smckusick     for ( index = 1 ; index <= ncycle ; index++ ) {
17916850Smckusick 	timesortnlp[nname+index-1] = &cyclenl[index];
18016850Smckusick     }
18116850Smckusick     qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
18216850Smckusick     for ( index = 0 ; index < nname + ncycle ; index++ ) {
18316850Smckusick 	timesortnlp[ index ] -> index = index + 1;
18416850Smckusick     }
18516850Smckusick     return( timesortnlp );
1867172Speter }
1877172Speter 
1887172Speter dotime()
1897172Speter {
1907172Speter     int	index;
1917172Speter 
1927172Speter     cycletime();
1934508Speter     for ( index = 0 ; index < nname ; index += 1 ) {
1947172Speter 	timepropagate( topsortnlp[ index ] );
1957127Speter     }
1967127Speter }
1977127Speter 
1987172Speter timepropagate( parentp )
1997127Speter     nltype	*parentp;
2007127Speter {
2017127Speter     arctype	*arcp;
2027127Speter     nltype	*childp;
2037127Speter     double	share;
2047221Speter     double	propshare;
2057127Speter 
2067221Speter     if ( parentp -> propfraction == 0.0 ) {
2077221Speter 	return;
2087221Speter     }
2097127Speter 	/*
2107127Speter 	 *	gather time from children of this parent.
2117127Speter 	 */
2127172Speter     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
2137127Speter 	childp = arcp -> arc_childp;
2147127Speter 	if ( arcp -> arc_count == 0 ) {
2157127Speter 	    continue;
2167127Speter 	}
2177221Speter 	if ( childp == parentp ) {
2187127Speter 	    continue;
2197127Speter 	}
2207221Speter 	if ( childp -> propfraction == 0.0 ) {
2217127Speter 	    continue;
2227127Speter 	}
2237127Speter 	if ( childp -> cyclehead != childp ) {
2247127Speter 	    if ( parentp -> cycleno == childp -> cycleno ) {
2257127Speter 		continue;
2267127Speter 	    }
2277127Speter 	    if ( parentp -> toporder <= childp -> toporder ) {
2287127Speter 		fprintf( stderr , "[propagate] toporder botches\n" );
2294508Speter 	    }
2307127Speter 	    childp = childp -> cyclehead;
2317127Speter 	} else {
2327127Speter 	    if ( parentp -> toporder <= childp -> toporder ) {
2337127Speter 		fprintf( stderr , "[propagate] toporder botches\n" );
2344508Speter 		continue;
2354508Speter 	    }
2367127Speter 	}
2377221Speter 	if ( childp -> ncall == 0 ) {
2387221Speter 	    continue;
2397221Speter 	}
2407127Speter 	    /*
2417127Speter 	     *	distribute time for this arc
2427127Speter 	     */
2437221Speter 	arcp -> arc_time = childp -> time
2447221Speter 			        * ( ( (double) arcp -> arc_count ) /
2457221Speter 				    ( (double) childp -> ncall ) );
2467221Speter 	arcp -> arc_childtime = childp -> childtime
2477221Speter 			        * ( ( (double) arcp -> arc_count ) /
2487221Speter 				    ( (double) childp -> ncall ) );
2497127Speter 	share = arcp -> arc_time + arcp -> arc_childtime;
2507127Speter 	parentp -> childtime += share;
2517127Speter 	    /*
2527221Speter 	     *	( 1 - propfraction ) gets lost along the way
2537127Speter 	     */
2547221Speter 	propshare = parentp -> propfraction * share;
2557221Speter 	    /*
2567221Speter 	     *	fix things for printing
2577221Speter 	     */
2587221Speter 	parentp -> propchild += propshare;
2597221Speter 	arcp -> arc_time *= parentp -> propfraction;
2607221Speter 	arcp -> arc_childtime *= parentp -> propfraction;
2617221Speter 	    /*
2627221Speter 	     *	add this share to the parent's cycle header, if any.
2637221Speter 	     */
2647127Speter 	if ( parentp -> cyclehead != parentp ) {
2657127Speter 	    parentp -> cyclehead -> childtime += share;
2667221Speter 	    parentp -> cyclehead -> propchild += propshare;
2674508Speter 	}
2687221Speter #	ifdef DEBUG
2697221Speter 	    if ( debug & PROPDEBUG ) {
2707221Speter 		printf( "[dotime] child \t" );
2717221Speter 		printname( childp );
2727221Speter 		printf( " with %f %f %d/%d\n" ,
2737221Speter 			childp -> time , childp -> childtime ,
2747221Speter 			arcp -> arc_count , childp -> ncall );
2757221Speter 		printf( "[dotime] parent\t" );
2767221Speter 		printname( parentp );
2777221Speter 		printf( "\n[dotime] share %f\n" , share );
2787221Speter 	    }
2797221Speter #	endif DEBUG
2804508Speter     }
2814508Speter }
2824508Speter 
2834508Speter cyclelink()
2844508Speter {
2854508Speter     register nltype	*nlp;
2864508Speter     register nltype	*cyclenlp;
2874508Speter     int			cycle;
2887172Speter     nltype		*memberp;
2897248Speter     arctype		*arcp;
2904508Speter 
2914508Speter 	/*
2924508Speter 	 *	Count the number of cycles, and initialze the cycle lists
2934508Speter 	 */
2947127Speter     ncycle = 0;
2954508Speter     for ( nlp = nl ; nlp < npe ; nlp++ ) {
2964508Speter 	    /*
2974508Speter 	     *	this is how you find unattached cycles
2984508Speter 	     */
2994508Speter 	if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) {
3007127Speter 	    ncycle += 1;
3014508Speter 	}
3024508Speter     }
3037127Speter 	/*
3047127Speter 	 *	cyclenl is indexed by cycle number:
3057127Speter 	 *	i.e. it is origin 1, not origin 0.
3067127Speter 	 */
3077127Speter     cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) );
3087127Speter     if ( cyclenl == 0 ) {
3097127Speter 	fprintf( stderr , "%s: No room for %d bytes of cycle headers\n" ,
3107127Speter 		whoami , ( ncycle + 1 ) * sizeof( nltype ) );
3117127Speter 	done();
3124508Speter     }
3134508Speter 	/*
3144508Speter 	 *	now link cycles to true cycleheads,
3154508Speter 	 *	number them, accumulate the data for the cycle
3164508Speter 	 */
3174508Speter     cycle = 0;
3184508Speter     for ( nlp = nl ; nlp < npe ; nlp++ ) {
31910284Speter 	if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) {
3204508Speter 	    continue;
3214508Speter 	}
3224508Speter 	cycle += 1;
3237127Speter 	cyclenlp = &cyclenl[cycle];
3247249Speter         cyclenlp -> name = 0;		/* the name */
3257221Speter         cyclenlp -> value = 0;		/* the pc entry point */
3267221Speter         cyclenlp -> time = 0.0;		/* ticks in this routine */
3277221Speter         cyclenlp -> childtime = 0.0;	/* cumulative ticks in children */
3287221Speter 	cyclenlp -> ncall = 0;		/* how many times called */
3297221Speter 	cyclenlp -> selfcalls = 0;	/* how many calls to self */
3307221Speter 	cyclenlp -> propfraction = 0.0;	/* what % of time propagates */
3317221Speter 	cyclenlp -> propself = 0.0;	/* how much self time propagates */
3327221Speter 	cyclenlp -> propchild = 0.0;	/* how much child time propagates */
3337221Speter 	cyclenlp -> printflag = TRUE;	/* should this be printed? */
3347221Speter 	cyclenlp -> index = 0;		/* index in the graph list */
33510284Speter 	cyclenlp -> toporder = DFN_NAN;	/* graph call chain top-sort order */
3367221Speter 	cyclenlp -> cycleno = cycle;	/* internal number of cycle on */
3377221Speter 	cyclenlp -> cyclehead = cyclenlp;	/* pointer to head of cycle */
3387221Speter 	cyclenlp -> cnext = nlp;	/* pointer to next member of cycle */
3397221Speter 	cyclenlp -> parents = 0;	/* list of caller arcs */
3407221Speter 	cyclenlp -> children = 0;	/* list of callee arcs */
3414508Speter #	ifdef DEBUG
3424508Speter 	    if ( debug & CYCLEDEBUG ) {
3434508Speter 		printf( "[cyclelink] " );
3444508Speter 		printname( nlp );
3454508Speter 		printf( " is the head of cycle %d\n" , cycle );
3464508Speter 	    }
3474508Speter #	endif DEBUG
3487248Speter 	    /*
3497248Speter 	     *	link members to cycle header
3507248Speter 	     */
3517172Speter 	for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
3527172Speter 	    memberp -> cycleno = cycle;
3537172Speter 	    memberp -> cyclehead = cyclenlp;
3547172Speter 	}
3557248Speter 	    /*
3567248Speter 	     *	count calls from outside the cycle
3577248Speter 	     *	and those among cycle members
3587248Speter 	     */
3597248Speter 	for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) {
3607248Speter 	    for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) {
3617248Speter 		if ( arcp -> arc_parentp == memberp ) {
3627248Speter 		    continue;
3637248Speter 		}
3647248Speter 		if ( arcp -> arc_parentp -> cycleno == cycle ) {
3657248Speter 		    cyclenlp -> selfcalls += arcp -> arc_count;
3667248Speter 		} else {
3677248Speter 		    cyclenlp -> ncall += arcp -> arc_count;
3687248Speter 		}
3697248Speter 	    }
3707248Speter 	}
3717172Speter     }
3727172Speter }
3737172Speter 
3747172Speter cycletime()
3757172Speter {
3767172Speter     int			cycle;
3777172Speter     nltype		*cyclenlp;
3787172Speter     nltype		*childp;
3797172Speter 
3807172Speter     for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) {
3817172Speter 	cyclenlp = &cyclenl[ cycle ];
3827221Speter 	for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) {
3837221Speter 	    if ( childp -> propfraction == 0.0 ) {
3847221Speter 		    /*
3857221Speter 		     * all members have the same propfraction except those
3867221Speter 		     *	that were excluded with -E
3877221Speter 		     */
3887221Speter 		continue;
3897221Speter 	    }
3907221Speter 	    cyclenlp -> time += childp -> time;
3914508Speter 	}
3927221Speter 	cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time;
3934508Speter     }
3944508Speter }
3957172Speter 
3967172Speter     /*
3977172Speter      *	in one top to bottom pass over the topologically sorted namelist
3987221Speter      *	propagate:
3997221Speter      *		printflag as the union of parents' printflags
4007221Speter      *		propfraction as the sum of fractional parents' propfractions
4017221Speter      *	and while we're here, sum time for functions.
4027172Speter      */
4037172Speter doflags()
4047172Speter {
4057172Speter     int		index;
4067172Speter     nltype	*childp;
4077172Speter     nltype	*oldhead;
4087172Speter 
4097172Speter     oldhead = 0;
4107172Speter     for ( index = nname-1 ; index >= 0 ; index -= 1 ) {
4117172Speter 	childp = topsortnlp[ index ];
4127172Speter 	    /*
4137172Speter 	     *	if we haven't done this function or cycle,
4147221Speter 	     *	inherit things from parent.
4157172Speter 	     *	this way, we are linear in the number of arcs
4167172Speter 	     *	since we do all members of a cycle (and the cycle itself)
4177172Speter 	     *	as we hit the first member of the cycle.
4187172Speter 	     */
4197172Speter 	if ( childp -> cyclehead != oldhead ) {
4207172Speter 	    oldhead = childp -> cyclehead;
4217221Speter 	    inheritflags( childp );
4227172Speter 	}
4237221Speter #	ifdef DEBUG
4247221Speter 	    if ( debug & PROPDEBUG ) {
4257221Speter 		printf( "[doflags] " );
4267221Speter 		printname( childp );
4277221Speter 		printf( " inherits printflag %d and propfraction %f\n" ,
4287221Speter 			childp -> printflag , childp -> propfraction );
4297221Speter 	    }
4307221Speter #	endif DEBUG
4317172Speter 	if ( ! childp -> printflag ) {
4327172Speter 		/*
4337221Speter 		 *	printflag is off
4347221Speter 		 *	it gets turned on by
4357221Speter 		 *	being on -f list,
4367221Speter 		 *	or there not being any -f list and not being on -e list.
4377172Speter 		 */
4387221Speter 	    if (   onlist( flist , childp -> name )
4397221Speter 		|| ( !fflag && !onlist( elist , childp -> name ) ) ) {
4407172Speter 		childp -> printflag = TRUE;
4417172Speter 	    }
4427221Speter 	} else {
4437221Speter 		/*
4447221Speter 		 *	this function has printing parents:
4457221Speter 		 *	maybe someone wants to shut it up
4467221Speter 		 *	by putting it on -e list.  (but favor -f over -e)
4477221Speter 		 */
4487221Speter 	    if (  ( !onlist( flist , childp -> name ) )
4497221Speter 		&& onlist( elist , childp -> name ) ) {
4507221Speter 		childp -> printflag = FALSE;
4517172Speter 	    }
4527221Speter 	}
4537221Speter 	if ( childp -> propfraction == 0.0 ) {
4547221Speter 		/*
4557221Speter 		 *	no parents to pass time to.
4567221Speter 		 *	collect time from children if
4577221Speter 		 *	its on -F list,
4587221Speter 		 *	or there isn't any -F list and its not on -E list.
4597221Speter 		 */
4607221Speter 	    if ( onlist( Flist , childp -> name )
4617221Speter 		|| ( !Fflag && !onlist( Elist , childp -> name ) ) ) {
4627221Speter 		    childp -> propfraction = 1.0;
4637172Speter 	    }
4647221Speter 	} else {
4657221Speter 		/*
4667221Speter 		 *	it has parents to pass time to,
4677221Speter 		 *	but maybe someone wants to shut it up
4687221Speter 		 *	by puttting it on -E list.  (but favor -F over -E)
4697221Speter 		 */
4707221Speter 	    if (  !onlist( Flist , childp -> name )
4717221Speter 		&& onlist( Elist , childp -> name ) ) {
4727221Speter 		childp -> propfraction = 0.0;
4737221Speter 	    }
4747172Speter 	}
4757221Speter 	childp -> propself = childp -> time * childp -> propfraction;
4767221Speter 	printtime += childp -> propself;
4777221Speter #	ifdef DEBUG
4787221Speter 	    if ( debug & PROPDEBUG ) {
4797221Speter 		printf( "[doflags] " );
4807221Speter 		printname( childp );
4817221Speter 		printf( " ends up with printflag %d and propfraction %f\n" ,
4827221Speter 			childp -> printflag , childp -> propfraction );
4838908Speter 		printf( "time %f propself %f printtime %f\n" ,
4848908Speter 			childp -> time , childp -> propself , printtime );
4857221Speter 	    }
4867221Speter #	endif DEBUG
4877172Speter     }
4887172Speter }
4897172Speter 
4907172Speter     /*
4917172Speter      *	check if any parent of this child
4927172Speter      *	(or outside parents of this cycle)
4937172Speter      *	have their print flags on and set the
4947172Speter      *	print flag of the child (cycle) appropriately.
4957221Speter      *	similarly, deal with propagation fractions from parents.
4967172Speter      */
4977221Speter inheritflags( childp )
4987172Speter     nltype	*childp;
4997172Speter {
5007172Speter     nltype	*headp;
5017221Speter     arctype	*arcp;
5027221Speter     nltype	*parentp;
5037172Speter     nltype	*memp;
5047172Speter 
5057172Speter     headp = childp -> cyclehead;
5067172Speter     if ( childp == headp ) {
5077172Speter 	    /*
5087172Speter 	     *	just a regular child, check its parents
5097172Speter 	     */
5107221Speter 	childp -> printflag = FALSE;
5117221Speter 	childp -> propfraction = 0.0;
5127221Speter 	for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) {
5137221Speter 	    parentp = arcp -> arc_parentp;
5148908Speter 	    if ( childp == parentp ) {
5158908Speter 		continue;
5168908Speter 	    }
5177221Speter 	    childp -> printflag |= parentp -> printflag;
51814140Speter 		/*
51914140Speter 		 *	if the child was never actually called
52014140Speter 		 *	(e.g. this arc is static (and all others are, too))
52114140Speter 		 *	no time propagates along this arc.
52214140Speter 		 */
52314140Speter 	    if ( childp -> ncall ) {
52414140Speter 		childp -> propfraction += parentp -> propfraction
52514140Speter 					    * ( ( (double) arcp -> arc_count )
52614140Speter 					      / ( (double) childp -> ncall ) );
52714140Speter 	    }
5287172Speter 	}
5297221Speter     } else {
5307221Speter 	    /*
5317221Speter 	     *	its a member of a cycle, look at all parents from
5327221Speter 	     *	outside the cycle
5337221Speter 	     */
5347221Speter 	headp -> printflag = FALSE;
5357221Speter 	headp -> propfraction = 0.0;
5367221Speter 	for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) {
5377221Speter 	    for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) {
5387221Speter 		if ( arcp -> arc_parentp -> cyclehead == headp ) {
5397221Speter 		    continue;
5407221Speter 		}
5417221Speter 		parentp = arcp -> arc_parentp;
5427221Speter 		headp -> printflag |= parentp -> printflag;
54314140Speter 		    /*
54414140Speter 		     *	if the cycle was never actually called
54514140Speter 		     *	(e.g. this arc is static (and all others are, too))
54614140Speter 		     *	no time propagates along this arc.
54714140Speter 		     */
54814140Speter 		if ( headp -> ncall ) {
54914140Speter 		    headp -> propfraction += parentp -> propfraction
55014140Speter 					    * ( ( (double) arcp -> arc_count )
55114140Speter 					      / ( (double) headp -> ncall ) );
55214140Speter 		}
5537172Speter 	    }
5547172Speter 	}
5557221Speter 	for ( memp = headp ; memp ; memp = memp -> cnext ) {
5567221Speter 	    memp -> printflag = headp -> printflag;
5577221Speter 	    memp -> propfraction = headp -> propfraction;
5587221Speter 	}
5597172Speter     }
5607172Speter }
561