1 /****************************************************************
2 Copyright 1990 by AT&T Bell Laboratories and Bellcore.
4 Permission to use, copy, modify, and distribute this software
5 and its documentation for any purpose and without fee is hereby
6 granted, provided that the above copyright notice appear in all
7 copies and that both that the copyright notice and this
8 permission notice and warranty disclaimer appear in supporting
9 documentation, and that the names of AT&T Bell Laboratories or
10 Bellcore or any of their entities not be used in advertising or
11 publicity pertaining to distribution of the software without
12 specific, written prior permission.
14 AT&T and Bellcore disclaim all warranties with regard to this
15 software, including all implied warranties of merchantability
16 and fitness. In no event shall AT&T or Bellcore be liable for
17 any special, indirect or consequential damages or any damages
18 whatsoever resulting from loss of use, data or profits, whether
19 in an action of contract, negligence or other tortious action,
20 arising out of or in connection with the use or performance of
22 ****************************************************************/
26 int oneof_stg (name, stg, mask)
30 if (stg == STGCOMMON && name) {
31 if ((mask & M(STGEQUIV)))
32 return name->vcommequiv;
33 if ((mask & M(STGCOMMON)))
34 return !name->vcommequiv;
36 return ONEOF(stg, mask);
40 /* op_assign -- given a binary opcode, return the associated assignment
43 int op_assign (opcode)
49 case OPPLUS: retval = OPPLUSEQ; break;
50 case OPMINUS: retval = OPMINUSEQ; break;
51 case OPSTAR: retval = OPSTAREQ; break;
52 case OPSLASH: retval = OPSLASHEQ; break;
53 case OPMOD: retval = OPMODEQ; break;
54 case OPLSHIFT: retval = OPLSHIFTEQ; break;
55 case OPRSHIFT: retval = OPRSHIFTEQ; break;
56 case OPBITAND: retval = OPBITANDEQ; break;
57 case OPBITXOR: retval = OPBITXOREQ; break;
58 case OPBITOR: retval = OPBITOREQ; break;
60 erri ("op_assign: bad opcode '%d'", opcode);
69 Alloc(n) /* error-checking version of malloc */
70 /* ckalloc initializes memory to 0; Alloc does not */
78 sprintf(errbuf, "malloc(%d) failure!", n);
111 cmpstr(a, b, la, lb) /* compare two strings */
112 register char *a, *b;
115 register char *aend, *bend;
158 /* hookup -- Same as LISP NCONC, that is a destructive append of two lists */
161 register chainp x, y;
168 for(p = x ; p->nextp ; p = p->nextp)
176 struct Listblock *mklist(p)
179 register struct Listblock *q;
181 q = ALLOC(Listblock);
197 chains = chains->nextp;
209 register chainp next;
211 register chainp p, prev = 0;
222 /* addunder -- turn a cvarname into an external name */
223 /* The cvarname may already end in _ (to avoid C keywords); */
224 /* if not, it has room for appending an _. */
247 /* copyn -- return a new copy of the input Fortran-string */
253 register char *p, *q;
255 p = q = (char *) Alloc(n);
263 /* copys -- return a new copy of the input C-string */
268 return( copyn( strlen(s)+1 , s) );
273 /* convci -- Convert Fortran-string to integer; assumes that input is a
274 legal number, with no trailing blanks */
283 sum = 10*sum + (*s++ - '0');
287 /* convic - Convert Integer constant to string */
308 /* mkname -- add a new identifier to the environment, including the closed
314 struct Hashentry *hp;
316 register int c, hash, i;
330 /* Add the name to the closed hash table */
335 if( hash == hp->hashval && !strcmp(s0,q->fvarname) )
337 else if(++hp >= lasthash)
340 if(++nintnames >= maxhash-1)
341 many("names", 'n', maxhash); /* Fatal error */
342 hp->varp = q = ALLOC(Nameblock);
344 q->tag = TNAME; /* TNAME means the tag type is NAME */
346 if (c > 7 && noextflag) {
347 sprintf(errbuf, "\"%.35s%s\" over 6 characters long", s0,
348 c > 36 ? "..." : "");
351 q->fvarname = strcpy(mem(c,0), s0);
352 t = q->cvarname = mem(c + i + 1, 0);
354 /* add __ to the end of any name containing _ */
361 else if (in_vector(s0) >= 0) {
369 struct Labelblock *mklabel(l)
372 register struct Labelblock *lp;
377 for(lp = labeltab ; lp < highlabtab ; ++lp)
381 if(++highlabtab > labtabend)
382 many("statement labels", 's', maxstno);
385 lp->labelno = newlabel();
391 lp->labtype = LABUNKNOWN;
399 return( ++lastlabno );
403 /* this label appears in a branch context */
405 struct Labelblock *execlab(stateno)
408 register struct Labelblock *lp;
410 if(lp = mklabel(stateno))
413 warn1("illegal branch to inner block, statement label %s",
415 else if(lp->labdefined == NO)
416 lp->blklevel = blklevel;
417 if(lp->labtype == LABFORMAT)
418 err("may not branch to a format");
420 lp->labtype = LABEXEC;
423 execerr("illegal label %s", convic(stateno));
429 /* find or put a name in the external symbol table */
436 for(p = extsymtab ; p<nextext ; ++p)
437 if(!strcmp(s,p->cextname))
440 if(nextext >= lastext)
441 many("external symbols", 'x', maxext);
443 nextext->fextname = strcpy(gmem(strlen(f)+1,0), f);
444 nextext->cextname = f == s
446 : strcpy(gmem(strlen(s)+1,0), s);
447 nextext->extstg = STGUNKNOWN;
449 nextext->allextp = 0;
450 nextext->extleng = 0;
451 nextext->maxleng = 0;
452 nextext->extinit = 0;
453 nextext->curno = nextext->maxno = 0;
458 Addrp builtin(t, s, dbi)
464 extern chainp used_builtins;
467 if(p->extstg == STGUNKNOWN)
469 else if(p->extstg != STGEXT)
471 errstr("improper use of builtin %s", s);
475 q = ALLOC(Addrblock);
480 q->memno = p - extsymtab;
481 q->dbl_builtin = dbi;
483 /* A NULL pointer here tells you to use memno to check the external
486 q -> uname_tag = UNAM_EXTERN;
488 /* Add to the list of used builtins */
491 add_extern_to_list (q, &used_builtins);
497 add_extern_to_list (addr, list_store)
501 chainp last = CHNULL;
505 if (list_store == (chainp *) NULL || addr == (Addrp) NULL)
509 memno = addr -> memno;
511 for (;list; last = list, list = list -> nextp) {
512 Addrp this = (Addrp) (list -> datap);
514 if (this -> tag == TADDR && this -> uname_tag == UNAM_EXTERN &&
515 this -> memno == memno)
519 if (*list_store == CHNULL)
520 *list_store = mkchain((char *)cpexpr((expptr)addr), CHNULL);
522 last->nextp = mkchain((char *)cpexpr((expptr)addr), CHNULL);
524 } /* add_extern_to_list */
535 for(q = *p; q->nextp ; q = q->nextp)
546 register chainp q, r;
550 frexpr((expptr)q->datap);
567 memcpy((char *)(q = ckalloc(n)), (char *)p, n);
576 return( a>b ? a : b);
582 return(a < b ? a : b);
593 t = t1 >= t2 ? t1 : t2;
594 if(t==TYCOMPLEX && (t1==TYDREAL || t2==TYDREAL) )
601 /* return log base 2 of n if n a power of 2; otherwise -1 */
607 /* trick based on binary representation */
609 if(n<=0 || (n & (n-1))!=0)
612 for(k = 0 ; n >>= 1 ; ++k)
625 rp = rpllist->rplnextp;
626 free( (charptr) rpllist);
633 /* Call a Fortran function with an arbitrary list of arguments */
637 expptr callk(type, name, args)
645 (expptr)builtin(callk_kludge ? callk_kludge : type, name, 0),
647 p->exprblock.vtype = type;
653 expptr call4(type, name, arg1, arg2, arg3, arg4)
656 expptr arg1, arg2, arg3, arg4;
658 struct Listblock *args;
659 args = mklist( mkchain((char *)arg1,
660 mkchain((char *)arg2,
661 mkchain((char *)arg3,
662 mkchain((char *)arg4, CHNULL)) ) ) );
663 return( callk(type, name, (chainp)args) );
669 expptr call3(type, name, arg1, arg2, arg3)
672 expptr arg1, arg2, arg3;
674 struct Listblock *args;
675 args = mklist( mkchain((char *)arg1,
676 mkchain((char *)arg2,
677 mkchain((char *)arg3, CHNULL) ) ) );
678 return( callk(type, name, (chainp)args) );
685 expptr call2(type, name, arg1, arg2)
690 struct Listblock *args;
692 args = mklist( mkchain((char *)arg1, mkchain((char *)arg2, CHNULL) ) );
693 return( callk(type,name, (chainp)args) );
699 expptr call1(type, name, arg)
704 return( callk(type,name, (chainp)mklist(mkchain((char *)arg,CHNULL)) ));
708 expptr call0(type, name)
712 return( callk(type, name, CHNULL) );
717 struct Impldoblock *mkiodo(dospec, list)
720 register struct Impldoblock *q;
722 q = ALLOC(Impldoblock);
724 q->impdospec = dospec;
732 /* ckalloc -- Allocate 1 memory unit of size n, checking for out of
739 if( p = (ptr)calloc(1, (unsigned) n) )
741 fprintf(stderr, "failing to get %d bytes\n",n);
742 Fatal("out of memory");
743 /* NOT REACHED */ return 0;
754 switch(p->exprblock.opcode)
757 return( isaddr(p->exprblock.rightp) );
770 return( isaddr(p->exprblock.leftp) );
782 if(p->headblock.vleng && !ISCONST(p->headblock.vleng))
791 if(ONEOF(p->addrblock.vstg,MSKSTATIC) &&
792 ISCONST(p->addrblock.memoffset) && !useauto)
802 /* addressable -- return True iff it is a constant value, or can be
803 referenced by constant values */
814 return( addressable(p->addrblock.memoffset) );
822 /* isnegative_const -- returns true if the constant is negative. Returns
823 false for imaginary and nonnumeric constants */
825 int isnegative_const (cp)
826 struct Constblock *cp;
833 switch (cp -> vtype) {
836 retval = cp -> Const.ci < 0;
840 retval = cp->vstg ? *cp->Const.cds[0] == '-'
841 : cp->Const.cd[0] < 0.0;
850 } /* isnegative_const */
855 if (cp == (struct Constblock *) NULL)
858 switch (cp -> vtype) {
861 cp -> Const.ci = - cp -> Const.ci;
866 switch(*cp->Const.cds[1]) {
876 cp->Const.cd[1] = -cp->Const.cd[1];
881 switch(*cp->Const.cds[0]) {
891 cp->Const.cd[0] = -cp->Const.cd[0];
895 erri ("negate_const: can't negate type '%d'", cp -> vtype);
898 erri ("negate_const: bad type '%d'",
904 ffilecopy (infp, outfp)
907 while (!feof (infp)) {
908 register c = getc (infp);
915 #define NOT_IN_VECTOR -1
917 /* in_vector -- verifies whether str is in c_keywords.
918 If so, the index is returned else NOT_IN_VECTOR is returned.
919 c_keywords must be in alphabetical order (as defined by strcmp).
925 extern int n_keywords;
926 extern char *c_keywords[];
927 register int n = n_keywords;
928 register char **K = c_keywords;
933 if (!(t = strcmp(str, K[n1])))
934 return K - c_keywords + n1;
944 return NOT_IN_VECTOR;
948 int is_negatable (Const)
952 if (Const != (Constp) NULL)
953 switch (Const -> vtype) {
955 retval = Const -> Const.ci >= -BIGGEST_SHORT;
958 retval = Const -> Const.ci >= -BIGGEST_LONG;
981 static char couldnt[] = "Couldn't open %.80s";
983 if (!(f = fopen(fname, binread))) {
984 warn1(couldnt, fname);
987 if (!(b = fopen(bname, binwrite))) {
988 warn1(couldnt, bname);
997 /* struct_eq -- returns YES if structures have the same field names and
998 types, NO otherwise */
1000 int struct_eq (s1, s2)
1003 struct Dimblock *d1, *d2;
1006 if (s1 == CHNULL && s2 == CHNULL)
1008 for(; s1 && s2; s1 = s1->nextp, s2 = s2->nextp) {
1009 register Namep v1 = (Namep) s1 -> datap;
1010 register Namep v2 = (Namep) s2 -> datap;
1012 if (v1 == (Namep) NULL || v1 -> tag != TNAME ||
1013 v2 == (Namep) NULL || v2 -> tag != TNAME)
1016 if (v1->vtype != v2->vtype || v1->vclass != v2->vclass
1017 || strcmp(v1->fvarname, v2->fvarname))
1020 /* compare dimensions (needed for comparing COMMON blocks) */
1022 if (d1 = v1->vdim) {
1023 if (!(cp1 = (Constp)d1->nelt) || cp1->tag != TCONST)
1025 if (!(d2 = v2->vdim))
1026 if (cp1->Const.ci == 1)
1030 if (!(cp2 = (Constp)d2->nelt) || cp2->tag != TCONST
1031 || cp1->Const.ci != cp2->Const.ci)
1034 else if ((d2 = v2->vdim) && (!(cp2 = (Constp)d2->nelt)
1035 || cp2->tag != TCONST
1036 || cp2->Const.ci != 1))
1038 } /* while s1 != CHNULL && s2 != CHNULL */
1040 return s1 == CHNULL && s2 == CHNULL;