xref: /csrg-svn/usr.bin/gprof/printgprof.c (revision 37801)
121963Sdist /*
221963Sdist  * Copyright (c) 1983 Regents of the University of California.
334199Sbostic  * All rights reserved.
434199Sbostic  *
534199Sbostic  * Redistribution and use in source and binary forms are permitted
634881Sbostic  * provided that the above copyright notice and this paragraph are
734881Sbostic  * duplicated in all such forms and that any documentation,
834881Sbostic  * advertising materials, and other materials related to such
934881Sbostic  * distribution and use acknowledge that the software was developed
1034881Sbostic  * by the University of California, Berkeley.  The name of the
1134881Sbostic  * University may not be used to endorse or promote products derived
1234881Sbostic  * from this software without specific prior written permission.
1334881Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434881Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534881Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621963Sdist  */
1721963Sdist 
184515Speter #ifndef lint
19*37801Sbostic static char sccsid[] = "@(#)printgprof.c	5.6 (Berkeley) 05/10/89";
2034199Sbostic #endif /* not lint */
214515Speter 
224562Speter #include "gprof.h"
23*37801Sbostic #include "pathnames.h"
244515Speter 
254753Speter printprof()
264753Speter {
274753Speter     register nltype	*np;
284753Speter     nltype		**sortednlp;
2933227Sbostic     int			index, timecmp();
304753Speter 
314753Speter     actime = 0.0;
3216853Smckusick     printf( "\f\n" );
334753Speter     flatprofheader();
344753Speter 	/*
354753Speter 	 *	Sort the symbol table in by time
364753Speter 	 */
374753Speter     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
384753Speter     if ( sortednlp == (nltype **) 0 ) {
394753Speter 	fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
404753Speter     }
414753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
424753Speter 	sortednlp[ index ] = &nl[ index ];
434753Speter     }
444753Speter     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
454753Speter     for ( index = 0 ; index < nname ; index += 1 ) {
464753Speter 	np = sortednlp[ index ];
474753Speter 	flatprofline( np );
484753Speter     }
494753Speter     actime = 0.0;
5016853Smckusick     cfree( sortednlp );
514753Speter }
524753Speter 
534753Speter timecmp( npp1 , npp2 )
544753Speter     nltype **npp1, **npp2;
554753Speter {
564856Speter     double	timediff;
574856Speter     long	calldiff;
584753Speter 
594856Speter     timediff = (*npp2) -> time - (*npp1) -> time;
604856Speter     if ( timediff > 0.0 )
614753Speter 	return 1 ;
624856Speter     if ( timediff < 0.0 )
634753Speter 	return -1;
644856Speter     calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
654856Speter     if ( calldiff > 0 )
664856Speter 	return 1;
674856Speter     if ( calldiff < 0 )
684856Speter 	return -1;
694753Speter     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
704753Speter }
714753Speter 
724753Speter     /*
734753Speter      *	header for flatprofline
744753Speter      */
754753Speter flatprofheader()
764753Speter {
774753Speter 
784854Speter     if ( bflag ) {
79*37801Sbostic 	printblurb( _PATH_FLAT_BLURB );
804854Speter     }
8116853Smckusick     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
8216853Smckusick 	    (long) scale * sizeof(UNIT) );
8316853Smckusick     if ( totime > 0.0 ) {
8416853Smckusick 	printf( " for %.2f%% of %.2f seconds\n\n" ,
8516853Smckusick 		100.0/totime , totime / hz );
8616853Smckusick     } else {
8716853Smckusick 	printf( " no time accumulated\n\n" );
8816853Smckusick 	    /*
8916853Smckusick 	     *	this doesn't hurt sinc eall the numerators will be zero.
9016853Smckusick 	     */
9116853Smckusick 	totime = 1.0;
9216853Smckusick     }
9316853Smckusick     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
9416853Smckusick 	    "%  " , "cumulative" , "self  " , "" , "self  " , "total " , "" );
9516853Smckusick     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
9616853Smckusick 	    "time" , "seconds " , "seconds" , "calls" ,
9716853Smckusick 	    "ms/call" , "ms/call" , "name" );
984753Speter }
994753Speter 
1004753Speter flatprofline( np )
1014753Speter     register nltype	*np;
1024753Speter {
1034753Speter 
1044854Speter     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
1054753Speter 	return;
1064753Speter     }
1074753Speter     actime += np -> time;
10816853Smckusick     printf( "%5.1f %10.2f %8.2f" ,
10910248Speter 	100 * np -> time / totime , actime / hz , np -> time / hz );
1104753Speter     if ( np -> ncall != 0 ) {
11116853Smckusick 	printf( " %8d %8.2f %8.2f  " , np -> ncall ,
11216853Smckusick 	    1000 * np -> time / hz / np -> ncall ,
11316853Smckusick 	    1000 * ( np -> time + np -> childtime ) / hz / np -> ncall );
1144753Speter     } else {
11516853Smckusick 	printf( " %8.8s %8.8s %8.8s  " , "" , "" , "" );
1164753Speter     }
11716853Smckusick     printname( np );
11816853Smckusick     printf( "\n" );
1194753Speter }
1204753Speter 
1214753Speter gprofheader()
1224753Speter {
1234854Speter 
1244854Speter     if ( bflag ) {
125*37801Sbostic 	printblurb( _PATH_CALLG_BLURB );
1264854Speter     }
1277172Speter     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
1287172Speter 	    (long) scale * sizeof(UNIT) );
1297225Speter     if ( printtime > 0.0 ) {
1307225Speter 	printf( " for %.2f%% of %.2f seconds\n\n" ,
13110248Speter 		100.0/printtime , printtime / hz );
1327225Speter     } else {
1337225Speter 	printf( " no time propagated\n\n" );
1347225Speter 	    /*
1357225Speter 	     *	this doesn't hurt, since all the numerators will be 0.0
1367225Speter 	     */
1377225Speter 	printtime = 1.0;
1387225Speter     }
1394753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
14030799Sbostic 	"" , "" , "" , "" , "called" , "total" , "parents");
1414753Speter     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
1424753Speter 	"index" , "%time" , "self" , "descendents" ,
1434753Speter 	"called" , "self" , "name" , "index" );
1444753Speter     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
14530799Sbostic 	"" , "" , "" , "" , "called" , "total" , "children");
1464753Speter     printf( "\n" );
1474753Speter }
1484753Speter 
1494753Speter gprofline( np )
1504753Speter     register nltype	*np;
1514753Speter {
1524753Speter     char	kirkbuffer[ BUFSIZ ];
1534753Speter 
1544753Speter     sprintf( kirkbuffer , "[%d]" , np -> index );
1554753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f" ,
1564753Speter 	    kirkbuffer ,
1577222Speter 	    100 * ( np -> propself + np -> propchild ) / printtime ,
15810248Speter 	    np -> propself / hz ,
15910248Speter 	    np -> propchild / hz );
1604753Speter     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
1614753Speter 	printf( " %7d" , np -> ncall );
1624753Speter 	if ( np -> selfcalls != 0 ) {
1634753Speter 	    printf( "+%-7d " , np -> selfcalls );
1644753Speter 	} else {
1654753Speter 	    printf( " %7.7s " , "" );
1664753Speter 	}
1674753Speter     } else {
1684753Speter 	printf( " %7.7s %7.7s " , "" , "" );
1694753Speter     }
1704753Speter     printname( np );
1714753Speter     printf( "\n" );
1724753Speter }
1734753Speter 
17416853Smckusick printgprof(timesortnlp)
17516853Smckusick     nltype	**timesortnlp;
1764515Speter {
1774515Speter     int		index;
1784515Speter     nltype	*parentp;
1794515Speter 
1804515Speter 	/*
18116853Smckusick 	 *	Print out the structured profiling list
1824515Speter 	 */
1834753Speter     gprofheader();
1847129Speter     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
1854515Speter 	parentp = timesortnlp[ index ];
1864854Speter 	if ( zflag == 0 &&
1874515Speter 	     parentp -> ncall == 0 &&
1884515Speter 	     parentp -> selfcalls == 0 &&
1897222Speter 	     parentp -> propself == 0 &&
1907222Speter 	     parentp -> propchild == 0 ) {
1914515Speter 	    continue;
1924515Speter 	}
1937172Speter 	if ( ! parentp -> printflag ) {
1947172Speter 	    continue;
1957172Speter 	}
1964515Speter 	if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
1974515Speter 		/*
1984515Speter 		 *	cycle header
1994515Speter 		 */
2004753Speter 	    printcycle( parentp );
2014753Speter 	    printmembers( parentp );
2024515Speter 	} else {
2034515Speter 	    printparents( parentp );
2044753Speter 	    gprofline( parentp );
2054515Speter 	    printchildren( parentp );
2064515Speter 	}
2074515Speter 	printf( "\n" );
2084753Speter 	printf( "-----------------------------------------------\n" );
2094753Speter 	printf( "\n" );
2104515Speter     }
21116853Smckusick     cfree( timesortnlp );
2124515Speter }
2134515Speter 
2144856Speter     /*
2157222Speter      *	sort by decreasing propagated time
2164856Speter      *	if times are equal, but one is a cycle header,
2174856Speter      *		say that's first (e.g. less, i.e. -1).
2184856Speter      *	if one's name doesn't have an underscore and the other does,
2194856Speter      *		say the one is first.
2204856Speter      *	all else being equal, sort by names.
2214856Speter      */
2224856Speter int
2234856Speter totalcmp( npp1 , npp2 )
2244856Speter     nltype	**npp1;
2254856Speter     nltype	**npp2;
2264856Speter {
2274856Speter     register nltype	*np1 = *npp1;
2284856Speter     register nltype	*np2 = *npp2;
2294856Speter     double		diff;
2304856Speter 
2317222Speter     diff =    ( np1 -> propself + np1 -> propchild )
2327222Speter 	    - ( np2 -> propself + np2 -> propchild );
2334856Speter     if ( diff < 0.0 )
2344856Speter 	    return 1;
2354856Speter     if ( diff > 0.0 )
2364856Speter 	    return -1;
2374856Speter     if ( np1 -> name == 0 && np1 -> cycleno != 0 )
2384856Speter 	return -1;
2394856Speter     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
2404856Speter 	return 1;
2414856Speter     if ( np1 -> name == 0 )
2424856Speter 	return -1;
2434856Speter     if ( np2 -> name == 0 )
2444856Speter 	return 1;
2454856Speter     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
2464856Speter 	return -1;
2474856Speter     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
2484856Speter 	return 1;
2497222Speter     if ( np1 -> ncall > np2 -> ncall )
2507222Speter 	return -1;
2517222Speter     if ( np1 -> ncall < np2 -> ncall )
2527222Speter 	return 1;
2534856Speter     return strcmp( np1 -> name , np2 -> name );
2544856Speter }
2554856Speter 
2564515Speter printparents( childp )
2574515Speter     nltype	*childp;
2584515Speter {
2594515Speter     nltype	*parentp;
2604515Speter     arctype	*arcp;
2614515Speter     nltype	*cycleheadp;
2624515Speter 
2634515Speter     if ( childp -> cyclehead != 0 ) {
2644515Speter 	cycleheadp = childp -> cyclehead;
2654515Speter     } else {
2664515Speter 	cycleheadp = childp;
2674515Speter     }
2684515Speter     if ( childp -> parents == 0 ) {
2694753Speter 	printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n" ,
2704515Speter 		"" , "" , "" , "" , "" , "" );
2714515Speter 	return;
2724515Speter     }
2734515Speter     sortparents( childp );
2744515Speter     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
2754515Speter 	parentp = arcp -> arc_parentp;
2764515Speter 	if ( childp == parentp ||
2774515Speter 	     ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
2784515Speter 		/*
2794753Speter 		 *	selfcall or call among siblings
2804515Speter 		 */
2814753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
2824515Speter 		    "" , "" , "" , "" ,
2834515Speter 		    arcp -> arc_count , "" );
2844515Speter 	    printname( parentp );
2854515Speter 	    printf( "\n" );
2864515Speter 	} else {
2874515Speter 		/*
2884515Speter 		 *	regular parent of child
2894515Speter 		 */
2904753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
2914753Speter 		    "" , "" ,
29210248Speter 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
2934515Speter 		    arcp -> arc_count , cycleheadp -> ncall );
2944515Speter 	    printname( parentp );
2954515Speter 	    printf( "\n" );
2964515Speter 	}
2974515Speter     }
2984515Speter }
2994515Speter 
3004515Speter printchildren( parentp )
3014515Speter     nltype	*parentp;
3024515Speter {
3034515Speter     nltype	*childp;
3044515Speter     arctype	*arcp;
3054515Speter 
3064515Speter     sortchildren( parentp );
3074515Speter     arcp = parentp -> children;
3084515Speter     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
3094515Speter 	childp = arcp -> arc_childp;
3104515Speter 	if ( childp == parentp ||
3114515Speter 	    ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
3124515Speter 		/*
3134515Speter 		 *	self call or call to sibling
3144515Speter 		 */
3154753Speter 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
3164753Speter 		    "" , "" , "" , "" , arcp -> arc_count , "" );
3174515Speter 	    printname( childp );
3184515Speter 	    printf( "\n" );
3194515Speter 	} else {
3204515Speter 		/*
3214515Speter 		 *	regular child of parent
3224515Speter 		 */
3234753Speter 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
3244753Speter 		    "" , "" ,
32510248Speter 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
3264515Speter 		    arcp -> arc_count , childp -> cyclehead -> ncall );
3274515Speter 	    printname( childp );
3284515Speter 	    printf( "\n" );
3294515Speter 	}
3304515Speter     }
3314515Speter }
3324515Speter 
3334515Speter printname( selfp )
3344515Speter     nltype	*selfp;
3354515Speter {
3364515Speter 
3374515Speter     if ( selfp -> name != 0 ) {
3384753Speter 	printf( "%s" , selfp -> name );
3394515Speter #	ifdef DEBUG
3404515Speter 	    if ( debug & DFNDEBUG ) {
3414515Speter 		printf( "{%d} " , selfp -> toporder );
3424515Speter 	    }
3437222Speter 	    if ( debug & PROPDEBUG ) {
3447222Speter 		printf( "%5.2f%% " , selfp -> propfraction );
3457222Speter 	    }
3464515Speter #	endif DEBUG
3474515Speter     }
3484842Speter     if ( selfp -> cycleno != 0 ) {
34916853Smckusick 	printf( " <cycle %d>" , selfp -> cycleno );
3504842Speter     }
3514753Speter     if ( selfp -> index != 0 ) {
3527172Speter 	if ( selfp -> printflag ) {
3537172Speter 	    printf( " [%d]" , selfp -> index );
3547172Speter 	} else {
3557172Speter 	    printf( " (%d)" , selfp -> index );
3567172Speter 	}
3574753Speter     }
3584515Speter }
3594515Speter 
3604515Speter sortchildren( parentp )
3614515Speter     nltype	*parentp;
3624515Speter {
3634515Speter     arctype	*arcp;
3644515Speter     arctype	*detachedp;
3654515Speter     arctype	sorted;
3664515Speter     arctype	*prevp;
3674515Speter 
3684515Speter 	/*
3694515Speter 	 *	unlink children from parent,
3704515Speter 	 *	then insertion sort back on to sorted's children.
3714515Speter 	 *	    *arcp	the arc you have detached and are inserting.
3724515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
3734515Speter 	 *	    sorted	arc list onto which you insertion sort.
3744515Speter 	 *	    *prevp	arc before the arc you are comparing.
3754515Speter 	 */
3764515Speter     sorted.arc_childlist = 0;
37711798Speter     for (  (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist);
3784515Speter 	    arcp ;
37911798Speter 	   (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) {
3804515Speter 	    /*
3814515Speter 	     *	consider *arcp as disconnected
3824515Speter 	     *	insert it into sorted
3834515Speter 	     */
3844515Speter 	for (   prevp = &sorted ;
3854515Speter 		prevp -> arc_childlist ;
3864515Speter 		prevp = prevp -> arc_childlist ) {
3874515Speter 	    if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
3884515Speter 		break;
3894515Speter 	    }
3904515Speter 	}
3914515Speter 	arcp -> arc_childlist = prevp -> arc_childlist;
3924515Speter 	prevp -> arc_childlist = arcp;
3934515Speter     }
3944515Speter 	/*
3954515Speter 	 *	reattach sorted children to parent
3964515Speter 	 */
3974515Speter     parentp -> children = sorted.arc_childlist;
3984515Speter }
3994515Speter 
4004515Speter sortparents( childp )
4014515Speter     nltype	*childp;
4024515Speter {
4034515Speter     arctype	*arcp;
4044515Speter     arctype	*detachedp;
4054515Speter     arctype	sorted;
4064515Speter     arctype	*prevp;
4074515Speter 
4084515Speter 	/*
4094515Speter 	 *	unlink parents from child,
4104515Speter 	 *	then insertion sort back on to sorted's parents.
4114515Speter 	 *	    *arcp	the arc you have detached and are inserting.
4124515Speter 	 *	    *detachedp	the rest of the arcs to be sorted.
4134515Speter 	 *	    sorted	arc list onto which you insertion sort.
4144515Speter 	 *	    *prevp	arc before the arc you are comparing.
4154515Speter 	 */
4164515Speter     sorted.arc_parentlist = 0;
41711798Speter     for (  (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist);
4184515Speter 	    arcp ;
41911798Speter 	   (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) {
4204515Speter 	    /*
4214515Speter 	     *	consider *arcp as disconnected
4224515Speter 	     *	insert it into sorted
4234515Speter 	     */
4244515Speter 	for (   prevp = &sorted ;
4254515Speter 		prevp -> arc_parentlist ;
4264515Speter 		prevp = prevp -> arc_parentlist ) {
4274515Speter 	    if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
4284515Speter 		break;
4294515Speter 	    }
4304515Speter 	}
4314515Speter 	arcp -> arc_parentlist = prevp -> arc_parentlist;
4324515Speter 	prevp -> arc_parentlist = arcp;
4334515Speter     }
4344515Speter 	/*
4354515Speter 	 *	reattach sorted arcs to child
4364515Speter 	 */
4374515Speter     childp -> parents = sorted.arc_parentlist;
4384515Speter }
4394515Speter 
4404515Speter     /*
4414753Speter      *	print a cycle header
4424753Speter      */
4434753Speter printcycle( cyclep )
4444753Speter     nltype	*cyclep;
4454753Speter {
4464753Speter     char	kirkbuffer[ BUFSIZ ];
4474753Speter 
4484753Speter     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
4494753Speter     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
4504753Speter 	    kirkbuffer ,
4517222Speter 	    100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
45210248Speter 	    cyclep -> propself / hz ,
45310248Speter 	    cyclep -> propchild / hz ,
4544753Speter 	    cyclep -> ncall );
4554753Speter     if ( cyclep -> selfcalls != 0 ) {
4564753Speter 	printf( "+%-7d" , cyclep -> selfcalls );
4574753Speter     } else {
4584753Speter 	printf( " %7.7s" , "" );
4594753Speter     }
4604753Speter     printf( " <cycle %d as a whole>\t[%d]\n" ,
4614753Speter 	    cyclep -> cycleno , cyclep -> index );
4624753Speter }
4634753Speter 
4644753Speter     /*
4654753Speter      *	print the members of a cycle
4664753Speter      */
4674753Speter printmembers( cyclep )
4684753Speter     nltype	*cyclep;
4694753Speter {
4704753Speter     nltype	*memberp;
4714753Speter 
4724753Speter     sortmembers( cyclep );
4734753Speter     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
4744753Speter 	printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
47510248Speter 		"" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
4764753Speter 		memberp -> ncall );
4774753Speter 	if ( memberp -> selfcalls != 0 ) {
4784753Speter 	    printf( "+%-7d" , memberp -> selfcalls );
4794753Speter 	} else {
4804753Speter 	    printf( " %7.7s" , "" );
4814753Speter 	}
4824753Speter 	printf( "     " );
4834753Speter 	printname( memberp );
4844753Speter 	printf( "\n" );
4854753Speter     }
4864753Speter }
4874753Speter 
4884753Speter     /*
4894753Speter      *	sort members of a cycle
4904753Speter      */
4914753Speter sortmembers( cyclep )
4924753Speter     nltype	*cyclep;
4934753Speter {
4944753Speter     nltype	*todo;
4954753Speter     nltype	*doing;
4964753Speter     nltype	*prev;
4974753Speter 
4984753Speter 	/*
4994753Speter 	 *	detach cycle members from cyclehead,
5004753Speter 	 *	and insertion sort them back on.
5014753Speter 	 */
5024753Speter     todo = cyclep -> cnext;
5034753Speter     cyclep -> cnext = 0;
50411798Speter     for (  (doing = todo)&&(todo = doing -> cnext);
5054753Speter 	    doing ;
50611798Speter 	   (doing = todo )&&(todo = doing -> cnext )){
5074753Speter 	for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
5084753Speter 	    if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
5094753Speter 		break;
5104753Speter 	    }
5114753Speter 	}
5124753Speter 	doing -> cnext = prev -> cnext;
5134753Speter 	prev -> cnext = doing;
5144753Speter     }
5154753Speter }
5164753Speter 
5174753Speter     /*
5187222Speter      *	major sort is on propself + propchild,
5194753Speter      *	next is sort on ncalls + selfcalls.
5204753Speter      */
5214842Speter int
5224753Speter membercmp( this , that )
5234753Speter     nltype	*this;
5244753Speter     nltype	*that;
5254753Speter {
5267222Speter     double	thistime = this -> propself + this -> propchild;
5277222Speter     double	thattime = that -> propself + that -> propchild;
5284753Speter     long	thiscalls = this -> ncall + this -> selfcalls;
5294753Speter     long	thatcalls = that -> ncall + that -> selfcalls;
5304753Speter 
5314753Speter     if ( thistime > thattime ) {
5324753Speter 	return GREATERTHAN;
5334753Speter     }
5344753Speter     if ( thistime < thattime ) {
5354753Speter 	return LESSTHAN;
5364753Speter     }
5374753Speter     if ( thiscalls > thatcalls ) {
5384753Speter 	return GREATERTHAN;
5394753Speter     }
5404753Speter     if ( thiscalls < thatcalls ) {
5414753Speter 	return LESSTHAN;
5424753Speter     }
5434753Speter     return EQUALTO;
5444753Speter }
5454753Speter     /*
5464515Speter      *	compare two arcs to/from the same child/parent.
5474515Speter      *	- if one arc is a self arc, it's least.
5484515Speter      *	- if one arc is within a cycle, it's less than.
5494515Speter      *	- if both arcs are within a cycle, compare arc counts.
5504515Speter      *	- if neither arc is within a cycle, compare with
5517222Speter      *		arc_time + arc_childtime as major key
5524515Speter      *		arc count as minor key
5534515Speter      */
5544515Speter int
5554515Speter arccmp( thisp , thatp )
5564515Speter     arctype	*thisp;
5574515Speter     arctype	*thatp;
5584515Speter {
5594515Speter     nltype	*thisparentp = thisp -> arc_parentp;
5604515Speter     nltype	*thischildp = thisp -> arc_childp;
5614515Speter     nltype	*thatparentp = thatp -> arc_parentp;
5624515Speter     nltype	*thatchildp = thatp -> arc_childp;
5634515Speter     double	thistime;
5644515Speter     double	thattime;
5654515Speter 
5664515Speter #   ifdef DEBUG
5674515Speter 	if ( debug & TIMEDEBUG ) {
5684515Speter 	    printf( "[arccmp] " );
5694515Speter 	    printname( thisparentp );
5704515Speter 	    printf( " calls " );
5714515Speter 	    printname ( thischildp );
5724515Speter 	    printf( " %f + %f %d/%d\n" ,
5734515Speter 		    thisp -> arc_time , thisp -> arc_childtime ,
5744515Speter 		    thisp -> arc_count , thischildp -> ncall );
5754515Speter 	    printf( "[arccmp] " );
5764515Speter 	    printname( thatparentp );
5774515Speter 	    printf( " calls " );
5784515Speter 	    printname( thatchildp );
5794515Speter 	    printf( " %f + %f %d/%d\n" ,
5804515Speter 		    thatp -> arc_time , thatp -> arc_childtime ,
5814515Speter 		    thatp -> arc_count , thatchildp -> ncall );
5824515Speter 	    printf( "\n" );
5834515Speter 	}
5844515Speter #   endif DEBUG
5854515Speter     if ( thisparentp == thischildp ) {
5864515Speter 	    /* this is a self call */
5874515Speter 	return LESSTHAN;
5884515Speter     }
5894515Speter     if ( thatparentp == thatchildp ) {
5904515Speter 	    /* that is a self call */
5914515Speter 	return GREATERTHAN;
5924515Speter     }
5934515Speter     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
5944515Speter 	thisparentp -> cycleno == thischildp -> cycleno ) {
5954515Speter 	    /* this is a call within a cycle */
5964515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
5974515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
5984515Speter 		/* that is a call within the cycle, too */
5994515Speter 	    if ( thisp -> arc_count < thatp -> arc_count ) {
6004515Speter 		return LESSTHAN;
6014515Speter 	    }
6024515Speter 	    if ( thisp -> arc_count > thatp -> arc_count ) {
6034515Speter 		return GREATERTHAN;
6044515Speter 	    }
6054515Speter 	    return EQUALTO;
6064515Speter 	} else {
6074515Speter 		/* that isn't a call within the cycle */
6084515Speter 	    return LESSTHAN;
6094515Speter 	}
6104515Speter     } else {
6114515Speter 	    /* this isn't a call within a cycle */
6124515Speter 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
6134515Speter 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
6144515Speter 		/* that is a call within a cycle */
6154515Speter 	    return GREATERTHAN;
6164515Speter 	} else {
6174515Speter 		/* neither is a call within a cycle */
6184515Speter 	    thistime = thisp -> arc_time + thisp -> arc_childtime;
6194515Speter 	    thattime = thatp -> arc_time + thatp -> arc_childtime;
6204515Speter 	    if ( thistime < thattime )
6214515Speter 		return LESSTHAN;
6224515Speter 	    if ( thistime > thattime )
6234515Speter 		return GREATERTHAN;
6244515Speter 	    if ( thisp -> arc_count < thatp -> arc_count )
6254515Speter 		return LESSTHAN;
6264515Speter 	    if ( thisp -> arc_count > thatp -> arc_count )
6274515Speter 		return GREATERTHAN;
6284515Speter 	    return EQUALTO;
6294515Speter 	}
6304515Speter     }
6314515Speter }
6324854Speter 
6334854Speter printblurb( blurbname )
6344854Speter     char	*blurbname;
6354854Speter {
6364854Speter     FILE	*blurbfile;
6374854Speter     int		input;
6384854Speter 
63910285Speter     blurbfile = fopen( blurbname , "r" );
6404854Speter     if ( blurbfile == NULL ) {
64110285Speter 	perror( blurbname );
6424854Speter 	return;
6434854Speter     }
6444854Speter     while ( ( input = getc( blurbfile ) ) != EOF ) {
6454854Speter 	putchar( input );
6464854Speter     }
6474854Speter     fclose( blurbfile );
6484854Speter }
64916853Smckusick 
65016853Smckusick int
65116853Smckusick namecmp( npp1 , npp2 )
65216853Smckusick     nltype **npp1, **npp2;
65316853Smckusick {
65416853Smckusick     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
65516853Smckusick }
65616853Smckusick 
65716853Smckusick printindex()
65816853Smckusick {
65916853Smckusick     nltype		**namesortnlp;
66016853Smckusick     register nltype	*nlp;
66116853Smckusick     int			index, nnames, todo, i, j;
66216853Smckusick     char		peterbuffer[ BUFSIZ ];
66316853Smckusick 
66416853Smckusick 	/*
66516853Smckusick 	 *	Now, sort regular function name alphbetically
66616853Smckusick 	 *	to create an index.
66716853Smckusick 	 */
66816853Smckusick     namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
66916853Smckusick     if ( namesortnlp == (nltype **) 0 ) {
67016853Smckusick 	fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
67116853Smckusick     }
67216853Smckusick     for ( index = 0 , nnames = 0 ; index < nname ; index++ ) {
67316853Smckusick 	if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 )
67416853Smckusick 		continue;
67516853Smckusick 	namesortnlp[nnames++] = &nl[index];
67616853Smckusick     }
67716853Smckusick     qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
67816853Smckusick     for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) {
67916853Smckusick 	namesortnlp[todo++] = &cyclenl[index];
68016853Smckusick     }
68116853Smckusick     printf( "\f\nIndex by function name\n\n" );
68216853Smckusick     index = ( todo + 2 ) / 3;
68316853Smckusick     for ( i = 0; i < index ; i++ ) {
68416853Smckusick 	for ( j = i; j < todo ; j += index ) {
68516853Smckusick 	    nlp = namesortnlp[ j ];
68616853Smckusick 	    if ( nlp -> printflag ) {
68716853Smckusick 		sprintf( peterbuffer , "[%d]" , nlp -> index );
68816853Smckusick 	    } else {
68916853Smckusick 		sprintf( peterbuffer , "(%d)" , nlp -> index );
69016853Smckusick 	    }
69116853Smckusick 	    if ( j < nnames ) {
69216853Smckusick 		printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name );
69316853Smckusick 	    } else {
69416853Smckusick 		printf( "%6.6s " , peterbuffer );
69516853Smckusick 		sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno );
69616853Smckusick 		printf( "%-19.19s" , peterbuffer );
69716853Smckusick 	    }
69816853Smckusick 	}
69916853Smckusick 	printf( "\n" );
70016853Smckusick     }
70116853Smckusick     cfree( namesortnlp );
70216853Smckusick }
703