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