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