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