Bell 32V release
[unix-history] / usr / src / cmd / f77 / equiv.c
CommitLineData
0d57d6f5
TL
1#include "defs"
2
3/* ROUTINES RELATED TO EQUIVALENCE CLASS PROCESSING */
4
5/* called at end of declarations section to process chains
6 created by EQUIVALENCE statements
7 */
8doequiv()
9{
10register int i;
11int inequiv, comno, ovarno;
12ftnint comoffset, offset, leng, iarrlen(), lmin(), lmax();
13register struct equivblock *p;
14register struct eqvchain *q;
15struct primblock *itemp;
16register struct nameblock *np;
17expptr offp, suboffset();
18int ns, nsubs();
19chainp cp;
20
21for(i = 0 ; i < nequiv ; ++i)
22 {
23 p = &eqvclass[i];
24 p->eqvbottom = p->eqvtop = 0;
25 comno = -1;
26
27 for(q = p->equivs ; q ; q = q->nextp)
28 {
29 itemp = q->eqvitem;
30 vardcl(np = itemp->namep);
31 if(itemp->argsp || itemp->fcharp)
32 {
33 if(np->vdim!=NULL && np->vdim->ndim>1 &&
34 nsubs(itemp->argsp)==1 )
35 {
36 if(! ftn66flag)
37 warn("1-dim subscript in EQUIVALENCE");
38 cp = NULL;
39 ns = np->vdim->ndim;
40 while(--ns > 0)
41 cp = mkchain( ICON(1), cp);
42 itemp->argsp->listp->nextp = cp;
43 }
44 offp = suboffset(itemp);
45 }
46 else offp = ICON(0);
47 if(ISICON(offp))
48 offset = q->eqvoffset = offp->const.ci;
49 else {
50 dclerr("nonconstant subscript in equivalence ", np);
51 np = NULL;
52 goto endit;
53 }
54 if( (leng = iarrlen(np)) < 0)
55 {
56 dclerr("adjustable in equivalence", np);
57 np = NULL;
58 goto endit;
59 }
60 p->eqvbottom = lmin(p->eqvbottom, -offset);
61 p->eqvtop = lmax(p->eqvtop, leng-offset);
62
63 switch(np->vstg)
64 {
65 case STGUNKNOWN:
66 case STGBSS:
67 case STGEQUIV:
68 break;
69
70 case STGCOMMON:
71 comno = np->vardesc.varno;
72 comoffset = np->voffset + offset;
73 break;
74
75 default:
76 dclerr("bad storage class in equivalence", np);
77 np = NULL;
78 goto endit;
79 }
80 endit:
81 frexpr(offp);
82 q->eqvitem = np;
83 }
84
85 if(comno >= 0)
86 eqvcommon(p, comno, comoffset);
87 else for(q = p->equivs ; q ; q = q->nextp)
88 {
89 if(np = q->eqvitem)
90 {
91 inequiv = NO;
92 if(np->vstg==STGEQUIV)
93 if( (ovarno = np->vardesc.varno) == i)
94 {
95 if(np->voffset + q->eqvoffset != 0)
96 dclerr("inconsistent equivalence", np);
97 }
98 else {
99 offset = np->voffset;
100 inequiv = YES;
101 }
102
103 np->vstg = STGEQUIV;
104 np->vardesc.varno = i;
105 np->voffset = - q->eqvoffset;
106
107 if(inequiv)
108 eqveqv(i, ovarno, q->eqvoffset + offset);
109 }
110 }
111 }
112
113for(i = 0 ; i < nequiv ; ++i)
114 {
115 p = & eqvclass[i];
116 if(p->eqvbottom!=0 || p->eqvtop!=0)
117 {
118 for(q = p->equivs ; q; q = q->nextp)
119 {
120 np = q->eqvitem;
121 np->voffset -= p->eqvbottom;
122 if(np->voffset % typealign[np->vtype] != 0)
123 dclerr("bad alignment forced by equivalence", np);
124 }
125 p->eqvtop -= p->eqvbottom;
126 p->eqvbottom = 0;
127 }
128 freqchain(p);
129 }
130}
131
132
133
134
135
136/* put equivalence chain p at common block comno + comoffset */
137
138LOCAL eqvcommon(p, comno, comoffset)
139struct equivblock *p;
140int comno;
141ftnint comoffset;
142{
143int ovarno;
144ftnint k, offq;
145register struct nameblock *np;
146register struct eqvchain *q;
147
148if(comoffset + p->eqvbottom < 0)
149 {
150 err1("attempt to extend common %s backward",
151 nounder(XL, extsymtab[comno].extname) );
152 freqchain(p);
153 return;
154 }
155
156if( (k = comoffset + p->eqvtop) > extsymtab[comno].extleng)
157 extsymtab[comno].extleng = k;
158
159for(q = p->equivs ; q ; q = q->nextp)
160 if(np = q->eqvitem)
161 {
162 switch(np->vstg)
163 {
164 case STGUNKNOWN:
165 case STGBSS:
166 np->vstg = STGCOMMON;
167 np->vardesc.varno = comno;
168 np->voffset = comoffset - q->eqvoffset;
169 break;
170
171 case STGEQUIV:
172 ovarno = np->vardesc.varno;
173 offq = comoffset - q->eqvoffset - np->voffset;
174 np->vstg = STGCOMMON;
175 np->vardesc.varno = comno;
176 np->voffset = comoffset - q->eqvoffset;
177 if(ovarno != (p - eqvclass))
178 eqvcommon(&eqvclass[ovarno], comno, offq);
179 break;
180
181 case STGCOMMON:
182 if(comno != np->vardesc.varno ||
183 comoffset != np->voffset+q->eqvoffset)
184 dclerr("inconsistent common usage", np);
185 break;
186
187
188 default:
189 fatal1("eqvcommon: impossible vstg %d", np->vstg);
190 }
191 }
192
193freqchain(p);
194p->eqvbottom = p->eqvtop = 0;
195}
196
197
198/* put all items on ovarno chain on front of nvarno chain
199 * adjust offsets of ovarno elements and top and bottom of nvarno chain
200 */
201
202LOCAL eqveqv(nvarno, ovarno, delta)
203int ovarno, nvarno;
204ftnint delta;
205{
206register struct equivblock *p0, *p;
207register struct nameblock *np;
208struct eqvchain *q, *q1;
209
210p0 = eqvclass + nvarno;
211p = eqvclass + ovarno;
212p0->eqvbottom = lmin(p0->eqvbottom, p->eqvbottom - delta);
213p0->eqvtop = lmax(p0->eqvtop, p->eqvtop - delta);
214p->eqvbottom = p->eqvtop = 0;
215
216for(q = p->equivs ; q ; q = q1)
217 {
218 q1 = q->nextp;
219 if( (np = q->eqvitem) && np->vardesc.varno==ovarno)
220 {
221 q->nextp = p0->equivs;
222 p0->equivs = q;
223 q->eqvoffset -= delta;
224 np->vardesc.varno = nvarno;
225 np->voffset -= delta;
226 }
227 else free(q);
228 }
229p->equivs = NULL;
230}
231
232
233
234
235LOCAL freqchain(p)
236register struct equivblock *p;
237{
238register struct eqvchain *q, *oq;
239
240for(q = p->equivs ; q ; q = oq)
241 {
242 oq = q->nextp;
243 free(q);
244 }
245p->equivs = NULL;
246}
247
248
249
250
251
252LOCAL nsubs(p)
253register struct listblock *p;
254{
255register int n;
256register chainp q;
257
258n = 0;
259if(p)
260 for(q = p->listp ; q ; q = q->nextp)
261 ++n;
262
263return(n);
264}