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