xref: /csrg-svn/usr.bin/f77/pass1.tahoe/expr.c (revision 47951)
1*47951Sbostic /*-
2*47951Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*47951Sbostic  * All rights reserved.
4*47951Sbostic  *
5*47951Sbostic  * %sccs.include.proprietary.c%
640230Sdonn  */
740230Sdonn 
840230Sdonn #ifndef lint
9*47951Sbostic static char sccsid[] = "@(#)expr.c	1.4 (Berkeley) 04/12/91";
10*47951Sbostic #endif /* not lint */
1140230Sdonn 
1240230Sdonn /*
1340230Sdonn  * expr.c
1440230Sdonn  *
1540230Sdonn  * Routines for handling expressions, f77 compiler pass 1.
1640230Sdonn  *
1740230Sdonn  * University of Utah CS Dept modification history:
1840230Sdonn  *
1940230Sdonn  * $Log:	expr.c,v $
2040230Sdonn  * Revision 1.3  86/02/26  17:13:37  rcs
2140230Sdonn  * Correct COFR 411.
2240230Sdonn  * P. Wong
2340230Sdonn  *
2440230Sdonn  * Revision 3.16  85/06/21  16:38:09  donn
2540230Sdonn  * The fix to mkprim() didn't handle null substring parameters (sigh).
2640230Sdonn  *
2740230Sdonn  * Revision 3.15  85/06/04  04:37:03  donn
2840230Sdonn  * Changed mkprim() to force substring parameters to be integral types.
2940230Sdonn  *
3040230Sdonn  * Revision 3.14  85/06/04  03:41:52  donn
3140230Sdonn  * Change impldcl() to handle functions of type 'undefined'.
3240230Sdonn  *
3340230Sdonn  * Revision 3.13  85/05/06  23:14:55  donn
3440230Sdonn  * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
3540230Sdonn  * a temporary when converting character strings to integers; previously we
3640230Sdonn  * were having problems because mkconv() was called after tempalloc().
3740230Sdonn  *
3840230Sdonn  * Revision 3.12  85/03/18  08:07:47  donn
3940230Sdonn  * Fixes to help out with short integers -- if integers are by default short,
4040230Sdonn  * then so are constants; and if addresses can't be stored in shorts, complain.
4140230Sdonn  *
4240230Sdonn  * Revision 3.11  85/03/16  22:31:27  donn
4340230Sdonn  * Added hack to mkconv() to allow character values of length > 1 to be
4440230Sdonn  * converted to numeric types, for Helge Skrivervik.  Note that this does
4540230Sdonn  * not affect use of the intrinsic ichar() conversion.
4640230Sdonn  *
4740230Sdonn  * Revision 3.10  85/01/15  21:06:47  donn
4840230Sdonn  * Changed mkconv() to comment on implicit conversions; added intrconv() for
4940230Sdonn  * use with explicit conversions by intrinsic functions.
5040230Sdonn  *
5140230Sdonn  * Revision 3.9  85/01/11  21:05:49  donn
5240230Sdonn  * Added changes to implement SAVE statements.
5340230Sdonn  *
5440230Sdonn  * Revision 3.8  84/12/17  02:21:06  donn
5540230Sdonn  * Added a test to prevent constant folding from being done on expressions
5640230Sdonn  * whose type is not known at that point in mkexpr().
5740230Sdonn  *
5840230Sdonn  * Revision 3.7  84/12/11  21:14:17  donn
5940230Sdonn  * Removed obnoxious 'excess precision' warning.
6040230Sdonn  *
6140230Sdonn  * Revision 3.6  84/11/23  01:00:36  donn
6240230Sdonn  * Added code to trim excess precision from single-precision constants, and
6340230Sdonn  * to warn the user when this occurs.
6440230Sdonn  *
6540230Sdonn  * Revision 3.5  84/11/23  00:10:39  donn
6640230Sdonn  * Changed stfcall() to remark on argument type clashes in 'calls' to
6740230Sdonn  * statement functions.
6840230Sdonn  *
6940230Sdonn  * Revision 3.4  84/11/22  21:21:17  donn
7040230Sdonn  * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
7140230Sdonn  *
7240230Sdonn  * Revision 3.3  84/11/12  18:26:14  donn
7340230Sdonn  * Shuffled some code around so that the compiler remembers to free some vleng
7440230Sdonn  * structures which used to just sit around.
7540230Sdonn  *
7640230Sdonn  * Revision 3.2  84/10/16  19:24:15  donn
7740230Sdonn  * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
7840230Sdonn  * core dumps by replacing bad subscripts with good ones.
7940230Sdonn  *
8040230Sdonn  * Revision 3.1  84/10/13  01:31:32  donn
8140230Sdonn  * Merged Jerry Berkman's version into mine.
8240230Sdonn  *
8340230Sdonn  * Revision 2.7  84/09/27  15:42:52  donn
8440230Sdonn  * The last fix for multiplying undeclared variables by 0 isn't sufficient,
8540230Sdonn  * since the type of the 0 may not be the (implicit) type of the variable.
8640230Sdonn  * I added a hack to check the implicit type of implicitly declared
8740230Sdonn  * variables...
8840230Sdonn  *
8940230Sdonn  * Revision 2.6  84/09/14  19:34:03  donn
9040230Sdonn  * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
9140230Sdonn  * 0 to type UNKNOWN, which is illegal.  Fix is to use native type instead.
9240230Sdonn  * Not sure how correct (or important) this is...
9340230Sdonn  *
9440230Sdonn  * Revision 2.5  84/08/05  23:05:27  donn
9540230Sdonn  * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
9640230Sdonn  * with two operands.
9740230Sdonn  *
9840230Sdonn  * Revision 2.4  84/08/05  17:34:48  donn
9940230Sdonn  * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
10040230Sdonn  * and assign constant length 1 to them.
10140230Sdonn  *
10240230Sdonn  * Revision 2.3  84/07/19  19:38:33  donn
10340230Sdonn  * Added a typecast to the last fix.  Somehow I missed it the first time...
10440230Sdonn  *
10540230Sdonn  * Revision 2.2  84/07/19  17:19:57  donn
10640230Sdonn  * Caused OPPAREN expressions to inherit the length of their operands, so
10740230Sdonn  * that parenthesized character expressions work correctly.
10840230Sdonn  *
10940230Sdonn  * Revision 2.1  84/07/19  12:03:02  donn
11040230Sdonn  * Changed comment headers for UofU.
11140230Sdonn  *
11240230Sdonn  * Revision 1.2  84/04/06  20:12:17  donn
11340230Sdonn  * Fixed bug which caused programs with mixed-type multiplications involving
11440230Sdonn  * the constant 0 to choke the compiler.
11540230Sdonn  *
11640230Sdonn  */
11740230Sdonn 
11840230Sdonn #include "defs.h"
11940230Sdonn 
12040230Sdonn 
12140230Sdonn /* little routines to create constant blocks */
12240230Sdonn 
mkconst(t)12340230Sdonn Constp mkconst(t)
12440230Sdonn register int t;
12540230Sdonn {
12640230Sdonn register Constp p;
12740230Sdonn 
12840230Sdonn p = ALLOC(Constblock);
12940230Sdonn p->tag = TCONST;
13040230Sdonn p->vtype = t;
13140230Sdonn return(p);
13240230Sdonn }
13340230Sdonn 
13440230Sdonn 
mklogcon(l)13540230Sdonn expptr mklogcon(l)
13640230Sdonn register int l;
13740230Sdonn {
13840230Sdonn register Constp  p;
13940230Sdonn 
14040230Sdonn p = mkconst(TYLOGICAL);
14146303Sbostic p->constant.ci = l;
14240230Sdonn return( (expptr) p );
14340230Sdonn }
14440230Sdonn 
14540230Sdonn 
14640230Sdonn 
mkintcon(l)14740230Sdonn expptr mkintcon(l)
14840230Sdonn ftnint l;
14940230Sdonn {
15040230Sdonn register Constp p;
15140230Sdonn int usetype;
15240230Sdonn 
15340230Sdonn if(tyint == TYSHORT)
15440230Sdonn   {
15540230Sdonn     short s = l;
15640230Sdonn     if(l != s)
15740230Sdonn       usetype = TYLONG;
15840230Sdonn     else
15940230Sdonn       usetype = TYSHORT;
16040230Sdonn   }
16140230Sdonn else
16240230Sdonn   usetype = tyint;
16340230Sdonn p = mkconst(usetype);
16446303Sbostic p->constant.ci = l;
16540230Sdonn return( (expptr) p );
16640230Sdonn }
16740230Sdonn 
16840230Sdonn 
16940230Sdonn 
mkaddcon(l)17040230Sdonn expptr mkaddcon(l)
17140230Sdonn register int l;
17240230Sdonn {
17340230Sdonn register Constp p;
17440230Sdonn 
17540230Sdonn p = mkconst(TYADDR);
17646303Sbostic p->constant.ci = l;
17740230Sdonn return( (expptr) p );
17840230Sdonn }
17940230Sdonn 
18040230Sdonn 
18140230Sdonn 
mkrealcon(t,d)18240230Sdonn expptr mkrealcon(t, d)
18340230Sdonn register int t;
18440230Sdonn double d;
18540230Sdonn {
18640230Sdonn register Constp p;
18740230Sdonn 
18840230Sdonn p = mkconst(t);
18946303Sbostic p->constant.cd[0] = d;
19040230Sdonn return( (expptr) p );
19140230Sdonn }
19240230Sdonn 
mkbitcon(shift,leng,s)19340230Sdonn expptr mkbitcon(shift, leng, s)
19440230Sdonn int shift;
19540230Sdonn register int leng;
19640230Sdonn register char *s;
19740230Sdonn {
19840230Sdonn   Constp p;
19940230Sdonn   register int i, j, k;
20040230Sdonn   register char *bp;
20140230Sdonn   int size;
20240230Sdonn 
20340230Sdonn   size = (shift*leng + BYTESIZE -1)/BYTESIZE;
20440230Sdonn   bp = (char *) ckalloc(size);
20540230Sdonn 
20640230Sdonn   i = 0;
20740230Sdonn 
20840230Sdonn #if (HERE == PDP11 || HERE == VAX)
20940230Sdonn   j = 0;
21040230Sdonn #else
21140230Sdonn   j = size;
21240230Sdonn #endif
21340230Sdonn 
21440230Sdonn   k = 0;
21540230Sdonn 
21640230Sdonn   while (leng > 0)
21740230Sdonn     {
21840230Sdonn       k |= (hextoi(s[--leng]) << i);
21940230Sdonn       i += shift;
22040230Sdonn       if (i >= BYTESIZE)
22140230Sdonn 	{
22240230Sdonn #if (HERE == PDP11 || HERE == VAX)
22340230Sdonn 	  bp[j++] = k & MAXBYTE;
22440230Sdonn #else
22540230Sdonn 	  bp[--j] = k & MAXBYTE;
22640230Sdonn #endif
22740230Sdonn 	  k = k >> BYTESIZE;
22840230Sdonn 	  i -= BYTESIZE;
22940230Sdonn 	}
23040230Sdonn     }
23140230Sdonn 
23240230Sdonn   if (k != 0)
23340230Sdonn #if (HERE == PDP11 || HERE == VAX)
23440230Sdonn     bp[j++] = k;
23540230Sdonn #else
23640230Sdonn     bp[--j] = k;
23740230Sdonn #endif
23840230Sdonn 
23940230Sdonn   p = mkconst(TYBITSTR);
24040230Sdonn   p->vleng = ICON(size);
24146303Sbostic   p->constant.ccp = bp;
24240230Sdonn 
24340230Sdonn   return ((expptr) p);
24440230Sdonn }
24540230Sdonn 
24640230Sdonn 
24740230Sdonn 
mkstrcon(l,v)24840230Sdonn expptr mkstrcon(l,v)
24940230Sdonn int l;
25040230Sdonn register char *v;
25140230Sdonn {
25240230Sdonn register Constp p;
25340230Sdonn register char *s;
25440230Sdonn 
25540230Sdonn p = mkconst(TYCHAR);
25640230Sdonn p->vleng = ICON(l);
25746303Sbostic p->constant.ccp = s = (char *) ckalloc(l);
25840230Sdonn while(--l >= 0)
25940230Sdonn 	*s++ = *v++;
26040230Sdonn return( (expptr) p );
26140230Sdonn }
26240230Sdonn 
26340230Sdonn 
mkcxcon(realp,imagp)26440230Sdonn expptr mkcxcon(realp,imagp)
26540230Sdonn register expptr realp, imagp;
26640230Sdonn {
26740230Sdonn int rtype, itype;
26840230Sdonn register Constp p;
26940230Sdonn 
27040230Sdonn rtype = realp->headblock.vtype;
27140230Sdonn itype = imagp->headblock.vtype;
27240230Sdonn 
27340230Sdonn if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
27440230Sdonn 	{
27540230Sdonn 	p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
27640230Sdonn 	if( ISINT(rtype) )
27746303Sbostic 		p->constant.cd[0] = realp->constblock.constant.ci;
27846303Sbostic 	else	p->constant.cd[0] = realp->constblock.constant.cd[0];
27940230Sdonn 	if( ISINT(itype) )
28046303Sbostic 		p->constant.cd[1] = imagp->constblock.constant.ci;
28146303Sbostic 	else	p->constant.cd[1] = imagp->constblock.constant.cd[0];
28240230Sdonn 	}
28340230Sdonn else
28440230Sdonn 	{
28540230Sdonn 	err("invalid complex constant");
28640230Sdonn 	p = (Constp) errnode();
28740230Sdonn 	}
28840230Sdonn 
28940230Sdonn frexpr(realp);
29040230Sdonn frexpr(imagp);
29140230Sdonn return( (expptr) p );
29240230Sdonn }
29340230Sdonn 
29440230Sdonn 
errnode()29540230Sdonn expptr errnode()
29640230Sdonn {
29740230Sdonn struct Errorblock *p;
29840230Sdonn p = ALLOC(Errorblock);
29940230Sdonn p->tag = TERROR;
30040230Sdonn p->vtype = TYERROR;
30140230Sdonn return( (expptr) p );
30240230Sdonn }
30340230Sdonn 
30440230Sdonn 
30540230Sdonn 
30640230Sdonn 
30740230Sdonn 
mkconv(t,p)30840230Sdonn expptr mkconv(t, p)
30940230Sdonn register int t;
31040230Sdonn register expptr p;
31140230Sdonn {
31240230Sdonn register expptr q;
31340230Sdonn Addrp r, s;
31440230Sdonn register int pt;
31540230Sdonn expptr opconv();
31640230Sdonn 
31740230Sdonn if(t==TYUNKNOWN || t==TYERROR)
31840230Sdonn 	badtype("mkconv", t);
31940230Sdonn pt = p->headblock.vtype;
32040230Sdonn if(t == pt)
32140230Sdonn 	return(p);
32240230Sdonn 
32340230Sdonn if( pt == TYCHAR && ISNUMERIC(t) )
32440230Sdonn 	{
32540230Sdonn 	warn("implicit conversion of character to numeric type");
32640230Sdonn 
32740230Sdonn 	/*
32840230Sdonn 	 * Ugly kluge to copy character values into numerics.
32940230Sdonn 	 */
33040230Sdonn 	s = mkaltemp(t, ENULL);
33140230Sdonn 	r = (Addrp) cpexpr(s);
33240230Sdonn 	r->vtype = TYCHAR;
33340230Sdonn 	r->varleng = typesize[t];
33440230Sdonn 	r->vleng = mkintcon(r->varleng);
33540230Sdonn 	q = mkexpr(OPASSIGN, r, p);
33640230Sdonn 	q = mkexpr(OPCOMMA, q, s);
33740230Sdonn 	return(q);
33840230Sdonn 	}
33940230Sdonn 
34040230Sdonn #if SZADDR > SZSHORT
34140230Sdonn if( pt == TYADDR && t == TYSHORT)
34240230Sdonn 	{
34340230Sdonn 	err("insufficient precision to hold address type");
34440230Sdonn 	return( errnode() );
34540230Sdonn 	}
34640230Sdonn #endif
34740230Sdonn if( pt == TYADDR && ISNUMERIC(t) )
34840230Sdonn 	warn("implicit conversion of address to numeric type");
34940230Sdonn 
35040230Sdonn if( ISCONST(p) && pt!=TYADDR)
35140230Sdonn 	{
35240230Sdonn 	q = (expptr) mkconst(t);
35346303Sbostic 	consconv(t, &(q->constblock.constant),
35446303Sbostic 		p->constblock.vtype, &(p->constblock.constant) );
35540230Sdonn 	frexpr(p);
35640230Sdonn 	}
35740230Sdonn #if TARGET == PDP11
35840230Sdonn else if(ISINT(t) && pt==TYCHAR)
35940230Sdonn 	{
36040230Sdonn 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
36140230Sdonn 	if(t == TYLONG)
36240230Sdonn 		q = opconv(q, TYLONG);
36340230Sdonn 	}
36440230Sdonn #endif
36540230Sdonn else
36640230Sdonn 	q = opconv(p, t);
36740230Sdonn 
36840230Sdonn if(t == TYCHAR)
36940230Sdonn 	q->constblock.vleng = ICON(1);
37040230Sdonn return(q);
37140230Sdonn }
37240230Sdonn 
37340230Sdonn 
37440230Sdonn 
37540230Sdonn /* intrinsic conversions */
intrconv(t,p)37640230Sdonn expptr intrconv(t, p)
37740230Sdonn register int t;
37840230Sdonn register expptr p;
37940230Sdonn {
38040230Sdonn register expptr q;
38140230Sdonn register int pt;
38240230Sdonn expptr opconv();
38340230Sdonn 
38440230Sdonn if(t==TYUNKNOWN || t==TYERROR)
38540230Sdonn 	badtype("intrconv", t);
38640230Sdonn pt = p->headblock.vtype;
38740230Sdonn if(t == pt)
38840230Sdonn 	return(p);
38940230Sdonn 
39040230Sdonn else if( ISCONST(p) && pt!=TYADDR)
39140230Sdonn 	{
39240230Sdonn 	q = (expptr) mkconst(t);
39346303Sbostic 	consconv(t, &(q->constblock.constant),
39446303Sbostic 		p->constblock.vtype, &(p->constblock.constant) );
39540230Sdonn 	frexpr(p);
39640230Sdonn 	}
39740230Sdonn #if TARGET == PDP11
39840230Sdonn else if(ISINT(t) && pt==TYCHAR)
39940230Sdonn 	{
40040230Sdonn 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
40140230Sdonn 	if(t == TYLONG)
40240230Sdonn 		q = opconv(q, TYLONG);
40340230Sdonn 	}
40440230Sdonn #endif
40540230Sdonn else
40640230Sdonn 	q = opconv(p, t);
40740230Sdonn 
40840230Sdonn if(t == TYCHAR)
40940230Sdonn 	q->constblock.vleng = ICON(1);
41040230Sdonn return(q);
41140230Sdonn }
41240230Sdonn 
41340230Sdonn 
41440230Sdonn 
opconv(p,t)41540230Sdonn expptr opconv(p, t)
41640230Sdonn expptr p;
41740230Sdonn int t;
41840230Sdonn {
41940230Sdonn register expptr q;
42040230Sdonn 
42140230Sdonn q = mkexpr(OPCONV, p, PNULL);
42240230Sdonn q->headblock.vtype = t;
42340230Sdonn return(q);
42440230Sdonn }
42540230Sdonn 
42640230Sdonn 
42740230Sdonn 
addrof(p)42840230Sdonn expptr addrof(p)
42940230Sdonn expptr p;
43040230Sdonn {
43140230Sdonn return( mkexpr(OPADDR, p, PNULL) );
43240230Sdonn }
43340230Sdonn 
43440230Sdonn 
43540230Sdonn 
cpexpr(p)43640230Sdonn tagptr cpexpr(p)
43740230Sdonn register tagptr p;
43840230Sdonn {
43940230Sdonn register tagptr e;
44040230Sdonn int tag;
44140230Sdonn register chainp ep, pp;
44240230Sdonn tagptr cpblock();
44340230Sdonn 
44440230Sdonn static int blksize[ ] =
44540230Sdonn 	{	0,
44640230Sdonn 		sizeof(struct Nameblock),
44740230Sdonn 		sizeof(struct Constblock),
44840230Sdonn 		sizeof(struct Exprblock),
44940230Sdonn 		sizeof(struct Addrblock),
45040230Sdonn 		sizeof(struct Tempblock),
45140230Sdonn 		sizeof(struct Primblock),
45240230Sdonn 		sizeof(struct Listblock),
45340230Sdonn 		sizeof(struct Errorblock)
45440230Sdonn 	};
45540230Sdonn 
45640230Sdonn if(p == NULL)
45740230Sdonn 	return(NULL);
45840230Sdonn 
45940230Sdonn if( (tag = p->tag) == TNAME)
46040230Sdonn 	return(p);
46140230Sdonn 
46240230Sdonn e = cpblock( blksize[p->tag] , p);
46340230Sdonn 
46440230Sdonn switch(tag)
46540230Sdonn 	{
46640230Sdonn 	case TCONST:
46740230Sdonn 		if(e->constblock.vtype == TYCHAR)
46840230Sdonn 			{
46946303Sbostic 			e->constblock.constant.ccp =
47046303Sbostic 				copyn(1+strlen(e->constblock.constant.ccp),
47146303Sbostic 					e->constblock.constant.ccp);
47240230Sdonn 			e->constblock.vleng =
47340230Sdonn 				(expptr) cpexpr(e->constblock.vleng);
47440230Sdonn 			}
47540230Sdonn 	case TERROR:
47640230Sdonn 		break;
47740230Sdonn 
47840230Sdonn 	case TEXPR:
47940230Sdonn 		e->exprblock.leftp =  (expptr) cpexpr(p->exprblock.leftp);
48040230Sdonn 		e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
48140230Sdonn 		break;
48240230Sdonn 
48340230Sdonn 	case TLIST:
48440230Sdonn 		if(pp = p->listblock.listp)
48540230Sdonn 			{
48640230Sdonn 			ep = e->listblock.listp =
48740230Sdonn 				mkchain( cpexpr(pp->datap), CHNULL);
48840230Sdonn 			for(pp = pp->nextp ; pp ; pp = pp->nextp)
48940230Sdonn 				ep = ep->nextp =
49040230Sdonn 					mkchain( cpexpr(pp->datap), CHNULL);
49140230Sdonn 			}
49240230Sdonn 		break;
49340230Sdonn 
49440230Sdonn 	case TADDR:
49540230Sdonn 		e->addrblock.vleng = (expptr)  cpexpr(e->addrblock.vleng);
49640230Sdonn 		e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
49740230Sdonn 		e->addrblock.istemp = NO;
49840230Sdonn 		break;
49940230Sdonn 
50040230Sdonn 	case TTEMP:
50140230Sdonn 		e->tempblock.vleng = (expptr)  cpexpr(e->tempblock.vleng);
50240230Sdonn 		e->tempblock.istemp = NO;
50340230Sdonn 		break;
50440230Sdonn 
50540230Sdonn 	case TPRIM:
50640230Sdonn 		e->primblock.argsp = (struct Listblock *)
50740230Sdonn 					cpexpr(e->primblock.argsp);
50840230Sdonn 		e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
50940230Sdonn 		e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
51040230Sdonn 		break;
51140230Sdonn 
51240230Sdonn 	default:
51340230Sdonn 		badtag("cpexpr", tag);
51440230Sdonn 	}
51540230Sdonn 
51640230Sdonn return(e);
51740230Sdonn }
51840230Sdonn 
frexpr(p)51940230Sdonn frexpr(p)
52040230Sdonn register tagptr p;
52140230Sdonn {
52240230Sdonn register chainp q;
52340230Sdonn 
52440230Sdonn if(p == NULL)
52540230Sdonn 	return;
52640230Sdonn 
52740230Sdonn switch(p->tag)
52840230Sdonn 	{
52940230Sdonn 	case TCONST:
53040230Sdonn 		switch (p->constblock.vtype)
53140230Sdonn 			{
53240230Sdonn 			case TYBITSTR:
53340230Sdonn 			case TYCHAR:
53440230Sdonn 			case TYHOLLERITH:
53546303Sbostic 				free( (charptr) (p->constblock.constant.ccp) );
53640230Sdonn 				frexpr(p->constblock.vleng);
53740230Sdonn 			}
53840230Sdonn 		break;
53940230Sdonn 
54040230Sdonn 	case TADDR:
54140230Sdonn 		if (!optimflag && p->addrblock.istemp)
54240230Sdonn 			{
54340230Sdonn 			frtemp(p);
54440230Sdonn 			return;
54540230Sdonn 			}
54640230Sdonn 		frexpr(p->addrblock.vleng);
54740230Sdonn 		frexpr(p->addrblock.memoffset);
54840230Sdonn 		break;
54940230Sdonn 
55040230Sdonn 	case TTEMP:
55140230Sdonn 		frexpr(p->tempblock.vleng);
55240230Sdonn 		break;
55340230Sdonn 
55440230Sdonn 	case TERROR:
55540230Sdonn 		break;
55640230Sdonn 
55740230Sdonn 	case TNAME:
55840230Sdonn 		return;
55940230Sdonn 
56040230Sdonn 	case TPRIM:
56140230Sdonn 		frexpr(p->primblock.argsp);
56240230Sdonn 		frexpr(p->primblock.fcharp);
56340230Sdonn 		frexpr(p->primblock.lcharp);
56440230Sdonn 		break;
56540230Sdonn 
56640230Sdonn 	case TEXPR:
56740230Sdonn 		frexpr(p->exprblock.leftp);
56840230Sdonn 		if(p->exprblock.rightp)
56940230Sdonn 			frexpr(p->exprblock.rightp);
57040230Sdonn 		break;
57140230Sdonn 
57240230Sdonn 	case TLIST:
57340230Sdonn 		for(q = p->listblock.listp ; q ; q = q->nextp)
57440230Sdonn 			frexpr(q->datap);
57540230Sdonn 		frchain( &(p->listblock.listp) );
57640230Sdonn 		break;
57740230Sdonn 
57840230Sdonn 	default:
57940230Sdonn 		badtag("frexpr", p->tag);
58040230Sdonn 	}
58140230Sdonn 
58240230Sdonn free( (charptr) p );
58340230Sdonn }
58440230Sdonn 
58540230Sdonn /* fix up types in expression; replace subtrees and convert
58640230Sdonn    names to address blocks */
58740230Sdonn 
fixtype(p)58840230Sdonn expptr fixtype(p)
58940230Sdonn register tagptr p;
59040230Sdonn {
59140230Sdonn 
59240230Sdonn if(p == 0)
59340230Sdonn 	return(0);
59440230Sdonn 
59540230Sdonn switch(p->tag)
59640230Sdonn 	{
59740230Sdonn 	case TCONST:
59840230Sdonn 		return( (expptr) p );
59940230Sdonn 
60040230Sdonn 	case TADDR:
60140230Sdonn 		p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
60240230Sdonn 		return( (expptr) p);
60340230Sdonn 
60440230Sdonn 	case TTEMP:
60540230Sdonn 		return( (expptr) p);
60640230Sdonn 
60740230Sdonn 	case TERROR:
60840230Sdonn 		return( (expptr) p);
60940230Sdonn 
61040230Sdonn 	default:
61140230Sdonn 		badtag("fixtype", p->tag);
61240230Sdonn 
61340230Sdonn 	case TEXPR:
61440230Sdonn 		return( fixexpr(p) );
61540230Sdonn 
61640230Sdonn 	case TLIST:
61740230Sdonn 		return( (expptr) p );
61840230Sdonn 
61940230Sdonn 	case TPRIM:
62040230Sdonn 		if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
62140230Sdonn 			{
62240230Sdonn 			if(p->primblock.namep->vtype == TYSUBR)
62340230Sdonn 				{
62440230Sdonn 				err("function invocation of subroutine");
62540230Sdonn 				return( errnode() );
62640230Sdonn 				}
62740230Sdonn 			else
62840230Sdonn 				return( mkfunct(p) );
62940230Sdonn 			}
63040230Sdonn 		else	return( mklhs(p) );
63140230Sdonn 	}
63240230Sdonn }
63340230Sdonn 
63440230Sdonn 
63540230Sdonn 
63640230Sdonn 
63740230Sdonn 
63840230Sdonn /* special case tree transformations and cleanups of expression trees */
63940230Sdonn 
fixexpr(p)64040230Sdonn expptr fixexpr(p)
64140230Sdonn register Exprp p;
64240230Sdonn {
64340230Sdonn expptr lp;
64440230Sdonn register expptr rp;
64540230Sdonn register expptr q;
64640230Sdonn int opcode, ltype, rtype, ptype, mtype;
64740230Sdonn expptr lconst, rconst;
64840230Sdonn expptr mkpower();
64940230Sdonn 
65040230Sdonn if( ISERROR(p) )
65140230Sdonn 	return( (expptr) p );
65240230Sdonn else if(p->tag != TEXPR)
65340230Sdonn 	badtag("fixexpr", p->tag);
65440230Sdonn opcode = p->opcode;
65540230Sdonn if (ISCONST(p->leftp))
65640230Sdonn 	lconst = (expptr) cpexpr(p->leftp);
65740230Sdonn else
65840230Sdonn 	lconst = NULL;
65940230Sdonn if (p->rightp && ISCONST(p->rightp))
66040230Sdonn 	rconst = (expptr) cpexpr(p->rightp);
66140230Sdonn else
66240230Sdonn 	rconst = NULL;
66340230Sdonn lp = p->leftp = fixtype(p->leftp);
66440230Sdonn ltype = lp->headblock.vtype;
66540230Sdonn if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
66640230Sdonn 	{
66740230Sdonn 	err("left side of assignment must be variable");
66840230Sdonn 	frexpr(p);
66940230Sdonn 	return( errnode() );
67040230Sdonn 	}
67140230Sdonn 
67240230Sdonn if(p->rightp)
67340230Sdonn 	{
67440230Sdonn 	rp = p->rightp = fixtype(p->rightp);
67540230Sdonn 	rtype = rp->headblock.vtype;
67640230Sdonn 	}
67740230Sdonn else
67840230Sdonn 	{
67940230Sdonn 	rp = NULL;
68040230Sdonn 	rtype = 0;
68140230Sdonn 	}
68240230Sdonn 
68340230Sdonn if(ltype==TYERROR || rtype==TYERROR)
68440230Sdonn 	{
68540230Sdonn 	frexpr(p);
68640230Sdonn 	frexpr(lconst);
68740230Sdonn 	frexpr(rconst);
68840230Sdonn 	return( errnode() );
68940230Sdonn 	}
69040230Sdonn 
69140230Sdonn /* force folding if possible */
69240230Sdonn if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
69340230Sdonn 	{
69440230Sdonn 	q = mkexpr(opcode, lp, rp);
69540230Sdonn 	if( ISCONST(q) )
69640230Sdonn 		{
69740230Sdonn 		frexpr(lconst);
69840230Sdonn 		frexpr(rconst);
69940230Sdonn 		return(q);
70040230Sdonn 		}
70140230Sdonn 	free( (charptr) q );	/* constants did not fold */
70240230Sdonn 	}
70340230Sdonn 
70440230Sdonn if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
70540230Sdonn 	{
70640230Sdonn 	frexpr(p);
70740230Sdonn 	frexpr(lconst);
70840230Sdonn 	frexpr(rconst);
70940230Sdonn 	return( errnode() );
71040230Sdonn 	}
71140230Sdonn 
71240230Sdonn switch(opcode)
71340230Sdonn 	{
71440230Sdonn 	case OPCONCAT:
71540230Sdonn 		if(p->vleng == NULL)
71640230Sdonn 			p->vleng = mkexpr(OPPLUS,
71740230Sdonn 				cpexpr(lp->headblock.vleng),
71840230Sdonn 				cpexpr(rp->headblock.vleng) );
71940230Sdonn 		break;
72040230Sdonn 
72140230Sdonn 	case OPASSIGN:
72240230Sdonn 	case OPPLUSEQ:
72340230Sdonn 	case OPSTAREQ:
72440230Sdonn 		if(ltype == rtype)
72540230Sdonn 			break;
72640230Sdonn #if TARGET == VAX
72740230Sdonn 		if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
72840230Sdonn 			break;
72940230Sdonn #endif
73040230Sdonn 		if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
73140230Sdonn 			break;
73240230Sdonn 		if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
73340230Sdonn #if FAMILY==PCC
73440230Sdonn 		    && typesize[ltype]>=typesize[rtype] )
73540230Sdonn #else
73640230Sdonn 		    && typesize[ltype]==typesize[rtype] )
73740230Sdonn #endif
73840230Sdonn 			break;
73940230Sdonn 		if (rconst)
74040230Sdonn 			{
74140230Sdonn 			p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
74240230Sdonn 			frexpr(rp);
74340230Sdonn 			}
74440230Sdonn 		else
74540230Sdonn 			p->rightp = fixtype(mkconv(ptype, rp));
74640230Sdonn 		break;
74740230Sdonn 
74840230Sdonn 	case OPSLASH:
74940230Sdonn 		if( ISCOMPLEX(rtype) )
75040230Sdonn 			{
75140230Sdonn 			p = (Exprp) call2(ptype,
75240230Sdonn 				ptype==TYCOMPLEX? "c_div" : "z_div",
75340230Sdonn 				mkconv(ptype, lp), mkconv(ptype, rp) );
75440230Sdonn 			break;
75540230Sdonn 			}
75640230Sdonn 	case OPPLUS:
75740230Sdonn 	case OPMINUS:
75840230Sdonn 	case OPSTAR:
75940230Sdonn 	case OPMOD:
76040230Sdonn #if TARGET == VAX
76140230Sdonn 		if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
76240230Sdonn 		    (rtype==TYREAL && ! rconst ) ))
76340230Sdonn 			break;
76440230Sdonn #endif
76540230Sdonn 		if( ISCOMPLEX(ptype) )
76640230Sdonn 			break;
76740230Sdonn 		if(ltype != ptype)
76840230Sdonn 			if (lconst)
76940230Sdonn 				{
77040230Sdonn 				p->leftp = fixtype(mkconv(ptype,
77140230Sdonn 						cpexpr(lconst)));
77240230Sdonn 				frexpr(lp);
77340230Sdonn 				}
77440230Sdonn 			else
77540230Sdonn 				p->leftp = fixtype(mkconv(ptype,lp));
77640230Sdonn 		if(rtype != ptype)
77740230Sdonn 			if (rconst)
77840230Sdonn 				{
77940230Sdonn 				p->rightp = fixtype(mkconv(ptype,
78040230Sdonn 						cpexpr(rconst)));
78140230Sdonn 				frexpr(rp);
78240230Sdonn 				}
78340230Sdonn 			else
78440230Sdonn 				p->rightp = fixtype(mkconv(ptype,rp));
78540230Sdonn 		break;
78640230Sdonn 
78740230Sdonn 	case OPPOWER:
78840230Sdonn 		return( mkpower(p) );
78940230Sdonn 
79040230Sdonn 	case OPLT:
79140230Sdonn 	case OPLE:
79240230Sdonn 	case OPGT:
79340230Sdonn 	case OPGE:
79440230Sdonn 	case OPEQ:
79540230Sdonn 	case OPNE:
79640230Sdonn 		if(ltype == rtype)
79740230Sdonn 			break;
79840230Sdonn 		mtype = cktype(OPMINUS, ltype, rtype);
79940230Sdonn #if TARGET == VAX
80040230Sdonn 		if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
80140230Sdonn 		    (rtype==TYREAL && ! rconst) ))
80240230Sdonn 			break;
80340230Sdonn #endif
80440230Sdonn 		if( ISCOMPLEX(mtype) )
80540230Sdonn 			break;
80640230Sdonn 		if(ltype != mtype)
80740230Sdonn 			if (lconst)
80840230Sdonn 				{
80940230Sdonn 				p->leftp = fixtype(mkconv(mtype,
81040230Sdonn 						cpexpr(lconst)));
81140230Sdonn 				frexpr(lp);
81240230Sdonn 				}
81340230Sdonn 			else
81440230Sdonn 				p->leftp = fixtype(mkconv(mtype,lp));
81540230Sdonn 		if(rtype != mtype)
81640230Sdonn 			if (rconst)
81740230Sdonn 				{
81840230Sdonn 				p->rightp = fixtype(mkconv(mtype,
81940230Sdonn 						cpexpr(rconst)));
82040230Sdonn 				frexpr(rp);
82140230Sdonn 				}
82240230Sdonn 			else
82340230Sdonn 				p->rightp = fixtype(mkconv(mtype,rp));
82440230Sdonn 		break;
82540230Sdonn 
82640230Sdonn 
82740230Sdonn 	case OPCONV:
82840230Sdonn 		if(ISCOMPLEX(p->vtype))
82940230Sdonn 			{
83040230Sdonn 			ptype = cktype(OPCONV, p->vtype, ltype);
83140230Sdonn 			if(p->rightp)
83240230Sdonn 				ptype = cktype(OPCONV, ptype, rtype);
83340230Sdonn 			break;
83440230Sdonn 			}
83540230Sdonn 		ptype = cktype(OPCONV, p->vtype, ltype);
83640230Sdonn 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
83740230Sdonn 			{
83840230Sdonn 			lp->exprblock.rightp =
83940230Sdonn 				fixtype( mkconv(ptype, lp->exprblock.rightp) );
84040230Sdonn 			free( (charptr) p );
84140230Sdonn 			p = (Exprp) lp;
84240230Sdonn 			}
84340230Sdonn 		break;
84440230Sdonn 
84540230Sdonn 	case OPADDR:
84640230Sdonn 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
84740230Sdonn 			fatal("addr of addr");
84840230Sdonn 		break;
84940230Sdonn 
85040230Sdonn 	case OPCOMMA:
85140230Sdonn 	case OPQUEST:
85240230Sdonn 	case OPCOLON:
85340230Sdonn 		break;
85440230Sdonn 
85540230Sdonn 	case OPPAREN:
85640230Sdonn 		p->vleng = (expptr) cpexpr( lp->headblock.vleng );
85740230Sdonn 		break;
85840230Sdonn 
85940230Sdonn 	case OPMIN:
86040230Sdonn 	case OPMAX:
86140230Sdonn 		ptype = p->vtype;
86240230Sdonn 		break;
86340230Sdonn 
86440230Sdonn 	default:
86540230Sdonn 		break;
86640230Sdonn 	}
86740230Sdonn 
86840230Sdonn p->vtype = ptype;
86940230Sdonn frexpr(lconst);
87040230Sdonn frexpr(rconst);
87140230Sdonn return((expptr) p);
87240230Sdonn }
87340230Sdonn 
87440230Sdonn #if SZINT < SZLONG
87540230Sdonn /*
87640230Sdonn    for efficient subscripting, replace long ints by shorts
87740230Sdonn    in easy places
87840230Sdonn */
87940230Sdonn 
shorten(p)88040230Sdonn expptr shorten(p)
88140230Sdonn register expptr p;
88240230Sdonn {
88340230Sdonn register expptr q;
88440230Sdonn 
88540230Sdonn if(p->headblock.vtype != TYLONG)
88640230Sdonn 	return(p);
88740230Sdonn 
88840230Sdonn switch(p->tag)
88940230Sdonn 	{
89040230Sdonn 	case TERROR:
89140230Sdonn 	case TLIST:
89240230Sdonn 		return(p);
89340230Sdonn 
89440230Sdonn 	case TCONST:
89540230Sdonn 	case TADDR:
89640230Sdonn 		return( mkconv(TYINT,p) );
89740230Sdonn 
89840230Sdonn 	case TEXPR:
89940230Sdonn 		break;
90040230Sdonn 
90140230Sdonn 	default:
90240230Sdonn 		badtag("shorten", p->tag);
90340230Sdonn 	}
90440230Sdonn 
90540230Sdonn switch(p->exprblock.opcode)
90640230Sdonn 	{
90740230Sdonn 	case OPPLUS:
90840230Sdonn 	case OPMINUS:
90940230Sdonn 	case OPSTAR:
91040230Sdonn 		q = shorten( cpexpr(p->exprblock.rightp) );
91140230Sdonn 		if(q->headblock.vtype == TYINT)
91240230Sdonn 			{
91340230Sdonn 			p->exprblock.leftp = shorten(p->exprblock.leftp);
91440230Sdonn 			if(p->exprblock.leftp->headblock.vtype == TYLONG)
91540230Sdonn 				frexpr(q);
91640230Sdonn 			else
91740230Sdonn 				{
91840230Sdonn 				frexpr(p->exprblock.rightp);
91940230Sdonn 				p->exprblock.rightp = q;
92040230Sdonn 				p->exprblock.vtype = TYINT;
92140230Sdonn 				}
92240230Sdonn 			}
92340230Sdonn 		break;
92440230Sdonn 
92540230Sdonn 	case OPNEG:
92640230Sdonn 	case OPPAREN:
92740230Sdonn 		p->exprblock.leftp = shorten(p->exprblock.leftp);
92840230Sdonn 		if(p->exprblock.leftp->headblock.vtype == TYINT)
92940230Sdonn 			p->exprblock.vtype = TYINT;
93040230Sdonn 		break;
93140230Sdonn 
93240230Sdonn 	case OPCALL:
93340230Sdonn 	case OPCCALL:
93440230Sdonn 		p = mkconv(TYINT,p);
93540230Sdonn 		break;
93640230Sdonn 	default:
93740230Sdonn 		break;
93840230Sdonn 	}
93940230Sdonn 
94040230Sdonn return(p);
94140230Sdonn }
94240230Sdonn #endif
94340230Sdonn /* fix an argument list, taking due care for special first level cases */
94440230Sdonn 
fixargs(doput,p0)94540230Sdonn fixargs(doput, p0)
94640230Sdonn int doput;	/* doput is true if the function is not intrinsic;
94740230Sdonn 		   was used to decide whether to do a putconst,
94840230Sdonn 		   but this is no longer done here (Feb82)*/
94940230Sdonn struct Listblock *p0;
95040230Sdonn {
95140230Sdonn register chainp p;
95240230Sdonn register tagptr q, t;
95340230Sdonn register int qtag;
95440230Sdonn int nargs;
95540230Sdonn Addrp mkscalar();
95640230Sdonn 
95740230Sdonn nargs = 0;
95840230Sdonn if(p0)
95940230Sdonn     for(p = p0->listp ; p ; p = p->nextp)
96040230Sdonn 	{
96140230Sdonn 	++nargs;
96240230Sdonn 	q = p->datap;
96340230Sdonn 	qtag = q->tag;
96440230Sdonn 	if(qtag == TCONST)
96540230Sdonn 		{
96640230Sdonn 
96740230Sdonn /*
96840230Sdonn 		if(q->constblock.vtype == TYSHORT)
96940230Sdonn 			q = (tagptr) mkconv(tyint, q);
97040230Sdonn */
97140230Sdonn 		p->datap = q ;
97240230Sdonn 		}
97340230Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
97440230Sdonn 		q->primblock.namep->vclass==CLPROC)
97540230Sdonn 			p->datap = (tagptr) mkaddr(q->primblock.namep);
97640230Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
97740230Sdonn 		q->primblock.namep->vdim!=NULL)
97840230Sdonn 			p->datap = (tagptr) mkscalar(q->primblock.namep);
97940230Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
98040230Sdonn 		q->primblock.namep->vdovar &&
98140230Sdonn 		(t = (tagptr) memversion(q->primblock.namep)) )
98240230Sdonn 			p->datap = (tagptr) fixtype(t);
98340230Sdonn 	else
98440230Sdonn 		p->datap = (tagptr) fixtype(q);
98540230Sdonn 	}
98640230Sdonn return(nargs);
98740230Sdonn }
98840230Sdonn 
98940230Sdonn 
mkscalar(np)99040230Sdonn Addrp mkscalar(np)
99140230Sdonn register Namep np;
99240230Sdonn {
99340230Sdonn register Addrp ap;
99440230Sdonn 
99540230Sdonn vardcl(np);
99640230Sdonn ap = mkaddr(np);
99740230Sdonn 
99840230Sdonn #if TARGET == VAX || TARGET == TAHOE
99940230Sdonn 	/* on the VAX, prolog causes array arguments
100040230Sdonn 	   to point at the (0,...,0) element, except when
100140230Sdonn 	   subscript checking is on
100240230Sdonn 	*/
100340230Sdonn #ifdef SDB
100440230Sdonn 	if( !checksubs && !sdbflag && np->vstg==STGARG)
100540230Sdonn #else
100640230Sdonn 	if( !checksubs && np->vstg==STGARG)
100740230Sdonn #endif
100840230Sdonn 		{
100940230Sdonn 		register struct Dimblock *dp;
101040230Sdonn 		dp = np->vdim;
101140230Sdonn 		frexpr(ap->memoffset);
101240230Sdonn 		ap->memoffset = mkexpr(OPSTAR,
101340230Sdonn 				(np->vtype==TYCHAR ?
101440230Sdonn 					cpexpr(np->vleng) :
101540230Sdonn 					(tagptr)ICON(typesize[np->vtype]) ),
101640230Sdonn 				cpexpr(dp->baseoffset) );
101740230Sdonn 		}
101840230Sdonn #endif
101940230Sdonn return(ap);
102040230Sdonn }
102140230Sdonn 
102240230Sdonn 
102340230Sdonn 
102440230Sdonn 
102540230Sdonn 
mkfunct(p)102640230Sdonn expptr mkfunct(p)
102740230Sdonn register struct Primblock *p;
102840230Sdonn {
102940230Sdonn struct Entrypoint *ep;
103040230Sdonn Addrp ap;
103140230Sdonn struct Extsym *extp;
103240230Sdonn register Namep np;
103340230Sdonn register expptr q;
103440230Sdonn expptr intrcall(), stfcall();
103540230Sdonn int k, nargs;
103640230Sdonn int class;
103740230Sdonn 
103840230Sdonn if(p->tag != TPRIM)
103940230Sdonn 	return( errnode() );
104040230Sdonn 
104140230Sdonn np = p->namep;
104240230Sdonn class = np->vclass;
104340230Sdonn 
104440230Sdonn if(class == CLUNKNOWN)
104540230Sdonn 	{
104640230Sdonn 	np->vclass = class = CLPROC;
104740230Sdonn 	if(np->vstg == STGUNKNOWN)
104840230Sdonn 		{
104940230Sdonn 		if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
105040230Sdonn 			{
105140230Sdonn 			np->vstg = STGINTR;
105240230Sdonn 			np->vardesc.varno = k;
105340230Sdonn 			np->vprocclass = PINTRINSIC;
105440230Sdonn 			}
105540230Sdonn 		else
105640230Sdonn 			{
105740230Sdonn 			extp = mkext( varunder(VL,np->varname) );
105840230Sdonn 			if(extp->extstg == STGCOMMON)
105940230Sdonn 				warn("conflicting declarations", np->varname);
106040230Sdonn 			extp->extstg = STGEXT;
106140230Sdonn 			np->vstg = STGEXT;
106240230Sdonn 			np->vardesc.varno = extp - extsymtab;
106340230Sdonn 			np->vprocclass = PEXTERNAL;
106440230Sdonn 			}
106540230Sdonn 		}
106640230Sdonn 	else if(np->vstg==STGARG)
106740230Sdonn 		{
106840230Sdonn 		if(np->vtype!=TYCHAR && !ftn66flag)
106940230Sdonn 		    warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
107040230Sdonn 		np->vprocclass = PEXTERNAL;
107140230Sdonn 		}
107240230Sdonn 	}
107340230Sdonn 
107440230Sdonn if(class != CLPROC)
107540230Sdonn 	fatali("invalid class code %d for function", class);
107640230Sdonn if(p->fcharp || p->lcharp)
107740230Sdonn 	{
107840230Sdonn 	err("no substring of function call");
107940230Sdonn 	goto error;
108040230Sdonn 	}
108140230Sdonn impldcl(np);
108240230Sdonn nargs = fixargs( np->vprocclass!=PINTRINSIC,  p->argsp);
108340230Sdonn 
108440230Sdonn switch(np->vprocclass)
108540230Sdonn 	{
108640230Sdonn 	case PEXTERNAL:
108740230Sdonn 		ap = mkaddr(np);
108840230Sdonn 	call:
108940230Sdonn 		q = mkexpr(OPCALL, ap, p->argsp);
109040230Sdonn 		if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
109140230Sdonn 			{
109240230Sdonn 			err("attempt to use untyped function");
109340230Sdonn 			goto error;
109440230Sdonn 			}
109540230Sdonn 		if(np->vleng)
109640230Sdonn 			q->exprblock.vleng = (expptr) cpexpr(np->vleng);
109740230Sdonn 		break;
109840230Sdonn 
109940230Sdonn 	case PINTRINSIC:
110040230Sdonn 		q = intrcall(np, p->argsp, nargs);
110140230Sdonn 		break;
110240230Sdonn 
110340230Sdonn 	case PSTFUNCT:
110440230Sdonn 		q = stfcall(np, p->argsp);
110540230Sdonn 		break;
110640230Sdonn 
110740230Sdonn 	case PTHISPROC:
110840230Sdonn 		warn("recursive call");
110940230Sdonn 		for(ep = entries ; ep ; ep = ep->entnextp)
111040230Sdonn 			if(ep->enamep == np)
111140230Sdonn 				break;
111240230Sdonn 		if(ep == NULL)
111340230Sdonn 			fatal("mkfunct: impossible recursion");
111440230Sdonn 		ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
111540230Sdonn 		goto call;
111640230Sdonn 
111740230Sdonn 	default:
111840230Sdonn 		fatali("mkfunct: impossible vprocclass %d",
111940230Sdonn 			(int) (np->vprocclass) );
112040230Sdonn 	}
112140230Sdonn free( (charptr) p );
112240230Sdonn return(q);
112340230Sdonn 
112440230Sdonn error:
112540230Sdonn 	frexpr(p);
112640230Sdonn 	return( errnode() );
112740230Sdonn }
112840230Sdonn 
112940230Sdonn 
113040230Sdonn 
stfcall(np,actlist)113140230Sdonn LOCAL expptr stfcall(np, actlist)
113240230Sdonn Namep np;
113340230Sdonn struct Listblock *actlist;
113440230Sdonn {
113540230Sdonn register chainp actuals;
113640230Sdonn int nargs;
113740230Sdonn chainp oactp, formals;
113840230Sdonn int type;
113940230Sdonn expptr q, rhs, ap;
114040230Sdonn Namep tnp;
114140230Sdonn register struct Rplblock *rp;
114240230Sdonn struct Rplblock *tlist;
114340230Sdonn 
114440230Sdonn if(actlist)
114540230Sdonn 	{
114640230Sdonn 	actuals = actlist->listp;
114740230Sdonn 	free( (charptr) actlist);
114840230Sdonn 	}
114940230Sdonn else
115040230Sdonn 	actuals = NULL;
115140230Sdonn oactp = actuals;
115240230Sdonn 
115340230Sdonn nargs = 0;
115440230Sdonn tlist = NULL;
115540230Sdonn if( (type = np->vtype) == TYUNKNOWN)
115640230Sdonn 	{
115740230Sdonn 	err("attempt to use untyped statement function");
115840230Sdonn 	q = errnode();
115940230Sdonn 	goto ret;
116040230Sdonn 	}
116140230Sdonn formals = (chainp) (np->varxptr.vstfdesc->datap);
116240230Sdonn rhs = (expptr) (np->varxptr.vstfdesc->nextp);
116340230Sdonn 
116440230Sdonn /* copy actual arguments into temporaries */
116540230Sdonn while(actuals!=NULL && formals!=NULL)
116640230Sdonn 	{
116740230Sdonn 	rp = ALLOC(Rplblock);
116840230Sdonn 	rp->rplnp = tnp = (Namep) (formals->datap);
116940230Sdonn 	ap = fixtype(actuals->datap);
117040230Sdonn 	if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
117140230Sdonn 	   && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
117240230Sdonn 		{
117340230Sdonn 		rp->rplvp = (expptr) ap;
117440230Sdonn 		rp->rplxp = NULL;
117540230Sdonn 		rp->rpltag = ap->tag;
117640230Sdonn 		}
117740230Sdonn 	else	{
117840230Sdonn 		rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
117940230Sdonn 		rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
118040230Sdonn 		if( (rp->rpltag = rp->rplxp->tag) == TERROR)
118140230Sdonn 			err("disagreement of argument types in statement function call");
118240230Sdonn 		else if(tnp->vtype!=ap->headblock.vtype)
118340230Sdonn 			warn("argument type mismatch in statement function");
118440230Sdonn 		}
118540230Sdonn 	rp->rplnextp = tlist;
118640230Sdonn 	tlist = rp;
118740230Sdonn 	actuals = actuals->nextp;
118840230Sdonn 	formals = formals->nextp;
118940230Sdonn 	++nargs;
119040230Sdonn 	}
119140230Sdonn 
119240230Sdonn if(actuals!=NULL || formals!=NULL)
119340230Sdonn 	err("statement function definition and argument list differ");
119440230Sdonn 
119540230Sdonn /*
119640230Sdonn    now push down names involved in formal argument list, then
119740230Sdonn    evaluate rhs of statement function definition in this environment
119840230Sdonn */
119940230Sdonn 
120040230Sdonn if(tlist)	/* put tlist in front of the rpllist */
120140230Sdonn 	{
120240230Sdonn 	for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
120340230Sdonn 		;
120440230Sdonn 	rp->rplnextp = rpllist;
120540230Sdonn 	rpllist = tlist;
120640230Sdonn 	}
120740230Sdonn 
120840230Sdonn q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
120940230Sdonn 
121040230Sdonn /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
121140230Sdonn while(--nargs >= 0)
121240230Sdonn 	{
121340230Sdonn 	if(rpllist->rplxp)
121440230Sdonn 		q = mkexpr(OPCOMMA, rpllist->rplxp, q);
121540230Sdonn 	rp = rpllist->rplnextp;
121640230Sdonn 	frexpr(rpllist->rplvp);
121740230Sdonn 	free(rpllist);
121840230Sdonn 	rpllist = rp;
121940230Sdonn 	}
122040230Sdonn 
122140230Sdonn ret:
122240230Sdonn 	frchain( &oactp );
122340230Sdonn 	return(q);
122440230Sdonn }
122540230Sdonn 
122640230Sdonn 
122740230Sdonn 
122840230Sdonn 
mkplace(np)122940230Sdonn Addrp mkplace(np)
123040230Sdonn register Namep np;
123140230Sdonn {
123240230Sdonn register Addrp s;
123340230Sdonn register struct Rplblock *rp;
123440230Sdonn int regn;
123540230Sdonn 
123640230Sdonn /* is name on the replace list? */
123740230Sdonn 
123840230Sdonn for(rp = rpllist ; rp ; rp = rp->rplnextp)
123940230Sdonn 	{
124040230Sdonn 	if(np == rp->rplnp)
124140230Sdonn 		{
124240230Sdonn 		if(rp->rpltag == TNAME)
124340230Sdonn 			{
124440230Sdonn 			np = (Namep) (rp->rplvp);
124540230Sdonn 			break;
124640230Sdonn 			}
124740230Sdonn 		else	return( (Addrp) cpexpr(rp->rplvp) );
124840230Sdonn 		}
124940230Sdonn 	}
125040230Sdonn 
125140230Sdonn /* is variable a DO index in a register ? */
125240230Sdonn 
125340230Sdonn if(np->vdovar && ( (regn = inregister(np)) >= 0) )
125440230Sdonn 	if(np->vtype == TYERROR)
125540230Sdonn 		return( (Addrp) errnode() );
125640230Sdonn 	else
125740230Sdonn 		{
125840230Sdonn 		s = ALLOC(Addrblock);
125940230Sdonn 		s->tag = TADDR;
126040230Sdonn 		s->vstg = STGREG;
126140230Sdonn 		s->vtype = TYIREG;
126240230Sdonn 		s->issaved = np->vsave;
126340230Sdonn 		s->memno = regn;
126440230Sdonn 		s->memoffset = ICON(0);
126540230Sdonn 		return(s);
126640230Sdonn 		}
126740230Sdonn 
126840230Sdonn vardcl(np);
126940230Sdonn return(mkaddr(np));
127040230Sdonn }
127140230Sdonn 
127240230Sdonn 
127340230Sdonn 
127440230Sdonn 
mklhs(p)127540230Sdonn expptr mklhs(p)
127640230Sdonn register struct Primblock *p;
127740230Sdonn {
127840230Sdonn expptr suboffset();
127940230Sdonn register Addrp s;
128040230Sdonn Namep np;
128140230Sdonn 
128240230Sdonn if(p->tag != TPRIM)
128340230Sdonn 	return( (expptr) p );
128440230Sdonn np = p->namep;
128540230Sdonn 
128640230Sdonn s = mkplace(np);
128740230Sdonn if(s->tag!=TADDR || s->vstg==STGREG)
128840230Sdonn 	{
128940230Sdonn 	free( (charptr) p );
129040230Sdonn 	return( (expptr) s );
129140230Sdonn 	}
129240230Sdonn 
129340230Sdonn /* compute the address modified by subscripts */
129440230Sdonn 
129540230Sdonn s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
129640230Sdonn frexpr(p->argsp);
129740230Sdonn p->argsp = NULL;
129840230Sdonn 
129940230Sdonn /* now do substring part */
130040230Sdonn 
130140230Sdonn if(p->fcharp || p->lcharp)
130240230Sdonn 	{
130340230Sdonn 	if(np->vtype != TYCHAR)
130440230Sdonn 		errstr("substring of noncharacter %s", varstr(VL,np->varname));
130540230Sdonn 	else	{
130640230Sdonn 		if(p->lcharp == NULL)
130740230Sdonn 			p->lcharp = (expptr) cpexpr(s->vleng);
130840230Sdonn 		frexpr(s->vleng);
130940230Sdonn 		if(p->fcharp)
131040230Sdonn 			{
131140230Sdonn 			if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
131240230Sdonn 			&& p->fcharp->primblock.namep == p->lcharp->primblock.namep)
131340230Sdonn 				/* A trivial optimization -- upper == lower */
131440230Sdonn 				s->vleng = ICON(1);
131540230Sdonn 			else
131640230Sdonn 				s->vleng = mkexpr(OPMINUS, p->lcharp,
131740230Sdonn 					mkexpr(OPMINUS, p->fcharp, ICON(1) ));
131840230Sdonn 			}
131940230Sdonn 		else
132040230Sdonn 			s->vleng = p->lcharp;
132140230Sdonn 		}
132240230Sdonn 	}
132340230Sdonn 
132440230Sdonn s->vleng = fixtype( s->vleng );
132540230Sdonn s->memoffset = fixtype( s->memoffset );
132640230Sdonn free( (charptr) p );
132740230Sdonn return( (expptr) s );
132840230Sdonn }
132940230Sdonn 
133040230Sdonn 
133140230Sdonn 
133240230Sdonn 
133340230Sdonn 
deregister(np)133440230Sdonn deregister(np)
133540230Sdonn Namep np;
133640230Sdonn {
133740230Sdonn if(nregvar>0 && regnamep[nregvar-1]==np)
133840230Sdonn 	{
133940230Sdonn 	--nregvar;
134040230Sdonn #if FAMILY == DMR
134140230Sdonn 	putnreg();
134240230Sdonn #endif
134340230Sdonn 	}
134440230Sdonn }
134540230Sdonn 
134640230Sdonn 
134740230Sdonn 
134840230Sdonn 
memversion(np)134940230Sdonn Addrp memversion(np)
135040230Sdonn register Namep np;
135140230Sdonn {
135240230Sdonn register Addrp s;
135340230Sdonn 
135440230Sdonn if(np->vdovar==NO || (inregister(np)<0) )
135540230Sdonn 	return(NULL);
135640230Sdonn np->vdovar = NO;
135740230Sdonn s = mkplace(np);
135840230Sdonn np->vdovar = YES;
135940230Sdonn return(s);
136040230Sdonn }
136140230Sdonn 
136240230Sdonn 
136340230Sdonn 
inregister(np)136440230Sdonn inregister(np)
136540230Sdonn register Namep np;
136640230Sdonn {
136740230Sdonn register int i;
136840230Sdonn 
136940230Sdonn for(i = 0 ; i < nregvar ; ++i)
137040230Sdonn 	if(regnamep[i] == np)
137140230Sdonn 		return( regnum[i] );
137240230Sdonn return(-1);
137340230Sdonn }
137440230Sdonn 
137540230Sdonn 
137640230Sdonn 
137740230Sdonn 
enregister(np)137840230Sdonn enregister(np)
137940230Sdonn Namep np;
138040230Sdonn {
138140230Sdonn if( inregister(np) >= 0)
138240230Sdonn 	return(YES);
138340230Sdonn if(nregvar >= maxregvar)
138440230Sdonn 	return(NO);
138540230Sdonn vardcl(np);
138640230Sdonn if( ONEOF(np->vtype, MSKIREG) )
138740230Sdonn 	{
138840230Sdonn 	regnamep[nregvar++] = np;
138940230Sdonn 	if(nregvar > highregvar)
139040230Sdonn 		highregvar = nregvar;
139140230Sdonn #if FAMILY == DMR
139240230Sdonn 	putnreg();
139340230Sdonn #endif
139440230Sdonn 	return(YES);
139540230Sdonn 	}
139640230Sdonn else
139740230Sdonn 	return(NO);
139840230Sdonn }
139940230Sdonn 
140040230Sdonn 
140140230Sdonn 
140240230Sdonn 
suboffset(p)140340230Sdonn expptr suboffset(p)
140440230Sdonn register struct Primblock *p;
140540230Sdonn {
140640230Sdonn int n;
140740230Sdonn expptr size;
140840230Sdonn expptr oftwo();
140940230Sdonn chainp cp;
141040230Sdonn expptr offp, prod;
141140230Sdonn expptr subcheck();
141240230Sdonn struct Dimblock *dimp;
141340230Sdonn expptr sub[MAXDIM+1];
141440230Sdonn register Namep np;
141540230Sdonn 
141640230Sdonn np = p->namep;
141740230Sdonn offp = ICON(0);
141840230Sdonn n = 0;
141940230Sdonn if(p->argsp)
142040230Sdonn 	for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
142140230Sdonn 		{
142240230Sdonn 		sub[n] = fixtype(cpexpr(cp->datap));
142340230Sdonn 		if ( ! ISINT(sub[n]->headblock.vtype)) {
142440230Sdonn 			errstr("%s: non-integer subscript expression",
142540230Sdonn 				varstr(VL, np->varname) );
142640230Sdonn 			/* Provide a substitute -- go on to find more errors */
142740230Sdonn 			frexpr(sub[n]);
142840230Sdonn 			sub[n] = ICON(1);
142940230Sdonn 		}
143040230Sdonn 		if(n > maxdim)
143140230Sdonn 			{
143240230Sdonn 			   char str[28+VL];
143340230Sdonn 			   sprintf(str, "%s: more than %d subscripts",
143440230Sdonn 				varstr(VL, np->varname), maxdim );
143540230Sdonn 			   err( str );
143640230Sdonn 			break;
143740230Sdonn 			}
143840230Sdonn 		}
143940230Sdonn 
144040230Sdonn dimp = np->vdim;
144140230Sdonn if(n>0 && dimp==NULL)
144240230Sdonn 	errstr("%s: subscripts on scalar variable",
144340230Sdonn 		varstr(VL, np->varname), maxdim );
144440230Sdonn else if(dimp && dimp->ndim!=n)
144540230Sdonn 	errstr("wrong number of subscripts on %s",
144640230Sdonn 		varstr(VL, np->varname) );
144740230Sdonn else if(n > 0)
144840230Sdonn 	{
144940230Sdonn 	prod = sub[--n];
145040230Sdonn 	while( --n >= 0)
145140230Sdonn 		prod = mkexpr(OPPLUS, sub[n],
145240230Sdonn 			mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
145340230Sdonn #if TARGET == VAX || TARGET == TAHOE
145440230Sdonn #ifdef SDB
145540230Sdonn 	if(checksubs || np->vstg!=STGARG || sdbflag)
145640230Sdonn #else
145740230Sdonn 	if(checksubs || np->vstg!=STGARG)
145840230Sdonn #endif
145940230Sdonn 		prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146040230Sdonn #else
146140230Sdonn 	prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146240230Sdonn #endif
146340230Sdonn 	if(checksubs)
146440230Sdonn 		prod = subcheck(np, prod);
146540230Sdonn 	size = np->vtype == TYCHAR ?
146640230Sdonn 		(expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
146740230Sdonn 	if (!oftwo(size))
146840230Sdonn 		prod = mkexpr(OPSTAR, prod, size);
146940230Sdonn 	else
147040230Sdonn 		prod = mkexpr(OPLSHIFT,prod,oftwo(size));
147140230Sdonn 
147240230Sdonn 	offp = mkexpr(OPPLUS, offp, prod);
147340230Sdonn 	}
147440230Sdonn 
147540230Sdonn if(p->fcharp && np->vtype==TYCHAR)
147640230Sdonn 	offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
147740230Sdonn 
147840230Sdonn return(offp);
147940230Sdonn }
148040230Sdonn 
148140230Sdonn 
148240230Sdonn 
148340230Sdonn 
subcheck(np,p)148440230Sdonn expptr subcheck(np, p)
148540230Sdonn Namep np;
148640230Sdonn register expptr p;
148740230Sdonn {
148840230Sdonn struct Dimblock *dimp;
148940230Sdonn expptr t, checkvar, checkcond, badcall;
149040230Sdonn 
149140230Sdonn dimp = np->vdim;
149240230Sdonn if(dimp->nelt == NULL)
149340230Sdonn 	return(p);	/* don't check arrays with * bounds */
149440230Sdonn checkvar = NULL;
149540230Sdonn checkcond = NULL;
149640230Sdonn if( ISICON(p) )
149740230Sdonn 	{
149846303Sbostic 	if(p->constblock.constant.ci < 0)
149940230Sdonn 		goto badsub;
150040230Sdonn 	if( ISICON(dimp->nelt) )
150146303Sbostic 		if(p->constblock.constant.ci <
150246303Sbostic 		    dimp->nelt->constblock.constant.ci)
150340230Sdonn 			return(p);
150440230Sdonn 		else
150540230Sdonn 			goto badsub;
150640230Sdonn 	}
150740230Sdonn if(p->tag==TADDR && p->addrblock.vstg==STGREG)
150840230Sdonn 	{
150940230Sdonn 	checkvar = (expptr) cpexpr(p);
151040230Sdonn 	t = p;
151140230Sdonn 	}
151240230Sdonn else	{
151340230Sdonn 	checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
151440230Sdonn 	t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
151540230Sdonn 	}
151640230Sdonn checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
151740230Sdonn if( ! ISICON(p) )
151840230Sdonn 	checkcond = mkexpr(OPAND, checkcond,
151940230Sdonn 			mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
152040230Sdonn 
152140230Sdonn badcall = call4(p->headblock.vtype, "s_rnge",
152240230Sdonn 		mkstrcon(VL, np->varname),
152340230Sdonn 		mkconv(TYLONG,  cpexpr(checkvar)),
152440230Sdonn 		mkstrcon(XL, procname),
152540230Sdonn 		ICON(lineno) );
152640230Sdonn badcall->exprblock.opcode = OPCCALL;
152740230Sdonn p = mkexpr(OPQUEST, checkcond,
152840230Sdonn 	mkexpr(OPCOLON, checkvar, badcall));
152940230Sdonn 
153040230Sdonn return(p);
153140230Sdonn 
153240230Sdonn badsub:
153340230Sdonn 	frexpr(p);
153440230Sdonn 	errstr("subscript on variable %s out of range", varstr(VL,np->varname));
153540230Sdonn 	return ( ICON(0) );
153640230Sdonn }
153740230Sdonn 
153840230Sdonn 
153940230Sdonn 
154040230Sdonn 
mkaddr(p)154140230Sdonn Addrp mkaddr(p)
154240230Sdonn register Namep p;
154340230Sdonn {
154440230Sdonn struct Extsym *extp;
154540230Sdonn register Addrp t;
154640230Sdonn Addrp intraddr();
154740230Sdonn 
154840230Sdonn switch( p->vstg)
154940230Sdonn 	{
155040230Sdonn 	case STGUNKNOWN:
155140230Sdonn 		if(p->vclass != CLPROC)
155240230Sdonn 			break;
155340230Sdonn 		extp = mkext( varunder(VL, p->varname) );
155440230Sdonn 		extp->extstg = STGEXT;
155540230Sdonn 		p->vstg = STGEXT;
155640230Sdonn 		p->vardesc.varno = extp - extsymtab;
155740230Sdonn 		p->vprocclass = PEXTERNAL;
155840230Sdonn 
155940230Sdonn 	case STGCOMMON:
156040230Sdonn 	case STGEXT:
156140230Sdonn 	case STGBSS:
156240230Sdonn 	case STGINIT:
156340230Sdonn 	case STGEQUIV:
156440230Sdonn 	case STGARG:
156540230Sdonn 	case STGLENG:
156640230Sdonn 	case STGAUTO:
156740230Sdonn 		t = ALLOC(Addrblock);
156840230Sdonn 		t->tag = TADDR;
156940230Sdonn 		if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
157040230Sdonn 			t->vclass = CLVAR;
157140230Sdonn 		else
157240230Sdonn 			t->vclass = p->vclass;
157340230Sdonn 		t->vtype = p->vtype;
157440230Sdonn 		t->vstg = p->vstg;
157540230Sdonn 		t->memno = p->vardesc.varno;
157640230Sdonn 		t->issaved = p->vsave;
157740230Sdonn                 if(p->vdim) t->isarray = YES;
157840230Sdonn 		t->memoffset = ICON(p->voffset);
157940230Sdonn 		if(p->vleng)
158040230Sdonn 			{
158140230Sdonn 			t->vleng = (expptr) cpexpr(p->vleng);
158240230Sdonn 			if( ISICON(t->vleng) )
158346303Sbostic 				t->varleng = t->vleng->constblock.constant.ci;
158440230Sdonn 			}
158540230Sdonn 		if (p->vstg == STGBSS)
158640230Sdonn 			t->varsize = p->varsize;
158740230Sdonn 		else if (p->vstg == STGEQUIV)
158840230Sdonn 			t->varsize = eqvclass[t->memno].eqvleng;
158940230Sdonn 		return(t);
159040230Sdonn 
159140230Sdonn 	case STGINTR:
159240230Sdonn 		return( intraddr(p) );
159340230Sdonn 
159440230Sdonn 	}
159540230Sdonn /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
159640230Sdonn badstg("mkaddr", p->vstg);
159740230Sdonn /* NOTREACHED */
159840230Sdonn }
159940230Sdonn 
160040230Sdonn 
160140230Sdonn 
160240230Sdonn 
mkarg(type,argno)160340230Sdonn Addrp mkarg(type, argno)
160440230Sdonn int type, argno;
160540230Sdonn {
160640230Sdonn register Addrp p;
160740230Sdonn 
160840230Sdonn p = ALLOC(Addrblock);
160940230Sdonn p->tag = TADDR;
161040230Sdonn p->vtype = type;
161140230Sdonn p->vclass = CLVAR;
161240230Sdonn p->vstg = (type==TYLENG ? STGLENG : STGARG);
161340230Sdonn p->memno = argno;
161440230Sdonn return(p);
161540230Sdonn }
161640230Sdonn 
161740230Sdonn 
161840230Sdonn 
161940230Sdonn 
162040230Sdonn expptr mkprim(v, args, substr)
162140230Sdonn register union
162240230Sdonn 	{
162340230Sdonn 	struct Paramblock paramblock;
162440230Sdonn 	struct Nameblock nameblock;
162540230Sdonn 	struct Headblock headblock;
162640230Sdonn 	} *v;
162740230Sdonn struct Listblock *args;
162840230Sdonn chainp substr;
162940230Sdonn {
163040230Sdonn register struct Primblock *p;
163140230Sdonn 
163240230Sdonn if(v->headblock.vclass == CLPARAM)
163340230Sdonn 	{
163440230Sdonn 	if(args || substr)
163540230Sdonn 		{
163640230Sdonn 		errstr("no qualifiers on parameter name %s",
163740230Sdonn 			varstr(VL,v->paramblock.varname));
163840230Sdonn 		frexpr(args);
163940230Sdonn 		if(substr)
164040230Sdonn 			{
164140230Sdonn 			frexpr(substr->datap);
164240230Sdonn 			frexpr(substr->nextp->datap);
164340230Sdonn 			frchain(&substr);
164440230Sdonn 			}
164540230Sdonn 		frexpr(v);
164640230Sdonn 		return( errnode() );
164740230Sdonn 		}
164840230Sdonn 	return( (expptr) cpexpr(v->paramblock.paramval) );
164940230Sdonn 	}
165040230Sdonn 
165140230Sdonn p = ALLOC(Primblock);
165240230Sdonn p->tag = TPRIM;
165340230Sdonn p->vtype = v->nameblock.vtype;
165440230Sdonn p->namep = (Namep) v;
165540230Sdonn p->argsp = args;
165640230Sdonn if(substr)
165740230Sdonn 	{
165840230Sdonn 	p->fcharp = (expptr) substr->datap;
165940231Sdonn 	if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
166040230Sdonn 		p->fcharp = mkconv(TYINT, p->fcharp);
166140230Sdonn 	p->lcharp = (expptr) substr->nextp->datap;
166240231Sdonn 	if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
166340230Sdonn 		p->lcharp = mkconv(TYINT, p->lcharp);
166440230Sdonn 	frchain(&substr);
166540230Sdonn 	}
166640230Sdonn return( (expptr) p);
166740230Sdonn }
166840230Sdonn 
166940230Sdonn 
167040230Sdonn 
vardcl(v)167140230Sdonn vardcl(v)
167240230Sdonn register Namep v;
167340230Sdonn {
167440230Sdonn int nelt;
167540230Sdonn struct Dimblock *t;
167640230Sdonn Addrp p;
167740230Sdonn expptr neltp;
167840230Sdonn int eltsize;
167940230Sdonn int varsize;
168040230Sdonn int tsize;
168140230Sdonn int align;
168240230Sdonn 
168340230Sdonn if(v->vdcldone)
168440230Sdonn 	return;
168540230Sdonn if(v->vclass == CLNAMELIST)
168640230Sdonn 	return;
168740230Sdonn 
168840230Sdonn if(v->vtype == TYUNKNOWN)
168940230Sdonn 	impldcl(v);
169040230Sdonn if(v->vclass == CLUNKNOWN)
169140230Sdonn 	v->vclass = CLVAR;
169240230Sdonn else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
169340230Sdonn 	{
169440230Sdonn 	dclerr("used both as variable and non-variable", v);
169540230Sdonn 	return;
169640230Sdonn 	}
169740230Sdonn if(v->vstg==STGUNKNOWN)
169840230Sdonn 	v->vstg = implstg[ letter(v->varname[0]) ];
169940230Sdonn 
170040230Sdonn switch(v->vstg)
170140230Sdonn 	{
170240230Sdonn 	case STGBSS:
170340230Sdonn 		v->vardesc.varno = ++lastvarno;
170440230Sdonn 		if (v->vclass != CLVAR)
170540230Sdonn 			break;
170640230Sdonn 		nelt = 1;
170740230Sdonn 		t = v->vdim;
170840230Sdonn 		if (t)
170940230Sdonn 			{
171040230Sdonn 			neltp = t->nelt;
171140230Sdonn 			if (neltp && ISICON(neltp))
171246303Sbostic 				nelt = neltp->constblock.constant.ci;
171340230Sdonn 			else
171440230Sdonn 				dclerr("improperly dimensioned array", v);
171540230Sdonn 			}
171640230Sdonn 
171740230Sdonn 		if (v->vtype == TYCHAR)
171840230Sdonn 			{
171940230Sdonn 			v->vleng = fixtype(v->vleng);
172040230Sdonn 			if (v->vleng == NULL)
172140230Sdonn 				eltsize = typesize[TYCHAR];
172240230Sdonn 			else if (ISICON(v->vleng))
172340230Sdonn 				eltsize = typesize[TYCHAR] *
172446303Sbostic 					v->vleng->constblock.constant.ci;
172540230Sdonn 			else if (v->vleng->tag != TERROR)
172640230Sdonn 				{
172740230Sdonn 				errstr("nonconstant string length on %s",
172840230Sdonn 					varstr(VL, v->varname));
172940230Sdonn 				eltsize = 0;
173040230Sdonn 				}
173140230Sdonn 			}
173240230Sdonn 		else
173340230Sdonn 			eltsize = typesize[v->vtype];
173440230Sdonn 
173540230Sdonn 		v->varsize = nelt * eltsize;
173640230Sdonn 		break;
173740230Sdonn 	case STGAUTO:
173840230Sdonn 		if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
173940230Sdonn 			break;
174040230Sdonn 		nelt = 1;
174140230Sdonn 		if(t = v->vdim)
174240230Sdonn 			if( (neltp = t->nelt) && ISCONST(neltp) )
174346303Sbostic 				nelt = neltp->constblock.constant.ci;
174440230Sdonn 			else
174540230Sdonn 				dclerr("adjustable automatic array", v);
174640230Sdonn 		p = autovar(nelt, v->vtype, v->vleng);
174740230Sdonn 		v->vardesc.varno = p->memno;
174846303Sbostic 		v->voffset = p->memoffset->constblock.constant.ci;
174940230Sdonn 		frexpr(p);
175040230Sdonn 		break;
175140230Sdonn 
175240230Sdonn 	default:
175340230Sdonn 		break;
175440230Sdonn 	}
175540230Sdonn v->vdcldone = YES;
175640230Sdonn }
175740230Sdonn 
175840230Sdonn 
175940230Sdonn 
176040230Sdonn 
impldcl(p)176140230Sdonn impldcl(p)
176240230Sdonn register Namep p;
176340230Sdonn {
176440230Sdonn register int k;
176540230Sdonn int type, leng;
176640230Sdonn 
176740230Sdonn if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
176840230Sdonn 	return;
176940230Sdonn if(p->vtype == TYUNKNOWN)
177040230Sdonn 	{
177140230Sdonn 	k = letter(p->varname[0]);
177240230Sdonn 	type = impltype[ k ];
177340230Sdonn 	leng = implleng[ k ];
177440230Sdonn 	if(type == TYUNKNOWN)
177540230Sdonn 		{
177640230Sdonn 		if(p->vclass == CLPROC)
177740230Sdonn 			dclerr("attempt to use function of undefined type", p);
177840230Sdonn 		else
177940230Sdonn 			dclerr("attempt to use undefined variable", p);
178040230Sdonn 		type = TYERROR;
178140230Sdonn 		leng = 1;
178240230Sdonn 		}
178340230Sdonn 	settype(p, type, leng);
178440230Sdonn 	}
178540230Sdonn }
178640230Sdonn 
178740230Sdonn 
178840230Sdonn 
178940230Sdonn 
letter(c)179040230Sdonn LOCAL letter(c)
179140230Sdonn register int c;
179240230Sdonn {
179340230Sdonn if( isupper(c) )
179440230Sdonn 	c = tolower(c);
179540230Sdonn return(c - 'a');
179640230Sdonn }
179740230Sdonn 
179846303Sbostic #define ICONEQ(z, c)  (ISICON(z) && z->constblock.constant.ci==c)
179940230Sdonn #define COMMUTE	{ e = lp;  lp = rp;  rp = e; }
180040230Sdonn 
180140230Sdonn 
mkexpr(opcode,lp,rp)180240230Sdonn expptr mkexpr(opcode, lp, rp)
180340230Sdonn int opcode;
180440230Sdonn register expptr lp, rp;
180540230Sdonn {
180640230Sdonn register expptr e, e1;
180740230Sdonn int etype;
180840230Sdonn int ltype, rtype;
180940230Sdonn int ltag, rtag;
181040230Sdonn expptr q, q1;
181140230Sdonn expptr fold();
181240230Sdonn int k;
181340230Sdonn 
181440230Sdonn ltype = lp->headblock.vtype;
181540230Sdonn ltag = lp->tag;
181640230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL)
181740230Sdonn 	{
181840230Sdonn 	rtype = rp->headblock.vtype;
181940230Sdonn 	rtag = rp->tag;
182040230Sdonn 	}
182140230Sdonn else	{
182240230Sdonn 	rtype = 0;
182340230Sdonn 	rtag = 0;
182440230Sdonn 	}
182540230Sdonn 
182640230Sdonn /*
182740230Sdonn  * Yuck.  Why can't we fold constants AFTER
182840230Sdonn  * variables are implicitly declared???
182940230Sdonn  */
183040230Sdonn if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
183140230Sdonn 	{
183240230Sdonn 	k = letter(lp->primblock.namep->varname[0]);
183340230Sdonn 	ltype = impltype[ k ];
183440230Sdonn 	}
183540230Sdonn if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
183640230Sdonn 	{
183740230Sdonn 	k = letter(rp->primblock.namep->varname[0]);
183840230Sdonn 	rtype = impltype[ k ];
183940230Sdonn 	}
184040230Sdonn 
184140230Sdonn etype = cktype(opcode, ltype, rtype);
184240230Sdonn if(etype == TYERROR)
184340230Sdonn 	goto error;
184440230Sdonn 
184540230Sdonn if(etype != TYUNKNOWN)
184640230Sdonn switch(opcode)
184740230Sdonn 	{
184840230Sdonn 	/* check for multiplication by 0 and 1 and addition to 0 */
184940230Sdonn 
185040230Sdonn 	case OPSTAR:
185140230Sdonn 		if( ISCONST(lp) )
185240230Sdonn 			COMMUTE
185340230Sdonn 
185440230Sdonn 		if( ISICON(rp) )
185540230Sdonn 			{
185646303Sbostic 			if(rp->constblock.constant.ci == 0)
185740230Sdonn 				{
185840230Sdonn 				if(etype == TYUNKNOWN)
185940230Sdonn 					break;
186040230Sdonn 				rp = mkconv(etype, rp);
186140230Sdonn 				goto retright;
186240230Sdonn 				}
186340230Sdonn 			if ((lp->tag == TEXPR) &&
186440230Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
186540230Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
186640230Sdonn 			    ISCONST(lp->exprblock.rightp) &&
186740230Sdonn 			    ISINT(lp->exprblock.rightp->constblock.vtype))
186840230Sdonn 				{
186940230Sdonn 				q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
187040230Sdonn 					   cpexpr(rp));
187140230Sdonn 				q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
187240230Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
187340230Sdonn 				free ((char *) lp);
187440230Sdonn 				return q;
187540230Sdonn 				}
187640230Sdonn 			else
187740230Sdonn 				goto mulop;
187840230Sdonn 			}
187940230Sdonn 		break;
188040230Sdonn 
188140230Sdonn 	case OPSLASH:
188240230Sdonn 	case OPMOD:
188340230Sdonn 		if( ICONEQ(rp, 0) )
188440230Sdonn 			{
188540230Sdonn 			err("attempted division by zero");
188640230Sdonn 			rp = ICON(1);
188740230Sdonn 			break;
188840230Sdonn 			}
188940230Sdonn 		if(opcode == OPMOD)
189040230Sdonn 			break;
189140230Sdonn 
189240230Sdonn 
189340230Sdonn 	mulop:
189440230Sdonn 		if( ISICON(rp) )
189540230Sdonn 			{
189646303Sbostic 			if(rp->constblock.constant.ci == 1)
189740230Sdonn 				goto retleft;
189840230Sdonn 
189946303Sbostic 			if(rp->constblock.constant.ci == -1)
190040230Sdonn 				{
190140230Sdonn 				frexpr(rp);
190240230Sdonn 				return( mkexpr(OPNEG, lp, PNULL) );
190340230Sdonn 				}
190440230Sdonn 			}
190540230Sdonn 
190640230Sdonn 		if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
190740230Sdonn 			{
190840230Sdonn 			if(opcode == OPSTAR)
190940230Sdonn 				e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
191040230Sdonn 			else  if(ISICON(rp) &&
191146303Sbostic 				(lp->exprblock.rightp->constblock.constant.ci %
191246303Sbostic 					rp->constblock.constant.ci) == 0)
191340230Sdonn 				e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
191440230Sdonn 			else	break;
191540230Sdonn 
191640230Sdonn 			e1 = lp->exprblock.leftp;
191740230Sdonn 			free( (charptr) lp );
191840230Sdonn 			return( mkexpr(OPSTAR, e1, e) );
191940230Sdonn 			}
192040230Sdonn 		break;
192140230Sdonn 
192240230Sdonn 
192340230Sdonn 	case OPPLUS:
192440230Sdonn 		if( ISCONST(lp) )
192540230Sdonn 			COMMUTE
192640230Sdonn 		goto addop;
192740230Sdonn 
192840230Sdonn 	case OPMINUS:
192940230Sdonn 		if( ICONEQ(lp, 0) )
193040230Sdonn 			{
193140230Sdonn 			frexpr(lp);
193240230Sdonn 			return( mkexpr(OPNEG, rp, ENULL) );
193340230Sdonn 			}
193440230Sdonn 
193540230Sdonn 		if( ISCONST(rp) )
193640230Sdonn 			{
193740230Sdonn 			opcode = OPPLUS;
193840230Sdonn 			consnegop(rp);
193940230Sdonn 			}
194040230Sdonn 
194140230Sdonn 	addop:
194240230Sdonn 		if( ISICON(rp) )
194340230Sdonn 			{
194446303Sbostic 			if(rp->constblock.constant.ci == 0)
194540230Sdonn 				goto retleft;
194640230Sdonn 			if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
194740230Sdonn 				{
194840230Sdonn 				e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
194940230Sdonn 				e1 = lp->exprblock.leftp;
195040230Sdonn 				free( (charptr) lp );
195140230Sdonn 				return( mkexpr(OPPLUS, e1, e) );
195240230Sdonn 				}
195340230Sdonn 			}
195440230Sdonn 		break;
195540230Sdonn 
195640230Sdonn 
195740230Sdonn 	case OPPOWER:
195840230Sdonn 		break;
195940230Sdonn 
196040230Sdonn 	case OPNEG:
196140230Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
196240230Sdonn 			{
196340230Sdonn 			e = lp->exprblock.leftp;
196440230Sdonn 			free( (charptr) lp );
196540230Sdonn 			return(e);
196640230Sdonn 			}
196740230Sdonn 		break;
196840230Sdonn 
196940230Sdonn 	case OPNOT:
197040230Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
197140230Sdonn 			{
197240230Sdonn 			e = lp->exprblock.leftp;
197340230Sdonn 			free( (charptr) lp );
197440230Sdonn 			return(e);
197540230Sdonn 			}
197640230Sdonn 		break;
197740230Sdonn 
197840230Sdonn 	case OPCALL:
197940230Sdonn 	case OPCCALL:
198040230Sdonn 		etype = ltype;
198140230Sdonn 		if(rp!=NULL && rp->listblock.listp==NULL)
198240230Sdonn 			{
198340230Sdonn 			free( (charptr) rp );
198440230Sdonn 			rp = NULL;
198540230Sdonn 			}
198640230Sdonn 		break;
198740230Sdonn 
198840230Sdonn 	case OPAND:
198940230Sdonn 	case OPOR:
199040230Sdonn 		if( ISCONST(lp) )
199140230Sdonn 			COMMUTE
199240230Sdonn 
199340230Sdonn 		if( ISCONST(rp) )
199440230Sdonn 			{
199546303Sbostic 			if(rp->constblock.constant.ci == 0)
199640230Sdonn 				if(opcode == OPOR)
199740230Sdonn 					goto retleft;
199840230Sdonn 				else
199940230Sdonn 					goto retright;
200040230Sdonn 			else if(opcode == OPOR)
200140230Sdonn 				goto retright;
200240230Sdonn 			else
200340230Sdonn 				goto retleft;
200440230Sdonn 			}
200540230Sdonn 	case OPLSHIFT:
200640230Sdonn 		if (ISICON(rp))
200740230Sdonn 			{
200846303Sbostic 			if (rp->constblock.constant.ci == 0)
200940230Sdonn 				goto retleft;
201040230Sdonn 			if ((lp->tag == TEXPR) &&
201140230Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
201240230Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
201340230Sdonn 			    ISICON(lp->exprblock.rightp))
201440230Sdonn 				{
201540230Sdonn 				q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
201640230Sdonn 					cpexpr(rp));
201740230Sdonn 				q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
201840230Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
201940230Sdonn 				free((char *) lp);
202040230Sdonn 				return q;
202140230Sdonn 				}
202240230Sdonn 			}
202340230Sdonn 
202440230Sdonn 	case OPEQV:
202540230Sdonn 	case OPNEQV:
202640230Sdonn 
202740230Sdonn 	case OPBITAND:
202840230Sdonn 	case OPBITOR:
202940230Sdonn 	case OPBITXOR:
203040230Sdonn 	case OPBITNOT:
203140230Sdonn 	case OPRSHIFT:
203240230Sdonn 
203340230Sdonn 	case OPLT:
203440230Sdonn 	case OPGT:
203540230Sdonn 	case OPLE:
203640230Sdonn 	case OPGE:
203740230Sdonn 	case OPEQ:
203840230Sdonn 	case OPNE:
203940230Sdonn 
204040230Sdonn 	case OPCONCAT:
204140230Sdonn 		break;
204240230Sdonn 	case OPMIN:
204340230Sdonn 	case OPMAX:
204440230Sdonn 
204540230Sdonn 	case OPASSIGN:
204640230Sdonn 	case OPPLUSEQ:
204740230Sdonn 	case OPSTAREQ:
204840230Sdonn 
204940230Sdonn 	case OPCONV:
205040230Sdonn 	case OPADDR:
205140230Sdonn 
205240230Sdonn 	case OPCOMMA:
205340230Sdonn 	case OPQUEST:
205440230Sdonn 	case OPCOLON:
205540230Sdonn 
205640230Sdonn 	case OPPAREN:
205740230Sdonn 		break;
205840230Sdonn 
205940230Sdonn 	default:
206040230Sdonn 		badop("mkexpr", opcode);
206140230Sdonn 	}
206240230Sdonn 
206340230Sdonn e = (expptr) ALLOC(Exprblock);
206440230Sdonn e->exprblock.tag = TEXPR;
206540230Sdonn e->exprblock.opcode = opcode;
206640230Sdonn e->exprblock.vtype = etype;
206740230Sdonn e->exprblock.leftp = lp;
206840230Sdonn e->exprblock.rightp = rp;
206940230Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) )
207040230Sdonn 	e = fold(e);
207140230Sdonn return(e);
207240230Sdonn 
207340230Sdonn retleft:
207440230Sdonn 	frexpr(rp);
207540230Sdonn 	return(lp);
207640230Sdonn 
207740230Sdonn retright:
207840230Sdonn 	frexpr(lp);
207940230Sdonn 	return(rp);
208040230Sdonn 
208140230Sdonn error:
208240230Sdonn 	frexpr(lp);
208340230Sdonn 	if(rp && opcode!=OPCALL && opcode!=OPCCALL)
208440230Sdonn 		frexpr(rp);
208540230Sdonn 	return( errnode() );
208640230Sdonn }
208740230Sdonn 
208840230Sdonn #define ERR(s)   { errs = s; goto error; }
208940230Sdonn 
cktype(op,lt,rt)209040230Sdonn cktype(op, lt, rt)
209140230Sdonn register int op, lt, rt;
209240230Sdonn {
209340230Sdonn char *errs;
209440230Sdonn 
209540230Sdonn if(lt==TYERROR || rt==TYERROR)
209640230Sdonn 	goto error1;
209740230Sdonn 
209840230Sdonn if(lt==TYUNKNOWN)
209940230Sdonn 	return(TYUNKNOWN);
210040230Sdonn if(rt==TYUNKNOWN)
210140230Sdonn 	if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
210240230Sdonn 	    op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
210340230Sdonn 		return(TYUNKNOWN);
210440230Sdonn 
210540230Sdonn switch(op)
210640230Sdonn 	{
210740230Sdonn 	case OPPLUS:
210840230Sdonn 	case OPMINUS:
210940230Sdonn 	case OPSTAR:
211040230Sdonn 	case OPSLASH:
211140230Sdonn 	case OPPOWER:
211240230Sdonn 	case OPMOD:
211340230Sdonn 		if( ISNUMERIC(lt) && ISNUMERIC(rt) )
211440230Sdonn 			return( maxtype(lt, rt) );
211540230Sdonn 		ERR("nonarithmetic operand of arithmetic operator")
211640230Sdonn 
211740230Sdonn 	case OPNEG:
211840230Sdonn 		if( ISNUMERIC(lt) )
211940230Sdonn 			return(lt);
212040230Sdonn 		ERR("nonarithmetic operand of negation")
212140230Sdonn 
212240230Sdonn 	case OPNOT:
212340230Sdonn 		if(lt == TYLOGICAL)
212440230Sdonn 			return(TYLOGICAL);
212540230Sdonn 		ERR("NOT of nonlogical")
212640230Sdonn 
212740230Sdonn 	case OPAND:
212840230Sdonn 	case OPOR:
212940230Sdonn 	case OPEQV:
213040230Sdonn 	case OPNEQV:
213140230Sdonn 		if(lt==TYLOGICAL && rt==TYLOGICAL)
213240230Sdonn 			return(TYLOGICAL);
213340230Sdonn 		ERR("nonlogical operand of logical operator")
213440230Sdonn 
213540230Sdonn 	case OPLT:
213640230Sdonn 	case OPGT:
213740230Sdonn 	case OPLE:
213840230Sdonn 	case OPGE:
213940230Sdonn 	case OPEQ:
214040230Sdonn 	case OPNE:
214140230Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
214240230Sdonn 			{
214340230Sdonn 			if(lt != rt)
214440230Sdonn 				ERR("illegal comparison")
214540230Sdonn 			}
214640230Sdonn 
214740230Sdonn 		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
214840230Sdonn 			{
214940230Sdonn 			if(op!=OPEQ && op!=OPNE)
215040230Sdonn 				ERR("order comparison of complex data")
215140230Sdonn 			}
215240230Sdonn 
215340230Sdonn 		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
215440230Sdonn 			ERR("comparison of nonarithmetic data")
215540230Sdonn 		return(TYLOGICAL);
215640230Sdonn 
215740230Sdonn 	case OPCONCAT:
215840230Sdonn 		if(lt==TYCHAR && rt==TYCHAR)
215940230Sdonn 			return(TYCHAR);
216040230Sdonn 		ERR("concatenation of nonchar data")
216140230Sdonn 
216240230Sdonn 	case OPCALL:
216340230Sdonn 	case OPCCALL:
216440230Sdonn 		return(lt);
216540230Sdonn 
216640230Sdonn 	case OPADDR:
216740230Sdonn 		return(TYADDR);
216840230Sdonn 
216940230Sdonn 	case OPCONV:
217040230Sdonn 		if(ISCOMPLEX(lt))
217140230Sdonn 			{
217240230Sdonn 			if(ISNUMERIC(rt))
217340230Sdonn 				return(lt);
217440230Sdonn 			ERR("impossible conversion")
217540230Sdonn 			}
217640230Sdonn 		if(rt == 0)
217740230Sdonn 			return(0);
217840230Sdonn 		if(lt==TYCHAR && ISINT(rt) )
217940230Sdonn 			return(TYCHAR);
218040230Sdonn 	case OPASSIGN:
218140230Sdonn 	case OPPLUSEQ:
218240230Sdonn 	case OPSTAREQ:
218340230Sdonn 		if( ISINT(lt) && rt==TYCHAR)
218440230Sdonn 			return(lt);
218540230Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
218640230Sdonn 			if(op!=OPASSIGN || lt!=rt)
218740230Sdonn 				{
218840230Sdonn /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
218940230Sdonn /* debug fatal("impossible conversion.  possible compiler bug"); */
219040230Sdonn 				ERR("impossible conversion")
219140230Sdonn 				}
219240230Sdonn 		return(lt);
219340230Sdonn 
219440230Sdonn 	case OPMIN:
219540230Sdonn 	case OPMAX:
219640230Sdonn 	case OPBITOR:
219740230Sdonn 	case OPBITAND:
219840230Sdonn 	case OPBITXOR:
219940230Sdonn 	case OPBITNOT:
220040230Sdonn 	case OPLSHIFT:
220140230Sdonn 	case OPRSHIFT:
220240230Sdonn 	case OPPAREN:
220340230Sdonn 		return(lt);
220440230Sdonn 
220540230Sdonn 	case OPCOMMA:
220640230Sdonn 	case OPQUEST:
220740230Sdonn 	case OPCOLON:
220840230Sdonn 		return(rt);
220940230Sdonn 
221040230Sdonn 	default:
221140230Sdonn 		badop("cktype", op);
221240230Sdonn 	}
221340230Sdonn error:	err(errs);
221440230Sdonn error1:	return(TYERROR);
221540230Sdonn }
221640230Sdonn 
fold(e)221740230Sdonn LOCAL expptr fold(e)
221840230Sdonn register expptr e;
221940230Sdonn {
222040230Sdonn Constp p;
222140230Sdonn register expptr lp, rp;
222240230Sdonn int etype, mtype, ltype, rtype, opcode;
222340230Sdonn int i, ll, lr;
222440230Sdonn char *q, *s;
222540230Sdonn union Constant lcon, rcon;
222640230Sdonn 
222740230Sdonn opcode = e->exprblock.opcode;
222840230Sdonn etype = e->exprblock.vtype;
222940230Sdonn 
223040230Sdonn lp = e->exprblock.leftp;
223140230Sdonn ltype = lp->headblock.vtype;
223240230Sdonn rp = e->exprblock.rightp;
223340230Sdonn 
223440230Sdonn if(rp == 0)
223540230Sdonn 	switch(opcode)
223640230Sdonn 		{
223740230Sdonn 		case OPNOT:
223846303Sbostic 			lp->constblock.constant.ci =
223946303Sbostic 			    ! lp->constblock.constant.ci;
224040230Sdonn 			return(lp);
224140230Sdonn 
224240230Sdonn 		case OPBITNOT:
224346303Sbostic 			lp->constblock.constant.ci =
224446303Sbostic 			    ~ lp->constblock.constant.ci;
224540230Sdonn 			return(lp);
224640230Sdonn 
224740230Sdonn 		case OPNEG:
224840230Sdonn 			consnegop(lp);
224940230Sdonn 			return(lp);
225040230Sdonn 
225140230Sdonn 		case OPCONV:
225240230Sdonn 		case OPADDR:
225340230Sdonn 		case OPPAREN:
225440230Sdonn 			return(e);
225540230Sdonn 
225640230Sdonn 		default:
225740230Sdonn 			badop("fold", opcode);
225840230Sdonn 		}
225940230Sdonn 
226040230Sdonn rtype = rp->headblock.vtype;
226140230Sdonn 
226240230Sdonn p = ALLOC(Constblock);
226340230Sdonn p->tag = TCONST;
226440230Sdonn p->vtype = etype;
226540230Sdonn p->vleng = e->exprblock.vleng;
226640230Sdonn 
226740230Sdonn switch(opcode)
226840230Sdonn 	{
226940230Sdonn 	case OPCOMMA:
227040230Sdonn 	case OPQUEST:
227140230Sdonn 	case OPCOLON:
227240230Sdonn 		return(e);
227340230Sdonn 
227440230Sdonn 	case OPAND:
227546303Sbostic 		p->constant.ci = lp->constblock.constant.ci &&
227646303Sbostic 				rp->constblock.constant.ci;
227740230Sdonn 		break;
227840230Sdonn 
227940230Sdonn 	case OPOR:
228046303Sbostic 		p->constant.ci = lp->constblock.constant.ci ||
228146303Sbostic 				rp->constblock.constant.ci;
228240230Sdonn 		break;
228340230Sdonn 
228440230Sdonn 	case OPEQV:
228546303Sbostic 		p->constant.ci = lp->constblock.constant.ci ==
228646303Sbostic 				rp->constblock.constant.ci;
228740230Sdonn 		break;
228840230Sdonn 
228940230Sdonn 	case OPNEQV:
229046303Sbostic 		p->constant.ci = lp->constblock.constant.ci !=
229146303Sbostic 				rp->constblock.constant.ci;
229240230Sdonn 		break;
229340230Sdonn 
229440230Sdonn 	case OPBITAND:
229546303Sbostic 		p->constant.ci = lp->constblock.constant.ci &
229646303Sbostic 				rp->constblock.constant.ci;
229740230Sdonn 		break;
229840230Sdonn 
229940230Sdonn 	case OPBITOR:
230046303Sbostic 		p->constant.ci = lp->constblock.constant.ci |
230146303Sbostic 				rp->constblock.constant.ci;
230240230Sdonn 		break;
230340230Sdonn 
230440230Sdonn 	case OPBITXOR:
230546303Sbostic 		p->constant.ci = lp->constblock.constant.ci ^
230646303Sbostic 				rp->constblock.constant.ci;
230740230Sdonn 		break;
230840230Sdonn 
230940230Sdonn 	case OPLSHIFT:
231046303Sbostic 		p->constant.ci = lp->constblock.constant.ci <<
231146303Sbostic 				rp->constblock.constant.ci;
231240230Sdonn 		break;
231340230Sdonn 
231440230Sdonn 	case OPRSHIFT:
231546303Sbostic 		p->constant.ci = lp->constblock.constant.ci >>
231646303Sbostic 				rp->constblock.constant.ci;
231740230Sdonn 		break;
231840230Sdonn 
231940230Sdonn 	case OPCONCAT:
232046303Sbostic 		ll = lp->constblock.vleng->constblock.constant.ci;
232146303Sbostic 		lr = rp->constblock.vleng->constblock.constant.ci;
232246303Sbostic 		p->constant.ccp = q = (char *) ckalloc(ll+lr);
232340230Sdonn 		p->vleng = ICON(ll+lr);
232446303Sbostic 		s = lp->constblock.constant.ccp;
232540230Sdonn 		for(i = 0 ; i < ll ; ++i)
232640230Sdonn 			*q++ = *s++;
232746303Sbostic 		s = rp->constblock.constant.ccp;
232840230Sdonn 		for(i = 0; i < lr; ++i)
232940230Sdonn 			*q++ = *s++;
233040230Sdonn 		break;
233140230Sdonn 
233240230Sdonn 
233340230Sdonn 	case OPPOWER:
233440230Sdonn 		if( ! ISINT(rtype) )
233540230Sdonn 			return(e);
233646303Sbostic 		conspower(&(p->constant), lp, rp->constblock.constant.ci);
233740230Sdonn 		break;
233840230Sdonn 
233940230Sdonn 
234040230Sdonn 	default:
234140230Sdonn 		if(ltype == TYCHAR)
234240230Sdonn 			{
234346303Sbostic 			lcon.ci = cmpstr(lp->constblock.constant.ccp,
234446303Sbostic 				rp->constblock.constant.ccp,
234546303Sbostic 				lp->constblock.vleng->constblock.constant.ci,
234646303Sbostic 				rp->constblock.vleng->constblock.constant.ci);
234740230Sdonn 			rcon.ci = 0;
234840230Sdonn 			mtype = tyint;
234940230Sdonn 			}
235040230Sdonn 		else	{
235140230Sdonn 			mtype = maxtype(ltype, rtype);
235246303Sbostic 			consconv(mtype, &lcon, ltype,
235346303Sbostic 				&(lp->constblock.constant) );
235446303Sbostic 			consconv(mtype, &rcon, rtype,
235546303Sbostic 				&(rp->constblock.constant) );
235640230Sdonn 			}
235746303Sbostic 		consbinop(opcode, mtype, &(p->constant), &lcon, &rcon);
235840230Sdonn 		break;
235940230Sdonn 	}
236040230Sdonn 
236140230Sdonn frexpr(e);
236240230Sdonn return( (expptr) p );
236340230Sdonn }
236440230Sdonn 
236540230Sdonn 
236640230Sdonn 
236740230Sdonn /* assign constant l = r , doing coercion */
236840230Sdonn 
consconv(lt,lv,rt,rv)236940230Sdonn consconv(lt, lv, rt, rv)
237040230Sdonn int lt, rt;
237140230Sdonn register union Constant *lv, *rv;
237240230Sdonn {
237340230Sdonn switch(lt)
237440230Sdonn 	{
237540230Sdonn 	case TYCHAR:
237640230Sdonn 		*(lv->ccp = (char *) ckalloc(1)) = rv->ci;
237740230Sdonn 		break;
237840230Sdonn 
237940230Sdonn 	case TYSHORT:
238040230Sdonn 	case TYLONG:
238140230Sdonn 		if(rt == TYCHAR)
238240230Sdonn 			lv->ci = rv->ccp[0];
238340230Sdonn 		else if( ISINT(rt) )
238440230Sdonn 			lv->ci = rv->ci;
238540230Sdonn 		else	lv->ci = rv->cd[0];
238640230Sdonn 		break;
238740230Sdonn 
238840230Sdonn 	case TYCOMPLEX:
238940230Sdonn 	case TYDCOMPLEX:
239040230Sdonn 		switch(rt)
239140230Sdonn 			{
239240230Sdonn 			case TYSHORT:
239340230Sdonn 			case TYLONG:
239440230Sdonn 				/* fall through and do real assignment of
239540230Sdonn 				   first element
239640230Sdonn 				*/
239740230Sdonn 			case TYREAL:
239840230Sdonn 			case TYDREAL:
239940230Sdonn 				lv->cd[1] = 0; break;
240040230Sdonn 			case TYCOMPLEX:
240140230Sdonn 			case TYDCOMPLEX:
240240230Sdonn 				lv->cd[1] = rv->cd[1]; break;
240340230Sdonn 			}
240440230Sdonn 
240540230Sdonn 	case TYREAL:
240640230Sdonn 	case TYDREAL:
240740230Sdonn 		if( ISINT(rt) )
240840230Sdonn 			lv->cd[0] = rv->ci;
240940230Sdonn 		else	lv->cd[0] = rv->cd[0];
241040230Sdonn 		if( lt == TYREAL)
241140230Sdonn 			{
241240230Sdonn 			float f = lv->cd[0];
241340230Sdonn 			lv->cd[0] = f;
241440230Sdonn 			}
241540230Sdonn 		break;
241640230Sdonn 
241740230Sdonn 	case TYLOGICAL:
241840230Sdonn 		lv->ci = rv->ci;
241940230Sdonn 		break;
242040230Sdonn 	}
242140230Sdonn }
242240230Sdonn 
242340230Sdonn 
242440230Sdonn 
consnegop(p)242540230Sdonn consnegop(p)
242640230Sdonn register Constp p;
242740230Sdonn {
242840230Sdonn switch(p->vtype)
242940230Sdonn 	{
243040230Sdonn 	case TYSHORT:
243140230Sdonn 	case TYLONG:
243246303Sbostic 		p->constant.ci = - p->constant.ci;
243340230Sdonn 		break;
243440230Sdonn 
243540230Sdonn 	case TYCOMPLEX:
243640230Sdonn 	case TYDCOMPLEX:
243746303Sbostic 		p->constant.cd[1] = - p->constant.cd[1];
243840230Sdonn 		/* fall through and do the real parts */
243940230Sdonn 	case TYREAL:
244040230Sdonn 	case TYDREAL:
244146303Sbostic 		p->constant.cd[0] = - p->constant.cd[0];
244240230Sdonn 		break;
244340230Sdonn 	default:
244440230Sdonn 		badtype("consnegop", p->vtype);
244540230Sdonn 	}
244640230Sdonn }
244740230Sdonn 
244840230Sdonn 
244940230Sdonn 
conspower(powp,ap,n)245040230Sdonn LOCAL conspower(powp, ap, n)
245140230Sdonn register union Constant *powp;
245240230Sdonn Constp ap;
245340230Sdonn ftnint n;
245440230Sdonn {
245540230Sdonn register int type;
245640230Sdonn union Constant x;
245740230Sdonn 
245840230Sdonn switch(type = ap->vtype)	/* pow = 1 */
245940230Sdonn 	{
246040230Sdonn 	case TYSHORT:
246140230Sdonn 	case TYLONG:
246240230Sdonn 		powp->ci = 1;
246340230Sdonn 		break;
246440230Sdonn 	case TYCOMPLEX:
246540230Sdonn 	case TYDCOMPLEX:
246640230Sdonn 		powp->cd[1] = 0;
246740230Sdonn 	case TYREAL:
246840230Sdonn 	case TYDREAL:
246940230Sdonn 		powp->cd[0] = 1;
247040230Sdonn 		break;
247140230Sdonn 	default:
247240230Sdonn 		badtype("conspower", type);
247340230Sdonn 	}
247440230Sdonn 
247540230Sdonn if(n == 0)
247640230Sdonn 	return;
247740230Sdonn if(n < 0)
247840230Sdonn 	{
247940230Sdonn 	if( ISINT(type) )
248040230Sdonn 		{
248146303Sbostic 		if (ap->constant.ci == 0)
248240230Sdonn 			err("zero raised to a negative power");
248346303Sbostic 		else if (ap->constant.ci == 1)
248440230Sdonn 			return;
248546303Sbostic 		else if (ap->constant.ci == -1)
248640230Sdonn 			{
248740230Sdonn 			if (n < -2)
248840230Sdonn 				n = n + 2;
248940230Sdonn 			n = -n;
249040230Sdonn 			if (n % 2 == 1)
249140230Sdonn 				powp->ci = -1;
249240230Sdonn 			}
249340230Sdonn 		else
249440230Sdonn 			powp->ci = 0;
249540230Sdonn 		return;
249640230Sdonn 		}
249740230Sdonn 	n = - n;
249846303Sbostic 	consbinop(OPSLASH, type, &x, powp, &(ap->constant));
249940230Sdonn 	}
250040230Sdonn else
250146303Sbostic 	consbinop(OPSTAR, type, &x, powp, &(ap->constant));
250240230Sdonn 
250340230Sdonn for( ; ; )
250440230Sdonn 	{
250540230Sdonn 	if(n & 01)
250640230Sdonn 		consbinop(OPSTAR, type, powp, powp, &x);
250740230Sdonn 	if(n >>= 1)
250840230Sdonn 		consbinop(OPSTAR, type, &x, &x, &x);
250940230Sdonn 	else
251040230Sdonn 		break;
251140230Sdonn 	}
251240230Sdonn }
251340230Sdonn 
251440230Sdonn 
251540230Sdonn 
251640230Sdonn /* do constant operation cp = a op b */
251740230Sdonn 
251840230Sdonn 
consbinop(opcode,type,cp,ap,bp)251940230Sdonn LOCAL consbinop(opcode, type, cp, ap, bp)
252040230Sdonn int opcode, type;
252140230Sdonn register union Constant *ap, *bp, *cp;
252240230Sdonn {
252340230Sdonn int k;
252440230Sdonn double temp;
252540230Sdonn 
252640230Sdonn switch(opcode)
252740230Sdonn 	{
252840230Sdonn 	case OPPLUS:
252940230Sdonn 		switch(type)
253040230Sdonn 			{
253140230Sdonn 			case TYSHORT:
253240230Sdonn 			case TYLONG:
253340230Sdonn 				cp->ci = ap->ci + bp->ci;
253440230Sdonn 				break;
253540230Sdonn 			case TYCOMPLEX:
253640230Sdonn 			case TYDCOMPLEX:
253740230Sdonn 				cp->cd[1] = ap->cd[1] + bp->cd[1];
253840230Sdonn 			case TYREAL:
253940230Sdonn 			case TYDREAL:
254040230Sdonn 				cp->cd[0] = ap->cd[0] + bp->cd[0];
254140230Sdonn 				break;
254240230Sdonn 			}
254340230Sdonn 		break;
254440230Sdonn 
254540230Sdonn 	case OPMINUS:
254640230Sdonn 		switch(type)
254740230Sdonn 			{
254840230Sdonn 			case TYSHORT:
254940230Sdonn 			case TYLONG:
255040230Sdonn 				cp->ci = ap->ci - bp->ci;
255140230Sdonn 				break;
255240230Sdonn 			case TYCOMPLEX:
255340230Sdonn 			case TYDCOMPLEX:
255440230Sdonn 				cp->cd[1] = ap->cd[1] - bp->cd[1];
255540230Sdonn 			case TYREAL:
255640230Sdonn 			case TYDREAL:
255740230Sdonn 				cp->cd[0] = ap->cd[0] - bp->cd[0];
255840230Sdonn 				break;
255940230Sdonn 			}
256040230Sdonn 		break;
256140230Sdonn 
256240230Sdonn 	case OPSTAR:
256340230Sdonn 		switch(type)
256440230Sdonn 			{
256540230Sdonn 			case TYSHORT:
256640230Sdonn 			case TYLONG:
256740230Sdonn 				cp->ci = ap->ci * bp->ci;
256840230Sdonn 				break;
256940230Sdonn 			case TYREAL:
257040230Sdonn 			case TYDREAL:
257140230Sdonn 				cp->cd[0] = ap->cd[0] * bp->cd[0];
257240230Sdonn 				break;
257340230Sdonn 			case TYCOMPLEX:
257440230Sdonn 			case TYDCOMPLEX:
257540230Sdonn 				temp = ap->cd[0] * bp->cd[0] -
257640230Sdonn 					    ap->cd[1] * bp->cd[1] ;
257740230Sdonn 				cp->cd[1] = ap->cd[0] * bp->cd[1] +
257840230Sdonn 					    ap->cd[1] * bp->cd[0] ;
257940230Sdonn 				cp->cd[0] = temp;
258040230Sdonn 				break;
258140230Sdonn 			}
258240230Sdonn 		break;
258340230Sdonn 	case OPSLASH:
258440230Sdonn 		switch(type)
258540230Sdonn 			{
258640230Sdonn 			case TYSHORT:
258740230Sdonn 			case TYLONG:
258840230Sdonn 				cp->ci = ap->ci / bp->ci;
258940230Sdonn 				break;
259040230Sdonn 			case TYREAL:
259140230Sdonn 			case TYDREAL:
259240230Sdonn 				cp->cd[0] = ap->cd[0] / bp->cd[0];
259340230Sdonn 				break;
259440230Sdonn 			case TYCOMPLEX:
259540230Sdonn 			case TYDCOMPLEX:
259640230Sdonn 				zdiv(cp,ap,bp);
259740230Sdonn 				break;
259840230Sdonn 			}
259940230Sdonn 		break;
260040230Sdonn 
260140230Sdonn 	case OPMOD:
260240230Sdonn 		if( ISINT(type) )
260340230Sdonn 			{
260440230Sdonn 			cp->ci = ap->ci % bp->ci;
260540230Sdonn 			break;
260640230Sdonn 			}
260740230Sdonn 		else
260840230Sdonn 			fatal("inline mod of noninteger");
260940230Sdonn 
261040230Sdonn 	default:	  /* relational ops */
261140230Sdonn 		switch(type)
261240230Sdonn 			{
261340230Sdonn 			case TYSHORT:
261440230Sdonn 			case TYLONG:
261540230Sdonn 				if(ap->ci < bp->ci)
261640230Sdonn 					k = -1;
261740230Sdonn 				else if(ap->ci == bp->ci)
261840230Sdonn 					k = 0;
261940230Sdonn 				else	k = 1;
262040230Sdonn 				break;
262140230Sdonn 			case TYREAL:
262240230Sdonn 			case TYDREAL:
262340230Sdonn 				if(ap->cd[0] < bp->cd[0])
262440230Sdonn 					k = -1;
262540230Sdonn 				else if(ap->cd[0] == bp->cd[0])
262640230Sdonn 					k = 0;
262740230Sdonn 				else	k = 1;
262840230Sdonn 				break;
262940230Sdonn 			case TYCOMPLEX:
263040230Sdonn 			case TYDCOMPLEX:
263140230Sdonn 				if(ap->cd[0] == bp->cd[0] &&
263240230Sdonn 				   ap->cd[1] == bp->cd[1] )
263340230Sdonn 					k = 0;
263440230Sdonn 				else	k = 1;
263540230Sdonn 				break;
263640230Sdonn 			}
263740230Sdonn 
263840230Sdonn 		switch(opcode)
263940230Sdonn 			{
264040230Sdonn 			case OPEQ:
264140230Sdonn 				cp->ci = (k == 0);
264240230Sdonn 				break;
264340230Sdonn 			case OPNE:
264440230Sdonn 				cp->ci = (k != 0);
264540230Sdonn 				break;
264640230Sdonn 			case OPGT:
264740230Sdonn 				cp->ci = (k == 1);
264840230Sdonn 				break;
264940230Sdonn 			case OPLT:
265040230Sdonn 				cp->ci = (k == -1);
265140230Sdonn 				break;
265240230Sdonn 			case OPGE:
265340230Sdonn 				cp->ci = (k >= 0);
265440230Sdonn 				break;
265540230Sdonn 			case OPLE:
265640230Sdonn 				cp->ci = (k <= 0);
265740230Sdonn 				break;
265840230Sdonn 			default:
265940230Sdonn 				badop ("consbinop", opcode);
266040230Sdonn 			}
266140230Sdonn 		break;
266240230Sdonn 	}
266340230Sdonn }
266440230Sdonn 
266540230Sdonn 
266640230Sdonn 
266740230Sdonn 
conssgn(p)266840230Sdonn conssgn(p)
266940230Sdonn register expptr p;
267040230Sdonn {
267140230Sdonn if( ! ISCONST(p) )
267240230Sdonn 	fatal( "sgn(nonconstant)" );
267340230Sdonn 
267440230Sdonn switch(p->headblock.vtype)
267540230Sdonn 	{
267640230Sdonn 	case TYSHORT:
267740230Sdonn 	case TYLONG:
267846303Sbostic 		if(p->constblock.constant.ci > 0) return(1);
267946303Sbostic 		if(p->constblock.constant.ci < 0) return(-1);
268040230Sdonn 		return(0);
268140230Sdonn 
268240230Sdonn 	case TYREAL:
268340230Sdonn 	case TYDREAL:
268446303Sbostic 		if(p->constblock.constant.cd[0] > 0) return(1);
268546303Sbostic 		if(p->constblock.constant.cd[0] < 0) return(-1);
268640230Sdonn 		return(0);
268740230Sdonn 
268840230Sdonn 	case TYCOMPLEX:
268940230Sdonn 	case TYDCOMPLEX:
269046303Sbostic 		return(p->constblock.constant.cd[0]!=0 ||
269146303Sbostic 			p->constblock.constant.cd[1]!=0);
269240230Sdonn 
269340230Sdonn 	default:
269440230Sdonn 		badtype( "conssgn", p->constblock.vtype);
269540230Sdonn 	}
269640230Sdonn /* NOTREACHED */
269740230Sdonn }
269840230Sdonn 
269940230Sdonn char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
270040230Sdonn 
270140230Sdonn 
mkpower(p)270240230Sdonn LOCAL expptr mkpower(p)
270340230Sdonn register expptr p;
270440230Sdonn {
270540230Sdonn register expptr q, lp, rp;
270640230Sdonn int ltype, rtype, mtype;
270740230Sdonn 
270840230Sdonn lp = p->exprblock.leftp;
270940230Sdonn rp = p->exprblock.rightp;
271040230Sdonn ltype = lp->headblock.vtype;
271140230Sdonn rtype = rp->headblock.vtype;
271240230Sdonn 
271340230Sdonn if(ISICON(rp))
271440230Sdonn 	{
271546303Sbostic 	if(rp->constblock.constant.ci == 0)
271640230Sdonn 		{
271740230Sdonn 		frexpr(p);
271840230Sdonn 		if( ISINT(ltype) )
271940230Sdonn 			return( ICON(1) );
272040230Sdonn 		else
272140230Sdonn 			{
272240230Sdonn 			expptr pp;
272340230Sdonn 			pp = mkconv(ltype, ICON(1));
272440230Sdonn 			return( pp );
272540230Sdonn 			}
272640230Sdonn 		}
272746303Sbostic 	if(rp->constblock.constant.ci < 0)
272840230Sdonn 		{
272940230Sdonn 		if( ISINT(ltype) )
273040230Sdonn 			{
273140230Sdonn 			frexpr(p);
273240230Sdonn 			err("integer**negative");
273340230Sdonn 			return( errnode() );
273440230Sdonn 			}
273546303Sbostic 		rp->constblock.constant.ci = - rp->constblock.constant.ci;
273640230Sdonn 		p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
273740230Sdonn 		}
273846303Sbostic 	if(rp->constblock.constant.ci == 1)
273940230Sdonn 		{
274040230Sdonn 		frexpr(rp);
274140230Sdonn 		free( (charptr) p );
274240230Sdonn 		return(lp);
274340230Sdonn 		}
274440230Sdonn 
274540230Sdonn 	if( ONEOF(ltype, MSKINT|MSKREAL) )
274640230Sdonn 		{
274740230Sdonn 		p->exprblock.vtype = ltype;
274840230Sdonn 		return(p);
274940230Sdonn 		}
275040230Sdonn 	}
275140230Sdonn if( ISINT(rtype) )
275240230Sdonn 	{
275340230Sdonn 	if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
275440230Sdonn 		q = call2(TYSHORT, "pow_hh", lp, rp);
275540230Sdonn 	else	{
275640230Sdonn 		if(ltype == TYSHORT)
275740230Sdonn 			{
275840230Sdonn 			ltype = TYLONG;
275940230Sdonn 			lp = mkconv(TYLONG,lp);
276040230Sdonn 			}
276140230Sdonn 		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
276240230Sdonn 		}
276340230Sdonn 	}
276440230Sdonn else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
276540230Sdonn 	q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
276640230Sdonn else	{
276740230Sdonn 	q  = call2(TYDCOMPLEX, "pow_zz",
276840230Sdonn 		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
276940230Sdonn 	if(mtype == TYCOMPLEX)
277040230Sdonn 		q = mkconv(TYCOMPLEX, q);
277140230Sdonn 	}
277240230Sdonn free( (charptr) p );
277340230Sdonn return(q);
277440230Sdonn }
277540230Sdonn 
277640230Sdonn 
277740230Sdonn 
277840230Sdonn /* Complex Division.  Same code as in Runtime Library
277940230Sdonn */
278040230Sdonn 
278140230Sdonn struct dcomplex { double dreal, dimag; };
278240230Sdonn 
278340230Sdonn 
zdiv(c,a,b)278440230Sdonn LOCAL zdiv(c, a, b)
278540230Sdonn register struct dcomplex *a, *b, *c;
278640230Sdonn {
278740230Sdonn double ratio, den;
278840230Sdonn double abr, abi;
278940230Sdonn 
279040230Sdonn if( (abr = b->dreal) < 0.)
279140230Sdonn 	abr = - abr;
279240230Sdonn if( (abi = b->dimag) < 0.)
279340230Sdonn 	abi = - abi;
279440230Sdonn if( abr <= abi )
279540230Sdonn 	{
279640230Sdonn 	if(abi == 0)
279740230Sdonn 		fatal("complex division by zero");
279840230Sdonn 	ratio = b->dreal / b->dimag ;
279940230Sdonn 	den = b->dimag * (1 + ratio*ratio);
280040230Sdonn 	c->dreal = (a->dreal*ratio + a->dimag) / den;
280140230Sdonn 	c->dimag = (a->dimag*ratio - a->dreal) / den;
280240230Sdonn 	}
280340230Sdonn 
280440230Sdonn else
280540230Sdonn 	{
280640230Sdonn 	ratio = b->dimag / b->dreal ;
280740230Sdonn 	den = b->dreal * (1 + ratio*ratio);
280840230Sdonn 	c->dreal = (a->dreal + a->dimag*ratio) / den;
280940230Sdonn 	c->dimag = (a->dimag - a->dreal*ratio) / den;
281040230Sdonn 	}
281140230Sdonn 
281240230Sdonn }
281340230Sdonn 
oftwo(e)281440230Sdonn expptr oftwo(e)
281540230Sdonn expptr e;
281640230Sdonn {
281740230Sdonn 	int val,res;
281840230Sdonn 
281940230Sdonn 	if (! ISCONST (e))
282040230Sdonn 		return (0);
282140230Sdonn 
282246303Sbostic 	val = e->constblock.constant.ci;
282340230Sdonn 	switch (val)
282440230Sdonn 		{
282540230Sdonn 		case 2:		res = 1; break;
282640230Sdonn 		case 4:		res = 2; break;
282740230Sdonn 		case 8:		res = 3; break;
282840230Sdonn 		case 16:	res = 4; break;
282940230Sdonn 		case 32:	res = 5; break;
283040230Sdonn 		case 64:	res = 6; break;
283140230Sdonn 		case 128:	res = 7; break;
283240230Sdonn 		case 256:	res = 8; break;
283340230Sdonn 		default:	return (0);
283440230Sdonn 		}
283540230Sdonn 	return (ICON (res));
283640230Sdonn }
2837