[BACK]Return to printgprof.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / gprof

Annotation of src/usr.bin/gprof/printgprof.c, Revision 1.1.1.1

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