xref: /csrg-svn/usr.bin/gprof/printgprof.c (revision 16853)
14515Speter #ifndef lint
2*16853Smckusick     static	char *sccsid = "@(#)printgprof.c	1.15 (Berkeley) 08/07/84";
34515Speter #endif lint
44515Speter 
54562Speter #include "gprof.h"
64515Speter 
74753Speter printprof()
84753Speter {
94753Speter     register nltype	*np;
104753Speter     nltype		**sortednlp;
114753Speter     int			index;
124753Speter 
134753Speter     actime = 0.0;
14*16853Smckusick     printf( "\f\n" );
154753Speter     flatprofheader();
164753Speter 	/*
174753Speter 	 *	Sort the symbol table in by time
184753Speter 	 */
194753Speter     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
204753Speter     if ( sortednlp == (nltype **) 0 ) {
214753Speter 	fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
224753Speter     }
234753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
244753Speter 	sortednlp[ index ] = &nl[ index ];
254753Speter     }
264753Speter     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
274753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
284753Speter 	np = sortednlp[ index ];
294753Speter 	flatprofline( np );
304753Speter     }
314753Speter     actime = 0.0;
32*16853Smckusick     cfree( sortednlp );
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 ) {
6110285Speter 	printblurb( FLAT_BLURB );
624854Speter     }
63*16853Smckusick     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
64*16853Smckusick 	    (long) scale * sizeof(UNIT) );
65*16853Smckusick     if ( totime > 0.0 ) {
66*16853Smckusick 	printf( " for %.2f%% of %.2f seconds\n\n" ,
67*16853Smckusick 		100.0/totime , totime / hz );
68*16853Smckusick     } else {
69*16853Smckusick 	printf( " no time accumulated\n\n" );
70*16853Smckusick 	    /*
71*16853Smckusick 	     *	this doesn't hurt sinc eall the numerators will be zero.
72*16853Smckusick 	     */
73*16853Smckusick 	totime = 1.0;
74*16853Smckusick     }
75*16853Smckusick     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
76*16853Smckusick 	    "%  " , "cumulative" , "self  " , "" , "self  " , "total " , "" );
77*16853Smckusick     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
78*16853Smckusick 	    "time" , "seconds " , "seconds" , "calls" ,
79*16853Smckusick 	    "ms/call" , "ms/call" , "name" );
804753Speter }
814753Speter 
824753Speter flatprofline( np )
834753Speter     register nltype	*np;
844753Speter {
854753Speter 
864854Speter     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
874753Speter 	return;
884753Speter     }
894753Speter     actime += np -> time;
90*16853Smckusick     printf( "%5.1f %10.2f %8.2f" ,
9110248Speter 	100 * np -> time / totime , actime / hz , np -> time / hz );
924753Speter     if ( np -> ncall != 0 ) {
93*16853Smckusick 	printf( " %8d %8.2f %8.2f  " , np -> ncall ,
94*16853Smckusick 	    1000 * np -> time / hz / np -> ncall ,
95*16853Smckusick 	    1000 * ( np -> time + np -> childtime ) / hz / np -> ncall );
964753Speter     } else {
97*16853Smckusick 	printf( " %8.8s %8.8s %8.8s  " , "" , "" , "" );
984753Speter     }
99*16853Smckusick     printname( np );
100*16853Smckusick     printf( "\n" );
1014753Speter }
1024753Speter 
1034753Speter gprofheader()
1044753Speter {
1054854Speter 
1064854Speter     if ( bflag ) {
10710285Speter 	printblurb( CALLG_BLURB );
1084854Speter     }
1097172Speter     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
1107172Speter 	    (long) scale * sizeof(UNIT) );
1117225Speter     if ( printtime > 0.0 ) {
1127225Speter 	printf( " for %.2f%% of %.2f seconds\n\n" ,
11310248Speter 		100.0/printtime , printtime / hz );
1147225Speter     } else {
1157225Speter 	printf( " no time propagated\n\n" );
1167225Speter 	    /*
1177225Speter 	     *	this doesn't hurt, since all the numerators will be 0.0
1187225Speter 	     */
1197225Speter 	printtime = 1.0;
1207225Speter     }
1214753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
1224753Speter 	"" , "" , "" , "" , "called" , "total" , "parents" , "" );
1234753Speter     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
1244753Speter 	"index" , "%time" , "self" , "descendents" ,
1254753Speter 	"called" , "self" , "name" , "index" );
1264753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
1274753Speter 	"" , "" , "" , "" , "called" , "total" , "children" , "" );
1284753Speter     printf( "\n" );
1294753Speter }
1304753Speter 
1314753Speter gprofline( np )
1324753Speter     register nltype	*np;
1334753Speter {
1344753Speter     char	kirkbuffer[ BUFSIZ ];
1354753Speter 
1364753Speter     sprintf( kirkbuffer , "[%d]" , np -> index );
1374753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f" ,
1384753Speter 	    kirkbuffer ,
1397222Speter 	    100 * ( np -> propself + np -> propchild ) / printtime ,
14010248Speter 	    np -> propself / hz ,
14110248Speter 	    np -> propchild / hz );
1424753Speter     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
1434753Speter 	printf( " %7d" , np -> ncall );
1444753Speter 	if ( np -> selfcalls != 0 ) {
1454753Speter 	    printf( "+%-7d " , np -> selfcalls );
1464753Speter 	} else {
1474753Speter 	    printf( " %7.7s " , "" );
1484753Speter 	}
1494753Speter     } else {
1504753Speter 	printf( " %7.7s %7.7s " , "" , "" );
1514753Speter     }
1524753Speter     printname( np );
1534753Speter     printf( "\n" );
1544753Speter }
1554753Speter 
156*16853Smckusick printgprof(timesortnlp)
157*16853Smckusick     nltype	**timesortnlp;
1584515Speter {
1594515Speter     int		index;
1604515Speter     nltype	*parentp;
1614515Speter 
1624515Speter 	/*
163*16853Smckusick 	 *	Print out the structured profiling list
1644515Speter 	 */
1654753Speter     gprofheader();
1667129Speter     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
1674515Speter 	parentp = timesortnlp[ index ];
1684854Speter 	if ( zflag == 0 &&
1694515Speter 	     parentp -> ncall == 0 &&
1704515Speter 	     parentp -> selfcalls == 0 &&
1717222Speter 	     parentp -> propself == 0 &&
1727222Speter 	     parentp -> propchild == 0 ) {
1734515Speter 	    continue;
1744515Speter 	}
1757172Speter 	if ( ! parentp -> printflag ) {
1767172Speter 	    continue;
1777172Speter 	}
1784515Speter 	if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
1794515Speter 		/*
1804515Speter 		 *	cycle header
1814515Speter 		 */
1824753Speter 	    printcycle( parentp );
1834753Speter 	    printmembers( parentp );
1844515Speter 	} else {
1854515Speter 	    printparents( parentp );
1864753Speter 	    gprofline( parentp );
1874515Speter 	    printchildren( parentp );
1884515Speter 	}
1894515Speter 	printf( "\n" );
1904753Speter 	printf( "-----------------------------------------------\n" );
1914753Speter 	printf( "\n" );
1924515Speter     }
193*16853Smckusick     cfree( timesortnlp );
1944515Speter }
1954515Speter 
1964856Speter     /*
1977222Speter      *	sort by decreasing propagated time
1984856Speter      *	if times are equal, but one is a cycle header,
1994856Speter      *		say that's first (e.g. less, i.e. -1).
2004856Speter      *	if one's name doesn't have an underscore and the other does,
2014856Speter      *		say the one is first.
2024856Speter      *	all else being equal, sort by names.
2034856Speter      */
2044856Speter int
2054856Speter totalcmp( npp1 , npp2 )
2064856Speter     nltype	**npp1;
2074856Speter     nltype	**npp2;
2084856Speter {
2094856Speter     register nltype	*np1 = *npp1;
2104856Speter     register nltype	*np2 = *npp2;
2114856Speter     double		diff;
2124856Speter 
2137222Speter     diff =    ( np1 -> propself + np1 -> propchild )
2147222Speter 	    - ( np2 -> propself + np2 -> propchild );
2154856Speter     if ( diff < 0.0 )
2164856Speter 	    return 1;
2174856Speter     if ( diff > 0.0 )
2184856Speter 	    return -1;
2194856Speter     if ( np1 -> name == 0 && np1 -> cycleno != 0 )
2204856Speter 	return -1;
2214856Speter     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
2224856Speter 	return 1;
2234856Speter     if ( np1 -> name == 0 )
2244856Speter 	return -1;
2254856Speter     if ( np2 -> name == 0 )
2264856Speter 	return 1;
2274856Speter     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
2284856Speter 	return -1;
2294856Speter     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
2304856Speter 	return 1;
2317222Speter     if ( np1 -> ncall > np2 -> ncall )
2327222Speter 	return -1;
2337222Speter     if ( np1 -> ncall < np2 -> ncall )
2347222Speter 	return 1;
2354856Speter     return strcmp( np1 -> name , np2 -> name );
2364856Speter }
2374856Speter 
2384515Speter printparents( childp )
2394515Speter     nltype	*childp;
2404515Speter {
2414515Speter     nltype	*parentp;
2424515Speter     arctype	*arcp;
2434515Speter     nltype	*cycleheadp;
2444515Speter 
2454515Speter     if ( childp -> cyclehead != 0 ) {
2464515Speter 	cycleheadp = childp -> cyclehead;
2474515Speter     } else {
2484515Speter 	cycleheadp = childp;
2494515Speter     }
2504515Speter     if ( childp -> parents == 0 ) {
2514753Speter 	printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n" ,
2524515Speter 		"" , "" , "" , "" , "" , "" );
2534515Speter 	return;
2544515Speter     }
2554515Speter     sortparents( childp );
2564515Speter     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
2574515Speter 	parentp = arcp -> arc_parentp;
2584515Speter 	if ( childp == parentp ||
2594515Speter 	     ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
2604515Speter 		/*
2614753Speter 		 *	selfcall or call among siblings
2624515Speter 		 */
2634753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
2644515Speter 		    "" , "" , "" , "" ,
2654515Speter 		    arcp -> arc_count , "" );
2664515Speter 	    printname( parentp );
2674515Speter 	    printf( "\n" );
2684515Speter 	} else {
2694515Speter 		/*
2704515Speter 		 *	regular parent of child
2714515Speter 		 */
2724753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
2734753Speter 		    "" , "" ,
27410248Speter 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
2754515Speter 		    arcp -> arc_count , cycleheadp -> ncall );
2764515Speter 	    printname( parentp );
2774515Speter 	    printf( "\n" );
2784515Speter 	}
2794515Speter     }
2804515Speter }
2814515Speter 
2824515Speter printchildren( parentp )
2834515Speter     nltype	*parentp;
2844515Speter {
2854515Speter     nltype	*childp;
2864515Speter     arctype	*arcp;
2874515Speter 
2884515Speter     sortchildren( parentp );
2894515Speter     arcp = parentp -> children;
2904515Speter     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
2914515Speter 	childp = arcp -> arc_childp;
2924515Speter 	if ( childp == parentp ||
2934515Speter 	    ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
2944515Speter 		/*
2954515Speter 		 *	self call or call to sibling
2964515Speter 		 */
2974753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
2984753Speter 		    "" , "" , "" , "" , arcp -> arc_count , "" );
2994515Speter 	    printname( childp );
3004515Speter 	    printf( "\n" );
3014515Speter 	} else {
3024515Speter 		/*
3034515Speter 		 *	regular child of parent
3044515Speter 		 */
3054753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
3064753Speter 		    "" , "" ,
30710248Speter 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
3084515Speter 		    arcp -> arc_count , childp -> cyclehead -> ncall );
3094515Speter 	    printname( childp );
3104515Speter 	    printf( "\n" );
3114515Speter 	}
3124515Speter     }
3134515Speter }
3144515Speter 
3154515Speter printname( selfp )
3164515Speter     nltype	*selfp;
3174515Speter {
3184515Speter 
3194515Speter     if ( selfp -> name != 0 ) {
3204753Speter 	printf( "%s" , selfp -> name );
3214515Speter #	ifdef DEBUG
3224515Speter 	    if ( debug & DFNDEBUG ) {
3234515Speter 		printf( "{%d} " , selfp -> toporder );
3244515Speter 	    }
3257222Speter 	    if ( debug & PROPDEBUG ) {
3267222Speter 		printf( "%5.2f%% " , selfp -> propfraction );
3277222Speter 	    }
3284515Speter #	endif DEBUG
3294515Speter     }
3304842Speter     if ( selfp -> cycleno != 0 ) {
331*16853Smckusick 	printf( " <cycle %d>" , selfp -> cycleno );
3324842Speter     }
3334753Speter     if ( selfp -> index != 0 ) {
3347172Speter 	if ( selfp -> printflag ) {
3357172Speter 	    printf( " [%d]" , selfp -> index );
3367172Speter 	} else {
3377172Speter 	    printf( " (%d)" , selfp -> index );
3387172Speter 	}
3394753Speter     }
3404515Speter }
3414515Speter 
3424515Speter sortchildren( parentp )
3434515Speter     nltype	*parentp;
3444515Speter {
3454515Speter     arctype	*arcp;
3464515Speter     arctype	*detachedp;
3474515Speter     arctype	sorted;
3484515Speter     arctype	*prevp;
3494515Speter 
3504515Speter 	/*
3514515Speter 	 *	unlink children from parent,
3524515Speter 	 *	then insertion sort back on to sorted's children.
3534515Speter 	 *	    *arcp	the arc you have detached and are inserting.
3544515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
3554515Speter 	 *	    sorted	arc list onto which you insertion sort.
3564515Speter 	 *	    *prevp	arc before the arc you are comparing.
3574515Speter 	 */
3584515Speter     sorted.arc_childlist = 0;
35911798Speter     for (  (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist);
3604515Speter 	    arcp ;
36111798Speter 	   (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) {
3624515Speter 	    /*
3634515Speter 	     *	consider *arcp as disconnected
3644515Speter 	     *	insert it into sorted
3654515Speter 	     */
3664515Speter 	for (   prevp = &sorted ;
3674515Speter 		prevp -> arc_childlist ;
3684515Speter 		prevp = prevp -> arc_childlist ) {
3694515Speter 	    if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
3704515Speter 		break;
3714515Speter 	    }
3724515Speter 	}
3734515Speter 	arcp -> arc_childlist = prevp -> arc_childlist;
3744515Speter 	prevp -> arc_childlist = arcp;
3754515Speter     }
3764515Speter 	/*
3774515Speter 	 *	reattach sorted children to parent
3784515Speter 	 */
3794515Speter     parentp -> children = sorted.arc_childlist;
3804515Speter }
3814515Speter 
3824515Speter sortparents( childp )
3834515Speter     nltype	*childp;
3844515Speter {
3854515Speter     arctype	*arcp;
3864515Speter     arctype	*detachedp;
3874515Speter     arctype	sorted;
3884515Speter     arctype	*prevp;
3894515Speter 
3904515Speter 	/*
3914515Speter 	 *	unlink parents from child,
3924515Speter 	 *	then insertion sort back on to sorted's parents.
3934515Speter 	 *	    *arcp	the arc you have detached and are inserting.
3944515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
3954515Speter 	 *	    sorted	arc list onto which you insertion sort.
3964515Speter 	 *	    *prevp	arc before the arc you are comparing.
3974515Speter 	 */
3984515Speter     sorted.arc_parentlist = 0;
39911798Speter     for (  (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist);
4004515Speter 	    arcp ;
40111798Speter 	   (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) {
4024515Speter 	    /*
4034515Speter 	     *	consider *arcp as disconnected
4044515Speter 	     *	insert it into sorted
4054515Speter 	     */
4064515Speter 	for (   prevp = &sorted ;
4074515Speter 		prevp -> arc_parentlist ;
4084515Speter 		prevp = prevp -> arc_parentlist ) {
4094515Speter 	    if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
4104515Speter 		break;
4114515Speter 	    }
4124515Speter 	}
4134515Speter 	arcp -> arc_parentlist = prevp -> arc_parentlist;
4144515Speter 	prevp -> arc_parentlist = arcp;
4154515Speter     }
4164515Speter 	/*
4174515Speter 	 *	reattach sorted arcs to child
4184515Speter 	 */
4194515Speter     childp -> parents = sorted.arc_parentlist;
4204515Speter }
4214515Speter 
4224515Speter     /*
4234753Speter      *	print a cycle header
4244753Speter      */
4254753Speter printcycle( cyclep )
4264753Speter     nltype	*cyclep;
4274753Speter {
4284753Speter     char	kirkbuffer[ BUFSIZ ];
4294753Speter 
4304753Speter     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
4314753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
4324753Speter 	    kirkbuffer ,
4337222Speter 	    100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
43410248Speter 	    cyclep -> propself / hz ,
43510248Speter 	    cyclep -> propchild / hz ,
4364753Speter 	    cyclep -> ncall );
4374753Speter     if ( cyclep -> selfcalls != 0 ) {
4384753Speter 	printf( "+%-7d" , cyclep -> selfcalls );
4394753Speter     } else {
4404753Speter 	printf( " %7.7s" , "" );
4414753Speter     }
4424753Speter     printf( " <cycle %d as a whole>\t[%d]\n" ,
4434753Speter 	    cyclep -> cycleno , cyclep -> index );
4444753Speter }
4454753Speter 
4464753Speter     /*
4474753Speter      *	print the members of a cycle
4484753Speter      */
4494753Speter printmembers( cyclep )
4504753Speter     nltype	*cyclep;
4514753Speter {
4524753Speter     nltype	*memberp;
4534753Speter 
4544753Speter     sortmembers( cyclep );
4554753Speter     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
4564753Speter 	printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
45710248Speter 		"" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
4584753Speter 		memberp -> ncall );
4594753Speter 	if ( memberp -> selfcalls != 0 ) {
4604753Speter 	    printf( "+%-7d" , memberp -> selfcalls );
4614753Speter 	} else {
4624753Speter 	    printf( " %7.7s" , "" );
4634753Speter 	}
4644753Speter 	printf( "     " );
4654753Speter 	printname( memberp );
4664753Speter 	printf( "\n" );
4674753Speter     }
4684753Speter }
4694753Speter 
4704753Speter     /*
4714753Speter      *	sort members of a cycle
4724753Speter      */
4734753Speter sortmembers( cyclep )
4744753Speter     nltype	*cyclep;
4754753Speter {
4764753Speter     nltype	*todo;
4774753Speter     nltype	*doing;
4784753Speter     nltype	*prev;
4794753Speter 
4804753Speter 	/*
4814753Speter 	 *	detach cycle members from cyclehead,
4824753Speter 	 *	and insertion sort them back on.
4834753Speter 	 */
4844753Speter     todo = cyclep -> cnext;
4854753Speter     cyclep -> cnext = 0;
48611798Speter     for (  (doing = todo)&&(todo = doing -> cnext);
4874753Speter 	    doing ;
48811798Speter 	   (doing = todo )&&(todo = doing -> cnext )){
4894753Speter 	for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
4904753Speter 	    if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
4914753Speter 		break;
4924753Speter 	    }
4934753Speter 	}
4944753Speter 	doing -> cnext = prev -> cnext;
4954753Speter 	prev -> cnext = doing;
4964753Speter     }
4974753Speter }
4984753Speter 
4994753Speter     /*
5007222Speter      *	major sort is on propself + propchild,
5014753Speter      *	next is sort on ncalls + selfcalls.
5024753Speter      */
5034842Speter int
5044753Speter membercmp( this , that )
5054753Speter     nltype	*this;
5064753Speter     nltype	*that;
5074753Speter {
5087222Speter     double	thistime = this -> propself + this -> propchild;
5097222Speter     double	thattime = that -> propself + that -> propchild;
5104753Speter     long	thiscalls = this -> ncall + this -> selfcalls;
5114753Speter     long	thatcalls = that -> ncall + that -> selfcalls;
5124753Speter 
5134753Speter     if ( thistime > thattime ) {
5144753Speter 	return GREATERTHAN;
5154753Speter     }
5164753Speter     if ( thistime < thattime ) {
5174753Speter 	return LESSTHAN;
5184753Speter     }
5194753Speter     if ( thiscalls > thatcalls ) {
5204753Speter 	return GREATERTHAN;
5214753Speter     }
5224753Speter     if ( thiscalls < thatcalls ) {
5234753Speter 	return LESSTHAN;
5244753Speter     }
5254753Speter     return EQUALTO;
5264753Speter }
5274753Speter     /*
5284515Speter      *	compare two arcs to/from the same child/parent.
5294515Speter      *	- if one arc is a self arc, it's least.
5304515Speter      *	- if one arc is within a cycle, it's less than.
5314515Speter      *	- if both arcs are within a cycle, compare arc counts.
5324515Speter      *	- if neither arc is within a cycle, compare with
5337222Speter      *		arc_time + arc_childtime as major key
5344515Speter      *		arc count as minor key
5354515Speter      */
5364515Speter int
5374515Speter arccmp( thisp , thatp )
5384515Speter     arctype	*thisp;
5394515Speter     arctype	*thatp;
5404515Speter {
5414515Speter     nltype	*thisparentp = thisp -> arc_parentp;
5424515Speter     nltype	*thischildp = thisp -> arc_childp;
5434515Speter     nltype	*thatparentp = thatp -> arc_parentp;
5444515Speter     nltype	*thatchildp = thatp -> arc_childp;
5454515Speter     double	thistime;
5464515Speter     double	thattime;
5474515Speter 
5484515Speter #   ifdef DEBUG
5494515Speter 	if ( debug & TIMEDEBUG ) {
5504515Speter 	    printf( "[arccmp] " );
5514515Speter 	    printname( thisparentp );
5524515Speter 	    printf( " calls " );
5534515Speter 	    printname ( thischildp );
5544515Speter 	    printf( " %f + %f %d/%d\n" ,
5554515Speter 		    thisp -> arc_time , thisp -> arc_childtime ,
5564515Speter 		    thisp -> arc_count , thischildp -> ncall );
5574515Speter 	    printf( "[arccmp] " );
5584515Speter 	    printname( thatparentp );
5594515Speter 	    printf( " calls " );
5604515Speter 	    printname( thatchildp );
5614515Speter 	    printf( " %f + %f %d/%d\n" ,
5624515Speter 		    thatp -> arc_time , thatp -> arc_childtime ,
5634515Speter 		    thatp -> arc_count , thatchildp -> ncall );
5644515Speter 	    printf( "\n" );
5654515Speter 	}
5664515Speter #   endif DEBUG
5674515Speter     if ( thisparentp == thischildp ) {
5684515Speter 	    /* this is a self call */
5694515Speter 	return LESSTHAN;
5704515Speter     }
5714515Speter     if ( thatparentp == thatchildp ) {
5724515Speter 	    /* that is a self call */
5734515Speter 	return GREATERTHAN;
5744515Speter     }
5754515Speter     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
5764515Speter 	thisparentp -> cycleno == thischildp -> cycleno ) {
5774515Speter 	    /* this is a call within a cycle */
5784515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
5794515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
5804515Speter 		/* that is a call within the cycle, too */
5814515Speter 	    if ( thisp -> arc_count < thatp -> arc_count ) {
5824515Speter 		return LESSTHAN;
5834515Speter 	    }
5844515Speter 	    if ( thisp -> arc_count > thatp -> arc_count ) {
5854515Speter 		return GREATERTHAN;
5864515Speter 	    }
5874515Speter 	    return EQUALTO;
5884515Speter 	} else {
5894515Speter 		/* that isn't a call within the cycle */
5904515Speter 	    return LESSTHAN;
5914515Speter 	}
5924515Speter     } else {
5934515Speter 	    /* this isn't a call within a cycle */
5944515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
5954515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
5964515Speter 		/* that is a call within a cycle */
5974515Speter 	    return GREATERTHAN;
5984515Speter 	} else {
5994515Speter 		/* neither is a call within a cycle */
6004515Speter 	    thistime = thisp -> arc_time + thisp -> arc_childtime;
6014515Speter 	    thattime = thatp -> arc_time + thatp -> arc_childtime;
6024515Speter 	    if ( thistime < thattime )
6034515Speter 		return LESSTHAN;
6044515Speter 	    if ( thistime > thattime )
6054515Speter 		return GREATERTHAN;
6064515Speter 	    if ( thisp -> arc_count < thatp -> arc_count )
6074515Speter 		return LESSTHAN;
6084515Speter 	    if ( thisp -> arc_count > thatp -> arc_count )
6094515Speter 		return GREATERTHAN;
6104515Speter 	    return EQUALTO;
6114515Speter 	}
6124515Speter     }
6134515Speter }
6144854Speter 
6154854Speter printblurb( blurbname )
6164854Speter     char	*blurbname;
6174854Speter {
6184854Speter     FILE	*blurbfile;
6194854Speter     int		input;
6204854Speter 
62110285Speter     blurbfile = fopen( blurbname , "r" );
6224854Speter     if ( blurbfile == NULL ) {
62310285Speter 	perror( blurbname );
6244854Speter 	return;
6254854Speter     }
6264854Speter     while ( ( input = getc( blurbfile ) ) != EOF ) {
6274854Speter 	putchar( input );
6284854Speter     }
6294854Speter     fclose( blurbfile );
6304854Speter }
631*16853Smckusick 
632*16853Smckusick int
633*16853Smckusick namecmp( npp1 , npp2 )
634*16853Smckusick     nltype **npp1, **npp2;
635*16853Smckusick {
636*16853Smckusick     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
637*16853Smckusick }
638*16853Smckusick 
639*16853Smckusick printindex()
640*16853Smckusick {
641*16853Smckusick     nltype		**namesortnlp;
642*16853Smckusick     register nltype	*nlp;
643*16853Smckusick     int			index, nnames, todo, i, j;
644*16853Smckusick     char		peterbuffer[ BUFSIZ ];
645*16853Smckusick 
646*16853Smckusick 	/*
647*16853Smckusick 	 *	Now, sort regular function name alphbetically
648*16853Smckusick 	 *	to create an index.
649*16853Smckusick 	 */
650*16853Smckusick     namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
651*16853Smckusick     if ( namesortnlp == (nltype **) 0 ) {
652*16853Smckusick 	fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
653*16853Smckusick     }
654*16853Smckusick     for ( index = 0 , nnames = 0 ; index < nname ; index++ ) {
655*16853Smckusick 	if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 )
656*16853Smckusick 		continue;
657*16853Smckusick 	namesortnlp[nnames++] = &nl[index];
658*16853Smckusick     }
659*16853Smckusick     qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
660*16853Smckusick     for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) {
661*16853Smckusick 	namesortnlp[todo++] = &cyclenl[index];
662*16853Smckusick     }
663*16853Smckusick     printf( "\f\nIndex by function name\n\n" );
664*16853Smckusick     index = ( todo + 2 ) / 3;
665*16853Smckusick     for ( i = 0; i < index ; i++ ) {
666*16853Smckusick 	for ( j = i; j < todo ; j += index ) {
667*16853Smckusick 	    nlp = namesortnlp[ j ];
668*16853Smckusick 	    if ( nlp -> printflag ) {
669*16853Smckusick 		sprintf( peterbuffer , "[%d]" , nlp -> index );
670*16853Smckusick 	    } else {
671*16853Smckusick 		sprintf( peterbuffer , "(%d)" , nlp -> index );
672*16853Smckusick 	    }
673*16853Smckusick 	    if ( j < nnames ) {
674*16853Smckusick 		printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name );
675*16853Smckusick 	    } else {
676*16853Smckusick 		printf( "%6.6s " , peterbuffer );
677*16853Smckusick 		sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno );
678*16853Smckusick 		printf( "%-19.19s" , peterbuffer );
679*16853Smckusick 	    }
680*16853Smckusick 	}
681*16853Smckusick 	printf( "\n" );
682*16853Smckusick     }
683*16853Smckusick     cfree( namesortnlp );
684*16853Smckusick }
685