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