Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

equiv.c File Reference

#include "defs.h"

Go to the source code of this file.


Functions

void eqvcommon Argdcl ((struct Equivblock *, int, long int))
void eqveqv Argdcl ((int, int, long int))
int nsubs Argdcl ((struct Listblock *))
void doequiv (Void)
LOCAL void eqvcommon (struct Equivblock *p, int comno, ftnint comoffset)
LOCAL void eqveqv (int nvarno, int ovarno, ftnint delta)
void freqchain (register struct Equivblock *p)
LOCAL int nsubs (register struct Listblock *p)
Primblockprimchk (expptr e)

Function Documentation

int nsubs Argdcl (struct Listblock *)    [static]
 

void eqveqv Argdcl (int, int, long int)    [static]
 

void eqvcommon Argdcl (struct Equivblock *, int, long int)    [static]
 

void doequiv Void   
 

Definition at line 36 of file equiv.c.

References Primblock::argsp, Constant::ci, Constblock::Const, Expression::constblock, dclerr(), Equivblock::equivs, Equivblock::eqvbottom, eqvcommon(), eqveqv(), Eqvchain::eqvitem, Eqvchain::eqvnextp, Eqvchain::eqvoffset, Equivblock::eqvtop, Equivblock::eqvtype, Primblock::fcharp, freqchain(), frexpr(), i, iarrlen(), ICON, ISICON, Listblock::listp, lmax(), lmin(), mkchain(), Primblock::namep, Chain::nextp, NO, nsubs(), offset, STGBSS, STGCOMMON, STGEQUIV, STGUNKNOWN, suboffset(), type_pref, vardcl(), warni(), and YES.

