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