home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- Copyright 1990 by AT&T Bell Laboratories and Bellcore.
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the names of AT&T Bell Laboratories or
- Bellcore or any of their entities not be used in advertising or
- publicity pertaining to distribution of the software without
- specific, written prior permission.
-
- AT&T and Bellcore disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall AT&T or Bellcore be liable for
- any special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
- ****************************************************************/
-
- #include "defs.h"
-
- int oneof_stg (name, stg, mask)
- Namep name;
- int stg, mask;
- {
- if (stg == STGCOMMON && name) {
- if ((mask & M(STGEQUIV)))
- return name->vcommequiv;
- if ((mask & M(STGCOMMON)))
- return !name->vcommequiv;
- }
- return ONEOF(stg, mask);
- }
-
-
- /* op_assign -- given a binary opcode, return the associated assignment
- operator */
-
- int op_assign (opcode)
- int opcode;
- {
- int retval = -1;
-
- switch (opcode) {
- case OPPLUS: retval = OPPLUSEQ; break;
- case OPMINUS: retval = OPMINUSEQ; break;
- case OPSTAR: retval = OPSTAREQ; break;
- case OPSLASH: retval = OPSLASHEQ; break;
- case OPMOD: retval = OPMODEQ; break;
- case OPLSHIFT: retval = OPLSHIFTEQ; break;
- case OPRSHIFT: retval = OPRSHIFTEQ; break;
- case OPBITAND: retval = OPBITANDEQ; break;
- case OPBITXOR: retval = OPBITXOREQ; break;
- case OPBITOR: retval = OPBITOREQ; break;
- default:
- erri ("op_assign: bad opcode '%d'", opcode);
- break;
- } /* switch */
-
- return retval;
- } /* op_assign */
-
-
- char *
- Alloc(n) /* error-checking version of malloc */
- /* ckalloc initializes memory to 0; Alloc does not */
- int n;
- {
- char errbuf[32];
- register char *rv;
-
- rv = malloc(n);
- if (!rv) {
- sprintf(errbuf, "malloc(%d) failure!", n);
- Fatal(errbuf);
- }
- return rv;
- }
-
-
- cpn(n, a, b)
- register int n;
- register char *a, *b;
- {
- while(--n >= 0)
- *b++ = *a++;
- }
-
-
-
- eqn(n, a, b)
- register int n;
- register char *a, *b;
- {
- while(--n >= 0)
- if(*a++ != *b++)
- return(NO);
- return(YES);
- }
-
-
-
-
-
-
-
- cmpstr(a, b, la, lb) /* compare two strings */
- register char *a, *b;
- ftnint la, lb;
- {
- register char *aend, *bend;
- aend = a + la;
- bend = b + lb;
-
-
- if(la <= lb)
- {
- while(a < aend)
- if(*a != *b)
- return( *a - *b );
- else
- {
- ++a;
- ++b;
- }
-
- while(b < bend)
- if(*b != ' ')
- return(' ' - *b);
- else
- ++b;
- }
-
- else
- {
- while(b < bend)
- if(*a != *b)
- return( *a - *b );
- else
- {
- ++a;
- ++b;
- }
- while(a < aend)
- if(*a != ' ')
- return(*a - ' ');
- else
- ++a;
- }
- return(0);
- }
-
-
- /* hookup -- Same as LISP NCONC, that is a destructive append of two lists */
-
- chainp hookup(x,y)
- register chainp x, y;
- {
- register chainp p;
-
- if(x == NULL)
- return(y);
-
- for(p = x ; p->nextp ; p = p->nextp)
- ;
- p->nextp = y;
- return(x);
- }
-
-
-
- struct Listblock *mklist(p)
- chainp p;
- {
- register struct Listblock *q;
-
- q = ALLOC(Listblock);
- q->tag = TLIST;
- q->listp = p;
- return(q);
- }
-
-
- chainp mkchain(p,q)
- register char * p;
- register chainp q;
- {
- register chainp r;
-
- if(chains)
- {
- r = chains;
- chains = chains->nextp;
- }
- else
- r = ALLOC(Chain);
-
- r->datap = p;
- r->nextp = q;
- return(r);
- }
-
- chainp
- revchain(next)
- register chainp next;
- {
- register chainp p, prev = 0;
-
- while(p = next) {
- next = p->nextp;
- p->nextp = prev;
- prev = p;
- }
- return prev;
- }
-
-
- /* addunder -- turn a cvarname into an external name */
- /* The cvarname may already end in _ (to avoid C keywords); */
- /* if not, it has room for appending an _. */
-
- char *
- addunder(s)
- register char *s;
- {
- register int c, i;
- char *s0 = s;
-
- i = 0;
- while(c = *s++)
- if (c == '_')
- i++;
- else
- i = 0;
- if (!i) {
- *s-- = 0;
- *s = '_';
- }
- return( s0 );
- }
-
-
- /* copyn -- return a new copy of the input Fortran-string */
-
- char *copyn(n, s)
- register int n;
- register char *s;
- {
- register char *p, *q;
-
- p = q = (char *) Alloc(n);
- while(--n >= 0)
- *q++ = *s++;
- return(p);
- }
-
-
-
- /* copys -- return a new copy of the input C-string */
-
- char *copys(s)
- char *s;
- {
- return( copyn( strlen(s)+1 , s) );
- }
-
-
-
- /* convci -- Convert Fortran-string to integer; assumes that input is a
- legal number, with no trailing blanks */
-
- ftnint convci(n, s)
- register int n;
- register char *s;
- {
- ftnint sum;
- sum = 0;
- while(n-- > 0)
- sum = 10*sum + (*s++ - '0');
- return(sum);
- }
-
- /* convic - Convert Integer constant to string */
-
- char *convic(n)
- ftnint n;
- {
- static char s[20];
- register char *t;
-
- s[19] = '\0';
- t = s+19;
-
- do {
- *--t = '0' + n%10;
- n /= 10;
- } while(n > 0);
-
- return(t);
- }
-
-
-
- /* mkname -- add a new identifier to the environment, including the closed
- hash table. */
-
- Namep mkname(s)
- register char *s;
- {
- struct Hashentry *hp;
- register Namep q;
- register int c, hash, i;
- register char *t;
- char *s0;
- char errbuf[64];
-
- hash = i = 0;
- s0 = s;
- while(c = *s++) {
- hash += c;
- if (c == '_')
- i = 1;
- }
- hash %= maxhash;
-
- /* Add the name to the closed hash table */
-
- hp = hashtab + hash;
-
- while(q = hp->varp)
- if( hash == hp->hashval && !strcmp(s0,q->fvarname) )
- return(q);
- else if(++hp >= lasthash)
- hp = hashtab;
-
- if(++nintnames >= maxhash-1)
- many("names", 'n', maxhash); /* Fatal error */
- hp->varp = q = ALLOC(Nameblock);
- hp->hashval = hash;
- q->tag = TNAME; /* TNAME means the tag type is NAME */
- c = s - s0;
- if (c > 7 && noextflag) {
- sprintf(errbuf, "\"%.35s%s\" over 6 characters long", s0,
- c > 36 ? "..." : "");
- errext(errbuf);
- }
- q->fvarname = strcpy(mem(c,0), s0);
- t = q->cvarname = mem(c + i + 1, 0);
- s = s0;
- /* add __ to the end of any name containing _ */
- while(*t = *s++)
- t++;
- if (i) {
- t[0] = t[1] = '_';
- t[2] = 0;
- }
- else if (in_vector(s0) >= 0) {
- t[0] = '_';
- t[1] = 0;
- }
- return(q);
- }
-
-
- struct Labelblock *mklabel(l)
- ftnint l;
- {
- register struct Labelblock *lp;
-
- if(l <= 0)
- return(NULL);
-
- for(lp = labeltab ; lp < highlabtab ; ++lp)
- if(lp->stateno == l)
- return(lp);
-
- if(++highlabtab > labtabend)
- many("statement labels", 's', maxstno);
-
- lp->stateno = l;
- lp->labelno = newlabel();
- lp->blklevel = 0;
- lp->labused = NO;
- lp->fmtlabused = NO;
- lp->labdefined = NO;
- lp->labinacc = NO;
- lp->labtype = LABUNKNOWN;
- lp->fmtstring = 0;
- return(lp);
- }
-
-
- newlabel()
- {
- return( ++lastlabno );
- }
-
-
- /* this label appears in a branch context */
-
- struct Labelblock *execlab(stateno)
- ftnint stateno;
- {
- register struct Labelblock *lp;
-
- if(lp = mklabel(stateno))
- {
- if(lp->labinacc)
- warn1("illegal branch to inner block, statement label %s",
- convic(stateno) );
- else if(lp->labdefined == NO)
- lp->blklevel = blklevel;
- if(lp->labtype == LABFORMAT)
- err("may not branch to a format");
- else
- lp->labtype = LABEXEC;
- }
- else
- execerr("illegal label %s", convic(stateno));
-
- return(lp);
- }
-
-
- /* find or put a name in the external symbol table */
-
- Extsym *mkext(f,s)
- char *f, *s;
- {
- Extsym *p;
-
- for(p = extsymtab ; p<nextext ; ++p)
- if(!strcmp(s,p->cextname))
- return( p );
-
- if(nextext >= lastext)
- many("external symbols", 'x', maxext);
-
- nextext->fextname = strcpy(gmem(strlen(f)+1,0), f);
- nextext->cextname = f == s
- ? nextext->fextname
- : strcpy(gmem(strlen(s)+1,0), s);
- nextext->extstg = STGUNKNOWN;
- nextext->extp = 0;
- nextext->allextp = 0;
- nextext->extleng = 0;
- nextext->maxleng = 0;
- nextext->extinit = 0;
- nextext->curno = nextext->maxno = 0;
- return( nextext++ );
- }
-
-
- Addrp builtin(t, s, dbi)
- int t, dbi;
- char *s;
- {
- register Extsym *p;
- register Addrp q;
- extern chainp used_builtins;
-
- p = mkext(s,s);
- if(p->extstg == STGUNKNOWN)
- p->extstg = STGEXT;
- else if(p->extstg != STGEXT)
- {
- errstr("improper use of builtin %s", s);
- return(0);
- }
-
- q = ALLOC(Addrblock);
- q->tag = TADDR;
- q->vtype = t;
- q->vclass = CLPROC;
- q->vstg = STGEXT;
- q->memno = p - extsymtab;
- q->dbl_builtin = dbi;
-
- /* A NULL pointer here tells you to use memno to check the external
- symbol table */
-
- q -> uname_tag = UNAM_EXTERN;
-
- /* Add to the list of used builtins */
-
- if (dbi >= 0)
- add_extern_to_list (q, &used_builtins);
- return(q);
- }
-
-
-
- add_extern_to_list (addr, list_store)
- Addrp addr;
- chainp *list_store;
- {
- chainp last = CHNULL;
- chainp list;
- int memno;
-
- if (list_store == (chainp *) NULL || addr == (Addrp) NULL)
- return;
-
- list = *list_store;
- memno = addr -> memno;
-
- for (;list; last = list, list = list -> nextp) {
- Addrp this = (Addrp) (list -> datap);
-
- if (this -> tag == TADDR && this -> uname_tag == UNAM_EXTERN &&
- this -> memno == memno)
- return;
- } /* for */
-
- if (*list_store == CHNULL)
- *list_store = mkchain((char *)cpexpr((expptr)addr), CHNULL);
- else
- last->nextp = mkchain((char *)cpexpr((expptr)addr), CHNULL);
-
- } /* add_extern_to_list */
-
-
- frchain(p)
- register chainp *p;
- {
- register chainp q;
-
- if(p==0 || *p==0)
- return;
-
- for(q = *p; q->nextp ; q = q->nextp)
- ;
- q->nextp = chains;
- chains = *p;
- *p = 0;
- }
-
- void
- frexchain(p)
- register chainp *p;
- {
- register chainp q, r;
-
- if (q = *p) {
- for(;;q = r) {
- frexpr((expptr)q->datap);
- if (!(r = q->nextp))
- break;
- }
- q->nextp = chains;
- chains = *p;
- *p = 0;
- }
- }
-
-
- tagptr cpblock(n,p)
- register int n;
- register char * p;
- {
- register ptr q;
-
- memcpy((char *)(q = ckalloc(n)), (char *)p, n);
- return( (tagptr) q);
- }
-
-
-
- ftnint lmax(a, b)
- ftnint a, b;
- {
- return( a>b ? a : b);
- }
-
- ftnint lmin(a, b)
- ftnint a, b;
- {
- return(a < b ? a : b);
- }
-
-
-
-
- maxtype(t1, t2)
- int t1, t2;
- {
- int t;
-
- t = t1 >= t2 ? t1 : t2;
- if(t==TYCOMPLEX && (t1==TYDREAL || t2==TYDREAL) )
- t = TYDCOMPLEX;
- return(t);
- }
-
-
-
- /* return log base 2 of n if n a power of 2; otherwise -1 */
- log_2(n)
- ftnint n;
- {
- int k;
-
- /* trick based on binary representation */
-
- if(n<=0 || (n & (n-1))!=0)
- return(-1);
-
- for(k = 0 ; n >>= 1 ; ++k)
- ;
- return(k);
- }
-
-
-
- frrpl()
- {
- struct Rplblock *rp;
-
- while(rpllist)
- {
- rp = rpllist->rplnextp;
- free( (charptr) rpllist);
- rpllist = rp;
- }
- }
-
-
-
- /* Call a Fortran function with an arbitrary list of arguments */
-
- int callk_kludge;
-
- expptr callk(type, name, args)
- int type;
- char *name;
- chainp args;
- {
- register expptr p;
-
- p = mkexpr(OPCALL,
- (expptr)builtin(callk_kludge ? callk_kludge : type, name, 0),
- (expptr)args);
- p->exprblock.vtype = type;
- return(p);
- }
-
-
-
- expptr call4(type, name, arg1, arg2, arg3, arg4)
- int type;
- char *name;
- expptr arg1, arg2, arg3, arg4;
- {
- struct Listblock *args;
- args = mklist( mkchain((char *)arg1,
- mkchain((char *)arg2,
- mkchain((char *)arg3,
- mkchain((char *)arg4, CHNULL)) ) ) );
- return( callk(type, name, (chainp)args) );
- }
-
-
-
-
- expptr call3(type, name, arg1, arg2, arg3)
- int type;
- char *name;
- expptr arg1, arg2, arg3;
- {
- struct Listblock *args;
- args = mklist( mkchain((char *)arg1,
- mkchain((char *)arg2,
- mkchain((char *)arg3, CHNULL) ) ) );
- return( callk(type, name, (chainp)args) );
- }
-
-
-
-
-
- expptr call2(type, name, arg1, arg2)
- int type;
- char *name;
- expptr arg1, arg2;
- {
- struct Listblock *args;
-
- args = mklist( mkchain((char *)arg1, mkchain((char *)arg2, CHNULL) ) );
- return( callk(type,name, (chainp)args) );
- }
-
-
-
-
- expptr call1(type, name, arg)
- int type;
- char *name;
- expptr arg;
- {
- return( callk(type,name, (chainp)mklist(mkchain((char *)arg,CHNULL)) ));
- }
-
-
- expptr call0(type, name)
- int type;
- char *name;
- {
- return( callk(type, name, CHNULL) );
- }
-
-
-
- struct Impldoblock *mkiodo(dospec, list)
- chainp dospec, list;
- {
- register struct Impldoblock *q;
-
- q = ALLOC(Impldoblock);
- q->tag = TIMPLDO;
- q->impdospec = dospec;
- q->datalist = list;
- return(q);
- }
-
-
-
-
- /* ckalloc -- Allocate 1 memory unit of size n, checking for out of
- memory error */
-
- ptr ckalloc(n)
- register int n;
- {
- register ptr p;
- if( p = (ptr)calloc(1, (unsigned) n) )
- return(p);
- fprintf(stderr, "failing to get %d bytes\n",n);
- Fatal("out of memory");
- /* NOT REACHED */ return 0;
- }
-
-
-
- isaddr(p)
- register expptr p;
- {
- if(p->tag == TADDR)
- return(YES);
- if(p->tag == TEXPR)
- switch(p->exprblock.opcode)
- {
- case OPCOMMA:
- return( isaddr(p->exprblock.rightp) );
-
- case OPASSIGN:
- case OPASSIGNI:
- case OPPLUSEQ:
- case OPMINUSEQ:
- case OPSLASHEQ:
- case OPMODEQ:
- case OPLSHIFTEQ:
- case OPRSHIFTEQ:
- case OPBITANDEQ:
- case OPBITXOREQ:
- case OPBITOREQ:
- return( isaddr(p->exprblock.leftp) );
- }
- return(NO);
- }
-
-
-
-
- isstatic(p)
- register expptr p;
- {
- extern int useauto;
- if(p->headblock.vleng && !ISCONST(p->headblock.vleng))
- return(NO);
-
- switch(p->tag)
- {
- case TCONST:
- return(YES);
-
- case TADDR:
- if(ONEOF(p->addrblock.vstg,MSKSTATIC) &&
- ISCONST(p->addrblock.memoffset) && !useauto)
- return(YES);
-
- default:
- return(NO);
- }
- }
-
-
-
- /* addressable -- return True iff it is a constant value, or can be
- referenced by constant values */
-
- addressable(p)
- register expptr p;
- {
- switch(p->tag)
- {
- case TCONST:
- return(YES);
-
- case TADDR:
- return( addressable(p->addrblock.memoffset) );
-
- default:
- return(NO);
- }
- }
-
-
- /* isnegative_const -- returns true if the constant is negative. Returns
- false for imaginary and nonnumeric constants */
-
- int isnegative_const (cp)
- struct Constblock *cp;
- {
- int retval;
-
- if (cp == NULL)
- return 0;
-
- switch (cp -> vtype) {
- case TYSHORT:
- case TYLONG:
- retval = cp -> Const.ci < 0;
- break;
- case TYREAL:
- case TYDREAL:
- retval = cp->vstg ? *cp->Const.cds[0] == '-'
- : cp->Const.cd[0] < 0.0;
- break;
- default:
-
- retval = 0;
- break;
- } /* switch */
-
- return retval;
- } /* isnegative_const */
-
- negate_const(cp)
- Constp cp;
- {
- if (cp == (struct Constblock *) NULL)
- return;
-
- switch (cp -> vtype) {
- case TYSHORT:
- case TYLONG:
- cp -> Const.ci = - cp -> Const.ci;
- break;
- case TYCOMPLEX:
- case TYDCOMPLEX:
- if (cp->vstg)
- switch(*cp->Const.cds[1]) {
- case '-':
- ++cp->Const.cds[1];
- break;
- case '0':
- break;
- default:
- --cp->Const.cds[1];
- }
- else
- cp->Const.cd[1] = -cp->Const.cd[1];
- /* no break */
- case TYREAL:
- case TYDREAL:
- if (cp->vstg)
- switch(*cp->Const.cds[0]) {
- case '-':
- ++cp->Const.cds[0];
- break;
- case '0':
- break;
- default:
- --cp->Const.cds[0];
- }
- else
- cp->Const.cd[0] = -cp->Const.cd[0];
- break;
- case TYCHAR:
- case TYLOGICAL:
- erri ("negate_const: can't negate type '%d'", cp -> vtype);
- break;
- default:
- erri ("negate_const: bad type '%d'",
- cp -> vtype);
- break;
- } /* switch */
- } /* negate_const */
-
- ffilecopy (infp, outfp)
- FILE *infp, *outfp;
- {
- while (!feof (infp)) {
- register c = getc (infp);
- if (!feof (infp))
- putc (c, outfp);
- } /* while */
- } /* ffilecopy */
-
-
- #define NOT_IN_VECTOR -1
-
- /* in_vector -- verifies whether str is in c_keywords.
- If so, the index is returned else NOT_IN_VECTOR is returned.
- c_keywords must be in alphabetical order (as defined by strcmp).
- */
-
- int in_vector(str)
- char *str;
- {
- extern int n_keywords;
- extern char *c_keywords[];
- register int n = n_keywords;
- register char **K = c_keywords;
- register int n1, t;
- extern int strcmp();
-
- do {
- n1 = n >> 1;
- if (!(t = strcmp(str, K[n1])))
- return K - c_keywords + n1;
- if (t < 0)
- n = n1;
- else {
- n -= ++n1;
- K += n1;
- }
- }
- while(n > 0);
-
- return NOT_IN_VECTOR;
- } /* in_vector */
-
-
- int is_negatable (Const)
- Constp Const;
- {
- int retval = 0;
- if (Const != (Constp) NULL)
- switch (Const -> vtype) {
- case TYSHORT:
- retval = Const -> Const.ci >= -BIGGEST_SHORT;
- break;
- case TYLONG:
- retval = Const -> Const.ci >= -BIGGEST_LONG;
- break;
- case TYREAL:
- case TYDREAL:
- case TYCOMPLEX:
- case TYDCOMPLEX:
- retval = 1;
- break;
- case TYLOGICAL:
- case TYCHAR:
- case TYSUBR:
- default:
- retval = 0;
- break;
- } /* switch */
-
- return retval;
- } /* is_negatable */
-
- backup(fname, bname)
- char *fname, *bname;
- {
- FILE *b, *f;
- static char couldnt[] = "Couldn't open %.80s";
-
- if (!(f = fopen(fname, binread))) {
- warn1(couldnt, fname);
- return;
- }
- if (!(b = fopen(bname, binwrite))) {
- warn1(couldnt, bname);
- return;
- }
- ffilecopy(f, b);
- fclose(f);
- fclose(b);
- }
-
-
- /* struct_eq -- returns YES if structures have the same field names and
- types, NO otherwise */
-
- int struct_eq (s1, s2)
- chainp s1, s2;
- {
- struct Dimblock *d1, *d2;
- Constp cp1, cp2;
-
- if (s1 == CHNULL && s2 == CHNULL)
- return YES;
- for(; s1 && s2; s1 = s1->nextp, s2 = s2->nextp) {
- register Namep v1 = (Namep) s1 -> datap;
- register Namep v2 = (Namep) s2 -> datap;
-
- if (v1 == (Namep) NULL || v1 -> tag != TNAME ||
- v2 == (Namep) NULL || v2 -> tag != TNAME)
- return NO;
-
- if (v1->vtype != v2->vtype || v1->vclass != v2->vclass
- || strcmp(v1->fvarname, v2->fvarname))
- return NO;
-
- /* compare dimensions (needed for comparing COMMON blocks) */
-
- if (d1 = v1->vdim) {
- if (!(cp1 = (Constp)d1->nelt) || cp1->tag != TCONST)
- return NO;
- if (!(d2 = v2->vdim))
- if (cp1->Const.ci == 1)
- continue;
- else
- return NO;
- if (!(cp2 = (Constp)d2->nelt) || cp2->tag != TCONST
- || cp1->Const.ci != cp2->Const.ci)
- return NO;
- }
- else if ((d2 = v2->vdim) && (!(cp2 = (Constp)d2->nelt)
- || cp2->tag != TCONST
- || cp2->Const.ci != 1))
- return NO;
- } /* while s1 != CHNULL && s2 != CHNULL */
-
- return s1 == CHNULL && s2 == CHNULL;
- } /* struct_eq */
-