|
|
1.1 root 1: /****************************************************************
2: Copyright 1990, 1993 by AT&T Bell Laboratories and Bellcore.
3:
4: Permission to use, copy, modify, and distribute this software
5: and its documentation for any purpose and without fee is hereby
6: granted, provided that the above copyright notice appear in all
7: copies and that both that the copyright notice and this
8: permission notice and warranty disclaimer appear in supporting
9: documentation, and that the names of AT&T Bell Laboratories or
10: Bellcore or any of their entities not be used in advertising or
11: publicity pertaining to distribution of the software without
12: specific, written prior permission.
13:
14: AT&T and Bellcore disclaim all warranties with regard to this
15: software, including all implied warranties of merchantability
16: and fitness. In no event shall AT&T or Bellcore be liable for
17: any special, indirect or consequential damages or any damages
18: whatsoever resulting from loss of use, data or profits, whether
19: in an action of contract, negligence or other tortious action,
20: arising out of or in connection with the use or performance of
21: this software.
22: ****************************************************************/
23:
24: #include "defs.h"
25:
26: LOCAL eqvcommon(), eqveqv(), nsubs();
27:
28: /* ROUTINES RELATED TO EQUIVALENCE CLASS PROCESSING */
29:
30: /* called at end of declarations section to process chains
31: created by EQUIVALENCE statements
32: */
33: doequiv()
34: {
35: register int i;
36: int inequiv; /* True if one namep occurs in
37: several EQUIV declarations */
38: int comno; /* Index into Extsym table of the last
39: COMMON block seen (implicitly assuming
40: that only one will be given) */
41: int ovarno;
42: ftnint comoffset; /* Index into the COMMON block */
43: ftnint offset; /* Offset from array base */
44: ftnint leng;
45: register struct Equivblock *equivdecl;
46: register struct Eqvchain *q;
47: struct Primblock *primp;
48: register Namep np;
49: int k, k1, ns, pref, t;
50: chainp cp;
51: extern int type_pref[];
52: char *s;
53:
54: for(i = 0 ; i < nequiv ; ++i)
55: {
56:
57: /* Handle each equivalence declaration */
58:
59: equivdecl = &eqvclass[i];
60: equivdecl->eqvbottom = equivdecl->eqvtop = 0;
61: comno = -1;
62:
63:
64:
65: for(q = equivdecl->equivs ; q ; q = q->eqvnextp)
66: {
67: offset = 0;
68: primp = q->eqvitem.eqvlhs;
69: vardcl(np = primp->namep);
70: if(primp->argsp || primp->fcharp)
71: {
72: expptr offp, suboffset();
73:
74: /* Pad ones onto the end of an array declaration when needed */
75:
76: if(np->vdim!=NULL && np->vdim->ndim>1 &&
77: nsubs(primp->argsp)==1 )
78: {
79: if(! ftn66flag)
80: warni
81: ("1-dim subscript in EQUIVALENCE, %d-dim declared",
82: np -> vdim -> ndim);
83: cp = NULL;
84: ns = np->vdim->ndim;
85: while(--ns > 0)
86: cp = mkchain((char *)ICON(1), cp);
87: primp->argsp->listp->nextp = cp;
88: }
89:
90: offp = suboffset(primp);
91: if(ISICON(offp))
92: offset = offp->constblock.Const.ci;
93: else {
94: dclerr
95: ("nonconstant subscript in equivalence ",
96: np);
97: np = NULL;
98: }
99: frexpr(offp);
100: }
101:
102: /* Free up the primblock, since we now have a hash table (Namep) entry */
103:
104: frexpr((expptr)primp);
105:
106: if(np && (leng = iarrlen(np))<0)
107: {
108: dclerr("adjustable in equivalence", np);
109: np = NULL;
110: }
111:
112: if(np) switch(np->vstg)
113: {
114: case STGUNKNOWN:
115: case STGBSS:
116: case STGEQUIV:
117: if (in_vector(np->cvarname, st_fields,
118: n_st_fields) >= 0) {
119: k = strlen(np->cvarname);
120: strcpy(s = mem(k+2,0), np->cvarname);
121: s[k] = '_';
122: s[k+1] = 0;
123: np->cvarname = s;
124: }
125: break;
126:
127: case STGCOMMON:
128:
129: /* The code assumes that all COMMON references in a given EQUIVALENCE will
130: be to the same COMMON block, and will all be consistent */
131:
132: comno = np->vardesc.varno;
133: comoffset = np->voffset + offset;
134: break;
135:
136: default:
137: dclerr("bad storage class in equivalence", np);
138: np = NULL;
139: break;
140: }
141:
142: if(np)
143: {
144: q->eqvoffset = offset;
145:
146: /* eqvbottom gets the largest difference between the array base address
147: and the address specified in the EQUIV declaration */
148:
149: equivdecl->eqvbottom =
150: lmin(equivdecl->eqvbottom, -offset);
151:
152: /* eqvtop gets the largest difference between the end of the array and
153: the address given in the EQUIVALENCE */
154:
155: equivdecl->eqvtop =
156: lmax(equivdecl->eqvtop, leng-offset);
157: }
158: q->eqvitem.eqvname = np;
159: }
160:
161: /* Now all equivalenced variables are in the hash table with the proper
162: offset, and eqvtop and eqvbottom are set. */
163:
164: if(comno >= 0)
165:
166: /* Get rid of all STGEQUIVS, they will be mapped onto STGCOMMON variables
167: */
168:
169: eqvcommon(equivdecl, comno, comoffset);
170: else for(q = equivdecl->equivs ; q ; q = q->eqvnextp)
171: {
172: if(np = q->eqvitem.eqvname)
173: {
174: inequiv = NO;
175: if(np->vstg==STGEQUIV)
176: if( (ovarno = np->vardesc.varno) == i)
177: {
178:
179: /* Can't EQUIV different elements of the same array */
180:
181: if(np->voffset + q->eqvoffset != 0)
182: dclerr
183: ("inconsistent equivalence", np);
184: }
185: else {
186: offset = np->voffset;
187: inequiv = YES;
188: }
189:
190: np->vstg = STGEQUIV;
191: np->vardesc.varno = i;
192: np->voffset = - q->eqvoffset;
193:
194: if(inequiv)
195:
196: /* Combine 2 equivalence declarations */
197:
198: eqveqv(i, ovarno, q->eqvoffset + offset);
199: }
200: }
201: }
202:
203: /* Now each equivalence declaration is distinct (all connections have been
204: merged in eqveqv()), and some may be empty. */
205:
206: for(i = 0 ; i < nequiv ; ++i)
207: {
208: equivdecl = & eqvclass[i];
209: if(equivdecl->eqvbottom!=0 || equivdecl->eqvtop!=0) {
210:
211: /* a live chain */
212:
213: k = TYCHAR;
214: pref = 1;
215: for(q = equivdecl->equivs ; q; q = q->eqvnextp)
216: if (np = q->eqvitem.eqvname){
217: np->voffset -= equivdecl->eqvbottom;
218: t = typealign[k1 = np->vtype];
219: if (pref < type_pref[k1]) {
220: k = k1;
221: pref = type_pref[k1];
222: }
223: if(np->voffset % t != 0) {
224: dclerr("bad alignment forced by equivalence", np);
225: --nerr; /* don't give bad return code for this */
226: }
227: }
228: equivdecl->eqvtype = k;
229: }
230: freqchain(equivdecl);
231: }
232: }
233:
234:
235:
236:
237:
238: /* put equivalence chain p at common block comno + comoffset */
239:
240: LOCAL eqvcommon(p, comno, comoffset)
241: struct Equivblock *p;
242: int comno;
243: ftnint comoffset;
244: {
245: int ovarno;
246: ftnint k, offq;
247: register Namep np;
248: register struct Eqvchain *q;
249:
250: if(comoffset + p->eqvbottom < 0)
251: {
252: errstr("attempt to extend common %s backward",
253: extsymtab[comno].fextname);
254: freqchain(p);
255: return;
256: }
257:
258: if( (k = comoffset + p->eqvtop) > extsymtab[comno].extleng)
259: extsymtab[comno].extleng = k;
260:
261:
262: for(q = p->equivs ; q ; q = q->eqvnextp)
263: if(np = q->eqvitem.eqvname)
264: {
265: switch(np->vstg)
266: {
267: case STGUNKNOWN:
268: case STGBSS:
269: np->vstg = STGCOMMON;
270: np->vcommequiv = 1;
271: np->vardesc.varno = comno;
272:
273: /* np -> voffset will point to the base of the array */
274:
275: np->voffset = comoffset - q->eqvoffset;
276: break;
277:
278: case STGEQUIV:
279: ovarno = np->vardesc.varno;
280:
281: /* offq will point to the current element, even if it's in an array */
282:
283: offq = comoffset - q->eqvoffset - np->voffset;
284: np->vstg = STGCOMMON;
285: np->vcommequiv = 1;
286: np->vardesc.varno = comno;
287:
288: /* np -> voffset will point to the base of the array */
289:
290: np->voffset += offq;
291: if(ovarno != (p - eqvclass))
292: eqvcommon(&eqvclass[ovarno], comno, offq);
293: break;
294:
295: case STGCOMMON:
296: if(comno != np->vardesc.varno ||
297: comoffset != np->voffset+q->eqvoffset)
298: dclerr("inconsistent common usage", np);
299: break;
300:
301:
302: default:
303: badstg("eqvcommon", np->vstg);
304: }
305: }
306:
307: freqchain(p);
308: p->eqvbottom = p->eqvtop = 0;
309: }
310:
311:
312: /* Move all items on ovarno chain to the front of nvarno chain.
313: * adjust offsets of ovarno elements and top and bottom of nvarno chain
314: */
315:
316: LOCAL eqveqv(nvarno, ovarno, delta)
317: int ovarno, nvarno;
318: ftnint delta;
319: {
320: register struct Equivblock *neweqv, *oldeqv;
321: register Namep np;
322: struct Eqvchain *q, *q1;
323:
324: neweqv = eqvclass + nvarno;
325: oldeqv = eqvclass + ovarno;
326: neweqv->eqvbottom = lmin(neweqv->eqvbottom, oldeqv->eqvbottom - delta);
327: neweqv->eqvtop = lmax(neweqv->eqvtop, oldeqv->eqvtop - delta);
328: oldeqv->eqvbottom = oldeqv->eqvtop = 0;
329:
330: for(q = oldeqv->equivs ; q ; q = q1)
331: {
332: q1 = q->eqvnextp;
333: if( (np = q->eqvitem.eqvname) && np->vardesc.varno==ovarno)
334: {
335: q->eqvnextp = neweqv->equivs;
336: neweqv->equivs = q;
337: q->eqvoffset += delta;
338: np->vardesc.varno = nvarno;
339: np->voffset -= delta;
340: }
341: else free( (charptr) q);
342: }
343: oldeqv->equivs = NULL;
344: }
345:
346:
347:
348:
349: freqchain(p)
350: register struct Equivblock *p;
351: {
352: register struct Eqvchain *q, *oq;
353:
354: for(q = p->equivs ; q ; q = oq)
355: {
356: oq = q->eqvnextp;
357: free( (charptr) q);
358: }
359: p->equivs = NULL;
360: }
361:
362:
363:
364:
365:
366: /* nsubs -- number of subscripts in this arglist (just the length of the
367: list) */
368:
369: LOCAL nsubs(p)
370: register struct Listblock *p;
371: {
372: register int n;
373: register chainp q;
374:
375: n = 0;
376: if(p)
377: for(q = p->listp ; q ; q = q->nextp)
378: ++n;
379:
380: return(n);
381: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.