[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.3

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