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 * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 30105243Scharnier#if 0 311590Srgrimes#ifndef lint 3227327Scharnierstatic char sccsid[] = "@(#)arcs.c 8.1 (Berkeley) 6/6/93"; 33105243Scharnier#endif /* not lint */ 3427313Scharnier#endif 35105243Scharnier 3699112Sobrien#include <sys/cdefs.h> 3799112Sobrien__FBSDID("$FreeBSD: releng/10.3/usr.bin/gprof/arcs.c 246783 2013-02-14 08:16:03Z charnier $"); 381590Srgrimes 3927313Scharnier#include <err.h> 401590Srgrimes#include "gprof.h" 411590Srgrimes 421590Srgrimes#ifdef DEBUG 431590Srgrimesint visited; 441590Srgrimesint viable; 451590Srgrimesint newcycle; 461590Srgrimesint oldcycle; 4797631Swollman#endif /* DEBUG */ 481590Srgrimes 49246783Scharnierint topcmp(const void *, const void *); 50246783Scharnier 511590Srgrimes /* 521590Srgrimes * add (or just increment) an arc 531590Srgrimes */ 54105243Scharniervoid 55246783Scharnieraddarc(nltype *parentp, nltype *childp, long count) 561590Srgrimes{ 571590Srgrimes arctype *arcp; 581590Srgrimes 591590Srgrimes# ifdef DEBUG 601590Srgrimes if ( debug & TALLYDEBUG ) { 6191018Sbde printf( "[addarc] %ld arcs from %s to %s\n" , 621590Srgrimes count , parentp -> name , childp -> name ); 631590Srgrimes } 6497631Swollman# endif /* DEBUG */ 651590Srgrimes arcp = arclookup( parentp , childp ); 661590Srgrimes if ( arcp != 0 ) { 671590Srgrimes /* 681590Srgrimes * a hit: just increment the count. 691590Srgrimes */ 701590Srgrimes# ifdef DEBUG 711590Srgrimes if ( debug & TALLYDEBUG ) { 7291018Sbde printf( "[tally] hit %ld += %ld\n" , 731590Srgrimes arcp -> arc_count , count ); 741590Srgrimes } 7597631Swollman# endif /* DEBUG */ 761590Srgrimes arcp -> arc_count += count; 771590Srgrimes return; 781590Srgrimes } 791590Srgrimes arcp = (arctype *)calloc( 1 , sizeof *arcp ); 80105243Scharnier if (arcp == NULL) 81105243Scharnier errx( 1 , "malloc failed" ); 821590Srgrimes arcp -> arc_parentp = parentp; 831590Srgrimes arcp -> arc_childp = childp; 841590Srgrimes arcp -> arc_count = count; 851590Srgrimes /* 861590Srgrimes * prepend this child to the children of this parent 871590Srgrimes */ 881590Srgrimes arcp -> arc_childlist = parentp -> children; 891590Srgrimes parentp -> children = arcp; 901590Srgrimes /* 911590Srgrimes * prepend this parent to the parents of this child 921590Srgrimes */ 931590Srgrimes arcp -> arc_parentlist = childp -> parents; 941590Srgrimes childp -> parents = arcp; 951590Srgrimes} 961590Srgrimes 971590Srgrimes /* 981590Srgrimes * the code below topologically sorts the graph (collapsing cycles), 991590Srgrimes * and propagates time bottom up and flags top down. 1001590Srgrimes */ 1011590Srgrimes 1021590Srgrimes /* 1031590Srgrimes * the topologically sorted name list pointers 1041590Srgrimes */ 1051590Srgrimesnltype **topsortnlp; 1061590Srgrimes 107105243Scharnierint 108246783Scharniertopcmp(const void *v1, const void *v2) 1091590Srgrimes{ 110246783Scharnier const nltype **npp1 = (const nltype **)v1; 111246783Scharnier const nltype **npp2 = (const nltype **)v2; 112246783Scharnier 1131590Srgrimes return (*npp1) -> toporder - (*npp2) -> toporder; 1141590Srgrimes} 1151590Srgrimes 1161590Srgrimesnltype ** 117246783Scharnierdoarcs(void) 1181590Srgrimes{ 1191590Srgrimes nltype *parentp, **timesortnlp; 1201590Srgrimes arctype *arcp; 1211590Srgrimes long index; 1221590Srgrimes long pass; 1231590Srgrimes 1241590Srgrimes /* 1251590Srgrimes * initialize various things: 1261590Srgrimes * zero out child times. 1271590Srgrimes * count self-recursive calls. 1281590Srgrimes * indicate that nothing is on cycles. 1291590Srgrimes */ 1301590Srgrimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1311590Srgrimes parentp -> childtime = 0.0; 1321590Srgrimes arcp = arclookup( parentp , parentp ); 1331590Srgrimes if ( arcp != 0 ) { 1341590Srgrimes parentp -> ncall -= arcp -> arc_count; 1351590Srgrimes parentp -> selfcalls = arcp -> arc_count; 1361590Srgrimes } else { 1371590Srgrimes parentp -> selfcalls = 0; 1381590Srgrimes } 1391590Srgrimes parentp -> npropcall = parentp -> ncall; 1401590Srgrimes parentp -> propfraction = 0.0; 1411590Srgrimes parentp -> propself = 0.0; 1421590Srgrimes parentp -> propchild = 0.0; 1431590Srgrimes parentp -> printflag = FALSE; 1441590Srgrimes parentp -> toporder = DFN_NAN; 1451590Srgrimes parentp -> cycleno = 0; 1461590Srgrimes parentp -> cyclehead = parentp; 1471590Srgrimes parentp -> cnext = 0; 1481590Srgrimes } 1491590Srgrimes for ( pass = 1 ; ; pass++ ) { 1501590Srgrimes /* 1511590Srgrimes * topologically order things 1521590Srgrimes * if any node is unnumbered, 1531590Srgrimes * number it and any of its descendents. 1541590Srgrimes */ 1551590Srgrimes for ( dfn_init() , parentp = nl ; parentp < npe ; parentp++ ) { 1561590Srgrimes if ( parentp -> toporder == DFN_NAN ) { 1571590Srgrimes dfn( parentp ); 1581590Srgrimes } 1591590Srgrimes } 1601590Srgrimes /* 1611590Srgrimes * link together nodes on the same cycle 1621590Srgrimes */ 1631590Srgrimes cyclelink(); 1641590Srgrimes /* 1651590Srgrimes * if no cycles to break up, proceed 1661590Srgrimes */ 1671590Srgrimes if ( ! Cflag ) 1681590Srgrimes break; 1691590Srgrimes /* 1701590Srgrimes * analyze cycles to determine breakup 1711590Srgrimes */ 1721590Srgrimes# ifdef DEBUG 1731590Srgrimes if ( debug & BREAKCYCLE ) { 17491018Sbde printf("[doarcs] pass %ld, cycle(s) %d\n" , pass , ncycle ); 1751590Srgrimes } 17697631Swollman# endif /* DEBUG */ 1771590Srgrimes if ( pass == 1 ) { 1781590Srgrimes printf( "\n\n%s %s\n%s %d:\n" , 1791590Srgrimes "The following arcs were deleted" , 1801590Srgrimes "from the propagation calculation" , 1811590Srgrimes "to reduce the maximum cycle size to", cyclethreshold ); 1821590Srgrimes } 1831590Srgrimes if ( cycleanalyze() ) 1841590Srgrimes break; 1851590Srgrimes free ( cyclenl ); 1861590Srgrimes ncycle = 0; 1871590Srgrimes for ( parentp = nl ; parentp < npe ; parentp++ ) { 1881590Srgrimes parentp -> toporder = DFN_NAN; 1891590Srgrimes parentp -> cycleno = 0; 1901590Srgrimes parentp -> cyclehead = parentp; 1911590Srgrimes parentp -> cnext = 0; 1921590Srgrimes } 1931590Srgrimes } 1941590Srgrimes if ( pass > 1 ) { 1951590Srgrimes printf( "\f\n" ); 1961590Srgrimes } else { 1971590Srgrimes printf( "\tNone\n\n" ); 1981590Srgrimes } 1991590Srgrimes /* 2001590Srgrimes * Sort the symbol table in reverse topological order 2011590Srgrimes */ 2021590Srgrimes topsortnlp = (nltype **) calloc( nname , sizeof(nltype *) ); 203105243Scharnier if ( topsortnlp == (nltype **) 0 ) 204105243Scharnier errx( 1 , "[doarcs] ran out of memory for topo sorting" ); 2051590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2061590Srgrimes topsortnlp[ index ] = &nl[ index ]; 2071590Srgrimes } 2081590Srgrimes qsort( topsortnlp , nname , sizeof(nltype *) , topcmp ); 2091590Srgrimes# ifdef DEBUG 2101590Srgrimes if ( debug & DFNDEBUG ) { 2111590Srgrimes printf( "[doarcs] topological sort listing\n" ); 2121590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2131590Srgrimes printf( "[doarcs] " ); 2141590Srgrimes printf( "%d:" , topsortnlp[ index ] -> toporder ); 2151590Srgrimes printname( topsortnlp[ index ] ); 2161590Srgrimes printf( "\n" ); 2171590Srgrimes } 2181590Srgrimes } 21997631Swollman# endif /* DEBUG */ 2201590Srgrimes /* 2211590Srgrimes * starting from the topological top, 2221590Srgrimes * propagate print flags to children. 2231590Srgrimes * also, calculate propagation fractions. 2241590Srgrimes * this happens before time propagation 2251590Srgrimes * since time propagation uses the fractions. 2261590Srgrimes */ 2271590Srgrimes doflags(); 2281590Srgrimes /* 2298874Srgrimes * starting from the topological bottom, 230105243Scharnier * propagate children times up to parents. 2311590Srgrimes */ 2321590Srgrimes dotime(); 2331590Srgrimes /* 2341590Srgrimes * Now, sort by propself + propchild. 2351590Srgrimes * sorting both the regular function names 2361590Srgrimes * and cycle headers. 2371590Srgrimes */ 2381590Srgrimes timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 239105243Scharnier if ( timesortnlp == (nltype **) 0 ) 240105243Scharnier errx( 1 , "ran out of memory for sorting" ); 2411590Srgrimes for ( index = 0 ; index < nname ; index++ ) { 2421590Srgrimes timesortnlp[index] = &nl[index]; 2431590Srgrimes } 2441590Srgrimes for ( index = 1 ; index <= ncycle ; index++ ) { 2451590Srgrimes timesortnlp[nname+index-1] = &cyclenl[index]; 2461590Srgrimes } 2471590Srgrimes qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); 2481590Srgrimes for ( index = 0 ; index < nname + ncycle ; index++ ) { 2491590Srgrimes timesortnlp[ index ] -> index = index + 1; 2501590Srgrimes } 2511590Srgrimes return( timesortnlp ); 2521590Srgrimes} 2531590Srgrimes 254105243Scharniervoid 255246783Scharnierdotime(void) 2561590Srgrimes{ 2571590Srgrimes int index; 2581590Srgrimes 2591590Srgrimes cycletime(); 2601590Srgrimes for ( index = 0 ; index < nname ; index += 1 ) { 2611590Srgrimes timepropagate( topsortnlp[ index ] ); 2621590Srgrimes } 2631590Srgrimes} 2641590Srgrimes 265105243Scharniervoid 266246783Scharniertimepropagate(nltype *parentp) 2671590Srgrimes{ 2681590Srgrimes arctype *arcp; 2691590Srgrimes nltype *childp; 2701590Srgrimes double share; 2711590Srgrimes double propshare; 2721590Srgrimes 2731590Srgrimes if ( parentp -> propfraction == 0.0 ) { 2741590Srgrimes return; 2751590Srgrimes } 2761590Srgrimes /* 2771590Srgrimes * gather time from children of this parent. 2781590Srgrimes */ 2791590Srgrimes for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 2801590Srgrimes childp = arcp -> arc_childp; 2811590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 2821590Srgrimes continue; 2831590Srgrimes } 2841590Srgrimes if ( arcp -> arc_count == 0 ) { 2851590Srgrimes continue; 2861590Srgrimes } 2871590Srgrimes if ( childp == parentp ) { 2881590Srgrimes continue; 2891590Srgrimes } 2901590Srgrimes if ( childp -> propfraction == 0.0 ) { 2911590Srgrimes continue; 2921590Srgrimes } 2931590Srgrimes if ( childp -> cyclehead != childp ) { 2941590Srgrimes if ( parentp -> cycleno == childp -> cycleno ) { 2951590Srgrimes continue; 2961590Srgrimes } 2971590Srgrimes if ( parentp -> toporder <= childp -> toporder ) { 2981590Srgrimes fprintf( stderr , "[propagate] toporder botches\n" ); 2991590Srgrimes } 3001590Srgrimes childp = childp -> cyclehead; 3011590Srgrimes } else { 3021590Srgrimes if ( parentp -> toporder <= childp -> toporder ) { 3031590Srgrimes fprintf( stderr , "[propagate] toporder botches\n" ); 3041590Srgrimes continue; 3051590Srgrimes } 3061590Srgrimes } 3071590Srgrimes if ( childp -> npropcall == 0 ) { 3081590Srgrimes continue; 3091590Srgrimes } 3101590Srgrimes /* 3111590Srgrimes * distribute time for this arc 3121590Srgrimes */ 3131590Srgrimes arcp -> arc_time = childp -> time 3141590Srgrimes * ( ( (double) arcp -> arc_count ) / 3151590Srgrimes ( (double) childp -> npropcall ) ); 3161590Srgrimes arcp -> arc_childtime = childp -> childtime 3171590Srgrimes * ( ( (double) arcp -> arc_count ) / 3181590Srgrimes ( (double) childp -> npropcall ) ); 3191590Srgrimes share = arcp -> arc_time + arcp -> arc_childtime; 3201590Srgrimes parentp -> childtime += share; 3211590Srgrimes /* 3221590Srgrimes * ( 1 - propfraction ) gets lost along the way 3231590Srgrimes */ 3241590Srgrimes propshare = parentp -> propfraction * share; 3251590Srgrimes /* 3261590Srgrimes * fix things for printing 3271590Srgrimes */ 3281590Srgrimes parentp -> propchild += propshare; 3291590Srgrimes arcp -> arc_time *= parentp -> propfraction; 3301590Srgrimes arcp -> arc_childtime *= parentp -> propfraction; 3311590Srgrimes /* 3321590Srgrimes * add this share to the parent's cycle header, if any. 3331590Srgrimes */ 3341590Srgrimes if ( parentp -> cyclehead != parentp ) { 3351590Srgrimes parentp -> cyclehead -> childtime += share; 3361590Srgrimes parentp -> cyclehead -> propchild += propshare; 3371590Srgrimes } 3381590Srgrimes# ifdef DEBUG 3391590Srgrimes if ( debug & PROPDEBUG ) { 3401590Srgrimes printf( "[dotime] child \t" ); 3411590Srgrimes printname( childp ); 34291018Sbde printf( " with %f %f %ld/%ld\n" , 3431590Srgrimes childp -> time , childp -> childtime , 3441590Srgrimes arcp -> arc_count , childp -> npropcall ); 3451590Srgrimes printf( "[dotime] parent\t" ); 3461590Srgrimes printname( parentp ); 3471590Srgrimes printf( "\n[dotime] share %f\n" , share ); 3481590Srgrimes } 34997631Swollman# endif /* DEBUG */ 3501590Srgrimes } 3511590Srgrimes} 3521590Srgrimes 353105243Scharniervoid 354246783Scharniercyclelink(void) 3551590Srgrimes{ 3561590Srgrimes register nltype *nlp; 3571590Srgrimes register nltype *cyclenlp; 3581590Srgrimes int cycle; 3591590Srgrimes nltype *memberp; 3601590Srgrimes arctype *arcp; 3611590Srgrimes 3621590Srgrimes /* 363105243Scharnier * Count the number of cycles, and initialize the cycle lists 3641590Srgrimes */ 3651590Srgrimes ncycle = 0; 3661590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3671590Srgrimes /* 3681590Srgrimes * this is how you find unattached cycles 3691590Srgrimes */ 3701590Srgrimes if ( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) { 3711590Srgrimes ncycle += 1; 3721590Srgrimes } 3731590Srgrimes } 3741590Srgrimes /* 3751590Srgrimes * cyclenl is indexed by cycle number: 3761590Srgrimes * i.e. it is origin 1, not origin 0. 3771590Srgrimes */ 3781590Srgrimes cyclenl = (nltype *) calloc( ncycle + 1 , sizeof( nltype ) ); 379105243Scharnier if ( cyclenl == 0 ) 380228629Sdim errx( 1 , "no room for %zu bytes of cycle headers" , 38127414Scharnier ( ncycle + 1 ) * sizeof( nltype ) ); 3821590Srgrimes /* 3831590Srgrimes * now link cycles to true cycleheads, 3841590Srgrimes * number them, accumulate the data for the cycle 3851590Srgrimes */ 3861590Srgrimes cycle = 0; 3871590Srgrimes for ( nlp = nl ; nlp < npe ; nlp++ ) { 3881590Srgrimes if ( !( nlp -> cyclehead == nlp && nlp -> cnext != 0 ) ) { 3891590Srgrimes continue; 3901590Srgrimes } 3911590Srgrimes cycle += 1; 3921590Srgrimes cyclenlp = &cyclenl[cycle]; 3931590Srgrimes cyclenlp -> name = 0; /* the name */ 3941590Srgrimes cyclenlp -> value = 0; /* the pc entry point */ 3951590Srgrimes cyclenlp -> time = 0.0; /* ticks in this routine */ 3961590Srgrimes cyclenlp -> childtime = 0.0; /* cumulative ticks in children */ 3971590Srgrimes cyclenlp -> ncall = 0; /* how many times called */ 3981590Srgrimes cyclenlp -> selfcalls = 0; /* how many calls to self */ 3991590Srgrimes cyclenlp -> propfraction = 0.0; /* what % of time propagates */ 4001590Srgrimes cyclenlp -> propself = 0.0; /* how much self time propagates */ 4011590Srgrimes cyclenlp -> propchild = 0.0; /* how much child time propagates */ 4021590Srgrimes cyclenlp -> printflag = TRUE; /* should this be printed? */ 4031590Srgrimes cyclenlp -> index = 0; /* index in the graph list */ 4041590Srgrimes cyclenlp -> toporder = DFN_NAN; /* graph call chain top-sort order */ 4051590Srgrimes cyclenlp -> cycleno = cycle; /* internal number of cycle on */ 4061590Srgrimes cyclenlp -> cyclehead = cyclenlp; /* pointer to head of cycle */ 4071590Srgrimes cyclenlp -> cnext = nlp; /* pointer to next member of cycle */ 4081590Srgrimes cyclenlp -> parents = 0; /* list of caller arcs */ 4091590Srgrimes cyclenlp -> children = 0; /* list of callee arcs */ 4101590Srgrimes# ifdef DEBUG 4111590Srgrimes if ( debug & CYCLEDEBUG ) { 4121590Srgrimes printf( "[cyclelink] " ); 4131590Srgrimes printname( nlp ); 4141590Srgrimes printf( " is the head of cycle %d\n" , cycle ); 4151590Srgrimes } 41697631Swollman# endif /* DEBUG */ 4171590Srgrimes /* 4181590Srgrimes * link members to cycle header 4191590Srgrimes */ 4208874Srgrimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4211590Srgrimes memberp -> cycleno = cycle; 4221590Srgrimes memberp -> cyclehead = cyclenlp; 4231590Srgrimes } 4241590Srgrimes /* 4251590Srgrimes * count calls from outside the cycle 4261590Srgrimes * and those among cycle members 4271590Srgrimes */ 4281590Srgrimes for ( memberp = nlp ; memberp ; memberp = memberp -> cnext ) { 4291590Srgrimes for ( arcp=memberp->parents ; arcp ; arcp=arcp->arc_parentlist ) { 4301590Srgrimes if ( arcp -> arc_parentp == memberp ) { 4311590Srgrimes continue; 4321590Srgrimes } 4331590Srgrimes if ( arcp -> arc_parentp -> cycleno == cycle ) { 4341590Srgrimes cyclenlp -> selfcalls += arcp -> arc_count; 4351590Srgrimes } else { 4361590Srgrimes cyclenlp -> npropcall += arcp -> arc_count; 4371590Srgrimes } 4381590Srgrimes } 4391590Srgrimes } 4401590Srgrimes } 4411590Srgrimes} 4421590Srgrimes 4431590Srgrimes /* 4441590Srgrimes * analyze cycles to determine breakup 4451590Srgrimes */ 446105243Scharnierbool 447246783Scharniercycleanalyze(void) 4481590Srgrimes{ 4491590Srgrimes arctype **cyclestack; 4501590Srgrimes arctype **stkp; 4511590Srgrimes arctype **arcpp; 4521590Srgrimes arctype **endlist; 4531590Srgrimes arctype *arcp; 4541590Srgrimes nltype *nlp; 4551590Srgrimes cltype *clp; 4561590Srgrimes bool ret; 4571590Srgrimes bool done; 4581590Srgrimes int size; 4591590Srgrimes int cycleno; 4601590Srgrimes 4611590Srgrimes /* 4621590Srgrimes * calculate the size of the cycle, and find nodes that 4631590Srgrimes * exit the cycle as they are desirable targets to cut 4641590Srgrimes * some of their parents 4651590Srgrimes */ 4661590Srgrimes for ( done = TRUE , cycleno = 1 ; cycleno <= ncycle ; cycleno++ ) { 4671590Srgrimes size = 0; 4681590Srgrimes for (nlp = cyclenl[ cycleno ] . cnext; nlp; nlp = nlp -> cnext) { 4691590Srgrimes size += 1; 4701590Srgrimes nlp -> parentcnt = 0; 4711590Srgrimes nlp -> flags &= ~HASCYCLEXIT; 4721590Srgrimes for ( arcp = nlp -> parents; arcp; arcp = arcp -> arc_parentlist ) { 4731590Srgrimes nlp -> parentcnt += 1; 4741590Srgrimes if ( arcp -> arc_parentp -> cycleno != cycleno ) 4751590Srgrimes nlp -> flags |= HASCYCLEXIT; 4761590Srgrimes } 4771590Srgrimes } 4781590Srgrimes if ( size <= cyclethreshold ) 4791590Srgrimes continue; 4801590Srgrimes done = FALSE; 4811590Srgrimes cyclestack = (arctype **) calloc( size + 1 , sizeof( arctype *) ); 482105243Scharnier if ( cyclestack == 0 ) 483228629Sdim errx( 1, "no room for %zu bytes of cycle stack" , 48427414Scharnier ( size + 1 ) * sizeof( arctype * ) ); 4851590Srgrimes# ifdef DEBUG 4861590Srgrimes if ( debug & BREAKCYCLE ) { 4871590Srgrimes printf( "[cycleanalyze] starting cycle %d of %d, size %d\n" , 4881590Srgrimes cycleno , ncycle , size ); 4891590Srgrimes } 49097631Swollman# endif /* DEBUG */ 4911590Srgrimes for ( nlp = cyclenl[ cycleno ] . cnext ; nlp ; nlp = nlp -> cnext ) { 4921590Srgrimes stkp = &cyclestack[0]; 4931590Srgrimes nlp -> flags |= CYCLEHEAD; 4941590Srgrimes ret = descend ( nlp , cyclestack , stkp ); 4951590Srgrimes nlp -> flags &= ~CYCLEHEAD; 4961590Srgrimes if ( ret == FALSE ) 4971590Srgrimes break; 4981590Srgrimes } 4991590Srgrimes free( cyclestack ); 5001590Srgrimes if ( cyclecnt > 0 ) { 5011590Srgrimes compresslist(); 5021590Srgrimes for ( clp = cyclehead ; clp ; ) { 5031590Srgrimes endlist = &clp -> list[ clp -> size ]; 5041590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 5051590Srgrimes (*arcpp) -> arc_cyclecnt--; 5061590Srgrimes cyclecnt--; 5071590Srgrimes clp = clp -> next; 5081590Srgrimes free( clp ); 5091590Srgrimes } 5101590Srgrimes cyclehead = 0; 5111590Srgrimes } 5121590Srgrimes } 5131590Srgrimes# ifdef DEBUG 5141590Srgrimes if ( debug & BREAKCYCLE ) { 5151590Srgrimes printf("%s visited %d, viable %d, newcycle %d, oldcycle %d\n", 5161590Srgrimes "[doarcs]" , visited , viable , newcycle , oldcycle); 5171590Srgrimes } 51897631Swollman# endif /* DEBUG */ 5191590Srgrimes return( done ); 5201590Srgrimes} 5211590Srgrimes 522105243Scharnierbool 523246783Scharnierdescend(nltype *node, arctype **stkstart, arctype **stkp) 5241590Srgrimes{ 5251590Srgrimes arctype *arcp; 5261590Srgrimes bool ret; 5271590Srgrimes 5281590Srgrimes for ( arcp = node -> children ; arcp ; arcp = arcp -> arc_childlist ) { 5291590Srgrimes# ifdef DEBUG 5301590Srgrimes visited++; 53197631Swollman# endif /* DEBUG */ 5321590Srgrimes if ( arcp -> arc_childp -> cycleno != node -> cycleno 5331590Srgrimes || ( arcp -> arc_childp -> flags & VISITED ) 5341590Srgrimes || ( arcp -> arc_flags & DEADARC ) ) 5351590Srgrimes continue; 5361590Srgrimes# ifdef DEBUG 5371590Srgrimes viable++; 53897631Swollman# endif /* DEBUG */ 5391590Srgrimes *stkp = arcp; 5401590Srgrimes if ( arcp -> arc_childp -> flags & CYCLEHEAD ) { 5411590Srgrimes if ( addcycle( stkstart , stkp ) == FALSE ) 5421590Srgrimes return( FALSE ); 5431590Srgrimes continue; 5441590Srgrimes } 5451590Srgrimes arcp -> arc_childp -> flags |= VISITED; 5461590Srgrimes ret = descend( arcp -> arc_childp , stkstart , stkp + 1 ); 5471590Srgrimes arcp -> arc_childp -> flags &= ~VISITED; 5481590Srgrimes if ( ret == FALSE ) 5491590Srgrimes return( FALSE ); 5501590Srgrimes } 551105243Scharnier return( TRUE ); 5521590Srgrimes} 5531590Srgrimes 554105243Scharnierbool 555246783Scharnieraddcycle(arctype **stkstart, arctype **stkend) 5561590Srgrimes{ 5571590Srgrimes arctype **arcpp; 5581590Srgrimes arctype **stkloc; 5591590Srgrimes arctype **stkp; 5601590Srgrimes arctype **endlist; 5611590Srgrimes arctype *minarc; 5621590Srgrimes arctype *arcp; 5631590Srgrimes cltype *clp; 5641590Srgrimes int size; 5651590Srgrimes 5661590Srgrimes size = stkend - stkstart + 1; 5671590Srgrimes if ( size <= 1 ) 5681590Srgrimes return( TRUE ); 5691590Srgrimes for ( arcpp = stkstart , minarc = *arcpp ; arcpp <= stkend ; arcpp++ ) { 5701590Srgrimes if ( *arcpp > minarc ) 5711590Srgrimes continue; 5721590Srgrimes minarc = *arcpp; 5731590Srgrimes stkloc = arcpp; 5741590Srgrimes } 5751590Srgrimes for ( clp = cyclehead ; clp ; clp = clp -> next ) { 5761590Srgrimes if ( clp -> size != size ) 5771590Srgrimes continue; 5781590Srgrimes stkp = stkloc; 5791590Srgrimes endlist = &clp -> list[ size ]; 5801590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 5811590Srgrimes if ( *stkp++ != *arcpp ) 5821590Srgrimes break; 5831590Srgrimes if ( stkp > stkend ) 5841590Srgrimes stkp = stkstart; 5851590Srgrimes } 5861590Srgrimes if ( arcpp == endlist ) { 5871590Srgrimes# ifdef DEBUG 5881590Srgrimes oldcycle++; 58997631Swollman# endif /* DEBUG */ 5901590Srgrimes return( TRUE ); 5911590Srgrimes } 5921590Srgrimes } 5931590Srgrimes clp = (cltype *) 5941590Srgrimes calloc( 1 , sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 5951590Srgrimes if ( clp == 0 ) { 596228629Sdim warnx( "no room for %zu bytes of subcycle storage" , 59727313Scharnier sizeof ( cltype ) + ( size - 1 ) * sizeof( arctype * ) ); 5981590Srgrimes return( FALSE ); 5991590Srgrimes } 6001590Srgrimes stkp = stkloc; 6011590Srgrimes endlist = &clp -> list[ size ]; 6021590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) { 6031590Srgrimes arcp = *arcpp = *stkp++; 6041590Srgrimes if ( stkp > stkend ) 6051590Srgrimes stkp = stkstart; 6061590Srgrimes arcp -> arc_cyclecnt++; 6071590Srgrimes if ( ( arcp -> arc_flags & ONLIST ) == 0 ) { 6081590Srgrimes arcp -> arc_flags |= ONLIST; 6091590Srgrimes arcp -> arc_next = archead; 6101590Srgrimes archead = arcp; 6111590Srgrimes } 6121590Srgrimes } 6131590Srgrimes clp -> size = size; 6141590Srgrimes clp -> next = cyclehead; 6151590Srgrimes cyclehead = clp; 6161590Srgrimes# ifdef DEBUG 6171590Srgrimes newcycle++; 6181590Srgrimes if ( debug & SUBCYCLELIST ) { 6191590Srgrimes printsubcycle( clp ); 6201590Srgrimes } 62197631Swollman# endif /* DEBUG */ 6221590Srgrimes cyclecnt++; 6231590Srgrimes if ( cyclecnt >= CYCLEMAX ) 6241590Srgrimes return( FALSE ); 6251590Srgrimes return( TRUE ); 6261590Srgrimes} 6271590Srgrimes 628105243Scharniervoid 629246783Scharniercompresslist(void) 6301590Srgrimes{ 6311590Srgrimes cltype *clp; 6321590Srgrimes cltype **prev; 6331590Srgrimes arctype **arcpp; 6341590Srgrimes arctype **endlist; 6351590Srgrimes arctype *arcp; 6361590Srgrimes arctype *maxarcp; 6371590Srgrimes arctype *maxexitarcp; 6381590Srgrimes arctype *maxwithparentarcp; 6391590Srgrimes arctype *maxnoparentarcp; 6401590Srgrimes int maxexitcnt; 6411590Srgrimes int maxwithparentcnt; 6421590Srgrimes int maxnoparentcnt; 64391012Sbde# ifdef DEBUG 64491012Sbde const char *type; 64597631Swollman# endif /* DEBUG */ 6461590Srgrimes 6471590Srgrimes maxexitcnt = 0; 6481590Srgrimes maxwithparentcnt = 0; 6491590Srgrimes maxnoparentcnt = 0; 6501590Srgrimes for ( endlist = &archead , arcp = archead ; arcp ; ) { 6511590Srgrimes if ( arcp -> arc_cyclecnt == 0 ) { 6521590Srgrimes arcp -> arc_flags &= ~ONLIST; 6531590Srgrimes *endlist = arcp -> arc_next; 6541590Srgrimes arcp -> arc_next = 0; 6551590Srgrimes arcp = *endlist; 6561590Srgrimes continue; 6571590Srgrimes } 6581590Srgrimes if ( arcp -> arc_childp -> flags & HASCYCLEXIT ) { 6591590Srgrimes if ( arcp -> arc_cyclecnt > maxexitcnt || 6601590Srgrimes ( arcp -> arc_cyclecnt == maxexitcnt && 6611590Srgrimes arcp -> arc_cyclecnt < maxexitarcp -> arc_count ) ) { 6621590Srgrimes maxexitcnt = arcp -> arc_cyclecnt; 6631590Srgrimes maxexitarcp = arcp; 6641590Srgrimes } 6651590Srgrimes } else if ( arcp -> arc_childp -> parentcnt > 1 ) { 6661590Srgrimes if ( arcp -> arc_cyclecnt > maxwithparentcnt || 6671590Srgrimes ( arcp -> arc_cyclecnt == maxwithparentcnt && 6681590Srgrimes arcp -> arc_cyclecnt < maxwithparentarcp -> arc_count ) ) { 6691590Srgrimes maxwithparentcnt = arcp -> arc_cyclecnt; 6701590Srgrimes maxwithparentarcp = arcp; 6711590Srgrimes } 6721590Srgrimes } else { 6731590Srgrimes if ( arcp -> arc_cyclecnt > maxnoparentcnt || 6741590Srgrimes ( arcp -> arc_cyclecnt == maxnoparentcnt && 6751590Srgrimes arcp -> arc_cyclecnt < maxnoparentarcp -> arc_count ) ) { 6761590Srgrimes maxnoparentcnt = arcp -> arc_cyclecnt; 6771590Srgrimes maxnoparentarcp = arcp; 6781590Srgrimes } 6791590Srgrimes } 6801590Srgrimes endlist = &arcp -> arc_next; 6811590Srgrimes arcp = arcp -> arc_next; 6821590Srgrimes } 6831590Srgrimes if ( maxexitcnt > 0 ) { 6841590Srgrimes /* 6851590Srgrimes * first choice is edge leading to node with out-of-cycle parent 6861590Srgrimes */ 6871590Srgrimes maxarcp = maxexitarcp; 6881590Srgrimes# ifdef DEBUG 6891590Srgrimes type = "exit"; 69097631Swollman# endif /* DEBUG */ 6911590Srgrimes } else if ( maxwithparentcnt > 0 ) { 6921590Srgrimes /* 6931590Srgrimes * second choice is edge leading to node with at least one 6941590Srgrimes * other in-cycle parent 6951590Srgrimes */ 6961590Srgrimes maxarcp = maxwithparentarcp; 6971590Srgrimes# ifdef DEBUG 6981590Srgrimes type = "internal"; 69997631Swollman# endif /* DEBUG */ 7001590Srgrimes } else { 7011590Srgrimes /* 7021590Srgrimes * last choice is edge leading to node with only this arc as 7031590Srgrimes * a parent (as it will now be orphaned) 7041590Srgrimes */ 7051590Srgrimes maxarcp = maxnoparentarcp; 7061590Srgrimes# ifdef DEBUG 7071590Srgrimes type = "orphan"; 70897631Swollman# endif /* DEBUG */ 7091590Srgrimes } 7101590Srgrimes maxarcp -> arc_flags |= DEADARC; 7111590Srgrimes maxarcp -> arc_childp -> parentcnt -= 1; 7121590Srgrimes maxarcp -> arc_childp -> npropcall -= maxarcp -> arc_count; 7131590Srgrimes# ifdef DEBUG 7141590Srgrimes if ( debug & BREAKCYCLE ) { 71591018Sbde printf( "%s delete %s arc: %s (%ld) -> %s from %u cycle(s)\n" , 7161590Srgrimes "[compresslist]" , type , maxarcp -> arc_parentp -> name , 7171590Srgrimes maxarcp -> arc_count , maxarcp -> arc_childp -> name , 7181590Srgrimes maxarcp -> arc_cyclecnt ); 7191590Srgrimes } 72097631Swollman# endif /* DEBUG */ 72191018Sbde printf( "\t%s to %s with %ld calls\n" , maxarcp -> arc_parentp -> name , 7221590Srgrimes maxarcp -> arc_childp -> name , maxarcp -> arc_count ); 7231590Srgrimes prev = &cyclehead; 7241590Srgrimes for ( clp = cyclehead ; clp ; ) { 7251590Srgrimes endlist = &clp -> list[ clp -> size ]; 7261590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7271590Srgrimes if ( (*arcpp) -> arc_flags & DEADARC ) 7281590Srgrimes break; 7291590Srgrimes if ( arcpp == endlist ) { 7301590Srgrimes prev = &clp -> next; 7311590Srgrimes clp = clp -> next; 7321590Srgrimes continue; 7331590Srgrimes } 7341590Srgrimes for ( arcpp = clp -> list ; arcpp < endlist ; arcpp++ ) 7351590Srgrimes (*arcpp) -> arc_cyclecnt--; 7361590Srgrimes cyclecnt--; 7371590Srgrimes *prev = clp -> next; 7381590Srgrimes clp = clp -> next; 7391590Srgrimes free( clp ); 7401590Srgrimes } 7411590Srgrimes} 7421590Srgrimes 7431590Srgrimes#ifdef DEBUG 744105243Scharniervoid 745246783Scharnierprintsubcycle(cltype *clp) 7461590Srgrimes{ 7471590Srgrimes arctype **arcpp; 7481590Srgrimes arctype **endlist; 7491590Srgrimes 7501590Srgrimes arcpp = clp -> list; 7511590Srgrimes printf( "%s <cycle %d>\n" , (*arcpp) -> arc_parentp -> name , 7521590Srgrimes (*arcpp) -> arc_parentp -> cycleno ) ; 7531590Srgrimes for ( endlist = &clp -> list[ clp -> size ]; arcpp < endlist ; arcpp++ ) 75491018Sbde printf( "\t(%ld) -> %s\n" , (*arcpp) -> arc_count , 7551590Srgrimes (*arcpp) -> arc_childp -> name ) ; 7561590Srgrimes} 75797631Swollman#endif /* DEBUG */ 7581590Srgrimes 759105243Scharniervoid 760246783Scharniercycletime(void) 7611590Srgrimes{ 7621590Srgrimes int cycle; 7631590Srgrimes nltype *cyclenlp; 7641590Srgrimes nltype *childp; 7651590Srgrimes 7661590Srgrimes for ( cycle = 1 ; cycle <= ncycle ; cycle += 1 ) { 7671590Srgrimes cyclenlp = &cyclenl[ cycle ]; 7681590Srgrimes for ( childp = cyclenlp -> cnext ; childp ; childp = childp -> cnext ) { 7691590Srgrimes if ( childp -> propfraction == 0.0 ) { 7701590Srgrimes /* 7711590Srgrimes * all members have the same propfraction except those 7721590Srgrimes * that were excluded with -E 7731590Srgrimes */ 7741590Srgrimes continue; 7751590Srgrimes } 7761590Srgrimes cyclenlp -> time += childp -> time; 7771590Srgrimes } 7781590Srgrimes cyclenlp -> propself = cyclenlp -> propfraction * cyclenlp -> time; 7791590Srgrimes } 7801590Srgrimes} 7811590Srgrimes 7821590Srgrimes /* 7831590Srgrimes * in one top to bottom pass over the topologically sorted namelist 7841590Srgrimes * propagate: 7851590Srgrimes * printflag as the union of parents' printflags 7861590Srgrimes * propfraction as the sum of fractional parents' propfractions 7871590Srgrimes * and while we're here, sum time for functions. 7881590Srgrimes */ 789105243Scharniervoid 790246783Scharnierdoflags(void) 7911590Srgrimes{ 7921590Srgrimes int index; 7931590Srgrimes nltype *childp; 7941590Srgrimes nltype *oldhead; 7951590Srgrimes 7961590Srgrimes oldhead = 0; 7971590Srgrimes for ( index = nname-1 ; index >= 0 ; index -= 1 ) { 7981590Srgrimes childp = topsortnlp[ index ]; 7991590Srgrimes /* 8001590Srgrimes * if we haven't done this function or cycle, 8011590Srgrimes * inherit things from parent. 8021590Srgrimes * this way, we are linear in the number of arcs 8031590Srgrimes * since we do all members of a cycle (and the cycle itself) 8041590Srgrimes * as we hit the first member of the cycle. 8051590Srgrimes */ 8061590Srgrimes if ( childp -> cyclehead != oldhead ) { 8071590Srgrimes oldhead = childp -> cyclehead; 8081590Srgrimes inheritflags( childp ); 8091590Srgrimes } 8101590Srgrimes# ifdef DEBUG 8111590Srgrimes if ( debug & PROPDEBUG ) { 8121590Srgrimes printf( "[doflags] " ); 8131590Srgrimes printname( childp ); 8141590Srgrimes printf( " inherits printflag %d and propfraction %f\n" , 8151590Srgrimes childp -> printflag , childp -> propfraction ); 8161590Srgrimes } 81797631Swollman# endif /* DEBUG */ 8181590Srgrimes if ( ! childp -> printflag ) { 8191590Srgrimes /* 8201590Srgrimes * printflag is off 8211590Srgrimes * it gets turned on by 8221590Srgrimes * being on -f list, 8231590Srgrimes * or there not being any -f list and not being on -e list. 8241590Srgrimes */ 8251590Srgrimes if ( onlist( flist , childp -> name ) 8261590Srgrimes || ( !fflag && !onlist( elist , childp -> name ) ) ) { 8271590Srgrimes childp -> printflag = TRUE; 8281590Srgrimes } 8291590Srgrimes } else { 8301590Srgrimes /* 8311590Srgrimes * this function has printing parents: 8321590Srgrimes * maybe someone wants to shut it up 8331590Srgrimes * by putting it on -e list. (but favor -f over -e) 8341590Srgrimes */ 8351590Srgrimes if ( ( !onlist( flist , childp -> name ) ) 8361590Srgrimes && onlist( elist , childp -> name ) ) { 8371590Srgrimes childp -> printflag = FALSE; 8381590Srgrimes } 8391590Srgrimes } 8401590Srgrimes if ( childp -> propfraction == 0.0 ) { 8411590Srgrimes /* 8421590Srgrimes * no parents to pass time to. 8431590Srgrimes * collect time from children if 8441590Srgrimes * its on -F list, 8451590Srgrimes * or there isn't any -F list and its not on -E list. 8461590Srgrimes */ 8471590Srgrimes if ( onlist( Flist , childp -> name ) 8481590Srgrimes || ( !Fflag && !onlist( Elist , childp -> name ) ) ) { 8491590Srgrimes childp -> propfraction = 1.0; 8501590Srgrimes } 8511590Srgrimes } else { 8521590Srgrimes /* 8538874Srgrimes * it has parents to pass time to, 8541590Srgrimes * but maybe someone wants to shut it up 855105243Scharnier * by putting it on -E list. (but favor -F over -E) 8561590Srgrimes */ 8571590Srgrimes if ( !onlist( Flist , childp -> name ) 8581590Srgrimes && onlist( Elist , childp -> name ) ) { 8591590Srgrimes childp -> propfraction = 0.0; 8601590Srgrimes } 8611590Srgrimes } 8621590Srgrimes childp -> propself = childp -> time * childp -> propfraction; 8631590Srgrimes printtime += childp -> propself; 8641590Srgrimes# ifdef DEBUG 8651590Srgrimes if ( debug & PROPDEBUG ) { 8661590Srgrimes printf( "[doflags] " ); 8671590Srgrimes printname( childp ); 8681590Srgrimes printf( " ends up with printflag %d and propfraction %f\n" , 8691590Srgrimes childp -> printflag , childp -> propfraction ); 8701590Srgrimes printf( "time %f propself %f printtime %f\n" , 8711590Srgrimes childp -> time , childp -> propself , printtime ); 8721590Srgrimes } 87397631Swollman# endif /* DEBUG */ 8741590Srgrimes } 8751590Srgrimes} 8761590Srgrimes 8771590Srgrimes /* 8781590Srgrimes * check if any parent of this child 8791590Srgrimes * (or outside parents of this cycle) 8808874Srgrimes * have their print flags on and set the 8811590Srgrimes * print flag of the child (cycle) appropriately. 8821590Srgrimes * similarly, deal with propagation fractions from parents. 8831590Srgrimes */ 884105243Scharniervoid 885246783Scharnierinheritflags(nltype *childp) 8861590Srgrimes{ 8871590Srgrimes nltype *headp; 8881590Srgrimes arctype *arcp; 8891590Srgrimes nltype *parentp; 8901590Srgrimes nltype *memp; 8911590Srgrimes 8921590Srgrimes headp = childp -> cyclehead; 8931590Srgrimes if ( childp == headp ) { 8941590Srgrimes /* 8951590Srgrimes * just a regular child, check its parents 8961590Srgrimes */ 8971590Srgrimes childp -> printflag = FALSE; 8981590Srgrimes childp -> propfraction = 0.0; 8991590Srgrimes for (arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist) { 9001590Srgrimes parentp = arcp -> arc_parentp; 9011590Srgrimes if ( childp == parentp ) { 9021590Srgrimes continue; 9031590Srgrimes } 9041590Srgrimes childp -> printflag |= parentp -> printflag; 9051590Srgrimes /* 9061590Srgrimes * if the child was never actually called 9071590Srgrimes * (e.g. this arc is static (and all others are, too)) 9081590Srgrimes * no time propagates along this arc. 9091590Srgrimes */ 9101590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 9111590Srgrimes continue; 9121590Srgrimes } 9131590Srgrimes if ( childp -> npropcall ) { 9141590Srgrimes childp -> propfraction += parentp -> propfraction 9151590Srgrimes * ( ( (double) arcp -> arc_count ) 9161590Srgrimes / ( (double) childp -> npropcall ) ); 9171590Srgrimes } 9181590Srgrimes } 9191590Srgrimes } else { 9201590Srgrimes /* 9218874Srgrimes * its a member of a cycle, look at all parents from 9221590Srgrimes * outside the cycle 9231590Srgrimes */ 9241590Srgrimes headp -> printflag = FALSE; 9251590Srgrimes headp -> propfraction = 0.0; 9261590Srgrimes for ( memp = headp -> cnext ; memp ; memp = memp -> cnext ) { 9271590Srgrimes for (arcp = memp->parents ; arcp ; arcp = arcp->arc_parentlist) { 9281590Srgrimes if ( arcp -> arc_parentp -> cyclehead == headp ) { 9291590Srgrimes continue; 9301590Srgrimes } 9311590Srgrimes parentp = arcp -> arc_parentp; 9321590Srgrimes headp -> printflag |= parentp -> printflag; 9331590Srgrimes /* 9341590Srgrimes * if the cycle was never actually called 9351590Srgrimes * (e.g. this arc is static (and all others are, too)) 9361590Srgrimes * no time propagates along this arc. 9371590Srgrimes */ 9381590Srgrimes if ( arcp -> arc_flags & DEADARC ) { 9391590Srgrimes continue; 9401590Srgrimes } 9411590Srgrimes if ( headp -> npropcall ) { 9421590Srgrimes headp -> propfraction += parentp -> propfraction 9431590Srgrimes * ( ( (double) arcp -> arc_count ) 9441590Srgrimes / ( (double) headp -> npropcall ) ); 9451590Srgrimes } 9461590Srgrimes } 9471590Srgrimes } 9481590Srgrimes for ( memp = headp ; memp ; memp = memp -> cnext ) { 9491590Srgrimes memp -> printflag = headp -> printflag; 9501590Srgrimes memp -> propfraction = headp -> propfraction; 9511590Srgrimes } 9521590Srgrimes } 9531590Srgrimes} 954