BSD 3 development
[unix-history] / usr / src / cmd / struct / 3.loop.c
CommitLineData
42d6e430
BJ
1#include <stdio.h>
2#include "def.h"
3#include "3.def.h"
4
5#define ARCCOUNT(v) REACH(v)
6
7
8fixhd(v,hd,head)
9VERT v,hd,*head;
10 {
11 VERT w,newhd;
12 int i;
13 head[v] = hd;
14 newhd = (NTYPE(v) == ITERVX) ? v : hd;
15 for (i = 0; i < CHILDNUM(v); ++i)
16 for (w = LCHILD(v,i); DEFINED(w); w = RSIB(w))
17 fixhd(w,newhd,head);
18 }
19
20getloop()
21 {
22 cntarcs();
23 fixloop(START);
24 }
25
26
27cntarcs() /* count arcs entering each node */
28 {
29 VERT w,v;
30 int i;
31 for (v = 0; v < nodenum; ++v)
32 ARCCOUNT(v) = 0;
33 for (v = 0; v < nodenum; ++v)
34 for (i = 0; i < ARCNUM(v); ++i)
35 {
36 w = ARC(v,i);
37 if (!DEFINED(w)) continue;
38 ++ARCCOUNT(w);
39 }
40 }
41
42
43fixloop(v) /* find WHILE loops */
44VERT v;
45 {
46 int recvar;
47 if (NTYPE(v) == LOOPVX)
48 {
49 ASSERT(DEFINED(ARC(v,0)),fixloop);
50 NXT(ARC(v,0)) = ARC(v,0);
51 if (!getwh(v))
52 getun(v);
53 }
54 else if (NTYPE(v) == IFVX && arbcase)
55 getswitch(v);
56 else if (NTYPE(v)==DOVX)
57 {
58 ASSERT(DEFINED(ARC(v,0)),fixloop);
59 NXT(ARC(v,0))=ARC(v,0);
60 }
61 RECURSE(fixloop,v,recvar);
62 }
63
64
65getwh(v)
66VERT v;
67 {
68 VERT vchild, vgrand,vgreat;
69 ASSERT(NTYPE(v) == LOOPVX,getwh);
70 vchild = LCHILD(v,0);
71 ASSERT(DEFINED(vchild),getwh);
72 ASSERT(NTYPE(vchild) == ITERVX,getwh);
73 vgrand = LCHILD(vchild,0);
74 if (!DEFINED(vgrand) || !IFTHEN(vgrand) )
75 return(FALSE);
76 vgreat = LCHILD(vgrand,THEN);
77 if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild))
78 {
79 /* turn into WHILE */
80 NTYPE(v) = WHIVX;
81 NEG(vgrand) = !NEG(vgrand);
82 LPRED(vchild) = vgrand;
83 LCHILD(vchild,0) = RSIB(vgrand);
84 RSIB(vgrand) = UNDEFINED;
85 return(TRUE);
86 }
87 return(FALSE);
88 }
89
90
91
92getun(v) /* change loop to REPEAT UNTIL if possible */
93VERT v;
94 {
95 VERT vchild, vgrand, vgreat, before, ch;
96 ASSERT(NTYPE(v) == LOOPVX,getun);
97 vchild = LCHILD(v,0);
98 ASSERT(DEFINED(vchild), getun);
99 if (ARCCOUNT(vchild) > 2)
100 return(FALSE); /* loop can be iterated without passing through predicate of UNTIL */
101 vgrand = ARC(vchild,0);
102 if (!DEFINED(vgrand))
103 return(FALSE);
104 for (ch = vgrand,before = UNDEFINED; DEFINED(RSIB(ch)); ch = RSIB(ch))
105 before = ch;
106 if (!IFTHEN(ch))
107 return(FALSE);
108 vgreat = LCHILD(ch,THEN);
109 if (DEFINED(vgreat) && NTYPE(vgreat) == GOVX && ARC(vgreat,0) == BRK(vchild))
110 {
111 /* create UNTIL node */
112 NTYPE(v) = UNTVX;
113 NXT(vchild) = ch;
114 LPRED(vchild)=ch;
115 RSIB(before) = UNDEFINED;
116 return(TRUE);
117 }
118 return(FALSE);
119 }
120
121
122#define FORMCASE(w) (DEFINED(w) && !DEFINED(RSIB(w)) && NTYPE(w) == IFVX && ARCCOUNT(w) == 1)
123
124getswitch(v)
125VERT v;
126 {
127 VERT ch, grand, temp;
128 /* must be of form if ... else if ... else if ... */
129 if (NTYPE(v) != IFVX) return(FALSE);
130 ch = LCHILD(v,ELSE);
131 if (!FORMCASE(ch)) return(FALSE);
132 grand = LCHILD(ch,ELSE);
133 if (!FORMCASE(grand)) return(FALSE);
134
135 temp = create(SWCHVX,0);
136 exchange(&graph[temp],&graph[v]); /* want arcs to enter switch, not first case*/
137 BEGCOM(v) = UNDEFINED;
138 RSIB(v) = RSIB(temp); /* statements which followed IFVX should follow switch */
139 EXP(v) = UNDEFINED;
140 LCHILD(v,0) = temp;
141 NTYPE(temp) = ACASVX;
142 for (ch = LCHILD(temp,ELSE); FORMCASE(ch); )
143 {
144 LCHILD(temp,ELSE) = UNDEFINED;
145 RSIB(temp) = ch;
146 NTYPE(ch) = ACASVX;
147 temp = ch;
148 ch = LCHILD(temp,ELSE);
149 }
150 ASSERT(!DEFINED(RSIB(temp)),getswitch);
151 return(TRUE);
152 }