xref: /original-bsd/usr.bin/gprof/printgprof.c (revision e7d21e74)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)printgprof.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 #include "gprof.h"
13 #include "pathnames.h"
14 
printprof()15 printprof()
16 {
17     register nltype	*np;
18     nltype		**sortednlp;
19     int			index, timecmp();
20 
21     actime = 0.0;
22     printf( "\f\n" );
23     flatprofheader();
24 	/*
25 	 *	Sort the symbol table in by time
26 	 */
27     sortednlp = (nltype **) calloc( nname , sizeof(nltype *) );
28     if ( sortednlp == (nltype **) 0 ) {
29 	fprintf( stderr , "[printprof] ran out of memory for time sorting\n" );
30     }
31     for ( index = 0 ; index < nname ; index += 1 ) {
32 	sortednlp[ index ] = &nl[ index ];
33     }
34     qsort( sortednlp , nname , sizeof(nltype *) , timecmp );
35     for ( index = 0 ; index < nname ; index += 1 ) {
36 	np = sortednlp[ index ];
37 	flatprofline( np );
38     }
39     actime = 0.0;
40     free( sortednlp );
41 }
42 
timecmp(npp1,npp2)43 timecmp( npp1 , npp2 )
44     nltype **npp1, **npp2;
45 {
46     double	timediff;
47     long	calldiff;
48 
49     timediff = (*npp2) -> time - (*npp1) -> time;
50     if ( timediff > 0.0 )
51 	return 1 ;
52     if ( timediff < 0.0 )
53 	return -1;
54     calldiff = (*npp2) -> ncall - (*npp1) -> ncall;
55     if ( calldiff > 0 )
56 	return 1;
57     if ( calldiff < 0 )
58 	return -1;
59     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
60 }
61 
62     /*
63      *	header for flatprofline
64      */
flatprofheader()65 flatprofheader()
66 {
67 
68     if ( bflag ) {
69 	printblurb( _PATH_FLAT_BLURB );
70     }
71     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
72 	    (long) scale * sizeof(UNIT) );
73     if ( totime > 0.0 ) {
74 	printf( " for %.2f%% of %.2f seconds\n\n" ,
75 		100.0/totime , totime / hz );
76     } else {
77 	printf( " no time accumulated\n\n" );
78 	    /*
79 	     *	this doesn't hurt sinc eall the numerators will be zero.
80 	     */
81 	totime = 1.0;
82     }
83     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
84 	    "%  " , "cumulative" , "self  " , "" , "self  " , "total " , "" );
85     printf( "%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s  %-8.8s\n" ,
86 	    "time" , "seconds " , "seconds" , "calls" ,
87 	    "ms/call" , "ms/call" , "name" );
88 }
89 
flatprofline(np)90 flatprofline( np )
91     register nltype	*np;
92 {
93 
94     if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) {
95 	return;
96     }
97     actime += np -> time;
98     printf( "%5.1f %10.2f %8.2f" ,
99 	100 * np -> time / totime , actime / hz , np -> time / hz );
100     if ( np -> ncall != 0 ) {
101 	printf( " %8d %8.2f %8.2f  " , np -> ncall ,
102 	    1000 * np -> time / hz / np -> ncall ,
103 	    1000 * ( np -> time + np -> childtime ) / hz / np -> ncall );
104     } else {
105 	printf( " %8.8s %8.8s %8.8s  " , "" , "" , "" );
106     }
107     printname( np );
108     printf( "\n" );
109 }
110 
gprofheader()111 gprofheader()
112 {
113 
114     if ( bflag ) {
115 	printblurb( _PATH_CALLG_BLURB );
116     }
117     printf( "\ngranularity: each sample hit covers %d byte(s)" ,
118 	    (long) scale * sizeof(UNIT) );
119     if ( printtime > 0.0 ) {
120 	printf( " for %.2f%% of %.2f seconds\n\n" ,
121 		100.0/printtime , printtime / hz );
122     } else {
123 	printf( " no time propagated\n\n" );
124 	    /*
125 	     *	this doesn't hurt, since all the numerators will be 0.0
126 	     */
127 	printtime = 1.0;
128     }
129     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
130 	"" , "" , "" , "" , "called" , "total" , "parents");
131     printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" ,
132 	"index" , "%time" , "self" , "descendents" ,
133 	"called" , "self" , "name" , "index" );
134     printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s     %-8.8s\n" ,
135 	"" , "" , "" , "" , "called" , "total" , "children");
136     printf( "\n" );
137 }
138 
gprofline(np)139 gprofline( np )
140     register nltype	*np;
141 {
142     char	kirkbuffer[ BUFSIZ ];
143 
144     sprintf( kirkbuffer , "[%d]" , np -> index );
145     printf( "%-6.6s %5.1f %7.2f %11.2f" ,
146 	    kirkbuffer ,
147 	    100 * ( np -> propself + np -> propchild ) / printtime ,
148 	    np -> propself / hz ,
149 	    np -> propchild / hz );
150     if ( ( np -> ncall + np -> selfcalls ) != 0 ) {
151 	printf( " %7d" , np -> npropcall );
152 	if ( np -> selfcalls != 0 ) {
153 	    printf( "+%-7d " , np -> selfcalls );
154 	} else {
155 	    printf( " %7.7s " , "" );
156 	}
157     } else {
158 	printf( " %7.7s %7.7s " , "" , "" );
159     }
160     printname( np );
161     printf( "\n" );
162 }
163 
printgprof(timesortnlp)164 printgprof(timesortnlp)
165     nltype	**timesortnlp;
166 {
167     int		index;
168     nltype	*parentp;
169 
170 	/*
171 	 *	Print out the structured profiling list
172 	 */
173     gprofheader();
174     for ( index = 0 ; index < nname + ncycle ; index ++ ) {
175 	parentp = timesortnlp[ index ];
176 	if ( zflag == 0 &&
177 	     parentp -> ncall == 0 &&
178 	     parentp -> selfcalls == 0 &&
179 	     parentp -> propself == 0 &&
180 	     parentp -> propchild == 0 ) {
181 	    continue;
182 	}
183 	if ( ! parentp -> printflag ) {
184 	    continue;
185 	}
186 	if ( parentp -> name == 0 && parentp -> cycleno != 0 ) {
187 		/*
188 		 *	cycle header
189 		 */
190 	    printcycle( parentp );
191 	    printmembers( parentp );
192 	} else {
193 	    printparents( parentp );
194 	    gprofline( parentp );
195 	    printchildren( parentp );
196 	}
197 	printf( "\n" );
198 	printf( "-----------------------------------------------\n" );
199 	printf( "\n" );
200     }
201     free( timesortnlp );
202 }
203 
204     /*
205      *	sort by decreasing propagated time
206      *	if times are equal, but one is a cycle header,
207      *		say that's first (e.g. less, i.e. -1).
208      *	if one's name doesn't have an underscore and the other does,
209      *		say the one is first.
210      *	all else being equal, sort by names.
211      */
212 int
totalcmp(npp1,npp2)213 totalcmp( npp1 , npp2 )
214     nltype	**npp1;
215     nltype	**npp2;
216 {
217     register nltype	*np1 = *npp1;
218     register nltype	*np2 = *npp2;
219     double		diff;
220 
221     diff =    ( np1 -> propself + np1 -> propchild )
222 	    - ( np2 -> propself + np2 -> propchild );
223     if ( diff < 0.0 )
224 	    return 1;
225     if ( diff > 0.0 )
226 	    return -1;
227     if ( np1 -> name == 0 && np1 -> cycleno != 0 )
228 	return -1;
229     if ( np2 -> name == 0 && np2 -> cycleno != 0 )
230 	return 1;
231     if ( np1 -> name == 0 )
232 	return -1;
233     if ( np2 -> name == 0 )
234 	return 1;
235     if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' )
236 	return -1;
237     if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' )
238 	return 1;
239     if ( np1 -> ncall > np2 -> ncall )
240 	return -1;
241     if ( np1 -> ncall < np2 -> ncall )
242 	return 1;
243     return strcmp( np1 -> name , np2 -> name );
244 }
245 
printparents(childp)246 printparents( childp )
247     nltype	*childp;
248 {
249     nltype	*parentp;
250     arctype	*arcp;
251     nltype	*cycleheadp;
252 
253     if ( childp -> cyclehead != 0 ) {
254 	cycleheadp = childp -> cyclehead;
255     } else {
256 	cycleheadp = childp;
257     }
258     if ( childp -> parents == 0 ) {
259 	printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s     <spontaneous>\n" ,
260 		"" , "" , "" , "" , "" , "" );
261 	return;
262     }
263     sortparents( childp );
264     for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) {
265 	parentp = arcp -> arc_parentp;
266 	if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) ||
267 	     ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) {
268 		/*
269 		 *	selfcall or call among siblings
270 		 */
271 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
272 		    "" , "" , "" , "" ,
273 		    arcp -> arc_count , "" );
274 	    printname( parentp );
275 	    printf( "\n" );
276 	} else {
277 		/*
278 		 *	regular parent of child
279 		 */
280 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
281 		    "" , "" ,
282 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
283 		    arcp -> arc_count , cycleheadp -> npropcall );
284 	    printname( parentp );
285 	    printf( "\n" );
286 	}
287     }
288 }
289 
printchildren(parentp)290 printchildren( parentp )
291     nltype	*parentp;
292 {
293     nltype	*childp;
294     arctype	*arcp;
295 
296     sortchildren( parentp );
297     arcp = parentp -> children;
298     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
299 	childp = arcp -> arc_childp;
300 	if ( childp == parentp || ( arcp -> arc_flags & DEADARC ) ||
301 	    ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) {
302 		/*
303 		 *	self call or call to sibling
304 		 */
305 	    printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s     " ,
306 		    "" , "" , "" , "" , arcp -> arc_count , "" );
307 	    printname( childp );
308 	    printf( "\n" );
309 	} else {
310 		/*
311 		 *	regular child of parent
312 		 */
313 	    printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d     " ,
314 		    "" , "" ,
315 		    arcp -> arc_time / hz , arcp -> arc_childtime / hz ,
316 		    arcp -> arc_count , childp -> cyclehead -> npropcall );
317 	    printname( childp );
318 	    printf( "\n" );
319 	}
320     }
321 }
322 
printname(selfp)323 printname( selfp )
324     nltype	*selfp;
325 {
326 
327     if ( selfp -> name != 0 ) {
328 	printf( "%s" , selfp -> name );
329 #	ifdef DEBUG
330 	    if ( debug & DFNDEBUG ) {
331 		printf( "{%d} " , selfp -> toporder );
332 	    }
333 	    if ( debug & PROPDEBUG ) {
334 		printf( "%5.2f%% " , selfp -> propfraction );
335 	    }
336 #	endif DEBUG
337     }
338     if ( selfp -> cycleno != 0 ) {
339 	printf( " <cycle %d>" , selfp -> cycleno );
340     }
341     if ( selfp -> index != 0 ) {
342 	if ( selfp -> printflag ) {
343 	    printf( " [%d]" , selfp -> index );
344 	} else {
345 	    printf( " (%d)" , selfp -> index );
346 	}
347     }
348 }
349 
sortchildren(parentp)350 sortchildren( parentp )
351     nltype	*parentp;
352 {
353     arctype	*arcp;
354     arctype	*detachedp;
355     arctype	sorted;
356     arctype	*prevp;
357 
358 	/*
359 	 *	unlink children from parent,
360 	 *	then insertion sort back on to sorted's children.
361 	 *	    *arcp	the arc you have detached and are inserting.
362 	 *	    *detachedp	the rest of the arcs to be sorted.
363 	 *	    sorted	arc list onto which you insertion sort.
364 	 *	    *prevp	arc before the arc you are comparing.
365 	 */
366     sorted.arc_childlist = 0;
367     for (  (arcp = parentp -> children)&&(detachedp = arcp -> arc_childlist);
368 	    arcp ;
369 	   (arcp = detachedp)&&(detachedp = detachedp -> arc_childlist)) {
370 	    /*
371 	     *	consider *arcp as disconnected
372 	     *	insert it into sorted
373 	     */
374 	for (   prevp = &sorted ;
375 		prevp -> arc_childlist ;
376 		prevp = prevp -> arc_childlist ) {
377 	    if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) {
378 		break;
379 	    }
380 	}
381 	arcp -> arc_childlist = prevp -> arc_childlist;
382 	prevp -> arc_childlist = arcp;
383     }
384 	/*
385 	 *	reattach sorted children to parent
386 	 */
387     parentp -> children = sorted.arc_childlist;
388 }
389 
sortparents(childp)390 sortparents( childp )
391     nltype	*childp;
392 {
393     arctype	*arcp;
394     arctype	*detachedp;
395     arctype	sorted;
396     arctype	*prevp;
397 
398 	/*
399 	 *	unlink parents from child,
400 	 *	then insertion sort back on to sorted's parents.
401 	 *	    *arcp	the arc you have detached and are inserting.
402 	 *	    *detachedp	the rest of the arcs to be sorted.
403 	 *	    sorted	arc list onto which you insertion sort.
404 	 *	    *prevp	arc before the arc you are comparing.
405 	 */
406     sorted.arc_parentlist = 0;
407     for (  (arcp = childp -> parents)&&(detachedp = arcp -> arc_parentlist);
408 	    arcp ;
409 	   (arcp = detachedp)&&(detachedp = detachedp -> arc_parentlist)) {
410 	    /*
411 	     *	consider *arcp as disconnected
412 	     *	insert it into sorted
413 	     */
414 	for (   prevp = &sorted ;
415 		prevp -> arc_parentlist ;
416 		prevp = prevp -> arc_parentlist ) {
417 	    if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) {
418 		break;
419 	    }
420 	}
421 	arcp -> arc_parentlist = prevp -> arc_parentlist;
422 	prevp -> arc_parentlist = arcp;
423     }
424 	/*
425 	 *	reattach sorted arcs to child
426 	 */
427     childp -> parents = sorted.arc_parentlist;
428 }
429 
430     /*
431      *	print a cycle header
432      */
printcycle(cyclep)433 printcycle( cyclep )
434     nltype	*cyclep;
435 {
436     char	kirkbuffer[ BUFSIZ ];
437 
438     sprintf( kirkbuffer , "[%d]" , cyclep -> index );
439     printf( "%-6.6s %5.1f %7.2f %11.2f %7d" ,
440 	    kirkbuffer ,
441 	    100 * ( cyclep -> propself + cyclep -> propchild ) / printtime ,
442 	    cyclep -> propself / hz ,
443 	    cyclep -> propchild / hz ,
444 	    cyclep -> npropcall );
445     if ( cyclep -> selfcalls != 0 ) {
446 	printf( "+%-7d" , cyclep -> selfcalls );
447     } else {
448 	printf( " %7.7s" , "" );
449     }
450     printf( " <cycle %d as a whole>\t[%d]\n" ,
451 	    cyclep -> cycleno , cyclep -> index );
452 }
453 
454     /*
455      *	print the members of a cycle
456      */
printmembers(cyclep)457 printmembers( cyclep )
458     nltype	*cyclep;
459 {
460     nltype	*memberp;
461 
462     sortmembers( cyclep );
463     for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) {
464 	printf( "%6.6s %5.5s %7.2f %11.2f %7d" ,
465 		"" , "" , memberp -> propself / hz , memberp -> propchild / hz ,
466 		memberp -> npropcall );
467 	if ( memberp -> selfcalls != 0 ) {
468 	    printf( "+%-7d" , memberp -> selfcalls );
469 	} else {
470 	    printf( " %7.7s" , "" );
471 	}
472 	printf( "     " );
473 	printname( memberp );
474 	printf( "\n" );
475     }
476 }
477 
478     /*
479      *	sort members of a cycle
480      */
sortmembers(cyclep)481 sortmembers( cyclep )
482     nltype	*cyclep;
483 {
484     nltype	*todo;
485     nltype	*doing;
486     nltype	*prev;
487 
488 	/*
489 	 *	detach cycle members from cyclehead,
490 	 *	and insertion sort them back on.
491 	 */
492     todo = cyclep -> cnext;
493     cyclep -> cnext = 0;
494     for (  (doing = todo)&&(todo = doing -> cnext);
495 	    doing ;
496 	   (doing = todo )&&(todo = doing -> cnext )){
497 	for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) {
498 	    if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) {
499 		break;
500 	    }
501 	}
502 	doing -> cnext = prev -> cnext;
503 	prev -> cnext = doing;
504     }
505 }
506 
507     /*
508      *	major sort is on propself + propchild,
509      *	next is sort on ncalls + selfcalls.
510      */
511 int
membercmp(this,that)512 membercmp( this , that )
513     nltype	*this;
514     nltype	*that;
515 {
516     double	thistime = this -> propself + this -> propchild;
517     double	thattime = that -> propself + that -> propchild;
518     long	thiscalls = this -> ncall + this -> selfcalls;
519     long	thatcalls = that -> ncall + that -> selfcalls;
520 
521     if ( thistime > thattime ) {
522 	return GREATERTHAN;
523     }
524     if ( thistime < thattime ) {
525 	return LESSTHAN;
526     }
527     if ( thiscalls > thatcalls ) {
528 	return GREATERTHAN;
529     }
530     if ( thiscalls < thatcalls ) {
531 	return LESSTHAN;
532     }
533     return EQUALTO;
534 }
535     /*
536      *	compare two arcs to/from the same child/parent.
537      *	- if one arc is a self arc, it's least.
538      *	- if one arc is within a cycle, it's less than.
539      *	- if both arcs are within a cycle, compare arc counts.
540      *	- if neither arc is within a cycle, compare with
541      *		arc_time + arc_childtime as major key
542      *		arc count as minor key
543      */
544 int
arccmp(thisp,thatp)545 arccmp( thisp , thatp )
546     arctype	*thisp;
547     arctype	*thatp;
548 {
549     nltype	*thisparentp = thisp -> arc_parentp;
550     nltype	*thischildp = thisp -> arc_childp;
551     nltype	*thatparentp = thatp -> arc_parentp;
552     nltype	*thatchildp = thatp -> arc_childp;
553     double	thistime;
554     double	thattime;
555 
556 #   ifdef DEBUG
557 	if ( debug & TIMEDEBUG ) {
558 	    printf( "[arccmp] " );
559 	    printname( thisparentp );
560 	    printf( " calls " );
561 	    printname ( thischildp );
562 	    printf( " %f + %f %d/%d\n" ,
563 		    thisp -> arc_time , thisp -> arc_childtime ,
564 		    thisp -> arc_count , thischildp -> ncall );
565 	    printf( "[arccmp] " );
566 	    printname( thatparentp );
567 	    printf( " calls " );
568 	    printname( thatchildp );
569 	    printf( " %f + %f %d/%d\n" ,
570 		    thatp -> arc_time , thatp -> arc_childtime ,
571 		    thatp -> arc_count , thatchildp -> ncall );
572 	    printf( "\n" );
573 	}
574 #   endif DEBUG
575     if ( thisparentp == thischildp ) {
576 	    /* this is a self call */
577 	return LESSTHAN;
578     }
579     if ( thatparentp == thatchildp ) {
580 	    /* that is a self call */
581 	return GREATERTHAN;
582     }
583     if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 &&
584 	thisparentp -> cycleno == thischildp -> cycleno ) {
585 	    /* this is a call within a cycle */
586 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
587 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
588 		/* that is a call within the cycle, too */
589 	    if ( thisp -> arc_count < thatp -> arc_count ) {
590 		return LESSTHAN;
591 	    }
592 	    if ( thisp -> arc_count > thatp -> arc_count ) {
593 		return GREATERTHAN;
594 	    }
595 	    return EQUALTO;
596 	} else {
597 		/* that isn't a call within the cycle */
598 	    return LESSTHAN;
599 	}
600     } else {
601 	    /* this isn't a call within a cycle */
602 	if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 &&
603 	    thatparentp -> cycleno == thatchildp -> cycleno ) {
604 		/* that is a call within a cycle */
605 	    return GREATERTHAN;
606 	} else {
607 		/* neither is a call within a cycle */
608 	    thistime = thisp -> arc_time + thisp -> arc_childtime;
609 	    thattime = thatp -> arc_time + thatp -> arc_childtime;
610 	    if ( thistime < thattime )
611 		return LESSTHAN;
612 	    if ( thistime > thattime )
613 		return GREATERTHAN;
614 	    if ( thisp -> arc_count < thatp -> arc_count )
615 		return LESSTHAN;
616 	    if ( thisp -> arc_count > thatp -> arc_count )
617 		return GREATERTHAN;
618 	    return EQUALTO;
619 	}
620     }
621 }
622 
printblurb(blurbname)623 printblurb( blurbname )
624     char	*blurbname;
625 {
626     FILE	*blurbfile;
627     int		input;
628 
629     blurbfile = fopen( blurbname , "r" );
630     if ( blurbfile == NULL ) {
631 	perror( blurbname );
632 	return;
633     }
634     while ( ( input = getc( blurbfile ) ) != EOF ) {
635 	putchar( input );
636     }
637     fclose( blurbfile );
638 }
639 
640 int
namecmp(npp1,npp2)641 namecmp( npp1 , npp2 )
642     nltype **npp1, **npp2;
643 {
644     return( strcmp( (*npp1) -> name , (*npp2) -> name ) );
645 }
646 
printindex()647 printindex()
648 {
649     nltype		**namesortnlp;
650     register nltype	*nlp;
651     int			index, nnames, todo, i, j;
652     char		peterbuffer[ BUFSIZ ];
653 
654 	/*
655 	 *	Now, sort regular function name alphbetically
656 	 *	to create an index.
657 	 */
658     namesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) );
659     if ( namesortnlp == (nltype **) 0 ) {
660 	fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami );
661     }
662     for ( index = 0 , nnames = 0 ; index < nname ; index++ ) {
663 	if ( zflag == 0 && nl[index].ncall == 0 && nl[index].time == 0 )
664 		continue;
665 	namesortnlp[nnames++] = &nl[index];
666     }
667     qsort( namesortnlp , nnames , sizeof(nltype *) , namecmp );
668     for ( index = 1 , todo = nnames ; index <= ncycle ; index++ ) {
669 	namesortnlp[todo++] = &cyclenl[index];
670     }
671     printf( "\f\nIndex by function name\n\n" );
672     index = ( todo + 2 ) / 3;
673     for ( i = 0; i < index ; i++ ) {
674 	for ( j = i; j < todo ; j += index ) {
675 	    nlp = namesortnlp[ j ];
676 	    if ( nlp -> printflag ) {
677 		sprintf( peterbuffer , "[%d]" , nlp -> index );
678 	    } else {
679 		sprintf( peterbuffer , "(%d)" , nlp -> index );
680 	    }
681 	    if ( j < nnames ) {
682 		printf( "%6.6s %-19.19s" , peterbuffer , nlp -> name );
683 	    } else {
684 		printf( "%6.6s " , peterbuffer );
685 		sprintf( peterbuffer , "<cycle %d>" , nlp -> cycleno );
686 		printf( "%-19.19s" , peterbuffer );
687 	    }
688 	}
689 	printf( "\n" );
690     }
691     free( namesortnlp );
692 }
693