equiv.c

Go to the documentation of this file.
00001 /****************************************************************
00002 Copyright 1990, 1993-6, 2000 by AT&T, Lucent Technologies and Bellcore.
00003 
00004 Permission to use, copy, modify, and distribute this software
00005 and its documentation for any purpose and without fee is hereby
00006 granted, provided that the above copyright notice appear in all
00007 copies and that both that the copyright notice and this
00008 permission notice and warranty disclaimer appear in supporting
00009 documentation, and that the names of AT&T, Bell Laboratories,
00010 Lucent or Bellcore or any of their entities not be used in
00011 advertising or publicity pertaining to distribution of the
00012 software without specific, written prior permission.
00013 
00014 AT&T, Lucent and Bellcore disclaim all warranties with regard to
00015 this software, including all implied warranties of
00016 merchantability and fitness.  In no event shall AT&T, Lucent or
00017 Bellcore be liable for any special, indirect or consequential
00018 damages or any damages whatsoever resulting from loss of use,
00019 data or profits, whether in an action of contract, negligence or
00020 other tortious action, arising out of or in connection with the
00021 use or performance of this software.
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 /* ROUTINES RELATED TO EQUIVALENCE CLASS PROCESSING */
00031 
00032 /* called at end of declarations section to process chains
00033    created by EQUIVALENCE statements
00034  */
00035  void
00036 doequiv(Void)
00037 {
00038         register int i;
00039         int inequiv;                    /* True if one namep occurs in
00040                                            several EQUIV declarations */
00041         int comno;              /* Index into Extsym table of the last
00042                                    COMMON block seen (implicitly assuming
00043                                    that only one will be given) */
00044         int ovarno;
00045         ftnint comoffset;       /* Index into the COMMON block */
00046         ftnint offset;          /* Offset from array base */
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 /* Handle each equivalence declaration */
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 /* Pad ones onto the end of an array declaration when needed */
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 /* Free up the primblock, since we now have a hash table (Namep) entry */
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 /* The code assumes that all COMMON references in a given EQUIVALENCE will
00125    be to the same COMMON block, and will all be consistent */
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 /* eqvbottom   gets the largest difference between the array base address
00142    and the address specified in the EQUIV declaration */
00143 
00144                                 equivdecl->eqvbottom =
00145                                     lmin(equivdecl->eqvbottom, -offset);
00146 
00147 /* eqvtop   gets the largest difference between the end of the array and
00148    the address given in the EQUIVALENCE */
00149 
00150                                 equivdecl->eqvtop =
00151                                     lmax(equivdecl->eqvtop, leng-offset);
00152                         }
00153                         q->eqvitem.eqvname = np;
00154                 }
00155 
00156 /* Now all equivalenced variables are in the hash table with the proper
00157    offset, and   eqvtop and eqvbottom   are set. */
00158 
00159                 if(comno >= 0)
00160 
00161 /* Get rid of all STGEQUIVS, they will be mapped onto STGCOMMON variables
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 /* Can't EQUIV different elements of the same array */
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 /* Combine 2 equivalence declarations */
00192 
00193                                         eqveqv(i, ovarno, q->eqvoffset + offset);
00194                         }
00195                 }
00196         }
00197 
00198 /* Now each equivalence declaration is distinct (all connections have been
00199    merged in eqveqv()), and some may be empty. */
00200 
00201         for(i = 0 ; i < nequiv ; ++i)
00202         {
00203                 equivdecl = & eqvclass[i];
00204                 if(equivdecl->eqvbottom!=0 || equivdecl->eqvtop!=0) {
00205 
00206 /* a live chain */
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; /* don't give bad return code for this */
00223                                         }
00224                                 }
00225                         equivdecl->eqvtype = k;
00226                 }
00227                 freqchain(equivdecl);
00228         }
00229 }
00230 
00231 
00232 
00233 
00234 
00235 /* put equivalence chain p at common block comno + comoffset */
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 /* np -> voffset   will point to the base of the array */
00276 
00277                                 np->voffset = comoffset - q->eqvoffset;
00278                                 break;
00279 
00280                         case STGEQUIV:
00281                                 ovarno = np->vardesc.varno;
00282 
00283 /* offq   will point to the current element, even if it's in an array */
00284 
00285                                 offq = comoffset - q->eqvoffset - np->voffset;
00286                                 np->vstg = STGCOMMON;
00287                                 np->vcommequiv = 1;
00288                                 np->vardesc.varno = comno;
00289 
00290 /* np -> voffset   will point to the base of the array */
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 /* Move all items on ovarno chain to the front of   nvarno   chain.
00315  * adjust offsets of ovarno elements and top and bottom of nvarno chain
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 /* nsubs -- number of subscripts in this arglist (just the length of the
00379    list) */
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         }

Generated on Sun Mar 4 15:03:44 2007 for Scilab [trunk] by  doxygen 1.5.1