#include "defs" static char mess[ ] = "inconsistent attributes"; attatt(a1 , a2) register struct atblock *a1, *a2; { #define MERGE1(x) {if(a1->x==0) a1->x = a2->x; else if(a2->x!=0 && a1->x!=a2->x) dclerr(mess,"x"+2); } MERGE1(attype); MERGE1(attypep); MERGE1(atprec); MERGE1(atclass); MERGE1(atext); MERGE1(atcommon); MERGE1(atdim); if(a1->atprec!=0 && (a1->attype==TYREAL || a1->attype==TYCOMPLEX) ) a1->attype += (TYLREAL-TYREAL); cfree(a2); } attvars(a , v) register struct atblock * a; register chainp v; { register chainp p; for(p=v; p!=0 ; p = p->nextp) attvr1(a, p->datap); if(a->attype == TYFIELD) cfree(a->attypep); else if(a->attype == TYCHAR) frexpr(a->attypep); cfree(a); } #define MERGE(x,y) {if(v->y==0) v->y = a->x; else if(a->x!=0 && a->x!=v->y) dclerr(mess,"x"+2); } attvr1(a, v) register struct atblock * a; register struct varblock * v; { register chainp p; if(v->vdcldone) { dclerr("attempt to declare variable after use", v->sthead->namep); return; } v->vdclstart = 1; if(v->vclass == CLMOS) dclerr("attempt to redefine structure member", v->sthead->namep); if (v->vdim == 0) v->vdim = a->atdim; else if(!eqdim(a->atdim, v->vdim)) dclerr("inconsistent dimensions", v->sthead->namep); if(v->vprec == 0) v->vprec = a->atprec; MERGE(attype,vtype); if(v->vtypep == 0) { if(a->attypep != 0) if(a->attype == TYFIELD) { v->vtypep = ALLOC(fieldspec); cpblock(a->attypep, v->vtypep, sizeof(struct fieldspec)); } else if(a->attype == TYCHAR) v->vtypep = cpexpr(a->attypep); else v->vtypep = a->attypep; else if(a->attypep!=0 && a->attypep!=v->vtypep) dclerr("inconsistent attributes", "typep"); } if(v->vprec!=0 && (v->vtype==TYREAL || v->vtype==TYCOMPLEX) ) v->vtype += (TYLREAL-TYREAL); if(a->atcommon) if(v->vclass != 0) dclerr("common variable already in common, argument list, or external", v->sthead->namep); else { if(blklevel != a->atcommon->blklevel) dclerr("inconsistent common block usage", ""); for(p = &(a->atcommon->comchain) ; p->nextp!=0 ; p = p->nextp) ; p->nextp = mkchain(v, PNULL); } if(a->atext!=0 && v->vext==0) { v->vext = 1; extname(v); } else if(a->atclass == CLVALUE) if(v->vclass==CLARG || v->vclass==CLVALUE) v->vclass = CLVALUE; else dclerr("cannot value a non-argument variable",v->sthead->namep); else MERGE(atclass,vclass); if(v->vclass==CLCOMMON || v->vclass==CLVALUE || v->vclass==CLAUTO) setvproc(v, PROCNO); } eqdim(a,b) register ptr a, b; { if(a==0 || b==0 || a==b) return(1); a = a->datap; b = b->datap; while(a!=0 && b!=0) { if(!eqexpr(a->lowerb,b->lowerb) || !eqexpr(a->upperb,b->upperb)) return(0); a = a->nextp; b = b->nextp; } return( a == b ); } eqexpr(a,b) register ptr a, b; { if(a==b) return(1); if(a==0 || b==0) return(0); if(a->tag!=b->tag || a->subtype!=b->subtype) return(0); switch(a->tag) { case TCONST: return( equals(a->leftp, b->leftp) ); case TNAME: return( a->sthead == b->sthead ); case TLIST: a = a->leftp; b = b->leftp; while(a!=0 && b!=0) { if(!eqexpr(a->datap,b->datap)) return(0); a = a->nextp; b = b->nextp; } return( a == b ); case TAROP: case TASGNOP: case TLOGOP: case TRELOP: case TCALL: case TREPOP: return(eqexpr(a->leftp,b->leftp) && eqexpr(a->rightp,b->rightp)); case TNOTOP: case TNEGOP: return(eqexpr(a->leftp,b->leftp)); default: badtag("eqexpr", a->tag); } /* NOTREACHED */ } setimpl(type, c1, c2) int type; register int c1, c2; { register int i; if(c1<'a' || c2'z') dclerr("bad implicit range", CNULL); else if(type==TYUNDEFINED || type>TYLCOMPLEX) dclerr("bad type in implicit statement", CNULL); else for(i = c1 ; i<=c2 ; ++i) impltype[i-'a'] = type; } doinits(p) register ptr p; { register ptr q; for( ; p ; p = p->nextp) if( (q = p->datap)->vinit) { mkinit(q, q->vinit); q->vinit = 0; } } mkinit(v, e) register ptr v; register ptr e; { if(v->vdcldone == 0) dclit(v); swii(idfile); if(v->vtype!=TYCHAR && v->vtypep) dclerr("structure initialization", v->sthead->namep); else if(v->vdim==NULL || v->vsubs!=NULL) { if(e->tag==TLIST && (v->vtype==TYCOMPLEX || v->vtype==TYLCOMPLEX) ) e = compconst(e); valinit(v, e); } else arrinit(v,e); swii(icfile); frexpr(e); } valinit(v, e) register ptr v; register ptr e; { static char buf[4] = "1hX"; int vt; vt = v->vtype; /*check for special case of one-character initialization of non-character datum */ if(vt==TYCHAR || e->vtype!=TYCHAR || !isconst(e) || strlen(e->leftp)!=1) { e = simple(RVAL, coerce(vt,e) ); if(e->tag == TERROR) return; if( ! isconst(e) ) { dclerr("nonconstant initializer", v->sthead->namep); return; } } if(vt == TYCHAR) { charinit(v, e->leftp); return; } prexpr( simple(LVAL,v) ); putic(ICOP,OPSLASH); if(e->vtype != TYCHAR) prexpr(e); else if(strlen(e->leftp) == 1) { buf[2] = e->leftp[0]; putsii(ICCONST, buf); } else dclerr("character initialization of nonchar", v->sthead->namep); putic(ICOP,OPSLASH); putic(ICMARK,0); } arrinit(v, e) register ptr v; register ptr e; { struct exprblock *listinit(), *firstelt(), *nextelt(); ptr arrsize(); if(e->tag!=TLIST && e->tag!=TREPOP) e = mknode(TREPOP, 0, arrsize(v), e); if( listinit(v, firstelt(v), e) ) warn("too few initializers"); if(v->vsubs) { frexpr(v->vsubs); v->vsubs = NULL; } } struct exprblock *listinit(v, subs, e) register struct varblock *v; struct exprblock *subs; register ptr e; { struct varblock *vt; register chainp p; int n; struct varblock *subscript(); struct exprblock *nextelt(); switch(e->tag) { case TLIST: for(p = e->leftp; p; p = p->nextp) { if(subs == NULL) goto toomany; subs = listinit(v, subs, p->datap); } return(subs); case TREPOP: if( ! isicon(e->leftp, &n) ) { dclerr("nonconstant repetition factor"); return(subs); } while(--n >= 0) { if(subs == NULL) goto toomany; subs = listinit(v, subs, e->rightp); } return(subs); default: if(subs == NULL) goto toomany; vt = subscript(cpexpr(v), cpexpr(subs)); valinit(vt, e); frexpr(vt); return( nextelt(v,subs) ); } toomany: dclerr("too many initializers", NULL); return(NULL); } charinit(v,e) ptr v; char *e; { register char *bp; char buf[50]; register int i, j; int nwd, nch; v = cpexpr(v); if(v->vsubs == 0) v->vsubs = mknode(TLIST,0, mkchain(mkint(1),CHNULL), PNULL); nwd = ceil( nch = conval(v->vtypep) , tailor.ftnchwd); sprintf(buf,"%dh", tailor.ftnchwd); for(bp = buf ; *bp ; ++bp ) ; for(i = 0; i 0) v->vsubs->leftp->datap = mknode(TAROP,OPPLUS, v->vsubs->leftp->datap, mkint(1)); prexpr( v = simple(LVAL,v) ); for(j = 0 ; j0 ; ) bp[j++] = *e++; while(j < tailor.ftnchwd) { bp[j++] = ' '; nch--; } bp[j] = '\0'; putic(ICOP,OPSLASH); putsii(ICCONST, buf); putic(ICOP,OPSLASH); putic(ICMARK,0); } frexpr(v); } struct exprblock *firstelt(v) register struct varblock *v; { register struct dimblock *b; register chainp s; ptr t; int junk; if(v->vdim==NULL || v->vsubs!=NULL) fatal("firstelt: bad argument"); s = NULL; for(b = v->vdim->datap ; b; b = b->nextp) { t = (b->lowerb ? cpexpr(b->lowerb) : mkint(1) ); s = hookup(s, mkchain(t,CHNULL) ); if(!isicon(b->upperb,&junk) || (b->lowerb && !isicon(b->lowerb,&junk)) ) dclerr("attempt to initialize adjustable array", v->sthead->namep); } return( mknode(TLIST, 0, s, PNULL) ); } struct exprblock *nextelt(v,subs) struct varblock *v; struct exprblock *subs; { register struct dimblock *b; register chainp *s; int sv; if(v == NULL) return(NULL); b = v->vdim->datap; s = subs->leftp; while(b && s) { sv = conval(s->datap); frexpr(s->datap); if( sv < conval(b->upperb) ) { s->datap =mkint(sv+1); return(subs); } s->datap = (b->lowerb ? cpexpr(b->lowerb) : mkint(1) ); b = b->nextp; s = s->nextp; } if(b || s) fatal("nextelt: bad subscript count"); return(NULL); }