#ifndef lint static char sccsid[] = "@(#)3.loop.c 4.1 (Berkeley) 2/11/83"; #endif not lint #include #include "def.h" #include "3.def.h" #define ARCCOUNT(v) REACH(v) fixhd(v,hd,head) VERT v,hd,*head; { VERT w,newhd; int i; head[v] = hd; newhd = (NTYPE(v) == ITERVX) ? v : hd; for (i = 0; i < CHILDNUM(v); ++i) for (w = LCHILD(v,i); DEFINED(w); w = RSIB(w)) fixhd(w,newhd,head); } getloop() { cntarcs(); fixloop(START); } cntarcs() /* count arcs entering each node */ { VERT w,v; int i; for (v = 0; v < nodenum; ++v) ARCCOUNT(v) = 0; for (v = 0; v < nodenum; ++v) for (i = 0; i < ARCNUM(v); ++i) { w = ARC(v,i); if (!DEFINED(w)) continue; ++ARCCOUNT(w); } } fixloop(v) /* find WHILE loops */ VERT v; { int recvar; if (NTYPE(v) == LOOPVX) { ASSERT(DEFINED(ARC(v,0)),fixloop); NXT(ARC(v,0)) = ARC(v,0); if (!getwh(v)) getun(v); } else if (NTYPE(v) == IFVX && arbcase) getswitch(v); else if (NTYPE(v)==DOVX) { ASSERT(DEFINED(ARC(v,0)),fixloop); NXT(ARC(v,0))=ARC(v,0); } RECURSE(fixloop,v,recvar); } getwh(v) VERT v; { VERT vchild, vgrand,vgreat; ASSERT(NTYPE(v) == LOOPVX,getwh); vchild = LCHILD(v,0); ASSERT(DEFINED(vchild),getwh); ASSERT(NTYPE(vchild) == ITERVX,getwh); vgrand = LCHILD(vchild,0); if (!DEFINED(vgrand) || !IFTHEN(vgrand) ) return(FALSE); vgreat = LCHILD(vgrand,THEN); if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild)) { /* turn into WHILE */ NTYPE(v) = WHIVX; NEG(vgrand) = !NEG(vgrand); LPRED(vchild) = vgrand; LCHILD(vchild,0) = RSIB(vgrand); RSIB(vgrand) = UNDEFINED; return(TRUE); } return(FALSE); } getun(v) /* change loop to REPEAT UNTIL if possible */ VERT v; { VERT vchild, vgrand, vgreat, before, ch; ASSERT(NTYPE(v) == LOOPVX,getun); vchild = LCHILD(v,0); ASSERT(DEFINED(vchild), getun); if (ARCCOUNT(vchild) > 2) return(FALSE); /* loop can be iterated without passing through predicate of UNTIL */ vgrand = ARC(vchild,0); if (!DEFINED(vgrand)) return(FALSE); for (ch = vgrand,before = UNDEFINED; DEFINED(RSIB(ch)); ch = RSIB(ch)) before = ch; if (!IFTHEN(ch)) return(FALSE); vgreat = LCHILD(ch,THEN); if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild)) { /* create UNTIL node */ NTYPE(v) = UNTVX; NXT(vchild) = ch; LPRED(vchild)=ch; RSIB(before) = UNDEFINED; return(TRUE); } return(FALSE); } #define FORMCASE(w) (DEFINED(w) && !DEFINED(RSIB(w)) && NTYPE(w) == IFVX && ARCCOUNT(w) == 1) getswitch(v) VERT v; { VERT ch, grand, temp; /* must be of form if ... else if ... else if ... */ if (NTYPE(v) != IFVX) return(FALSE); ch = LCHILD(v,ELSE); if (!FORMCASE(ch)) return(FALSE); grand = LCHILD(ch,ELSE); if (!FORMCASE(grand)) return(FALSE); temp = create(SWCHVX,0); exchange(&graph[temp],&graph[v]); /* want arcs to enter switch, not first case*/ BEGCOM(v) = UNDEFINED; RSIB(v) = RSIB(temp); /* statements which followed IFVX should follow switch */ EXP(v) = UNDEFINED; LCHILD(v,0) = temp; NTYPE(temp) = ACASVX; for (ch = LCHILD(temp,ELSE); FORMCASE(ch); ) { LCHILD(temp,ELSE) = UNDEFINED; RSIB(temp) = ch; NTYPE(ch) = ACASVX; temp = ch; ch = LCHILD(temp,ELSE); } ASSERT(!DEFINED(RSIB(temp)),getswitch); return(TRUE); }