[plain text]
#include <stdio.h>
#include <stdlib.h>
#include "stuff/errors.h"
#include "gprof.h"
#define DFN_DEPTH 1000
struct dfnstruct {
nltype *nlentryp;
int cycletop;
};
typedef struct dfnstruct dfntype;
static dfntype dfn_stack[DFN_DEPTH] = { {0} };
static int dfn_depth = 0;
static int dfn_counter = DFN_NAN;
static void dfn_pre_visit(
nltype *parentp);
static enum bool dfn_numbered(
nltype *childp);
static enum bool dfn_busy(
nltype *childp);
static void dfn_findcycle(
nltype *childp);
static void dfn_self_cycle(
nltype *parentp);
static void dfn_self_cycle(
nltype *parentp);
static void dfn_post_visit(
nltype *parentp);
void
dfn(
nltype *parentp)
{
arctype *arcp;
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn] dfn(");
printname(parentp);
printf(")\n");
}
#endif
if(dfn_numbered(parentp)){
return;
}
if(dfn_busy(parentp)){
dfn_findcycle(parentp);
return;
}
dfn_pre_visit(parentp);
for(arcp = parentp->children; arcp ; arcp = arcp->arc_childlist){
dfn(arcp->arc_childp);
}
dfn_post_visit(parentp);
}
static
void
dfn_pre_visit(
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
}
static
enum bool
dfn_numbered(
nltype *childp)
{
return(childp->toporder != DFN_NAN && childp->toporder != DFN_BUSY);
}
static
enum bool
dfn_busy(
nltype *childp)
{
if(childp->toporder == DFN_NAN){
return(FALSE);
}
return(TRUE);
}
static
void
dfn_findcycle(
nltype *childp)
{
int cycletop;
nltype *cycleheadp;
nltype *tailp;
int index;
cycleheadp = NULL;
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){
fatal("[dfn_findcycle] couldn't find head of cycle");
}
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn_findcycle] dfn_depth %d cycletop %d ",
dfn_depth, cycletop);
printname(cycleheadp);
printf("\n");
}
#endif
if(cycletop == dfn_depth){
dfn_self_cycle(childp);
}
else{
for(tailp = cycleheadp; tailp->cnext; tailp = tailp->cnext){
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn_findcycle] tail ");
printname(tailp);
printf("\n");
}
#endif
}
if(cycleheadp->cyclehead != cycleheadp){
cycleheadp = cycleheadp->cyclehead;
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn_findcycle] new cyclehead ");
printname(cycleheadp);
printf("\n");
}
#endif
}
for(index = cycletop + 1; index <= dfn_depth; index += 1){
childp = dfn_stack[index].nlentryp;
if(childp->cyclehead == childp){
tailp -> cnext = childp;
childp -> cyclehead = cycleheadp;
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn_findcycle] glomming ");
printname(childp);
printf(" onto ");
printname(cycleheadp);
printf("\n");
}
#endif
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
}
}
else if(childp->cyclehead != cycleheadp ){
fprintf(stderr,
"[dfn_busy] glommed, but not to cyclehead\n");
}
}
}
}
static
void
dfn_self_cycle(
nltype *parentp)
{
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn_self_cycle] ");
printname(parentp);
printf("\n");
}
#endif
}
static
void
dfn_post_visit(
nltype *parentp)
{
nltype *memberp;
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn_post_visit]\t%d: ", dfn_depth);
printname(parentp);
printf("\n");
}
#endif
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
}
}
else{
#ifdef DEBUG
if(debug & DFNDEBUG){
printf("[dfn_post_visit]\t\tis part of a cycle\n");
}
#endif
}
dfn_depth -= 1;
}
Generated by GNU enscript 1.6.4.