Referenced by enddcl().

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         char *s;
00056 
00057         for(i = 0 ; i < nequiv ; ++i)
00058         {
00059 
00060 /* Handle each equivalence declaration */
00061 
00062                 equivdecl = &eqvclass[i];
00063                 equivdecl->eqvbottom = equivdecl->eqvtop = 0;
00064                 comno = -1;
00065 
00066 
00067 
00068                 for(q = equivdecl->equivs ; q ; q = q->eqvnextp)
00069                 {
00070                         offset = 0;
00071                         if (!(primp = q->eqvitem.eqvlhs))
00072                                 continue;
00073                         vardcl(np = primp->namep);
00074                         if(primp->argsp || primp->fcharp)
00075                         {
00076                                 expptr offp;
00077 
00078 /* Pad ones onto the end of an array declaration when needed */
00079 
00080                                 if(np->vdim!=NULL && np->vdim->ndim>1 &&
00081                                     nsubs(primp->argsp)==1 )
00082                                 {
00083                                         if(! ftn66flag)
00084                                                 warni
00085                         ("1-dim subscript in EQUIVALENCE, %d-dim declared",
00086                                                     np -> vdim -> ndim);
00087                                         cp = NULL;
00088                                         ns = np->vdim->ndim;
00089                                         while(--ns > 0)
00090                                                 cp = mkchain((char *)ICON(1), cp);
00091                                         primp->argsp->listp->nextp = cp;
00092                                 }
00093 
00094                                 offp = suboffset(primp);
00095                                 if(ISICON(offp))
00096                                         offset = offp->constblock.Const.ci;
00097                                 else    {
00098                                         dclerr
00099                         ("nonconstant subscript in equivalence ",
00100                                             np);
00101                                         np = NULL;
00102                                 }
00103                                 frexpr(offp);
00104                         }
00105 
00106 /* Free up the primblock, since we now have a hash table (Namep) entry */
00107 
00108                         frexpr((expptr)primp);
00109 
00110                         if(np && (leng = iarrlen(np))<0)
00111                         {
00112                                 dclerr("adjustable in equivalence", np);
00113                                 np = NULL;
00114                         }
00115 
00116                         if(np) switch(np->vstg)
00117                         {
00118                         case STGUNKNOWN:
00119                         case STGBSS:
00120                         case STGEQUIV:
00121                                 break;
00122 
00123                         case STGCOMMON:
00124 
00125 /* The code assumes that all COMMON references in a given EQUIVALENCE will
00126    be to the same COMMON block, and will all be consistent */
00127 
00128                                 comno = np->vardesc.varno;
00129                                 comoffset = np->voffset + offset;
00130                                 break;
00131 
00132                         default:
00133                                 dclerr("bad storage class in equivalence", np);
00134                                 np = NULL;
00135                                 break;
00136                         }
00137 
00138                         if(np)
00139                         {
00140                                 q->eqvoffset = offset;
00141 
00142 /* eqvbottom   gets the largest difference between the array base address
00143    and the address specified in the EQUIV declaration */
00144 
00145                                 equivdecl->eqvbottom =
00146                                     lmin(equivdecl->eqvbottom, -offset);
00147 
00148 /* eqvtop   gets the largest difference between the end of the array and
00149    the address given in the EQUIVALENCE */
00150 
00151                                 equivdecl->eqvtop =
00152                                     lmax(equivdecl->eqvtop, leng-offset);
00153                         }
00154                         q->eqvitem.eqvname = np;
00155                 }
00156 
00157 /* Now all equivalenced variables are in the hash table with the proper
00158    offset, and   eqvtop and eqvbottom   are set. */
00159 
00160                 if(comno >= 0)
00161 
00162 /* Get rid of all STGEQUIVS, they will be mapped onto STGCOMMON variables
00163    */
00164 
00165                         eqvcommon(equivdecl, comno, comoffset);
00166                 else for(q = equivdecl->equivs ; q ; q = q->eqvnextp)
00167                 {
00168                         if(np = q->eqvitem.eqvname)
00169                         {
00170                                 inequiv = NO;
00171                                 if(np->vstg==STGEQUIV)
00172                                         if( (ovarno = np->vardesc.varno) == i)
00173                                         {
00174 
00175 /* Can't EQUIV different elements of the same array */
00176 
00177                                                 if(np->voffset + q->eqvoffset != 0)
00178                                                         dclerr
00179                         ("inconsistent equivalence", np);
00180                                         }
00181                                         else    {
00182                                                 offset = np->voffset;
00183                                                 inequiv = YES;
00184                                         }
00185 
00186                                 np->vstg = STGEQUIV;
00187                                 np->vardesc.varno = i;
00188                                 np->voffset = - q->eqvoffset;
00189 
00190                                 if(inequiv)
00191 
00192 /* Combine 2 equivalence declarations */
00193 
00194                                         eqveqv(i, ovarno, q->eqvoffset + offset);
00195                         }
00196                 }
00197         }
00198 
00199 /* Now each equivalence declaration is distinct (all connections have been
00200    merged in eqveqv()), and some may be empty. */
00201 
00202         for(i = 0 ; i < nequiv ; ++i)
00203         {
00204                 equivdecl = & eqvclass[i];
00205                 if(equivdecl->eqvbottom!=0 || equivdecl->eqvtop!=0) {
00206 
00207 /* a live chain */
00208 
00209                         k = TYCHAR;
00210                         pref = 1;
00211                         for(q = equivdecl->equivs ; q; q = q->eqvnextp)
00212                             if ((np = q->eqvitem.eqvname)
00213                                         && !np->veqvadjust) {
00214                                 np->veqvadjust = 1;
00215                                 np->voffset -= equivdecl->eqvbottom;
00216                                 t = typealign[k1 = np->vtype];
00217                                 if (pref < type_pref[k1]) {
00218                                         k = k1;
00219                                         pref = type_pref[k1];
00220                                         }
00221                                 if(np->voffset % t != 0) {
00222                                         dclerr("bad alignment forced by equivalence", np);
00223                                         --nerr; /* don't give bad return code for this */
00224                                         }
00225                                 }
00226                         equivdecl->eqvtype = k;
00227                 }
00228                 freqchain(equivdecl);
00229         }
00230 }

LOCAL void eqvcommon struct Equivblock   p,
int    comno,
ftnint    comoffset
 

Definition at line 245 of file equiv.c.

References badstg(), dclerr(), Equivblock::equivs, Equivblock::eqvbottom, Eqvchain::eqvitem, Eqvchain::eqvnextp, Eqvchain::eqvoffset, Equivblock::eqvtop, errstr(), freqchain(), STGBSS, STGCOMMON, STGEQUIV, STGUNKNOWN, Nameblock::vardesc, Nameblock::vcommequiv, Nameblock::voffset, and Nameblock::vstg.

Referenced by doequiv().

