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