xref: /csrg-svn/usr.bin/f77/pass1.tahoe/expr.c (revision 40231)
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);
14040230Sdonn p->const.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);
16340230Sdonn p->const.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);
17540230Sdonn p->const.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);
18840230Sdonn p->const.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);
24040230Sdonn   p->const.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);
25640230Sdonn p->const.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) )
27640230Sdonn 		p->const.cd[0] = realp->constblock.const.ci;
27740230Sdonn 	else	p->const.cd[0] = realp->constblock.const.cd[0];
27840230Sdonn 	if( ISINT(itype) )
27940230Sdonn 		p->const.cd[1] = imagp->constblock.const.ci;
28040230Sdonn 	else	p->const.cd[1] = imagp->constblock.const.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);
35240230Sdonn 	consconv(t, &(q->constblock.const),
35340230Sdonn 		p->constblock.vtype, &(p->constblock.const) );
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);
39240230Sdonn 	consconv(t, &(q->constblock.const),
39340230Sdonn 		p->constblock.vtype, &(p->constblock.const) );
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 			{
46840230Sdonn 			e->constblock.const.ccp =
46940230Sdonn 				copyn(1+strlen(e->constblock.const.ccp),
47040230Sdonn 					e->constblock.const.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:
53440230Sdonn 				free( (charptr) (p->constblock.const.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 	{
149740230Sdonn 	if(p->constblock.const.ci < 0)
149840230Sdonn 		goto badsub;
149940230Sdonn 	if( ISICON(dimp->nelt) )
150040230Sdonn 		if(p->constblock.const.ci < dimp->nelt->constblock.const.ci)
150140230Sdonn 			return(p);
150240230Sdonn 		else
150340230Sdonn 			goto badsub;
150440230Sdonn 	}
150540230Sdonn if(p->tag==TADDR && p->addrblock.vstg==STGREG)
150640230Sdonn 	{
150740230Sdonn 	checkvar = (expptr) cpexpr(p);
150840230Sdonn 	t = p;
150940230Sdonn 	}
151040230Sdonn else	{
151140230Sdonn 	checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
151240230Sdonn 	t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
151340230Sdonn 	}
151440230Sdonn checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
151540230Sdonn if( ! ISICON(p) )
151640230Sdonn 	checkcond = mkexpr(OPAND, checkcond,
151740230Sdonn 			mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
151840230Sdonn 
151940230Sdonn badcall = call4(p->headblock.vtype, "s_rnge",
152040230Sdonn 		mkstrcon(VL, np->varname),
152140230Sdonn 		mkconv(TYLONG,  cpexpr(checkvar)),
152240230Sdonn 		mkstrcon(XL, procname),
152340230Sdonn 		ICON(lineno) );
152440230Sdonn badcall->exprblock.opcode = OPCCALL;
152540230Sdonn p = mkexpr(OPQUEST, checkcond,
152640230Sdonn 	mkexpr(OPCOLON, checkvar, badcall));
152740230Sdonn 
152840230Sdonn return(p);
152940230Sdonn 
153040230Sdonn badsub:
153140230Sdonn 	frexpr(p);
153240230Sdonn 	errstr("subscript on variable %s out of range", varstr(VL,np->varname));
153340230Sdonn 	return ( ICON(0) );
153440230Sdonn }
153540230Sdonn 
153640230Sdonn 
153740230Sdonn 
153840230Sdonn 
153940230Sdonn Addrp mkaddr(p)
154040230Sdonn register Namep p;
154140230Sdonn {
154240230Sdonn struct Extsym *extp;
154340230Sdonn register Addrp t;
154440230Sdonn Addrp intraddr();
154540230Sdonn 
154640230Sdonn switch( p->vstg)
154740230Sdonn 	{
154840230Sdonn 	case STGUNKNOWN:
154940230Sdonn 		if(p->vclass != CLPROC)
155040230Sdonn 			break;
155140230Sdonn 		extp = mkext( varunder(VL, p->varname) );
155240230Sdonn 		extp->extstg = STGEXT;
155340230Sdonn 		p->vstg = STGEXT;
155440230Sdonn 		p->vardesc.varno = extp - extsymtab;
155540230Sdonn 		p->vprocclass = PEXTERNAL;
155640230Sdonn 
155740230Sdonn 	case STGCOMMON:
155840230Sdonn 	case STGEXT:
155940230Sdonn 	case STGBSS:
156040230Sdonn 	case STGINIT:
156140230Sdonn 	case STGEQUIV:
156240230Sdonn 	case STGARG:
156340230Sdonn 	case STGLENG:
156440230Sdonn 	case STGAUTO:
156540230Sdonn 		t = ALLOC(Addrblock);
156640230Sdonn 		t->tag = TADDR;
156740230Sdonn 		if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
156840230Sdonn 			t->vclass = CLVAR;
156940230Sdonn 		else
157040230Sdonn 			t->vclass = p->vclass;
157140230Sdonn 		t->vtype = p->vtype;
157240230Sdonn 		t->vstg = p->vstg;
157340230Sdonn 		t->memno = p->vardesc.varno;
157440230Sdonn 		t->issaved = p->vsave;
157540230Sdonn                 if(p->vdim) t->isarray = YES;
157640230Sdonn 		t->memoffset = ICON(p->voffset);
157740230Sdonn 		if(p->vleng)
157840230Sdonn 			{
157940230Sdonn 			t->vleng = (expptr) cpexpr(p->vleng);
158040230Sdonn 			if( ISICON(t->vleng) )
158140230Sdonn 				t->varleng = t->vleng->constblock.const.ci;
158240230Sdonn 			}
158340230Sdonn 		if (p->vstg == STGBSS)
158440230Sdonn 			t->varsize = p->varsize;
158540230Sdonn 		else if (p->vstg == STGEQUIV)
158640230Sdonn 			t->varsize = eqvclass[t->memno].eqvleng;
158740230Sdonn 		return(t);
158840230Sdonn 
158940230Sdonn 	case STGINTR:
159040230Sdonn 		return( intraddr(p) );
159140230Sdonn 
159240230Sdonn 	}
159340230Sdonn /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
159440230Sdonn badstg("mkaddr", p->vstg);
159540230Sdonn /* NOTREACHED */
159640230Sdonn }
159740230Sdonn 
159840230Sdonn 
159940230Sdonn 
160040230Sdonn 
160140230Sdonn Addrp mkarg(type, argno)
160240230Sdonn int type, argno;
160340230Sdonn {
160440230Sdonn register Addrp p;
160540230Sdonn 
160640230Sdonn p = ALLOC(Addrblock);
160740230Sdonn p->tag = TADDR;
160840230Sdonn p->vtype = type;
160940230Sdonn p->vclass = CLVAR;
161040230Sdonn p->vstg = (type==TYLENG ? STGLENG : STGARG);
161140230Sdonn p->memno = argno;
161240230Sdonn return(p);
161340230Sdonn }
161440230Sdonn 
161540230Sdonn 
161640230Sdonn 
161740230Sdonn 
161840230Sdonn expptr mkprim(v, args, substr)
161940230Sdonn register union
162040230Sdonn 	{
162140230Sdonn 	struct Paramblock paramblock;
162240230Sdonn 	struct Nameblock nameblock;
162340230Sdonn 	struct Headblock headblock;
162440230Sdonn 	} *v;
162540230Sdonn struct Listblock *args;
162640230Sdonn chainp substr;
162740230Sdonn {
162840230Sdonn register struct Primblock *p;
162940230Sdonn 
163040230Sdonn if(v->headblock.vclass == CLPARAM)
163140230Sdonn 	{
163240230Sdonn 	if(args || substr)
163340230Sdonn 		{
163440230Sdonn 		errstr("no qualifiers on parameter name %s",
163540230Sdonn 			varstr(VL,v->paramblock.varname));
163640230Sdonn 		frexpr(args);
163740230Sdonn 		if(substr)
163840230Sdonn 			{
163940230Sdonn 			frexpr(substr->datap);
164040230Sdonn 			frexpr(substr->nextp->datap);
164140230Sdonn 			frchain(&substr);
164240230Sdonn 			}
164340230Sdonn 		frexpr(v);
164440230Sdonn 		return( errnode() );
164540230Sdonn 		}
164640230Sdonn 	return( (expptr) cpexpr(v->paramblock.paramval) );
164740230Sdonn 	}
164840230Sdonn 
164940230Sdonn p = ALLOC(Primblock);
165040230Sdonn p->tag = TPRIM;
165140230Sdonn p->vtype = v->nameblock.vtype;
165240230Sdonn p->namep = (Namep) v;
165340230Sdonn p->argsp = args;
165440230Sdonn if(substr)
165540230Sdonn 	{
165640230Sdonn 	p->fcharp = (expptr) substr->datap;
1657*40231Sdonn 	if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
165840230Sdonn 		p->fcharp = mkconv(TYINT, p->fcharp);
165940230Sdonn 	p->lcharp = (expptr) substr->nextp->datap;
1660*40231Sdonn 	if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
166140230Sdonn 		p->lcharp = mkconv(TYINT, p->lcharp);
166240230Sdonn 	frchain(&substr);
166340230Sdonn 	}
166440230Sdonn return( (expptr) p);
166540230Sdonn }
166640230Sdonn 
166740230Sdonn 
166840230Sdonn 
166940230Sdonn vardcl(v)
167040230Sdonn register Namep v;
167140230Sdonn {
167240230Sdonn int nelt;
167340230Sdonn struct Dimblock *t;
167440230Sdonn Addrp p;
167540230Sdonn expptr neltp;
167640230Sdonn int eltsize;
167740230Sdonn int varsize;
167840230Sdonn int tsize;
167940230Sdonn int align;
168040230Sdonn 
168140230Sdonn if(v->vdcldone)
168240230Sdonn 	return;
168340230Sdonn if(v->vclass == CLNAMELIST)
168440230Sdonn 	return;
168540230Sdonn 
168640230Sdonn if(v->vtype == TYUNKNOWN)
168740230Sdonn 	impldcl(v);
168840230Sdonn if(v->vclass == CLUNKNOWN)
168940230Sdonn 	v->vclass = CLVAR;
169040230Sdonn else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
169140230Sdonn 	{
169240230Sdonn 	dclerr("used both as variable and non-variable", v);
169340230Sdonn 	return;
169440230Sdonn 	}
169540230Sdonn if(v->vstg==STGUNKNOWN)
169640230Sdonn 	v->vstg = implstg[ letter(v->varname[0]) ];
169740230Sdonn 
169840230Sdonn switch(v->vstg)
169940230Sdonn 	{
170040230Sdonn 	case STGBSS:
170140230Sdonn 		v->vardesc.varno = ++lastvarno;
170240230Sdonn 		if (v->vclass != CLVAR)
170340230Sdonn 			break;
170440230Sdonn 		nelt = 1;
170540230Sdonn 		t = v->vdim;
170640230Sdonn 		if (t)
170740230Sdonn 			{
170840230Sdonn 			neltp = t->nelt;
170940230Sdonn 			if (neltp && ISICON(neltp))
171040230Sdonn 				nelt = neltp->constblock.const.ci;
171140230Sdonn 			else
171240230Sdonn 				dclerr("improperly dimensioned array", v);
171340230Sdonn 			}
171440230Sdonn 
171540230Sdonn 		if (v->vtype == TYCHAR)
171640230Sdonn 			{
171740230Sdonn 			v->vleng = fixtype(v->vleng);
171840230Sdonn 			if (v->vleng == NULL)
171940230Sdonn 				eltsize = typesize[TYCHAR];
172040230Sdonn 			else if (ISICON(v->vleng))
172140230Sdonn 				eltsize = typesize[TYCHAR] *
172240230Sdonn 					v->vleng->constblock.const.ci;
172340230Sdonn 			else if (v->vleng->tag != TERROR)
172440230Sdonn 				{
172540230Sdonn 				errstr("nonconstant string length on %s",
172640230Sdonn 					varstr(VL, v->varname));
172740230Sdonn 				eltsize = 0;
172840230Sdonn 				}
172940230Sdonn 			}
173040230Sdonn 		else
173140230Sdonn 			eltsize = typesize[v->vtype];
173240230Sdonn 
173340230Sdonn 		v->varsize = nelt * eltsize;
173440230Sdonn 		break;
173540230Sdonn 	case STGAUTO:
173640230Sdonn 		if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
173740230Sdonn 			break;
173840230Sdonn 		nelt = 1;
173940230Sdonn 		if(t = v->vdim)
174040230Sdonn 			if( (neltp = t->nelt) && ISCONST(neltp) )
174140230Sdonn 				nelt = neltp->constblock.const.ci;
174240230Sdonn 			else
174340230Sdonn 				dclerr("adjustable automatic array", v);
174440230Sdonn 		p = autovar(nelt, v->vtype, v->vleng);
174540230Sdonn 		v->vardesc.varno = p->memno;
174640230Sdonn 		v->voffset = p->memoffset->constblock.const.ci;
174740230Sdonn 		frexpr(p);
174840230Sdonn 		break;
174940230Sdonn 
175040230Sdonn 	default:
175140230Sdonn 		break;
175240230Sdonn 	}
175340230Sdonn v->vdcldone = YES;
175440230Sdonn }
175540230Sdonn 
175640230Sdonn 
175740230Sdonn 
175840230Sdonn 
175940230Sdonn impldcl(p)
176040230Sdonn register Namep p;
176140230Sdonn {
176240230Sdonn register int k;
176340230Sdonn int type, leng;
176440230Sdonn 
176540230Sdonn if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
176640230Sdonn 	return;
176740230Sdonn if(p->vtype == TYUNKNOWN)
176840230Sdonn 	{
176940230Sdonn 	k = letter(p->varname[0]);
177040230Sdonn 	type = impltype[ k ];
177140230Sdonn 	leng = implleng[ k ];
177240230Sdonn 	if(type == TYUNKNOWN)
177340230Sdonn 		{
177440230Sdonn 		if(p->vclass == CLPROC)
177540230Sdonn 			dclerr("attempt to use function of undefined type", p);
177640230Sdonn 		else
177740230Sdonn 			dclerr("attempt to use undefined variable", p);
177840230Sdonn 		type = TYERROR;
177940230Sdonn 		leng = 1;
178040230Sdonn 		}
178140230Sdonn 	settype(p, type, leng);
178240230Sdonn 	}
178340230Sdonn }
178440230Sdonn 
178540230Sdonn 
178640230Sdonn 
178740230Sdonn 
178840230Sdonn LOCAL letter(c)
178940230Sdonn register int c;
179040230Sdonn {
179140230Sdonn if( isupper(c) )
179240230Sdonn 	c = tolower(c);
179340230Sdonn return(c - 'a');
179440230Sdonn }
179540230Sdonn 
179640230Sdonn #define ICONEQ(z, c)  (ISICON(z) && z->constblock.const.ci==c)
179740230Sdonn #define COMMUTE	{ e = lp;  lp = rp;  rp = e; }
179840230Sdonn 
179940230Sdonn 
180040230Sdonn expptr mkexpr(opcode, lp, rp)
180140230Sdonn int opcode;
180240230Sdonn register expptr lp, rp;
180340230Sdonn {
180440230Sdonn register expptr e, e1;
180540230Sdonn int etype;
180640230Sdonn int ltype, rtype;
180740230Sdonn int ltag, rtag;
180840230Sdonn expptr q, q1;
180940230Sdonn expptr fold();
181040230Sdonn int k;
181140230Sdonn 
181240230Sdonn ltype = lp->headblock.vtype;
181340230Sdonn ltag = lp->tag;
181440230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL)
181540230Sdonn 	{
181640230Sdonn 	rtype = rp->headblock.vtype;
181740230Sdonn 	rtag = rp->tag;
181840230Sdonn 	}
181940230Sdonn else	{
182040230Sdonn 	rtype = 0;
182140230Sdonn 	rtag = 0;
182240230Sdonn 	}
182340230Sdonn 
182440230Sdonn /*
182540230Sdonn  * Yuck.  Why can't we fold constants AFTER
182640230Sdonn  * variables are implicitly declared???
182740230Sdonn  */
182840230Sdonn if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
182940230Sdonn 	{
183040230Sdonn 	k = letter(lp->primblock.namep->varname[0]);
183140230Sdonn 	ltype = impltype[ k ];
183240230Sdonn 	}
183340230Sdonn if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
183440230Sdonn 	{
183540230Sdonn 	k = letter(rp->primblock.namep->varname[0]);
183640230Sdonn 	rtype = impltype[ k ];
183740230Sdonn 	}
183840230Sdonn 
183940230Sdonn etype = cktype(opcode, ltype, rtype);
184040230Sdonn if(etype == TYERROR)
184140230Sdonn 	goto error;
184240230Sdonn 
184340230Sdonn if(etype != TYUNKNOWN)
184440230Sdonn switch(opcode)
184540230Sdonn 	{
184640230Sdonn 	/* check for multiplication by 0 and 1 and addition to 0 */
184740230Sdonn 
184840230Sdonn 	case OPSTAR:
184940230Sdonn 		if( ISCONST(lp) )
185040230Sdonn 			COMMUTE
185140230Sdonn 
185240230Sdonn 		if( ISICON(rp) )
185340230Sdonn 			{
185440230Sdonn 			if(rp->constblock.const.ci == 0)
185540230Sdonn 				{
185640230Sdonn 				if(etype == TYUNKNOWN)
185740230Sdonn 					break;
185840230Sdonn 				rp = mkconv(etype, rp);
185940230Sdonn 				goto retright;
186040230Sdonn 				}
186140230Sdonn 			if ((lp->tag == TEXPR) &&
186240230Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
186340230Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
186440230Sdonn 			    ISCONST(lp->exprblock.rightp) &&
186540230Sdonn 			    ISINT(lp->exprblock.rightp->constblock.vtype))
186640230Sdonn 				{
186740230Sdonn 				q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
186840230Sdonn 					   cpexpr(rp));
186940230Sdonn 				q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
187040230Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
187140230Sdonn 				free ((char *) lp);
187240230Sdonn 				return q;
187340230Sdonn 				}
187440230Sdonn 			else
187540230Sdonn 				goto mulop;
187640230Sdonn 			}
187740230Sdonn 		break;
187840230Sdonn 
187940230Sdonn 	case OPSLASH:
188040230Sdonn 	case OPMOD:
188140230Sdonn 		if( ICONEQ(rp, 0) )
188240230Sdonn 			{
188340230Sdonn 			err("attempted division by zero");
188440230Sdonn 			rp = ICON(1);
188540230Sdonn 			break;
188640230Sdonn 			}
188740230Sdonn 		if(opcode == OPMOD)
188840230Sdonn 			break;
188940230Sdonn 
189040230Sdonn 
189140230Sdonn 	mulop:
189240230Sdonn 		if( ISICON(rp) )
189340230Sdonn 			{
189440230Sdonn 			if(rp->constblock.const.ci == 1)
189540230Sdonn 				goto retleft;
189640230Sdonn 
189740230Sdonn 			if(rp->constblock.const.ci == -1)
189840230Sdonn 				{
189940230Sdonn 				frexpr(rp);
190040230Sdonn 				return( mkexpr(OPNEG, lp, PNULL) );
190140230Sdonn 				}
190240230Sdonn 			}
190340230Sdonn 
190440230Sdonn 		if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
190540230Sdonn 			{
190640230Sdonn 			if(opcode == OPSTAR)
190740230Sdonn 				e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
190840230Sdonn 			else  if(ISICON(rp) &&
190940230Sdonn 				(lp->exprblock.rightp->constblock.const.ci %
191040230Sdonn 					rp->constblock.const.ci) == 0)
191140230Sdonn 				e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
191240230Sdonn 			else	break;
191340230Sdonn 
191440230Sdonn 			e1 = lp->exprblock.leftp;
191540230Sdonn 			free( (charptr) lp );
191640230Sdonn 			return( mkexpr(OPSTAR, e1, e) );
191740230Sdonn 			}
191840230Sdonn 		break;
191940230Sdonn 
192040230Sdonn 
192140230Sdonn 	case OPPLUS:
192240230Sdonn 		if( ISCONST(lp) )
192340230Sdonn 			COMMUTE
192440230Sdonn 		goto addop;
192540230Sdonn 
192640230Sdonn 	case OPMINUS:
192740230Sdonn 		if( ICONEQ(lp, 0) )
192840230Sdonn 			{
192940230Sdonn 			frexpr(lp);
193040230Sdonn 			return( mkexpr(OPNEG, rp, ENULL) );
193140230Sdonn 			}
193240230Sdonn 
193340230Sdonn 		if( ISCONST(rp) )
193440230Sdonn 			{
193540230Sdonn 			opcode = OPPLUS;
193640230Sdonn 			consnegop(rp);
193740230Sdonn 			}
193840230Sdonn 
193940230Sdonn 	addop:
194040230Sdonn 		if( ISICON(rp) )
194140230Sdonn 			{
194240230Sdonn 			if(rp->constblock.const.ci == 0)
194340230Sdonn 				goto retleft;
194440230Sdonn 			if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
194540230Sdonn 				{
194640230Sdonn 				e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
194740230Sdonn 				e1 = lp->exprblock.leftp;
194840230Sdonn 				free( (charptr) lp );
194940230Sdonn 				return( mkexpr(OPPLUS, e1, e) );
195040230Sdonn 				}
195140230Sdonn 			}
195240230Sdonn 		break;
195340230Sdonn 
195440230Sdonn 
195540230Sdonn 	case OPPOWER:
195640230Sdonn 		break;
195740230Sdonn 
195840230Sdonn 	case OPNEG:
195940230Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
196040230Sdonn 			{
196140230Sdonn 			e = lp->exprblock.leftp;
196240230Sdonn 			free( (charptr) lp );
196340230Sdonn 			return(e);
196440230Sdonn 			}
196540230Sdonn 		break;
196640230Sdonn 
196740230Sdonn 	case OPNOT:
196840230Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
196940230Sdonn 			{
197040230Sdonn 			e = lp->exprblock.leftp;
197140230Sdonn 			free( (charptr) lp );
197240230Sdonn 			return(e);
197340230Sdonn 			}
197440230Sdonn 		break;
197540230Sdonn 
197640230Sdonn 	case OPCALL:
197740230Sdonn 	case OPCCALL:
197840230Sdonn 		etype = ltype;
197940230Sdonn 		if(rp!=NULL && rp->listblock.listp==NULL)
198040230Sdonn 			{
198140230Sdonn 			free( (charptr) rp );
198240230Sdonn 			rp = NULL;
198340230Sdonn 			}
198440230Sdonn 		break;
198540230Sdonn 
198640230Sdonn 	case OPAND:
198740230Sdonn 	case OPOR:
198840230Sdonn 		if( ISCONST(lp) )
198940230Sdonn 			COMMUTE
199040230Sdonn 
199140230Sdonn 		if( ISCONST(rp) )
199240230Sdonn 			{
199340230Sdonn 			if(rp->constblock.const.ci == 0)
199440230Sdonn 				if(opcode == OPOR)
199540230Sdonn 					goto retleft;
199640230Sdonn 				else
199740230Sdonn 					goto retright;
199840230Sdonn 			else if(opcode == OPOR)
199940230Sdonn 				goto retright;
200040230Sdonn 			else
200140230Sdonn 				goto retleft;
200240230Sdonn 			}
200340230Sdonn 	case OPLSHIFT:
200440230Sdonn 		if (ISICON(rp))
200540230Sdonn 			{
200640230Sdonn 			if (rp->constblock.const.ci == 0)
200740230Sdonn 				goto retleft;
200840230Sdonn 			if ((lp->tag == TEXPR) &&
200940230Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
201040230Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
201140230Sdonn 			    ISICON(lp->exprblock.rightp))
201240230Sdonn 				{
201340230Sdonn 				q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
201440230Sdonn 					cpexpr(rp));
201540230Sdonn 				q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
201640230Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
201740230Sdonn 				free((char *) lp);
201840230Sdonn 				return q;
201940230Sdonn 				}
202040230Sdonn 			}
202140230Sdonn 
202240230Sdonn 	case OPEQV:
202340230Sdonn 	case OPNEQV:
202440230Sdonn 
202540230Sdonn 	case OPBITAND:
202640230Sdonn 	case OPBITOR:
202740230Sdonn 	case OPBITXOR:
202840230Sdonn 	case OPBITNOT:
202940230Sdonn 	case OPRSHIFT:
203040230Sdonn 
203140230Sdonn 	case OPLT:
203240230Sdonn 	case OPGT:
203340230Sdonn 	case OPLE:
203440230Sdonn 	case OPGE:
203540230Sdonn 	case OPEQ:
203640230Sdonn 	case OPNE:
203740230Sdonn 
203840230Sdonn 	case OPCONCAT:
203940230Sdonn 		break;
204040230Sdonn 	case OPMIN:
204140230Sdonn 	case OPMAX:
204240230Sdonn 
204340230Sdonn 	case OPASSIGN:
204440230Sdonn 	case OPPLUSEQ:
204540230Sdonn 	case OPSTAREQ:
204640230Sdonn 
204740230Sdonn 	case OPCONV:
204840230Sdonn 	case OPADDR:
204940230Sdonn 
205040230Sdonn 	case OPCOMMA:
205140230Sdonn 	case OPQUEST:
205240230Sdonn 	case OPCOLON:
205340230Sdonn 
205440230Sdonn 	case OPPAREN:
205540230Sdonn 		break;
205640230Sdonn 
205740230Sdonn 	default:
205840230Sdonn 		badop("mkexpr", opcode);
205940230Sdonn 	}
206040230Sdonn 
206140230Sdonn e = (expptr) ALLOC(Exprblock);
206240230Sdonn e->exprblock.tag = TEXPR;
206340230Sdonn e->exprblock.opcode = opcode;
206440230Sdonn e->exprblock.vtype = etype;
206540230Sdonn e->exprblock.leftp = lp;
206640230Sdonn e->exprblock.rightp = rp;
206740230Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) )
206840230Sdonn 	e = fold(e);
206940230Sdonn return(e);
207040230Sdonn 
207140230Sdonn retleft:
207240230Sdonn 	frexpr(rp);
207340230Sdonn 	return(lp);
207440230Sdonn 
207540230Sdonn retright:
207640230Sdonn 	frexpr(lp);
207740230Sdonn 	return(rp);
207840230Sdonn 
207940230Sdonn error:
208040230Sdonn 	frexpr(lp);
208140230Sdonn 	if(rp && opcode!=OPCALL && opcode!=OPCCALL)
208240230Sdonn 		frexpr(rp);
208340230Sdonn 	return( errnode() );
208440230Sdonn }
208540230Sdonn 
208640230Sdonn #define ERR(s)   { errs = s; goto error; }
208740230Sdonn 
208840230Sdonn cktype(op, lt, rt)
208940230Sdonn register int op, lt, rt;
209040230Sdonn {
209140230Sdonn char *errs;
209240230Sdonn 
209340230Sdonn if(lt==TYERROR || rt==TYERROR)
209440230Sdonn 	goto error1;
209540230Sdonn 
209640230Sdonn if(lt==TYUNKNOWN)
209740230Sdonn 	return(TYUNKNOWN);
209840230Sdonn if(rt==TYUNKNOWN)
209940230Sdonn 	if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
210040230Sdonn 	    op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
210140230Sdonn 		return(TYUNKNOWN);
210240230Sdonn 
210340230Sdonn switch(op)
210440230Sdonn 	{
210540230Sdonn 	case OPPLUS:
210640230Sdonn 	case OPMINUS:
210740230Sdonn 	case OPSTAR:
210840230Sdonn 	case OPSLASH:
210940230Sdonn 	case OPPOWER:
211040230Sdonn 	case OPMOD:
211140230Sdonn 		if( ISNUMERIC(lt) && ISNUMERIC(rt) )
211240230Sdonn 			return( maxtype(lt, rt) );
211340230Sdonn 		ERR("nonarithmetic operand of arithmetic operator")
211440230Sdonn 
211540230Sdonn 	case OPNEG:
211640230Sdonn 		if( ISNUMERIC(lt) )
211740230Sdonn 			return(lt);
211840230Sdonn 		ERR("nonarithmetic operand of negation")
211940230Sdonn 
212040230Sdonn 	case OPNOT:
212140230Sdonn 		if(lt == TYLOGICAL)
212240230Sdonn 			return(TYLOGICAL);
212340230Sdonn 		ERR("NOT of nonlogical")
212440230Sdonn 
212540230Sdonn 	case OPAND:
212640230Sdonn 	case OPOR:
212740230Sdonn 	case OPEQV:
212840230Sdonn 	case OPNEQV:
212940230Sdonn 		if(lt==TYLOGICAL && rt==TYLOGICAL)
213040230Sdonn 			return(TYLOGICAL);
213140230Sdonn 		ERR("nonlogical operand of logical operator")
213240230Sdonn 
213340230Sdonn 	case OPLT:
213440230Sdonn 	case OPGT:
213540230Sdonn 	case OPLE:
213640230Sdonn 	case OPGE:
213740230Sdonn 	case OPEQ:
213840230Sdonn 	case OPNE:
213940230Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
214040230Sdonn 			{
214140230Sdonn 			if(lt != rt)
214240230Sdonn 				ERR("illegal comparison")
214340230Sdonn 			}
214440230Sdonn 
214540230Sdonn 		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
214640230Sdonn 			{
214740230Sdonn 			if(op!=OPEQ && op!=OPNE)
214840230Sdonn 				ERR("order comparison of complex data")
214940230Sdonn 			}
215040230Sdonn 
215140230Sdonn 		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
215240230Sdonn 			ERR("comparison of nonarithmetic data")
215340230Sdonn 		return(TYLOGICAL);
215440230Sdonn 
215540230Sdonn 	case OPCONCAT:
215640230Sdonn 		if(lt==TYCHAR && rt==TYCHAR)
215740230Sdonn 			return(TYCHAR);
215840230Sdonn 		ERR("concatenation of nonchar data")
215940230Sdonn 
216040230Sdonn 	case OPCALL:
216140230Sdonn 	case OPCCALL:
216240230Sdonn 		return(lt);
216340230Sdonn 
216440230Sdonn 	case OPADDR:
216540230Sdonn 		return(TYADDR);
216640230Sdonn 
216740230Sdonn 	case OPCONV:
216840230Sdonn 		if(ISCOMPLEX(lt))
216940230Sdonn 			{
217040230Sdonn 			if(ISNUMERIC(rt))
217140230Sdonn 				return(lt);
217240230Sdonn 			ERR("impossible conversion")
217340230Sdonn 			}
217440230Sdonn 		if(rt == 0)
217540230Sdonn 			return(0);
217640230Sdonn 		if(lt==TYCHAR && ISINT(rt) )
217740230Sdonn 			return(TYCHAR);
217840230Sdonn 	case OPASSIGN:
217940230Sdonn 	case OPPLUSEQ:
218040230Sdonn 	case OPSTAREQ:
218140230Sdonn 		if( ISINT(lt) && rt==TYCHAR)
218240230Sdonn 			return(lt);
218340230Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
218440230Sdonn 			if(op!=OPASSIGN || lt!=rt)
218540230Sdonn 				{
218640230Sdonn /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
218740230Sdonn /* debug fatal("impossible conversion.  possible compiler bug"); */
218840230Sdonn 				ERR("impossible conversion")
218940230Sdonn 				}
219040230Sdonn 		return(lt);
219140230Sdonn 
219240230Sdonn 	case OPMIN:
219340230Sdonn 	case OPMAX:
219440230Sdonn 	case OPBITOR:
219540230Sdonn 	case OPBITAND:
219640230Sdonn 	case OPBITXOR:
219740230Sdonn 	case OPBITNOT:
219840230Sdonn 	case OPLSHIFT:
219940230Sdonn 	case OPRSHIFT:
220040230Sdonn 	case OPPAREN:
220140230Sdonn 		return(lt);
220240230Sdonn 
220340230Sdonn 	case OPCOMMA:
220440230Sdonn 	case OPQUEST:
220540230Sdonn 	case OPCOLON:
220640230Sdonn 		return(rt);
220740230Sdonn 
220840230Sdonn 	default:
220940230Sdonn 		badop("cktype", op);
221040230Sdonn 	}
221140230Sdonn error:	err(errs);
221240230Sdonn error1:	return(TYERROR);
221340230Sdonn }
221440230Sdonn 
221540230Sdonn LOCAL expptr fold(e)
221640230Sdonn register expptr e;
221740230Sdonn {
221840230Sdonn Constp p;
221940230Sdonn register expptr lp, rp;
222040230Sdonn int etype, mtype, ltype, rtype, opcode;
222140230Sdonn int i, ll, lr;
222240230Sdonn char *q, *s;
222340230Sdonn union Constant lcon, rcon;
222440230Sdonn 
222540230Sdonn opcode = e->exprblock.opcode;
222640230Sdonn etype = e->exprblock.vtype;
222740230Sdonn 
222840230Sdonn lp = e->exprblock.leftp;
222940230Sdonn ltype = lp->headblock.vtype;
223040230Sdonn rp = e->exprblock.rightp;
223140230Sdonn 
223240230Sdonn if(rp == 0)
223340230Sdonn 	switch(opcode)
223440230Sdonn 		{
223540230Sdonn 		case OPNOT:
223640230Sdonn 			lp->constblock.const.ci = ! lp->constblock.const.ci;
223740230Sdonn 			return(lp);
223840230Sdonn 
223940230Sdonn 		case OPBITNOT:
224040230Sdonn 			lp->constblock.const.ci = ~ lp->constblock.const.ci;
224140230Sdonn 			return(lp);
224240230Sdonn 
224340230Sdonn 		case OPNEG:
224440230Sdonn 			consnegop(lp);
224540230Sdonn 			return(lp);
224640230Sdonn 
224740230Sdonn 		case OPCONV:
224840230Sdonn 		case OPADDR:
224940230Sdonn 		case OPPAREN:
225040230Sdonn 			return(e);
225140230Sdonn 
225240230Sdonn 		default:
225340230Sdonn 			badop("fold", opcode);
225440230Sdonn 		}
225540230Sdonn 
225640230Sdonn rtype = rp->headblock.vtype;
225740230Sdonn 
225840230Sdonn p = ALLOC(Constblock);
225940230Sdonn p->tag = TCONST;
226040230Sdonn p->vtype = etype;
226140230Sdonn p->vleng = e->exprblock.vleng;
226240230Sdonn 
226340230Sdonn switch(opcode)
226440230Sdonn 	{
226540230Sdonn 	case OPCOMMA:
226640230Sdonn 	case OPQUEST:
226740230Sdonn 	case OPCOLON:
226840230Sdonn 		return(e);
226940230Sdonn 
227040230Sdonn 	case OPAND:
227140230Sdonn 		p->const.ci = lp->constblock.const.ci &&
227240230Sdonn 				rp->constblock.const.ci;
227340230Sdonn 		break;
227440230Sdonn 
227540230Sdonn 	case OPOR:
227640230Sdonn 		p->const.ci = lp->constblock.const.ci ||
227740230Sdonn 				rp->constblock.const.ci;
227840230Sdonn 		break;
227940230Sdonn 
228040230Sdonn 	case OPEQV:
228140230Sdonn 		p->const.ci = lp->constblock.const.ci ==
228240230Sdonn 				rp->constblock.const.ci;
228340230Sdonn 		break;
228440230Sdonn 
228540230Sdonn 	case OPNEQV:
228640230Sdonn 		p->const.ci = lp->constblock.const.ci !=
228740230Sdonn 				rp->constblock.const.ci;
228840230Sdonn 		break;
228940230Sdonn 
229040230Sdonn 	case OPBITAND:
229140230Sdonn 		p->const.ci = lp->constblock.const.ci &
229240230Sdonn 				rp->constblock.const.ci;
229340230Sdonn 		break;
229440230Sdonn 
229540230Sdonn 	case OPBITOR:
229640230Sdonn 		p->const.ci = lp->constblock.const.ci |
229740230Sdonn 				rp->constblock.const.ci;
229840230Sdonn 		break;
229940230Sdonn 
230040230Sdonn 	case OPBITXOR:
230140230Sdonn 		p->const.ci = lp->constblock.const.ci ^
230240230Sdonn 				rp->constblock.const.ci;
230340230Sdonn 		break;
230440230Sdonn 
230540230Sdonn 	case OPLSHIFT:
230640230Sdonn 		p->const.ci = lp->constblock.const.ci <<
230740230Sdonn 				rp->constblock.const.ci;
230840230Sdonn 		break;
230940230Sdonn 
231040230Sdonn 	case OPRSHIFT:
231140230Sdonn 		p->const.ci = lp->constblock.const.ci >>
231240230Sdonn 				rp->constblock.const.ci;
231340230Sdonn 		break;
231440230Sdonn 
231540230Sdonn 	case OPCONCAT:
231640230Sdonn 		ll = lp->constblock.vleng->constblock.const.ci;
231740230Sdonn 		lr = rp->constblock.vleng->constblock.const.ci;
231840230Sdonn 		p->const.ccp = q = (char *) ckalloc(ll+lr);
231940230Sdonn 		p->vleng = ICON(ll+lr);
232040230Sdonn 		s = lp->constblock.const.ccp;
232140230Sdonn 		for(i = 0 ; i < ll ; ++i)
232240230Sdonn 			*q++ = *s++;
232340230Sdonn 		s = rp->constblock.const.ccp;
232440230Sdonn 		for(i = 0; i < lr; ++i)
232540230Sdonn 			*q++ = *s++;
232640230Sdonn 		break;
232740230Sdonn 
232840230Sdonn 
232940230Sdonn 	case OPPOWER:
233040230Sdonn 		if( ! ISINT(rtype) )
233140230Sdonn 			return(e);
233240230Sdonn 		conspower(&(p->const), lp, rp->constblock.const.ci);
233340230Sdonn 		break;
233440230Sdonn 
233540230Sdonn 
233640230Sdonn 	default:
233740230Sdonn 		if(ltype == TYCHAR)
233840230Sdonn 			{
233940230Sdonn 			lcon.ci = cmpstr(lp->constblock.const.ccp,
234040230Sdonn 					rp->constblock.const.ccp,
234140230Sdonn 					lp->constblock.vleng->constblock.const.ci,
234240230Sdonn 					rp->constblock.vleng->constblock.const.ci);
234340230Sdonn 			rcon.ci = 0;
234440230Sdonn 			mtype = tyint;
234540230Sdonn 			}
234640230Sdonn 		else	{
234740230Sdonn 			mtype = maxtype(ltype, rtype);
234840230Sdonn 			consconv(mtype, &lcon, ltype, &(lp->constblock.const) );
234940230Sdonn 			consconv(mtype, &rcon, rtype, &(rp->constblock.const) );
235040230Sdonn 			}
235140230Sdonn 		consbinop(opcode, mtype, &(p->const), &lcon, &rcon);
235240230Sdonn 		break;
235340230Sdonn 	}
235440230Sdonn 
235540230Sdonn frexpr(e);
235640230Sdonn return( (expptr) p );
235740230Sdonn }
235840230Sdonn 
235940230Sdonn 
236040230Sdonn 
236140230Sdonn /* assign constant l = r , doing coercion */
236240230Sdonn 
236340230Sdonn consconv(lt, lv, rt, rv)
236440230Sdonn int lt, rt;
236540230Sdonn register union Constant *lv, *rv;
236640230Sdonn {
236740230Sdonn switch(lt)
236840230Sdonn 	{
236940230Sdonn 	case TYCHAR:
237040230Sdonn 		*(lv->ccp = (char *) ckalloc(1)) = rv->ci;
237140230Sdonn 		break;
237240230Sdonn 
237340230Sdonn 	case TYSHORT:
237440230Sdonn 	case TYLONG:
237540230Sdonn 		if(rt == TYCHAR)
237640230Sdonn 			lv->ci = rv->ccp[0];
237740230Sdonn 		else if( ISINT(rt) )
237840230Sdonn 			lv->ci = rv->ci;
237940230Sdonn 		else	lv->ci = rv->cd[0];
238040230Sdonn 		break;
238140230Sdonn 
238240230Sdonn 	case TYCOMPLEX:
238340230Sdonn 	case TYDCOMPLEX:
238440230Sdonn 		switch(rt)
238540230Sdonn 			{
238640230Sdonn 			case TYSHORT:
238740230Sdonn 			case TYLONG:
238840230Sdonn 				/* fall through and do real assignment of
238940230Sdonn 				   first element
239040230Sdonn 				*/
239140230Sdonn 			case TYREAL:
239240230Sdonn 			case TYDREAL:
239340230Sdonn 				lv->cd[1] = 0; break;
239440230Sdonn 			case TYCOMPLEX:
239540230Sdonn 			case TYDCOMPLEX:
239640230Sdonn 				lv->cd[1] = rv->cd[1]; break;
239740230Sdonn 			}
239840230Sdonn 
239940230Sdonn 	case TYREAL:
240040230Sdonn 	case TYDREAL:
240140230Sdonn 		if( ISINT(rt) )
240240230Sdonn 			lv->cd[0] = rv->ci;
240340230Sdonn 		else	lv->cd[0] = rv->cd[0];
240440230Sdonn 		if( lt == TYREAL)
240540230Sdonn 			{
240640230Sdonn 			float f = lv->cd[0];
240740230Sdonn 			lv->cd[0] = f;
240840230Sdonn 			}
240940230Sdonn 		break;
241040230Sdonn 
241140230Sdonn 	case TYLOGICAL:
241240230Sdonn 		lv->ci = rv->ci;
241340230Sdonn 		break;
241440230Sdonn 	}
241540230Sdonn }
241640230Sdonn 
241740230Sdonn 
241840230Sdonn 
241940230Sdonn consnegop(p)
242040230Sdonn register Constp p;
242140230Sdonn {
242240230Sdonn switch(p->vtype)
242340230Sdonn 	{
242440230Sdonn 	case TYSHORT:
242540230Sdonn 	case TYLONG:
242640230Sdonn 		p->const.ci = - p->const.ci;
242740230Sdonn 		break;
242840230Sdonn 
242940230Sdonn 	case TYCOMPLEX:
243040230Sdonn 	case TYDCOMPLEX:
243140230Sdonn 		p->const.cd[1] = - p->const.cd[1];
243240230Sdonn 		/* fall through and do the real parts */
243340230Sdonn 	case TYREAL:
243440230Sdonn 	case TYDREAL:
243540230Sdonn 		p->const.cd[0] = - p->const.cd[0];
243640230Sdonn 		break;
243740230Sdonn 	default:
243840230Sdonn 		badtype("consnegop", p->vtype);
243940230Sdonn 	}
244040230Sdonn }
244140230Sdonn 
244240230Sdonn 
244340230Sdonn 
244440230Sdonn LOCAL conspower(powp, ap, n)
244540230Sdonn register union Constant *powp;
244640230Sdonn Constp ap;
244740230Sdonn ftnint n;
244840230Sdonn {
244940230Sdonn register int type;
245040230Sdonn union Constant x;
245140230Sdonn 
245240230Sdonn switch(type = ap->vtype)	/* pow = 1 */
245340230Sdonn 	{
245440230Sdonn 	case TYSHORT:
245540230Sdonn 	case TYLONG:
245640230Sdonn 		powp->ci = 1;
245740230Sdonn 		break;
245840230Sdonn 	case TYCOMPLEX:
245940230Sdonn 	case TYDCOMPLEX:
246040230Sdonn 		powp->cd[1] = 0;
246140230Sdonn 	case TYREAL:
246240230Sdonn 	case TYDREAL:
246340230Sdonn 		powp->cd[0] = 1;
246440230Sdonn 		break;
246540230Sdonn 	default:
246640230Sdonn 		badtype("conspower", type);
246740230Sdonn 	}
246840230Sdonn 
246940230Sdonn if(n == 0)
247040230Sdonn 	return;
247140230Sdonn if(n < 0)
247240230Sdonn 	{
247340230Sdonn 	if( ISINT(type) )
247440230Sdonn 		{
247540230Sdonn 		if (ap->const.ci == 0)
247640230Sdonn 			err("zero raised to a negative power");
247740230Sdonn 		else if (ap->const.ci == 1)
247840230Sdonn 			return;
247940230Sdonn 		else if (ap->const.ci == -1)
248040230Sdonn 			{
248140230Sdonn 			if (n < -2)
248240230Sdonn 				n = n + 2;
248340230Sdonn 			n = -n;
248440230Sdonn 			if (n % 2 == 1)
248540230Sdonn 				powp->ci = -1;
248640230Sdonn 			}
248740230Sdonn 		else
248840230Sdonn 			powp->ci = 0;
248940230Sdonn 		return;
249040230Sdonn 		}
249140230Sdonn 	n = - n;
249240230Sdonn 	consbinop(OPSLASH, type, &x, powp, &(ap->const));
249340230Sdonn 	}
249440230Sdonn else
249540230Sdonn 	consbinop(OPSTAR, type, &x, powp, &(ap->const));
249640230Sdonn 
249740230Sdonn for( ; ; )
249840230Sdonn 	{
249940230Sdonn 	if(n & 01)
250040230Sdonn 		consbinop(OPSTAR, type, powp, powp, &x);
250140230Sdonn 	if(n >>= 1)
250240230Sdonn 		consbinop(OPSTAR, type, &x, &x, &x);
250340230Sdonn 	else
250440230Sdonn 		break;
250540230Sdonn 	}
250640230Sdonn }
250740230Sdonn 
250840230Sdonn 
250940230Sdonn 
251040230Sdonn /* do constant operation cp = a op b */
251140230Sdonn 
251240230Sdonn 
251340230Sdonn LOCAL consbinop(opcode, type, cp, ap, bp)
251440230Sdonn int opcode, type;
251540230Sdonn register union Constant *ap, *bp, *cp;
251640230Sdonn {
251740230Sdonn int k;
251840230Sdonn double temp;
251940230Sdonn 
252040230Sdonn switch(opcode)
252140230Sdonn 	{
252240230Sdonn 	case OPPLUS:
252340230Sdonn 		switch(type)
252440230Sdonn 			{
252540230Sdonn 			case TYSHORT:
252640230Sdonn 			case TYLONG:
252740230Sdonn 				cp->ci = ap->ci + bp->ci;
252840230Sdonn 				break;
252940230Sdonn 			case TYCOMPLEX:
253040230Sdonn 			case TYDCOMPLEX:
253140230Sdonn 				cp->cd[1] = ap->cd[1] + bp->cd[1];
253240230Sdonn 			case TYREAL:
253340230Sdonn 			case TYDREAL:
253440230Sdonn 				cp->cd[0] = ap->cd[0] + bp->cd[0];
253540230Sdonn 				break;
253640230Sdonn 			}
253740230Sdonn 		break;
253840230Sdonn 
253940230Sdonn 	case OPMINUS:
254040230Sdonn 		switch(type)
254140230Sdonn 			{
254240230Sdonn 			case TYSHORT:
254340230Sdonn 			case TYLONG:
254440230Sdonn 				cp->ci = ap->ci - bp->ci;
254540230Sdonn 				break;
254640230Sdonn 			case TYCOMPLEX:
254740230Sdonn 			case TYDCOMPLEX:
254840230Sdonn 				cp->cd[1] = ap->cd[1] - bp->cd[1];
254940230Sdonn 			case TYREAL:
255040230Sdonn 			case TYDREAL:
255140230Sdonn 				cp->cd[0] = ap->cd[0] - bp->cd[0];
255240230Sdonn 				break;
255340230Sdonn 			}
255440230Sdonn 		break;
255540230Sdonn 
255640230Sdonn 	case OPSTAR:
255740230Sdonn 		switch(type)
255840230Sdonn 			{
255940230Sdonn 			case TYSHORT:
256040230Sdonn 			case TYLONG:
256140230Sdonn 				cp->ci = ap->ci * bp->ci;
256240230Sdonn 				break;
256340230Sdonn 			case TYREAL:
256440230Sdonn 			case TYDREAL:
256540230Sdonn 				cp->cd[0] = ap->cd[0] * bp->cd[0];
256640230Sdonn 				break;
256740230Sdonn 			case TYCOMPLEX:
256840230Sdonn 			case TYDCOMPLEX:
256940230Sdonn 				temp = ap->cd[0] * bp->cd[0] -
257040230Sdonn 					    ap->cd[1] * bp->cd[1] ;
257140230Sdonn 				cp->cd[1] = ap->cd[0] * bp->cd[1] +
257240230Sdonn 					    ap->cd[1] * bp->cd[0] ;
257340230Sdonn 				cp->cd[0] = temp;
257440230Sdonn 				break;
257540230Sdonn 			}
257640230Sdonn 		break;
257740230Sdonn 	case OPSLASH:
257840230Sdonn 		switch(type)
257940230Sdonn 			{
258040230Sdonn 			case TYSHORT:
258140230Sdonn 			case TYLONG:
258240230Sdonn 				cp->ci = ap->ci / bp->ci;
258340230Sdonn 				break;
258440230Sdonn 			case TYREAL:
258540230Sdonn 			case TYDREAL:
258640230Sdonn 				cp->cd[0] = ap->cd[0] / bp->cd[0];
258740230Sdonn 				break;
258840230Sdonn 			case TYCOMPLEX:
258940230Sdonn 			case TYDCOMPLEX:
259040230Sdonn 				zdiv(cp,ap,bp);
259140230Sdonn 				break;
259240230Sdonn 			}
259340230Sdonn 		break;
259440230Sdonn 
259540230Sdonn 	case OPMOD:
259640230Sdonn 		if( ISINT(type) )
259740230Sdonn 			{
259840230Sdonn 			cp->ci = ap->ci % bp->ci;
259940230Sdonn 			break;
260040230Sdonn 			}
260140230Sdonn 		else
260240230Sdonn 			fatal("inline mod of noninteger");
260340230Sdonn 
260440230Sdonn 	default:	  /* relational ops */
260540230Sdonn 		switch(type)
260640230Sdonn 			{
260740230Sdonn 			case TYSHORT:
260840230Sdonn 			case TYLONG:
260940230Sdonn 				if(ap->ci < bp->ci)
261040230Sdonn 					k = -1;
261140230Sdonn 				else if(ap->ci == bp->ci)
261240230Sdonn 					k = 0;
261340230Sdonn 				else	k = 1;
261440230Sdonn 				break;
261540230Sdonn 			case TYREAL:
261640230Sdonn 			case TYDREAL:
261740230Sdonn 				if(ap->cd[0] < bp->cd[0])
261840230Sdonn 					k = -1;
261940230Sdonn 				else if(ap->cd[0] == bp->cd[0])
262040230Sdonn 					k = 0;
262140230Sdonn 				else	k = 1;
262240230Sdonn 				break;
262340230Sdonn 			case TYCOMPLEX:
262440230Sdonn 			case TYDCOMPLEX:
262540230Sdonn 				if(ap->cd[0] == bp->cd[0] &&
262640230Sdonn 				   ap->cd[1] == bp->cd[1] )
262740230Sdonn 					k = 0;
262840230Sdonn 				else	k = 1;
262940230Sdonn 				break;
263040230Sdonn 			}
263140230Sdonn 
263240230Sdonn 		switch(opcode)
263340230Sdonn 			{
263440230Sdonn 			case OPEQ:
263540230Sdonn 				cp->ci = (k == 0);
263640230Sdonn 				break;
263740230Sdonn 			case OPNE:
263840230Sdonn 				cp->ci = (k != 0);
263940230Sdonn 				break;
264040230Sdonn 			case OPGT:
264140230Sdonn 				cp->ci = (k == 1);
264240230Sdonn 				break;
264340230Sdonn 			case OPLT:
264440230Sdonn 				cp->ci = (k == -1);
264540230Sdonn 				break;
264640230Sdonn 			case OPGE:
264740230Sdonn 				cp->ci = (k >= 0);
264840230Sdonn 				break;
264940230Sdonn 			case OPLE:
265040230Sdonn 				cp->ci = (k <= 0);
265140230Sdonn 				break;
265240230Sdonn 			default:
265340230Sdonn 				badop ("consbinop", opcode);
265440230Sdonn 			}
265540230Sdonn 		break;
265640230Sdonn 	}
265740230Sdonn }
265840230Sdonn 
265940230Sdonn 
266040230Sdonn 
266140230Sdonn 
266240230Sdonn conssgn(p)
266340230Sdonn register expptr p;
266440230Sdonn {
266540230Sdonn if( ! ISCONST(p) )
266640230Sdonn 	fatal( "sgn(nonconstant)" );
266740230Sdonn 
266840230Sdonn switch(p->headblock.vtype)
266940230Sdonn 	{
267040230Sdonn 	case TYSHORT:
267140230Sdonn 	case TYLONG:
267240230Sdonn 		if(p->constblock.const.ci > 0) return(1);
267340230Sdonn 		if(p->constblock.const.ci < 0) return(-1);
267440230Sdonn 		return(0);
267540230Sdonn 
267640230Sdonn 	case TYREAL:
267740230Sdonn 	case TYDREAL:
267840230Sdonn 		if(p->constblock.const.cd[0] > 0) return(1);
267940230Sdonn 		if(p->constblock.const.cd[0] < 0) return(-1);
268040230Sdonn 		return(0);
268140230Sdonn 
268240230Sdonn 	case TYCOMPLEX:
268340230Sdonn 	case TYDCOMPLEX:
268440230Sdonn 		return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0);
268540230Sdonn 
268640230Sdonn 	default:
268740230Sdonn 		badtype( "conssgn", p->constblock.vtype);
268840230Sdonn 	}
268940230Sdonn /* NOTREACHED */
269040230Sdonn }
269140230Sdonn 
269240230Sdonn char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
269340230Sdonn 
269440230Sdonn 
269540230Sdonn LOCAL expptr mkpower(p)
269640230Sdonn register expptr p;
269740230Sdonn {
269840230Sdonn register expptr q, lp, rp;
269940230Sdonn int ltype, rtype, mtype;
270040230Sdonn 
270140230Sdonn lp = p->exprblock.leftp;
270240230Sdonn rp = p->exprblock.rightp;
270340230Sdonn ltype = lp->headblock.vtype;
270440230Sdonn rtype = rp->headblock.vtype;
270540230Sdonn 
270640230Sdonn if(ISICON(rp))
270740230Sdonn 	{
270840230Sdonn 	if(rp->constblock.const.ci == 0)
270940230Sdonn 		{
271040230Sdonn 		frexpr(p);
271140230Sdonn 		if( ISINT(ltype) )
271240230Sdonn 			return( ICON(1) );
271340230Sdonn 		else
271440230Sdonn 			{
271540230Sdonn 			expptr pp;
271640230Sdonn 			pp = mkconv(ltype, ICON(1));
271740230Sdonn 			return( pp );
271840230Sdonn 			}
271940230Sdonn 		}
272040230Sdonn 	if(rp->constblock.const.ci < 0)
272140230Sdonn 		{
272240230Sdonn 		if( ISINT(ltype) )
272340230Sdonn 			{
272440230Sdonn 			frexpr(p);
272540230Sdonn 			err("integer**negative");
272640230Sdonn 			return( errnode() );
272740230Sdonn 			}
272840230Sdonn 		rp->constblock.const.ci = - rp->constblock.const.ci;
272940230Sdonn 		p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
273040230Sdonn 		}
273140230Sdonn 	if(rp->constblock.const.ci == 1)
273240230Sdonn 		{
273340230Sdonn 		frexpr(rp);
273440230Sdonn 		free( (charptr) p );
273540230Sdonn 		return(lp);
273640230Sdonn 		}
273740230Sdonn 
273840230Sdonn 	if( ONEOF(ltype, MSKINT|MSKREAL) )
273940230Sdonn 		{
274040230Sdonn 		p->exprblock.vtype = ltype;
274140230Sdonn 		return(p);
274240230Sdonn 		}
274340230Sdonn 	}
274440230Sdonn if( ISINT(rtype) )
274540230Sdonn 	{
274640230Sdonn 	if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
274740230Sdonn 		q = call2(TYSHORT, "pow_hh", lp, rp);
274840230Sdonn 	else	{
274940230Sdonn 		if(ltype == TYSHORT)
275040230Sdonn 			{
275140230Sdonn 			ltype = TYLONG;
275240230Sdonn 			lp = mkconv(TYLONG,lp);
275340230Sdonn 			}
275440230Sdonn 		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
275540230Sdonn 		}
275640230Sdonn 	}
275740230Sdonn else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
275840230Sdonn 	q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
275940230Sdonn else	{
276040230Sdonn 	q  = call2(TYDCOMPLEX, "pow_zz",
276140230Sdonn 		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
276240230Sdonn 	if(mtype == TYCOMPLEX)
276340230Sdonn 		q = mkconv(TYCOMPLEX, q);
276440230Sdonn 	}
276540230Sdonn free( (charptr) p );
276640230Sdonn return(q);
276740230Sdonn }
276840230Sdonn 
276940230Sdonn 
277040230Sdonn 
277140230Sdonn /* Complex Division.  Same code as in Runtime Library
277240230Sdonn */
277340230Sdonn 
277440230Sdonn struct dcomplex { double dreal, dimag; };
277540230Sdonn 
277640230Sdonn 
277740230Sdonn LOCAL zdiv(c, a, b)
277840230Sdonn register struct dcomplex *a, *b, *c;
277940230Sdonn {
278040230Sdonn double ratio, den;
278140230Sdonn double abr, abi;
278240230Sdonn 
278340230Sdonn if( (abr = b->dreal) < 0.)
278440230Sdonn 	abr = - abr;
278540230Sdonn if( (abi = b->dimag) < 0.)
278640230Sdonn 	abi = - abi;
278740230Sdonn if( abr <= abi )
278840230Sdonn 	{
278940230Sdonn 	if(abi == 0)
279040230Sdonn 		fatal("complex division by zero");
279140230Sdonn 	ratio = b->dreal / b->dimag ;
279240230Sdonn 	den = b->dimag * (1 + ratio*ratio);
279340230Sdonn 	c->dreal = (a->dreal*ratio + a->dimag) / den;
279440230Sdonn 	c->dimag = (a->dimag*ratio - a->dreal) / den;
279540230Sdonn 	}
279640230Sdonn 
279740230Sdonn else
279840230Sdonn 	{
279940230Sdonn 	ratio = b->dimag / b->dreal ;
280040230Sdonn 	den = b->dreal * (1 + ratio*ratio);
280140230Sdonn 	c->dreal = (a->dreal + a->dimag*ratio) / den;
280240230Sdonn 	c->dimag = (a->dimag - a->dreal*ratio) / den;
280340230Sdonn 	}
280440230Sdonn 
280540230Sdonn }
280640230Sdonn 
280740230Sdonn expptr oftwo(e)
280840230Sdonn expptr e;
280940230Sdonn {
281040230Sdonn 	int val,res;
281140230Sdonn 
281240230Sdonn 	if (! ISCONST (e))
281340230Sdonn 		return (0);
281440230Sdonn 
281540230Sdonn 	val = e->constblock.const.ci;
281640230Sdonn 	switch (val)
281740230Sdonn 		{
281840230Sdonn 		case 2:		res = 1; break;
281940230Sdonn 		case 4:		res = 2; break;
282040230Sdonn 		case 8:		res = 3; break;
282140230Sdonn 		case 16:	res = 4; break;
282240230Sdonn 		case 32:	res = 5; break;
282340230Sdonn 		case 64:	res = 6; break;
282440230Sdonn 		case 128:	res = 7; break;
282540230Sdonn 		case 256:	res = 8; break;
282640230Sdonn 		default:	return (0);
282740230Sdonn 		}
282840230Sdonn 	return (ICON (res));
282940230Sdonn }
2830