xref: /csrg-svn/usr.bin/gprof/printgprof.c (revision 10248)
14515Speter #ifndef lint
2*10248Speter     static	char *sccsid = "@(#)printgprof.c	1.12 (Berkeley) 01/11/83";
34515Speter #endif lint
44515Speter 
54562Speter #include "gprof.h"
64515Speter 
74753Speter printprof()
84753Speter {
94753Speter     register nltype	*np;
104753Speter     nltype		**sortednlp;
114753Speter     int			index;
124753Speter 
137172Speter     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
147172Speter 	    (long) scale * sizeof(UNIT) );
157225Speter     if ( totime > 0.0 ) {
167225Speter 	printf( " for %.2f%% of %.2f seconds\n\n" ,
17*10248Speter 		100.0/totime , totime / hz );
187225Speter     } else {
197225Speter 	printf( " no time accumulated\n\n" );
207225Speter 	    /*
217225Speter 	     *	this doesn't hurt sinc eall the numerators will be zero.
227225Speter 	     */
237225Speter 	totime = 1.0;
247225Speter     }
254753Speter     actime = 0.0;
264753Speter     flatprofheader();
274753Speter 	/*
284753Speter 	 *	Sort the symbol table in by time
294753Speter 	 */
304753Speter     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
314753Speter     if ( sortednlp == (nltype **) 0 ) {
324753Speter 	fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
334753Speter     }
344753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
354753Speter 	sortednlp[ index ] = &nl[ index ];
364753Speter     }
374753Speter     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
384753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
394753Speter 	np = sortednlp[ index ];
404753Speter 	flatprofline( np );
414753Speter     }
424753Speter     actime = 0.0;
434753Speter }
444753Speter 
454753Speter timecmp( npp1 , npp2 )
464753Speter     nltype **npp1, **npp2;
474753Speter {
484856Speter     double	timediff;
494856Speter     long	calldiff;
504753Speter 
514856Speter     timediff = (*npp2) -> time - (*npp1) -> time;
524856Speter     if ( timediff > 0.0 )
534753Speter 	return 1 ;
544856Speter     if ( timediff < 0.0 )
554753Speter 	return -1;
564856Speter     calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
574856Speter     if ( calldiff > 0 )
584856Speter 	return 1;
594856Speter     if ( calldiff < 0 )
604856Speter 	return -1;
614753Speter     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
624753Speter }
634753Speter 
644753Speter     /*
654753Speter      *	header for flatprofline
664753Speter      */
674753Speter flatprofheader()
684753Speter {
694753Speter 
704854Speter     if ( bflag ) {
714854Speter 	printblurb( "flat.blurb" );
724854Speter     }
734753Speter     printf( "%5.5s %7.7s %7.7s %7.7s %-8.8s\n" ,
744753Speter 	    "%time" , "cumsecs" , "seconds" , "calls" , "name" );
754753Speter }
764753Speter 
774753Speter flatprofline( np )
784753Speter     register nltype	*np;
794753Speter {
804753Speter 
814854Speter     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
824753Speter 	return;
834753Speter     }
844753Speter     actime += np -> time;
854753Speter     printf( "%5.1f %7.2f %7.2f" ,
86*10248Speter 	100 * np -> time / totime , actime / hz , np -> time / hz );
874753Speter     if ( np -> ncall != 0 ) {
884753Speter 	printf( " %7d" , np -> ncall );
894753Speter     } else {
904753Speter 	printf( " %7.7s" , "" );
914753Speter     }
924753Speter     printf( " %s\n" , np -> name );
934753Speter }
944753Speter 
954753Speter gprofheader()
964753Speter {
974854Speter 
984854Speter     if ( bflag ) {
994854Speter 	printblurb( "callg.blurb" );
1004854Speter     }
1017172Speter     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
1027172Speter 	    (long) scale * sizeof(UNIT) );
1037225Speter     if ( printtime > 0.0 ) {
1047225Speter 	printf( " for %.2f%% of %.2f seconds\n\n" ,
105*10248Speter 		100.0/printtime , printtime / hz );
1067225Speter     } else {
1077225Speter 	printf( " no time propagated\n\n" );
1087225Speter 	    /*
1097225Speter 	     *	this doesn't hurt, since all the numerators will be 0.0
1107225Speter 	     */
1117225Speter 	printtime = 1.0;
1127225Speter     }
1134753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
1144753Speter 	"" , "" , "" , "" , "called" , "total" , "parents" , "" );
1154753Speter     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
1164753Speter 	"index" , "%time" , "self" , "descendents" ,
1174753Speter 	"called" , "self" , "name" , "index" );
1184753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
1194753Speter 	"" , "" , "" , "" , "called" , "total" , "children" , "" );
1204753Speter     printf( "\n" );
1214753Speter }
1224753Speter 
1234753Speter gprofline( np )
1244753Speter     register nltype	*np;
1254753Speter {
1264753Speter     char	kirkbuffer[ BUFSIZ ];
1274753Speter 
1284753Speter     sprintf( kirkbuffer , "[%d]" , np -> index );
1294753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f" ,
1304753Speter 	    kirkbuffer ,
1317222Speter 	    100 * ( np -> propself + np -> propchild ) / printtime ,
132*10248Speter 	    np -> propself / hz ,
133*10248Speter 	    np -> propchild / hz );
1344753Speter     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
1354753Speter 	printf( " %7d" , np -> ncall );
1364753Speter 	if ( np -> selfcalls != 0 ) {
1374753Speter 	    printf( "+%-7d " , np -> selfcalls );
1384753Speter 	} else {
1394753Speter 	    printf( " %7.7s " , "" );
1404753Speter 	}
1414753Speter     } else {
1424753Speter 	printf( " %7.7s %7.7s " , "" , "" );
1434753Speter     }
1444753Speter     printname( np );
1454753Speter     printf( "\n" );
1464753Speter }
1474753Speter 
1484562Speter printgprof()
1494515Speter {
1504515Speter     nltype	**timesortnlp;
1514515Speter     int		index;
1524515Speter     nltype	*parentp;
1534515Speter 
1544515Speter 	/*
1557222Speter 	 *	Now, sort by propself + propchild.
1567129Speter 	 *	sorting both the regular function names
1577129Speter 	 *	and cycle headers.
1584515Speter 	 */
1597129Speter     timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
1604515Speter     if ( timesortnlp == (nltype **) 0 ) {
1617129Speter 	fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
1624515Speter     }
1634753Speter     for ( index = 0 ; index < nname ; index++ ) {
1644515Speter 	timesortnlp[index] = &nl[index];
1654515Speter     }
1667129Speter     for ( index = 1 ; index <= ncycle ; index++ ) {
1677129Speter 	timesortnlp[nname+index-1] = &cyclenl[index];
1684753Speter     }
1697129Speter     qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
1707129Speter     for ( index = 0 ; index < nname + ncycle ; index++ ) {
1714515Speter 	timesortnlp[ index ] -> index = index + 1;
1724515Speter     }
1734515Speter 	/*
1744515Speter 	 *	Now, print out the structured profiling list
1754515Speter 	 */
1764753Speter     printf( "\f\n" );
1774753Speter     gprofheader();
1787129Speter     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
1794515Speter 	parentp = timesortnlp[ index ];
1804854Speter 	if ( zflag == 0 &&
1814515Speter 	     parentp -> ncall == 0 &&
1824515Speter 	     parentp -> selfcalls == 0 &&
1837222Speter 	     parentp -> propself == 0 &&
1847222Speter 	     parentp -> propchild == 0 ) {
1854515Speter 	    continue;
1864515Speter 	}
1877172Speter 	if ( ! parentp -> printflag ) {
1887172Speter 	    continue;
1897172Speter 	}
1904515Speter 	if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
1914515Speter 		/*
1924515Speter 		 *	cycle header
1934515Speter 		 */
1944753Speter 	    printcycle( parentp );
1954753Speter 	    printmembers( parentp );
1964515Speter 	} else {
1974515Speter 	    printparents( parentp );
1984753Speter 	    gprofline( parentp );
1994515Speter 	    printchildren( parentp );
2004515Speter 	}
2014515Speter 	printf( "\n" );
2024753Speter 	printf( "-----------------------------------------------\n" );
2034753Speter 	printf( "\n" );
2044515Speter     }
2054515Speter }
2064515Speter 
2074856Speter     /*
2087222Speter      *	sort by decreasing propagated time
2094856Speter      *	if times are equal, but one is a cycle header,
2104856Speter      *		say that's first (e.g. less, i.e. -1).
2114856Speter      *	if one's name doesn't have an underscore and the other does,
2124856Speter      *		say the one is first.
2134856Speter      *	all else being equal, sort by names.
2144856Speter      */
2154856Speter int
2164856Speter totalcmp( npp1 , npp2 )
2174856Speter     nltype	**npp1;
2184856Speter     nltype	**npp2;
2194856Speter {
2204856Speter     register nltype	*np1 = *npp1;
2214856Speter     register nltype	*np2 = *npp2;
2224856Speter     double		diff;
2234856Speter 
2247222Speter     diff =    ( np1 -> propself + np1 -> propchild )
2257222Speter 	    - ( np2 -> propself + np2 -> propchild );
2264856Speter     if ( diff < 0.0 )
2274856Speter 	    return 1;
2284856Speter     if ( diff > 0.0 )
2294856Speter 	    return -1;
2304856Speter     if ( np1 -> name == 0 && np1 -> cycleno != 0 )
2314856Speter 	return -1;
2324856Speter     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
2334856Speter 	return 1;
2344856Speter     if ( np1 -> name == 0 )
2354856Speter 	return -1;
2364856Speter     if ( np2 -> name == 0 )
2374856Speter 	return 1;
2384856Speter     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
2394856Speter 	return -1;
2404856Speter     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
2414856Speter 	return 1;
2427222Speter     if ( np1 -> ncall > np2 -> ncall )
2437222Speter 	return -1;
2447222Speter     if ( np1 -> ncall < np2 -> ncall )
2457222Speter 	return 1;
2464856Speter     return strcmp( np1 -> name , np2 -> name );
2474856Speter }
2484856Speter 
2494515Speter printparents( childp )
2504515Speter     nltype	*childp;
2514515Speter {
2524515Speter     nltype	*parentp;
2534515Speter     arctype	*arcp;
2544515Speter     nltype	*cycleheadp;
2554515Speter 
2564515Speter     if ( childp -> cyclehead != 0 ) {
2574515Speter 	cycleheadp = childp -> cyclehead;
2584515Speter     } else {
2594515Speter 	cycleheadp = childp;
2604515Speter     }
2614515Speter     if ( childp -> parents == 0 ) {
2624753Speter 	printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n" ,
2634515Speter 		"" , "" , "" , "" , "" , "" );
2644515Speter 	return;
2654515Speter     }
2664515Speter     sortparents( childp );
2674515Speter     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
2684515Speter 	parentp = arcp -> arc_parentp;
2694515Speter 	if ( childp == parentp ||
2704515Speter 	     ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
2714515Speter 		/*
2724753Speter 		 *	selfcall or call among siblings
2734515Speter 		 */
2744753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
2754515Speter 		    "" , "" , "" , "" ,
2764515Speter 		    arcp -> arc_count , "" );
2774515Speter 	    printname( parentp );
2784515Speter 	    printf( "\n" );
2794515Speter 	} else {
2804515Speter 		/*
2814515Speter 		 *	regular parent of child
2824515Speter 		 */
2834753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
2844753Speter 		    "" , "" ,
285*10248Speter 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
2864515Speter 		    arcp -> arc_count , cycleheadp -> ncall );
2874515Speter 	    printname( parentp );
2884515Speter 	    printf( "\n" );
2894515Speter 	}
2904515Speter     }
2914515Speter }
2924515Speter 
2934515Speter printchildren( parentp )
2944515Speter     nltype	*parentp;
2954515Speter {
2964515Speter     nltype	*childp;
2974515Speter     arctype	*arcp;
2984515Speter 
2994515Speter     sortchildren( parentp );
3004515Speter     arcp = parentp -> children;
3014515Speter     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
3024515Speter 	childp = arcp -> arc_childp;
3034515Speter 	if ( childp == parentp ||
3044515Speter 	    ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
3054515Speter 		/*
3064515Speter 		 *	self call or call to sibling
3074515Speter 		 */
3084753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
3094753Speter 		    "" , "" , "" , "" , arcp -> arc_count , "" );
3104515Speter 	    printname( childp );
3114515Speter 	    printf( "\n" );
3124515Speter 	} else {
3134515Speter 		/*
3144515Speter 		 *	regular child of parent
3154515Speter 		 */
3164753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
3174753Speter 		    "" , "" ,
318*10248Speter 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
3194515Speter 		    arcp -> arc_count , childp -> cyclehead -> ncall );
3204515Speter 	    printname( childp );
3214515Speter 	    printf( "\n" );
3224515Speter 	}
3234515Speter     }
3244515Speter }
3254515Speter 
3264515Speter printname( selfp )
3274515Speter     nltype	*selfp;
3284515Speter {
3294515Speter 
3304515Speter     if ( selfp -> name != 0 ) {
3314753Speter 	printf( "%s" , selfp -> name );
3324515Speter #	ifdef DEBUG
3334515Speter 	    if ( debug & DFNDEBUG ) {
3344515Speter 		printf( "{%d} " , selfp -> toporder );
3354515Speter 	    }
3367222Speter 	    if ( debug & PROPDEBUG ) {
3377222Speter 		printf( "%5.2f%% " , selfp -> propfraction );
3387222Speter 	    }
3394515Speter #	endif DEBUG
3404515Speter     }
3414842Speter     if ( selfp -> cycleno != 0 ) {
3424842Speter 	printf( "\t<cycle %d>" , selfp -> cycleno );
3434842Speter     }
3444753Speter     if ( selfp -> index != 0 ) {
3457172Speter 	if ( selfp -> printflag ) {
3467172Speter 	    printf( " [%d]" , selfp -> index );
3477172Speter 	} else {
3487172Speter 	    printf( " (%d)" , selfp -> index );
3497172Speter 	}
3504753Speter     }
3514515Speter }
3524515Speter 
3534515Speter sortchildren( parentp )
3544515Speter     nltype	*parentp;
3554515Speter {
3564515Speter     arctype	*arcp;
3574515Speter     arctype	*detachedp;
3584515Speter     arctype	sorted;
3594515Speter     arctype	*prevp;
3604515Speter 
3614515Speter 	/*
3624515Speter 	 *	unlink children from parent,
3634515Speter 	 *	then insertion sort back on to sorted's children.
3644515Speter 	 *	    *arcp	the arc you have detached and are inserting.
3654515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
3664515Speter 	 *	    sorted	arc list onto which you insertion sort.
3674515Speter 	 *	    *prevp	arc before the arc you are comparing.
3684515Speter 	 */
3694515Speter     sorted.arc_childlist = 0;
3704515Speter     for (   arcp = parentp -> children , detachedp = arcp -> arc_childlist ;
3714515Speter 	    arcp ;
3724515Speter 	    arcp = detachedp , detachedp = detachedp -> arc_childlist ) {
3734515Speter 	    /*
3744515Speter 	     *	consider *arcp as disconnected
3754515Speter 	     *	insert it into sorted
3764515Speter 	     */
3774515Speter 	for (   prevp = &sorted ;
3784515Speter 		prevp -> arc_childlist ;
3794515Speter 		prevp = prevp -> arc_childlist ) {
3804515Speter 	    if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
3814515Speter 		break;
3824515Speter 	    }
3834515Speter 	}
3844515Speter 	arcp -> arc_childlist = prevp -> arc_childlist;
3854515Speter 	prevp -> arc_childlist = arcp;
3864515Speter     }
3874515Speter 	/*
3884515Speter 	 *	reattach sorted children to parent
3894515Speter 	 */
3904515Speter     parentp -> children = sorted.arc_childlist;
3914515Speter }
3924515Speter 
3934515Speter sortparents( childp )
3944515Speter     nltype	*childp;
3954515Speter {
3964515Speter     arctype	*arcp;
3974515Speter     arctype	*detachedp;
3984515Speter     arctype	sorted;
3994515Speter     arctype	*prevp;
4004515Speter 
4014515Speter 	/*
4024515Speter 	 *	unlink parents from child,
4034515Speter 	 *	then insertion sort back on to sorted's parents.
4044515Speter 	 *	    *arcp	the arc you have detached and are inserting.
4054515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
4064515Speter 	 *	    sorted	arc list onto which you insertion sort.
4074515Speter 	 *	    *prevp	arc before the arc you are comparing.
4084515Speter 	 */
4094515Speter     sorted.arc_parentlist = 0;
4104515Speter     for (   arcp = childp -> parents , detachedp = arcp -> arc_parentlist ;
4114515Speter 	    arcp ;
4124515Speter 	    arcp = detachedp , detachedp = detachedp -> arc_parentlist ) {
4134515Speter 	    /*
4144515Speter 	     *	consider *arcp as disconnected
4154515Speter 	     *	insert it into sorted
4164515Speter 	     */
4174515Speter 	for (   prevp = &sorted ;
4184515Speter 		prevp -> arc_parentlist ;
4194515Speter 		prevp = prevp -> arc_parentlist ) {
4204515Speter 	    if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
4214515Speter 		break;
4224515Speter 	    }
4234515Speter 	}
4244515Speter 	arcp -> arc_parentlist = prevp -> arc_parentlist;
4254515Speter 	prevp -> arc_parentlist = arcp;
4264515Speter     }
4274515Speter 	/*
4284515Speter 	 *	reattach sorted arcs to child
4294515Speter 	 */
4304515Speter     childp -> parents = sorted.arc_parentlist;
4314515Speter }
4324515Speter 
4334515Speter     /*
4344753Speter      *	print a cycle header
4354753Speter      */
4364753Speter printcycle( cyclep )
4374753Speter     nltype	*cyclep;
4384753Speter {
4394753Speter     char	kirkbuffer[ BUFSIZ ];
4404753Speter 
4414753Speter     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
4424753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
4434753Speter 	    kirkbuffer ,
4447222Speter 	    100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
445*10248Speter 	    cyclep -> propself / hz ,
446*10248Speter 	    cyclep -> propchild / hz ,
4474753Speter 	    cyclep -> ncall );
4484753Speter     if ( cyclep -> selfcalls != 0 ) {
4494753Speter 	printf( "+%-7d" , cyclep -> selfcalls );
4504753Speter     } else {
4514753Speter 	printf( " %7.7s" , "" );
4524753Speter     }
4534753Speter     printf( " <cycle %d as a whole>\t[%d]\n" ,
4544753Speter 	    cyclep -> cycleno , cyclep -> index );
4554753Speter }
4564753Speter 
4574753Speter     /*
4584753Speter      *	print the members of a cycle
4594753Speter      */
4604753Speter printmembers( cyclep )
4614753Speter     nltype	*cyclep;
4624753Speter {
4634753Speter     nltype	*memberp;
4644753Speter 
4654753Speter     sortmembers( cyclep );
4664753Speter     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
4674753Speter 	printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
468*10248Speter 		"" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
4694753Speter 		memberp -> ncall );
4704753Speter 	if ( memberp -> selfcalls != 0 ) {
4714753Speter 	    printf( "+%-7d" , memberp -> selfcalls );
4724753Speter 	} else {
4734753Speter 	    printf( " %7.7s" , "" );
4744753Speter 	}
4754753Speter 	printf( "     " );
4764753Speter 	printname( memberp );
4774753Speter 	printf( "\n" );
4784753Speter     }
4794753Speter }
4804753Speter 
4814753Speter     /*
4824753Speter      *	sort members of a cycle
4834753Speter      */
4844753Speter sortmembers( cyclep )
4854753Speter     nltype	*cyclep;
4864753Speter {
4874753Speter     nltype	*todo;
4884753Speter     nltype	*doing;
4894753Speter     nltype	*prev;
4904753Speter 
4914753Speter 	/*
4924753Speter 	 *	detach cycle members from cyclehead,
4934753Speter 	 *	and insertion sort them back on.
4944753Speter 	 */
4954753Speter     todo = cyclep -> cnext;
4964753Speter     cyclep -> cnext = 0;
4974753Speter     for (   doing = todo , todo = doing -> cnext ;
4984753Speter 	    doing ;
4994753Speter 	    doing = todo , todo = doing -> cnext ) {
5004753Speter 	for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
5014753Speter 	    if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
5024753Speter 		break;
5034753Speter 	    }
5044753Speter 	}
5054753Speter 	doing -> cnext = prev -> cnext;
5064753Speter 	prev -> cnext = doing;
5074753Speter     }
5084753Speter }
5094753Speter 
5104753Speter     /*
5117222Speter      *	major sort is on propself + propchild,
5124753Speter      *	next is sort on ncalls + selfcalls.
5134753Speter      */
5144842Speter int
5154753Speter membercmp( this , that )
5164753Speter     nltype	*this;
5174753Speter     nltype	*that;
5184753Speter {
5197222Speter     double	thistime = this -> propself + this -> propchild;
5207222Speter     double	thattime = that -> propself + that -> propchild;
5214753Speter     long	thiscalls = this -> ncall + this -> selfcalls;
5224753Speter     long	thatcalls = that -> ncall + that -> selfcalls;
5234753Speter 
5244753Speter     if ( thistime > thattime ) {
5254753Speter 	return GREATERTHAN;
5264753Speter     }
5274753Speter     if ( thistime < thattime ) {
5284753Speter 	return LESSTHAN;
5294753Speter     }
5304753Speter     if ( thiscalls > thatcalls ) {
5314753Speter 	return GREATERTHAN;
5324753Speter     }
5334753Speter     if ( thiscalls < thatcalls ) {
5344753Speter 	return LESSTHAN;
5354753Speter     }
5364753Speter     return EQUALTO;
5374753Speter }
5384753Speter     /*
5394515Speter      *	compare two arcs to/from the same child/parent.
5404515Speter      *	- if one arc is a self arc, it's least.
5414515Speter      *	- if one arc is within a cycle, it's less than.
5424515Speter      *	- if both arcs are within a cycle, compare arc counts.
5434515Speter      *	- if neither arc is within a cycle, compare with
5447222Speter      *		arc_time + arc_childtime as major key
5454515Speter      *		arc count as minor key
5464515Speter      */
5474515Speter int
5484515Speter arccmp( thisp , thatp )
5494515Speter     arctype	*thisp;
5504515Speter     arctype	*thatp;
5514515Speter {
5524515Speter     nltype	*thisparentp = thisp -> arc_parentp;
5534515Speter     nltype	*thischildp = thisp -> arc_childp;
5544515Speter     nltype	*thatparentp = thatp -> arc_parentp;
5554515Speter     nltype	*thatchildp = thatp -> arc_childp;
5564515Speter     double	thistime;
5574515Speter     double	thattime;
5584515Speter 
5594515Speter #   ifdef DEBUG
5604515Speter 	if ( debug & TIMEDEBUG ) {
5614515Speter 	    printf( "[arccmp] " );
5624515Speter 	    printname( thisparentp );
5634515Speter 	    printf( " calls " );
5644515Speter 	    printname ( thischildp );
5654515Speter 	    printf( " %f + %f %d/%d\n" ,
5664515Speter 		    thisp -> arc_time , thisp -> arc_childtime ,
5674515Speter 		    thisp -> arc_count , thischildp -> ncall );
5684515Speter 	    printf( "[arccmp] " );
5694515Speter 	    printname( thatparentp );
5704515Speter 	    printf( " calls " );
5714515Speter 	    printname( thatchildp );
5724515Speter 	    printf( " %f + %f %d/%d\n" ,
5734515Speter 		    thatp -> arc_time , thatp -> arc_childtime ,
5744515Speter 		    thatp -> arc_count , thatchildp -> ncall );
5754515Speter 	    printf( "\n" );
5764515Speter 	}
5774515Speter #   endif DEBUG
5784515Speter     if ( thisparentp == thischildp ) {
5794515Speter 	    /* this is a self call */
5804515Speter 	return LESSTHAN;
5814515Speter     }
5824515Speter     if ( thatparentp == thatchildp ) {
5834515Speter 	    /* that is a self call */
5844515Speter 	return GREATERTHAN;
5854515Speter     }
5864515Speter     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
5874515Speter 	thisparentp -> cycleno == thischildp -> cycleno ) {
5884515Speter 	    /* this is a call within a cycle */
5894515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
5904515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
5914515Speter 		/* that is a call within the cycle, too */
5924515Speter 	    if ( thisp -> arc_count < thatp -> arc_count ) {
5934515Speter 		return LESSTHAN;
5944515Speter 	    }
5954515Speter 	    if ( thisp -> arc_count > thatp -> arc_count ) {
5964515Speter 		return GREATERTHAN;
5974515Speter 	    }
5984515Speter 	    return EQUALTO;
5994515Speter 	} else {
6004515Speter 		/* that isn't a call within the cycle */
6014515Speter 	    return LESSTHAN;
6024515Speter 	}
6034515Speter     } else {
6044515Speter 	    /* this isn't a call within a cycle */
6054515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
6064515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
6074515Speter 		/* that is a call within a cycle */
6084515Speter 	    return GREATERTHAN;
6094515Speter 	} else {
6104515Speter 		/* neither is a call within a cycle */
6114515Speter 	    thistime = thisp -> arc_time + thisp -> arc_childtime;
6124515Speter 	    thattime = thatp -> arc_time + thatp -> arc_childtime;
6134515Speter 	    if ( thistime < thattime )
6144515Speter 		return LESSTHAN;
6154515Speter 	    if ( thistime > thattime )
6164515Speter 		return GREATERTHAN;
6174515Speter 	    if ( thisp -> arc_count < thatp -> arc_count )
6184515Speter 		return LESSTHAN;
6194515Speter 	    if ( thisp -> arc_count > thatp -> arc_count )
6204515Speter 		return GREATERTHAN;
6214515Speter 	    return EQUALTO;
6224515Speter 	}
6234515Speter     }
6244515Speter }
6254854Speter 
6264854Speter printblurb( blurbname )
6274854Speter     char	*blurbname;
6284854Speter {
6294854Speter     char	pathname[ BUFSIZ ];
6304854Speter     FILE	*blurbfile;
6314854Speter     int		input;
6324854Speter 
6334854Speter     sprintf( pathname , "%s%s" , BLURBLIB , blurbname );
6344854Speter     blurbfile = fopen( pathname , "r" );
6354854Speter     if ( blurbfile == NULL ) {
6364854Speter 	perror( pathname );
6374854Speter 	return;
6384854Speter     }
6394854Speter     while ( ( input = getc( blurbfile ) ) != EOF ) {
6404854Speter 	putchar( input );
6414854Speter     }
6424854Speter     fclose( blurbfile );
6434854Speter }
644