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