xref: /csrg-svn/usr.bin/gprof/printgprof.c (revision 7129)
14515Speter #ifndef lint
2*7129Speter     static	char *sccsid = "@(#)printgprof.c	1.8 (Berkeley) 06/08/82";
34515Speter #endif lint
44515Speter 
54562Speter #include "gprof.h"
64515Speter 
74753Speter printprof()
84753Speter {
94753Speter     register nltype	*np;
104753Speter     nltype		**sortednlp;
114753Speter     int			index;
124753Speter 
134854Speter     printf( "\ngranularity: each sample hit covers %d byte(s)" , (long) scale );
144854Speter     printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/totime , totime / HZ );
154753Speter     actime = 0.0;
164753Speter     flatprofheader();
174753Speter 	/*
184753Speter 	 *	Sort the symbol table in by time
194753Speter 	 */
204753Speter     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
214753Speter     if ( sortednlp == (nltype **) 0 ) {
224753Speter 	fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
234753Speter     }
244753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
254753Speter 	sortednlp[ index ] = &nl[ index ];
264753Speter     }
274753Speter     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
284753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
294753Speter 	np = sortednlp[ index ];
304753Speter 	flatprofline( np );
314753Speter     }
324753Speter     actime = 0.0;
334753Speter }
344753Speter 
354753Speter timecmp( npp1 , npp2 )
364753Speter     nltype **npp1, **npp2;
374753Speter {
384856Speter     double	timediff;
394856Speter     long	calldiff;
404753Speter 
414856Speter     timediff = (*npp2) -> time - (*npp1) -> time;
424856Speter     if ( timediff > 0.0 )
434753Speter 	return 1 ;
444856Speter     if ( timediff < 0.0 )
454753Speter 	return -1;
464856Speter     calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
474856Speter     if ( calldiff > 0 )
484856Speter 	return 1;
494856Speter     if ( calldiff < 0 )
504856Speter 	return -1;
514753Speter     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
524753Speter }
534753Speter 
544753Speter     /*
554753Speter      *	header for flatprofline
564753Speter      */
574753Speter flatprofheader()
584753Speter {
594753Speter 
604854Speter     if ( bflag ) {
614854Speter 	printblurb( "flat.blurb" );
624854Speter     }
634753Speter     printf( "%5.5s %7.7s %7.7s %7.7s %-8.8s\n" ,
644753Speter 	    "%time" , "cumsecs" , "seconds" , "calls" , "name" );
654753Speter }
664753Speter 
674753Speter flatprofline( np )
684753Speter     register nltype	*np;
694753Speter {
704753Speter 
714854Speter     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
724753Speter 	return;
734753Speter     }
744753Speter     actime += np -> time;
754753Speter     printf( "%5.1f %7.2f %7.2f" ,
764753Speter 	100 * np -> time / totime , actime / HZ , np -> time / HZ );
774753Speter     if ( np -> ncall != 0 ) {
784753Speter 	printf( " %7d" , np -> ncall );
794753Speter     } else {
804753Speter 	printf( " %7.7s" , "" );
814753Speter     }
824753Speter     printf( " %s\n" , np -> name );
834753Speter }
844753Speter 
854753Speter gprofheader()
864753Speter {
874854Speter 
884854Speter     if ( bflag ) {
894854Speter 	printblurb( "callg.blurb" );
904854Speter     }
914753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
924753Speter 	"" , "" , "" , "" , "called" , "total" , "parents" , "" );
934753Speter     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
944753Speter 	"index" , "%time" , "self" , "descendents" ,
954753Speter 	"called" , "self" , "name" , "index" );
964753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
974753Speter 	"" , "" , "" , "" , "called" , "total" , "children" , "" );
984753Speter     printf( "\n" );
994753Speter }
1004753Speter 
1014753Speter gprofline( np )
1024753Speter     register nltype	*np;
1034753Speter {
1044753Speter     char	kirkbuffer[ BUFSIZ ];
1054753Speter 
1064753Speter     sprintf( kirkbuffer , "[%d]" , np -> index );
1074753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f" ,
1084753Speter 	    kirkbuffer ,
1094753Speter 	    100 * ( np -> time + np -> childtime ) / totime ,
1104753Speter 	    np -> time / HZ ,
1114753Speter 	    np -> childtime / HZ );
1124753Speter     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
1134753Speter 	printf( " %7d" , np -> ncall );
1144753Speter 	if ( np -> selfcalls != 0 ) {
1154753Speter 	    printf( "+%-7d " , np -> selfcalls );
1164753Speter 	} else {
1174753Speter 	    printf( " %7.7s " , "" );
1184753Speter 	}
1194753Speter     } else {
1204753Speter 	printf( " %7.7s %7.7s " , "" , "" );
1214753Speter     }
1224753Speter     printname( np );
1234753Speter     printf( "\n" );
1244753Speter }
1254753Speter 
1264562Speter printgprof()
1274515Speter {
1284515Speter     nltype	**timesortnlp;
1294515Speter     int		index;
1304515Speter     nltype	*parentp;
1314515Speter 
1324515Speter 	/*
1334515Speter 	 *	Now, sort by time + childtime.
134*7129Speter 	 *	sorting both the regular function names
135*7129Speter 	 *	and cycle headers.
1364515Speter 	 */
137*7129Speter     timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
1384515Speter     if ( timesortnlp == (nltype **) 0 ) {
139*7129Speter 	fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
1404515Speter     }
1414753Speter     for ( index = 0 ; index < nname ; index++ ) {
1424515Speter 	timesortnlp[index] = &nl[index];
1434515Speter     }
144*7129Speter     for ( index = 1 ; index <= ncycle ; index++ ) {
145*7129Speter 	timesortnlp[nname+index-1] = &cyclenl[index];
1464753Speter     }
147*7129Speter     qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp );
148*7129Speter     for ( index = 0 ; index < nname + ncycle ; index++ ) {
1494515Speter 	timesortnlp[ index ] -> index = index + 1;
1504515Speter     }
1514515Speter 	/*
1524515Speter 	 *	Now, print out the structured profiling list
1534515Speter 	 */
1544753Speter     printf( "\f\n" );
1554753Speter     gprofheader();
156*7129Speter     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
1574515Speter 	parentp = timesortnlp[ index ];
1584854Speter 	if ( zflag == 0 &&
1594515Speter 	     parentp -> ncall == 0 &&
1604515Speter 	     parentp -> selfcalls == 0 &&
1614515Speter 	     parentp -> time == 0 &&
1624515Speter 	     parentp -> childtime == 0 ) {
1634515Speter 	    continue;
1644515Speter 	}
1654515Speter 	if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
1664515Speter 		/*
1674515Speter 		 *	cycle header
1684515Speter 		 */
1694753Speter 	    printcycle( parentp );
1704753Speter 	    printmembers( parentp );
1714515Speter 	} else {
1724515Speter 	    printparents( parentp );
1734753Speter 	    gprofline( parentp );
1744515Speter 	    printchildren( parentp );
1754515Speter 	}
1764515Speter 	printf( "\n" );
1774753Speter 	printf( "-----------------------------------------------\n" );
1784753Speter 	printf( "\n" );
1794515Speter     }
1804515Speter }
1814515Speter 
1824856Speter     /*
1834856Speter      *	sort by decreasing total time (time+childtime)
1844856Speter      *	if times are equal, but one is a cycle header,
1854856Speter      *		say that's first (e.g. less, i.e. -1).
1864856Speter      *	if one's name doesn't have an underscore and the other does,
1874856Speter      *		say the one is first.
1884856Speter      *	all else being equal, sort by names.
1894856Speter      */
1904856Speter int
1914856Speter totalcmp( npp1 , npp2 )
1924856Speter     nltype	**npp1;
1934856Speter     nltype	**npp2;
1944856Speter {
1954856Speter     register nltype	*np1 = *npp1;
1964856Speter     register nltype	*np2 = *npp2;
1974856Speter     double		diff;
1984856Speter 
1994856Speter     diff =    ( np1 -> time + np1 -> childtime )
2004856Speter 	    - ( np2 -> time + np2 -> childtime );
2014856Speter     if ( diff < 0.0 )
2024856Speter 	    return 1;
2034856Speter     if ( diff > 0.0 )
2044856Speter 	    return -1;
2054856Speter     if ( np1 -> name == 0 && np1 -> cycleno != 0 )
2064856Speter 	return -1;
2074856Speter     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
2084856Speter 	return 1;
2094856Speter     if ( np1 -> name == 0 )
2104856Speter 	return -1;
2114856Speter     if ( np2 -> name == 0 )
2124856Speter 	return 1;
2134856Speter     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
2144856Speter 	return -1;
2154856Speter     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
2164856Speter 	return 1;
2174856Speter     return strcmp( np1 -> name , np2 -> name );
2184856Speter }
2194856Speter 
2204515Speter printparents( childp )
2214515Speter     nltype	*childp;
2224515Speter {
2234515Speter     nltype	*parentp;
2244515Speter     arctype	*arcp;
2254515Speter     nltype	*cycleheadp;
2264515Speter 
2274515Speter     if ( childp -> cyclehead != 0 ) {
2284515Speter 	cycleheadp = childp -> cyclehead;
2294515Speter     } else {
2304515Speter 	cycleheadp = childp;
2314515Speter     }
2324515Speter     if ( childp -> parents == 0 ) {
2334753Speter 	printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n" ,
2344515Speter 		"" , "" , "" , "" , "" , "" );
2354515Speter 	return;
2364515Speter     }
2374515Speter     sortparents( childp );
2384515Speter     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
2394515Speter 	parentp = arcp -> arc_parentp;
2404515Speter 	if ( childp == parentp ||
2414515Speter 	     ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
2424515Speter 		/*
2434753Speter 		 *	selfcall or call among siblings
2444515Speter 		 */
2454753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
2464515Speter 		    "" , "" , "" , "" ,
2474515Speter 		    arcp -> arc_count , "" );
2484515Speter 	    printname( parentp );
2494515Speter 	    printf( "\n" );
2504515Speter 	} else {
2514515Speter 		/*
2524515Speter 		 *	regular parent of child
2534515Speter 		 */
2544753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
2554753Speter 		    "" , "" ,
2564515Speter 		    arcp -> arc_time / HZ , arcp -> arc_childtime / HZ ,
2574515Speter 		    arcp -> arc_count , cycleheadp -> ncall );
2584515Speter 	    printname( parentp );
2594515Speter 	    printf( "\n" );
2604515Speter 	}
2614515Speter     }
2624515Speter }
2634515Speter 
2644515Speter printchildren( parentp )
2654515Speter     nltype	*parentp;
2664515Speter {
2674515Speter     nltype	*childp;
2684515Speter     arctype	*arcp;
2694515Speter 
2704515Speter     sortchildren( parentp );
2714515Speter     arcp = parentp -> children;
2724515Speter     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
2734515Speter 	childp = arcp -> arc_childp;
2744515Speter 	if ( childp == parentp ||
2754515Speter 	    ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
2764515Speter 		/*
2774515Speter 		 *	self call or call to sibling
2784515Speter 		 */
2794753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
2804753Speter 		    "" , "" , "" , "" , arcp -> arc_count , "" );
2814515Speter 	    printname( childp );
2824515Speter 	    printf( "\n" );
2834515Speter 	} else {
2844515Speter 		/*
2854515Speter 		 *	regular child of parent
2864515Speter 		 */
2874753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
2884753Speter 		    "" , "" ,
2894515Speter 		    arcp -> arc_time / HZ , arcp -> arc_childtime / HZ ,
2904515Speter 		    arcp -> arc_count , childp -> cyclehead -> ncall );
2914515Speter 	    printname( childp );
2924515Speter 	    printf( "\n" );
2934515Speter 	}
2944515Speter     }
2954515Speter }
2964515Speter 
2974515Speter printname( selfp )
2984515Speter     nltype	*selfp;
2994515Speter {
3004515Speter 
3014515Speter     if ( selfp -> name != 0 ) {
3024753Speter 	printf( "%s" , selfp -> name );
3034515Speter #	ifdef DEBUG
3044515Speter 	    if ( debug & DFNDEBUG ) {
3054515Speter 		printf( "{%d} " , selfp -> toporder );
3064515Speter 	    }
3074515Speter #	endif DEBUG
3084515Speter     }
3094842Speter     if ( selfp -> cycleno != 0 ) {
3104842Speter 	printf( "\t<cycle %d>" , selfp -> cycleno );
3114842Speter     }
3124753Speter     if ( selfp -> index != 0 ) {
3134842Speter 	printf( " [%d]" , selfp -> index );
3144753Speter     }
3154515Speter }
3164515Speter 
3174515Speter sortchildren( parentp )
3184515Speter     nltype	*parentp;
3194515Speter {
3204515Speter     arctype	*arcp;
3214515Speter     arctype	*detachedp;
3224515Speter     arctype	sorted;
3234515Speter     arctype	*prevp;
3244515Speter 
3254515Speter 	/*
3264515Speter 	 *	unlink children from parent,
3274515Speter 	 *	then insertion sort back on to sorted's children.
3284515Speter 	 *	    *arcp	the arc you have detached and are inserting.
3294515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
3304515Speter 	 *	    sorted	arc list onto which you insertion sort.
3314515Speter 	 *	    *prevp	arc before the arc you are comparing.
3324515Speter 	 */
3334515Speter     sorted.arc_childlist = 0;
3344515Speter     for (   arcp = parentp -> children , detachedp = arcp -> arc_childlist ;
3354515Speter 	    arcp ;
3364515Speter 	    arcp = detachedp , detachedp = detachedp -> arc_childlist ) {
3374515Speter 	    /*
3384515Speter 	     *	consider *arcp as disconnected
3394515Speter 	     *	insert it into sorted
3404515Speter 	     */
3414515Speter 	for (   prevp = &sorted ;
3424515Speter 		prevp -> arc_childlist ;
3434515Speter 		prevp = prevp -> arc_childlist ) {
3444515Speter 	    if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
3454515Speter 		break;
3464515Speter 	    }
3474515Speter 	}
3484515Speter 	arcp -> arc_childlist = prevp -> arc_childlist;
3494515Speter 	prevp -> arc_childlist = arcp;
3504515Speter     }
3514515Speter 	/*
3524515Speter 	 *	reattach sorted children to parent
3534515Speter 	 */
3544515Speter     parentp -> children = sorted.arc_childlist;
3554515Speter }
3564515Speter 
3574515Speter sortparents( childp )
3584515Speter     nltype	*childp;
3594515Speter {
3604515Speter     arctype	*arcp;
3614515Speter     arctype	*detachedp;
3624515Speter     arctype	sorted;
3634515Speter     arctype	*prevp;
3644515Speter 
3654515Speter 	/*
3664515Speter 	 *	unlink parents from child,
3674515Speter 	 *	then insertion sort back on to sorted's parents.
3684515Speter 	 *	    *arcp	the arc you have detached and are inserting.
3694515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
3704515Speter 	 *	    sorted	arc list onto which you insertion sort.
3714515Speter 	 *	    *prevp	arc before the arc you are comparing.
3724515Speter 	 */
3734515Speter     sorted.arc_parentlist = 0;
3744515Speter     for (   arcp = childp -> parents , detachedp = arcp -> arc_parentlist ;
3754515Speter 	    arcp ;
3764515Speter 	    arcp = detachedp , detachedp = detachedp -> arc_parentlist ) {
3774515Speter 	    /*
3784515Speter 	     *	consider *arcp as disconnected
3794515Speter 	     *	insert it into sorted
3804515Speter 	     */
3814515Speter 	for (   prevp = &sorted ;
3824515Speter 		prevp -> arc_parentlist ;
3834515Speter 		prevp = prevp -> arc_parentlist ) {
3844515Speter 	    if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
3854515Speter 		break;
3864515Speter 	    }
3874515Speter 	}
3884515Speter 	arcp -> arc_parentlist = prevp -> arc_parentlist;
3894515Speter 	prevp -> arc_parentlist = arcp;
3904515Speter     }
3914515Speter 	/*
3924515Speter 	 *	reattach sorted arcs to child
3934515Speter 	 */
3944515Speter     childp -> parents = sorted.arc_parentlist;
3954515Speter }
3964515Speter 
3974515Speter     /*
3984753Speter      *	print a cycle header
3994753Speter      */
4004753Speter printcycle( cyclep )
4014753Speter     nltype	*cyclep;
4024753Speter {
4034753Speter     char	kirkbuffer[ BUFSIZ ];
4044753Speter 
4054753Speter     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
4064753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
4074753Speter 	    kirkbuffer ,
4084753Speter 	    100 * ( cyclep -> time + cyclep -> childtime ) / totime ,
4094753Speter 	    cyclep -> time / HZ ,
4104753Speter 	    cyclep -> childtime / HZ ,
4114753Speter 	    cyclep -> ncall );
4124753Speter     if ( cyclep -> selfcalls != 0 ) {
4134753Speter 	printf( "+%-7d" , cyclep -> selfcalls );
4144753Speter     } else {
4154753Speter 	printf( " %7.7s" , "" );
4164753Speter     }
4174753Speter     printf( " <cycle %d as a whole>\t[%d]\n" ,
4184753Speter 	    cyclep -> cycleno , cyclep -> index );
4194753Speter }
4204753Speter 
4214753Speter     /*
4224753Speter      *	print the members of a cycle
4234753Speter      */
4244753Speter printmembers( cyclep )
4254753Speter     nltype	*cyclep;
4264753Speter {
4274753Speter     nltype	*memberp;
4284753Speter 
4294753Speter     sortmembers( cyclep );
4304753Speter     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
4314753Speter 	printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
4324753Speter 		"" , "" , memberp -> time / HZ , memberp -> childtime / HZ ,
4334753Speter 		memberp -> ncall );
4344753Speter 	if ( memberp -> selfcalls != 0 ) {
4354753Speter 	    printf( "+%-7d" , memberp -> selfcalls );
4364753Speter 	} else {
4374753Speter 	    printf( " %7.7s" , "" );
4384753Speter 	}
4394753Speter 	printf( "     " );
4404753Speter 	printname( memberp );
4414753Speter 	printf( "\n" );
4424753Speter     }
4434753Speter }
4444753Speter 
4454753Speter     /*
4464753Speter      *	sort members of a cycle
4474753Speter      */
4484753Speter sortmembers( cyclep )
4494753Speter     nltype	*cyclep;
4504753Speter {
4514753Speter     nltype	*todo;
4524753Speter     nltype	*doing;
4534753Speter     nltype	*prev;
4544753Speter 
4554753Speter 	/*
4564753Speter 	 *	detach cycle members from cyclehead,
4574753Speter 	 *	and insertion sort them back on.
4584753Speter 	 */
4594753Speter     todo = cyclep -> cnext;
4604753Speter     cyclep -> cnext = 0;
4614753Speter     for (   doing = todo , todo = doing -> cnext ;
4624753Speter 	    doing ;
4634753Speter 	    doing = todo , todo = doing -> cnext ) {
4644753Speter 	for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
4654753Speter 	    if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
4664753Speter 		break;
4674753Speter 	    }
4684753Speter 	}
4694753Speter 	doing -> cnext = prev -> cnext;
4704753Speter 	prev -> cnext = doing;
4714753Speter     }
4724753Speter }
4734753Speter 
4744753Speter     /*
4754753Speter      *	major sort is on time + childtime,
4764753Speter      *	next is sort on ncalls + selfcalls.
4774753Speter      */
4784842Speter int
4794753Speter membercmp( this , that )
4804753Speter     nltype	*this;
4814753Speter     nltype	*that;
4824753Speter {
4834753Speter     double	thistime = this -> time + this -> childtime;
4844753Speter     double	thattime = that -> time + that -> childtime;
4854753Speter     long	thiscalls = this -> ncall + this -> selfcalls;
4864753Speter     long	thatcalls = that -> ncall + that -> selfcalls;
4874753Speter 
4884753Speter     if ( thistime > thattime ) {
4894753Speter 	return GREATERTHAN;
4904753Speter     }
4914753Speter     if ( thistime < thattime ) {
4924753Speter 	return LESSTHAN;
4934753Speter     }
4944753Speter     if ( thiscalls > thatcalls ) {
4954753Speter 	return GREATERTHAN;
4964753Speter     }
4974753Speter     if ( thiscalls < thatcalls ) {
4984753Speter 	return LESSTHAN;
4994753Speter     }
5004753Speter     return EQUALTO;
5014753Speter }
5024753Speter     /*
5034515Speter      *	compare two arcs to/from the same child/parent.
5044515Speter      *	- if one arc is a self arc, it's least.
5054515Speter      *	- if one arc is within a cycle, it's less than.
5064515Speter      *	- if both arcs are within a cycle, compare arc counts.
5074515Speter      *	- if neither arc is within a cycle, compare with
5084515Speter      *		time + childtime as major key
5094515Speter      *		arc count as minor key
5104515Speter      */
5114515Speter int
5124515Speter arccmp( thisp , thatp )
5134515Speter     arctype	*thisp;
5144515Speter     arctype	*thatp;
5154515Speter {
5164515Speter     nltype	*thisparentp = thisp -> arc_parentp;
5174515Speter     nltype	*thischildp = thisp -> arc_childp;
5184515Speter     nltype	*thatparentp = thatp -> arc_parentp;
5194515Speter     nltype	*thatchildp = thatp -> arc_childp;
5204515Speter     double	thistime;
5214515Speter     double	thattime;
5224515Speter 
5234515Speter #   ifdef DEBUG
5244515Speter 	if ( debug & TIMEDEBUG ) {
5254515Speter 	    printf( "[arccmp] " );
5264515Speter 	    printname( thisparentp );
5274515Speter 	    printf( " calls " );
5284515Speter 	    printname ( thischildp );
5294515Speter 	    printf( " %f + %f %d/%d\n" ,
5304515Speter 		    thisp -> arc_time , thisp -> arc_childtime ,
5314515Speter 		    thisp -> arc_count , thischildp -> ncall );
5324515Speter 	    printf( "[arccmp] " );
5334515Speter 	    printname( thatparentp );
5344515Speter 	    printf( " calls " );
5354515Speter 	    printname( thatchildp );
5364515Speter 	    printf( " %f + %f %d/%d\n" ,
5374515Speter 		    thatp -> arc_time , thatp -> arc_childtime ,
5384515Speter 		    thatp -> arc_count , thatchildp -> ncall );
5394515Speter 	    printf( "\n" );
5404515Speter 	}
5414515Speter #   endif DEBUG
5424515Speter     if ( thisparentp == thischildp ) {
5434515Speter 	    /* this is a self call */
5444515Speter 	return LESSTHAN;
5454515Speter     }
5464515Speter     if ( thatparentp == thatchildp ) {
5474515Speter 	    /* that is a self call */
5484515Speter 	return GREATERTHAN;
5494515Speter     }
5504515Speter     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
5514515Speter 	thisparentp -> cycleno == thischildp -> cycleno ) {
5524515Speter 	    /* this is a call within a cycle */
5534515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
5544515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
5554515Speter 		/* that is a call within the cycle, too */
5564515Speter 	    if ( thisp -> arc_count < thatp -> arc_count ) {
5574515Speter 		return LESSTHAN;
5584515Speter 	    }
5594515Speter 	    if ( thisp -> arc_count > thatp -> arc_count ) {
5604515Speter 		return GREATERTHAN;
5614515Speter 	    }
5624515Speter 	    return EQUALTO;
5634515Speter 	} else {
5644515Speter 		/* that isn't a call within the cycle */
5654515Speter 	    return LESSTHAN;
5664515Speter 	}
5674515Speter     } else {
5684515Speter 	    /* this isn't a call within a cycle */
5694515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
5704515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
5714515Speter 		/* that is a call within a cycle */
5724515Speter 	    return GREATERTHAN;
5734515Speter 	} else {
5744515Speter 		/* neither is a call within a cycle */
5754515Speter 	    thistime = thisp -> arc_time + thisp -> arc_childtime;
5764515Speter 	    thattime = thatp -> arc_time + thatp -> arc_childtime;
5774515Speter 	    if ( thistime < thattime )
5784515Speter 		return LESSTHAN;
5794515Speter 	    if ( thistime > thattime )
5804515Speter 		return GREATERTHAN;
5814515Speter 	    if ( thisp -> arc_count < thatp -> arc_count )
5824515Speter 		return LESSTHAN;
5834515Speter 	    if ( thisp -> arc_count > thatp -> arc_count )
5844515Speter 		return GREATERTHAN;
5854515Speter 	    return EQUALTO;
5864515Speter 	}
5874515Speter     }
5884515Speter }
5894854Speter 
5904854Speter printblurb( blurbname )
5914854Speter     char	*blurbname;
5924854Speter {
5934854Speter     char	pathname[ BUFSIZ ];
5944854Speter     FILE	*blurbfile;
5954854Speter     int		input;
5964854Speter 
5974854Speter     sprintf( pathname , "%s%s" , BLURBLIB , blurbname );
5984854Speter     blurbfile = fopen( pathname , "r" );
5994854Speter     if ( blurbfile == NULL ) {
6004854Speter 	perror( pathname );
6014854Speter 	return;
6024854Speter     }
6034854Speter     while ( ( input = getc( blurbfile ) ) != EOF ) {
6044854Speter 	putchar( input );
6054854Speter     }
6064854Speter     fclose( blurbfile );
6074854Speter }
608