#include # /* depth-first search used to identify back edges, unreachable nodes; each node v entered by back edge replaced by LOOPVX ->ITERVX -> v, so that back edges entering v now enter the ITERVX, and other edges entering v now enter the LOOPVX. Nodes are numbered according to depth-first search: before numbering- ntobef[v] = i => node numbered v is i'th node in order of first visit during the search; after numbering- ntoaft[v] = i => node numbered v is i'th node visited in order of last visit during the search. Also, in this case after[i] = v. */ #include "def.h" #include "2.def.h" #define MAXINS 3 /* spacing needed between numbers generated during depth first search */ int *status; int befcount, aftcount; /* following defines used to mark back edges and nodes entered by back edges */ #define UNPROCESSED 0 #define STACKED 1 #define FINISHED 2 #define MARK(v) {REACH(v) = 1; } /* mark node v */ #define UNMARK(v) {REACH(v) = 0; } #define MARKED(v) (REACH(v)) #define MKEDGE(e) {if (e >= -1) e = -(e+3); } /* mark edge e */ #define UNMKEDGE(e) {if (e < -1) e = -(e+3); } #define BACKEDGE(e) (e < -1) dfs(v) /* depth first search */ VERT v; { int i; VERT w; accessnum = 0; status = challoc(sizeof(*status) * nodenum); for (w = 0; w < nodenum; ++w) { status[w] = UNPROCESSED; UNMARK(w); } search(v); chreach(); chfree(status, sizeof(*status) * nodenum); addloop(); after = challoc(sizeof(*after) * accessnum); for (i = 0; i < accessnum; ++i) after[i] = UNDEFINED; ntoaft = challoc(sizeof(*ntoaft) * nodenum); ntobef = challoc(sizeof(*ntobef) * nodenum); for (w = 0; w < nodenum; ++w) ntobef[w] = ntoaft[w] = UNDEFINED; befcount = 0; aftcount = 0; repsearch(v); } search(v) /* using depth first search, mark back edges using MKEDGE, and nodes entered by back edges using MARK */ VERT v; { VERT adj; int i; status[v] = STACKED; for(i = 0; i < ARCNUM(v); ++i) { adj = ARC(v,i); if (!DEFINED(adj)) continue; else if (status[adj] == UNPROCESSED) search(adj); else if (status[adj] == STACKED) { MARK(adj); /* mark adj as entered by back edge */ MKEDGE(ARC(v,i)); /* mark edge ARC(v,i) as being back edge */ } } status[v] = FINISHED; ++accessnum; } chreach() /* look for unreachable nodes */ { VERT v; LOGICAL unreach; unreach = FALSE; for (v = 0; v < nodenum; ++v) if (status[v] == UNPROCESSED && NTYPE(v) != FMTVX && NTYPE(v) != STOPVX && NTYPE(v) != RETVX) { unreach = TRUE; if (debug) fprintf(stderr,"node %d unreachable\n",v); } if (unreach) error(": unreachable statements - ","will be ignored",""); } addloop() /* add LOOPVX, ITERVX at nodes entered by back edges, and adjust edges */ { VERT v, adj; int j, oldnum; for (v = 0, oldnum = nodenum; v < oldnum; ++v) /* insloop increases nodenum */ if (MARKED(v)) { UNMARK(v); /* remove mark indicating v entered by back edge */ if (NTYPE(v) != ITERVX) /* DO loops already have ITERVX */ insloop(v); /* add LOOPVX, ITERVX since v entered by back edge*/ } /* arcs which used to enter v now enter LOOPVX; must make back edges enter ITERVX */ for (v = 0; v < nodenum; ++v) for (j = 0; j < ARCNUM(v); ++j) { if (BACKEDGE(ARC(v,j))) { UNMKEDGE(ARC(v,j)); /* return edge to normal value */ adj = ARC(v,j); if (NTYPE(adj) == ITERVX) continue; ASSERT(NTYPE(adj) == LOOPVX,addloop); ARC(v,j) = ARC(adj,0); /* change arc to point to ITERVX */ ASSERT(NTYPE(ARC(v,j)) == ITERVX,addloop); } } } insloop(v) /* insert LOOPVX, ITERVX at node number v */ VERT v; { VERT loo, iter; loo = create(LOOPVX, 1); iter = create(ITERVX,1); accessnum += 2; /* want LOOPVX to take on node number v, so that arcs other than back arcs entering v will enter the LOOPVX automatically */ exchange(&graph[v], &graph[loo]); exchange(&v, &loo); ARC(loo,0) = iter; ARC(iter,0) = v; FATH(iter) = UNDEFINED; /* will be defined later along with FATH for DOVX */ } exchange(p1,p2) /* exchange values of p1,p2 */ int *p1,*p2; { int temp; temp = *p1; *p1 = *p2; *p2 = temp; } repsearch(v) /* repeat df search in order to fill in after, ntoaft, ntobef tables */ VERT v; { VERT adj; int i,temp; ntobef[v] = befcount; ++befcount; for(i = 0; i < ARCNUM(v); ++i) { adj = ARC(v,i); if (DEFINED(adj) && ntobef[adj] == UNDEFINED) repsearch(adj); } ++aftcount; temp = accessnum - aftcount; after[temp] = v; ntoaft[v] = temp; }