arcs.c revision 27414
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1983, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3527313Scharnier#if 0 3627327Scharnierstatic char sccsid[] = "@(#)arcs.c 8.1 (Berkeley) 6/6/93"; 3727313Scharnier#endif 3827313Scharnierstatic const char rcsid[] = 3927414Scharnier "$Id: arcs.c,v 1.4 1997/07/11 06:11:35 charnier Exp $"; 401590Srgrimes#endif /* not lint */ 411590Srgrimes 4227313Scharnier#include <err.h> 431590Srgrimes#include "gprof.h" 441590Srgrimes 451590Srgrimes#ifdef DEBUG 461590Srgrimesint visited; 471590Srgrimesint viable; 481590Srgrimesint newcycle; 491590Srgrimesint oldcycle; 501590Srgrimes#endif DEBUG 511590Srgrimes 521590Srgrimes /* 531590Srgrimes * add (or just increment) an arc 541590Srgrimes */ 551590Srgrimesaddarc( parentp , childp , count ) 561590Srgrimes nltype *parentp; 571590Srgrimes nltype *childp; 581590Srgrimes long count; 591590Srgrimes{ 601590Srgrimes arctype *arcp; 611590Srgrimes 621590Srgrimes# ifdef DEBUG 631590Srgrimes if ( debug & TALLYDEBUG ) { 641590Srgrimes printf( "[addarc] %d arcs from %s to %s\n" , 651590Srgrimes count , parentp -> name , childp -> name ); 661590Srgrimes } 671590Srgrimes# endif DEBUG 681590Srgrimes arcp = arclookup( parentp , childp ); 691590Srgrimes if ( arcp != 0 ) { 701590Srgrimes /* 711590Srgrimes * a hit: just increment the count. 721590Srgrimes */ 731590Srgrimes# ifdef DEBUG 741590Srgrimes if ( debug & TALLYDEBUG ) { 751590Srgrimes printf( "[tally] hit %d += %d\n" , 761590Srgrimes arcp -> arc_count , count ); 771590Srgrimes } 781590Srgrimes# endif DEBUG 791590Srgrimes arcp -> arc_count += count; 801590Srgrimes return; 811590Srgrimes } 821590Srgrimes arcp = (arctype *)calloc( 1 , sizeof *arcp ); 831590Srgrimes arcp -> arc_parentp = parentp; 841590Srgrimes arcp -> arc_childp = childp; 851590Srgrimes arcp -> arc_count = count; 861590Srgrimes /* 871590Srgrimes * prepend this child to the children of this parent 881590Srgrimes */ 891590Srgrimes arcp -> arc_childlist = parentp -> children; 901590Srgrimes parentp -> children = arcp; 911590Srgrimes /* 921590Srgrimes * prepend this parent to the parents of this child 931590Srgrimes */ 941590Srgrimes arcp -> arc_parentlist = childp -> parents; 951590Srgrimes childp -> parents = arcp; 961590Srgrimes} 971590Srgrimes 981590Srgrimes /* 991590Srgrimes * the code below topologically sorts the graph (collapsing cycles), 1001590Srgrimes * and propagates time bottom up and flags top down. 1011590Srgrimes */ 1021590Srgrimes 1031590Srgrimes /* 1041590Srgrimes * the topologically sorted name list pointers 1051590Srgrimes */ 1061590Srgrimesnltype **topsortnlp; 1071590Srgrimes 1081590Srgrimestopcmp( npp1 , npp2 ) 1091590Srgrimes nltype **npp1; 1101590Srgrimes nltype **npp2; 1111590Srgrimes{ 1121590Srgrimes return (*npp1) -> toporder - (*npp2) -> toporder; 1131590Srgrimes} 1141590Srgrimes 1151590Srgrimesnltype ** 1161590Srgrimesdoarcs() 1171590Srgrimes{ 1181590Srgrimes nltype *parentp, **timesortnlp; 1191590Srgrimes arctype *arcp; 1201590Srgrimes long index; 1211590Srgrimes long pass; 1221590Srgrimes 1231590Srgrimes /* 1241590Srgrimes * initialize various things: 1251590Srgrimes * zero out child times. 1261590Srgrimes * count self-recursive calls. 1271590Srgrimes * indicate that nothing is on cycles. 1281590Srgrimes */ 1291590Srgrimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1301590Srgrimes parentp -> childtime = 0.0; 1311590Srgrimes arcp = arclookup( parentp , parentp ); 1321590Srgrimes if ( arcp != 0 ) { 1331590Srgrimes parentp -> ncall -= arcp -> arc_count; 1341590Srgrimes parentp -> selfcalls = arcp -> arc_count; 1351590Srgrimes } else { 1361590Srgrimes parentp -> selfcalls = 0; 1371590Srgrimes } 1381590Srgrimes parentp -> npropcall = parentp -> ncall; 1391590Srgrimes parentp -> propfraction = 0.0; 1401590Srgrimes parentp -> propself = 0.0; 1411590Srgrimes parentp -> propchild = 0.0; 1421590Srgrimes parentp -> printflag = FALSE; 1431590Srgrimes parentp -> toporder = DFN_NAN; 1441590Srgrimes parentp -> cycleno = 0; 1451590Srgrimes parentp -> cyclehead = parentp; 1461590Srgrimes parentp -> cnext = 0; 1471590Srgrimes if ( cflag ) { 1481590Srgrimes findcall( parentp , parentp -> value , (parentp+1) -> value ); 1491590Srgrimes } 1501590Srgrimes } 1511590Srgrimes for ( pass = 1 ; ; pass++ ) { 1521590Srgrimes /* 1531590Srgrimes * topologically order things 1541590Srgrimes * if any node is unnumbered, 1551590Srgrimes * number it and any of its descendents. 1561590Srgrimes */ 1571590Srgrimes for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) { 1581590Srgrimes if ( parentp -> toporder == DFN_NAN ) { 1591590Srgrimes dfn( parentp ); 1601590Srgrimes } 1611590Srgrimes } 1621590Srgrimes /* 1631590Srgrimes * link together nodes on the same cycle 1641590Srgrimes */ 1651590Srgrimes cyclelink(); 1661590Srgrimes /* 1671590Srgrimes * if no cycles to break up, proceed 1681590Srgrimes */ 1691590Srgrimes if ( ! Cflag ) 1701590Srgrimes break; 1711590Srgrimes /* 1721590Srgrimes * analyze cycles to determine breakup 1731590Srgrimes */ 1741590Srgrimes# ifdef DEBUG 1751590Srgrimes if ( debug & BREAKCYCLE ) { 1761590Srgrimes printf("[doarcs] pass %d, cycle(s) %d\n" , pass , ncycle ); 1771590Srgrimes } 1781590Srgrimes# endif DEBUG 1791590Srgrimes if ( pass == 1 ) { 1801590Srgrimes printf( "\n\n%s %s\n%s %d:\n" , 1811590Srgrimes "The following arcs were deleted" , 1821590Srgrimes "from the propagation calculation" , 1831590Srgrimes "to reduce the maximum cycle size to", cyclethreshold ); 1841590Srgrimes } 1851590Srgrimes if ( cycleanalyze() ) 1861590Srgrimes break; 1871590Srgrimes free ( cyclenl ); 1881590Srgrimes ncycle = 0; 1891590Srgrimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1901590Srgrimes parentp -> toporder = DFN_NAN; 1911590Srgrimes parentp -> cycleno = 0; 1921590Srgrimes parentp -> cyclehead = parentp; 1931590Srgrimes parentp -> cnext = 0; 1941590Srgrimes } 1951590Srgrimes } 1961590Srgrimes if ( pass > 1 ) { 1971590Srgrimes printf( "\f\n" ); 1981590Srgrimes } else { 1991590Srgrimes printf( "\tNone\n\n" ); 2001590Srgrimes } 2011590Srgrimes /* 2021590Srgrimes * Sort the symbol table in reverse topological order 2031590Srgrimes */ 2041590Srgrimes topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 2051590Srgrimes if ( topsortnlp == (nltype **) 0 ) { 2061590Srgrimes fprintf( stderr , "[doarcs] ran out of memory for topo sorting\n" ); 2071590Srgrimes } 2081590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2091590Srgrimes topsortnlp[ index ] = &nl[ index ]; 2101590Srgrimes } 2111590Srgrimes qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 2121590Srgrimes# ifdef DEBUG 2131590Srgrimes if ( debug & DFNDEBUG ) { 2141590Srgrimes printf( "[doarcs] topological sort listing\n" ); 2151590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2161590Srgrimes printf( "[doarcs] " ); 2171590Srgrimes printf( "%d:" , topsortnlp[ index ] -> toporder ); 2181590Srgrimes printname( topsortnlp[ index ] ); 2191590Srgrimes printf( "\n" ); 2201590Srgrimes } 2211590Srgrimes } 2221590Srgrimes# endif DEBUG 2231590Srgrimes /* 2241590Srgrimes * starting from the topological top, 2251590Srgrimes * propagate print flags to children. 2261590Srgrimes * also, calculate propagation fractions. 2271590Srgrimes * this happens before time propagation 2281590Srgrimes * since time propagation uses the fractions. 2291590Srgrimes */ 2301590Srgrimes doflags(); 2311590Srgrimes /* 2328874Srgrimes * starting from the topological bottom, 2331590Srgrimes * propogate children times up to parents. 2341590Srgrimes */ 2351590Srgrimes dotime(); 2361590Srgrimes /* 2371590Srgrimes * Now, sort by propself + propchild. 2381590Srgrimes * sorting both the regular function names 2391590Srgrimes * and cycle headers. 2401590Srgrimes */ 2411590Srgrimes timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 2421590Srgrimes if ( timesortnlp == (nltype **) 0 ) { 24327313Scharnier warnx("ran out of memory for sorting"); 2441590Srgrimes } 2451590Srgrimes for ( index = 0 ; index < nname ; index++ ) { 2461590Srgrimes timesortnlp[index] = &nl[index]; 2471590Srgrimes } 2481590Srgrimes for ( index = 1 ; index <= ncycle ; index++ ) { 2491590Srgrimes timesortnlp[nname+index-1] = &cyclenl[index]; 2501590Srgrimes } 2511590Srgrimes qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); 2521590Srgrimes for ( index = 0 ; index < nname + ncycle ; index++ ) { 2531590Srgrimes timesortnlp[ index ] -> index = index + 1; 2541590Srgrimes } 2551590Srgrimes return( timesortnlp ); 2561590Srgrimes} 2571590Srgrimes 2581590Srgrimesdotime() 2591590Srgrimes{ 2601590Srgrimes int index; 2611590Srgrimes 2621590Srgrimes cycletime(); 2631590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2641590Srgrimes timepropagate( topsortnlp[ index ] ); 2651590Srgrimes } 2661590Srgrimes} 2671590Srgrimes 2681590Srgrimestimepropagate( parentp ) 2691590Srgrimes nltype *parentp; 2701590Srgrimes{ 2711590Srgrimes arctype *arcp; 2721590Srgrimes nltype *childp; 2731590Srgrimes double share; 2741590Srgrimes double propshare; 2751590Srgrimes 2761590Srgrimes if ( parentp -> propfraction == 0.0 ) { 2771590Srgrimes return; 2781590Srgrimes } 2791590Srgrimes /* 2801590Srgrimes * gather time from children of this parent. 2811590Srgrimes */ 2821590Srgrimes for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 2831590Srgrimes childp = arcp -> arc_childp; 2841590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 2851590Srgrimes continue; 2861590Srgrimes } 2871590Srgrimes if ( arcp -> arc_count == 0 ) { 2881590Srgrimes continue; 2891590Srgrimes } 2901590Srgrimes if ( childp == parentp ) { 2911590Srgrimes continue; 2921590Srgrimes } 2931590Srgrimes if ( childp -> propfraction == 0.0 ) { 2941590Srgrimes continue; 2951590Srgrimes } 2961590Srgrimes if ( childp -> cyclehead != childp ) { 2971590Srgrimes if ( parentp -> cycleno == childp -> cycleno ) { 2981590Srgrimes continue; 2991590Srgrimes } 3001590Srgrimes if ( parentp -> toporder <= childp -> toporder ) { 3011590Srgrimes fprintf( stderr , "[propagate] toporder botches\n" ); 3021590Srgrimes } 3031590Srgrimes childp = childp -> cyclehead; 3041590Srgrimes } else { 3051590Srgrimes if ( parentp -> toporder <= childp -> toporder ) { 3061590Srgrimes fprintf( stderr , "[propagate] toporder botches\n" ); 3071590Srgrimes continue; 3081590Srgrimes } 3091590Srgrimes } 3101590Srgrimes if ( childp -> npropcall == 0 ) { 3111590Srgrimes continue; 3121590Srgrimes } 3131590Srgrimes /* 3141590Srgrimes * distribute time for this arc 3151590Srgrimes */ 3161590Srgrimes arcp -> arc_time = childp -> time 3171590Srgrimes * ( ( (double) arcp -> arc_count ) / 3181590Srgrimes ( (double) childp -> npropcall ) ); 3191590Srgrimes arcp -> arc_childtime = childp -> childtime 3201590Srgrimes * ( ( (double) arcp -> arc_count ) / 3211590Srgrimes ( (double) childp -> npropcall ) ); 3221590Srgrimes share = arcp -> arc_time + arcp -> arc_childtime; 3231590Srgrimes parentp -> childtime += share; 3241590Srgrimes /* 3251590Srgrimes * ( 1 - propfraction ) gets lost along the way 3261590Srgrimes */ 3271590Srgrimes propshare = parentp -> propfraction * share; 3281590Srgrimes /* 3291590Srgrimes * fix things for printing 3301590Srgrimes */ 3311590Srgrimes parentp -> propchild += propshare; 3321590Srgrimes arcp -> arc_time *= parentp -> propfraction; 3331590Srgrimes arcp -> arc_childtime *= parentp -> propfraction; 3341590Srgrimes /* 3351590Srgrimes * add this share to the parent's cycle header, if any. 3361590Srgrimes */ 3371590Srgrimes if ( parentp -> cyclehead != parentp ) { 3381590Srgrimes parentp -> cyclehead -> childtime += share; 3391590Srgrimes parentp -> cyclehead -> propchild += propshare; 3401590Srgrimes } 3411590Srgrimes# ifdef DEBUG 3421590Srgrimes if ( debug & PROPDEBUG ) { 3431590Srgrimes printf( "[dotime] child \t" ); 3441590Srgrimes printname( childp ); 3451590Srgrimes printf( " with %f %f %d/%d\n" , 3461590Srgrimes childp -> time , childp -> childtime , 3471590Srgrimes arcp -> arc_count , childp -> npropcall ); 3481590Srgrimes printf( "[dotime] parent\t" ); 3491590Srgrimes printname( parentp ); 3501590Srgrimes printf( "\n[dotime] share %f\n" , share ); 3511590Srgrimes } 3521590Srgrimes# endif DEBUG 3531590Srgrimes } 3541590Srgrimes} 3551590Srgrimes 3561590Srgrimescyclelink() 3571590Srgrimes{ 3581590Srgrimes register nltype *nlp; 3591590Srgrimes register nltype *cyclenlp; 3601590Srgrimes int cycle; 3611590Srgrimes nltype *memberp; 3621590Srgrimes arctype *arcp; 3631590Srgrimes 3641590Srgrimes /* 3651590Srgrimes * Count the number of cycles, and initialze the cycle lists 3661590Srgrimes */ 3671590Srgrimes ncycle = 0; 3681590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3691590Srgrimes /* 3701590Srgrimes * this is how you find unattached cycles 3711590Srgrimes */ 3721590Srgrimes if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 3731590Srgrimes ncycle += 1; 3741590Srgrimes } 3751590Srgrimes } 3761590Srgrimes /* 3771590Srgrimes * cyclenl is indexed by cycle number: 3781590Srgrimes * i.e. it is origin 1, not origin 0. 3791590Srgrimes */ 3801590Srgrimes cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); 3811590Srgrimes if ( cyclenl == 0 ) { 38227414Scharnier warnx("no room for %d bytes of cycle headers", 38327414Scharnier ( ncycle + 1 ) * sizeof( nltype ) ); 3841590Srgrimes done(); 3851590Srgrimes } 3861590Srgrimes /* 3871590Srgrimes * now link cycles to true cycleheads, 3881590Srgrimes * number them, accumulate the data for the cycle 3891590Srgrimes */ 3901590Srgrimes cycle = 0; 3911590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3921590Srgrimes if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { 3931590Srgrimes continue; 3941590Srgrimes } 3951590Srgrimes cycle += 1; 3961590Srgrimes cyclenlp = &cyclenl[cycle]; 3971590Srgrimes cyclenlp -> name = 0; /* the name */ 3981590Srgrimes cyclenlp -> value = 0; /* the pc entry point */ 3991590Srgrimes cyclenlp -> time = 0.0; /* ticks in this routine */ 4001590Srgrimes cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ 4011590Srgrimes cyclenlp -> ncall = 0; /* how many times called */ 4021590Srgrimes cyclenlp -> selfcalls = 0; /* how many calls to self */ 4031590Srgrimes cyclenlp -> propfraction = 0.0; /* what % of time propagates */ 4041590Srgrimes cyclenlp -> propself = 0.0; /* how much self time propagates */ 4051590Srgrimes cyclenlp -> propchild = 0.0; /* how much child time propagates */ 4061590Srgrimes cyclenlp -> printflag = TRUE; /* should this be printed? */ 4071590Srgrimes cyclenlp -> index = 0; /* index in the graph list */ 4081590Srgrimes cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ 4091590Srgrimes cyclenlp -> cycleno = cycle; /* internal number of cycle on */ 4101590Srgrimes cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ 4111590Srgrimes cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ 4121590Srgrimes cyclenlp -> parents = 0; /* list of caller arcs */ 4131590Srgrimes cyclenlp -> children = 0; /* list of callee arcs */ 4141590Srgrimes# ifdef DEBUG 4151590Srgrimes if ( debug & CYCLEDEBUG ) { 4161590Srgrimes printf( "[cyclelink] " ); 4171590Srgrimes printname( nlp ); 4181590Srgrimes printf( " is the head of cycle %d\n" , cycle ); 4191590Srgrimes } 4201590Srgrimes# endif DEBUG 4211590Srgrimes /* 4221590Srgrimes * link members to cycle header 4231590Srgrimes */ 4248874Srgrimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4251590Srgrimes memberp -> cycleno = cycle; 4261590Srgrimes memberp -> cyclehead = cyclenlp; 4271590Srgrimes } 4281590Srgrimes /* 4291590Srgrimes * count calls from outside the cycle 4301590Srgrimes * and those among cycle members 4311590Srgrimes */ 4321590Srgrimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4331590Srgrimes for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { 4341590Srgrimes if ( arcp -> arc_parentp == memberp ) { 4351590Srgrimes continue; 4361590Srgrimes } 4371590Srgrimes if ( arcp -> arc_parentp -> cycleno == cycle ) { 4381590Srgrimes cyclenlp -> selfcalls += arcp -> arc_count; 4391590Srgrimes } else { 4401590Srgrimes cyclenlp -> npropcall += arcp -> arc_count; 4411590Srgrimes } 4421590Srgrimes } 4431590Srgrimes } 4441590Srgrimes } 4451590Srgrimes} 4461590Srgrimes 4471590Srgrimes /* 4481590Srgrimes * analyze cycles to determine breakup 4491590Srgrimes */ 4501590Srgrimescycleanalyze() 4511590Srgrimes{ 4521590Srgrimes arctype **cyclestack; 4531590Srgrimes arctype **stkp; 4541590Srgrimes arctype **arcpp; 4551590Srgrimes arctype **endlist; 4561590Srgrimes arctype *arcp; 4571590Srgrimes nltype *nlp; 4581590Srgrimes cltype *clp; 4591590Srgrimes bool ret; 4601590Srgrimes bool done; 4611590Srgrimes int size; 4621590Srgrimes int cycleno; 4631590Srgrimes 4641590Srgrimes /* 4651590Srgrimes * calculate the size of the cycle, and find nodes that 4661590Srgrimes * exit the cycle as they are desirable targets to cut 4671590Srgrimes * some of their parents 4681590Srgrimes */ 4691590Srgrimes for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) { 4701590Srgrimes size = 0; 4711590Srgrimes for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) { 4721590Srgrimes size += 1; 4731590Srgrimes nlp -> parentcnt = 0; 4741590Srgrimes nlp -> flags &= ~HASCYCLEXIT; 4751590Srgrimes for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) { 4761590Srgrimes nlp -> parentcnt += 1; 4771590Srgrimes if ( arcp -> arc_parentp -> cycleno != cycleno ) 4781590Srgrimes nlp -> flags |= HASCYCLEXIT; 4791590Srgrimes } 4801590Srgrimes } 4811590Srgrimes if ( size <= cyclethreshold ) 4821590Srgrimes continue; 4831590Srgrimes done = FALSE; 4841590Srgrimes cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) ); 4851590Srgrimes if ( cyclestack == 0 ) { 48627414Scharnier warnx("no room for %d bytes of cycle stack", 48727414Scharnier ( size + 1 ) * sizeof( arctype * ) ); 4881590Srgrimes return; 4891590Srgrimes } 4901590Srgrimes# ifdef DEBUG 4911590Srgrimes if ( debug & BREAKCYCLE ) { 4921590Srgrimes printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" , 4931590Srgrimes cycleno , ncycle , size ); 4941590Srgrimes } 4951590Srgrimes# endif DEBUG 4961590Srgrimes for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) { 4971590Srgrimes stkp = &cyclestack[0]; 4981590Srgrimes nlp -> flags |= CYCLEHEAD; 4991590Srgrimes ret = descend ( nlp , cyclestack , stkp ); 5001590Srgrimes nlp -> flags &= ~CYCLEHEAD; 5011590Srgrimes if ( ret == FALSE ) 5021590Srgrimes break; 5031590Srgrimes } 5041590Srgrimes free( cyclestack ); 5051590Srgrimes if ( cyclecnt > 0 ) { 5061590Srgrimes compresslist(); 5071590Srgrimes for ( clp = cyclehead ; clp ; ) { 5081590Srgrimes endlist = &clp -> list[ clp -> size ]; 5091590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 5101590Srgrimes (*arcpp) -> arc_cyclecnt--; 5111590Srgrimes cyclecnt--; 5121590Srgrimes clp = clp -> next; 5131590Srgrimes free( clp ); 5141590Srgrimes } 5151590Srgrimes cyclehead = 0; 5161590Srgrimes } 5171590Srgrimes } 5181590Srgrimes# ifdef DEBUG 5191590Srgrimes if ( debug & BREAKCYCLE ) { 5201590Srgrimes printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n", 5211590Srgrimes "[doarcs]" , visited , viable , newcycle , oldcycle); 5221590Srgrimes } 5231590Srgrimes# endif DEBUG 5241590Srgrimes return( done ); 5251590Srgrimes} 5261590Srgrimes 5271590Srgrimesdescend( node , stkstart , stkp ) 5281590Srgrimes nltype *node; 5291590Srgrimes arctype **stkstart; 5301590Srgrimes arctype **stkp; 5311590Srgrimes{ 5321590Srgrimes arctype *arcp; 5331590Srgrimes bool ret; 5341590Srgrimes 5351590Srgrimes for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) { 5361590Srgrimes# ifdef DEBUG 5371590Srgrimes visited++; 5381590Srgrimes# endif DEBUG 5391590Srgrimes if ( arcp -> arc_childp -> cycleno != node -> cycleno 5401590Srgrimes || ( arcp -> arc_childp -> flags & VISITED ) 5411590Srgrimes || ( arcp -> arc_flags & DEADARC ) ) 5421590Srgrimes continue; 5431590Srgrimes# ifdef DEBUG 5441590Srgrimes viable++; 5451590Srgrimes# endif DEBUG 5461590Srgrimes *stkp = arcp; 5471590Srgrimes if ( arcp -> arc_childp -> flags & CYCLEHEAD ) { 5481590Srgrimes if ( addcycle( stkstart , stkp ) == FALSE ) 5491590Srgrimes return( FALSE ); 5501590Srgrimes continue; 5511590Srgrimes } 5521590Srgrimes arcp -> arc_childp -> flags |= VISITED; 5531590Srgrimes ret = descend( arcp -> arc_childp , stkstart , stkp + 1 ); 5541590Srgrimes arcp -> arc_childp -> flags &= ~VISITED; 5551590Srgrimes if ( ret == FALSE ) 5561590Srgrimes return( FALSE ); 5571590Srgrimes } 5581590Srgrimes} 5591590Srgrimes 5601590Srgrimesaddcycle( stkstart , stkend ) 5611590Srgrimes arctype **stkstart; 5621590Srgrimes arctype **stkend; 5631590Srgrimes{ 5641590Srgrimes arctype **arcpp; 5651590Srgrimes arctype **stkloc; 5661590Srgrimes arctype **stkp; 5671590Srgrimes arctype **endlist; 5681590Srgrimes arctype *minarc; 5691590Srgrimes arctype *arcp; 5701590Srgrimes cltype *clp; 5711590Srgrimes int size; 5721590Srgrimes 5731590Srgrimes size = stkend - stkstart + 1; 5741590Srgrimes if ( size <= 1 ) 5751590Srgrimes return( TRUE ); 5761590Srgrimes for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) { 5771590Srgrimes if ( *arcpp > minarc ) 5781590Srgrimes continue; 5791590Srgrimes minarc = *arcpp; 5801590Srgrimes stkloc = arcpp; 5811590Srgrimes } 5821590Srgrimes for ( clp = cyclehead ; clp ; clp = clp -> next ) { 5831590Srgrimes if ( clp -> size != size ) 5841590Srgrimes continue; 5851590Srgrimes stkp = stkloc; 5861590Srgrimes endlist = &clp -> list[ size ]; 5871590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 5881590Srgrimes if ( *stkp++ != *arcpp ) 5891590Srgrimes break; 5901590Srgrimes if ( stkp > stkend ) 5911590Srgrimes stkp = stkstart; 5921590Srgrimes } 5931590Srgrimes if ( arcpp == endlist ) { 5941590Srgrimes# ifdef DEBUG 5951590Srgrimes oldcycle++; 5961590Srgrimes# endif DEBUG 5971590Srgrimes return( TRUE ); 5981590Srgrimes } 5991590Srgrimes } 6001590Srgrimes clp = (cltype *) 6011590Srgrimes calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 6021590Srgrimes if ( clp == 0 ) { 60327313Scharnier warnx("no room for %d bytes of subcycle storage", 60427313Scharnier sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 6051590Srgrimes return( FALSE ); 6061590Srgrimes } 6071590Srgrimes stkp = stkloc; 6081590Srgrimes endlist = &clp -> list[ size ]; 6091590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 6101590Srgrimes arcp = *arcpp = *stkp++; 6111590Srgrimes if ( stkp > stkend ) 6121590Srgrimes stkp = stkstart; 6131590Srgrimes arcp -> arc_cyclecnt++; 6141590Srgrimes if ( ( arcp -> arc_flags & ONLIST ) == 0 ) { 6151590Srgrimes arcp -> arc_flags |= ONLIST; 6161590Srgrimes arcp -> arc_next = archead; 6171590Srgrimes archead = arcp; 6181590Srgrimes } 6191590Srgrimes } 6201590Srgrimes clp -> size = size; 6211590Srgrimes clp -> next = cyclehead; 6221590Srgrimes cyclehead = clp; 6231590Srgrimes# ifdef DEBUG 6241590Srgrimes newcycle++; 6251590Srgrimes if ( debug & SUBCYCLELIST ) { 6261590Srgrimes printsubcycle( clp ); 6271590Srgrimes } 6281590Srgrimes# endif DEBUG 6291590Srgrimes cyclecnt++; 6301590Srgrimes if ( cyclecnt >= CYCLEMAX ) 6311590Srgrimes return( FALSE ); 6321590Srgrimes return( TRUE ); 6331590Srgrimes} 6341590Srgrimes 6351590Srgrimescompresslist() 6361590Srgrimes{ 6371590Srgrimes cltype *clp; 6381590Srgrimes cltype **prev; 6391590Srgrimes arctype **arcpp; 6401590Srgrimes arctype **endlist; 6411590Srgrimes arctype *arcp; 6421590Srgrimes arctype *maxarcp; 6431590Srgrimes arctype *maxexitarcp; 6441590Srgrimes arctype *maxwithparentarcp; 6451590Srgrimes arctype *maxnoparentarcp; 6461590Srgrimes int maxexitcnt; 6471590Srgrimes int maxwithparentcnt; 6481590Srgrimes int maxnoparentcnt; 6491590Srgrimes 6501590Srgrimes maxexitcnt = 0; 6511590Srgrimes maxwithparentcnt = 0; 6521590Srgrimes maxnoparentcnt = 0; 6531590Srgrimes for ( endlist = &archead , arcp = archead ; arcp ; ) { 6541590Srgrimes if ( arcp -> arc_cyclecnt == 0 ) { 6551590Srgrimes arcp -> arc_flags &= ~ONLIST; 6561590Srgrimes *endlist = arcp -> arc_next; 6571590Srgrimes arcp -> arc_next = 0; 6581590Srgrimes arcp = *endlist; 6591590Srgrimes continue; 6601590Srgrimes } 6611590Srgrimes if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) { 6621590Srgrimes if ( arcp -> arc_cyclecnt > maxexitcnt || 6631590Srgrimes ( arcp -> arc_cyclecnt == maxexitcnt && 6641590Srgrimes arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) { 6651590Srgrimes maxexitcnt = arcp -> arc_cyclecnt; 6661590Srgrimes maxexitarcp = arcp; 6671590Srgrimes } 6681590Srgrimes } else if ( arcp -> arc_childp -> parentcnt > 1 ) { 6691590Srgrimes if ( arcp -> arc_cyclecnt > maxwithparentcnt || 6701590Srgrimes ( arcp -> arc_cyclecnt == maxwithparentcnt && 6711590Srgrimes arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) { 6721590Srgrimes maxwithparentcnt = arcp -> arc_cyclecnt; 6731590Srgrimes maxwithparentarcp = arcp; 6741590Srgrimes } 6751590Srgrimes } else { 6761590Srgrimes if ( arcp -> arc_cyclecnt > maxnoparentcnt || 6771590Srgrimes ( arcp -> arc_cyclecnt == maxnoparentcnt && 6781590Srgrimes arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) { 6791590Srgrimes maxnoparentcnt = arcp -> arc_cyclecnt; 6801590Srgrimes maxnoparentarcp = arcp; 6811590Srgrimes } 6821590Srgrimes } 6831590Srgrimes endlist = &arcp -> arc_next; 6841590Srgrimes arcp = arcp -> arc_next; 6851590Srgrimes } 6861590Srgrimes if ( maxexitcnt > 0 ) { 6871590Srgrimes /* 6881590Srgrimes * first choice is edge leading to node with out-of-cycle parent 6891590Srgrimes */ 6901590Srgrimes maxarcp = maxexitarcp; 6911590Srgrimes# ifdef DEBUG 6921590Srgrimes type = "exit"; 6931590Srgrimes# endif DEBUG 6941590Srgrimes } else if ( maxwithparentcnt > 0 ) { 6951590Srgrimes /* 6961590Srgrimes * second choice is edge leading to node with at least one 6971590Srgrimes * other in-cycle parent 6981590Srgrimes */ 6991590Srgrimes maxarcp = maxwithparentarcp; 7001590Srgrimes# ifdef DEBUG 7011590Srgrimes type = "internal"; 7021590Srgrimes# endif DEBUG 7031590Srgrimes } else { 7041590Srgrimes /* 7051590Srgrimes * last choice is edge leading to node with only this arc as 7061590Srgrimes * a parent (as it will now be orphaned) 7071590Srgrimes */ 7081590Srgrimes maxarcp = maxnoparentarcp; 7091590Srgrimes# ifdef DEBUG 7101590Srgrimes type = "orphan"; 7111590Srgrimes# endif DEBUG 7121590Srgrimes } 7131590Srgrimes maxarcp -> arc_flags |= DEADARC; 7141590Srgrimes maxarcp -> arc_childp -> parentcnt -= 1; 7151590Srgrimes maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count; 7161590Srgrimes# ifdef DEBUG 7171590Srgrimes if ( debug & BREAKCYCLE ) { 7181590Srgrimes printf( "%s delete %s arc: %s (%d) -> %s from %d cycle(s)\n" , 7191590Srgrimes "[compresslist]" , type , maxarcp -> arc_parentp -> name , 7201590Srgrimes maxarcp -> arc_count , maxarcp -> arc_childp -> name , 7211590Srgrimes maxarcp -> arc_cyclecnt ); 7221590Srgrimes } 7231590Srgrimes# endif DEBUG 7241590Srgrimes printf( "\t%s to %s with %d calls\n" , maxarcp -> arc_parentp -> name , 7251590Srgrimes maxarcp -> arc_childp -> name , maxarcp -> arc_count ); 7261590Srgrimes prev = &cyclehead; 7271590Srgrimes for ( clp = cyclehead ; clp ; ) { 7281590Srgrimes endlist = &clp -> list[ clp -> size ]; 7291590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7301590Srgrimes if ( (*arcpp) -> arc_flags & DEADARC ) 7311590Srgrimes break; 7321590Srgrimes if ( arcpp == endlist ) { 7331590Srgrimes prev = &clp -> next; 7341590Srgrimes clp = clp -> next; 7351590Srgrimes continue; 7361590Srgrimes } 7371590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7381590Srgrimes (*arcpp) -> arc_cyclecnt--; 7391590Srgrimes cyclecnt--; 7401590Srgrimes *prev = clp -> next; 7411590Srgrimes clp = clp -> next; 7421590Srgrimes free( clp ); 7431590Srgrimes } 7441590Srgrimes} 7451590Srgrimes 7461590Srgrimes#ifdef DEBUG 7471590Srgrimesprintsubcycle( clp ) 7481590Srgrimes cltype *clp; 7491590Srgrimes{ 7501590Srgrimes arctype **arcpp; 7511590Srgrimes arctype **endlist; 7521590Srgrimes 7531590Srgrimes arcpp = clp -> list; 7541590Srgrimes printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name , 7551590Srgrimes (*arcpp) -> arc_parentp -> cycleno ) ; 7561590Srgrimes for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ ) 7571590Srgrimes printf( "\t(%d) -> %s\n" , (*arcpp) -> arc_count , 7581590Srgrimes (*arcpp) -> arc_childp -> name ) ; 7591590Srgrimes} 7601590Srgrimes#endif DEBUG 7611590Srgrimes 7621590Srgrimescycletime() 7631590Srgrimes{ 7641590Srgrimes int cycle; 7651590Srgrimes nltype *cyclenlp; 7661590Srgrimes nltype *childp; 7671590Srgrimes 7681590Srgrimes for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 7691590Srgrimes cyclenlp = &cyclenl[ cycle ]; 7701590Srgrimes for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 7711590Srgrimes if ( childp -> propfraction == 0.0 ) { 7721590Srgrimes /* 7731590Srgrimes * all members have the same propfraction except those 7741590Srgrimes * that were excluded with -E 7751590Srgrimes */ 7761590Srgrimes continue; 7771590Srgrimes } 7781590Srgrimes cyclenlp -> time += childp -> time; 7791590Srgrimes } 7801590Srgrimes cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 7811590Srgrimes } 7821590Srgrimes} 7831590Srgrimes 7841590Srgrimes /* 7851590Srgrimes * in one top to bottom pass over the topologically sorted namelist 7861590Srgrimes * propagate: 7871590Srgrimes * printflag as the union of parents' printflags 7881590Srgrimes * propfraction as the sum of fractional parents' propfractions 7891590Srgrimes * and while we're here, sum time for functions. 7901590Srgrimes */ 7911590Srgrimesdoflags() 7921590Srgrimes{ 7931590Srgrimes int index; 7941590Srgrimes nltype *childp; 7951590Srgrimes nltype *oldhead; 7961590Srgrimes 7971590Srgrimes oldhead = 0; 7981590Srgrimes for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 7991590Srgrimes childp = topsortnlp[ index ]; 8001590Srgrimes /* 8011590Srgrimes * if we haven't done this function or cycle, 8021590Srgrimes * inherit things from parent. 8031590Srgrimes * this way, we are linear in the number of arcs 8041590Srgrimes * since we do all members of a cycle (and the cycle itself) 8051590Srgrimes * as we hit the first member of the cycle. 8061590Srgrimes */ 8071590Srgrimes if ( childp -> cyclehead != oldhead ) { 8081590Srgrimes oldhead = childp -> cyclehead; 8091590Srgrimes inheritflags( childp ); 8101590Srgrimes } 8111590Srgrimes# ifdef DEBUG 8121590Srgrimes if ( debug & PROPDEBUG ) { 8131590Srgrimes printf( "[doflags] " ); 8141590Srgrimes printname( childp ); 8151590Srgrimes printf( " inherits printflag %d and propfraction %f\n" , 8161590Srgrimes childp -> printflag , childp -> propfraction ); 8171590Srgrimes } 8181590Srgrimes# endif DEBUG 8191590Srgrimes if ( ! childp -> printflag ) { 8201590Srgrimes /* 8211590Srgrimes * printflag is off 8221590Srgrimes * it gets turned on by 8231590Srgrimes * being on -f list, 8241590Srgrimes * or there not being any -f list and not being on -e list. 8251590Srgrimes */ 8261590Srgrimes if ( onlist( flist , childp -> name ) 8271590Srgrimes || ( !fflag && !onlist( elist , childp -> name ) ) ) { 8281590Srgrimes childp -> printflag = TRUE; 8291590Srgrimes } 8301590Srgrimes } else { 8311590Srgrimes /* 8321590Srgrimes * this function has printing parents: 8331590Srgrimes * maybe someone wants to shut it up 8341590Srgrimes * by putting it on -e list. (but favor -f over -e) 8351590Srgrimes */ 8361590Srgrimes if ( ( !onlist( flist , childp -> name ) ) 8371590Srgrimes && onlist( elist , childp -> name ) ) { 8381590Srgrimes childp -> printflag = FALSE; 8391590Srgrimes } 8401590Srgrimes } 8411590Srgrimes if ( childp -> propfraction == 0.0 ) { 8421590Srgrimes /* 8431590Srgrimes * no parents to pass time to. 8441590Srgrimes * collect time from children if 8451590Srgrimes * its on -F list, 8461590Srgrimes * or there isn't any -F list and its not on -E list. 8471590Srgrimes */ 8481590Srgrimes if ( onlist( Flist , childp -> name ) 8491590Srgrimes || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 8501590Srgrimes childp -> propfraction = 1.0; 8511590Srgrimes } 8521590Srgrimes } else { 8531590Srgrimes /* 8548874Srgrimes * it has parents to pass time to, 8551590Srgrimes * but maybe someone wants to shut it up 8561590Srgrimes * by puttting it on -E list. (but favor -F over -E) 8571590Srgrimes */ 8581590Srgrimes if ( !onlist( Flist , childp -> name ) 8591590Srgrimes && onlist( Elist , childp -> name ) ) { 8601590Srgrimes childp -> propfraction = 0.0; 8611590Srgrimes } 8621590Srgrimes } 8631590Srgrimes childp -> propself = childp -> time * childp -> propfraction; 8641590Srgrimes printtime += childp -> propself; 8651590Srgrimes# ifdef DEBUG 8661590Srgrimes if ( debug & PROPDEBUG ) { 8671590Srgrimes printf( "[doflags] " ); 8681590Srgrimes printname( childp ); 8691590Srgrimes printf( " ends up with printflag %d and propfraction %f\n" , 8701590Srgrimes childp -> printflag , childp -> propfraction ); 8711590Srgrimes printf( "time %f propself %f printtime %f\n" , 8721590Srgrimes childp -> time , childp -> propself , printtime ); 8731590Srgrimes } 8741590Srgrimes# endif DEBUG 8751590Srgrimes } 8761590Srgrimes} 8771590Srgrimes 8781590Srgrimes /* 8791590Srgrimes * check if any parent of this child 8801590Srgrimes * (or outside parents of this cycle) 8818874Srgrimes * have their print flags on and set the 8821590Srgrimes * print flag of the child (cycle) appropriately. 8831590Srgrimes * similarly, deal with propagation fractions from parents. 8841590Srgrimes */ 8851590Srgrimesinheritflags( childp ) 8861590Srgrimes nltype *childp; 8871590Srgrimes{ 8881590Srgrimes nltype *headp; 8891590Srgrimes arctype *arcp; 8901590Srgrimes nltype *parentp; 8911590Srgrimes nltype *memp; 8921590Srgrimes 8931590Srgrimes headp = childp -> cyclehead; 8941590Srgrimes if ( childp == headp ) { 8951590Srgrimes /* 8961590Srgrimes * just a regular child, check its parents 8971590Srgrimes */ 8981590Srgrimes childp -> printflag = FALSE; 8991590Srgrimes childp -> propfraction = 0.0; 9001590Srgrimes for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 9011590Srgrimes parentp = arcp -> arc_parentp; 9021590Srgrimes if ( childp == parentp ) { 9031590Srgrimes continue; 9041590Srgrimes } 9051590Srgrimes childp -> printflag |= parentp -> printflag; 9061590Srgrimes /* 9071590Srgrimes * if the child was never actually called 9081590Srgrimes * (e.g. this arc is static (and all others are, too)) 9091590Srgrimes * no time propagates along this arc. 9101590Srgrimes */ 9111590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 9121590Srgrimes continue; 9131590Srgrimes } 9141590Srgrimes if ( childp -> npropcall ) { 9151590Srgrimes childp -> propfraction += parentp -> propfraction 9161590Srgrimes * ( ( (double) arcp -> arc_count ) 9171590Srgrimes / ( (double) childp -> npropcall ) ); 9181590Srgrimes } 9191590Srgrimes } 9201590Srgrimes } else { 9211590Srgrimes /* 9228874Srgrimes * its a member of a cycle, look at all parents from 9231590Srgrimes * outside the cycle 9241590Srgrimes */ 9251590Srgrimes headp -> printflag = FALSE; 9261590Srgrimes headp -> propfraction = 0.0; 9271590Srgrimes for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 9281590Srgrimes for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 9291590Srgrimes if ( arcp -> arc_parentp -> cyclehead == headp ) { 9301590Srgrimes continue; 9311590Srgrimes } 9321590Srgrimes parentp = arcp -> arc_parentp; 9331590Srgrimes headp -> printflag |= parentp -> printflag; 9341590Srgrimes /* 9351590Srgrimes * if the cycle was never actually called 9361590Srgrimes * (e.g. this arc is static (and all others are, too)) 9371590Srgrimes * no time propagates along this arc. 9381590Srgrimes */ 9391590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 9401590Srgrimes continue; 9411590Srgrimes } 9421590Srgrimes if ( headp -> npropcall ) { 9431590Srgrimes headp -> propfraction += parentp -> propfraction 9441590Srgrimes * ( ( (double) arcp -> arc_count ) 9451590Srgrimes / ( (double) headp -> npropcall ) ); 9461590Srgrimes } 9471590Srgrimes } 9481590Srgrimes } 9491590Srgrimes for ( memp = headp ; memp ; memp = memp -> cnext ) { 9501590Srgrimes memp -> printflag = headp -> printflag; 9511590Srgrimes memp -> propfraction = headp -> propfraction; 9521590Srgrimes } 9531590Srgrimes } 9541590Srgrimes} 955