home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / gprof / printgprof.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-12  |  19.1 KB  |  719 lines

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