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