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

Annotation of src/usr.bin/gprof/dfn.c, Revision 1.3

1.3     ! mickey      1: /*     $OpenBSD: dfn.c,v 1.2 1996/06/26 05:33:49 deraadt Exp $ */
1.1       deraadt     2: /*     $NetBSD: dfn.c,v 1.5 1995/04/19 07:15:56 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[] = "@(#)dfn.c      8.1 (Berkeley) 6/6/93";
                     40: #else
1.3     ! mickey     41: static char rcsid[] = "$OpenBSD: dfn.c,v 1.2 1996/06/26 05:33:49 deraadt Exp $";
1.1       deraadt    42: #endif
                     43: #endif /* not lint */
                     44:
                     45: #include <stdio.h>
                     46: #include "gprof.h"
                     47:
                     48: #define        DFN_DEPTH       100
                     49: struct dfnstruct {
                     50:     nltype     *nlentryp;
                     51:     int                cycletop;
                     52: };
                     53: typedef struct dfnstruct       dfntype;
                     54:
                     55: dfntype        dfn_stack[ DFN_DEPTH ];
                     56: int    dfn_depth;
                     57:
                     58: int    dfn_counter;
                     59:
1.3     ! mickey     60: void
1.1       deraadt    61: dfn_init()
                     62: {
                     63:
                     64:     dfn_depth = 0;
                     65:     dfn_counter = DFN_NAN;
                     66: }
                     67:
                     68:     /*
                     69:      * given this parent, depth first number its children.
                     70:      */
1.3     ! mickey     71: void
1.1       deraadt    72: dfn( parentp )
                     73:     nltype     *parentp;
                     74: {
                     75:     arctype    *arcp;
                     76:
                     77: #   ifdef DEBUG
                     78:        if ( debug & DFNDEBUG ) {
                     79:            printf( "[dfn] dfn(" );
                     80:            printname( parentp );
                     81:            printf( ")\n" );
                     82:        }
                     83: #   endif DEBUG
                     84:        /*
                     85:         *      if we're already numbered, no need to look any furthur.
                     86:         */
                     87:     if ( dfn_numbered( parentp ) ) {
                     88:        return;
                     89:     }
                     90:        /*
                     91:         *      if we're already busy, must be a cycle
                     92:         */
                     93:     if ( dfn_busy( parentp ) ) {
                     94:        dfn_findcycle( parentp );
                     95:        return;
                     96:     }
                     97:        /*
                     98:         *      visit yourself before your children
                     99:         */
                    100:     dfn_pre_visit( parentp );
                    101:        /*
                    102:         *      visit children
                    103:         */
                    104:     for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
                    105:            if ( arcp -> arc_flags & DEADARC )
                    106:                continue;
                    107:            dfn( arcp -> arc_childp );
                    108:     }
                    109:        /*
                    110:         *      visit yourself after your children
                    111:         */
                    112:     dfn_post_visit( parentp );
                    113: }
                    114:
                    115:     /*
                    116:      * push a parent onto the stack and mark it busy
                    117:      */
1.3     ! mickey    118: void
1.1       deraadt   119: dfn_pre_visit( parentp )
                    120:     nltype     *parentp;
                    121: {
                    122:
                    123:     dfn_depth += 1;
1.3     ! mickey    124:     if ( dfn_depth >= DFN_DEPTH )
        !           125:        errx(1, "[dfn] out of my depth (dfn_stack overflow)" );
1.1       deraadt   126:     dfn_stack[ dfn_depth ].nlentryp = parentp;
                    127:     dfn_stack[ dfn_depth ].cycletop = dfn_depth;
                    128:     parentp -> toporder = DFN_BUSY;
                    129: #   ifdef DEBUG
                    130:        if ( debug & DFNDEBUG ) {
                    131:            printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth );
                    132:            printname( parentp );
                    133:            printf( "\n" );
                    134:        }
                    135: #   endif DEBUG
                    136: }
                    137:
                    138:     /*
                    139:      * are we already numbered?
                    140:      */
                    141: bool
                    142: dfn_numbered( childp )
                    143:     nltype     *childp;
                    144: {
                    145:
                    146:     return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
                    147: }
                    148:
                    149:     /*
                    150:      * are we already busy?
                    151:      */
                    152: bool
                    153: dfn_busy( childp )
                    154:     nltype     *childp;
                    155: {
                    156:
                    157:     if ( childp -> toporder == DFN_NAN ) {
                    158:        return FALSE;
                    159:     }
                    160:     return TRUE;
                    161: }
                    162:
                    163:     /*
                    164:      * MISSING: an explanation
                    165:      */
1.3     ! mickey    166: void
1.1       deraadt   167: dfn_findcycle( childp )
                    168:     nltype     *childp;
                    169: {
                    170:     int                cycletop;
                    171:     nltype     *cycleheadp;
                    172:     nltype     *tailp;
                    173:     int                index;
                    174:
                    175:     for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) {
                    176:        cycleheadp = dfn_stack[ cycletop ].nlentryp;
                    177:        if ( childp == cycleheadp ) {
                    178:            break;
                    179:        }
                    180:        if ( childp -> cyclehead != childp &&
                    181:            childp -> cyclehead == cycleheadp ) {
                    182:            break;
                    183:        }
                    184:     }
1.3     ! mickey    185:     if ( cycletop <= 0 )
        !           186:        errx( 1, "[dfn_findcycle] couldn't find head of cycle");
1.1       deraadt   187: #   ifdef DEBUG
                    188:        if ( debug & DFNDEBUG ) {
                    189:            printf( "[dfn_findcycle] dfn_depth %d cycletop %d " ,
                    190:                    dfn_depth , cycletop  );
                    191:            printname( cycleheadp );
                    192:            printf( "\n" );
                    193:        }
                    194: #   endif DEBUG
                    195:     if ( cycletop == dfn_depth ) {
                    196:            /*
                    197:             *  this is previous function, e.g. this calls itself
                    198:             *  sort of boring
                    199:             */
                    200:        dfn_self_cycle( childp );
                    201:     } else {
                    202:            /*
                    203:             *  glom intervening functions that aren't already
                    204:             *  glommed into this cycle.
                    205:             *  things have been glommed when their cyclehead field
                    206:             *  points to the head of the cycle they are glommed into.
                    207:             */
                    208:        for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) {
                    209:            /* void: chase down to tail of things already glommed */
                    210: #          ifdef DEBUG
                    211:                if ( debug & DFNDEBUG ) {
                    212:                    printf( "[dfn_findcycle] tail " );
                    213:                    printname( tailp );
                    214:                    printf( "\n" );
                    215:                }
                    216: #          endif DEBUG
                    217:        }
                    218:            /*
                    219:             *  if what we think is the top of the cycle
                    220:             *  has a cyclehead field, then it's not really the
                    221:             *  head of the cycle, which is really what we want
                    222:             */
                    223:        if ( cycleheadp -> cyclehead != cycleheadp ) {
                    224:            cycleheadp = cycleheadp -> cyclehead;
                    225: #          ifdef DEBUG
                    226:                if ( debug & DFNDEBUG ) {
                    227:                    printf( "[dfn_findcycle] new cyclehead " );
                    228:                    printname( cycleheadp );
                    229:                    printf( "\n" );
                    230:                }
                    231: #          endif DEBUG
                    232:        }
                    233:        for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) {
                    234:            childp = dfn_stack[ index ].nlentryp;
                    235:            if ( childp -> cyclehead == childp ) {
                    236:                    /*
                    237:                     *  not yet glommed anywhere, glom it
                    238:                     *  and fix any children it has glommed
                    239:                     */
                    240:                tailp -> cnext = childp;
                    241:                childp -> cyclehead = cycleheadp;
                    242: #              ifdef DEBUG
                    243:                    if ( debug & DFNDEBUG ) {
                    244:                        printf( "[dfn_findcycle] glomming " );
                    245:                        printname( childp );
                    246:                        printf( " onto " );
                    247:                        printname( cycleheadp );
                    248:                        printf( "\n" );
                    249:                    }
                    250: #              endif DEBUG
                    251:                for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) {
                    252:                    tailp -> cnext -> cyclehead = cycleheadp;
                    253: #                  ifdef DEBUG
                    254:                        if ( debug & DFNDEBUG ) {
                    255:                            printf( "[dfn_findcycle] and its tail " );
                    256:                            printname( tailp -> cnext );
                    257:                            printf( " onto " );
                    258:                            printname( cycleheadp );
                    259:                            printf( "\n" );
                    260:                        }
                    261: #                  endif DEBUG
                    262:                }
1.3     ! mickey    263:            } else if ( childp -> cyclehead != cycleheadp /* firewall */ )
        !           264:                warnx("[dfn_busy] glommed, but not to cyclehead");
1.1       deraadt   265:        }
                    266:     }
                    267: }
                    268:
                    269:     /*
                    270:      * deal with self-cycles
                    271:      * for lint: ARGSUSED
                    272:      */
1.3     ! mickey    273: void
1.1       deraadt   274: dfn_self_cycle( parentp )
                    275:     nltype     *parentp;
                    276: {
                    277:        /*
                    278:         *      since we are taking out self-cycles elsewhere
                    279:         *      no need for the special case, here.
                    280:         */
                    281: #   ifdef DEBUG
                    282:        if ( debug & DFNDEBUG ) {
                    283:            printf( "[dfn_self_cycle] " );
                    284:            printname( parentp );
                    285:            printf( "\n" );
                    286:        }
                    287: #   endif DEBUG
                    288: }
                    289:
                    290:     /*
                    291:      * visit a node after all its children
                    292:      * [MISSING: an explanation]
                    293:      * and pop it off the stack
                    294:      */
1.3     ! mickey    295: void
1.1       deraadt   296: dfn_post_visit( parentp )
                    297:     nltype     *parentp;
                    298: {
                    299:     nltype     *memberp;
                    300:
                    301: #   ifdef DEBUG
                    302:        if ( debug & DFNDEBUG ) {
                    303:            printf( "[dfn_post_visit]\t%d: " , dfn_depth );
                    304:            printname( parentp );
                    305:            printf( "\n" );
                    306:        }
                    307: #   endif DEBUG
                    308:        /*
                    309:         *      number functions and things in their cycles
                    310:         *      unless the function is itself part of a cycle
                    311:         */
                    312:     if ( parentp -> cyclehead == parentp ) {
                    313:        dfn_counter += 1;
                    314:        for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) {
                    315:            memberp -> toporder = dfn_counter;
                    316: #          ifdef DEBUG
                    317:                if ( debug & DFNDEBUG ) {
                    318:                    printf( "[dfn_post_visit]\t\tmember " );
                    319:                    printname( memberp );
                    320:                    printf( " -> toporder = %d\n" , dfn_counter );
                    321:                }
                    322: #          endif DEBUG
                    323:        }
                    324:     } else {
                    325: #      ifdef DEBUG
                    326:            if ( debug & DFNDEBUG ) {
                    327:                printf( "[dfn_post_visit]\t\tis part of a cycle\n" );
                    328:            }
                    329: #      endif DEBUG
                    330:     }
                    331:     dfn_depth -= 1;
                    332: }