1*4509Speter #ifndef lint 2*4509Speter static char *sccsid = "@(#)dfn.c 1.1 (Berkeley) 10/15/81"; 3*4509Speter #endif lint 4*4509Speter 5*4509Speter #include <stdio.h> 6*4509Speter #include "dprof.h" 7*4509Speter 8*4509Speter #define DFN_DEPTH 100 9*4509Speter struct dfnstruct { 10*4509Speter nltype *nlentryp; 11*4509Speter int cycletop; 12*4509Speter }; 13*4509Speter typedef struct dfnstruct dfntype; 14*4509Speter 15*4509Speter dfntype dfn_stack[ DFN_DEPTH ]; 16*4509Speter int dfn_depth = 0; 17*4509Speter 18*4509Speter int dfn_counter = 0; 19*4509Speter 20*4509Speter /* 21*4509Speter * given this parent, depth first number its children. 22*4509Speter */ 23*4509Speter dfn( parentp ) 24*4509Speter nltype *parentp; 25*4509Speter { 26*4509Speter arctype *arcp; 27*4509Speter 28*4509Speter # ifdef DEBUG 29*4509Speter if ( debug & DFNDEBUG ) { 30*4509Speter printf( "[dfn] dfn(" ); 31*4509Speter printname( parentp ); 32*4509Speter printf( ")\n" ); 33*4509Speter } 34*4509Speter # endif DEBUG 35*4509Speter /* 36*4509Speter * if we're already numbered, no need to look any furthur. 37*4509Speter */ 38*4509Speter if ( dfn_numbered( parentp ) ) { 39*4509Speter return; 40*4509Speter } 41*4509Speter /* 42*4509Speter * if we're already busy, must be a cycle 43*4509Speter */ 44*4509Speter if ( dfn_busy( parentp ) ) { 45*4509Speter dfn_findcycle( parentp ); 46*4509Speter return; 47*4509Speter } 48*4509Speter /* 49*4509Speter * visit yourself before your children 50*4509Speter */ 51*4509Speter dfn_pre_visit( parentp ); 52*4509Speter /* 53*4509Speter * visit children 54*4509Speter */ 55*4509Speter for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 56*4509Speter dfn( arcp -> arc_childp ); 57*4509Speter } 58*4509Speter /* 59*4509Speter * visit yourself after your children 60*4509Speter */ 61*4509Speter dfn_post_visit( parentp ); 62*4509Speter } 63*4509Speter 64*4509Speter /* 65*4509Speter * push a parent onto the stack and mark it busy 66*4509Speter */ 67*4509Speter dfn_pre_visit( parentp ) 68*4509Speter nltype *parentp; 69*4509Speter { 70*4509Speter 71*4509Speter dfn_depth += 1; 72*4509Speter if ( dfn_depth >= DFN_DEPTH ) { 73*4509Speter fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" ); 74*4509Speter exit( 1 ); 75*4509Speter } 76*4509Speter dfn_stack[ dfn_depth ].nlentryp = parentp; 77*4509Speter dfn_stack[ dfn_depth ].cycletop = dfn_depth; 78*4509Speter parentp -> toporder = DFN_BUSY; 79*4509Speter # ifdef DEBUG 80*4509Speter if ( debug & DFNDEBUG ) { 81*4509Speter printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth ); 82*4509Speter printname( parentp ); 83*4509Speter printf( "\n" ); 84*4509Speter } 85*4509Speter # endif DEBUG 86*4509Speter } 87*4509Speter 88*4509Speter /* 89*4509Speter * are we already numbered? 90*4509Speter */ 91*4509Speter bool 92*4509Speter dfn_numbered( childp ) 93*4509Speter nltype *childp; 94*4509Speter { 95*4509Speter 96*4509Speter return ( childp -> toporder != 0 && childp -> toporder != DFN_BUSY ); 97*4509Speter } 98*4509Speter 99*4509Speter /* 100*4509Speter * are we already busy? 101*4509Speter */ 102*4509Speter bool 103*4509Speter dfn_busy( childp ) 104*4509Speter nltype *childp; 105*4509Speter { 106*4509Speter 107*4509Speter if ( childp -> toporder == 0 ) { 108*4509Speter return FALSE; 109*4509Speter } 110*4509Speter return TRUE; 111*4509Speter } 112*4509Speter 113*4509Speter /* 114*4509Speter * MISSING: an explanation 115*4509Speter */ 116*4509Speter dfn_findcycle( childp ) 117*4509Speter nltype *childp; 118*4509Speter { 119*4509Speter int cycletop; 120*4509Speter nltype *cycleheadp; 121*4509Speter nltype *tailp; 122*4509Speter int index; 123*4509Speter 124*4509Speter for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) { 125*4509Speter cycleheadp = dfn_stack[ cycletop ].nlentryp; 126*4509Speter if ( childp == cycleheadp ) { 127*4509Speter break; 128*4509Speter } 129*4509Speter if ( childp -> cyclehead != childp && 130*4509Speter childp -> cyclehead == cycleheadp ) { 131*4509Speter break; 132*4509Speter } 133*4509Speter } 134*4509Speter if ( cycletop <= 0 ) { 135*4509Speter fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" ); 136*4509Speter exit( 1 ); 137*4509Speter } 138*4509Speter # ifdef DEBUG 139*4509Speter if ( debug & DFNDEBUG ) { 140*4509Speter printf( "[dfn_findcycle] dfn_depth %d cycletop %d " , 141*4509Speter dfn_depth , cycletop ); 142*4509Speter printname( cycleheadp ); 143*4509Speter printf( "\n" ); 144*4509Speter } 145*4509Speter # endif DEBUG 146*4509Speter if ( cycletop == dfn_depth ) { 147*4509Speter /* 148*4509Speter * this is previous function, e.g. this calls itself 149*4509Speter * sort of boring 150*4509Speter */ 151*4509Speter dfn_self_cycle( childp ); 152*4509Speter } else { 153*4509Speter /* 154*4509Speter * glom intervening functions that aren't already 155*4509Speter * glommed into this cycle. 156*4509Speter * things have been glommed when their cyclehead field 157*4509Speter * points to the head of the cycle they are glommed into. 158*4509Speter */ 159*4509Speter for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) { 160*4509Speter /* void: chase down to tail of things already glommed */ 161*4509Speter # ifdef DEBUG 162*4509Speter if ( debug & DFNDEBUG ) { 163*4509Speter printf( "[dfn_findcycle] tail " ); 164*4509Speter printname( tailp ); 165*4509Speter printf( "\n" ); 166*4509Speter } 167*4509Speter # endif DEBUG 168*4509Speter } 169*4509Speter /* 170*4509Speter * if what we think is the top of the cycle 171*4509Speter * has a cyclehead field, then it's not really the 172*4509Speter * head of the cycle, which is really what we want 173*4509Speter */ 174*4509Speter if ( cycleheadp -> cyclehead != cycleheadp ) { 175*4509Speter cycleheadp = cycleheadp -> cyclehead; 176*4509Speter # ifdef DEBUG 177*4509Speter if ( debug & DFNDEBUG ) { 178*4509Speter printf( "[dfn_findcycle] new cyclehead " ); 179*4509Speter printname( cycleheadp ); 180*4509Speter printf( "\n" ); 181*4509Speter } 182*4509Speter # endif DEBUG 183*4509Speter } 184*4509Speter for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) { 185*4509Speter childp = dfn_stack[ index ].nlentryp; 186*4509Speter if ( childp -> cyclehead == childp ) { 187*4509Speter /* 188*4509Speter * not yet glommed anywhere, glom it 189*4509Speter * and fix any children it has glommed 190*4509Speter */ 191*4509Speter tailp -> cnext = childp; 192*4509Speter childp -> cyclehead = cycleheadp; 193*4509Speter # ifdef DEBUG 194*4509Speter if ( debug & DFNDEBUG ) { 195*4509Speter printf( "[dfn_findcycle] glomming " ); 196*4509Speter printname( childp ); 197*4509Speter printf( " onto " ); 198*4509Speter printname( cycleheadp ); 199*4509Speter printf( "\n" ); 200*4509Speter } 201*4509Speter # endif DEBUG 202*4509Speter for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) { 203*4509Speter tailp -> cnext -> cyclehead = cycleheadp; 204*4509Speter # ifdef DEBUG 205*4509Speter if ( debug & DFNDEBUG ) { 206*4509Speter printf( "[dfn_findcycle] and its tail " ); 207*4509Speter printname( tailp -> cnext ); 208*4509Speter printf( " onto " ); 209*4509Speter printname( cycleheadp ); 210*4509Speter printf( "\n" ); 211*4509Speter } 212*4509Speter # endif DEBUG 213*4509Speter } 214*4509Speter } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) { 215*4509Speter fprintf( stderr , 216*4509Speter "[dfn_busy] glommed, but not to cyclehead\n" ); 217*4509Speter } 218*4509Speter } 219*4509Speter } 220*4509Speter } 221*4509Speter 222*4509Speter /* 223*4509Speter * deal with self-cycles 224*4509Speter * for lint: ARGSUSED 225*4509Speter */ 226*4509Speter dfn_self_cycle( parentp ) 227*4509Speter nltype *parentp; 228*4509Speter { 229*4509Speter /* 230*4509Speter * since we are taking out self-cycles elsewhere 231*4509Speter * no need for the special case, here. 232*4509Speter */ 233*4509Speter # ifdef DEBUG 234*4509Speter if ( debug & DFNDEBUG ) { 235*4509Speter printf( "[dfn_self_cycle] " ); 236*4509Speter printname( parentp ); 237*4509Speter printf( "\n" ); 238*4509Speter } 239*4509Speter # endif DEBUG 240*4509Speter } 241*4509Speter 242*4509Speter /* 243*4509Speter * visit a node after all its children 244*4509Speter * [MISSING: an explanation] 245*4509Speter * and pop it off the stack 246*4509Speter */ 247*4509Speter dfn_post_visit( parentp ) 248*4509Speter nltype *parentp; 249*4509Speter { 250*4509Speter nltype *memberp; 251*4509Speter 252*4509Speter # ifdef DEBUG 253*4509Speter if ( debug & DFNDEBUG ) { 254*4509Speter printf( "[dfn_post_visit]\t%d: " , dfn_depth ); 255*4509Speter printname( parentp ); 256*4509Speter printf( "\n" ); 257*4509Speter } 258*4509Speter # endif DEBUG 259*4509Speter /* 260*4509Speter * number functions and things in their cycles 261*4509Speter * unless the function is itself part of a cycle 262*4509Speter */ 263*4509Speter if ( parentp -> cyclehead == parentp ) { 264*4509Speter dfn_counter += 1; 265*4509Speter for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) { 266*4509Speter memberp -> toporder = dfn_counter; 267*4509Speter # ifdef DEBUG 268*4509Speter if ( debug & DFNDEBUG ) { 269*4509Speter printf( "[dfn_post_visit]\t\tmember " ); 270*4509Speter printname( memberp ); 271*4509Speter printf( " -> toporder = %d\n" , dfn_counter ); 272*4509Speter } 273*4509Speter # endif DEBUG 274*4509Speter } 275*4509Speter } else { 276*4509Speter # ifdef DEBUG 277*4509Speter if ( debug & DFNDEBUG ) { 278*4509Speter printf( "[dfn_post_visit]\t\tis part of a cycle\n" ); 279*4509Speter } 280*4509Speter # endif DEBUG 281*4509Speter } 282*4509Speter dfn_depth -= 1; 283*4509Speter } 284