00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "defs.h"
00025
00026 static void eqvcommon Argdcl((struct Equivblock*, int, long int));
00027 static void eqveqv Argdcl((int, int, long int));
00028 static int nsubs Argdcl((struct Listblock*));
00029
00030
00031
00032
00033
00034
00035 void
00036 doequiv(Void)
00037 {
00038 register int i;
00039 int inequiv;
00040
00041 int comno;
00042
00043
00044 int ovarno;
00045 ftnint comoffset;
00046 ftnint offset;
00047 ftnint leng;
00048 register struct Equivblock *equivdecl;
00049 register struct Eqvchain *q;
00050 struct Primblock *primp;
00051 register Namep np;
00052 int k, k1, ns, pref, t;
00053 chainp cp;
00054 extern int type_pref[];
00055
00056 for(i = 0 ; i < nequiv ; ++i)
00057 {
00058
00059
00060
00061 equivdecl = &eqvclass[i];
00062 equivdecl->eqvbottom = equivdecl->eqvtop = 0;
00063 comno = -1;
00064
00065
00066
00067 for(q = equivdecl->equivs ; q ; q = q->eqvnextp)
00068 {
00069 offset = 0;
00070 if (!(primp = q->eqvitem.eqvlhs))
00071 continue;
00072 vardcl(np = primp->namep);
00073 if(primp->argsp || primp->fcharp)
00074 {
00075 expptr offp;
00076
00077
00078
00079 if(np->vdim!=NULL && np->vdim->ndim>1 &&
00080 nsubs(primp->argsp)==1 )
00081 {
00082 if(! ftn66flag)
00083 warni
00084 ("1-dim subscript in EQUIVALENCE, %d-dim declared",
00085 np -> vdim -> ndim);
00086 cp = NULL;
00087 ns = np->vdim->ndim;
00088 while(--ns > 0)
00089 cp = mkchain((char *)ICON(1), cp);
00090 primp->argsp->listp->nextp = cp;
00091 }
00092
00093 offp = suboffset(primp);
00094 if(ISICON(offp))
00095 offset = offp->constblock.Const.ci;
00096 else {
00097 dclerr
00098 ("nonconstant subscript in equivalence ",
00099 np);
00100 np = NULL;
00101 }
00102 frexpr(offp);
00103 }
00104
00105
00106
00107 frexpr((expptr)primp);
00108
00109 if(np && (leng = iarrlen(np))<0)
00110 {
00111 dclerr("adjustable in equivalence", np);
00112 np = NULL;
00113 }
00114
00115 if(np) switch(np->vstg)
00116 {
00117 case STGUNKNOWN:
00118 case STGBSS:
00119 case STGEQUIV:
00120 break;
00121
00122 case STGCOMMON:
00123
00124
00125
00126
00127 comno = np->vardesc.varno;
00128 comoffset = np->voffset + offset;
00129 break;
00130
00131 default:
00132 dclerr("bad storage class in equivalence", np);
00133 np = NULL;
00134 break;
00135 }
00136
00137 if(np)
00138 {
00139 q->eqvoffset = offset;
00140
00141
00142
00143
00144 equivdecl->eqvbottom =
00145 lmin(equivdecl->eqvbottom, -offset);
00146
00147
00148
00149
00150 equivdecl->eqvtop =
00151 lmax(equivdecl->eqvtop, leng-offset);
00152 }
00153 q->eqvitem.eqvname = np;
00154 }
00155
00156
00157
00158
00159 if(comno >= 0)
00160
00161
00162
00163
00164 eqvcommon(equivdecl, comno, comoffset);
00165 else for(q = equivdecl->equivs ; q ; q = q->eqvnextp)
00166 {
00167 if(np = q->eqvitem.eqvname)
00168 {
00169 inequiv = NO;
00170 if(np->vstg==STGEQUIV)
00171 if( (ovarno = np->vardesc.varno) == i)
00172 {
00173
00174
00175
00176 if(np->voffset + q->eqvoffset != 0)
00177 dclerr
00178 ("inconsistent equivalence", np);
00179 }
00180 else {
00181 offset = np->voffset;
00182 inequiv = YES;
00183 }
00184
00185 np->vstg = STGEQUIV;
00186 np->vardesc.varno = i;
00187 np->voffset = - q->eqvoffset;
00188
00189 if(inequiv)
00190
00191
00192
00193 eqveqv(i, ovarno, q->eqvoffset + offset);
00194 }
00195 }
00196 }
00197
00198
00199
00200
00201 for(i = 0 ; i < nequiv ; ++i)
00202 {
00203 equivdecl = & eqvclass[i];
00204 if(equivdecl->eqvbottom!=0 || equivdecl->eqvtop!=0) {
00205
00206
00207
00208 k = TYCHAR;
00209 pref = 1;
00210 for(q = equivdecl->equivs ; q; q = q->eqvnextp)
00211 if ((np = q->eqvitem.eqvname)
00212 && !np->veqvadjust) {
00213 np->veqvadjust = 1;
00214 np->voffset -= equivdecl->eqvbottom;
00215 t = typealign[k1 = np->vtype];
00216 if (pref < type_pref[k1]) {
00217 k = k1;
00218 pref = type_pref[k1];
00219 }
00220 if(np->voffset % t != 0) {
00221 dclerr("bad alignment forced by equivalence", np);
00222 --nerr;
00223 }
00224 }
00225 equivdecl->eqvtype = k;
00226 }
00227 freqchain(equivdecl);
00228 }
00229 }
00230
00231
00232
00233
00234
00235
00236
00237 LOCAL void
00238 #ifdef KR_headers
00239 eqvcommon(p, comno, comoffset)
00240 struct Equivblock *p;
00241 int comno;
00242 ftnint comoffset;
00243 #else
00244 eqvcommon(struct Equivblock *p, int comno, ftnint comoffset)
00245 #endif
00246 {
00247 int ovarno;
00248 ftnint k, offq;
00249 register Namep np;
00250 register struct Eqvchain *q;
00251
00252 if(comoffset + p->eqvbottom < 0)
00253 {
00254 errstr("attempt to extend common %s backward",
00255 extsymtab[comno].fextname);
00256 freqchain(p);
00257 return;
00258 }
00259
00260 if( (k = comoffset + p->eqvtop) > extsymtab[comno].extleng)
00261 extsymtab[comno].extleng = k;
00262
00263
00264 for(q = p->equivs ; q ; q = q->eqvnextp)
00265 if(np = q->eqvitem.eqvname)
00266 {
00267 switch(np->vstg)
00268 {
00269 case STGUNKNOWN:
00270 case STGBSS:
00271 np->vstg = STGCOMMON;
00272 np->vcommequiv = 1;
00273 np->vardesc.varno = comno;
00274
00275
00276
00277 np->voffset = comoffset - q->eqvoffset;
00278 break;
00279
00280 case STGEQUIV:
00281 ovarno = np->vardesc.varno;
00282
00283
00284
00285 offq = comoffset - q->eqvoffset - np->voffset;
00286 np->vstg = STGCOMMON;
00287 np->vcommequiv = 1;
00288 np->vardesc.varno = comno;
00289
00290
00291
00292 np->voffset += offq;
00293 if(ovarno != (p - eqvclass))
00294 eqvcommon(&eqvclass[ovarno], comno, offq);
00295 break;
00296
00297 case STGCOMMON:
00298 if(comno != np->vardesc.varno ||
00299 comoffset != np->voffset+q->eqvoffset)
00300 dclerr("inconsistent common usage", np);
00301 break;
00302
00303
00304 default:
00305 badstg("eqvcommon", np->vstg);
00306 }
00307 }
00308
00309 freqchain(p);
00310 p->eqvbottom = p->eqvtop = 0;
00311 }
00312
00313
00314
00315
00316
00317
00318 LOCAL void
00319 #ifdef KR_headers
00320 eqveqv(nvarno, ovarno, delta)
00321 int nvarno;
00322 int ovarno;
00323 ftnint delta;
00324 #else
00325 eqveqv(int nvarno, int ovarno, ftnint delta)
00326 #endif
00327 {
00328 register struct Equivblock *neweqv, *oldeqv;
00329 register Namep np;
00330 struct Eqvchain *q, *q1;
00331
00332 neweqv = eqvclass + nvarno;
00333 oldeqv = eqvclass + ovarno;
00334 neweqv->eqvbottom = lmin(neweqv->eqvbottom, oldeqv->eqvbottom - delta);
00335 neweqv->eqvtop = lmax(neweqv->eqvtop, oldeqv->eqvtop - delta);
00336 oldeqv->eqvbottom = oldeqv->eqvtop = 0;
00337
00338 for(q = oldeqv->equivs ; q ; q = q1)
00339 {
00340 q1 = q->eqvnextp;
00341 if( (np = q->eqvitem.eqvname) && np->vardesc.varno==ovarno)
00342 {
00343 q->eqvnextp = neweqv->equivs;
00344 neweqv->equivs = q;
00345 q->eqvoffset += delta;
00346 np->vardesc.varno = nvarno;
00347 np->voffset -= delta;
00348 }
00349 else free( (charptr) q);
00350 }
00351 oldeqv->equivs = NULL;
00352 }
00353
00354
00355
00356 void
00357 #ifdef KR_headers
00358 freqchain(p)
00359 register struct Equivblock *p;
00360 #else
00361 freqchain(register struct Equivblock *p)
00362 #endif
00363 {
00364 register struct Eqvchain *q, *oq;
00365
00366 for(q = p->equivs ; q ; q = oq)
00367 {
00368 oq = q->eqvnextp;
00369 free( (charptr) q);
00370 }
00371 p->equivs = NULL;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381 LOCAL int
00382 #ifdef KR_headers
00383 nsubs(p)
00384 register struct Listblock *p;
00385 #else
00386 nsubs(register struct Listblock *p)
00387 #endif
00388 {
00389 register int n;
00390 register chainp q;
00391
00392 n = 0;
00393 if(p)
00394 for(q = p->listp ; q ; q = q->nextp)
00395 ++n;
00396
00397 return(n);
00398 }
00399
00400 struct Primblock *
00401 #ifdef KR_headers
00402 primchk(e) expptr e;
00403 #else
00404 primchk(expptr e)
00405 #endif
00406 {
00407 if (e->headblock.tag != TPRIM) {
00408 err("Invalid name in EQUIVALENCE.");
00409 return 0;
00410 }
00411 return &e->primblock;
00412 }