00247 {
00248         int ovarno;
00249         ftnint k, offq;
00250         register Namep np;
00251         register struct Eqvchain *q;
00252 
00253         if(comoffset + p->eqvbottom < 0)
00254         {
00255                 errstr("attempt to extend common %s backward",
00256                     extsymtab[comno].fextname);
00257                 freqchain(p);
00258                 return;
00259         }
00260 
00261         if( (k = comoffset + p->eqvtop) > extsymtab[comno].extleng)
00262                 extsymtab[comno].extleng = k;
00263 
00264 
00265         for(q = p->equivs ; q ; q = q->eqvnextp)
00266                 if(np = q->eqvitem.eqvname)
00267                 {
00268                         switch(np->vstg)
00269                         {
00270                         case STGUNKNOWN:
00271                         case STGBSS:
00272                                 np->vstg = STGCOMMON;
00273                                 np->vcommequiv = 1;
00274                                 np->vardesc.varno = comno;
00275 
00276 /* np -> voffset   will point to the base of the array */
00277 
00278                                 np->voffset = comoffset - q->eqvoffset;
00279                                 break;
00280 
00281                         case STGEQUIV:
00282                                 ovarno = np->vardesc.varno;
00283 
00284 /* offq   will point to the current element, even if it's in an array */
00285 
00286                                 offq = comoffset - q->eqvoffset - np->voffset;
00287                                 np->vstg = STGCOMMON;
00288                                 np->vcommequiv = 1;
00289                                 np->vardesc.varno = comno;
00290 
00291 /* np -> voffset   will point to the base of the array */
00292 
00293                                 np->voffset += offq;
00294                                 if(ovarno != (p - eqvclass))
00295                                         eqvcommon(&eqvclass[ovarno], comno, offq);
00296                                 break;
00297 
00298                         case STGCOMMON:
00299                                 if(comno != np->vardesc.varno ||
00300                                     comoffset != np->voffset+q->eqvoffset)
00301                                         dclerr("inconsistent common usage", np);
00302                                 break;
00303 
00304 
00305                         default:
00306                                 badstg("eqvcommon", np->vstg);
00307                         }
00308                 }
00309 
00310         freqchain(p);
00311         p->eqvbottom = p->eqvtop = 0;
00312 }

LOCAL void eqveqv int    nvarno,
int    ovarno,
ftnint    delta
 

Definition at line 326 of file equiv.c.

References charptr, Equivblock::equivs, Equivblock::eqvbottom, Eqvchain::eqvitem, Eqvchain::eqvnextp, Eqvchain::eqvoffset, Equivblock::eqvtop, free, lmax(), and lmin().

Referenced by doequiv().

00328 {
00329         register struct Equivblock *neweqv, *oldeqv;
00330         register Namep np;
00331         struct Eqvchain *q, *q1;
00332 
00333         neweqv = eqvclass + nvarno;
00334         oldeqv = eqvclass + ovarno;
00335         neweqv->eqvbottom = lmin(neweqv->eqvbottom, oldeqv->eqvbottom - delta);
00336         neweqv->eqvtop = lmax(neweqv->eqvtop, oldeqv->eqvtop - delta);
00337         oldeqv->eqvbottom = oldeqv->eqvtop = 0;
00338 
00339         for(q = oldeqv->equivs ; q ; q = q1)
00340         {
00341                 q1 = q->eqvnextp;
00342                 if( (np = q->eqvitem.eqvname) && np->vardesc.varno==ovarno)
00343                 {
00344                         q->eqvnextp = neweqv->equivs;
00345                         neweqv->equivs = q;
00346                         q->eqvoffset += delta;
00347                         np->vardesc.varno = nvarno;
00348                         np->voffset -= delta;
00349                 }
00350                 else    free( (charptr) q);
00351         }
00352         oldeqv->equivs = NULL;
00353 }

void freqchain register struct Equivblock   p
 

Definition at line 362 of file equiv.c.

References charptr, Equivblock::equivs, Eqvchain::eqvnextp, and free.

Referenced by doequiv(), and eqvcommon().

00364 {
00365         register struct Eqvchain *q, *oq;
00366 
00367         for(q = p->equivs ; q ; q = oq)
00368         {
00369                 oq = q->eqvnextp;
00370                 free( (charptr) q);
00371         }
00372         p->equivs = NULL;
00373 }

LOCAL int nsubs register struct Listblock   p
 

Definition at line 387 of file equiv.c.

References Listblock::listp, Chain::nextp, and q.

Referenced by doequiv().

00389 {
00390         register int n;
00391         register chainp q;
00392 
00393         n = 0;
00394         if(p)
00395                 for(q = p->listp ; q ; q = q->nextp)
00396                         ++n;
00397 
00398         return(n);
00399 }

struct Primblock* primchk expptr    e
 

Definition at line 405 of file equiv.c.

References err, Primblock::tag, and TPRIM.

Referenced by yyparse().

00407 {
00408         if (e->headblock.tag != TPRIM) {
00409                 err("Invalid name in EQUIVALENCE.");
00410                 return 0;
00411                 }
00412         return &e->primblock;
00413         }
 

Powered by Plone

This site conforms to the following standards: