14509Speter #ifndef lint 2*10284Speter static char *sccsid = "@(#)dfn.c 1.3 (Berkeley) 01/15/83"; 34509Speter #endif lint 44509Speter 54509Speter #include <stdio.h> 64560Speter #include "gprof.h" 74509Speter 84509Speter #define DFN_DEPTH 100 94509Speter struct dfnstruct { 104509Speter nltype *nlentryp; 114509Speter int cycletop; 124509Speter }; 134509Speter typedef struct dfnstruct dfntype; 144509Speter 154509Speter dfntype dfn_stack[ DFN_DEPTH ]; 164509Speter int dfn_depth = 0; 174509Speter 18*10284Speter int dfn_counter = DFN_NAN; 194509Speter 204509Speter /* 214509Speter * given this parent, depth first number its children. 224509Speter */ 234509Speter dfn( parentp ) 244509Speter nltype *parentp; 254509Speter { 264509Speter arctype *arcp; 274509Speter 284509Speter # ifdef DEBUG 294509Speter if ( debug & DFNDEBUG ) { 304509Speter printf( "[dfn] dfn(" ); 314509Speter printname( parentp ); 324509Speter printf( ")\n" ); 334509Speter } 344509Speter # endif DEBUG 354509Speter /* 364509Speter * if we're already numbered, no need to look any furthur. 374509Speter */ 384509Speter if ( dfn_numbered( parentp ) ) { 394509Speter return; 404509Speter } 414509Speter /* 424509Speter * if we're already busy, must be a cycle 434509Speter */ 444509Speter if ( dfn_busy( parentp ) ) { 454509Speter dfn_findcycle( parentp ); 464509Speter return; 474509Speter } 484509Speter /* 494509Speter * visit yourself before your children 504509Speter */ 514509Speter dfn_pre_visit( parentp ); 524509Speter /* 534509Speter * visit children 544509Speter */ 554509Speter for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 564509Speter dfn( arcp -> arc_childp ); 574509Speter } 584509Speter /* 594509Speter * visit yourself after your children 604509Speter */ 614509Speter dfn_post_visit( parentp ); 624509Speter } 634509Speter 644509Speter /* 654509Speter * push a parent onto the stack and mark it busy 664509Speter */ 674509Speter dfn_pre_visit( parentp ) 684509Speter nltype *parentp; 694509Speter { 704509Speter 714509Speter dfn_depth += 1; 724509Speter if ( dfn_depth >= DFN_DEPTH ) { 734509Speter fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" ); 744509Speter exit( 1 ); 754509Speter } 764509Speter dfn_stack[ dfn_depth ].nlentryp = parentp; 774509Speter dfn_stack[ dfn_depth ].cycletop = dfn_depth; 784509Speter parentp -> toporder = DFN_BUSY; 794509Speter # ifdef DEBUG 804509Speter if ( debug & DFNDEBUG ) { 814509Speter printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth ); 824509Speter printname( parentp ); 834509Speter printf( "\n" ); 844509Speter } 854509Speter # endif DEBUG 864509Speter } 874509Speter 884509Speter /* 894509Speter * are we already numbered? 904509Speter */ 914509Speter bool 924509Speter dfn_numbered( childp ) 934509Speter nltype *childp; 944509Speter { 954509Speter 96*10284Speter return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY ); 974509Speter } 984509Speter 994509Speter /* 1004509Speter * are we already busy? 1014509Speter */ 1024509Speter bool 1034509Speter dfn_busy( childp ) 1044509Speter nltype *childp; 1054509Speter { 1064509Speter 107*10284Speter if ( childp -> toporder == DFN_NAN ) { 1084509Speter return FALSE; 1094509Speter } 1104509Speter return TRUE; 1114509Speter } 1124509Speter 1134509Speter /* 1144509Speter * MISSING: an explanation 1154509Speter */ 1164509Speter dfn_findcycle( childp ) 1174509Speter nltype *childp; 1184509Speter { 1194509Speter int cycletop; 1204509Speter nltype *cycleheadp; 1214509Speter nltype *tailp; 1224509Speter int index; 1234509Speter 1244509Speter for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) { 1254509Speter cycleheadp = dfn_stack[ cycletop ].nlentryp; 1264509Speter if ( childp == cycleheadp ) { 1274509Speter break; 1284509Speter } 1294509Speter if ( childp -> cyclehead != childp && 1304509Speter childp -> cyclehead == cycleheadp ) { 1314509Speter break; 1324509Speter } 1334509Speter } 1344509Speter if ( cycletop <= 0 ) { 1354509Speter fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" ); 1364509Speter exit( 1 ); 1374509Speter } 1384509Speter # ifdef DEBUG 1394509Speter if ( debug & DFNDEBUG ) { 1404509Speter printf( "[dfn_findcycle] dfn_depth %d cycletop %d " , 1414509Speter dfn_depth , cycletop ); 1424509Speter printname( cycleheadp ); 1434509Speter printf( "\n" ); 1444509Speter } 1454509Speter # endif DEBUG 1464509Speter if ( cycletop == dfn_depth ) { 1474509Speter /* 1484509Speter * this is previous function, e.g. this calls itself 1494509Speter * sort of boring 1504509Speter */ 1514509Speter dfn_self_cycle( childp ); 1524509Speter } else { 1534509Speter /* 1544509Speter * glom intervening functions that aren't already 1554509Speter * glommed into this cycle. 1564509Speter * things have been glommed when their cyclehead field 1574509Speter * points to the head of the cycle they are glommed into. 1584509Speter */ 1594509Speter for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) { 1604509Speter /* void: chase down to tail of things already glommed */ 1614509Speter # ifdef DEBUG 1624509Speter if ( debug & DFNDEBUG ) { 1634509Speter printf( "[dfn_findcycle] tail " ); 1644509Speter printname( tailp ); 1654509Speter printf( "\n" ); 1664509Speter } 1674509Speter # endif DEBUG 1684509Speter } 1694509Speter /* 1704509Speter * if what we think is the top of the cycle 1714509Speter * has a cyclehead field, then it's not really the 1724509Speter * head of the cycle, which is really what we want 1734509Speter */ 1744509Speter if ( cycleheadp -> cyclehead != cycleheadp ) { 1754509Speter cycleheadp = cycleheadp -> cyclehead; 1764509Speter # ifdef DEBUG 1774509Speter if ( debug & DFNDEBUG ) { 1784509Speter printf( "[dfn_findcycle] new cyclehead " ); 1794509Speter printname( cycleheadp ); 1804509Speter printf( "\n" ); 1814509Speter } 1824509Speter # endif DEBUG 1834509Speter } 1844509Speter for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) { 1854509Speter childp = dfn_stack[ index ].nlentryp; 1864509Speter if ( childp -> cyclehead == childp ) { 1874509Speter /* 1884509Speter * not yet glommed anywhere, glom it 1894509Speter * and fix any children it has glommed 1904509Speter */ 1914509Speter tailp -> cnext = childp; 1924509Speter childp -> cyclehead = cycleheadp; 1934509Speter # ifdef DEBUG 1944509Speter if ( debug & DFNDEBUG ) { 1954509Speter printf( "[dfn_findcycle] glomming " ); 1964509Speter printname( childp ); 1974509Speter printf( " onto " ); 1984509Speter printname( cycleheadp ); 1994509Speter printf( "\n" ); 2004509Speter } 2014509Speter # endif DEBUG 2024509Speter for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) { 2034509Speter tailp -> cnext -> cyclehead = cycleheadp; 2044509Speter # ifdef DEBUG 2054509Speter if ( debug & DFNDEBUG ) { 2064509Speter printf( "[dfn_findcycle] and its tail " ); 2074509Speter printname( tailp -> cnext ); 2084509Speter printf( " onto " ); 2094509Speter printname( cycleheadp ); 2104509Speter printf( "\n" ); 2114509Speter } 2124509Speter # endif DEBUG 2134509Speter } 2144509Speter } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) { 2154509Speter fprintf( stderr , 2164509Speter "[dfn_busy] glommed, but not to cyclehead\n" ); 2174509Speter } 2184509Speter } 2194509Speter } 2204509Speter } 2214509Speter 2224509Speter /* 2234509Speter * deal with self-cycles 2244509Speter * for lint: ARGSUSED 2254509Speter */ 2264509Speter dfn_self_cycle( parentp ) 2274509Speter nltype *parentp; 2284509Speter { 2294509Speter /* 2304509Speter * since we are taking out self-cycles elsewhere 2314509Speter * no need for the special case, here. 2324509Speter */ 2334509Speter # ifdef DEBUG 2344509Speter if ( debug & DFNDEBUG ) { 2354509Speter printf( "[dfn_self_cycle] " ); 2364509Speter printname( parentp ); 2374509Speter printf( "\n" ); 2384509Speter } 2394509Speter # endif DEBUG 2404509Speter } 2414509Speter 2424509Speter /* 2434509Speter * visit a node after all its children 2444509Speter * [MISSING: an explanation] 2454509Speter * and pop it off the stack 2464509Speter */ 2474509Speter dfn_post_visit( parentp ) 2484509Speter nltype *parentp; 2494509Speter { 2504509Speter nltype *memberp; 2514509Speter 2524509Speter # ifdef DEBUG 2534509Speter if ( debug & DFNDEBUG ) { 2544509Speter printf( "[dfn_post_visit]\t%d: " , dfn_depth ); 2554509Speter printname( parentp ); 2564509Speter printf( "\n" ); 2574509Speter } 2584509Speter # endif DEBUG 2594509Speter /* 2604509Speter * number functions and things in their cycles 2614509Speter * unless the function is itself part of a cycle 2624509Speter */ 2634509Speter if ( parentp -> cyclehead == parentp ) { 2644509Speter dfn_counter += 1; 2654509Speter for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) { 2664509Speter memberp -> toporder = dfn_counter; 2674509Speter # ifdef DEBUG 2684509Speter if ( debug & DFNDEBUG ) { 2694509Speter printf( "[dfn_post_visit]\t\tmember " ); 2704509Speter printname( memberp ); 2714509Speter printf( " -> toporder = %d\n" , dfn_counter ); 2724509Speter } 2734509Speter # endif DEBUG 2744509Speter } 2754509Speter } else { 2764509Speter # ifdef DEBUG 2774509Speter if ( debug & DFNDEBUG ) { 2784509Speter printf( "[dfn_post_visit]\t\tis part of a cycle\n" ); 2794509Speter } 2804509Speter # endif DEBUG 2814509Speter } 2824509Speter dfn_depth -= 1; 2834509Speter } 284