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