home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that: (1) source distributions retain this entire copyright
- * notice and comment, and (2) distributions including binaries display
- * the following acknowledgement: ``This product includes software
- * developed by the University of California, Berkeley and its contributors''
- * in the documentation or other materials provided with the distribution
- * and in all advertising materials mentioning features or use of this
- * software. Neither the name of the University nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#)dfn.c 5.4 (Berkeley) 6/1/90";
- #endif /* not lint */
-
- #include <stdio.h>
- #include "gprof.h"
-
- #define DFN_DEPTH 100
- struct dfnstruct {
- nltype *nlentryp;
- int cycletop;
- };
- typedef struct dfnstruct dfntype;
-
- dfntype dfn_stack[ DFN_DEPTH ];
- int dfn_depth = 0;
-
- int dfn_counter = DFN_NAN;
-
- /*
- * given this parent, depth first number its children.
- */
- dfn( parentp )
- nltype *parentp;
- {
- arctype *arcp;
-
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn] dfn(" );
- printname( parentp );
- printf( ")\n" );
- }
- # endif DEBUG
- /*
- * if we're already numbered, no need to look any furthur.
- */
- if ( dfn_numbered( parentp ) ) {
- return;
- }
- /*
- * if we're already busy, must be a cycle
- */
- if ( dfn_busy( parentp ) ) {
- dfn_findcycle( parentp );
- return;
- }
- /*
- * visit yourself before your children
- */
- dfn_pre_visit( parentp );
- /*
- * visit children
- */
- for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) {
- dfn( arcp -> arc_childp );
- }
- /*
- * visit yourself after your children
- */
- dfn_post_visit( parentp );
- }
-
- /*
- * push a parent onto the stack and mark it busy
- */
- dfn_pre_visit( parentp )
- nltype *parentp;
- {
-
- dfn_depth += 1;
- if ( dfn_depth >= DFN_DEPTH ) {
- fprintf( stderr , "[dfn] out of my depth (dfn_stack overflow)\n" );
- exit( 1 );
- }
- dfn_stack[ dfn_depth ].nlentryp = parentp;
- dfn_stack[ dfn_depth ].cycletop = dfn_depth;
- parentp -> toporder = DFN_BUSY;
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_pre_visit]\t\t%d:" , dfn_depth );
- printname( parentp );
- printf( "\n" );
- }
- # endif DEBUG
- }
-
- /*
- * are we already numbered?
- */
- bool
- dfn_numbered( childp )
- nltype *childp;
- {
-
- return ( childp -> toporder != DFN_NAN && childp -> toporder != DFN_BUSY );
- }
-
- /*
- * are we already busy?
- */
- bool
- dfn_busy( childp )
- nltype *childp;
- {
-
- if ( childp -> toporder == DFN_NAN ) {
- return FALSE;
- }
- return TRUE;
- }
-
- /*
- * MISSING: an explanation
- */
- dfn_findcycle( childp )
- nltype *childp;
- {
- int cycletop;
- nltype *cycleheadp;
- nltype *tailp;
- int index;
-
- for ( cycletop = dfn_depth ; cycletop > 0 ; cycletop -= 1 ) {
- cycleheadp = dfn_stack[ cycletop ].nlentryp;
- if ( childp == cycleheadp ) {
- break;
- }
- if ( childp -> cyclehead != childp &&
- childp -> cyclehead == cycleheadp ) {
- break;
- }
- }
- if ( cycletop <= 0 ) {
- fprintf( stderr , "[dfn_findcycle] couldn't find head of cycle\n" );
- exit( 1 );
- }
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_findcycle] dfn_depth %d cycletop %d " ,
- dfn_depth , cycletop );
- printname( cycleheadp );
- printf( "\n" );
- }
- # endif DEBUG
- if ( cycletop == dfn_depth ) {
- /*
- * this is previous function, e.g. this calls itself
- * sort of boring
- */
- dfn_self_cycle( childp );
- } else {
- /*
- * glom intervening functions that aren't already
- * glommed into this cycle.
- * things have been glommed when their cyclehead field
- * points to the head of the cycle they are glommed into.
- */
- for ( tailp = cycleheadp ; tailp -> cnext ; tailp = tailp -> cnext ) {
- /* void: chase down to tail of things already glommed */
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_findcycle] tail " );
- printname( tailp );
- printf( "\n" );
- }
- # endif DEBUG
- }
- /*
- * if what we think is the top of the cycle
- * has a cyclehead field, then it's not really the
- * head of the cycle, which is really what we want
- */
- if ( cycleheadp -> cyclehead != cycleheadp ) {
- cycleheadp = cycleheadp -> cyclehead;
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_findcycle] new cyclehead " );
- printname( cycleheadp );
- printf( "\n" );
- }
- # endif DEBUG
- }
- for ( index = cycletop + 1 ; index <= dfn_depth ; index += 1 ) {
- childp = dfn_stack[ index ].nlentryp;
- if ( childp -> cyclehead == childp ) {
- /*
- * not yet glommed anywhere, glom it
- * and fix any children it has glommed
- */
- tailp -> cnext = childp;
- childp -> cyclehead = cycleheadp;
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_findcycle] glomming " );
- printname( childp );
- printf( " onto " );
- printname( cycleheadp );
- printf( "\n" );
- }
- # endif DEBUG
- for ( tailp = childp ; tailp->cnext ; tailp = tailp->cnext ) {
- tailp -> cnext -> cyclehead = cycleheadp;
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_findcycle] and its tail " );
- printname( tailp -> cnext );
- printf( " onto " );
- printname( cycleheadp );
- printf( "\n" );
- }
- # endif DEBUG
- }
- } else if ( childp -> cyclehead != cycleheadp /* firewall */ ) {
- fprintf( stderr ,
- "[dfn_busy] glommed, but not to cyclehead\n" );
- }
- }
- }
- }
-
- /*
- * deal with self-cycles
- * for lint: ARGSUSED
- */
- dfn_self_cycle( parentp )
- nltype *parentp;
- {
- /*
- * since we are taking out self-cycles elsewhere
- * no need for the special case, here.
- */
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_self_cycle] " );
- printname( parentp );
- printf( "\n" );
- }
- # endif DEBUG
- }
-
- /*
- * visit a node after all its children
- * [MISSING: an explanation]
- * and pop it off the stack
- */
- dfn_post_visit( parentp )
- nltype *parentp;
- {
- nltype *memberp;
-
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_post_visit]\t%d: " , dfn_depth );
- printname( parentp );
- printf( "\n" );
- }
- # endif DEBUG
- /*
- * number functions and things in their cycles
- * unless the function is itself part of a cycle
- */
- if ( parentp -> cyclehead == parentp ) {
- dfn_counter += 1;
- for ( memberp = parentp ; memberp ; memberp = memberp -> cnext ) {
- memberp -> toporder = dfn_counter;
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_post_visit]\t\tmember " );
- printname( memberp );
- printf( " -> toporder = %d\n" , dfn_counter );
- }
- # endif DEBUG
- }
- } else {
- # ifdef DEBUG
- if ( debug & DFNDEBUG ) {
- printf( "[dfn_post_visit]\t\tis part of a cycle\n" );
- }
- # endif DEBUG
- }
- dfn_depth -= 1;
- }
-