BSD 4_1c_2 release
[unix-history] / usr / src / usr.bin / struct / 3.loop.c
#ifndef lint
static char sccsid[] = "@(#)3.loop.c 4.1 (Berkeley) 2/11/83";
#endif not lint
#include <stdio.h>
#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);
}