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