[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     ! 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: }