xref: /csrg-svn/usr.bin/f77/pass1.vax/expr.c (revision 24477)
122812Smckusick /*
222812Smckusick  * Copyright (c) 1980 Regents of the University of California.
322812Smckusick  * All rights reserved.  The Berkeley software License Agreement
422812Smckusick  * specifies the terms and conditions for redistribution.
522812Smckusick  */
622812Smckusick 
722812Smckusick #ifndef lint
8*24477Sdonn static char *sccsid[] = "@(#)expr.c	5.4 (Berkeley) 08/29/85";
922812Smckusick #endif not lint
1022812Smckusick 
1122812Smckusick /*
1222812Smckusick  * expr.c
1322812Smckusick  *
1422812Smckusick  * Routines for handling expressions, f77 compiler pass 1.
1522812Smckusick  *
1622812Smckusick  * University of Utah CS Dept modification history:
1722812Smckusick  *
1823476Smckusick  * $Log:	expr.c,v $
19*24477Sdonn  * Revision 5.3  85/08/10  05:48:16  donn
20*24477Sdonn  * Fixed another of my goofs in the substring parameter conversion code.
21*24477Sdonn  *
22*24477Sdonn  * Revision 5.2  85/08/10  04:13:51  donn
23*24477Sdonn  * Jerry Berkman's change to call pow() directly rather than indirectly
24*24477Sdonn  * through pow_dd, in mkpower().
25*24477Sdonn  *
26*24477Sdonn  * Revision 5.1  85/08/10  03:44:19  donn
27*24477Sdonn  * 4.3 alpha
28*24477Sdonn  *
2923680Smckusick  * Revision 3.16  85/06/21  16:38:09  donn
3023680Smckusick  * The fix to mkprim() didn't handle null substring parameters (sigh).
3123680Smckusick  *
3223476Smckusick  * Revision 3.15  85/06/04  04:37:03  donn
3323476Smckusick  * Changed mkprim() to force substring parameters to be integral types.
3422812Smckusick  *
3523476Smckusick  * Revision 3.14  85/06/04  03:41:52  donn
3623476Smckusick  * Change impldcl() to handle functions of type 'undefined'.
3723476Smckusick  *
3823476Smckusick  * Revision 3.13  85/05/06  23:14:55  donn
3923476Smckusick  * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
4023476Smckusick  * a temporary when converting character strings to integers; previously we
4123476Smckusick  * were having problems because mkconv() was called after tempalloc().
4223476Smckusick  *
4322812Smckusick  * Revision 3.12  85/03/18  08:07:47  donn
4422812Smckusick  * Fixes to help out with short integers -- if integers are by default short,
4522812Smckusick  * then so are constants; and if addresses can't be stored in shorts, complain.
4622812Smckusick  *
4722812Smckusick  * Revision 3.11  85/03/16  22:31:27  donn
4822812Smckusick  * Added hack to mkconv() to allow character values of length > 1 to be
4922812Smckusick  * converted to numeric types, for Helge Skrivervik.  Note that this does
5022812Smckusick  * not affect use of the intrinsic ichar() conversion.
5122812Smckusick  *
5222812Smckusick  * Revision 3.10  85/01/15  21:06:47  donn
5322812Smckusick  * Changed mkconv() to comment on implicit conversions; added intrconv() for
5422812Smckusick  * use with explicit conversions by intrinsic functions.
5522812Smckusick  *
5622812Smckusick  * Revision 3.9  85/01/11  21:05:49  donn
5722812Smckusick  * Added changes to implement SAVE statements.
5822812Smckusick  *
5922812Smckusick  * Revision 3.8  84/12/17  02:21:06  donn
6022812Smckusick  * Added a test to prevent constant folding from being done on expressions
6122812Smckusick  * whose type is not known at that point in mkexpr().
6222812Smckusick  *
6322812Smckusick  * Revision 3.7  84/12/11  21:14:17  donn
6422812Smckusick  * Removed obnoxious 'excess precision' warning.
6522812Smckusick  *
6622812Smckusick  * Revision 3.6  84/11/23  01:00:36  donn
6722812Smckusick  * Added code to trim excess precision from single-precision constants, and
6822812Smckusick  * to warn the user when this occurs.
6922812Smckusick  *
7022812Smckusick  * Revision 3.5  84/11/23  00:10:39  donn
7122812Smckusick  * Changed stfcall() to remark on argument type clashes in 'calls' to
7222812Smckusick  * statement functions.
7322812Smckusick  *
7422812Smckusick  * Revision 3.4  84/11/22  21:21:17  donn
7522812Smckusick  * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
7622812Smckusick  *
7722812Smckusick  * Revision 3.3  84/11/12  18:26:14  donn
7822812Smckusick  * Shuffled some code around so that the compiler remembers to free some vleng
7922812Smckusick  * structures which used to just sit around.
8022812Smckusick  *
8122812Smckusick  * Revision 3.2  84/10/16  19:24:15  donn
8222812Smckusick  * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
8322812Smckusick  * core dumps by replacing bad subscripts with good ones.
8422812Smckusick  *
8522812Smckusick  * Revision 3.1  84/10/13  01:31:32  donn
8622812Smckusick  * Merged Jerry Berkman's version into mine.
8722812Smckusick  *
8822812Smckusick  * Revision 2.7  84/09/27  15:42:52  donn
8922812Smckusick  * The last fix for multiplying undeclared variables by 0 isn't sufficient,
9022812Smckusick  * since the type of the 0 may not be the (implicit) type of the variable.
9122812Smckusick  * I added a hack to check the implicit type of implicitly declared
9222812Smckusick  * variables...
9322812Smckusick  *
9422812Smckusick  * Revision 2.6  84/09/14  19:34:03  donn
9522812Smckusick  * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
9622812Smckusick  * 0 to type UNKNOWN, which is illegal.  Fix is to use native type instead.
9722812Smckusick  * Not sure how correct (or important) this is...
9822812Smckusick  *
9922812Smckusick  * Revision 2.5  84/08/05  23:05:27  donn
10022812Smckusick  * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
10122812Smckusick  * with two operands.
10222812Smckusick  *
10322812Smckusick  * Revision 2.4  84/08/05  17:34:48  donn
10422812Smckusick  * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
10522812Smckusick  * and assign constant length 1 to them.
10622812Smckusick  *
10722812Smckusick  * Revision 2.3  84/07/19  19:38:33  donn
10822812Smckusick  * Added a typecast to the last fix.  Somehow I missed it the first time...
10922812Smckusick  *
11022812Smckusick  * Revision 2.2  84/07/19  17:19:57  donn
11122812Smckusick  * Caused OPPAREN expressions to inherit the length of their operands, so
11222812Smckusick  * that parenthesized character expressions work correctly.
11322812Smckusick  *
11422812Smckusick  * Revision 2.1  84/07/19  12:03:02  donn
11522812Smckusick  * Changed comment headers for UofU.
11622812Smckusick  *
11722812Smckusick  * Revision 1.2  84/04/06  20:12:17  donn
11822812Smckusick  * Fixed bug which caused programs with mixed-type multiplications involving
11922812Smckusick  * the constant 0 to choke the compiler.
12022812Smckusick  *
12122812Smckusick  */
12222812Smckusick 
12322812Smckusick #include "defs.h"
12422812Smckusick 
12522812Smckusick 
12622812Smckusick /* little routines to create constant blocks */
12722812Smckusick 
12822812Smckusick Constp mkconst(t)
12922812Smckusick register int t;
13022812Smckusick {
13122812Smckusick register Constp p;
13222812Smckusick 
13322812Smckusick p = ALLOC(Constblock);
13422812Smckusick p->tag = TCONST;
13522812Smckusick p->vtype = t;
13622812Smckusick return(p);
13722812Smckusick }
13822812Smckusick 
13922812Smckusick 
14022812Smckusick expptr mklogcon(l)
14122812Smckusick register int l;
14222812Smckusick {
14322812Smckusick register Constp  p;
14422812Smckusick 
14522812Smckusick p = mkconst(TYLOGICAL);
14622812Smckusick p->const.ci = l;
14722812Smckusick return( (expptr) p );
14822812Smckusick }
14922812Smckusick 
15022812Smckusick 
15122812Smckusick 
15222812Smckusick expptr mkintcon(l)
15322812Smckusick ftnint l;
15422812Smckusick {
15522812Smckusick register Constp p;
15622812Smckusick int usetype;
15722812Smckusick 
15822812Smckusick if(tyint == TYSHORT)
15922812Smckusick   {
16022812Smckusick     short s = l;
16122812Smckusick     if(l != s)
16222812Smckusick       usetype = TYLONG;
16322812Smckusick     else
16422812Smckusick       usetype = TYSHORT;
16522812Smckusick   }
16622812Smckusick else
16722812Smckusick   usetype = tyint;
16822812Smckusick p = mkconst(usetype);
16922812Smckusick p->const.ci = l;
17022812Smckusick return( (expptr) p );
17122812Smckusick }
17222812Smckusick 
17322812Smckusick 
17422812Smckusick 
17522812Smckusick expptr mkaddcon(l)
17622812Smckusick register int l;
17722812Smckusick {
17822812Smckusick register Constp p;
17922812Smckusick 
18022812Smckusick p = mkconst(TYADDR);
18122812Smckusick p->const.ci = l;
18222812Smckusick return( (expptr) p );
18322812Smckusick }
18422812Smckusick 
18522812Smckusick 
18622812Smckusick 
18722812Smckusick expptr mkrealcon(t, d)
18822812Smckusick register int t;
18922812Smckusick double d;
19022812Smckusick {
19122812Smckusick register Constp p;
19222812Smckusick 
19322812Smckusick if(t == TYREAL)
19422812Smckusick   {
19522812Smckusick     float f = d;
19622812Smckusick     if(f != d)
19722812Smckusick       {
19822812Smckusick #ifdef notdef
19922812Smckusick 	warn("excess precision in real constant lost");
20022812Smckusick #endif notdef
20122812Smckusick 	d = f;
20222812Smckusick       }
20322812Smckusick   }
20422812Smckusick p = mkconst(t);
20522812Smckusick p->const.cd[0] = d;
20622812Smckusick return( (expptr) p );
20722812Smckusick }
20822812Smckusick 
20922812Smckusick 
21022812Smckusick expptr mkbitcon(shift, leng, s)
21122812Smckusick int shift;
21222812Smckusick register int leng;
21322812Smckusick register char *s;
21422812Smckusick {
21522812Smckusick   Constp p;
21622812Smckusick   register int i, j, k;
21722812Smckusick   register char *bp;
21822812Smckusick   int size;
21922812Smckusick 
22022812Smckusick   size = (shift*leng + BYTESIZE -1)/BYTESIZE;
22122812Smckusick   bp = (char *) ckalloc(size);
22222812Smckusick 
22322812Smckusick   i = 0;
22422812Smckusick 
22522812Smckusick #if (TARGET == PDP11 || TARGET == VAX)
22622812Smckusick   j = 0;
22722812Smckusick #else
22822812Smckusick   j = size;
22922812Smckusick #endif
23022812Smckusick 
23122812Smckusick   k = 0;
23222812Smckusick 
23322812Smckusick   while (leng > 0)
23422812Smckusick     {
23522812Smckusick       k |= (hextoi(s[--leng]) << i);
23622812Smckusick       i += shift;
23722812Smckusick       if (i >= BYTESIZE)
23822812Smckusick 	{
23922812Smckusick #if (TARGET == PDP11 || TARGET == VAX)
24022812Smckusick 	  bp[j++] = k & MAXBYTE;
24122812Smckusick #else
24222812Smckusick 	  bp[--j] = k & MAXBYTE;
24322812Smckusick #endif
24422812Smckusick 	  k = k >> BYTESIZE;
24522812Smckusick 	  i -= BYTESIZE;
24622812Smckusick 	}
24722812Smckusick     }
24822812Smckusick 
24922812Smckusick   if (k != 0)
25022812Smckusick #if (TARGET == PDP11 || TARGET == VAX)
25122812Smckusick     bp[j++] = k;
25222812Smckusick #else
25322812Smckusick     bp[--j] = k;
25422812Smckusick #endif
25522812Smckusick 
25622812Smckusick   p = mkconst(TYBITSTR);
25722812Smckusick   p->vleng = ICON(size);
25822812Smckusick   p->const.ccp = bp;
25922812Smckusick 
26022812Smckusick   return ((expptr) p);
26122812Smckusick }
26222812Smckusick 
26322812Smckusick 
26422812Smckusick 
26522812Smckusick expptr mkstrcon(l,v)
26622812Smckusick int l;
26722812Smckusick register char *v;
26822812Smckusick {
26922812Smckusick register Constp p;
27022812Smckusick register char *s;
27122812Smckusick 
27222812Smckusick p = mkconst(TYCHAR);
27322812Smckusick p->vleng = ICON(l);
27422812Smckusick p->const.ccp = s = (char *) ckalloc(l);
27522812Smckusick while(--l >= 0)
27622812Smckusick 	*s++ = *v++;
27722812Smckusick return( (expptr) p );
27822812Smckusick }
27922812Smckusick 
28022812Smckusick 
28122812Smckusick expptr mkcxcon(realp,imagp)
28222812Smckusick register expptr realp, imagp;
28322812Smckusick {
28422812Smckusick int rtype, itype;
28522812Smckusick register Constp p;
28622812Smckusick 
28722812Smckusick rtype = realp->headblock.vtype;
28822812Smckusick itype = imagp->headblock.vtype;
28922812Smckusick 
29022812Smckusick if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
29122812Smckusick 	{
29222812Smckusick 	p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
29322812Smckusick 	if( ISINT(rtype) )
29422812Smckusick 		p->const.cd[0] = realp->constblock.const.ci;
29522812Smckusick 	else	p->const.cd[0] = realp->constblock.const.cd[0];
29622812Smckusick 	if( ISINT(itype) )
29722812Smckusick 		p->const.cd[1] = imagp->constblock.const.ci;
29822812Smckusick 	else	p->const.cd[1] = imagp->constblock.const.cd[0];
29922812Smckusick 	}
30022812Smckusick else
30122812Smckusick 	{
30222812Smckusick 	err("invalid complex constant");
30322812Smckusick 	p = (Constp) errnode();
30422812Smckusick 	}
30522812Smckusick 
30622812Smckusick frexpr(realp);
30722812Smckusick frexpr(imagp);
30822812Smckusick return( (expptr) p );
30922812Smckusick }
31022812Smckusick 
31122812Smckusick 
31222812Smckusick expptr errnode()
31322812Smckusick {
31422812Smckusick struct Errorblock *p;
31522812Smckusick p = ALLOC(Errorblock);
31622812Smckusick p->tag = TERROR;
31722812Smckusick p->vtype = TYERROR;
31822812Smckusick return( (expptr) p );
31922812Smckusick }
32022812Smckusick 
32122812Smckusick 
32222812Smckusick 
32322812Smckusick 
32422812Smckusick 
32522812Smckusick expptr mkconv(t, p)
32622812Smckusick register int t;
32722812Smckusick register expptr p;
32822812Smckusick {
32922812Smckusick register expptr q;
33022812Smckusick Addrp r, s;
33122812Smckusick register int pt;
33222812Smckusick expptr opconv();
33322812Smckusick 
33422812Smckusick if(t==TYUNKNOWN || t==TYERROR)
33522812Smckusick 	badtype("mkconv", t);
33622812Smckusick pt = p->headblock.vtype;
33722812Smckusick if(t == pt)
33822812Smckusick 	return(p);
33922812Smckusick 
34022812Smckusick if( pt == TYCHAR && ISNUMERIC(t) )
34122812Smckusick 	{
34222812Smckusick 	warn("implicit conversion of character to numeric type");
34322812Smckusick 
34422812Smckusick 	/*
34522812Smckusick 	 * Ugly kluge to copy character values into numerics.
34622812Smckusick 	 */
34722812Smckusick 	s = mkaltemp(t, ENULL);
34822812Smckusick 	r = (Addrp) cpexpr(s);
34922812Smckusick 	r->vtype = TYCHAR;
35022812Smckusick 	r->varleng = typesize[t];
35122812Smckusick 	r->vleng = mkintcon(r->varleng);
35222812Smckusick 	q = mkexpr(OPASSIGN, r, p);
35322812Smckusick 	q = mkexpr(OPCOMMA, q, s);
35422812Smckusick 	return(q);
35522812Smckusick 	}
35622812Smckusick 
35722812Smckusick #if SZADDR > SZSHORT
35822812Smckusick if( pt == TYADDR && t == TYSHORT)
35922812Smckusick 	{
36022812Smckusick 	err("insufficient precision to hold address type");
36122812Smckusick 	return( errnode() );
36222812Smckusick 	}
36322812Smckusick #endif
36422812Smckusick if( pt == TYADDR && ISNUMERIC(t) )
36522812Smckusick 	warn("implicit conversion of address to numeric type");
36622812Smckusick 
36722812Smckusick if( ISCONST(p) && pt!=TYADDR)
36822812Smckusick 	{
36922812Smckusick 	q = (expptr) mkconst(t);
37022812Smckusick 	consconv(t, &(q->constblock.const),
37122812Smckusick 		p->constblock.vtype, &(p->constblock.const) );
37222812Smckusick 	frexpr(p);
37322812Smckusick 	}
37422812Smckusick #if TARGET == PDP11
37522812Smckusick else if(ISINT(t) && pt==TYCHAR)
37622812Smckusick 	{
37722812Smckusick 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
37822812Smckusick 	if(t == TYLONG)
37922812Smckusick 		q = opconv(q, TYLONG);
38022812Smckusick 	}
38122812Smckusick #endif
38222812Smckusick else
38322812Smckusick 	q = opconv(p, t);
38422812Smckusick 
38522812Smckusick if(t == TYCHAR)
38622812Smckusick 	q->constblock.vleng = ICON(1);
38722812Smckusick return(q);
38822812Smckusick }
38922812Smckusick 
39022812Smckusick 
39122812Smckusick 
39222812Smckusick /* intrinsic conversions */
39322812Smckusick expptr intrconv(t, p)
39422812Smckusick register int t;
39522812Smckusick register expptr p;
39622812Smckusick {
39722812Smckusick register expptr q;
39822812Smckusick register int pt;
39922812Smckusick expptr opconv();
40022812Smckusick 
40122812Smckusick if(t==TYUNKNOWN || t==TYERROR)
40222812Smckusick 	badtype("intrconv", t);
40322812Smckusick pt = p->headblock.vtype;
40422812Smckusick if(t == pt)
40522812Smckusick 	return(p);
40622812Smckusick 
40722812Smckusick else if( ISCONST(p) && pt!=TYADDR)
40822812Smckusick 	{
40922812Smckusick 	q = (expptr) mkconst(t);
41022812Smckusick 	consconv(t, &(q->constblock.const),
41122812Smckusick 		p->constblock.vtype, &(p->constblock.const) );
41222812Smckusick 	frexpr(p);
41322812Smckusick 	}
41422812Smckusick #if TARGET == PDP11
41522812Smckusick else if(ISINT(t) && pt==TYCHAR)
41622812Smckusick 	{
41722812Smckusick 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
41822812Smckusick 	if(t == TYLONG)
41922812Smckusick 		q = opconv(q, TYLONG);
42022812Smckusick 	}
42122812Smckusick #endif
42222812Smckusick else
42322812Smckusick 	q = opconv(p, t);
42422812Smckusick 
42522812Smckusick if(t == TYCHAR)
42622812Smckusick 	q->constblock.vleng = ICON(1);
42722812Smckusick return(q);
42822812Smckusick }
42922812Smckusick 
43022812Smckusick 
43122812Smckusick 
43222812Smckusick expptr opconv(p, t)
43322812Smckusick expptr p;
43422812Smckusick int t;
43522812Smckusick {
43622812Smckusick register expptr q;
43722812Smckusick 
43822812Smckusick q = mkexpr(OPCONV, p, PNULL);
43922812Smckusick q->headblock.vtype = t;
44022812Smckusick return(q);
44122812Smckusick }
44222812Smckusick 
44322812Smckusick 
44422812Smckusick 
44522812Smckusick expptr addrof(p)
44622812Smckusick expptr p;
44722812Smckusick {
44822812Smckusick return( mkexpr(OPADDR, p, PNULL) );
44922812Smckusick }
45022812Smckusick 
45122812Smckusick 
45222812Smckusick 
45322812Smckusick tagptr cpexpr(p)
45422812Smckusick register tagptr p;
45522812Smckusick {
45622812Smckusick register tagptr e;
45722812Smckusick int tag;
45822812Smckusick register chainp ep, pp;
45922812Smckusick tagptr cpblock();
46022812Smckusick 
46122812Smckusick static int blksize[ ] =
46222812Smckusick 	{	0,
46322812Smckusick 		sizeof(struct Nameblock),
46422812Smckusick 		sizeof(struct Constblock),
46522812Smckusick 		sizeof(struct Exprblock),
46622812Smckusick 		sizeof(struct Addrblock),
46722812Smckusick 		sizeof(struct Tempblock),
46822812Smckusick 		sizeof(struct Primblock),
46922812Smckusick 		sizeof(struct Listblock),
47022812Smckusick 		sizeof(struct Errorblock)
47122812Smckusick 	};
47222812Smckusick 
47322812Smckusick if(p == NULL)
47422812Smckusick 	return(NULL);
47522812Smckusick 
47622812Smckusick if( (tag = p->tag) == TNAME)
47722812Smckusick 	return(p);
47822812Smckusick 
47922812Smckusick e = cpblock( blksize[p->tag] , p);
48022812Smckusick 
48122812Smckusick switch(tag)
48222812Smckusick 	{
48322812Smckusick 	case TCONST:
48422812Smckusick 		if(e->constblock.vtype == TYCHAR)
48522812Smckusick 			{
48622812Smckusick 			e->constblock.const.ccp =
48722812Smckusick 				copyn(1+strlen(e->constblock.const.ccp),
48822812Smckusick 					e->constblock.const.ccp);
48922812Smckusick 			e->constblock.vleng =
49022812Smckusick 				(expptr) cpexpr(e->constblock.vleng);
49122812Smckusick 			}
49222812Smckusick 	case TERROR:
49322812Smckusick 		break;
49422812Smckusick 
49522812Smckusick 	case TEXPR:
49622812Smckusick 		e->exprblock.leftp =  (expptr) cpexpr(p->exprblock.leftp);
49722812Smckusick 		e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
49822812Smckusick 		break;
49922812Smckusick 
50022812Smckusick 	case TLIST:
50122812Smckusick 		if(pp = p->listblock.listp)
50222812Smckusick 			{
50322812Smckusick 			ep = e->listblock.listp =
50422812Smckusick 				mkchain( cpexpr(pp->datap), CHNULL);
50522812Smckusick 			for(pp = pp->nextp ; pp ; pp = pp->nextp)
50622812Smckusick 				ep = ep->nextp =
50722812Smckusick 					mkchain( cpexpr(pp->datap), CHNULL);
50822812Smckusick 			}
50922812Smckusick 		break;
51022812Smckusick 
51122812Smckusick 	case TADDR:
51222812Smckusick 		e->addrblock.vleng = (expptr)  cpexpr(e->addrblock.vleng);
51322812Smckusick 		e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
51422812Smckusick 		e->addrblock.istemp = NO;
51522812Smckusick 		break;
51622812Smckusick 
51722812Smckusick 	case TTEMP:
51822812Smckusick 		e->tempblock.vleng = (expptr)  cpexpr(e->tempblock.vleng);
51922812Smckusick 		e->tempblock.istemp = NO;
52022812Smckusick 		break;
52122812Smckusick 
52222812Smckusick 	case TPRIM:
52322812Smckusick 		e->primblock.argsp = (struct Listblock *)
52422812Smckusick 					cpexpr(e->primblock.argsp);
52522812Smckusick 		e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
52622812Smckusick 		e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
52722812Smckusick 		break;
52822812Smckusick 
52922812Smckusick 	default:
53022812Smckusick 		badtag("cpexpr", tag);
53122812Smckusick 	}
53222812Smckusick 
53322812Smckusick return(e);
53422812Smckusick }
53522812Smckusick 
53622812Smckusick frexpr(p)
53722812Smckusick register tagptr p;
53822812Smckusick {
53922812Smckusick register chainp q;
54022812Smckusick 
54122812Smckusick if(p == NULL)
54222812Smckusick 	return;
54322812Smckusick 
54422812Smckusick switch(p->tag)
54522812Smckusick 	{
54622812Smckusick 	case TCONST:
54722812Smckusick 		switch (p->constblock.vtype)
54822812Smckusick 			{
54922812Smckusick 			case TYBITSTR:
55022812Smckusick 			case TYCHAR:
55122812Smckusick 			case TYHOLLERITH:
55222812Smckusick 				free( (charptr) (p->constblock.const.ccp) );
55322812Smckusick 				frexpr(p->constblock.vleng);
55422812Smckusick 			}
55522812Smckusick 		break;
55622812Smckusick 
55722812Smckusick 	case TADDR:
55822812Smckusick 		if (!optimflag && p->addrblock.istemp)
55922812Smckusick 			{
56022812Smckusick 			frtemp(p);
56122812Smckusick 			return;
56222812Smckusick 			}
56322812Smckusick 		frexpr(p->addrblock.vleng);
56422812Smckusick 		frexpr(p->addrblock.memoffset);
56522812Smckusick 		break;
56622812Smckusick 
56722812Smckusick 	case TTEMP:
56822812Smckusick 		frexpr(p->tempblock.vleng);
56922812Smckusick 		break;
57022812Smckusick 
57122812Smckusick 	case TERROR:
57222812Smckusick 		break;
57322812Smckusick 
57422812Smckusick 	case TNAME:
57522812Smckusick 		return;
57622812Smckusick 
57722812Smckusick 	case TPRIM:
57822812Smckusick 		frexpr(p->primblock.argsp);
57922812Smckusick 		frexpr(p->primblock.fcharp);
58022812Smckusick 		frexpr(p->primblock.lcharp);
58122812Smckusick 		break;
58222812Smckusick 
58322812Smckusick 	case TEXPR:
58422812Smckusick 		frexpr(p->exprblock.leftp);
58522812Smckusick 		if(p->exprblock.rightp)
58622812Smckusick 			frexpr(p->exprblock.rightp);
58722812Smckusick 		break;
58822812Smckusick 
58922812Smckusick 	case TLIST:
59022812Smckusick 		for(q = p->listblock.listp ; q ; q = q->nextp)
59122812Smckusick 			frexpr(q->datap);
59222812Smckusick 		frchain( &(p->listblock.listp) );
59322812Smckusick 		break;
59422812Smckusick 
59522812Smckusick 	default:
59622812Smckusick 		badtag("frexpr", p->tag);
59722812Smckusick 	}
59822812Smckusick 
59922812Smckusick free( (charptr) p );
60022812Smckusick }
60122812Smckusick 
60222812Smckusick /* fix up types in expression; replace subtrees and convert
60322812Smckusick    names to address blocks */
60422812Smckusick 
60522812Smckusick expptr fixtype(p)
60622812Smckusick register tagptr p;
60722812Smckusick {
60822812Smckusick 
60922812Smckusick if(p == 0)
61022812Smckusick 	return(0);
61122812Smckusick 
61222812Smckusick switch(p->tag)
61322812Smckusick 	{
61422812Smckusick 	case TCONST:
61522812Smckusick 		return( (expptr) p );
61622812Smckusick 
61722812Smckusick 	case TADDR:
61822812Smckusick 		p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
61922812Smckusick 		return( (expptr) p);
62022812Smckusick 
62122812Smckusick 	case TTEMP:
62222812Smckusick 		return( (expptr) p);
62322812Smckusick 
62422812Smckusick 	case TERROR:
62522812Smckusick 		return( (expptr) p);
62622812Smckusick 
62722812Smckusick 	default:
62822812Smckusick 		badtag("fixtype", p->tag);
62922812Smckusick 
63022812Smckusick 	case TEXPR:
63122812Smckusick 		return( fixexpr(p) );
63222812Smckusick 
63322812Smckusick 	case TLIST:
63422812Smckusick 		return( (expptr) p );
63522812Smckusick 
63622812Smckusick 	case TPRIM:
63722812Smckusick 		if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
63822812Smckusick 			{
63922812Smckusick 			if(p->primblock.namep->vtype == TYSUBR)
64022812Smckusick 				{
64122812Smckusick 				err("function invocation of subroutine");
64222812Smckusick 				return( errnode() );
64322812Smckusick 				}
64422812Smckusick 			else
64522812Smckusick 				return( mkfunct(p) );
64622812Smckusick 			}
64722812Smckusick 		else	return( mklhs(p) );
64822812Smckusick 	}
64922812Smckusick }
65022812Smckusick 
65122812Smckusick 
65222812Smckusick 
65322812Smckusick 
65422812Smckusick 
65522812Smckusick /* special case tree transformations and cleanups of expression trees */
65622812Smckusick 
65722812Smckusick expptr fixexpr(p)
65822812Smckusick register Exprp p;
65922812Smckusick {
66022812Smckusick expptr lp;
66122812Smckusick register expptr rp;
66222812Smckusick register expptr q;
66322812Smckusick int opcode, ltype, rtype, ptype, mtype;
66422812Smckusick expptr lconst, rconst;
66522812Smckusick expptr mkpower();
66622812Smckusick 
66722812Smckusick if( ISERROR(p) )
66822812Smckusick 	return( (expptr) p );
66922812Smckusick else if(p->tag != TEXPR)
67022812Smckusick 	badtag("fixexpr", p->tag);
67122812Smckusick opcode = p->opcode;
67222812Smckusick if (ISCONST(p->leftp))
67322812Smckusick 	lconst = (expptr) cpexpr(p->leftp);
67422812Smckusick else
67522812Smckusick 	lconst = NULL;
67622812Smckusick if (p->rightp && ISCONST(p->rightp))
67722812Smckusick 	rconst = (expptr) cpexpr(p->rightp);
67822812Smckusick else
67922812Smckusick 	rconst = NULL;
68022812Smckusick lp = p->leftp = fixtype(p->leftp);
68122812Smckusick ltype = lp->headblock.vtype;
68222812Smckusick if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
68322812Smckusick 	{
68422812Smckusick 	err("left side of assignment must be variable");
68522812Smckusick 	frexpr(p);
68622812Smckusick 	return( errnode() );
68722812Smckusick 	}
68822812Smckusick 
68922812Smckusick if(p->rightp)
69022812Smckusick 	{
69122812Smckusick 	rp = p->rightp = fixtype(p->rightp);
69222812Smckusick 	rtype = rp->headblock.vtype;
69322812Smckusick 	}
69422812Smckusick else
69522812Smckusick 	{
69622812Smckusick 	rp = NULL;
69722812Smckusick 	rtype = 0;
69822812Smckusick 	}
69922812Smckusick 
70022812Smckusick if(ltype==TYERROR || rtype==TYERROR)
70122812Smckusick 	{
70222812Smckusick 	frexpr(p);
70322812Smckusick 	frexpr(lconst);
70422812Smckusick 	frexpr(rconst);
70522812Smckusick 	return( errnode() );
70622812Smckusick 	}
70722812Smckusick 
70822812Smckusick /* force folding if possible */
70922812Smckusick if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
71022812Smckusick 	{
71122812Smckusick 	q = mkexpr(opcode, lp, rp);
71222812Smckusick 	if( ISCONST(q) )
71322812Smckusick 		{
71422812Smckusick 		frexpr(lconst);
71522812Smckusick 		frexpr(rconst);
71622812Smckusick 		return(q);
71722812Smckusick 		}
71822812Smckusick 	free( (charptr) q );	/* constants did not fold */
71922812Smckusick 	}
72022812Smckusick 
72122812Smckusick if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
72222812Smckusick 	{
72322812Smckusick 	frexpr(p);
72422812Smckusick 	frexpr(lconst);
72522812Smckusick 	frexpr(rconst);
72622812Smckusick 	return( errnode() );
72722812Smckusick 	}
72822812Smckusick 
72922812Smckusick switch(opcode)
73022812Smckusick 	{
73122812Smckusick 	case OPCONCAT:
73222812Smckusick 		if(p->vleng == NULL)
73322812Smckusick 			p->vleng = mkexpr(OPPLUS,
73422812Smckusick 				cpexpr(lp->headblock.vleng),
73522812Smckusick 				cpexpr(rp->headblock.vleng) );
73622812Smckusick 		break;
73722812Smckusick 
73822812Smckusick 	case OPASSIGN:
73922812Smckusick 	case OPPLUSEQ:
74022812Smckusick 	case OPSTAREQ:
74122812Smckusick 		if(ltype == rtype)
74222812Smckusick 			break;
74322812Smckusick 		if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
74422812Smckusick 			break;
74522812Smckusick 		if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
74622812Smckusick 			break;
74722812Smckusick 		if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
74822812Smckusick #if FAMILY==PCC
74922812Smckusick 		    && typesize[ltype]>=typesize[rtype] )
75022812Smckusick #else
75122812Smckusick 		    && typesize[ltype]==typesize[rtype] )
75222812Smckusick #endif
75322812Smckusick 			break;
75422812Smckusick 		if (rconst)
75522812Smckusick 			{
75622812Smckusick 			p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
75722812Smckusick 			frexpr(rp);
75822812Smckusick 			}
75922812Smckusick 		else
76022812Smckusick 			p->rightp = fixtype(mkconv(ptype, rp));
76122812Smckusick 		break;
76222812Smckusick 
76322812Smckusick 	case OPSLASH:
76422812Smckusick 		if( ISCOMPLEX(rtype) )
76522812Smckusick 			{
76622812Smckusick 			p = (Exprp) call2(ptype,
76722812Smckusick 				ptype==TYCOMPLEX? "c_div" : "z_div",
76822812Smckusick 				mkconv(ptype, lp), mkconv(ptype, rp) );
76922812Smckusick 			break;
77022812Smckusick 			}
77122812Smckusick 	case OPPLUS:
77222812Smckusick 	case OPMINUS:
77322812Smckusick 	case OPSTAR:
77422812Smckusick 	case OPMOD:
77522812Smckusick 		if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
77622812Smckusick 		    (rtype==TYREAL && ! rconst ) ))
77722812Smckusick 			break;
77822812Smckusick 		if( ISCOMPLEX(ptype) )
77922812Smckusick 			break;
78022812Smckusick 		if(ltype != ptype)
78122812Smckusick 			if (lconst)
78222812Smckusick 				{
78322812Smckusick 				p->leftp = fixtype(mkconv(ptype,
78422812Smckusick 						cpexpr(lconst)));
78522812Smckusick 				frexpr(lp);
78622812Smckusick 				}
78722812Smckusick 			else
78822812Smckusick 				p->leftp = fixtype(mkconv(ptype,lp));
78922812Smckusick 		if(rtype != ptype)
79022812Smckusick 			if (rconst)
79122812Smckusick 				{
79222812Smckusick 				p->rightp = fixtype(mkconv(ptype,
79322812Smckusick 						cpexpr(rconst)));
79422812Smckusick 				frexpr(rp);
79522812Smckusick 				}
79622812Smckusick 			else
79722812Smckusick 				p->rightp = fixtype(mkconv(ptype,rp));
79822812Smckusick 		break;
79922812Smckusick 
80022812Smckusick 	case OPPOWER:
80122812Smckusick 		return( mkpower(p) );
80222812Smckusick 
80322812Smckusick 	case OPLT:
80422812Smckusick 	case OPLE:
80522812Smckusick 	case OPGT:
80622812Smckusick 	case OPGE:
80722812Smckusick 	case OPEQ:
80822812Smckusick 	case OPNE:
80922812Smckusick 		if(ltype == rtype)
81022812Smckusick 			break;
81122812Smckusick 		mtype = cktype(OPMINUS, ltype, rtype);
81222812Smckusick 		if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
81322812Smckusick 		    (rtype==TYREAL && ! rconst) ))
81422812Smckusick 			break;
81522812Smckusick 		if( ISCOMPLEX(mtype) )
81622812Smckusick 			break;
81722812Smckusick 		if(ltype != mtype)
81822812Smckusick 			if (lconst)
81922812Smckusick 				{
82022812Smckusick 				p->leftp = fixtype(mkconv(mtype,
82122812Smckusick 						cpexpr(lconst)));
82222812Smckusick 				frexpr(lp);
82322812Smckusick 				}
82422812Smckusick 			else
82522812Smckusick 				p->leftp = fixtype(mkconv(mtype,lp));
82622812Smckusick 		if(rtype != mtype)
82722812Smckusick 			if (rconst)
82822812Smckusick 				{
82922812Smckusick 				p->rightp = fixtype(mkconv(mtype,
83022812Smckusick 						cpexpr(rconst)));
83122812Smckusick 				frexpr(rp);
83222812Smckusick 				}
83322812Smckusick 			else
83422812Smckusick 				p->rightp = fixtype(mkconv(mtype,rp));
83522812Smckusick 		break;
83622812Smckusick 
83722812Smckusick 
83822812Smckusick 	case OPCONV:
83922812Smckusick 		if(ISCOMPLEX(p->vtype))
84022812Smckusick 			{
84122812Smckusick 			ptype = cktype(OPCONV, p->vtype, ltype);
84222812Smckusick 			if(p->rightp)
84322812Smckusick 				ptype = cktype(OPCONV, ptype, rtype);
84422812Smckusick 			break;
84522812Smckusick 			}
84622812Smckusick 		ptype = cktype(OPCONV, p->vtype, ltype);
84722812Smckusick 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
84822812Smckusick 			{
84922812Smckusick 			lp->exprblock.rightp =
85022812Smckusick 				fixtype( mkconv(ptype, lp->exprblock.rightp) );
85122812Smckusick 			free( (charptr) p );
85222812Smckusick 			p = (Exprp) lp;
85322812Smckusick 			}
85422812Smckusick 		break;
85522812Smckusick 
85622812Smckusick 	case OPADDR:
85722812Smckusick 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
85822812Smckusick 			fatal("addr of addr");
85922812Smckusick 		break;
86022812Smckusick 
86122812Smckusick 	case OPCOMMA:
86222812Smckusick 	case OPQUEST:
86322812Smckusick 	case OPCOLON:
86422812Smckusick 		break;
86522812Smckusick 
86622812Smckusick 	case OPPAREN:
86722812Smckusick 		p->vleng = (expptr) cpexpr( lp->headblock.vleng );
86822812Smckusick 		break;
86922812Smckusick 
87022812Smckusick 	case OPMIN:
87122812Smckusick 	case OPMAX:
87222812Smckusick 		ptype = p->vtype;
87322812Smckusick 		break;
87422812Smckusick 
87522812Smckusick 	default:
87622812Smckusick 		break;
87722812Smckusick 	}
87822812Smckusick 
87922812Smckusick p->vtype = ptype;
88022812Smckusick frexpr(lconst);
88122812Smckusick frexpr(rconst);
88222812Smckusick return((expptr) p);
88322812Smckusick }
88422812Smckusick 
88522812Smckusick #if SZINT < SZLONG
88622812Smckusick /*
88722812Smckusick    for efficient subscripting, replace long ints by shorts
88822812Smckusick    in easy places
88922812Smckusick */
89022812Smckusick 
89122812Smckusick expptr shorten(p)
89222812Smckusick register expptr p;
89322812Smckusick {
89422812Smckusick register expptr q;
89522812Smckusick 
89622812Smckusick if(p->headblock.vtype != TYLONG)
89722812Smckusick 	return(p);
89822812Smckusick 
89922812Smckusick switch(p->tag)
90022812Smckusick 	{
90122812Smckusick 	case TERROR:
90222812Smckusick 	case TLIST:
90322812Smckusick 		return(p);
90422812Smckusick 
90522812Smckusick 	case TCONST:
90622812Smckusick 	case TADDR:
90722812Smckusick 		return( mkconv(TYINT,p) );
90822812Smckusick 
90922812Smckusick 	case TEXPR:
91022812Smckusick 		break;
91122812Smckusick 
91222812Smckusick 	default:
91322812Smckusick 		badtag("shorten", p->tag);
91422812Smckusick 	}
91522812Smckusick 
91622812Smckusick switch(p->exprblock.opcode)
91722812Smckusick 	{
91822812Smckusick 	case OPPLUS:
91922812Smckusick 	case OPMINUS:
92022812Smckusick 	case OPSTAR:
92122812Smckusick 		q = shorten( cpexpr(p->exprblock.rightp) );
92222812Smckusick 		if(q->headblock.vtype == TYINT)
92322812Smckusick 			{
92422812Smckusick 			p->exprblock.leftp = shorten(p->exprblock.leftp);
92522812Smckusick 			if(p->exprblock.leftp->headblock.vtype == TYLONG)
92622812Smckusick 				frexpr(q);
92722812Smckusick 			else
92822812Smckusick 				{
92922812Smckusick 				frexpr(p->exprblock.rightp);
93022812Smckusick 				p->exprblock.rightp = q;
93122812Smckusick 				p->exprblock.vtype = TYINT;
93222812Smckusick 				}
93322812Smckusick 			}
93422812Smckusick 		break;
93522812Smckusick 
93622812Smckusick 	case OPNEG:
93722812Smckusick 	case OPPAREN:
93822812Smckusick 		p->exprblock.leftp = shorten(p->exprblock.leftp);
93922812Smckusick 		if(p->exprblock.leftp->headblock.vtype == TYINT)
94022812Smckusick 			p->exprblock.vtype = TYINT;
94122812Smckusick 		break;
94222812Smckusick 
94322812Smckusick 	case OPCALL:
94422812Smckusick 	case OPCCALL:
94522812Smckusick 		p = mkconv(TYINT,p);
94622812Smckusick 		break;
94722812Smckusick 	default:
94822812Smckusick 		break;
94922812Smckusick 	}
95022812Smckusick 
95122812Smckusick return(p);
95222812Smckusick }
95322812Smckusick #endif
95422812Smckusick 
95522812Smckusick /* fix an argument list, taking due care for special first level cases */
95622812Smckusick 
95722812Smckusick fixargs(doput, p0)
95822812Smckusick int doput;	/* doput is true if the function is not intrinsic;
95922812Smckusick 		   was used to decide whether to do a putconst,
96022812Smckusick 		   but this is no longer done here (Feb82)*/
96122812Smckusick struct Listblock *p0;
96222812Smckusick {
96322812Smckusick register chainp p;
96422812Smckusick register tagptr q, t;
96522812Smckusick register int qtag;
96622812Smckusick int nargs;
96722812Smckusick Addrp mkscalar();
96822812Smckusick 
96922812Smckusick nargs = 0;
97022812Smckusick if(p0)
97122812Smckusick     for(p = p0->listp ; p ; p = p->nextp)
97222812Smckusick 	{
97322812Smckusick 	++nargs;
97422812Smckusick 	q = p->datap;
97522812Smckusick 	qtag = q->tag;
97622812Smckusick 	if(qtag == TCONST)
97722812Smckusick 		{
97822812Smckusick 		if(q->constblock.vtype == TYSHORT)
97922812Smckusick 			q = (tagptr) mkconv(tyint, q);
98022812Smckusick 		p->datap = q ;
98122812Smckusick 		}
98222812Smckusick 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
98322812Smckusick 		q->primblock.namep->vclass==CLPROC)
98422812Smckusick 			p->datap = (tagptr) mkaddr(q->primblock.namep);
98522812Smckusick 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
98622812Smckusick 		q->primblock.namep->vdim!=NULL)
98722812Smckusick 			p->datap = (tagptr) mkscalar(q->primblock.namep);
98822812Smckusick 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
98922812Smckusick 		q->primblock.namep->vdovar &&
99022812Smckusick 		(t = (tagptr) memversion(q->primblock.namep)) )
99122812Smckusick 			p->datap = (tagptr) fixtype(t);
99222812Smckusick 	else
99322812Smckusick 		p->datap = (tagptr) fixtype(q);
99422812Smckusick 	}
99522812Smckusick return(nargs);
99622812Smckusick }
99722812Smckusick 
99822812Smckusick 
99922812Smckusick Addrp mkscalar(np)
100022812Smckusick register Namep np;
100122812Smckusick {
100222812Smckusick register Addrp ap;
100322812Smckusick 
100422812Smckusick vardcl(np);
100522812Smckusick ap = mkaddr(np);
100622812Smckusick 
100722812Smckusick #if TARGET == VAX
100822812Smckusick 	/* on the VAX, prolog causes array arguments
100922812Smckusick 	   to point at the (0,...,0) element, except when
101022812Smckusick 	   subscript checking is on
101122812Smckusick 	*/
101222812Smckusick #ifdef SDB
101322812Smckusick 	if( !checksubs && !sdbflag && np->vstg==STGARG)
101422812Smckusick #else
101522812Smckusick 	if( !checksubs && np->vstg==STGARG)
101622812Smckusick #endif
101722812Smckusick 		{
101822812Smckusick 		register struct Dimblock *dp;
101922812Smckusick 		dp = np->vdim;
102022812Smckusick 		frexpr(ap->memoffset);
102122812Smckusick 		ap->memoffset = mkexpr(OPSTAR,
102222812Smckusick 				(np->vtype==TYCHAR ?
102322812Smckusick 					cpexpr(np->vleng) :
102422812Smckusick 					(tagptr)ICON(typesize[np->vtype]) ),
102522812Smckusick 				cpexpr(dp->baseoffset) );
102622812Smckusick 		}
102722812Smckusick #endif
102822812Smckusick return(ap);
102922812Smckusick }
103022812Smckusick 
103122812Smckusick 
103222812Smckusick 
103322812Smckusick 
103422812Smckusick 
103522812Smckusick expptr mkfunct(p)
103622812Smckusick register struct Primblock *p;
103722812Smckusick {
103822812Smckusick struct Entrypoint *ep;
103922812Smckusick Addrp ap;
104022812Smckusick struct Extsym *extp;
104122812Smckusick register Namep np;
104222812Smckusick register expptr q;
104322812Smckusick expptr intrcall(), stfcall();
104422812Smckusick int k, nargs;
104522812Smckusick int class;
104622812Smckusick 
104722812Smckusick if(p->tag != TPRIM)
104822812Smckusick 	return( errnode() );
104922812Smckusick 
105022812Smckusick np = p->namep;
105122812Smckusick class = np->vclass;
105222812Smckusick 
105322812Smckusick if(class == CLUNKNOWN)
105422812Smckusick 	{
105522812Smckusick 	np->vclass = class = CLPROC;
105622812Smckusick 	if(np->vstg == STGUNKNOWN)
105722812Smckusick 		{
105822812Smckusick 		if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
105922812Smckusick 			{
106022812Smckusick 			np->vstg = STGINTR;
106122812Smckusick 			np->vardesc.varno = k;
106222812Smckusick 			np->vprocclass = PINTRINSIC;
106322812Smckusick 			}
106422812Smckusick 		else
106522812Smckusick 			{
106622812Smckusick 			extp = mkext( varunder(VL,np->varname) );
106722812Smckusick 			extp->extstg = STGEXT;
106822812Smckusick 			np->vstg = STGEXT;
106922812Smckusick 			np->vardesc.varno = extp - extsymtab;
107022812Smckusick 			np->vprocclass = PEXTERNAL;
107122812Smckusick 			}
107222812Smckusick 		}
107322812Smckusick 	else if(np->vstg==STGARG)
107422812Smckusick 		{
107522812Smckusick 		if(np->vtype!=TYCHAR && !ftn66flag)
107622812Smckusick 		    warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
107722812Smckusick 		np->vprocclass = PEXTERNAL;
107822812Smckusick 		}
107922812Smckusick 	}
108022812Smckusick 
108122812Smckusick if(class != CLPROC)
108222812Smckusick 	fatali("invalid class code %d for function", class);
108322812Smckusick if(p->fcharp || p->lcharp)
108422812Smckusick 	{
108522812Smckusick 	err("no substring of function call");
108622812Smckusick 	goto error;
108722812Smckusick 	}
108822812Smckusick impldcl(np);
108922812Smckusick nargs = fixargs( np->vprocclass!=PINTRINSIC,  p->argsp);
109022812Smckusick 
109122812Smckusick switch(np->vprocclass)
109222812Smckusick 	{
109322812Smckusick 	case PEXTERNAL:
109422812Smckusick 		ap = mkaddr(np);
109522812Smckusick 	call:
109622812Smckusick 		q = mkexpr(OPCALL, ap, p->argsp);
109722812Smckusick 		if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
109822812Smckusick 			{
109922812Smckusick 			err("attempt to use untyped function");
110022812Smckusick 			goto error;
110122812Smckusick 			}
110222812Smckusick 		if(np->vleng)
110322812Smckusick 			q->exprblock.vleng = (expptr) cpexpr(np->vleng);
110422812Smckusick 		break;
110522812Smckusick 
110622812Smckusick 	case PINTRINSIC:
110722812Smckusick 		q = intrcall(np, p->argsp, nargs);
110822812Smckusick 		break;
110922812Smckusick 
111022812Smckusick 	case PSTFUNCT:
111122812Smckusick 		q = stfcall(np, p->argsp);
111222812Smckusick 		break;
111322812Smckusick 
111422812Smckusick 	case PTHISPROC:
111522812Smckusick 		warn("recursive call");
111622812Smckusick 		for(ep = entries ; ep ; ep = ep->entnextp)
111722812Smckusick 			if(ep->enamep == np)
111822812Smckusick 				break;
111922812Smckusick 		if(ep == NULL)
112022812Smckusick 			fatal("mkfunct: impossible recursion");
112122812Smckusick 		ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
112222812Smckusick 		goto call;
112322812Smckusick 
112422812Smckusick 	default:
112522812Smckusick 		fatali("mkfunct: impossible vprocclass %d",
112622812Smckusick 			(int) (np->vprocclass) );
112722812Smckusick 	}
112822812Smckusick free( (charptr) p );
112922812Smckusick return(q);
113022812Smckusick 
113122812Smckusick error:
113222812Smckusick 	frexpr(p);
113322812Smckusick 	return( errnode() );
113422812Smckusick }
113522812Smckusick 
113622812Smckusick 
113722812Smckusick 
113822812Smckusick LOCAL expptr stfcall(np, actlist)
113922812Smckusick Namep np;
114022812Smckusick struct Listblock *actlist;
114122812Smckusick {
114222812Smckusick register chainp actuals;
114322812Smckusick int nargs;
114422812Smckusick chainp oactp, formals;
114522812Smckusick int type;
114622812Smckusick expptr q, rhs, ap;
114722812Smckusick Namep tnp;
114822812Smckusick register struct Rplblock *rp;
114922812Smckusick struct Rplblock *tlist;
115022812Smckusick 
115122812Smckusick if(actlist)
115222812Smckusick 	{
115322812Smckusick 	actuals = actlist->listp;
115422812Smckusick 	free( (charptr) actlist);
115522812Smckusick 	}
115622812Smckusick else
115722812Smckusick 	actuals = NULL;
115822812Smckusick oactp = actuals;
115922812Smckusick 
116022812Smckusick nargs = 0;
116122812Smckusick tlist = NULL;
116222812Smckusick if( (type = np->vtype) == TYUNKNOWN)
116322812Smckusick 	{
116422812Smckusick 	err("attempt to use untyped statement function");
116522812Smckusick 	q = errnode();
116622812Smckusick 	goto ret;
116722812Smckusick 	}
116822812Smckusick formals = (chainp) (np->varxptr.vstfdesc->datap);
116922812Smckusick rhs = (expptr) (np->varxptr.vstfdesc->nextp);
117022812Smckusick 
117122812Smckusick /* copy actual arguments into temporaries */
117222812Smckusick while(actuals!=NULL && formals!=NULL)
117322812Smckusick 	{
117422812Smckusick 	rp = ALLOC(Rplblock);
117522812Smckusick 	rp->rplnp = tnp = (Namep) (formals->datap);
117622812Smckusick 	ap = fixtype(actuals->datap);
117722812Smckusick 	if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
117822812Smckusick 	   && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
117922812Smckusick 		{
118022812Smckusick 		rp->rplvp = (expptr) ap;
118122812Smckusick 		rp->rplxp = NULL;
118222812Smckusick 		rp->rpltag = ap->tag;
118322812Smckusick 		}
118422812Smckusick 	else	{
118522812Smckusick 		rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
118622812Smckusick 		rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
118722812Smckusick 		if( (rp->rpltag = rp->rplxp->tag) == TERROR)
118822812Smckusick 			err("disagreement of argument types in statement function call");
118922812Smckusick 		else if(tnp->vtype!=ap->headblock.vtype)
119022812Smckusick 			warn("argument type mismatch in statement function");
119122812Smckusick 		}
119222812Smckusick 	rp->rplnextp = tlist;
119322812Smckusick 	tlist = rp;
119422812Smckusick 	actuals = actuals->nextp;
119522812Smckusick 	formals = formals->nextp;
119622812Smckusick 	++nargs;
119722812Smckusick 	}
119822812Smckusick 
119922812Smckusick if(actuals!=NULL || formals!=NULL)
120022812Smckusick 	err("statement function definition and argument list differ");
120122812Smckusick 
120222812Smckusick /*
120322812Smckusick    now push down names involved in formal argument list, then
120422812Smckusick    evaluate rhs of statement function definition in this environment
120522812Smckusick */
120622812Smckusick 
120722812Smckusick if(tlist)	/* put tlist in front of the rpllist */
120822812Smckusick 	{
120922812Smckusick 	for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
121022812Smckusick 		;
121122812Smckusick 	rp->rplnextp = rpllist;
121222812Smckusick 	rpllist = tlist;
121322812Smckusick 	}
121422812Smckusick 
121522812Smckusick q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
121622812Smckusick 
121722812Smckusick /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
121822812Smckusick while(--nargs >= 0)
121922812Smckusick 	{
122022812Smckusick 	if(rpllist->rplxp)
122122812Smckusick 		q = mkexpr(OPCOMMA, rpllist->rplxp, q);
122222812Smckusick 	rp = rpllist->rplnextp;
122322812Smckusick 	frexpr(rpllist->rplvp);
122422812Smckusick 	free(rpllist);
122522812Smckusick 	rpllist = rp;
122622812Smckusick 	}
122722812Smckusick 
122822812Smckusick ret:
122922812Smckusick 	frchain( &oactp );
123022812Smckusick 	return(q);
123122812Smckusick }
123222812Smckusick 
123322812Smckusick 
123422812Smckusick 
123522812Smckusick 
123622812Smckusick Addrp mkplace(np)
123722812Smckusick register Namep np;
123822812Smckusick {
123922812Smckusick register Addrp s;
124022812Smckusick register struct Rplblock *rp;
124122812Smckusick int regn;
124222812Smckusick 
124322812Smckusick /* is name on the replace list? */
124422812Smckusick 
124522812Smckusick for(rp = rpllist ; rp ; rp = rp->rplnextp)
124622812Smckusick 	{
124722812Smckusick 	if(np == rp->rplnp)
124822812Smckusick 		{
124922812Smckusick 		if(rp->rpltag == TNAME)
125022812Smckusick 			{
125122812Smckusick 			np = (Namep) (rp->rplvp);
125222812Smckusick 			break;
125322812Smckusick 			}
125422812Smckusick 		else	return( (Addrp) cpexpr(rp->rplvp) );
125522812Smckusick 		}
125622812Smckusick 	}
125722812Smckusick 
125822812Smckusick /* is variable a DO index in a register ? */
125922812Smckusick 
126022812Smckusick if(np->vdovar && ( (regn = inregister(np)) >= 0) )
126122812Smckusick 	if(np->vtype == TYERROR)
126222812Smckusick 		return( (Addrp) errnode() );
126322812Smckusick 	else
126422812Smckusick 		{
126522812Smckusick 		s = ALLOC(Addrblock);
126622812Smckusick 		s->tag = TADDR;
126722812Smckusick 		s->vstg = STGREG;
126822812Smckusick 		s->vtype = TYIREG;
126922812Smckusick 		s->issaved = np->vsave;
127022812Smckusick 		s->memno = regn;
127122812Smckusick 		s->memoffset = ICON(0);
127222812Smckusick 		return(s);
127322812Smckusick 		}
127422812Smckusick 
127522812Smckusick vardcl(np);
127622812Smckusick return(mkaddr(np));
127722812Smckusick }
127822812Smckusick 
127922812Smckusick 
128022812Smckusick 
128122812Smckusick 
128222812Smckusick expptr mklhs(p)
128322812Smckusick register struct Primblock *p;
128422812Smckusick {
128522812Smckusick expptr suboffset();
128622812Smckusick register Addrp s;
128722812Smckusick Namep np;
128822812Smckusick 
128922812Smckusick if(p->tag != TPRIM)
129022812Smckusick 	return( (expptr) p );
129122812Smckusick np = p->namep;
129222812Smckusick 
129322812Smckusick s = mkplace(np);
129422812Smckusick if(s->tag!=TADDR || s->vstg==STGREG)
129522812Smckusick 	{
129622812Smckusick 	free( (charptr) p );
129722812Smckusick 	return( (expptr) s );
129822812Smckusick 	}
129922812Smckusick 
130022812Smckusick /* compute the address modified by subscripts */
130122812Smckusick 
130222812Smckusick s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
130322812Smckusick frexpr(p->argsp);
130422812Smckusick p->argsp = NULL;
130522812Smckusick 
130622812Smckusick /* now do substring part */
130722812Smckusick 
130822812Smckusick if(p->fcharp || p->lcharp)
130922812Smckusick 	{
131022812Smckusick 	if(np->vtype != TYCHAR)
131122812Smckusick 		errstr("substring of noncharacter %s", varstr(VL,np->varname));
131222812Smckusick 	else	{
131322812Smckusick 		if(p->lcharp == NULL)
131422812Smckusick 			p->lcharp = (expptr) cpexpr(s->vleng);
131522812Smckusick 		frexpr(s->vleng);
131622812Smckusick 		if(p->fcharp)
131722812Smckusick 			{
131822812Smckusick 			if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
131922812Smckusick 			&& p->fcharp->primblock.namep == p->lcharp->primblock.namep)
132022812Smckusick 				/* A trivial optimization -- upper == lower */
132122812Smckusick 				s->vleng = ICON(1);
132222812Smckusick 			else
132322812Smckusick 				s->vleng = mkexpr(OPMINUS, p->lcharp,
132422812Smckusick 					mkexpr(OPMINUS, p->fcharp, ICON(1) ));
132522812Smckusick 			}
132622812Smckusick 		else
132722812Smckusick 			s->vleng = p->lcharp;
132822812Smckusick 		}
132922812Smckusick 	}
133022812Smckusick 
133122812Smckusick s->vleng = fixtype( s->vleng );
133222812Smckusick s->memoffset = fixtype( s->memoffset );
133322812Smckusick free( (charptr) p );
133422812Smckusick return( (expptr) s );
133522812Smckusick }
133622812Smckusick 
133722812Smckusick 
133822812Smckusick 
133922812Smckusick 
134022812Smckusick 
134122812Smckusick deregister(np)
134222812Smckusick Namep np;
134322812Smckusick {
134422812Smckusick if(nregvar>0 && regnamep[nregvar-1]==np)
134522812Smckusick 	{
134622812Smckusick 	--nregvar;
134722812Smckusick #if FAMILY == DMR
134822812Smckusick 	putnreg();
134922812Smckusick #endif
135022812Smckusick 	}
135122812Smckusick }
135222812Smckusick 
135322812Smckusick 
135422812Smckusick 
135522812Smckusick 
135622812Smckusick Addrp memversion(np)
135722812Smckusick register Namep np;
135822812Smckusick {
135922812Smckusick register Addrp s;
136022812Smckusick 
136122812Smckusick if(np->vdovar==NO || (inregister(np)<0) )
136222812Smckusick 	return(NULL);
136322812Smckusick np->vdovar = NO;
136422812Smckusick s = mkplace(np);
136522812Smckusick np->vdovar = YES;
136622812Smckusick return(s);
136722812Smckusick }
136822812Smckusick 
136922812Smckusick 
137022812Smckusick 
137122812Smckusick inregister(np)
137222812Smckusick register Namep np;
137322812Smckusick {
137422812Smckusick register int i;
137522812Smckusick 
137622812Smckusick for(i = 0 ; i < nregvar ; ++i)
137722812Smckusick 	if(regnamep[i] == np)
137822812Smckusick 		return( regnum[i] );
137922812Smckusick return(-1);
138022812Smckusick }
138122812Smckusick 
138222812Smckusick 
138322812Smckusick 
138422812Smckusick 
138522812Smckusick enregister(np)
138622812Smckusick Namep np;
138722812Smckusick {
138822812Smckusick if( inregister(np) >= 0)
138922812Smckusick 	return(YES);
139022812Smckusick if(nregvar >= maxregvar)
139122812Smckusick 	return(NO);
139222812Smckusick vardcl(np);
139322812Smckusick if( ONEOF(np->vtype, MSKIREG) )
139422812Smckusick 	{
139522812Smckusick 	regnamep[nregvar++] = np;
139622812Smckusick 	if(nregvar > highregvar)
139722812Smckusick 		highregvar = nregvar;
139822812Smckusick #if FAMILY == DMR
139922812Smckusick 	putnreg();
140022812Smckusick #endif
140122812Smckusick 	return(YES);
140222812Smckusick 	}
140322812Smckusick else
140422812Smckusick 	return(NO);
140522812Smckusick }
140622812Smckusick 
140722812Smckusick 
140822812Smckusick 
140922812Smckusick 
141022812Smckusick expptr suboffset(p)
141122812Smckusick register struct Primblock *p;
141222812Smckusick {
141322812Smckusick int n;
141422812Smckusick expptr size;
141522812Smckusick expptr oftwo();
141622812Smckusick chainp cp;
141722812Smckusick expptr offp, prod;
141822812Smckusick expptr subcheck();
141922812Smckusick struct Dimblock *dimp;
142022812Smckusick expptr sub[MAXDIM+1];
142122812Smckusick register Namep np;
142222812Smckusick 
142322812Smckusick np = p->namep;
142422812Smckusick offp = ICON(0);
142522812Smckusick n = 0;
142622812Smckusick if(p->argsp)
142722812Smckusick 	for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
142822812Smckusick 		{
142922812Smckusick 		sub[n] = fixtype(cpexpr(cp->datap));
143022812Smckusick 		if ( ! ISINT(sub[n]->headblock.vtype)) {
143122812Smckusick 			errstr("%s: non-integer subscript expression",
143222812Smckusick 				varstr(VL, np->varname) );
143322812Smckusick 			/* Provide a substitute -- go on to find more errors */
143422812Smckusick 			frexpr(sub[n]);
143522812Smckusick 			sub[n] = ICON(1);
143622812Smckusick 		}
143722812Smckusick 		if(n > maxdim)
143822812Smckusick 			{
143922812Smckusick 			   char str[28+VL];
144022812Smckusick 			   sprintf(str, "%s: more than %d subscripts",
144122812Smckusick 				varstr(VL, np->varname), maxdim );
144222812Smckusick 			   err( str );
144322812Smckusick 			break;
144422812Smckusick 			}
144522812Smckusick 		}
144622812Smckusick 
144722812Smckusick dimp = np->vdim;
144822812Smckusick if(n>0 && dimp==NULL)
144922812Smckusick 	errstr("%s: subscripts on scalar variable",
145022812Smckusick 		varstr(VL, np->varname), maxdim );
145122812Smckusick else if(dimp && dimp->ndim!=n)
145222812Smckusick 	errstr("wrong number of subscripts on %s",
145322812Smckusick 		varstr(VL, np->varname) );
145422812Smckusick else if(n > 0)
145522812Smckusick 	{
145622812Smckusick 	prod = sub[--n];
145722812Smckusick 	while( --n >= 0)
145822812Smckusick 		prod = mkexpr(OPPLUS, sub[n],
145922812Smckusick 			mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
146022812Smckusick #if TARGET == VAX
146122812Smckusick #ifdef SDB
146222812Smckusick 	if(checksubs || np->vstg!=STGARG || sdbflag)
146322812Smckusick #else
146422812Smckusick 	if(checksubs || np->vstg!=STGARG)
146522812Smckusick #endif
146622812Smckusick 		prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146722812Smckusick #else
146822812Smckusick 	prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146922812Smckusick #endif
147022812Smckusick 	if(checksubs)
147122812Smckusick 		prod = subcheck(np, prod);
147222812Smckusick 	size = np->vtype == TYCHAR ?
147322812Smckusick 		(expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
147422812Smckusick 	if (!oftwo(size))
147522812Smckusick 		prod = mkexpr(OPSTAR, prod, size);
147622812Smckusick 	else
147722812Smckusick 		prod = mkexpr(OPLSHIFT,prod,oftwo(size));
147822812Smckusick 
147922812Smckusick 	offp = mkexpr(OPPLUS, offp, prod);
148022812Smckusick 	}
148122812Smckusick 
148222812Smckusick if(p->fcharp && np->vtype==TYCHAR)
148322812Smckusick 	offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
148422812Smckusick 
148522812Smckusick return(offp);
148622812Smckusick }
148722812Smckusick 
148822812Smckusick 
148922812Smckusick 
149022812Smckusick 
149122812Smckusick expptr subcheck(np, p)
149222812Smckusick Namep np;
149322812Smckusick register expptr p;
149422812Smckusick {
149522812Smckusick struct Dimblock *dimp;
149622812Smckusick expptr t, checkvar, checkcond, badcall;
149722812Smckusick 
149822812Smckusick dimp = np->vdim;
149922812Smckusick if(dimp->nelt == NULL)
150022812Smckusick 	return(p);	/* don't check arrays with * bounds */
150122812Smckusick checkvar = NULL;
150222812Smckusick checkcond = NULL;
150322812Smckusick if( ISICON(p) )
150422812Smckusick 	{
150522812Smckusick 	if(p->constblock.const.ci < 0)
150622812Smckusick 		goto badsub;
150722812Smckusick 	if( ISICON(dimp->nelt) )
150822812Smckusick 		if(p->constblock.const.ci < dimp->nelt->constblock.const.ci)
150922812Smckusick 			return(p);
151022812Smckusick 		else
151122812Smckusick 			goto badsub;
151222812Smckusick 	}
151322812Smckusick if(p->tag==TADDR && p->addrblock.vstg==STGREG)
151422812Smckusick 	{
151522812Smckusick 	checkvar = (expptr) cpexpr(p);
151622812Smckusick 	t = p;
151722812Smckusick 	}
151822812Smckusick else	{
151922812Smckusick 	checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
152022812Smckusick 	t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
152122812Smckusick 	}
152222812Smckusick checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
152322812Smckusick if( ! ISICON(p) )
152422812Smckusick 	checkcond = mkexpr(OPAND, checkcond,
152522812Smckusick 			mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
152622812Smckusick 
152722812Smckusick badcall = call4(p->headblock.vtype, "s_rnge",
152822812Smckusick 		mkstrcon(VL, np->varname),
152922812Smckusick 		mkconv(TYLONG,  cpexpr(checkvar)),
153022812Smckusick 		mkstrcon(XL, procname),
153122812Smckusick 		ICON(lineno) );
153222812Smckusick badcall->exprblock.opcode = OPCCALL;
153322812Smckusick p = mkexpr(OPQUEST, checkcond,
153422812Smckusick 	mkexpr(OPCOLON, checkvar, badcall));
153522812Smckusick 
153622812Smckusick return(p);
153722812Smckusick 
153822812Smckusick badsub:
153922812Smckusick 	frexpr(p);
154022812Smckusick 	errstr("subscript on variable %s out of range", varstr(VL,np->varname));
154122812Smckusick 	return ( ICON(0) );
154222812Smckusick }
154322812Smckusick 
154422812Smckusick 
154522812Smckusick 
154622812Smckusick 
154722812Smckusick Addrp mkaddr(p)
154822812Smckusick register Namep p;
154922812Smckusick {
155022812Smckusick struct Extsym *extp;
155122812Smckusick register Addrp t;
155222812Smckusick Addrp intraddr();
155322812Smckusick 
155422812Smckusick switch( p->vstg)
155522812Smckusick 	{
155622812Smckusick 	case STGUNKNOWN:
155722812Smckusick 		if(p->vclass != CLPROC)
155822812Smckusick 			break;
155922812Smckusick 		extp = mkext( varunder(VL, p->varname) );
156022812Smckusick 		extp->extstg = STGEXT;
156122812Smckusick 		p->vstg = STGEXT;
156222812Smckusick 		p->vardesc.varno = extp - extsymtab;
156322812Smckusick 		p->vprocclass = PEXTERNAL;
156422812Smckusick 
156522812Smckusick 	case STGCOMMON:
156622812Smckusick 	case STGEXT:
156722812Smckusick 	case STGBSS:
156822812Smckusick 	case STGINIT:
156922812Smckusick 	case STGEQUIV:
157022812Smckusick 	case STGARG:
157122812Smckusick 	case STGLENG:
157222812Smckusick 	case STGAUTO:
157322812Smckusick 		t = ALLOC(Addrblock);
157422812Smckusick 		t->tag = TADDR;
157522812Smckusick 		if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
157622812Smckusick 			t->vclass = CLVAR;
157722812Smckusick 		else
157822812Smckusick 			t->vclass = p->vclass;
157922812Smckusick 		t->vtype = p->vtype;
158022812Smckusick 		t->vstg = p->vstg;
158122812Smckusick 		t->memno = p->vardesc.varno;
158222812Smckusick 		t->issaved = p->vsave;
158322812Smckusick                 if(p->vdim) t->isarray = YES;
158422812Smckusick 		t->memoffset = ICON(p->voffset);
158522812Smckusick 		if(p->vleng)
158622812Smckusick 			{
158722812Smckusick 			t->vleng = (expptr) cpexpr(p->vleng);
158822812Smckusick 			if( ISICON(t->vleng) )
158922812Smckusick 				t->varleng = t->vleng->constblock.const.ci;
159022812Smckusick 			}
159122812Smckusick 		if (p->vstg == STGBSS)
159222812Smckusick 			t->varsize = p->varsize;
159322812Smckusick 		else if (p->vstg == STGEQUIV)
159422812Smckusick 			t->varsize = eqvclass[t->memno].eqvleng;
159522812Smckusick 		return(t);
159622812Smckusick 
159722812Smckusick 	case STGINTR:
159822812Smckusick 		return( intraddr(p) );
159922812Smckusick 
160022812Smckusick 	}
160122812Smckusick /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
160222812Smckusick badstg("mkaddr", p->vstg);
160322812Smckusick /* NOTREACHED */
160422812Smckusick }
160522812Smckusick 
160622812Smckusick 
160722812Smckusick 
160822812Smckusick 
160922812Smckusick Addrp mkarg(type, argno)
161022812Smckusick int type, argno;
161122812Smckusick {
161222812Smckusick register Addrp p;
161322812Smckusick 
161422812Smckusick p = ALLOC(Addrblock);
161522812Smckusick p->tag = TADDR;
161622812Smckusick p->vtype = type;
161722812Smckusick p->vclass = CLVAR;
161822812Smckusick p->vstg = (type==TYLENG ? STGLENG : STGARG);
161922812Smckusick p->memno = argno;
162022812Smckusick return(p);
162122812Smckusick }
162222812Smckusick 
162322812Smckusick 
162422812Smckusick 
162522812Smckusick 
162622812Smckusick expptr mkprim(v, args, substr)
162722812Smckusick register union
162822812Smckusick 	{
162922812Smckusick 	struct Paramblock paramblock;
163022812Smckusick 	struct Nameblock nameblock;
163122812Smckusick 	struct Headblock headblock;
163222812Smckusick 	} *v;
163322812Smckusick struct Listblock *args;
163422812Smckusick chainp substr;
163522812Smckusick {
163622812Smckusick register struct Primblock *p;
163722812Smckusick 
163822812Smckusick if(v->headblock.vclass == CLPARAM)
163922812Smckusick 	{
164022812Smckusick 	if(args || substr)
164122812Smckusick 		{
164222812Smckusick 		errstr("no qualifiers on parameter name %s",
164322812Smckusick 			varstr(VL,v->paramblock.varname));
164422812Smckusick 		frexpr(args);
164522812Smckusick 		if(substr)
164622812Smckusick 			{
164722812Smckusick 			frexpr(substr->datap);
164822812Smckusick 			frexpr(substr->nextp->datap);
164922812Smckusick 			frchain(&substr);
165022812Smckusick 			}
165122812Smckusick 		frexpr(v);
165222812Smckusick 		return( errnode() );
165322812Smckusick 		}
165422812Smckusick 	return( (expptr) cpexpr(v->paramblock.paramval) );
165522812Smckusick 	}
165622812Smckusick 
165722812Smckusick p = ALLOC(Primblock);
165822812Smckusick p->tag = TPRIM;
165922812Smckusick p->vtype = v->nameblock.vtype;
166022812Smckusick p->namep = (Namep) v;
166122812Smckusick p->argsp = args;
166222812Smckusick if(substr)
166322812Smckusick 	{
166423680Smckusick 	p->fcharp = (expptr) substr->datap;
1665*24477Sdonn 	if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
166623680Smckusick 		p->fcharp = mkconv(TYINT, p->fcharp);
166723680Smckusick 	p->lcharp = (expptr) substr->nextp->datap;
1668*24477Sdonn 	if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
166923680Smckusick 		p->lcharp = mkconv(TYINT, p->lcharp);
167022812Smckusick 	frchain(&substr);
167122812Smckusick 	}
167222812Smckusick return( (expptr) p);
167322812Smckusick }
167422812Smckusick 
167522812Smckusick 
167622812Smckusick 
167722812Smckusick vardcl(v)
167822812Smckusick register Namep v;
167922812Smckusick {
168022812Smckusick int nelt;
168122812Smckusick struct Dimblock *t;
168222812Smckusick Addrp p;
168322812Smckusick expptr neltp;
168422812Smckusick int eltsize;
168522812Smckusick int varsize;
168622812Smckusick int tsize;
168722812Smckusick int align;
168822812Smckusick 
168922812Smckusick if(v->vdcldone)
169022812Smckusick 	return;
169122812Smckusick if(v->vclass == CLNAMELIST)
169222812Smckusick 	return;
169322812Smckusick 
169422812Smckusick if(v->vtype == TYUNKNOWN)
169522812Smckusick 	impldcl(v);
169622812Smckusick if(v->vclass == CLUNKNOWN)
169722812Smckusick 	v->vclass = CLVAR;
169822812Smckusick else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
169922812Smckusick 	{
170022812Smckusick 	dclerr("used both as variable and non-variable", v);
170122812Smckusick 	return;
170222812Smckusick 	}
170322812Smckusick if(v->vstg==STGUNKNOWN)
170422812Smckusick 	v->vstg = implstg[ letter(v->varname[0]) ];
170522812Smckusick 
170622812Smckusick switch(v->vstg)
170722812Smckusick 	{
170822812Smckusick 	case STGBSS:
170922812Smckusick 		v->vardesc.varno = ++lastvarno;
171022812Smckusick 		if (v->vclass != CLVAR)
171122812Smckusick 			break;
171222812Smckusick 		nelt = 1;
171322812Smckusick 		t = v->vdim;
171422812Smckusick 		if (t)
171522812Smckusick 			{
171622812Smckusick 			neltp = t->nelt;
171722812Smckusick 			if (neltp && ISICON(neltp))
171822812Smckusick 				nelt = neltp->constblock.const.ci;
171922812Smckusick 			else
172022812Smckusick 				dclerr("improperly dimensioned array", v);
172122812Smckusick 			}
172222812Smckusick 
172322812Smckusick 		if (v->vtype == TYCHAR)
172422812Smckusick 			{
172522812Smckusick 			v->vleng = fixtype(v->vleng);
172622812Smckusick 			if (v->vleng == NULL)
172722812Smckusick 				eltsize = typesize[TYCHAR];
172822812Smckusick 			else if (ISICON(v->vleng))
172922812Smckusick 				eltsize = typesize[TYCHAR] *
173022812Smckusick 					v->vleng->constblock.const.ci;
173122812Smckusick 			else if (v->vleng->tag != TERROR)
173222812Smckusick 				{
173322812Smckusick 				errstr("nonconstant string length on %s",
173422812Smckusick 					varstr(VL, v->varname));
173522812Smckusick 				eltsize = 0;
173622812Smckusick 				}
173722812Smckusick 			}
173822812Smckusick 		else
173922812Smckusick 			eltsize = typesize[v->vtype];
174022812Smckusick 
174122812Smckusick 		v->varsize = nelt * eltsize;
174222812Smckusick 		break;
174322812Smckusick 	case STGAUTO:
174422812Smckusick 		if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
174522812Smckusick 			break;
174622812Smckusick 		nelt = 1;
174722812Smckusick 		if(t = v->vdim)
174822812Smckusick 			if( (neltp = t->nelt) && ISCONST(neltp) )
174922812Smckusick 				nelt = neltp->constblock.const.ci;
175022812Smckusick 			else
175122812Smckusick 				dclerr("adjustable automatic array", v);
175222812Smckusick 		p = autovar(nelt, v->vtype, v->vleng);
175322812Smckusick 		v->vardesc.varno = p->memno;
175422812Smckusick 		v->voffset = p->memoffset->constblock.const.ci;
175522812Smckusick 		frexpr(p);
175622812Smckusick 		break;
175722812Smckusick 
175822812Smckusick 	default:
175922812Smckusick 		break;
176022812Smckusick 	}
176122812Smckusick v->vdcldone = YES;
176222812Smckusick }
176322812Smckusick 
176422812Smckusick 
176522812Smckusick 
176622812Smckusick 
176722812Smckusick impldcl(p)
176822812Smckusick register Namep p;
176922812Smckusick {
177022812Smckusick register int k;
177122812Smckusick int type, leng;
177222812Smckusick 
177322812Smckusick if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
177422812Smckusick 	return;
177522812Smckusick if(p->vtype == TYUNKNOWN)
177622812Smckusick 	{
177722812Smckusick 	k = letter(p->varname[0]);
177822812Smckusick 	type = impltype[ k ];
177922812Smckusick 	leng = implleng[ k ];
178022812Smckusick 	if(type == TYUNKNOWN)
178122812Smckusick 		{
178222812Smckusick 		if(p->vclass == CLPROC)
178323476Smckusick 			dclerr("attempt to use function of undefined type", p);
178423476Smckusick 		else
178523476Smckusick 			dclerr("attempt to use undefined variable", p);
178622812Smckusick 		type = TYERROR;
178722812Smckusick 		leng = 1;
178822812Smckusick 		}
178922812Smckusick 	settype(p, type, leng);
179022812Smckusick 	}
179122812Smckusick }
179222812Smckusick 
179322812Smckusick 
179422812Smckusick 
179522812Smckusick 
179622812Smckusick LOCAL letter(c)
179722812Smckusick register int c;
179822812Smckusick {
179922812Smckusick if( isupper(c) )
180022812Smckusick 	c = tolower(c);
180122812Smckusick return(c - 'a');
180222812Smckusick }
180322812Smckusick 
180422812Smckusick #define ICONEQ(z, c)  (ISICON(z) && z->constblock.const.ci==c)
180522812Smckusick #define COMMUTE	{ e = lp;  lp = rp;  rp = e; }
180622812Smckusick 
180722812Smckusick 
180822812Smckusick expptr mkexpr(opcode, lp, rp)
180922812Smckusick int opcode;
181022812Smckusick register expptr lp, rp;
181122812Smckusick {
181222812Smckusick register expptr e, e1;
181322812Smckusick int etype;
181422812Smckusick int ltype, rtype;
181522812Smckusick int ltag, rtag;
181622812Smckusick expptr q, q1;
181722812Smckusick expptr fold();
181822812Smckusick int k;
181922812Smckusick 
182022812Smckusick ltype = lp->headblock.vtype;
182122812Smckusick ltag = lp->tag;
182222812Smckusick if(rp && opcode!=OPCALL && opcode!=OPCCALL)
182322812Smckusick 	{
182422812Smckusick 	rtype = rp->headblock.vtype;
182522812Smckusick 	rtag = rp->tag;
182622812Smckusick 	}
182722812Smckusick else	{
182822812Smckusick 	rtype = 0;
182922812Smckusick 	rtag = 0;
183022812Smckusick 	}
183122812Smckusick 
183222812Smckusick /*
183322812Smckusick  * Yuck.  Why can't we fold constants AFTER
183422812Smckusick  * variables are implicitly declared???
183522812Smckusick  */
183622812Smckusick if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
183722812Smckusick 	{
183822812Smckusick 	k = letter(lp->primblock.namep->varname[0]);
183922812Smckusick 	ltype = impltype[ k ];
184022812Smckusick 	}
184122812Smckusick if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
184222812Smckusick 	{
184322812Smckusick 	k = letter(rp->primblock.namep->varname[0]);
184422812Smckusick 	rtype = impltype[ k ];
184522812Smckusick 	}
184622812Smckusick 
184722812Smckusick etype = cktype(opcode, ltype, rtype);
184822812Smckusick if(etype == TYERROR)
184922812Smckusick 	goto error;
185022812Smckusick 
185122812Smckusick if(etype != TYUNKNOWN)
185222812Smckusick switch(opcode)
185322812Smckusick 	{
185422812Smckusick 	/* check for multiplication by 0 and 1 and addition to 0 */
185522812Smckusick 
185622812Smckusick 	case OPSTAR:
185722812Smckusick 		if( ISCONST(lp) )
185822812Smckusick 			COMMUTE
185922812Smckusick 
186022812Smckusick 		if( ISICON(rp) )
186122812Smckusick 			{
186222812Smckusick 			if(rp->constblock.const.ci == 0)
186322812Smckusick 				{
186422812Smckusick 				if(etype == TYUNKNOWN)
186522812Smckusick 					break;
186622812Smckusick 				rp = mkconv(etype, rp);
186722812Smckusick 				goto retright;
186822812Smckusick 				}
186922812Smckusick 			if ((lp->tag == TEXPR) &&
187022812Smckusick 			    ((lp->exprblock.opcode == OPPLUS) ||
187122812Smckusick 			     (lp->exprblock.opcode == OPMINUS)) &&
187222812Smckusick 			    ISCONST(lp->exprblock.rightp) &&
187322812Smckusick 			    ISINT(lp->exprblock.rightp->constblock.vtype))
187422812Smckusick 				{
187522812Smckusick 				q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
187622812Smckusick 					   cpexpr(rp));
187722812Smckusick 				q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
187822812Smckusick 				q = mkexpr(lp->exprblock.opcode, q, q1);
187922812Smckusick 				free ((char *) lp);
188022812Smckusick 				return q;
188122812Smckusick 				}
188222812Smckusick 			else
188322812Smckusick 				goto mulop;
188422812Smckusick 			}
188522812Smckusick 		break;
188622812Smckusick 
188722812Smckusick 	case OPSLASH:
188822812Smckusick 	case OPMOD:
188922812Smckusick 		if( ICONEQ(rp, 0) )
189022812Smckusick 			{
189122812Smckusick 			err("attempted division by zero");
189222812Smckusick 			rp = ICON(1);
189322812Smckusick 			break;
189422812Smckusick 			}
189522812Smckusick 		if(opcode == OPMOD)
189622812Smckusick 			break;
189722812Smckusick 
189822812Smckusick 
189922812Smckusick 	mulop:
190022812Smckusick 		if( ISICON(rp) )
190122812Smckusick 			{
190222812Smckusick 			if(rp->constblock.const.ci == 1)
190322812Smckusick 				goto retleft;
190422812Smckusick 
190522812Smckusick 			if(rp->constblock.const.ci == -1)
190622812Smckusick 				{
190722812Smckusick 				frexpr(rp);
190822812Smckusick 				return( mkexpr(OPNEG, lp, PNULL) );
190922812Smckusick 				}
191022812Smckusick 			}
191122812Smckusick 
191222812Smckusick 		if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
191322812Smckusick 			{
191422812Smckusick 			if(opcode == OPSTAR)
191522812Smckusick 				e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
191622812Smckusick 			else  if(ISICON(rp) &&
191722812Smckusick 				(lp->exprblock.rightp->constblock.const.ci %
191822812Smckusick 					rp->constblock.const.ci) == 0)
191922812Smckusick 				e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
192022812Smckusick 			else	break;
192122812Smckusick 
192222812Smckusick 			e1 = lp->exprblock.leftp;
192322812Smckusick 			free( (charptr) lp );
192422812Smckusick 			return( mkexpr(OPSTAR, e1, e) );
192522812Smckusick 			}
192622812Smckusick 		break;
192722812Smckusick 
192822812Smckusick 
192922812Smckusick 	case OPPLUS:
193022812Smckusick 		if( ISCONST(lp) )
193122812Smckusick 			COMMUTE
193222812Smckusick 		goto addop;
193322812Smckusick 
193422812Smckusick 	case OPMINUS:
193522812Smckusick 		if( ICONEQ(lp, 0) )
193622812Smckusick 			{
193722812Smckusick 			frexpr(lp);
193822812Smckusick 			return( mkexpr(OPNEG, rp, ENULL) );
193922812Smckusick 			}
194022812Smckusick 
194122812Smckusick 		if( ISCONST(rp) )
194222812Smckusick 			{
194322812Smckusick 			opcode = OPPLUS;
194422812Smckusick 			consnegop(rp);
194522812Smckusick 			}
194622812Smckusick 
194722812Smckusick 	addop:
194822812Smckusick 		if( ISICON(rp) )
194922812Smckusick 			{
195022812Smckusick 			if(rp->constblock.const.ci == 0)
195122812Smckusick 				goto retleft;
195222812Smckusick 			if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
195322812Smckusick 				{
195422812Smckusick 				e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
195522812Smckusick 				e1 = lp->exprblock.leftp;
195622812Smckusick 				free( (charptr) lp );
195722812Smckusick 				return( mkexpr(OPPLUS, e1, e) );
195822812Smckusick 				}
195922812Smckusick 			}
196022812Smckusick 		break;
196122812Smckusick 
196222812Smckusick 
196322812Smckusick 	case OPPOWER:
196422812Smckusick 		break;
196522812Smckusick 
196622812Smckusick 	case OPNEG:
196722812Smckusick 		if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
196822812Smckusick 			{
196922812Smckusick 			e = lp->exprblock.leftp;
197022812Smckusick 			free( (charptr) lp );
197122812Smckusick 			return(e);
197222812Smckusick 			}
197322812Smckusick 		break;
197422812Smckusick 
197522812Smckusick 	case OPNOT:
197622812Smckusick 		if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
197722812Smckusick 			{
197822812Smckusick 			e = lp->exprblock.leftp;
197922812Smckusick 			free( (charptr) lp );
198022812Smckusick 			return(e);
198122812Smckusick 			}
198222812Smckusick 		break;
198322812Smckusick 
198422812Smckusick 	case OPCALL:
198522812Smckusick 	case OPCCALL:
198622812Smckusick 		etype = ltype;
198722812Smckusick 		if(rp!=NULL && rp->listblock.listp==NULL)
198822812Smckusick 			{
198922812Smckusick 			free( (charptr) rp );
199022812Smckusick 			rp = NULL;
199122812Smckusick 			}
199222812Smckusick 		break;
199322812Smckusick 
199422812Smckusick 	case OPAND:
199522812Smckusick 	case OPOR:
199622812Smckusick 		if( ISCONST(lp) )
199722812Smckusick 			COMMUTE
199822812Smckusick 
199922812Smckusick 		if( ISCONST(rp) )
200022812Smckusick 			{
200122812Smckusick 			if(rp->constblock.const.ci == 0)
200222812Smckusick 				if(opcode == OPOR)
200322812Smckusick 					goto retleft;
200422812Smckusick 				else
200522812Smckusick 					goto retright;
200622812Smckusick 			else if(opcode == OPOR)
200722812Smckusick 				goto retright;
200822812Smckusick 			else
200922812Smckusick 				goto retleft;
201022812Smckusick 			}
201122812Smckusick 	case OPLSHIFT:
201222812Smckusick 		if (ISICON(rp))
201322812Smckusick 			{
201422812Smckusick 			if (rp->constblock.const.ci == 0)
201522812Smckusick 				goto retleft;
201622812Smckusick 			if ((lp->tag == TEXPR) &&
201722812Smckusick 			    ((lp->exprblock.opcode == OPPLUS) ||
201822812Smckusick 			     (lp->exprblock.opcode == OPMINUS)) &&
201922812Smckusick 			    ISICON(lp->exprblock.rightp))
202022812Smckusick 				{
202122812Smckusick 				q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
202222812Smckusick 					cpexpr(rp));
202322812Smckusick 				q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
202422812Smckusick 				q = mkexpr(lp->exprblock.opcode, q, q1);
202522812Smckusick 				free((char *) lp);
202622812Smckusick 				return q;
202722812Smckusick 				}
202822812Smckusick 			}
202922812Smckusick 
203022812Smckusick 	case OPEQV:
203122812Smckusick 	case OPNEQV:
203222812Smckusick 
203322812Smckusick 	case OPBITAND:
203422812Smckusick 	case OPBITOR:
203522812Smckusick 	case OPBITXOR:
203622812Smckusick 	case OPBITNOT:
203722812Smckusick 	case OPRSHIFT:
203822812Smckusick 
203922812Smckusick 	case OPLT:
204022812Smckusick 	case OPGT:
204122812Smckusick 	case OPLE:
204222812Smckusick 	case OPGE:
204322812Smckusick 	case OPEQ:
204422812Smckusick 	case OPNE:
204522812Smckusick 
204622812Smckusick 	case OPCONCAT:
204722812Smckusick 		break;
204822812Smckusick 	case OPMIN:
204922812Smckusick 	case OPMAX:
205022812Smckusick 
205122812Smckusick 	case OPASSIGN:
205222812Smckusick 	case OPPLUSEQ:
205322812Smckusick 	case OPSTAREQ:
205422812Smckusick 
205522812Smckusick 	case OPCONV:
205622812Smckusick 	case OPADDR:
205722812Smckusick 
205822812Smckusick 	case OPCOMMA:
205922812Smckusick 	case OPQUEST:
206022812Smckusick 	case OPCOLON:
206122812Smckusick 
206222812Smckusick 	case OPPAREN:
206322812Smckusick 		break;
206422812Smckusick 
206522812Smckusick 	default:
206622812Smckusick 		badop("mkexpr", opcode);
206722812Smckusick 	}
206822812Smckusick 
206922812Smckusick e = (expptr) ALLOC(Exprblock);
207022812Smckusick e->exprblock.tag = TEXPR;
207122812Smckusick e->exprblock.opcode = opcode;
207222812Smckusick e->exprblock.vtype = etype;
207322812Smckusick e->exprblock.leftp = lp;
207422812Smckusick e->exprblock.rightp = rp;
207522812Smckusick if(ltag==TCONST && (rp==0 || rtag==TCONST) )
207622812Smckusick 	e = fold(e);
207722812Smckusick return(e);
207822812Smckusick 
207922812Smckusick retleft:
208022812Smckusick 	frexpr(rp);
208122812Smckusick 	return(lp);
208222812Smckusick 
208322812Smckusick retright:
208422812Smckusick 	frexpr(lp);
208522812Smckusick 	return(rp);
208622812Smckusick 
208722812Smckusick error:
208822812Smckusick 	frexpr(lp);
208922812Smckusick 	if(rp && opcode!=OPCALL && opcode!=OPCCALL)
209022812Smckusick 		frexpr(rp);
209122812Smckusick 	return( errnode() );
209222812Smckusick }
209322812Smckusick 
209422812Smckusick #define ERR(s)   { errs = s; goto error; }
209522812Smckusick 
209622812Smckusick cktype(op, lt, rt)
209722812Smckusick register int op, lt, rt;
209822812Smckusick {
209922812Smckusick char *errs;
210022812Smckusick 
210122812Smckusick if(lt==TYERROR || rt==TYERROR)
210222812Smckusick 	goto error1;
210322812Smckusick 
210422812Smckusick if(lt==TYUNKNOWN)
210522812Smckusick 	return(TYUNKNOWN);
210622812Smckusick if(rt==TYUNKNOWN)
210722812Smckusick 	if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
210822812Smckusick 	    op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
210922812Smckusick 		return(TYUNKNOWN);
211022812Smckusick 
211122812Smckusick switch(op)
211222812Smckusick 	{
211322812Smckusick 	case OPPLUS:
211422812Smckusick 	case OPMINUS:
211522812Smckusick 	case OPSTAR:
211622812Smckusick 	case OPSLASH:
211722812Smckusick 	case OPPOWER:
211822812Smckusick 	case OPMOD:
211922812Smckusick 		if( ISNUMERIC(lt) && ISNUMERIC(rt) )
212022812Smckusick 			return( maxtype(lt, rt) );
212122812Smckusick 		ERR("nonarithmetic operand of arithmetic operator")
212222812Smckusick 
212322812Smckusick 	case OPNEG:
212422812Smckusick 		if( ISNUMERIC(lt) )
212522812Smckusick 			return(lt);
212622812Smckusick 		ERR("nonarithmetic operand of negation")
212722812Smckusick 
212822812Smckusick 	case OPNOT:
212922812Smckusick 		if(lt == TYLOGICAL)
213022812Smckusick 			return(TYLOGICAL);
213122812Smckusick 		ERR("NOT of nonlogical")
213222812Smckusick 
213322812Smckusick 	case OPAND:
213422812Smckusick 	case OPOR:
213522812Smckusick 	case OPEQV:
213622812Smckusick 	case OPNEQV:
213722812Smckusick 		if(lt==TYLOGICAL && rt==TYLOGICAL)
213822812Smckusick 			return(TYLOGICAL);
213922812Smckusick 		ERR("nonlogical operand of logical operator")
214022812Smckusick 
214122812Smckusick 	case OPLT:
214222812Smckusick 	case OPGT:
214322812Smckusick 	case OPLE:
214422812Smckusick 	case OPGE:
214522812Smckusick 	case OPEQ:
214622812Smckusick 	case OPNE:
214722812Smckusick 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
214822812Smckusick 			{
214922812Smckusick 			if(lt != rt)
215022812Smckusick 				ERR("illegal comparison")
215122812Smckusick 			}
215222812Smckusick 
215322812Smckusick 		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
215422812Smckusick 			{
215522812Smckusick 			if(op!=OPEQ && op!=OPNE)
215622812Smckusick 				ERR("order comparison of complex data")
215722812Smckusick 			}
215822812Smckusick 
215922812Smckusick 		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
216022812Smckusick 			ERR("comparison of nonarithmetic data")
216122812Smckusick 		return(TYLOGICAL);
216222812Smckusick 
216322812Smckusick 	case OPCONCAT:
216422812Smckusick 		if(lt==TYCHAR && rt==TYCHAR)
216522812Smckusick 			return(TYCHAR);
216622812Smckusick 		ERR("concatenation of nonchar data")
216722812Smckusick 
216822812Smckusick 	case OPCALL:
216922812Smckusick 	case OPCCALL:
217022812Smckusick 		return(lt);
217122812Smckusick 
217222812Smckusick 	case OPADDR:
217322812Smckusick 		return(TYADDR);
217422812Smckusick 
217522812Smckusick 	case OPCONV:
217622812Smckusick 		if(ISCOMPLEX(lt))
217722812Smckusick 			{
217822812Smckusick 			if(ISNUMERIC(rt))
217922812Smckusick 				return(lt);
218022812Smckusick 			ERR("impossible conversion")
218122812Smckusick 			}
218222812Smckusick 		if(rt == 0)
218322812Smckusick 			return(0);
218422812Smckusick 		if(lt==TYCHAR && ISINT(rt) )
218522812Smckusick 			return(TYCHAR);
218622812Smckusick 	case OPASSIGN:
218722812Smckusick 	case OPPLUSEQ:
218822812Smckusick 	case OPSTAREQ:
218922812Smckusick 		if( ISINT(lt) && rt==TYCHAR)
219022812Smckusick 			return(lt);
219122812Smckusick 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
219222812Smckusick 			if(op!=OPASSIGN || lt!=rt)
219322812Smckusick 				{
219422812Smckusick /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
219522812Smckusick /* debug fatal("impossible conversion.  possible compiler bug"); */
219622812Smckusick 				ERR("impossible conversion")
219722812Smckusick 				}
219822812Smckusick 		return(lt);
219922812Smckusick 
220022812Smckusick 	case OPMIN:
220122812Smckusick 	case OPMAX:
220222812Smckusick 	case OPBITOR:
220322812Smckusick 	case OPBITAND:
220422812Smckusick 	case OPBITXOR:
220522812Smckusick 	case OPBITNOT:
220622812Smckusick 	case OPLSHIFT:
220722812Smckusick 	case OPRSHIFT:
220822812Smckusick 	case OPPAREN:
220922812Smckusick 		return(lt);
221022812Smckusick 
221122812Smckusick 	case OPCOMMA:
221222812Smckusick 	case OPQUEST:
221322812Smckusick 	case OPCOLON:
221422812Smckusick 		return(rt);
221522812Smckusick 
221622812Smckusick 	default:
221722812Smckusick 		badop("cktype", op);
221822812Smckusick 	}
221922812Smckusick error:	err(errs);
222022812Smckusick error1:	return(TYERROR);
222122812Smckusick }
222222812Smckusick 
222322812Smckusick LOCAL expptr fold(e)
222422812Smckusick register expptr e;
222522812Smckusick {
222622812Smckusick Constp p;
222722812Smckusick register expptr lp, rp;
222822812Smckusick int etype, mtype, ltype, rtype, opcode;
222922812Smckusick int i, ll, lr;
223022812Smckusick char *q, *s;
223122812Smckusick union Constant lcon, rcon;
223222812Smckusick 
223322812Smckusick opcode = e->exprblock.opcode;
223422812Smckusick etype = e->exprblock.vtype;
223522812Smckusick 
223622812Smckusick lp = e->exprblock.leftp;
223722812Smckusick ltype = lp->headblock.vtype;
223822812Smckusick rp = e->exprblock.rightp;
223922812Smckusick 
224022812Smckusick if(rp == 0)
224122812Smckusick 	switch(opcode)
224222812Smckusick 		{
224322812Smckusick 		case OPNOT:
224422812Smckusick 			lp->constblock.const.ci = ! lp->constblock.const.ci;
224522812Smckusick 			return(lp);
224622812Smckusick 
224722812Smckusick 		case OPBITNOT:
224822812Smckusick 			lp->constblock.const.ci = ~ lp->constblock.const.ci;
224922812Smckusick 			return(lp);
225022812Smckusick 
225122812Smckusick 		case OPNEG:
225222812Smckusick 			consnegop(lp);
225322812Smckusick 			return(lp);
225422812Smckusick 
225522812Smckusick 		case OPCONV:
225622812Smckusick 		case OPADDR:
225722812Smckusick 		case OPPAREN:
225822812Smckusick 			return(e);
225922812Smckusick 
226022812Smckusick 		default:
226122812Smckusick 			badop("fold", opcode);
226222812Smckusick 		}
226322812Smckusick 
226422812Smckusick rtype = rp->headblock.vtype;
226522812Smckusick 
226622812Smckusick p = ALLOC(Constblock);
226722812Smckusick p->tag = TCONST;
226822812Smckusick p->vtype = etype;
226922812Smckusick p->vleng = e->exprblock.vleng;
227022812Smckusick 
227122812Smckusick switch(opcode)
227222812Smckusick 	{
227322812Smckusick 	case OPCOMMA:
227422812Smckusick 	case OPQUEST:
227522812Smckusick 	case OPCOLON:
227622812Smckusick 		return(e);
227722812Smckusick 
227822812Smckusick 	case OPAND:
227922812Smckusick 		p->const.ci = lp->constblock.const.ci &&
228022812Smckusick 				rp->constblock.const.ci;
228122812Smckusick 		break;
228222812Smckusick 
228322812Smckusick 	case OPOR:
228422812Smckusick 		p->const.ci = lp->constblock.const.ci ||
228522812Smckusick 				rp->constblock.const.ci;
228622812Smckusick 		break;
228722812Smckusick 
228822812Smckusick 	case OPEQV:
228922812Smckusick 		p->const.ci = lp->constblock.const.ci ==
229022812Smckusick 				rp->constblock.const.ci;
229122812Smckusick 		break;
229222812Smckusick 
229322812Smckusick 	case OPNEQV:
229422812Smckusick 		p->const.ci = lp->constblock.const.ci !=
229522812Smckusick 				rp->constblock.const.ci;
229622812Smckusick 		break;
229722812Smckusick 
229822812Smckusick 	case OPBITAND:
229922812Smckusick 		p->const.ci = lp->constblock.const.ci &
230022812Smckusick 				rp->constblock.const.ci;
230122812Smckusick 		break;
230222812Smckusick 
230322812Smckusick 	case OPBITOR:
230422812Smckusick 		p->const.ci = lp->constblock.const.ci |
230522812Smckusick 				rp->constblock.const.ci;
230622812Smckusick 		break;
230722812Smckusick 
230822812Smckusick 	case OPBITXOR:
230922812Smckusick 		p->const.ci = lp->constblock.const.ci ^
231022812Smckusick 				rp->constblock.const.ci;
231122812Smckusick 		break;
231222812Smckusick 
231322812Smckusick 	case OPLSHIFT:
231422812Smckusick 		p->const.ci = lp->constblock.const.ci <<
231522812Smckusick 				rp->constblock.const.ci;
231622812Smckusick 		break;
231722812Smckusick 
231822812Smckusick 	case OPRSHIFT:
231922812Smckusick 		p->const.ci = lp->constblock.const.ci >>
232022812Smckusick 				rp->constblock.const.ci;
232122812Smckusick 		break;
232222812Smckusick 
232322812Smckusick 	case OPCONCAT:
232422812Smckusick 		ll = lp->constblock.vleng->constblock.const.ci;
232522812Smckusick 		lr = rp->constblock.vleng->constblock.const.ci;
232622812Smckusick 		p->const.ccp = q = (char *) ckalloc(ll+lr);
232722812Smckusick 		p->vleng = ICON(ll+lr);
232822812Smckusick 		s = lp->constblock.const.ccp;
232922812Smckusick 		for(i = 0 ; i < ll ; ++i)
233022812Smckusick 			*q++ = *s++;
233122812Smckusick 		s = rp->constblock.const.ccp;
233222812Smckusick 		for(i = 0; i < lr; ++i)
233322812Smckusick 			*q++ = *s++;
233422812Smckusick 		break;
233522812Smckusick 
233622812Smckusick 
233722812Smckusick 	case OPPOWER:
233822812Smckusick 		if( ! ISINT(rtype) )
233922812Smckusick 			return(e);
234022812Smckusick 		conspower(&(p->const), lp, rp->constblock.const.ci);
234122812Smckusick 		break;
234222812Smckusick 
234322812Smckusick 
234422812Smckusick 	default:
234522812Smckusick 		if(ltype == TYCHAR)
234622812Smckusick 			{
234722812Smckusick 			lcon.ci = cmpstr(lp->constblock.const.ccp,
234822812Smckusick 					rp->constblock.const.ccp,
234922812Smckusick 					lp->constblock.vleng->constblock.const.ci,
235022812Smckusick 					rp->constblock.vleng->constblock.const.ci);
235122812Smckusick 			rcon.ci = 0;
235222812Smckusick 			mtype = tyint;
235322812Smckusick 			}
235422812Smckusick 		else	{
235522812Smckusick 			mtype = maxtype(ltype, rtype);
235622812Smckusick 			consconv(mtype, &lcon, ltype, &(lp->constblock.const) );
235722812Smckusick 			consconv(mtype, &rcon, rtype, &(rp->constblock.const) );
235822812Smckusick 			}
235922812Smckusick 		consbinop(opcode, mtype, &(p->const), &lcon, &rcon);
236022812Smckusick 		break;
236122812Smckusick 	}
236222812Smckusick 
236322812Smckusick frexpr(e);
236422812Smckusick return( (expptr) p );
236522812Smckusick }
236622812Smckusick 
236722812Smckusick 
236822812Smckusick 
236922812Smckusick /* assign constant l = r , doing coercion */
237022812Smckusick 
237122812Smckusick consconv(lt, lv, rt, rv)
237222812Smckusick int lt, rt;
237322812Smckusick register union Constant *lv, *rv;
237422812Smckusick {
237522812Smckusick switch(lt)
237622812Smckusick 	{
237722812Smckusick 	case TYCHAR:
237822812Smckusick 		*(lv->ccp = (char *) ckalloc(1)) = rv->ci;
237922812Smckusick 		break;
238022812Smckusick 
238122812Smckusick 	case TYSHORT:
238222812Smckusick 	case TYLONG:
238322812Smckusick 		if(rt == TYCHAR)
238422812Smckusick 			lv->ci = rv->ccp[0];
238522812Smckusick 		else if( ISINT(rt) )
238622812Smckusick 			lv->ci = rv->ci;
238722812Smckusick 		else	lv->ci = rv->cd[0];
238822812Smckusick 		break;
238922812Smckusick 
239022812Smckusick 	case TYCOMPLEX:
239122812Smckusick 	case TYDCOMPLEX:
239222812Smckusick 		switch(rt)
239322812Smckusick 			{
239422812Smckusick 			case TYSHORT:
239522812Smckusick 			case TYLONG:
239622812Smckusick 				/* fall through and do real assignment of
239722812Smckusick 				   first element
239822812Smckusick 				*/
239922812Smckusick 			case TYREAL:
240022812Smckusick 			case TYDREAL:
240122812Smckusick 				lv->cd[1] = 0; break;
240222812Smckusick 			case TYCOMPLEX:
240322812Smckusick 			case TYDCOMPLEX:
240422812Smckusick 				lv->cd[1] = rv->cd[1]; break;
240522812Smckusick 			}
240622812Smckusick 
240722812Smckusick 	case TYREAL:
240822812Smckusick 	case TYDREAL:
240922812Smckusick 		if( ISINT(rt) )
241022812Smckusick 			lv->cd[0] = rv->ci;
241122812Smckusick 		else	lv->cd[0] = rv->cd[0];
241222812Smckusick 		if( lt == TYREAL)
241322812Smckusick 			{
241422812Smckusick 			float f = lv->cd[0];
241522812Smckusick 			lv->cd[0] = f;
241622812Smckusick 			}
241722812Smckusick 		break;
241822812Smckusick 
241922812Smckusick 	case TYLOGICAL:
242022812Smckusick 		lv->ci = rv->ci;
242122812Smckusick 		break;
242222812Smckusick 	}
242322812Smckusick }
242422812Smckusick 
242522812Smckusick 
242622812Smckusick 
242722812Smckusick consnegop(p)
242822812Smckusick register Constp p;
242922812Smckusick {
243022812Smckusick switch(p->vtype)
243122812Smckusick 	{
243222812Smckusick 	case TYSHORT:
243322812Smckusick 	case TYLONG:
243422812Smckusick 		p->const.ci = - p->const.ci;
243522812Smckusick 		break;
243622812Smckusick 
243722812Smckusick 	case TYCOMPLEX:
243822812Smckusick 	case TYDCOMPLEX:
243922812Smckusick 		p->const.cd[1] = - p->const.cd[1];
244022812Smckusick 		/* fall through and do the real parts */
244122812Smckusick 	case TYREAL:
244222812Smckusick 	case TYDREAL:
244322812Smckusick 		p->const.cd[0] = - p->const.cd[0];
244422812Smckusick 		break;
244522812Smckusick 	default:
244622812Smckusick 		badtype("consnegop", p->vtype);
244722812Smckusick 	}
244822812Smckusick }
244922812Smckusick 
245022812Smckusick 
245122812Smckusick 
245222812Smckusick LOCAL conspower(powp, ap, n)
245322812Smckusick register union Constant *powp;
245422812Smckusick Constp ap;
245522812Smckusick ftnint n;
245622812Smckusick {
245722812Smckusick register int type;
245822812Smckusick union Constant x;
245922812Smckusick 
246022812Smckusick switch(type = ap->vtype)	/* pow = 1 */
246122812Smckusick 	{
246222812Smckusick 	case TYSHORT:
246322812Smckusick 	case TYLONG:
246422812Smckusick 		powp->ci = 1;
246522812Smckusick 		break;
246622812Smckusick 	case TYCOMPLEX:
246722812Smckusick 	case TYDCOMPLEX:
246822812Smckusick 		powp->cd[1] = 0;
246922812Smckusick 	case TYREAL:
247022812Smckusick 	case TYDREAL:
247122812Smckusick 		powp->cd[0] = 1;
247222812Smckusick 		break;
247322812Smckusick 	default:
247422812Smckusick 		badtype("conspower", type);
247522812Smckusick 	}
247622812Smckusick 
247722812Smckusick if(n == 0)
247822812Smckusick 	return;
247922812Smckusick if(n < 0)
248022812Smckusick 	{
248122812Smckusick 	if( ISINT(type) )
248222812Smckusick 		{
248322812Smckusick 		if (ap->const.ci == 0)
248422812Smckusick 			err("zero raised to a negative power");
248522812Smckusick 		else if (ap->const.ci == 1)
248622812Smckusick 			return;
248722812Smckusick 		else if (ap->const.ci == -1)
248822812Smckusick 			{
248922812Smckusick 			if (n < -2)
249022812Smckusick 				n = n + 2;
249122812Smckusick 			n = -n;
249222812Smckusick 			if (n % 2 == 1)
249322812Smckusick 				powp->ci = -1;
249422812Smckusick 			}
249522812Smckusick 		else
249622812Smckusick 			powp->ci = 0;
249722812Smckusick 		return;
249822812Smckusick 		}
249922812Smckusick 	n = - n;
250022812Smckusick 	consbinop(OPSLASH, type, &x, powp, &(ap->const));
250122812Smckusick 	}
250222812Smckusick else
250322812Smckusick 	consbinop(OPSTAR, type, &x, powp, &(ap->const));
250422812Smckusick 
250522812Smckusick for( ; ; )
250622812Smckusick 	{
250722812Smckusick 	if(n & 01)
250822812Smckusick 		consbinop(OPSTAR, type, powp, powp, &x);
250922812Smckusick 	if(n >>= 1)
251022812Smckusick 		consbinop(OPSTAR, type, &x, &x, &x);
251122812Smckusick 	else
251222812Smckusick 		break;
251322812Smckusick 	}
251422812Smckusick }
251522812Smckusick 
251622812Smckusick 
251722812Smckusick 
251822812Smckusick /* do constant operation cp = a op b */
251922812Smckusick 
252022812Smckusick 
252122812Smckusick LOCAL consbinop(opcode, type, cp, ap, bp)
252222812Smckusick int opcode, type;
252322812Smckusick register union Constant *ap, *bp, *cp;
252422812Smckusick {
252522812Smckusick int k;
252622812Smckusick double temp;
252722812Smckusick 
252822812Smckusick switch(opcode)
252922812Smckusick 	{
253022812Smckusick 	case OPPLUS:
253122812Smckusick 		switch(type)
253222812Smckusick 			{
253322812Smckusick 			case TYSHORT:
253422812Smckusick 			case TYLONG:
253522812Smckusick 				cp->ci = ap->ci + bp->ci;
253622812Smckusick 				break;
253722812Smckusick 			case TYCOMPLEX:
253822812Smckusick 			case TYDCOMPLEX:
253922812Smckusick 				cp->cd[1] = ap->cd[1] + bp->cd[1];
254022812Smckusick 			case TYREAL:
254122812Smckusick 			case TYDREAL:
254222812Smckusick 				cp->cd[0] = ap->cd[0] + bp->cd[0];
254322812Smckusick 				break;
254422812Smckusick 			}
254522812Smckusick 		break;
254622812Smckusick 
254722812Smckusick 	case OPMINUS:
254822812Smckusick 		switch(type)
254922812Smckusick 			{
255022812Smckusick 			case TYSHORT:
255122812Smckusick 			case TYLONG:
255222812Smckusick 				cp->ci = ap->ci - bp->ci;
255322812Smckusick 				break;
255422812Smckusick 			case TYCOMPLEX:
255522812Smckusick 			case TYDCOMPLEX:
255622812Smckusick 				cp->cd[1] = ap->cd[1] - bp->cd[1];
255722812Smckusick 			case TYREAL:
255822812Smckusick 			case TYDREAL:
255922812Smckusick 				cp->cd[0] = ap->cd[0] - bp->cd[0];
256022812Smckusick 				break;
256122812Smckusick 			}
256222812Smckusick 		break;
256322812Smckusick 
256422812Smckusick 	case OPSTAR:
256522812Smckusick 		switch(type)
256622812Smckusick 			{
256722812Smckusick 			case TYSHORT:
256822812Smckusick 			case TYLONG:
256922812Smckusick 				cp->ci = ap->ci * bp->ci;
257022812Smckusick 				break;
257122812Smckusick 			case TYREAL:
257222812Smckusick 			case TYDREAL:
257322812Smckusick 				cp->cd[0] = ap->cd[0] * bp->cd[0];
257422812Smckusick 				break;
257522812Smckusick 			case TYCOMPLEX:
257622812Smckusick 			case TYDCOMPLEX:
257722812Smckusick 				temp = ap->cd[0] * bp->cd[0] -
257822812Smckusick 					    ap->cd[1] * bp->cd[1] ;
257922812Smckusick 				cp->cd[1] = ap->cd[0] * bp->cd[1] +
258022812Smckusick 					    ap->cd[1] * bp->cd[0] ;
258122812Smckusick 				cp->cd[0] = temp;
258222812Smckusick 				break;
258322812Smckusick 			}
258422812Smckusick 		break;
258522812Smckusick 	case OPSLASH:
258622812Smckusick 		switch(type)
258722812Smckusick 			{
258822812Smckusick 			case TYSHORT:
258922812Smckusick 			case TYLONG:
259022812Smckusick 				cp->ci = ap->ci / bp->ci;
259122812Smckusick 				break;
259222812Smckusick 			case TYREAL:
259322812Smckusick 			case TYDREAL:
259422812Smckusick 				cp->cd[0] = ap->cd[0] / bp->cd[0];
259522812Smckusick 				break;
259622812Smckusick 			case TYCOMPLEX:
259722812Smckusick 			case TYDCOMPLEX:
259822812Smckusick 				zdiv(cp,ap,bp);
259922812Smckusick 				break;
260022812Smckusick 			}
260122812Smckusick 		break;
260222812Smckusick 
260322812Smckusick 	case OPMOD:
260422812Smckusick 		if( ISINT(type) )
260522812Smckusick 			{
260622812Smckusick 			cp->ci = ap->ci % bp->ci;
260722812Smckusick 			break;
260822812Smckusick 			}
260922812Smckusick 		else
261022812Smckusick 			fatal("inline mod of noninteger");
261122812Smckusick 
261222812Smckusick 	default:	  /* relational ops */
261322812Smckusick 		switch(type)
261422812Smckusick 			{
261522812Smckusick 			case TYSHORT:
261622812Smckusick 			case TYLONG:
261722812Smckusick 				if(ap->ci < bp->ci)
261822812Smckusick 					k = -1;
261922812Smckusick 				else if(ap->ci == bp->ci)
262022812Smckusick 					k = 0;
262122812Smckusick 				else	k = 1;
262222812Smckusick 				break;
262322812Smckusick 			case TYREAL:
262422812Smckusick 			case TYDREAL:
262522812Smckusick 				if(ap->cd[0] < bp->cd[0])
262622812Smckusick 					k = -1;
262722812Smckusick 				else if(ap->cd[0] == bp->cd[0])
262822812Smckusick 					k = 0;
262922812Smckusick 				else	k = 1;
263022812Smckusick 				break;
263122812Smckusick 			case TYCOMPLEX:
263222812Smckusick 			case TYDCOMPLEX:
263322812Smckusick 				if(ap->cd[0] == bp->cd[0] &&
263422812Smckusick 				   ap->cd[1] == bp->cd[1] )
263522812Smckusick 					k = 0;
263622812Smckusick 				else	k = 1;
263722812Smckusick 				break;
263822812Smckusick 			}
263922812Smckusick 
264022812Smckusick 		switch(opcode)
264122812Smckusick 			{
264222812Smckusick 			case OPEQ:
264322812Smckusick 				cp->ci = (k == 0);
264422812Smckusick 				break;
264522812Smckusick 			case OPNE:
264622812Smckusick 				cp->ci = (k != 0);
264722812Smckusick 				break;
264822812Smckusick 			case OPGT:
264922812Smckusick 				cp->ci = (k == 1);
265022812Smckusick 				break;
265122812Smckusick 			case OPLT:
265222812Smckusick 				cp->ci = (k == -1);
265322812Smckusick 				break;
265422812Smckusick 			case OPGE:
265522812Smckusick 				cp->ci = (k >= 0);
265622812Smckusick 				break;
265722812Smckusick 			case OPLE:
265822812Smckusick 				cp->ci = (k <= 0);
265922812Smckusick 				break;
266022812Smckusick 			default:
266122812Smckusick 				badop ("consbinop", opcode);
266222812Smckusick 			}
266322812Smckusick 		break;
266422812Smckusick 	}
266522812Smckusick }
266622812Smckusick 
266722812Smckusick 
266822812Smckusick 
266922812Smckusick 
267022812Smckusick conssgn(p)
267122812Smckusick register expptr p;
267222812Smckusick {
267322812Smckusick if( ! ISCONST(p) )
267422812Smckusick 	fatal( "sgn(nonconstant)" );
267522812Smckusick 
267622812Smckusick switch(p->headblock.vtype)
267722812Smckusick 	{
267822812Smckusick 	case TYSHORT:
267922812Smckusick 	case TYLONG:
268022812Smckusick 		if(p->constblock.const.ci > 0) return(1);
268122812Smckusick 		if(p->constblock.const.ci < 0) return(-1);
268222812Smckusick 		return(0);
268322812Smckusick 
268422812Smckusick 	case TYREAL:
268522812Smckusick 	case TYDREAL:
268622812Smckusick 		if(p->constblock.const.cd[0] > 0) return(1);
268722812Smckusick 		if(p->constblock.const.cd[0] < 0) return(-1);
268822812Smckusick 		return(0);
268922812Smckusick 
269022812Smckusick 	case TYCOMPLEX:
269122812Smckusick 	case TYDCOMPLEX:
269222812Smckusick 		return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0);
269322812Smckusick 
269422812Smckusick 	default:
269522812Smckusick 		badtype( "conssgn", p->constblock.vtype);
269622812Smckusick 	}
269722812Smckusick /* NOTREACHED */
269822812Smckusick }
269922812Smckusick 
270022812Smckusick char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
270122812Smckusick 
270222812Smckusick 
270322812Smckusick LOCAL expptr mkpower(p)
270422812Smckusick register expptr p;
270522812Smckusick {
270622812Smckusick register expptr q, lp, rp;
270722812Smckusick int ltype, rtype, mtype;
2708*24477Sdonn struct Listblock *args, *mklist();
2709*24477Sdonn Addrp ap;
271022812Smckusick 
271122812Smckusick lp = p->exprblock.leftp;
271222812Smckusick rp = p->exprblock.rightp;
271322812Smckusick ltype = lp->headblock.vtype;
271422812Smckusick rtype = rp->headblock.vtype;
271522812Smckusick 
271622812Smckusick if(ISICON(rp))
271722812Smckusick 	{
271822812Smckusick 	if(rp->constblock.const.ci == 0)
271922812Smckusick 		{
272022812Smckusick 		frexpr(p);
272122812Smckusick 		if( ISINT(ltype) )
272222812Smckusick 			return( ICON(1) );
272322812Smckusick 		else
272422812Smckusick 			{
272522812Smckusick 			expptr pp;
272622812Smckusick 			pp = mkconv(ltype, ICON(1));
272722812Smckusick 			return( pp );
272822812Smckusick 			}
272922812Smckusick 		}
273022812Smckusick 	if(rp->constblock.const.ci < 0)
273122812Smckusick 		{
273222812Smckusick 		if( ISINT(ltype) )
273322812Smckusick 			{
273422812Smckusick 			frexpr(p);
273522812Smckusick 			err("integer**negative");
273622812Smckusick 			return( errnode() );
273722812Smckusick 			}
273822812Smckusick 		rp->constblock.const.ci = - rp->constblock.const.ci;
273922812Smckusick 		p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
274022812Smckusick 		}
274122812Smckusick 	if(rp->constblock.const.ci == 1)
274222812Smckusick 		{
274322812Smckusick 		frexpr(rp);
274422812Smckusick 		free( (charptr) p );
274522812Smckusick 		return(lp);
274622812Smckusick 		}
274722812Smckusick 
274822812Smckusick 	if( ONEOF(ltype, MSKINT|MSKREAL) )
274922812Smckusick 		{
275022812Smckusick 		p->exprblock.vtype = ltype;
275122812Smckusick 		return(p);
275222812Smckusick 		}
275322812Smckusick 	}
275422812Smckusick if( ISINT(rtype) )
275522812Smckusick 	{
275622812Smckusick 	if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
275722812Smckusick 		q = call2(TYSHORT, "pow_hh", lp, rp);
275822812Smckusick 	else	{
275922812Smckusick 		if(ltype == TYSHORT)
276022812Smckusick 			{
276122812Smckusick 			ltype = TYLONG;
276222812Smckusick 			lp = mkconv(TYLONG,lp);
276322812Smckusick 			}
276422812Smckusick 		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
276522812Smckusick 		}
276622812Smckusick 	}
276722812Smckusick else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
2768*24477Sdonn 	{
2769*24477Sdonn 	args = mklist( mkchain( mkconv(TYDREAL,lp), mkchain( mkconv(TYDREAL,rp), CHNULL ) ) );
2770*24477Sdonn 	fixargs(YES, args );
2771*24477Sdonn 	ap = builtin( TYDREAL, "pow" );
2772*24477Sdonn 	ap->vstg = STGINTR;
2773*24477Sdonn 	q = fixexpr( mkexpr(OPCCALL, ap, args ));
2774*24477Sdonn 	q->exprblock.vtype = mtype;
2775*24477Sdonn 	}
277622812Smckusick else	{
277722812Smckusick 	q  = call2(TYDCOMPLEX, "pow_zz",
277822812Smckusick 		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
277922812Smckusick 	if(mtype == TYCOMPLEX)
278022812Smckusick 		q = mkconv(TYCOMPLEX, q);
278122812Smckusick 	}
278222812Smckusick free( (charptr) p );
278322812Smckusick return(q);
278422812Smckusick }
278522812Smckusick 
278622812Smckusick 
278722812Smckusick 
278822812Smckusick /* Complex Division.  Same code as in Runtime Library
278922812Smckusick */
279022812Smckusick 
279122812Smckusick struct dcomplex { double dreal, dimag; };
279222812Smckusick 
279322812Smckusick 
279422812Smckusick LOCAL zdiv(c, a, b)
279522812Smckusick register struct dcomplex *a, *b, *c;
279622812Smckusick {
279722812Smckusick double ratio, den;
279822812Smckusick double abr, abi;
279922812Smckusick 
280022812Smckusick if( (abr = b->dreal) < 0.)
280122812Smckusick 	abr = - abr;
280222812Smckusick if( (abi = b->dimag) < 0.)
280322812Smckusick 	abi = - abi;
280422812Smckusick if( abr <= abi )
280522812Smckusick 	{
280622812Smckusick 	if(abi == 0)
280722812Smckusick 		fatal("complex division by zero");
280822812Smckusick 	ratio = b->dreal / b->dimag ;
280922812Smckusick 	den = b->dimag * (1 + ratio*ratio);
281022812Smckusick 	c->dreal = (a->dreal*ratio + a->dimag) / den;
281122812Smckusick 	c->dimag = (a->dimag*ratio - a->dreal) / den;
281222812Smckusick 	}
281322812Smckusick 
281422812Smckusick else
281522812Smckusick 	{
281622812Smckusick 	ratio = b->dimag / b->dreal ;
281722812Smckusick 	den = b->dreal * (1 + ratio*ratio);
281822812Smckusick 	c->dreal = (a->dreal + a->dimag*ratio) / den;
281922812Smckusick 	c->dimag = (a->dimag - a->dreal*ratio) / den;
282022812Smckusick 	}
282122812Smckusick 
282222812Smckusick }
282322812Smckusick 
282422812Smckusick expptr oftwo(e)
282522812Smckusick expptr e;
282622812Smckusick {
282722812Smckusick 	int val,res;
282822812Smckusick 
282922812Smckusick 	if (! ISCONST (e))
283022812Smckusick 		return (0);
283122812Smckusick 
283222812Smckusick 	val = e->constblock.const.ci;
283322812Smckusick 	switch (val)
283422812Smckusick 		{
283522812Smckusick 		case 2:		res = 1; break;
283622812Smckusick 		case 4:		res = 2; break;
283722812Smckusick 		case 8:		res = 3; break;
283822812Smckusick 		case 16:	res = 4; break;
283922812Smckusick 		case 32:	res = 5; break;
284022812Smckusick 		case 64:	res = 6; break;
284122812Smckusick 		case 128:	res = 7; break;
284222812Smckusick 		case 256:	res = 8; break;
284322812Smckusick 		default:	return (0);
284422812Smckusick 		}
284522812Smckusick 	return (ICON (res));
284622812Smckusick }
2847