xref: /csrg-svn/usr.bin/f77/pass1.vax/expr.c (revision 47955)
1*47955Sbostic /*-
2*47955Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*47955Sbostic  * All rights reserved.
4*47955Sbostic  *
5*47955Sbostic  * %sccs.include.proprietary.c%
622812Smckusick  */
722812Smckusick 
822812Smckusick #ifndef lint
9*47955Sbostic static char sccsid[] = "@(#)expr.c	5.10 (Berkeley) 04/12/91";
10*47955Sbostic #endif /* not lint */
1122812Smckusick 
1222812Smckusick /*
1322812Smckusick  * expr.c
1422812Smckusick  *
1522812Smckusick  * Routines for handling expressions, f77 compiler pass 1.
1622812Smckusick  *
1722812Smckusick  * University of Utah CS Dept modification history:
1822812Smckusick  *
1923476Smckusick  * $Log:	expr.c,v $
2027928Sdonn  * Revision 5.13  86/05/07  18:54:23  donn
2127928Sdonn  * Adjusted the warning for OPEQ with logical operands -- this is now printed
2227928Sdonn  * in mkexpr since cktype can be called several times on the same operands
2327928Sdonn  * (argh -- how slow can this compiler get?!).
2427928Sdonn  *
2527928Sdonn  * Revision 5.12  86/05/07  17:40:54  donn
2627928Sdonn  * Make the lengths of expr nodes be copied by cpexpr and freed by frexpr.
2727928Sdonn  *
2827928Sdonn  * Revision 5.11  86/05/07  16:57:17  donn
2927928Sdonn  * Logical data is supposed to be compared using .eqv. and .neqv., but we
3027928Sdonn  * will support .eq. and .ne. with a warning.  Other relational operators
3127928Sdonn  * now provoke errors when used with logical operands.
3227928Sdonn  *
3327451Sdonn  * Revision 5.10  86/04/26  13:24:30  donn
3427451Sdonn  * Someone forgot about comparisons of logical constants in consbinop() --
3527451Sdonn  * the results of such tests were garbage.
3627451Sdonn  *
3726307Sdonn  * Revision 5.9  86/02/20  23:38:31  donn
3826307Sdonn  * Fix memory management problem with reordering of array dimension and
3926307Sdonn  * substring code in mklhs().
4026307Sdonn  *
4125736Sdonn  * Revision 5.8  85/12/20  21:37:58  donn
4225736Sdonn  * Fix bug in mklhs() that caused the 'first character' substring parameter
4325736Sdonn  * to be evaluated twice.
4425736Sdonn  *
4525736Sdonn  * Revision 5.7  85/12/20  19:42:05  donn
4625736Sdonn  * Be more specfic -- name the offending subroutine when it's used as a
4725736Sdonn  * function.
4825736Sdonn  *
4925736Sdonn  * Revision 5.6  85/12/19  20:08:12  donn
5025736Sdonn  * Don't optimize first/last char values when they contain function calls
5125736Sdonn  * or array references.
5225736Sdonn  *
5325736Sdonn  * Revision 5.5  85/12/19  00:35:22  donn
5425736Sdonn  * Lots of changes for handling hardware errors which can crop up when
5525736Sdonn  * evaluating constant expressions.
5625736Sdonn  *
5725736Sdonn  * Revision 5.4  85/11/25  00:23:53  donn
5825736Sdonn  * 4.3 beta
5925736Sdonn  *
6024477Sdonn  * Revision 5.3  85/08/10  05:48:16  donn
6124477Sdonn  * Fixed another of my goofs in the substring parameter conversion code.
6224477Sdonn  *
6324477Sdonn  * Revision 5.2  85/08/10  04:13:51  donn
6424477Sdonn  * Jerry Berkman's change to call pow() directly rather than indirectly
6524477Sdonn  * through pow_dd, in mkpower().
6624477Sdonn  *
6724477Sdonn  * Revision 5.1  85/08/10  03:44:19  donn
6824477Sdonn  * 4.3 alpha
6924477Sdonn  *
7023680Smckusick  * Revision 3.16  85/06/21  16:38:09  donn
7123680Smckusick  * The fix to mkprim() didn't handle null substring parameters (sigh).
7223680Smckusick  *
7323476Smckusick  * Revision 3.15  85/06/04  04:37:03  donn
7423476Smckusick  * Changed mkprim() to force substring parameters to be integral types.
7522812Smckusick  *
7623476Smckusick  * Revision 3.14  85/06/04  03:41:52  donn
7723476Smckusick  * Change impldcl() to handle functions of type 'undefined'.
7823476Smckusick  *
7923476Smckusick  * Revision 3.13  85/05/06  23:14:55  donn
8023476Smckusick  * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
8123476Smckusick  * a temporary when converting character strings to integers; previously we
8223476Smckusick  * were having problems because mkconv() was called after tempalloc().
8323476Smckusick  *
8422812Smckusick  * Revision 3.12  85/03/18  08:07:47  donn
8522812Smckusick  * Fixes to help out with short integers -- if integers are by default short,
8622812Smckusick  * then so are constants; and if addresses can't be stored in shorts, complain.
8722812Smckusick  *
8822812Smckusick  * Revision 3.11  85/03/16  22:31:27  donn
8922812Smckusick  * Added hack to mkconv() to allow character values of length > 1 to be
9022812Smckusick  * converted to numeric types, for Helge Skrivervik.  Note that this does
9122812Smckusick  * not affect use of the intrinsic ichar() conversion.
9222812Smckusick  *
9322812Smckusick  * Revision 3.10  85/01/15  21:06:47  donn
9422812Smckusick  * Changed mkconv() to comment on implicit conversions; added intrconv() for
9522812Smckusick  * use with explicit conversions by intrinsic functions.
9622812Smckusick  *
9722812Smckusick  * Revision 3.9  85/01/11  21:05:49  donn
9822812Smckusick  * Added changes to implement SAVE statements.
9922812Smckusick  *
10022812Smckusick  * Revision 3.8  84/12/17  02:21:06  donn
10122812Smckusick  * Added a test to prevent constant folding from being done on expressions
10222812Smckusick  * whose type is not known at that point in mkexpr().
10322812Smckusick  *
10422812Smckusick  * Revision 3.7  84/12/11  21:14:17  donn
10522812Smckusick  * Removed obnoxious 'excess precision' warning.
10622812Smckusick  *
10722812Smckusick  * Revision 3.6  84/11/23  01:00:36  donn
10822812Smckusick  * Added code to trim excess precision from single-precision constants, and
10922812Smckusick  * to warn the user when this occurs.
11022812Smckusick  *
11122812Smckusick  * Revision 3.5  84/11/23  00:10:39  donn
11222812Smckusick  * Changed stfcall() to remark on argument type clashes in 'calls' to
11322812Smckusick  * statement functions.
11422812Smckusick  *
11522812Smckusick  * Revision 3.4  84/11/22  21:21:17  donn
11622812Smckusick  * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
11722812Smckusick  *
11822812Smckusick  * Revision 3.3  84/11/12  18:26:14  donn
11922812Smckusick  * Shuffled some code around so that the compiler remembers to free some vleng
12022812Smckusick  * structures which used to just sit around.
12122812Smckusick  *
12222812Smckusick  * Revision 3.2  84/10/16  19:24:15  donn
12322812Smckusick  * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
12422812Smckusick  * core dumps by replacing bad subscripts with good ones.
12522812Smckusick  *
12622812Smckusick  * Revision 3.1  84/10/13  01:31:32  donn
12722812Smckusick  * Merged Jerry Berkman's version into mine.
12822812Smckusick  *
12922812Smckusick  * Revision 2.7  84/09/27  15:42:52  donn
13022812Smckusick  * The last fix for multiplying undeclared variables by 0 isn't sufficient,
13122812Smckusick  * since the type of the 0 may not be the (implicit) type of the variable.
13222812Smckusick  * I added a hack to check the implicit type of implicitly declared
13322812Smckusick  * variables...
13422812Smckusick  *
13522812Smckusick  * Revision 2.6  84/09/14  19:34:03  donn
13622812Smckusick  * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
13722812Smckusick  * 0 to type UNKNOWN, which is illegal.  Fix is to use native type instead.
13822812Smckusick  * Not sure how correct (or important) this is...
13922812Smckusick  *
14022812Smckusick  * Revision 2.5  84/08/05  23:05:27  donn
14122812Smckusick  * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
14222812Smckusick  * with two operands.
14322812Smckusick  *
14422812Smckusick  * Revision 2.4  84/08/05  17:34:48  donn
14522812Smckusick  * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
14622812Smckusick  * and assign constant length 1 to them.
14722812Smckusick  *
14822812Smckusick  * Revision 2.3  84/07/19  19:38:33  donn
14922812Smckusick  * Added a typecast to the last fix.  Somehow I missed it the first time...
15022812Smckusick  *
15122812Smckusick  * Revision 2.2  84/07/19  17:19:57  donn
15222812Smckusick  * Caused OPPAREN expressions to inherit the length of their operands, so
15322812Smckusick  * that parenthesized character expressions work correctly.
15422812Smckusick  *
15522812Smckusick  * Revision 2.1  84/07/19  12:03:02  donn
15622812Smckusick  * Changed comment headers for UofU.
15722812Smckusick  *
15822812Smckusick  * Revision 1.2  84/04/06  20:12:17  donn
15922812Smckusick  * Fixed bug which caused programs with mixed-type multiplications involving
16022812Smckusick  * the constant 0 to choke the compiler.
16122812Smckusick  *
16222812Smckusick  */
16322812Smckusick 
16422812Smckusick #include "defs.h"
16522812Smckusick 
16622812Smckusick 
16722812Smckusick /* little routines to create constant blocks */
16822812Smckusick 
mkconst(t)16922812Smckusick Constp mkconst(t)
17022812Smckusick register int t;
17122812Smckusick {
17222812Smckusick register Constp p;
17322812Smckusick 
17422812Smckusick p = ALLOC(Constblock);
17522812Smckusick p->tag = TCONST;
17622812Smckusick p->vtype = t;
17722812Smckusick return(p);
17822812Smckusick }
17922812Smckusick 
18022812Smckusick 
mklogcon(l)18122812Smckusick expptr mklogcon(l)
18222812Smckusick register int l;
18322812Smckusick {
18422812Smckusick register Constp  p;
18522812Smckusick 
18622812Smckusick p = mkconst(TYLOGICAL);
18733256Sbostic p->constant.ci = l;
18822812Smckusick return( (expptr) p );
18922812Smckusick }
19022812Smckusick 
19122812Smckusick 
19222812Smckusick 
mkintcon(l)19322812Smckusick expptr mkintcon(l)
19422812Smckusick ftnint l;
19522812Smckusick {
19622812Smckusick register Constp p;
19722812Smckusick int usetype;
19822812Smckusick 
19922812Smckusick if(tyint == TYSHORT)
20022812Smckusick   {
20122812Smckusick     short s = l;
20222812Smckusick     if(l != s)
20322812Smckusick       usetype = TYLONG;
20422812Smckusick     else
20522812Smckusick       usetype = TYSHORT;
20622812Smckusick   }
20722812Smckusick else
20822812Smckusick   usetype = tyint;
20922812Smckusick p = mkconst(usetype);
21033256Sbostic p->constant.ci = l;
21122812Smckusick return( (expptr) p );
21222812Smckusick }
21322812Smckusick 
21422812Smckusick 
21522812Smckusick 
mkaddcon(l)21622812Smckusick expptr mkaddcon(l)
21722812Smckusick register int l;
21822812Smckusick {
21922812Smckusick register Constp p;
22022812Smckusick 
22122812Smckusick p = mkconst(TYADDR);
22233256Sbostic p->constant.ci = l;
22322812Smckusick return( (expptr) p );
22422812Smckusick }
22522812Smckusick 
22622812Smckusick 
22722812Smckusick 
mkrealcon(t,d)22822812Smckusick expptr mkrealcon(t, d)
22922812Smckusick register int t;
23022812Smckusick double d;
23122812Smckusick {
23222812Smckusick register Constp p;
23322812Smckusick 
23422812Smckusick if(t == TYREAL)
23522812Smckusick   {
23622812Smckusick     float f = d;
23722812Smckusick     if(f != d)
23822812Smckusick       {
23922812Smckusick #ifdef notdef
24022812Smckusick 	warn("excess precision in real constant lost");
24122812Smckusick #endif notdef
24222812Smckusick 	d = f;
24322812Smckusick       }
24422812Smckusick   }
24522812Smckusick p = mkconst(t);
24633256Sbostic p->constant.cd[0] = d;
24722812Smckusick return( (expptr) p );
24822812Smckusick }
24922812Smckusick 
25022812Smckusick 
mkbitcon(shift,leng,s)25122812Smckusick expptr mkbitcon(shift, leng, s)
25222812Smckusick int shift;
25322812Smckusick register int leng;
25422812Smckusick register char *s;
25522812Smckusick {
25622812Smckusick   Constp p;
25722812Smckusick   register int i, j, k;
25822812Smckusick   register char *bp;
25922812Smckusick   int size;
26022812Smckusick 
26122812Smckusick   size = (shift*leng + BYTESIZE -1)/BYTESIZE;
26222812Smckusick   bp = (char *) ckalloc(size);
26322812Smckusick 
26422812Smckusick   i = 0;
26522812Smckusick 
26622812Smckusick #if (TARGET == PDP11 || TARGET == VAX)
26722812Smckusick   j = 0;
26822812Smckusick #else
26922812Smckusick   j = size;
27022812Smckusick #endif
27122812Smckusick 
27222812Smckusick   k = 0;
27322812Smckusick 
27422812Smckusick   while (leng > 0)
27522812Smckusick     {
27622812Smckusick       k |= (hextoi(s[--leng]) << i);
27722812Smckusick       i += shift;
27822812Smckusick       if (i >= BYTESIZE)
27922812Smckusick 	{
28022812Smckusick #if (TARGET == PDP11 || TARGET == VAX)
28122812Smckusick 	  bp[j++] = k & MAXBYTE;
28222812Smckusick #else
28322812Smckusick 	  bp[--j] = k & MAXBYTE;
28422812Smckusick #endif
28522812Smckusick 	  k = k >> BYTESIZE;
28622812Smckusick 	  i -= BYTESIZE;
28722812Smckusick 	}
28822812Smckusick     }
28922812Smckusick 
29022812Smckusick   if (k != 0)
29122812Smckusick #if (TARGET == PDP11 || TARGET == VAX)
29222812Smckusick     bp[j++] = k;
29322812Smckusick #else
29422812Smckusick     bp[--j] = k;
29522812Smckusick #endif
29622812Smckusick 
29722812Smckusick   p = mkconst(TYBITSTR);
29822812Smckusick   p->vleng = ICON(size);
29933256Sbostic   p->constant.ccp = bp;
30022812Smckusick 
30122812Smckusick   return ((expptr) p);
30222812Smckusick }
30322812Smckusick 
30422812Smckusick 
30522812Smckusick 
mkstrcon(l,v)30622812Smckusick expptr mkstrcon(l,v)
30722812Smckusick int l;
30822812Smckusick register char *v;
30922812Smckusick {
31022812Smckusick register Constp p;
31122812Smckusick register char *s;
31222812Smckusick 
31322812Smckusick p = mkconst(TYCHAR);
31422812Smckusick p->vleng = ICON(l);
31533256Sbostic p->constant.ccp = s = (char *) ckalloc(l);
31622812Smckusick while(--l >= 0)
31722812Smckusick 	*s++ = *v++;
31822812Smckusick return( (expptr) p );
31922812Smckusick }
32022812Smckusick 
32122812Smckusick 
mkcxcon(realp,imagp)32222812Smckusick expptr mkcxcon(realp,imagp)
32322812Smckusick register expptr realp, imagp;
32422812Smckusick {
32522812Smckusick int rtype, itype;
32622812Smckusick register Constp p;
32722812Smckusick 
32822812Smckusick rtype = realp->headblock.vtype;
32922812Smckusick itype = imagp->headblock.vtype;
33022812Smckusick 
33122812Smckusick if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
33222812Smckusick 	{
33322812Smckusick 	p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
33422812Smckusick 	if( ISINT(rtype) )
33533256Sbostic 		p->constant.cd[0] = realp->constblock.constant.ci;
33633256Sbostic 	else	p->constant.cd[0] = realp->constblock.constant.cd[0];
33722812Smckusick 	if( ISINT(itype) )
33833256Sbostic 		p->constant.cd[1] = imagp->constblock.constant.ci;
33933256Sbostic 	else	p->constant.cd[1] = imagp->constblock.constant.cd[0];
34022812Smckusick 	}
34122812Smckusick else
34222812Smckusick 	{
34322812Smckusick 	err("invalid complex constant");
34422812Smckusick 	p = (Constp) errnode();
34522812Smckusick 	}
34622812Smckusick 
34722812Smckusick frexpr(realp);
34822812Smckusick frexpr(imagp);
34922812Smckusick return( (expptr) p );
35022812Smckusick }
35122812Smckusick 
35222812Smckusick 
errnode()35322812Smckusick expptr errnode()
35422812Smckusick {
35522812Smckusick struct Errorblock *p;
35622812Smckusick p = ALLOC(Errorblock);
35722812Smckusick p->tag = TERROR;
35822812Smckusick p->vtype = TYERROR;
35922812Smckusick return( (expptr) p );
36022812Smckusick }
36122812Smckusick 
36222812Smckusick 
36322812Smckusick 
36422812Smckusick 
36522812Smckusick 
mkconv(t,p)36622812Smckusick expptr mkconv(t, p)
36722812Smckusick register int t;
36822812Smckusick register expptr p;
36922812Smckusick {
37022812Smckusick register expptr q;
37122812Smckusick Addrp r, s;
37222812Smckusick register int pt;
37322812Smckusick expptr opconv();
37422812Smckusick 
37522812Smckusick if(t==TYUNKNOWN || t==TYERROR)
37622812Smckusick 	badtype("mkconv", t);
37722812Smckusick pt = p->headblock.vtype;
37822812Smckusick if(t == pt)
37922812Smckusick 	return(p);
38022812Smckusick 
38122812Smckusick if( pt == TYCHAR && ISNUMERIC(t) )
38222812Smckusick 	{
38322812Smckusick 	warn("implicit conversion of character to numeric type");
38422812Smckusick 
38522812Smckusick 	/*
38622812Smckusick 	 * Ugly kluge to copy character values into numerics.
38722812Smckusick 	 */
38822812Smckusick 	s = mkaltemp(t, ENULL);
38922812Smckusick 	r = (Addrp) cpexpr(s);
39022812Smckusick 	r->vtype = TYCHAR;
39122812Smckusick 	r->varleng = typesize[t];
39222812Smckusick 	r->vleng = mkintcon(r->varleng);
39322812Smckusick 	q = mkexpr(OPASSIGN, r, p);
39422812Smckusick 	q = mkexpr(OPCOMMA, q, s);
39522812Smckusick 	return(q);
39622812Smckusick 	}
39722812Smckusick 
39822812Smckusick #if SZADDR > SZSHORT
39922812Smckusick if( pt == TYADDR && t == TYSHORT)
40022812Smckusick 	{
40122812Smckusick 	err("insufficient precision to hold address type");
40222812Smckusick 	return( errnode() );
40322812Smckusick 	}
40422812Smckusick #endif
40522812Smckusick if( pt == TYADDR && ISNUMERIC(t) )
40622812Smckusick 	warn("implicit conversion of address to numeric type");
40722812Smckusick 
40822812Smckusick if( ISCONST(p) && pt!=TYADDR)
40922812Smckusick 	{
41022812Smckusick 	q = (expptr) mkconst(t);
41133256Sbostic 	consconv(t, &(q->constblock.constant),
41233256Sbostic 		p->constblock.vtype, &(p->constblock.constant) );
41322812Smckusick 	frexpr(p);
41422812Smckusick 	}
41522812Smckusick #if TARGET == PDP11
41622812Smckusick else if(ISINT(t) && pt==TYCHAR)
41722812Smckusick 	{
41822812Smckusick 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
41922812Smckusick 	if(t == TYLONG)
42022812Smckusick 		q = opconv(q, TYLONG);
42122812Smckusick 	}
42222812Smckusick #endif
42322812Smckusick else
42422812Smckusick 	q = opconv(p, t);
42522812Smckusick 
42622812Smckusick if(t == TYCHAR)
42722812Smckusick 	q->constblock.vleng = ICON(1);
42822812Smckusick return(q);
42922812Smckusick }
43022812Smckusick 
43122812Smckusick 
43222812Smckusick 
43322812Smckusick /* intrinsic conversions */
intrconv(t,p)43422812Smckusick expptr intrconv(t, p)
43522812Smckusick register int t;
43622812Smckusick register expptr p;
43722812Smckusick {
43822812Smckusick register expptr q;
43922812Smckusick register int pt;
44022812Smckusick expptr opconv();
44122812Smckusick 
44222812Smckusick if(t==TYUNKNOWN || t==TYERROR)
44322812Smckusick 	badtype("intrconv", t);
44422812Smckusick pt = p->headblock.vtype;
44522812Smckusick if(t == pt)
44622812Smckusick 	return(p);
44722812Smckusick 
44822812Smckusick else if( ISCONST(p) && pt!=TYADDR)
44922812Smckusick 	{
45022812Smckusick 	q = (expptr) mkconst(t);
45133256Sbostic 	consconv(t, &(q->constblock.constant),
45233256Sbostic 		p->constblock.vtype, &(p->constblock.constant) );
45322812Smckusick 	frexpr(p);
45422812Smckusick 	}
45522812Smckusick #if TARGET == PDP11
45622812Smckusick else if(ISINT(t) && pt==TYCHAR)
45722812Smckusick 	{
45822812Smckusick 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
45922812Smckusick 	if(t == TYLONG)
46022812Smckusick 		q = opconv(q, TYLONG);
46122812Smckusick 	}
46222812Smckusick #endif
46322812Smckusick else
46422812Smckusick 	q = opconv(p, t);
46522812Smckusick 
46622812Smckusick if(t == TYCHAR)
46722812Smckusick 	q->constblock.vleng = ICON(1);
46822812Smckusick return(q);
46922812Smckusick }
47022812Smckusick 
47122812Smckusick 
47222812Smckusick 
opconv(p,t)47322812Smckusick expptr opconv(p, t)
47422812Smckusick expptr p;
47522812Smckusick int t;
47622812Smckusick {
47722812Smckusick register expptr q;
47822812Smckusick 
47922812Smckusick q = mkexpr(OPCONV, p, PNULL);
48022812Smckusick q->headblock.vtype = t;
48122812Smckusick return(q);
48222812Smckusick }
48322812Smckusick 
48422812Smckusick 
48522812Smckusick 
addrof(p)48622812Smckusick expptr addrof(p)
48722812Smckusick expptr p;
48822812Smckusick {
48922812Smckusick return( mkexpr(OPADDR, p, PNULL) );
49022812Smckusick }
49122812Smckusick 
49222812Smckusick 
49322812Smckusick 
cpexpr(p)49422812Smckusick tagptr cpexpr(p)
49522812Smckusick register tagptr p;
49622812Smckusick {
49722812Smckusick register tagptr e;
49822812Smckusick int tag;
49922812Smckusick register chainp ep, pp;
50022812Smckusick tagptr cpblock();
50122812Smckusick 
50222812Smckusick static int blksize[ ] =
50322812Smckusick 	{	0,
50422812Smckusick 		sizeof(struct Nameblock),
50522812Smckusick 		sizeof(struct Constblock),
50622812Smckusick 		sizeof(struct Exprblock),
50722812Smckusick 		sizeof(struct Addrblock),
50822812Smckusick 		sizeof(struct Tempblock),
50922812Smckusick 		sizeof(struct Primblock),
51022812Smckusick 		sizeof(struct Listblock),
51122812Smckusick 		sizeof(struct Errorblock)
51222812Smckusick 	};
51322812Smckusick 
51422812Smckusick if(p == NULL)
51522812Smckusick 	return(NULL);
51622812Smckusick 
51722812Smckusick if( (tag = p->tag) == TNAME)
51822812Smckusick 	return(p);
51922812Smckusick 
52022812Smckusick e = cpblock( blksize[p->tag] , p);
52122812Smckusick 
52222812Smckusick switch(tag)
52322812Smckusick 	{
52422812Smckusick 	case TCONST:
52522812Smckusick 		if(e->constblock.vtype == TYCHAR)
52622812Smckusick 			{
52733256Sbostic 			e->constblock.constant.ccp =
52833256Sbostic 				copyn(1+strlen(e->constblock.constant.ccp),
52933256Sbostic 					e->constblock.constant.ccp);
53022812Smckusick 			e->constblock.vleng =
53122812Smckusick 				(expptr) cpexpr(e->constblock.vleng);
53222812Smckusick 			}
53322812Smckusick 	case TERROR:
53422812Smckusick 		break;
53522812Smckusick 
53622812Smckusick 	case TEXPR:
53722812Smckusick 		e->exprblock.leftp =  (expptr) cpexpr(p->exprblock.leftp);
53822812Smckusick 		e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
53927928Sdonn 		e->addrblock.vleng =  (expptr) cpexpr(e->addrblock.vleng);
54022812Smckusick 		break;
54122812Smckusick 
54222812Smckusick 	case TLIST:
54322812Smckusick 		if(pp = p->listblock.listp)
54422812Smckusick 			{
54522812Smckusick 			ep = e->listblock.listp =
54622812Smckusick 				mkchain( cpexpr(pp->datap), CHNULL);
54722812Smckusick 			for(pp = pp->nextp ; pp ; pp = pp->nextp)
54822812Smckusick 				ep = ep->nextp =
54922812Smckusick 					mkchain( cpexpr(pp->datap), CHNULL);
55022812Smckusick 			}
55122812Smckusick 		break;
55222812Smckusick 
55322812Smckusick 	case TADDR:
55422812Smckusick 		e->addrblock.vleng = (expptr)  cpexpr(e->addrblock.vleng);
55522812Smckusick 		e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
55622812Smckusick 		e->addrblock.istemp = NO;
55722812Smckusick 		break;
55822812Smckusick 
55922812Smckusick 	case TTEMP:
56022812Smckusick 		e->tempblock.vleng = (expptr)  cpexpr(e->tempblock.vleng);
56122812Smckusick 		e->tempblock.istemp = NO;
56222812Smckusick 		break;
56322812Smckusick 
56422812Smckusick 	case TPRIM:
56522812Smckusick 		e->primblock.argsp = (struct Listblock *)
56622812Smckusick 					cpexpr(e->primblock.argsp);
56722812Smckusick 		e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
56822812Smckusick 		e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
56922812Smckusick 		break;
57022812Smckusick 
57122812Smckusick 	default:
57222812Smckusick 		badtag("cpexpr", tag);
57322812Smckusick 	}
57422812Smckusick 
57522812Smckusick return(e);
57622812Smckusick }
57722812Smckusick 
frexpr(p)57822812Smckusick frexpr(p)
57922812Smckusick register tagptr p;
58022812Smckusick {
58122812Smckusick register chainp q;
58222812Smckusick 
58322812Smckusick if(p == NULL)
58422812Smckusick 	return;
58522812Smckusick 
58622812Smckusick switch(p->tag)
58722812Smckusick 	{
58822812Smckusick 	case TCONST:
58922812Smckusick 		switch (p->constblock.vtype)
59022812Smckusick 			{
59122812Smckusick 			case TYBITSTR:
59222812Smckusick 			case TYCHAR:
59322812Smckusick 			case TYHOLLERITH:
59433256Sbostic 				free( (charptr) (p->constblock.constant.ccp) );
59522812Smckusick 				frexpr(p->constblock.vleng);
59622812Smckusick 			}
59722812Smckusick 		break;
59822812Smckusick 
59922812Smckusick 	case TADDR:
60022812Smckusick 		if (!optimflag && p->addrblock.istemp)
60122812Smckusick 			{
60222812Smckusick 			frtemp(p);
60322812Smckusick 			return;
60422812Smckusick 			}
60522812Smckusick 		frexpr(p->addrblock.vleng);
60622812Smckusick 		frexpr(p->addrblock.memoffset);
60722812Smckusick 		break;
60822812Smckusick 
60922812Smckusick 	case TTEMP:
61022812Smckusick 		frexpr(p->tempblock.vleng);
61122812Smckusick 		break;
61222812Smckusick 
61322812Smckusick 	case TERROR:
61422812Smckusick 		break;
61522812Smckusick 
61622812Smckusick 	case TNAME:
61722812Smckusick 		return;
61822812Smckusick 
61922812Smckusick 	case TPRIM:
62022812Smckusick 		frexpr(p->primblock.argsp);
62122812Smckusick 		frexpr(p->primblock.fcharp);
62222812Smckusick 		frexpr(p->primblock.lcharp);
62322812Smckusick 		break;
62422812Smckusick 
62522812Smckusick 	case TEXPR:
62622812Smckusick 		frexpr(p->exprblock.leftp);
62722812Smckusick 		if(p->exprblock.rightp)
62822812Smckusick 			frexpr(p->exprblock.rightp);
62927928Sdonn 		if(p->exprblock.vleng)
63027928Sdonn 			frexpr(p->exprblock.vleng);
63122812Smckusick 		break;
63222812Smckusick 
63322812Smckusick 	case TLIST:
63422812Smckusick 		for(q = p->listblock.listp ; q ; q = q->nextp)
63522812Smckusick 			frexpr(q->datap);
63622812Smckusick 		frchain( &(p->listblock.listp) );
63722812Smckusick 		break;
63822812Smckusick 
63922812Smckusick 	default:
64022812Smckusick 		badtag("frexpr", p->tag);
64122812Smckusick 	}
64222812Smckusick 
64322812Smckusick free( (charptr) p );
64422812Smckusick }
64522812Smckusick 
64622812Smckusick /* fix up types in expression; replace subtrees and convert
64722812Smckusick    names to address blocks */
64822812Smckusick 
fixtype(p)64922812Smckusick expptr fixtype(p)
65022812Smckusick register tagptr p;
65122812Smckusick {
65222812Smckusick 
65322812Smckusick if(p == 0)
65422812Smckusick 	return(0);
65522812Smckusick 
65622812Smckusick switch(p->tag)
65722812Smckusick 	{
65822812Smckusick 	case TCONST:
65922812Smckusick 		return( (expptr) p );
66022812Smckusick 
66122812Smckusick 	case TADDR:
66222812Smckusick 		p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
66322812Smckusick 		return( (expptr) p);
66422812Smckusick 
66522812Smckusick 	case TTEMP:
66622812Smckusick 		return( (expptr) p);
66722812Smckusick 
66822812Smckusick 	case TERROR:
66922812Smckusick 		return( (expptr) p);
67022812Smckusick 
67122812Smckusick 	default:
67222812Smckusick 		badtag("fixtype", p->tag);
67322812Smckusick 
67422812Smckusick 	case TEXPR:
67522812Smckusick 		return( fixexpr(p) );
67622812Smckusick 
67722812Smckusick 	case TLIST:
67822812Smckusick 		return( (expptr) p );
67922812Smckusick 
68022812Smckusick 	case TPRIM:
68122812Smckusick 		if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
68222812Smckusick 			{
68322812Smckusick 			if(p->primblock.namep->vtype == TYSUBR)
68422812Smckusick 				{
68525736Sdonn 				dclerr("function invocation of subroutine",
68625736Sdonn 					p->primblock.namep);
68722812Smckusick 				return( errnode() );
68822812Smckusick 				}
68922812Smckusick 			else
69022812Smckusick 				return( mkfunct(p) );
69122812Smckusick 			}
69222812Smckusick 		else	return( mklhs(p) );
69322812Smckusick 	}
69422812Smckusick }
69522812Smckusick 
69622812Smckusick 
69722812Smckusick 
69822812Smckusick 
69922812Smckusick 
70022812Smckusick /* special case tree transformations and cleanups of expression trees */
70122812Smckusick 
fixexpr(p)70222812Smckusick expptr fixexpr(p)
70322812Smckusick register Exprp p;
70422812Smckusick {
70522812Smckusick expptr lp;
70622812Smckusick register expptr rp;
70722812Smckusick register expptr q;
70822812Smckusick int opcode, ltype, rtype, ptype, mtype;
70922812Smckusick expptr lconst, rconst;
71022812Smckusick expptr mkpower();
71122812Smckusick 
71222812Smckusick if( ISERROR(p) )
71322812Smckusick 	return( (expptr) p );
71422812Smckusick else if(p->tag != TEXPR)
71522812Smckusick 	badtag("fixexpr", p->tag);
71622812Smckusick opcode = p->opcode;
71722812Smckusick if (ISCONST(p->leftp))
71822812Smckusick 	lconst = (expptr) cpexpr(p->leftp);
71922812Smckusick else
72022812Smckusick 	lconst = NULL;
72122812Smckusick if (p->rightp && ISCONST(p->rightp))
72222812Smckusick 	rconst = (expptr) cpexpr(p->rightp);
72322812Smckusick else
72422812Smckusick 	rconst = NULL;
72522812Smckusick lp = p->leftp = fixtype(p->leftp);
72622812Smckusick ltype = lp->headblock.vtype;
72722812Smckusick if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
72822812Smckusick 	{
72922812Smckusick 	err("left side of assignment must be variable");
73022812Smckusick 	frexpr(p);
73122812Smckusick 	return( errnode() );
73222812Smckusick 	}
73322812Smckusick 
73422812Smckusick if(p->rightp)
73522812Smckusick 	{
73622812Smckusick 	rp = p->rightp = fixtype(p->rightp);
73722812Smckusick 	rtype = rp->headblock.vtype;
73822812Smckusick 	}
73922812Smckusick else
74022812Smckusick 	{
74122812Smckusick 	rp = NULL;
74222812Smckusick 	rtype = 0;
74322812Smckusick 	}
74422812Smckusick 
74522812Smckusick if(ltype==TYERROR || rtype==TYERROR)
74622812Smckusick 	{
74722812Smckusick 	frexpr(p);
74822812Smckusick 	frexpr(lconst);
74922812Smckusick 	frexpr(rconst);
75022812Smckusick 	return( errnode() );
75122812Smckusick 	}
75222812Smckusick 
75322812Smckusick /* force folding if possible */
75422812Smckusick if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
75522812Smckusick 	{
75622812Smckusick 	q = mkexpr(opcode, lp, rp);
75722812Smckusick 	if( ISCONST(q) )
75822812Smckusick 		{
75922812Smckusick 		frexpr(lconst);
76022812Smckusick 		frexpr(rconst);
76122812Smckusick 		return(q);
76222812Smckusick 		}
76322812Smckusick 	free( (charptr) q );	/* constants did not fold */
76422812Smckusick 	}
76522812Smckusick 
76622812Smckusick if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
76722812Smckusick 	{
76822812Smckusick 	frexpr(p);
76922812Smckusick 	frexpr(lconst);
77022812Smckusick 	frexpr(rconst);
77122812Smckusick 	return( errnode() );
77222812Smckusick 	}
77322812Smckusick 
77422812Smckusick switch(opcode)
77522812Smckusick 	{
77622812Smckusick 	case OPCONCAT:
77722812Smckusick 		if(p->vleng == NULL)
77822812Smckusick 			p->vleng = mkexpr(OPPLUS,
77922812Smckusick 				cpexpr(lp->headblock.vleng),
78022812Smckusick 				cpexpr(rp->headblock.vleng) );
78122812Smckusick 		break;
78222812Smckusick 
78322812Smckusick 	case OPASSIGN:
78422812Smckusick 	case OPPLUSEQ:
78522812Smckusick 	case OPSTAREQ:
78622812Smckusick 		if(ltype == rtype)
78722812Smckusick 			break;
78822812Smckusick 		if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
78922812Smckusick 			break;
79022812Smckusick 		if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
79122812Smckusick 			break;
79222812Smckusick 		if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
79322812Smckusick #if FAMILY==PCC
79422812Smckusick 		    && typesize[ltype]>=typesize[rtype] )
79522812Smckusick #else
79622812Smckusick 		    && typesize[ltype]==typesize[rtype] )
79722812Smckusick #endif
79822812Smckusick 			break;
79922812Smckusick 		if (rconst)
80022812Smckusick 			{
80122812Smckusick 			p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
80222812Smckusick 			frexpr(rp);
80322812Smckusick 			}
80422812Smckusick 		else
80522812Smckusick 			p->rightp = fixtype(mkconv(ptype, rp));
80622812Smckusick 		break;
80722812Smckusick 
80822812Smckusick 	case OPSLASH:
80922812Smckusick 		if( ISCOMPLEX(rtype) )
81022812Smckusick 			{
81122812Smckusick 			p = (Exprp) call2(ptype,
81222812Smckusick 				ptype==TYCOMPLEX? "c_div" : "z_div",
81322812Smckusick 				mkconv(ptype, lp), mkconv(ptype, rp) );
81422812Smckusick 			break;
81522812Smckusick 			}
81622812Smckusick 	case OPPLUS:
81722812Smckusick 	case OPMINUS:
81822812Smckusick 	case OPSTAR:
81922812Smckusick 	case OPMOD:
82022812Smckusick 		if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
82122812Smckusick 		    (rtype==TYREAL && ! rconst ) ))
82222812Smckusick 			break;
82322812Smckusick 		if( ISCOMPLEX(ptype) )
82422812Smckusick 			break;
82522812Smckusick 		if(ltype != ptype)
82622812Smckusick 			if (lconst)
82722812Smckusick 				{
82822812Smckusick 				p->leftp = fixtype(mkconv(ptype,
82922812Smckusick 						cpexpr(lconst)));
83022812Smckusick 				frexpr(lp);
83122812Smckusick 				}
83222812Smckusick 			else
83322812Smckusick 				p->leftp = fixtype(mkconv(ptype,lp));
83422812Smckusick 		if(rtype != ptype)
83522812Smckusick 			if (rconst)
83622812Smckusick 				{
83722812Smckusick 				p->rightp = fixtype(mkconv(ptype,
83822812Smckusick 						cpexpr(rconst)));
83922812Smckusick 				frexpr(rp);
84022812Smckusick 				}
84122812Smckusick 			else
84222812Smckusick 				p->rightp = fixtype(mkconv(ptype,rp));
84322812Smckusick 		break;
84422812Smckusick 
84522812Smckusick 	case OPPOWER:
84622812Smckusick 		return( mkpower(p) );
84722812Smckusick 
84822812Smckusick 	case OPLT:
84922812Smckusick 	case OPLE:
85022812Smckusick 	case OPGT:
85122812Smckusick 	case OPGE:
85222812Smckusick 	case OPEQ:
85322812Smckusick 	case OPNE:
85422812Smckusick 		if(ltype == rtype)
85522812Smckusick 			break;
85622812Smckusick 		mtype = cktype(OPMINUS, ltype, rtype);
85722812Smckusick 		if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
85822812Smckusick 		    (rtype==TYREAL && ! rconst) ))
85922812Smckusick 			break;
86022812Smckusick 		if( ISCOMPLEX(mtype) )
86122812Smckusick 			break;
86222812Smckusick 		if(ltype != mtype)
86322812Smckusick 			if (lconst)
86422812Smckusick 				{
86522812Smckusick 				p->leftp = fixtype(mkconv(mtype,
86622812Smckusick 						cpexpr(lconst)));
86722812Smckusick 				frexpr(lp);
86822812Smckusick 				}
86922812Smckusick 			else
87022812Smckusick 				p->leftp = fixtype(mkconv(mtype,lp));
87122812Smckusick 		if(rtype != mtype)
87222812Smckusick 			if (rconst)
87322812Smckusick 				{
87422812Smckusick 				p->rightp = fixtype(mkconv(mtype,
87522812Smckusick 						cpexpr(rconst)));
87622812Smckusick 				frexpr(rp);
87722812Smckusick 				}
87822812Smckusick 			else
87922812Smckusick 				p->rightp = fixtype(mkconv(mtype,rp));
88022812Smckusick 		break;
88122812Smckusick 
88222812Smckusick 
88322812Smckusick 	case OPCONV:
88422812Smckusick 		if(ISCOMPLEX(p->vtype))
88522812Smckusick 			{
88622812Smckusick 			ptype = cktype(OPCONV, p->vtype, ltype);
88722812Smckusick 			if(p->rightp)
88822812Smckusick 				ptype = cktype(OPCONV, ptype, rtype);
88922812Smckusick 			break;
89022812Smckusick 			}
89122812Smckusick 		ptype = cktype(OPCONV, p->vtype, ltype);
89222812Smckusick 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
89322812Smckusick 			{
89422812Smckusick 			lp->exprblock.rightp =
89522812Smckusick 				fixtype( mkconv(ptype, lp->exprblock.rightp) );
89622812Smckusick 			free( (charptr) p );
89722812Smckusick 			p = (Exprp) lp;
89822812Smckusick 			}
89922812Smckusick 		break;
90022812Smckusick 
90122812Smckusick 	case OPADDR:
90222812Smckusick 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
90322812Smckusick 			fatal("addr of addr");
90422812Smckusick 		break;
90522812Smckusick 
90622812Smckusick 	case OPCOMMA:
90722812Smckusick 	case OPQUEST:
90822812Smckusick 	case OPCOLON:
90922812Smckusick 		break;
91022812Smckusick 
91122812Smckusick 	case OPPAREN:
91222812Smckusick 		p->vleng = (expptr) cpexpr( lp->headblock.vleng );
91322812Smckusick 		break;
91422812Smckusick 
91522812Smckusick 	case OPMIN:
91622812Smckusick 	case OPMAX:
91722812Smckusick 		ptype = p->vtype;
91822812Smckusick 		break;
91922812Smckusick 
92022812Smckusick 	default:
92122812Smckusick 		break;
92222812Smckusick 	}
92322812Smckusick 
92422812Smckusick p->vtype = ptype;
92522812Smckusick frexpr(lconst);
92622812Smckusick frexpr(rconst);
92722812Smckusick return((expptr) p);
92822812Smckusick }
92922812Smckusick 
93022812Smckusick #if SZINT < SZLONG
93122812Smckusick /*
93222812Smckusick    for efficient subscripting, replace long ints by shorts
93322812Smckusick    in easy places
93422812Smckusick */
93522812Smckusick 
shorten(p)93622812Smckusick expptr shorten(p)
93722812Smckusick register expptr p;
93822812Smckusick {
93922812Smckusick register expptr q;
94022812Smckusick 
94122812Smckusick if(p->headblock.vtype != TYLONG)
94222812Smckusick 	return(p);
94322812Smckusick 
94422812Smckusick switch(p->tag)
94522812Smckusick 	{
94622812Smckusick 	case TERROR:
94722812Smckusick 	case TLIST:
94822812Smckusick 		return(p);
94922812Smckusick 
95022812Smckusick 	case TCONST:
95122812Smckusick 	case TADDR:
95222812Smckusick 		return( mkconv(TYINT,p) );
95322812Smckusick 
95422812Smckusick 	case TEXPR:
95522812Smckusick 		break;
95622812Smckusick 
95722812Smckusick 	default:
95822812Smckusick 		badtag("shorten", p->tag);
95922812Smckusick 	}
96022812Smckusick 
96122812Smckusick switch(p->exprblock.opcode)
96222812Smckusick 	{
96322812Smckusick 	case OPPLUS:
96422812Smckusick 	case OPMINUS:
96522812Smckusick 	case OPSTAR:
96622812Smckusick 		q = shorten( cpexpr(p->exprblock.rightp) );
96722812Smckusick 		if(q->headblock.vtype == TYINT)
96822812Smckusick 			{
96922812Smckusick 			p->exprblock.leftp = shorten(p->exprblock.leftp);
97022812Smckusick 			if(p->exprblock.leftp->headblock.vtype == TYLONG)
97122812Smckusick 				frexpr(q);
97222812Smckusick 			else
97322812Smckusick 				{
97422812Smckusick 				frexpr(p->exprblock.rightp);
97522812Smckusick 				p->exprblock.rightp = q;
97622812Smckusick 				p->exprblock.vtype = TYINT;
97722812Smckusick 				}
97822812Smckusick 			}
97922812Smckusick 		break;
98022812Smckusick 
98122812Smckusick 	case OPNEG:
98222812Smckusick 	case OPPAREN:
98322812Smckusick 		p->exprblock.leftp = shorten(p->exprblock.leftp);
98422812Smckusick 		if(p->exprblock.leftp->headblock.vtype == TYINT)
98522812Smckusick 			p->exprblock.vtype = TYINT;
98622812Smckusick 		break;
98722812Smckusick 
98822812Smckusick 	case OPCALL:
98922812Smckusick 	case OPCCALL:
99022812Smckusick 		p = mkconv(TYINT,p);
99122812Smckusick 		break;
99222812Smckusick 	default:
99322812Smckusick 		break;
99422812Smckusick 	}
99522812Smckusick 
99622812Smckusick return(p);
99722812Smckusick }
99822812Smckusick #endif
99922812Smckusick 
100022812Smckusick /* fix an argument list, taking due care for special first level cases */
100122812Smckusick 
fixargs(doput,p0)100222812Smckusick fixargs(doput, p0)
100322812Smckusick int doput;	/* doput is true if the function is not intrinsic;
100422812Smckusick 		   was used to decide whether to do a putconst,
100522812Smckusick 		   but this is no longer done here (Feb82)*/
100622812Smckusick struct Listblock *p0;
100722812Smckusick {
100822812Smckusick register chainp p;
100922812Smckusick register tagptr q, t;
101022812Smckusick register int qtag;
101122812Smckusick int nargs;
101222812Smckusick Addrp mkscalar();
101322812Smckusick 
101422812Smckusick nargs = 0;
101522812Smckusick if(p0)
101622812Smckusick     for(p = p0->listp ; p ; p = p->nextp)
101722812Smckusick 	{
101822812Smckusick 	++nargs;
101922812Smckusick 	q = p->datap;
102022812Smckusick 	qtag = q->tag;
102122812Smckusick 	if(qtag == TCONST)
102222812Smckusick 		{
102322812Smckusick 		if(q->constblock.vtype == TYSHORT)
102422812Smckusick 			q = (tagptr) mkconv(tyint, q);
102522812Smckusick 		p->datap = q ;
102622812Smckusick 		}
102722812Smckusick 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
102822812Smckusick 		q->primblock.namep->vclass==CLPROC)
102922812Smckusick 			p->datap = (tagptr) mkaddr(q->primblock.namep);
103022812Smckusick 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
103122812Smckusick 		q->primblock.namep->vdim!=NULL)
103222812Smckusick 			p->datap = (tagptr) mkscalar(q->primblock.namep);
103322812Smckusick 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
103422812Smckusick 		q->primblock.namep->vdovar &&
103522812Smckusick 		(t = (tagptr) memversion(q->primblock.namep)) )
103622812Smckusick 			p->datap = (tagptr) fixtype(t);
103722812Smckusick 	else
103822812Smckusick 		p->datap = (tagptr) fixtype(q);
103922812Smckusick 	}
104022812Smckusick return(nargs);
104122812Smckusick }
104222812Smckusick 
104322812Smckusick 
mkscalar(np)104422812Smckusick Addrp mkscalar(np)
104522812Smckusick register Namep np;
104622812Smckusick {
104722812Smckusick register Addrp ap;
104822812Smckusick 
104922812Smckusick vardcl(np);
105022812Smckusick ap = mkaddr(np);
105122812Smckusick 
105222812Smckusick #if TARGET == VAX
105322812Smckusick 	/* on the VAX, prolog causes array arguments
105422812Smckusick 	   to point at the (0,...,0) element, except when
105522812Smckusick 	   subscript checking is on
105622812Smckusick 	*/
105722812Smckusick #ifdef SDB
105822812Smckusick 	if( !checksubs && !sdbflag && np->vstg==STGARG)
105922812Smckusick #else
106022812Smckusick 	if( !checksubs && np->vstg==STGARG)
106122812Smckusick #endif
106222812Smckusick 		{
106322812Smckusick 		register struct Dimblock *dp;
106422812Smckusick 		dp = np->vdim;
106522812Smckusick 		frexpr(ap->memoffset);
106622812Smckusick 		ap->memoffset = mkexpr(OPSTAR,
106722812Smckusick 				(np->vtype==TYCHAR ?
106822812Smckusick 					cpexpr(np->vleng) :
106922812Smckusick 					(tagptr)ICON(typesize[np->vtype]) ),
107022812Smckusick 				cpexpr(dp->baseoffset) );
107122812Smckusick 		}
107222812Smckusick #endif
107322812Smckusick return(ap);
107422812Smckusick }
107522812Smckusick 
107622812Smckusick 
107722812Smckusick 
107822812Smckusick 
107922812Smckusick 
mkfunct(p)108022812Smckusick expptr mkfunct(p)
108122812Smckusick register struct Primblock *p;
108222812Smckusick {
108322812Smckusick struct Entrypoint *ep;
108422812Smckusick Addrp ap;
108522812Smckusick struct Extsym *extp;
108622812Smckusick register Namep np;
108722812Smckusick register expptr q;
108822812Smckusick expptr intrcall(), stfcall();
108922812Smckusick int k, nargs;
109022812Smckusick int class;
109122812Smckusick 
109222812Smckusick if(p->tag != TPRIM)
109322812Smckusick 	return( errnode() );
109422812Smckusick 
109522812Smckusick np = p->namep;
109622812Smckusick class = np->vclass;
109722812Smckusick 
109822812Smckusick if(class == CLUNKNOWN)
109922812Smckusick 	{
110022812Smckusick 	np->vclass = class = CLPROC;
110122812Smckusick 	if(np->vstg == STGUNKNOWN)
110222812Smckusick 		{
110322812Smckusick 		if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
110422812Smckusick 			{
110522812Smckusick 			np->vstg = STGINTR;
110622812Smckusick 			np->vardesc.varno = k;
110722812Smckusick 			np->vprocclass = PINTRINSIC;
110822812Smckusick 			}
110922812Smckusick 		else
111022812Smckusick 			{
111122812Smckusick 			extp = mkext( varunder(VL,np->varname) );
111222812Smckusick 			extp->extstg = STGEXT;
111322812Smckusick 			np->vstg = STGEXT;
111422812Smckusick 			np->vardesc.varno = extp - extsymtab;
111522812Smckusick 			np->vprocclass = PEXTERNAL;
111622812Smckusick 			}
111722812Smckusick 		}
111822812Smckusick 	else if(np->vstg==STGARG)
111922812Smckusick 		{
112022812Smckusick 		if(np->vtype!=TYCHAR && !ftn66flag)
112122812Smckusick 		    warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
112222812Smckusick 		np->vprocclass = PEXTERNAL;
112322812Smckusick 		}
112422812Smckusick 	}
112522812Smckusick 
112622812Smckusick if(class != CLPROC)
112722812Smckusick 	fatali("invalid class code %d for function", class);
112822812Smckusick if(p->fcharp || p->lcharp)
112922812Smckusick 	{
113022812Smckusick 	err("no substring of function call");
113122812Smckusick 	goto error;
113222812Smckusick 	}
113322812Smckusick impldcl(np);
113422812Smckusick nargs = fixargs( np->vprocclass!=PINTRINSIC,  p->argsp);
113522812Smckusick 
113622812Smckusick switch(np->vprocclass)
113722812Smckusick 	{
113822812Smckusick 	case PEXTERNAL:
113922812Smckusick 		ap = mkaddr(np);
114022812Smckusick 	call:
114122812Smckusick 		q = mkexpr(OPCALL, ap, p->argsp);
114222812Smckusick 		if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
114322812Smckusick 			{
114422812Smckusick 			err("attempt to use untyped function");
114522812Smckusick 			goto error;
114622812Smckusick 			}
114722812Smckusick 		if(np->vleng)
114822812Smckusick 			q->exprblock.vleng = (expptr) cpexpr(np->vleng);
114922812Smckusick 		break;
115022812Smckusick 
115122812Smckusick 	case PINTRINSIC:
115222812Smckusick 		q = intrcall(np, p->argsp, nargs);
115322812Smckusick 		break;
115422812Smckusick 
115522812Smckusick 	case PSTFUNCT:
115622812Smckusick 		q = stfcall(np, p->argsp);
115722812Smckusick 		break;
115822812Smckusick 
115922812Smckusick 	case PTHISPROC:
116022812Smckusick 		warn("recursive call");
116122812Smckusick 		for(ep = entries ; ep ; ep = ep->entnextp)
116222812Smckusick 			if(ep->enamep == np)
116322812Smckusick 				break;
116422812Smckusick 		if(ep == NULL)
116522812Smckusick 			fatal("mkfunct: impossible recursion");
116622812Smckusick 		ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
116722812Smckusick 		goto call;
116822812Smckusick 
116922812Smckusick 	default:
117022812Smckusick 		fatali("mkfunct: impossible vprocclass %d",
117122812Smckusick 			(int) (np->vprocclass) );
117222812Smckusick 	}
117322812Smckusick free( (charptr) p );
117422812Smckusick return(q);
117522812Smckusick 
117622812Smckusick error:
117722812Smckusick 	frexpr(p);
117822812Smckusick 	return( errnode() );
117922812Smckusick }
118022812Smckusick 
118122812Smckusick 
118222812Smckusick 
stfcall(np,actlist)118322812Smckusick LOCAL expptr stfcall(np, actlist)
118422812Smckusick Namep np;
118522812Smckusick struct Listblock *actlist;
118622812Smckusick {
118722812Smckusick register chainp actuals;
118822812Smckusick int nargs;
118922812Smckusick chainp oactp, formals;
119022812Smckusick int type;
119122812Smckusick expptr q, rhs, ap;
119222812Smckusick Namep tnp;
119322812Smckusick register struct Rplblock *rp;
119422812Smckusick struct Rplblock *tlist;
119522812Smckusick 
119622812Smckusick if(actlist)
119722812Smckusick 	{
119822812Smckusick 	actuals = actlist->listp;
119922812Smckusick 	free( (charptr) actlist);
120022812Smckusick 	}
120122812Smckusick else
120222812Smckusick 	actuals = NULL;
120322812Smckusick oactp = actuals;
120422812Smckusick 
120522812Smckusick nargs = 0;
120622812Smckusick tlist = NULL;
120722812Smckusick if( (type = np->vtype) == TYUNKNOWN)
120822812Smckusick 	{
120922812Smckusick 	err("attempt to use untyped statement function");
121022812Smckusick 	q = errnode();
121122812Smckusick 	goto ret;
121222812Smckusick 	}
121322812Smckusick formals = (chainp) (np->varxptr.vstfdesc->datap);
121422812Smckusick rhs = (expptr) (np->varxptr.vstfdesc->nextp);
121522812Smckusick 
121622812Smckusick /* copy actual arguments into temporaries */
121722812Smckusick while(actuals!=NULL && formals!=NULL)
121822812Smckusick 	{
121922812Smckusick 	rp = ALLOC(Rplblock);
122022812Smckusick 	rp->rplnp = tnp = (Namep) (formals->datap);
122122812Smckusick 	ap = fixtype(actuals->datap);
122222812Smckusick 	if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
122322812Smckusick 	   && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
122422812Smckusick 		{
122522812Smckusick 		rp->rplvp = (expptr) ap;
122622812Smckusick 		rp->rplxp = NULL;
122722812Smckusick 		rp->rpltag = ap->tag;
122822812Smckusick 		}
122922812Smckusick 	else	{
123022812Smckusick 		rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
123122812Smckusick 		rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
123222812Smckusick 		if( (rp->rpltag = rp->rplxp->tag) == TERROR)
123322812Smckusick 			err("disagreement of argument types in statement function call");
123422812Smckusick 		else if(tnp->vtype!=ap->headblock.vtype)
123522812Smckusick 			warn("argument type mismatch in statement function");
123622812Smckusick 		}
123722812Smckusick 	rp->rplnextp = tlist;
123822812Smckusick 	tlist = rp;
123922812Smckusick 	actuals = actuals->nextp;
124022812Smckusick 	formals = formals->nextp;
124122812Smckusick 	++nargs;
124222812Smckusick 	}
124322812Smckusick 
124422812Smckusick if(actuals!=NULL || formals!=NULL)
124522812Smckusick 	err("statement function definition and argument list differ");
124622812Smckusick 
124722812Smckusick /*
124822812Smckusick    now push down names involved in formal argument list, then
124922812Smckusick    evaluate rhs of statement function definition in this environment
125022812Smckusick */
125122812Smckusick 
125222812Smckusick if(tlist)	/* put tlist in front of the rpllist */
125322812Smckusick 	{
125422812Smckusick 	for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
125522812Smckusick 		;
125622812Smckusick 	rp->rplnextp = rpllist;
125722812Smckusick 	rpllist = tlist;
125822812Smckusick 	}
125922812Smckusick 
126022812Smckusick q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
126122812Smckusick 
126222812Smckusick /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
126322812Smckusick while(--nargs >= 0)
126422812Smckusick 	{
126522812Smckusick 	if(rpllist->rplxp)
126622812Smckusick 		q = mkexpr(OPCOMMA, rpllist->rplxp, q);
126722812Smckusick 	rp = rpllist->rplnextp;
126822812Smckusick 	frexpr(rpllist->rplvp);
126922812Smckusick 	free(rpllist);
127022812Smckusick 	rpllist = rp;
127122812Smckusick 	}
127222812Smckusick 
127322812Smckusick ret:
127422812Smckusick 	frchain( &oactp );
127522812Smckusick 	return(q);
127622812Smckusick }
127722812Smckusick 
127822812Smckusick 
127922812Smckusick 
128022812Smckusick 
mkplace(np)128122812Smckusick Addrp mkplace(np)
128222812Smckusick register Namep np;
128322812Smckusick {
128422812Smckusick register Addrp s;
128522812Smckusick register struct Rplblock *rp;
128622812Smckusick int regn;
128722812Smckusick 
128822812Smckusick /* is name on the replace list? */
128922812Smckusick 
129022812Smckusick for(rp = rpllist ; rp ; rp = rp->rplnextp)
129122812Smckusick 	{
129222812Smckusick 	if(np == rp->rplnp)
129322812Smckusick 		{
129422812Smckusick 		if(rp->rpltag == TNAME)
129522812Smckusick 			{
129622812Smckusick 			np = (Namep) (rp->rplvp);
129722812Smckusick 			break;
129822812Smckusick 			}
129922812Smckusick 		else	return( (Addrp) cpexpr(rp->rplvp) );
130022812Smckusick 		}
130122812Smckusick 	}
130222812Smckusick 
130322812Smckusick /* is variable a DO index in a register ? */
130422812Smckusick 
130522812Smckusick if(np->vdovar && ( (regn = inregister(np)) >= 0) )
130622812Smckusick 	if(np->vtype == TYERROR)
130722812Smckusick 		return( (Addrp) errnode() );
130822812Smckusick 	else
130922812Smckusick 		{
131022812Smckusick 		s = ALLOC(Addrblock);
131122812Smckusick 		s->tag = TADDR;
131222812Smckusick 		s->vstg = STGREG;
131322812Smckusick 		s->vtype = TYIREG;
131422812Smckusick 		s->issaved = np->vsave;
131522812Smckusick 		s->memno = regn;
131622812Smckusick 		s->memoffset = ICON(0);
131722812Smckusick 		return(s);
131822812Smckusick 		}
131922812Smckusick 
132022812Smckusick vardcl(np);
132122812Smckusick return(mkaddr(np));
132222812Smckusick }
132322812Smckusick 
132422812Smckusick 
132522812Smckusick 
132622812Smckusick 
mklhs(p)132722812Smckusick expptr mklhs(p)
132822812Smckusick register struct Primblock *p;
132922812Smckusick {
133022812Smckusick expptr suboffset();
133125736Sdonn expptr ep = ENULL;
133222812Smckusick register Addrp s;
133322812Smckusick Namep np;
133422812Smckusick 
133522812Smckusick if(p->tag != TPRIM)
133622812Smckusick 	return( (expptr) p );
133722812Smckusick np = p->namep;
133822812Smckusick 
133922812Smckusick s = mkplace(np);
134022812Smckusick if(s->tag!=TADDR || s->vstg==STGREG)
134122812Smckusick 	{
134222812Smckusick 	free( (charptr) p );
134322812Smckusick 	return( (expptr) s );
134422812Smckusick 	}
134522812Smckusick 
134625736Sdonn /* do the substring part */
134722812Smckusick 
134822812Smckusick if(p->fcharp || p->lcharp)
134922812Smckusick 	{
135022812Smckusick 	if(np->vtype != TYCHAR)
135122812Smckusick 		errstr("substring of noncharacter %s", varstr(VL,np->varname));
135222812Smckusick 	else	{
135322812Smckusick 		if(p->lcharp == NULL)
135422812Smckusick 			p->lcharp = (expptr) cpexpr(s->vleng);
135522812Smckusick 		frexpr(s->vleng);
135622812Smckusick 		if(p->fcharp)
135722812Smckusick 			{
135822812Smckusick 			if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
135925736Sdonn 			&& p->fcharp->primblock.namep == p->lcharp->primblock.namep
136025736Sdonn 			&& p->fcharp->primblock.argsp == NULL
136125736Sdonn 			&& p->lcharp->primblock.argsp == NULL)
136222812Smckusick 				/* A trivial optimization -- upper == lower */
136322812Smckusick 				s->vleng = ICON(1);
136422812Smckusick 			else
136525736Sdonn 				{
136625736Sdonn 				if(p->fcharp->tag == TEXPR
136725736Sdonn 				|| (p->fcharp->tag == TPRIM
136825736Sdonn 				   && p->fcharp->primblock.argsp != NULL))
136925736Sdonn 					{
137026307Sdonn 					ep = fixtype(cpexpr(p->fcharp));
137125736Sdonn 					p->fcharp = (expptr) mktemp(ep->headblock.vtype, ENULL);
137225736Sdonn 					}
137322812Smckusick 				s->vleng = mkexpr(OPMINUS, p->lcharp,
137426307Sdonn 				 mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
137525736Sdonn 				}
137622812Smckusick 			}
137722812Smckusick 		else
137822812Smckusick 			s->vleng = p->lcharp;
137922812Smckusick 		}
138022812Smckusick 	}
138122812Smckusick 
138225736Sdonn /* compute the address modified by subscripts */
138325736Sdonn 
138425736Sdonn s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
138525736Sdonn frexpr(p->argsp);
138625736Sdonn p->argsp = NULL;
138725736Sdonn 
138822812Smckusick s->vleng = fixtype( s->vleng );
138922812Smckusick s->memoffset = fixtype( s->memoffset );
139025736Sdonn if(ep)
139125736Sdonn 	/* this code depends on memoffset being evaluated before vleng */
139225736Sdonn 	s->memoffset = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(p->fcharp), ep), s->memoffset);
139326307Sdonn frexpr(p->fcharp);
139422812Smckusick free( (charptr) p );
139522812Smckusick return( (expptr) s );
139622812Smckusick }
139722812Smckusick 
139822812Smckusick 
139922812Smckusick 
140022812Smckusick 
140122812Smckusick 
deregister(np)140222812Smckusick deregister(np)
140322812Smckusick Namep np;
140422812Smckusick {
140522812Smckusick if(nregvar>0 && regnamep[nregvar-1]==np)
140622812Smckusick 	{
140722812Smckusick 	--nregvar;
140822812Smckusick #if FAMILY == DMR
140922812Smckusick 	putnreg();
141022812Smckusick #endif
141122812Smckusick 	}
141222812Smckusick }
141322812Smckusick 
141422812Smckusick 
141522812Smckusick 
141622812Smckusick 
memversion(np)141722812Smckusick Addrp memversion(np)
141822812Smckusick register Namep np;
141922812Smckusick {
142022812Smckusick register Addrp s;
142122812Smckusick 
142222812Smckusick if(np->vdovar==NO || (inregister(np)<0) )
142322812Smckusick 	return(NULL);
142422812Smckusick np->vdovar = NO;
142522812Smckusick s = mkplace(np);
142622812Smckusick np->vdovar = YES;
142722812Smckusick return(s);
142822812Smckusick }
142922812Smckusick 
143022812Smckusick 
143122812Smckusick 
inregister(np)143222812Smckusick inregister(np)
143322812Smckusick register Namep np;
143422812Smckusick {
143522812Smckusick register int i;
143622812Smckusick 
143722812Smckusick for(i = 0 ; i < nregvar ; ++i)
143822812Smckusick 	if(regnamep[i] == np)
143922812Smckusick 		return( regnum[i] );
144022812Smckusick return(-1);
144122812Smckusick }
144222812Smckusick 
144322812Smckusick 
144422812Smckusick 
144522812Smckusick 
enregister(np)144622812Smckusick enregister(np)
144722812Smckusick Namep np;
144822812Smckusick {
144922812Smckusick if( inregister(np) >= 0)
145022812Smckusick 	return(YES);
145122812Smckusick if(nregvar >= maxregvar)
145222812Smckusick 	return(NO);
145322812Smckusick vardcl(np);
145422812Smckusick if( ONEOF(np->vtype, MSKIREG) )
145522812Smckusick 	{
145622812Smckusick 	regnamep[nregvar++] = np;
145722812Smckusick 	if(nregvar > highregvar)
145822812Smckusick 		highregvar = nregvar;
145922812Smckusick #if FAMILY == DMR
146022812Smckusick 	putnreg();
146122812Smckusick #endif
146222812Smckusick 	return(YES);
146322812Smckusick 	}
146422812Smckusick else
146522812Smckusick 	return(NO);
146622812Smckusick }
146722812Smckusick 
146822812Smckusick 
146922812Smckusick 
147022812Smckusick 
suboffset(p)147122812Smckusick expptr suboffset(p)
147222812Smckusick register struct Primblock *p;
147322812Smckusick {
147422812Smckusick int n;
147522812Smckusick expptr size;
147622812Smckusick expptr oftwo();
147722812Smckusick chainp cp;
147822812Smckusick expptr offp, prod;
147922812Smckusick expptr subcheck();
148022812Smckusick struct Dimblock *dimp;
148122812Smckusick expptr sub[MAXDIM+1];
148222812Smckusick register Namep np;
148322812Smckusick 
148422812Smckusick np = p->namep;
148522812Smckusick offp = ICON(0);
148622812Smckusick n = 0;
148722812Smckusick if(p->argsp)
148822812Smckusick 	for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
148922812Smckusick 		{
149022812Smckusick 		sub[n] = fixtype(cpexpr(cp->datap));
149122812Smckusick 		if ( ! ISINT(sub[n]->headblock.vtype)) {
149222812Smckusick 			errstr("%s: non-integer subscript expression",
149322812Smckusick 				varstr(VL, np->varname) );
149422812Smckusick 			/* Provide a substitute -- go on to find more errors */
149522812Smckusick 			frexpr(sub[n]);
149622812Smckusick 			sub[n] = ICON(1);
149722812Smckusick 		}
149822812Smckusick 		if(n > maxdim)
149922812Smckusick 			{
150022812Smckusick 			   char str[28+VL];
150122812Smckusick 			   sprintf(str, "%s: more than %d subscripts",
150222812Smckusick 				varstr(VL, np->varname), maxdim );
150322812Smckusick 			   err( str );
150422812Smckusick 			break;
150522812Smckusick 			}
150622812Smckusick 		}
150722812Smckusick 
150822812Smckusick dimp = np->vdim;
150922812Smckusick if(n>0 && dimp==NULL)
151022812Smckusick 	errstr("%s: subscripts on scalar variable",
151122812Smckusick 		varstr(VL, np->varname), maxdim );
151222812Smckusick else if(dimp && dimp->ndim!=n)
151322812Smckusick 	errstr("wrong number of subscripts on %s",
151422812Smckusick 		varstr(VL, np->varname) );
151522812Smckusick else if(n > 0)
151622812Smckusick 	{
151722812Smckusick 	prod = sub[--n];
151822812Smckusick 	while( --n >= 0)
151922812Smckusick 		prod = mkexpr(OPPLUS, sub[n],
152022812Smckusick 			mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
152122812Smckusick #if TARGET == VAX
152222812Smckusick #ifdef SDB
152322812Smckusick 	if(checksubs || np->vstg!=STGARG || sdbflag)
152422812Smckusick #else
152522812Smckusick 	if(checksubs || np->vstg!=STGARG)
152622812Smckusick #endif
152722812Smckusick 		prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
152822812Smckusick #else
152922812Smckusick 	prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
153022812Smckusick #endif
153122812Smckusick 	if(checksubs)
153222812Smckusick 		prod = subcheck(np, prod);
153322812Smckusick 	size = np->vtype == TYCHAR ?
153422812Smckusick 		(expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
153522812Smckusick 	if (!oftwo(size))
153622812Smckusick 		prod = mkexpr(OPSTAR, prod, size);
153722812Smckusick 	else
153822812Smckusick 		prod = mkexpr(OPLSHIFT,prod,oftwo(size));
153922812Smckusick 
154022812Smckusick 	offp = mkexpr(OPPLUS, offp, prod);
154122812Smckusick 	}
154222812Smckusick 
154322812Smckusick if(p->fcharp && np->vtype==TYCHAR)
154422812Smckusick 	offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
154522812Smckusick 
154622812Smckusick return(offp);
154722812Smckusick }
154822812Smckusick 
154922812Smckusick 
155022812Smckusick 
155122812Smckusick 
subcheck(np,p)155222812Smckusick expptr subcheck(np, p)
155322812Smckusick Namep np;
155422812Smckusick register expptr p;
155522812Smckusick {
155622812Smckusick struct Dimblock *dimp;
155722812Smckusick expptr t, checkvar, checkcond, badcall;
155822812Smckusick 
155922812Smckusick dimp = np->vdim;
156022812Smckusick if(dimp->nelt == NULL)
156122812Smckusick 	return(p);	/* don't check arrays with * bounds */
156222812Smckusick checkvar = NULL;
156322812Smckusick checkcond = NULL;
156422812Smckusick if( ISICON(p) )
156522812Smckusick 	{
156633256Sbostic 	if(p->constblock.constant.ci < 0)
156722812Smckusick 		goto badsub;
156822812Smckusick 	if( ISICON(dimp->nelt) )
156933256Sbostic 		if(p->constblock.constant.ci < dimp->nelt->constblock.constant.ci)
157022812Smckusick 			return(p);
157122812Smckusick 		else
157222812Smckusick 			goto badsub;
157322812Smckusick 	}
157422812Smckusick if(p->tag==TADDR && p->addrblock.vstg==STGREG)
157522812Smckusick 	{
157622812Smckusick 	checkvar = (expptr) cpexpr(p);
157722812Smckusick 	t = p;
157822812Smckusick 	}
157922812Smckusick else	{
158022812Smckusick 	checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
158122812Smckusick 	t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
158222812Smckusick 	}
158322812Smckusick checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
158422812Smckusick if( ! ISICON(p) )
158522812Smckusick 	checkcond = mkexpr(OPAND, checkcond,
158622812Smckusick 			mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
158722812Smckusick 
158822812Smckusick badcall = call4(p->headblock.vtype, "s_rnge",
158922812Smckusick 		mkstrcon(VL, np->varname),
159022812Smckusick 		mkconv(TYLONG,  cpexpr(checkvar)),
159122812Smckusick 		mkstrcon(XL, procname),
159222812Smckusick 		ICON(lineno) );
159322812Smckusick badcall->exprblock.opcode = OPCCALL;
159422812Smckusick p = mkexpr(OPQUEST, checkcond,
159522812Smckusick 	mkexpr(OPCOLON, checkvar, badcall));
159622812Smckusick 
159722812Smckusick return(p);
159822812Smckusick 
159922812Smckusick badsub:
160022812Smckusick 	frexpr(p);
160122812Smckusick 	errstr("subscript on variable %s out of range", varstr(VL,np->varname));
160222812Smckusick 	return ( ICON(0) );
160322812Smckusick }
160422812Smckusick 
160522812Smckusick 
160622812Smckusick 
160722812Smckusick 
mkaddr(p)160822812Smckusick Addrp mkaddr(p)
160922812Smckusick register Namep p;
161022812Smckusick {
161122812Smckusick struct Extsym *extp;
161222812Smckusick register Addrp t;
161322812Smckusick Addrp intraddr();
161422812Smckusick 
161522812Smckusick switch( p->vstg)
161622812Smckusick 	{
161722812Smckusick 	case STGUNKNOWN:
161822812Smckusick 		if(p->vclass != CLPROC)
161922812Smckusick 			break;
162022812Smckusick 		extp = mkext( varunder(VL, p->varname) );
162122812Smckusick 		extp->extstg = STGEXT;
162222812Smckusick 		p->vstg = STGEXT;
162322812Smckusick 		p->vardesc.varno = extp - extsymtab;
162422812Smckusick 		p->vprocclass = PEXTERNAL;
162522812Smckusick 
162622812Smckusick 	case STGCOMMON:
162722812Smckusick 	case STGEXT:
162822812Smckusick 	case STGBSS:
162922812Smckusick 	case STGINIT:
163022812Smckusick 	case STGEQUIV:
163122812Smckusick 	case STGARG:
163222812Smckusick 	case STGLENG:
163322812Smckusick 	case STGAUTO:
163422812Smckusick 		t = ALLOC(Addrblock);
163522812Smckusick 		t->tag = TADDR;
163622812Smckusick 		if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
163722812Smckusick 			t->vclass = CLVAR;
163822812Smckusick 		else
163922812Smckusick 			t->vclass = p->vclass;
164022812Smckusick 		t->vtype = p->vtype;
164122812Smckusick 		t->vstg = p->vstg;
164222812Smckusick 		t->memno = p->vardesc.varno;
164322812Smckusick 		t->issaved = p->vsave;
164422812Smckusick                 if(p->vdim) t->isarray = YES;
164522812Smckusick 		t->memoffset = ICON(p->voffset);
164622812Smckusick 		if(p->vleng)
164722812Smckusick 			{
164822812Smckusick 			t->vleng = (expptr) cpexpr(p->vleng);
164922812Smckusick 			if( ISICON(t->vleng) )
165033256Sbostic 				t->varleng = t->vleng->constblock.constant.ci;
165122812Smckusick 			}
165222812Smckusick 		if (p->vstg == STGBSS)
165322812Smckusick 			t->varsize = p->varsize;
165422812Smckusick 		else if (p->vstg == STGEQUIV)
165522812Smckusick 			t->varsize = eqvclass[t->memno].eqvleng;
165622812Smckusick 		return(t);
165722812Smckusick 
165822812Smckusick 	case STGINTR:
165922812Smckusick 		return( intraddr(p) );
166022812Smckusick 
166122812Smckusick 	}
166222812Smckusick /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
166322812Smckusick badstg("mkaddr", p->vstg);
166422812Smckusick /* NOTREACHED */
166522812Smckusick }
166622812Smckusick 
166722812Smckusick 
166822812Smckusick 
166922812Smckusick 
mkarg(type,argno)167022812Smckusick Addrp mkarg(type, argno)
167122812Smckusick int type, argno;
167222812Smckusick {
167322812Smckusick register Addrp p;
167422812Smckusick 
167522812Smckusick p = ALLOC(Addrblock);
167622812Smckusick p->tag = TADDR;
167722812Smckusick p->vtype = type;
167822812Smckusick p->vclass = CLVAR;
167922812Smckusick p->vstg = (type==TYLENG ? STGLENG : STGARG);
168022812Smckusick p->memno = argno;
168122812Smckusick return(p);
168222812Smckusick }
168322812Smckusick 
168422812Smckusick 
168522812Smckusick 
168622812Smckusick 
168722812Smckusick expptr mkprim(v, args, substr)
168822812Smckusick register union
168922812Smckusick 	{
169022812Smckusick 	struct Paramblock paramblock;
169122812Smckusick 	struct Nameblock nameblock;
169222812Smckusick 	struct Headblock headblock;
169322812Smckusick 	} *v;
169422812Smckusick struct Listblock *args;
169522812Smckusick chainp substr;
169622812Smckusick {
169722812Smckusick register struct Primblock *p;
169822812Smckusick 
169922812Smckusick if(v->headblock.vclass == CLPARAM)
170022812Smckusick 	{
170122812Smckusick 	if(args || substr)
170222812Smckusick 		{
170322812Smckusick 		errstr("no qualifiers on parameter name %s",
170422812Smckusick 			varstr(VL,v->paramblock.varname));
170522812Smckusick 		frexpr(args);
170622812Smckusick 		if(substr)
170722812Smckusick 			{
170822812Smckusick 			frexpr(substr->datap);
170922812Smckusick 			frexpr(substr->nextp->datap);
171022812Smckusick 			frchain(&substr);
171122812Smckusick 			}
171222812Smckusick 		frexpr(v);
171322812Smckusick 		return( errnode() );
171422812Smckusick 		}
171522812Smckusick 	return( (expptr) cpexpr(v->paramblock.paramval) );
171622812Smckusick 	}
171722812Smckusick 
171822812Smckusick p = ALLOC(Primblock);
171922812Smckusick p->tag = TPRIM;
172022812Smckusick p->vtype = v->nameblock.vtype;
172122812Smckusick p->namep = (Namep) v;
172222812Smckusick p->argsp = args;
172322812Smckusick if(substr)
172422812Smckusick 	{
172523680Smckusick 	p->fcharp = (expptr) substr->datap;
172624477Sdonn 	if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
172723680Smckusick 		p->fcharp = mkconv(TYINT, p->fcharp);
172823680Smckusick 	p->lcharp = (expptr) substr->nextp->datap;
172924477Sdonn 	if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
173023680Smckusick 		p->lcharp = mkconv(TYINT, p->lcharp);
173122812Smckusick 	frchain(&substr);
173222812Smckusick 	}
173322812Smckusick return( (expptr) p);
173422812Smckusick }
173522812Smckusick 
173622812Smckusick 
173722812Smckusick 
vardcl(v)173822812Smckusick vardcl(v)
173922812Smckusick register Namep v;
174022812Smckusick {
174122812Smckusick int nelt;
174222812Smckusick struct Dimblock *t;
174322812Smckusick Addrp p;
174422812Smckusick expptr neltp;
174522812Smckusick int eltsize;
174622812Smckusick int varsize;
174722812Smckusick int tsize;
174822812Smckusick int align;
174922812Smckusick 
175022812Smckusick if(v->vdcldone)
175122812Smckusick 	return;
175222812Smckusick if(v->vclass == CLNAMELIST)
175322812Smckusick 	return;
175422812Smckusick 
175522812Smckusick if(v->vtype == TYUNKNOWN)
175622812Smckusick 	impldcl(v);
175722812Smckusick if(v->vclass == CLUNKNOWN)
175822812Smckusick 	v->vclass = CLVAR;
175922812Smckusick else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
176022812Smckusick 	{
176122812Smckusick 	dclerr("used both as variable and non-variable", v);
176222812Smckusick 	return;
176322812Smckusick 	}
176422812Smckusick if(v->vstg==STGUNKNOWN)
176522812Smckusick 	v->vstg = implstg[ letter(v->varname[0]) ];
176622812Smckusick 
176722812Smckusick switch(v->vstg)
176822812Smckusick 	{
176922812Smckusick 	case STGBSS:
177022812Smckusick 		v->vardesc.varno = ++lastvarno;
177122812Smckusick 		if (v->vclass != CLVAR)
177222812Smckusick 			break;
177322812Smckusick 		nelt = 1;
177422812Smckusick 		t = v->vdim;
177522812Smckusick 		if (t)
177622812Smckusick 			{
177722812Smckusick 			neltp = t->nelt;
177822812Smckusick 			if (neltp && ISICON(neltp))
177933256Sbostic 				nelt = neltp->constblock.constant.ci;
178022812Smckusick 			else
178122812Smckusick 				dclerr("improperly dimensioned array", v);
178222812Smckusick 			}
178322812Smckusick 
178422812Smckusick 		if (v->vtype == TYCHAR)
178522812Smckusick 			{
178622812Smckusick 			v->vleng = fixtype(v->vleng);
178722812Smckusick 			if (v->vleng == NULL)
178822812Smckusick 				eltsize = typesize[TYCHAR];
178922812Smckusick 			else if (ISICON(v->vleng))
179022812Smckusick 				eltsize = typesize[TYCHAR] *
179133256Sbostic 					v->vleng->constblock.constant.ci;
179222812Smckusick 			else if (v->vleng->tag != TERROR)
179322812Smckusick 				{
179422812Smckusick 				errstr("nonconstant string length on %s",
179522812Smckusick 					varstr(VL, v->varname));
179622812Smckusick 				eltsize = 0;
179722812Smckusick 				}
179822812Smckusick 			}
179922812Smckusick 		else
180022812Smckusick 			eltsize = typesize[v->vtype];
180122812Smckusick 
180222812Smckusick 		v->varsize = nelt * eltsize;
180322812Smckusick 		break;
180422812Smckusick 	case STGAUTO:
180522812Smckusick 		if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
180622812Smckusick 			break;
180722812Smckusick 		nelt = 1;
180822812Smckusick 		if(t = v->vdim)
180922812Smckusick 			if( (neltp = t->nelt) && ISCONST(neltp) )
181033256Sbostic 				nelt = neltp->constblock.constant.ci;
181122812Smckusick 			else
181222812Smckusick 				dclerr("adjustable automatic array", v);
181322812Smckusick 		p = autovar(nelt, v->vtype, v->vleng);
181422812Smckusick 		v->vardesc.varno = p->memno;
181533256Sbostic 		v->voffset = p->memoffset->constblock.constant.ci;
181622812Smckusick 		frexpr(p);
181722812Smckusick 		break;
181822812Smckusick 
181922812Smckusick 	default:
182022812Smckusick 		break;
182122812Smckusick 	}
182222812Smckusick v->vdcldone = YES;
182322812Smckusick }
182422812Smckusick 
182522812Smckusick 
182622812Smckusick 
182722812Smckusick 
impldcl(p)182822812Smckusick impldcl(p)
182922812Smckusick register Namep p;
183022812Smckusick {
183122812Smckusick register int k;
183222812Smckusick int type, leng;
183322812Smckusick 
183422812Smckusick if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
183522812Smckusick 	return;
183622812Smckusick if(p->vtype == TYUNKNOWN)
183722812Smckusick 	{
183822812Smckusick 	k = letter(p->varname[0]);
183922812Smckusick 	type = impltype[ k ];
184022812Smckusick 	leng = implleng[ k ];
184122812Smckusick 	if(type == TYUNKNOWN)
184222812Smckusick 		{
184322812Smckusick 		if(p->vclass == CLPROC)
184423476Smckusick 			dclerr("attempt to use function of undefined type", p);
184523476Smckusick 		else
184623476Smckusick 			dclerr("attempt to use undefined variable", p);
184722812Smckusick 		type = TYERROR;
184822812Smckusick 		leng = 1;
184922812Smckusick 		}
185022812Smckusick 	settype(p, type, leng);
185122812Smckusick 	}
185222812Smckusick }
185322812Smckusick 
185422812Smckusick 
185522812Smckusick 
185622812Smckusick 
letter(c)185722812Smckusick LOCAL letter(c)
185822812Smckusick register int c;
185922812Smckusick {
186022812Smckusick if( isupper(c) )
186122812Smckusick 	c = tolower(c);
186222812Smckusick return(c - 'a');
186322812Smckusick }
186422812Smckusick 
186533256Sbostic #define ICONEQ(z, c)  (ISICON(z) && z->constblock.constant.ci==c)
186622812Smckusick #define COMMUTE	{ e = lp;  lp = rp;  rp = e; }
186722812Smckusick 
186822812Smckusick 
mkexpr(opcode,lp,rp)186922812Smckusick expptr mkexpr(opcode, lp, rp)
187022812Smckusick int opcode;
187122812Smckusick register expptr lp, rp;
187222812Smckusick {
187322812Smckusick register expptr e, e1;
187422812Smckusick int etype;
187522812Smckusick int ltype, rtype;
187622812Smckusick int ltag, rtag;
187722812Smckusick expptr q, q1;
187822812Smckusick expptr fold();
187922812Smckusick int k;
188022812Smckusick 
188122812Smckusick ltype = lp->headblock.vtype;
188222812Smckusick ltag = lp->tag;
188322812Smckusick if(rp && opcode!=OPCALL && opcode!=OPCCALL)
188422812Smckusick 	{
188522812Smckusick 	rtype = rp->headblock.vtype;
188622812Smckusick 	rtag = rp->tag;
188722812Smckusick 	}
188822812Smckusick else	{
188922812Smckusick 	rtype = 0;
189022812Smckusick 	rtag = 0;
189122812Smckusick 	}
189222812Smckusick 
189322812Smckusick /*
189422812Smckusick  * Yuck.  Why can't we fold constants AFTER
189522812Smckusick  * variables are implicitly declared???
189622812Smckusick  */
189722812Smckusick if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
189822812Smckusick 	{
189922812Smckusick 	k = letter(lp->primblock.namep->varname[0]);
190022812Smckusick 	ltype = impltype[ k ];
190122812Smckusick 	}
190222812Smckusick if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
190322812Smckusick 	{
190422812Smckusick 	k = letter(rp->primblock.namep->varname[0]);
190522812Smckusick 	rtype = impltype[ k ];
190622812Smckusick 	}
190722812Smckusick 
190825736Sdonn /*
190925736Sdonn  * Eliminate all but the topmost OPPAREN operator when folding constants.
191025736Sdonn  */
191125736Sdonn if(lp->tag == TEXPR &&
191225736Sdonn    lp->exprblock.opcode == OPPAREN &&
191325736Sdonn    lp->exprblock.leftp->tag == TCONST)
191425736Sdonn 	{
191525736Sdonn 	q = (expptr) cpexpr(lp->exprblock.leftp);
191625736Sdonn 	frexpr(lp);
191725736Sdonn 	lp = q;
191825736Sdonn 	ltag = TCONST;
191925736Sdonn 	ltype = lp->constblock.vtype;
192025736Sdonn 	}
192125736Sdonn if(rp &&
192225736Sdonn    rp->tag == TEXPR &&
192325736Sdonn    rp->exprblock.opcode == OPPAREN &&
192425736Sdonn    rp->exprblock.leftp->tag == TCONST)
192525736Sdonn 	{
192625736Sdonn 	q = (expptr) cpexpr(rp->exprblock.leftp);
192725736Sdonn 	frexpr(rp);
192825736Sdonn 	rp = q;
192925736Sdonn 	rtag = TCONST;
193025736Sdonn 	rtype = rp->constblock.vtype;
193125736Sdonn 	}
193225736Sdonn 
193322812Smckusick etype = cktype(opcode, ltype, rtype);
193422812Smckusick if(etype == TYERROR)
193522812Smckusick 	goto error;
193622812Smckusick 
193725736Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) )
193825736Sdonn 	goto makenode;
193925736Sdonn if(etype == TYUNKNOWN)
194025736Sdonn 	goto makenode;
194125736Sdonn 
194222812Smckusick switch(opcode)
194322812Smckusick 	{
194422812Smckusick 	/* check for multiplication by 0 and 1 and addition to 0 */
194522812Smckusick 
194622812Smckusick 	case OPSTAR:
194722812Smckusick 		if( ISCONST(lp) )
194822812Smckusick 			COMMUTE
194922812Smckusick 
195022812Smckusick 		if( ISICON(rp) )
195122812Smckusick 			{
195233256Sbostic 			if(rp->constblock.constant.ci == 0)
195322812Smckusick 				{
195422812Smckusick 				if(etype == TYUNKNOWN)
195522812Smckusick 					break;
195622812Smckusick 				rp = mkconv(etype, rp);
195722812Smckusick 				goto retright;
195822812Smckusick 				}
195922812Smckusick 			if ((lp->tag == TEXPR) &&
196022812Smckusick 			    ((lp->exprblock.opcode == OPPLUS) ||
196122812Smckusick 			     (lp->exprblock.opcode == OPMINUS)) &&
196222812Smckusick 			    ISCONST(lp->exprblock.rightp) &&
196322812Smckusick 			    ISINT(lp->exprblock.rightp->constblock.vtype))
196422812Smckusick 				{
196522812Smckusick 				q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
196622812Smckusick 					   cpexpr(rp));
196722812Smckusick 				q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
196822812Smckusick 				q = mkexpr(lp->exprblock.opcode, q, q1);
196922812Smckusick 				free ((char *) lp);
197022812Smckusick 				return q;
197122812Smckusick 				}
197222812Smckusick 			else
197322812Smckusick 				goto mulop;
197422812Smckusick 			}
197522812Smckusick 		break;
197622812Smckusick 
197722812Smckusick 	case OPSLASH:
197822812Smckusick 	case OPMOD:
197922812Smckusick 		if( ICONEQ(rp, 0) )
198022812Smckusick 			{
198122812Smckusick 			err("attempted division by zero");
198222812Smckusick 			rp = ICON(1);
198322812Smckusick 			break;
198422812Smckusick 			}
198522812Smckusick 		if(opcode == OPMOD)
198622812Smckusick 			break;
198722812Smckusick 
198822812Smckusick 
198922812Smckusick 	mulop:
199022812Smckusick 		if( ISICON(rp) )
199122812Smckusick 			{
199233256Sbostic 			if(rp->constblock.constant.ci == 1)
199322812Smckusick 				goto retleft;
199422812Smckusick 
199533256Sbostic 			if(rp->constblock.constant.ci == -1)
199622812Smckusick 				{
199722812Smckusick 				frexpr(rp);
199822812Smckusick 				return( mkexpr(OPNEG, lp, PNULL) );
199922812Smckusick 				}
200022812Smckusick 			}
200122812Smckusick 
200222812Smckusick 		if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
200322812Smckusick 			{
200422812Smckusick 			if(opcode == OPSTAR)
200522812Smckusick 				e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
200622812Smckusick 			else  if(ISICON(rp) &&
200733256Sbostic 				(lp->exprblock.rightp->constblock.constant.ci %
200833256Sbostic 					rp->constblock.constant.ci) == 0)
200922812Smckusick 				e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
201022812Smckusick 			else	break;
201122812Smckusick 
201222812Smckusick 			e1 = lp->exprblock.leftp;
201322812Smckusick 			free( (charptr) lp );
201422812Smckusick 			return( mkexpr(OPSTAR, e1, e) );
201522812Smckusick 			}
201622812Smckusick 		break;
201722812Smckusick 
201822812Smckusick 
201922812Smckusick 	case OPPLUS:
202022812Smckusick 		if( ISCONST(lp) )
202122812Smckusick 			COMMUTE
202222812Smckusick 		goto addop;
202322812Smckusick 
202422812Smckusick 	case OPMINUS:
202522812Smckusick 		if( ICONEQ(lp, 0) )
202622812Smckusick 			{
202722812Smckusick 			frexpr(lp);
202822812Smckusick 			return( mkexpr(OPNEG, rp, ENULL) );
202922812Smckusick 			}
203022812Smckusick 
203122812Smckusick 		if( ISCONST(rp) )
203222812Smckusick 			{
203322812Smckusick 			opcode = OPPLUS;
203422812Smckusick 			consnegop(rp);
203522812Smckusick 			}
203622812Smckusick 
203722812Smckusick 	addop:
203822812Smckusick 		if( ISICON(rp) )
203922812Smckusick 			{
204033256Sbostic 			if(rp->constblock.constant.ci == 0)
204122812Smckusick 				goto retleft;
204222812Smckusick 			if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
204322812Smckusick 				{
204422812Smckusick 				e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
204522812Smckusick 				e1 = lp->exprblock.leftp;
204622812Smckusick 				free( (charptr) lp );
204722812Smckusick 				return( mkexpr(OPPLUS, e1, e) );
204822812Smckusick 				}
204922812Smckusick 			}
205022812Smckusick 		break;
205122812Smckusick 
205222812Smckusick 
205322812Smckusick 	case OPPOWER:
205422812Smckusick 		break;
205522812Smckusick 
205622812Smckusick 	case OPNEG:
205722812Smckusick 		if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
205822812Smckusick 			{
205922812Smckusick 			e = lp->exprblock.leftp;
206022812Smckusick 			free( (charptr) lp );
206122812Smckusick 			return(e);
206222812Smckusick 			}
206322812Smckusick 		break;
206422812Smckusick 
206522812Smckusick 	case OPNOT:
206622812Smckusick 		if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
206722812Smckusick 			{
206822812Smckusick 			e = lp->exprblock.leftp;
206922812Smckusick 			free( (charptr) lp );
207022812Smckusick 			return(e);
207122812Smckusick 			}
207222812Smckusick 		break;
207322812Smckusick 
207422812Smckusick 	case OPCALL:
207522812Smckusick 	case OPCCALL:
207622812Smckusick 		etype = ltype;
207722812Smckusick 		if(rp!=NULL && rp->listblock.listp==NULL)
207822812Smckusick 			{
207922812Smckusick 			free( (charptr) rp );
208022812Smckusick 			rp = NULL;
208122812Smckusick 			}
208222812Smckusick 		break;
208322812Smckusick 
208422812Smckusick 	case OPAND:
208522812Smckusick 	case OPOR:
208622812Smckusick 		if( ISCONST(lp) )
208722812Smckusick 			COMMUTE
208822812Smckusick 
208922812Smckusick 		if( ISCONST(rp) )
209022812Smckusick 			{
209133256Sbostic 			if(rp->constblock.constant.ci == 0)
209222812Smckusick 				if(opcode == OPOR)
209322812Smckusick 					goto retleft;
209422812Smckusick 				else
209522812Smckusick 					goto retright;
209622812Smckusick 			else if(opcode == OPOR)
209722812Smckusick 				goto retright;
209822812Smckusick 			else
209922812Smckusick 				goto retleft;
210022812Smckusick 			}
210122812Smckusick 	case OPLSHIFT:
210222812Smckusick 		if (ISICON(rp))
210322812Smckusick 			{
210433256Sbostic 			if (rp->constblock.constant.ci == 0)
210522812Smckusick 				goto retleft;
210622812Smckusick 			if ((lp->tag == TEXPR) &&
210722812Smckusick 			    ((lp->exprblock.opcode == OPPLUS) ||
210822812Smckusick 			     (lp->exprblock.opcode == OPMINUS)) &&
210922812Smckusick 			    ISICON(lp->exprblock.rightp))
211022812Smckusick 				{
211122812Smckusick 				q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
211222812Smckusick 					cpexpr(rp));
211322812Smckusick 				q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
211422812Smckusick 				q = mkexpr(lp->exprblock.opcode, q, q1);
211522812Smckusick 				free((char *) lp);
211622812Smckusick 				return q;
211722812Smckusick 				}
211822812Smckusick 			}
211922812Smckusick 
212022812Smckusick 	case OPEQV:
212122812Smckusick 	case OPNEQV:
212222812Smckusick 
212322812Smckusick 	case OPBITAND:
212422812Smckusick 	case OPBITOR:
212522812Smckusick 	case OPBITXOR:
212622812Smckusick 	case OPBITNOT:
212722812Smckusick 	case OPRSHIFT:
212822812Smckusick 
212922812Smckusick 	case OPLT:
213022812Smckusick 	case OPGT:
213122812Smckusick 	case OPLE:
213222812Smckusick 	case OPGE:
213327928Sdonn 		break;
213427928Sdonn 
213522812Smckusick 	case OPEQ:
213622812Smckusick 	case OPNE:
213727928Sdonn 		/*
213827928Sdonn 		 * This warning is here instead of in cktype because
213927928Sdonn 		 * cktype repeats warnings (it can be run more
214027928Sdonn 		 * than once on an expression).
214127928Sdonn 		 */
214227928Sdonn 		if (ltype == TYLOGICAL)
214327928Sdonn 			warn("logical operand of nonlogical operator");
214427928Sdonn 		break;
214522812Smckusick 
214622812Smckusick 	case OPCONCAT:
214727928Sdonn 
214822812Smckusick 	case OPMIN:
214922812Smckusick 	case OPMAX:
215022812Smckusick 
215122812Smckusick 	case OPASSIGN:
215222812Smckusick 	case OPPLUSEQ:
215322812Smckusick 	case OPSTAREQ:
215422812Smckusick 
215522812Smckusick 	case OPCONV:
215622812Smckusick 	case OPADDR:
215722812Smckusick 
215822812Smckusick 	case OPCOMMA:
215922812Smckusick 	case OPQUEST:
216022812Smckusick 	case OPCOLON:
216122812Smckusick 
216222812Smckusick 	case OPPAREN:
216322812Smckusick 		break;
216422812Smckusick 
216522812Smckusick 	default:
216622812Smckusick 		badop("mkexpr", opcode);
216722812Smckusick 	}
216822812Smckusick 
216925736Sdonn makenode:
217025736Sdonn 
217122812Smckusick e = (expptr) ALLOC(Exprblock);
217222812Smckusick e->exprblock.tag = TEXPR;
217322812Smckusick e->exprblock.opcode = opcode;
217422812Smckusick e->exprblock.vtype = etype;
217522812Smckusick e->exprblock.leftp = lp;
217622812Smckusick e->exprblock.rightp = rp;
217722812Smckusick if(ltag==TCONST && (rp==0 || rtag==TCONST) )
217822812Smckusick 	e = fold(e);
217922812Smckusick return(e);
218022812Smckusick 
218122812Smckusick retleft:
218222812Smckusick 	frexpr(rp);
218322812Smckusick 	return(lp);
218422812Smckusick 
218522812Smckusick retright:
218622812Smckusick 	frexpr(lp);
218722812Smckusick 	return(rp);
218822812Smckusick 
218922812Smckusick error:
219022812Smckusick 	frexpr(lp);
219122812Smckusick 	if(rp && opcode!=OPCALL && opcode!=OPCCALL)
219222812Smckusick 		frexpr(rp);
219322812Smckusick 	return( errnode() );
219422812Smckusick }
219522812Smckusick 
219622812Smckusick #define ERR(s)   { errs = s; goto error; }
219722812Smckusick 
cktype(op,lt,rt)219822812Smckusick cktype(op, lt, rt)
219922812Smckusick register int op, lt, rt;
220022812Smckusick {
220122812Smckusick char *errs;
220222812Smckusick 
220322812Smckusick if(lt==TYERROR || rt==TYERROR)
220422812Smckusick 	goto error1;
220522812Smckusick 
220622812Smckusick if(lt==TYUNKNOWN)
220722812Smckusick 	return(TYUNKNOWN);
220822812Smckusick if(rt==TYUNKNOWN)
220922812Smckusick 	if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
221022812Smckusick 	    op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
221122812Smckusick 		return(TYUNKNOWN);
221222812Smckusick 
221322812Smckusick switch(op)
221422812Smckusick 	{
221522812Smckusick 	case OPPLUS:
221622812Smckusick 	case OPMINUS:
221722812Smckusick 	case OPSTAR:
221822812Smckusick 	case OPSLASH:
221922812Smckusick 	case OPPOWER:
222022812Smckusick 	case OPMOD:
222122812Smckusick 		if( ISNUMERIC(lt) && ISNUMERIC(rt) )
222222812Smckusick 			return( maxtype(lt, rt) );
222322812Smckusick 		ERR("nonarithmetic operand of arithmetic operator")
222422812Smckusick 
222522812Smckusick 	case OPNEG:
222622812Smckusick 		if( ISNUMERIC(lt) )
222722812Smckusick 			return(lt);
222822812Smckusick 		ERR("nonarithmetic operand of negation")
222922812Smckusick 
223022812Smckusick 	case OPNOT:
223122812Smckusick 		if(lt == TYLOGICAL)
223222812Smckusick 			return(TYLOGICAL);
223322812Smckusick 		ERR("NOT of nonlogical")
223422812Smckusick 
223522812Smckusick 	case OPAND:
223622812Smckusick 	case OPOR:
223722812Smckusick 	case OPEQV:
223822812Smckusick 	case OPNEQV:
223922812Smckusick 		if(lt==TYLOGICAL && rt==TYLOGICAL)
224022812Smckusick 			return(TYLOGICAL);
224122812Smckusick 		ERR("nonlogical operand of logical operator")
224222812Smckusick 
224322812Smckusick 	case OPLT:
224422812Smckusick 	case OPGT:
224522812Smckusick 	case OPLE:
224622812Smckusick 	case OPGE:
224722812Smckusick 	case OPEQ:
224822812Smckusick 	case OPNE:
224922812Smckusick 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
225022812Smckusick 			{
225122812Smckusick 			if(lt != rt)
225222812Smckusick 				ERR("illegal comparison")
225327928Sdonn 			if(lt == TYLOGICAL)
225427928Sdonn 				{
225527928Sdonn 				if(op!=OPEQ && op!=OPNE)
225627928Sdonn 					ERR("order comparison of complex data")
225727928Sdonn 				}
225822812Smckusick 			}
225922812Smckusick 
226022812Smckusick 		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
226122812Smckusick 			{
226222812Smckusick 			if(op!=OPEQ && op!=OPNE)
226322812Smckusick 				ERR("order comparison of complex data")
226422812Smckusick 			}
226522812Smckusick 
226622812Smckusick 		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
226722812Smckusick 			ERR("comparison of nonarithmetic data")
226822812Smckusick 		return(TYLOGICAL);
226922812Smckusick 
227022812Smckusick 	case OPCONCAT:
227122812Smckusick 		if(lt==TYCHAR && rt==TYCHAR)
227222812Smckusick 			return(TYCHAR);
227322812Smckusick 		ERR("concatenation of nonchar data")
227422812Smckusick 
227522812Smckusick 	case OPCALL:
227622812Smckusick 	case OPCCALL:
227722812Smckusick 		return(lt);
227822812Smckusick 
227922812Smckusick 	case OPADDR:
228022812Smckusick 		return(TYADDR);
228122812Smckusick 
228222812Smckusick 	case OPCONV:
228322812Smckusick 		if(ISCOMPLEX(lt))
228422812Smckusick 			{
228522812Smckusick 			if(ISNUMERIC(rt))
228622812Smckusick 				return(lt);
228722812Smckusick 			ERR("impossible conversion")
228822812Smckusick 			}
228922812Smckusick 		if(rt == 0)
229022812Smckusick 			return(0);
229122812Smckusick 		if(lt==TYCHAR && ISINT(rt) )
229222812Smckusick 			return(TYCHAR);
229322812Smckusick 	case OPASSIGN:
229422812Smckusick 	case OPPLUSEQ:
229522812Smckusick 	case OPSTAREQ:
229622812Smckusick 		if( ISINT(lt) && rt==TYCHAR)
229722812Smckusick 			return(lt);
229822812Smckusick 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
229922812Smckusick 			if(op!=OPASSIGN || lt!=rt)
230022812Smckusick 				{
230122812Smckusick /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
230222812Smckusick /* debug fatal("impossible conversion.  possible compiler bug"); */
230322812Smckusick 				ERR("impossible conversion")
230422812Smckusick 				}
230522812Smckusick 		return(lt);
230622812Smckusick 
230722812Smckusick 	case OPMIN:
230822812Smckusick 	case OPMAX:
230922812Smckusick 	case OPBITOR:
231022812Smckusick 	case OPBITAND:
231122812Smckusick 	case OPBITXOR:
231222812Smckusick 	case OPBITNOT:
231322812Smckusick 	case OPLSHIFT:
231422812Smckusick 	case OPRSHIFT:
231522812Smckusick 	case OPPAREN:
231622812Smckusick 		return(lt);
231722812Smckusick 
231822812Smckusick 	case OPCOMMA:
231922812Smckusick 	case OPQUEST:
232022812Smckusick 	case OPCOLON:
232122812Smckusick 		return(rt);
232222812Smckusick 
232322812Smckusick 	default:
232422812Smckusick 		badop("cktype", op);
232522812Smckusick 	}
232622812Smckusick error:	err(errs);
232722812Smckusick error1:	return(TYERROR);
232822812Smckusick }
232922812Smckusick 
233025736Sdonn #if HERE == VAX
233125736Sdonn #include <signal.h>
233225736Sdonn #include <setjmp.h>
233325736Sdonn #define	setfpe()	;asm("bispsw	$0x60")
233425736Sdonn jmp_buf jmp_fpe;
233525736Sdonn 
fold_fpe_handler(sig,code)233625736Sdonn LOCAL int fold_fpe_handler( sig, code )
233725736Sdonn int sig;
233825736Sdonn int code;
233925736Sdonn {
234025736Sdonn char		*message;
234125736Sdonn 
234225736Sdonn switch ( code )
234325736Sdonn 	{
234425736Sdonn 	case FPE_INTOVF_TRAP:
234525736Sdonn 		message = "integer overflow"; break;
234625736Sdonn 	case FPE_INTDIV_TRAP:
234725736Sdonn 		message = "integer divide by zero"; break;
234825736Sdonn 	case FPE_FLTOVF_TRAP:
234925736Sdonn 	case FPE_FLTOVF_FAULT:
235025736Sdonn 		message = "floating overflow"; break;
235125736Sdonn 	case FPE_FLTDIV_TRAP:
235225736Sdonn 	case FPE_FLTDIV_FAULT:
235325736Sdonn 		message = "floating divide by zero"; break;
235425736Sdonn 	case FPE_FLTUND_TRAP:
235525736Sdonn 	case FPE_FLTUND_FAULT:
235625736Sdonn 		message = "floating underflow"; break;
235725736Sdonn 	default:
235825736Sdonn 		message		= "arithmetic exception";
235925736Sdonn 	}
236025736Sdonn errstr("%s in constant expression", message);
236125736Sdonn longjmp(jmp_fpe, 1);
236225736Sdonn }
236325736Sdonn #endif
236425736Sdonn 
236525736Sdonn #ifndef setfpe
236625736Sdonn #define	setfpe()
236725736Sdonn #endif
236825736Sdonn 
fold(e)236922812Smckusick LOCAL expptr fold(e)
237022812Smckusick register expptr e;
237122812Smckusick {
237222812Smckusick Constp p;
237322812Smckusick register expptr lp, rp;
237422812Smckusick int etype, mtype, ltype, rtype, opcode;
237522812Smckusick int i, ll, lr;
237622812Smckusick char *q, *s;
237722812Smckusick union Constant lcon, rcon;
237822812Smckusick 
237925736Sdonn #if HERE == VAX
238025736Sdonn int (*fpe_handler)();
238125736Sdonn 
238225736Sdonn if(setjmp(jmp_fpe))
238325736Sdonn 	{
238425736Sdonn 	(void) signal(SIGFPE, fpe_handler);
238525736Sdonn 	frexpr(e);
238625736Sdonn 	return(errnode());
238725736Sdonn 	}
238825736Sdonn fpe_handler = signal(SIGFPE, fold_fpe_handler);
238925736Sdonn setfpe();
239025736Sdonn #endif
239125736Sdonn 
239222812Smckusick opcode = e->exprblock.opcode;
239322812Smckusick etype = e->exprblock.vtype;
239422812Smckusick 
239522812Smckusick lp = e->exprblock.leftp;
239622812Smckusick ltype = lp->headblock.vtype;
239722812Smckusick rp = e->exprblock.rightp;
239822812Smckusick 
239922812Smckusick if(rp == 0)
240022812Smckusick 	switch(opcode)
240122812Smckusick 		{
240222812Smckusick 		case OPNOT:
240333256Sbostic 			lp->constblock.constant.ci = ! lp->constblock.constant.ci;
240422812Smckusick 			return(lp);
240522812Smckusick 
240622812Smckusick 		case OPBITNOT:
240733256Sbostic 			lp->constblock.constant.ci = ~ lp->constblock.constant.ci;
240822812Smckusick 			return(lp);
240922812Smckusick 
241022812Smckusick 		case OPNEG:
241122812Smckusick 			consnegop(lp);
241222812Smckusick 			return(lp);
241322812Smckusick 
241422812Smckusick 		case OPCONV:
241522812Smckusick 		case OPADDR:
241622812Smckusick 		case OPPAREN:
241722812Smckusick 			return(e);
241822812Smckusick 
241922812Smckusick 		default:
242022812Smckusick 			badop("fold", opcode);
242122812Smckusick 		}
242222812Smckusick 
242322812Smckusick rtype = rp->headblock.vtype;
242422812Smckusick 
242522812Smckusick p = ALLOC(Constblock);
242622812Smckusick p->tag = TCONST;
242722812Smckusick p->vtype = etype;
242822812Smckusick p->vleng = e->exprblock.vleng;
242922812Smckusick 
243022812Smckusick switch(opcode)
243122812Smckusick 	{
243222812Smckusick 	case OPCOMMA:
243322812Smckusick 	case OPQUEST:
243422812Smckusick 	case OPCOLON:
243522812Smckusick 		return(e);
243622812Smckusick 
243722812Smckusick 	case OPAND:
243833256Sbostic 		p->constant.ci = lp->constblock.constant.ci &&
243933256Sbostic 				rp->constblock.constant.ci;
244022812Smckusick 		break;
244122812Smckusick 
244222812Smckusick 	case OPOR:
244333256Sbostic 		p->constant.ci = lp->constblock.constant.ci ||
244433256Sbostic 				rp->constblock.constant.ci;
244522812Smckusick 		break;
244622812Smckusick 
244722812Smckusick 	case OPEQV:
244833256Sbostic 		p->constant.ci = lp->constblock.constant.ci ==
244933256Sbostic 				rp->constblock.constant.ci;
245022812Smckusick 		break;
245122812Smckusick 
245222812Smckusick 	case OPNEQV:
245333256Sbostic 		p->constant.ci = lp->constblock.constant.ci !=
245433256Sbostic 				rp->constblock.constant.ci;
245522812Smckusick 		break;
245622812Smckusick 
245722812Smckusick 	case OPBITAND:
245833256Sbostic 		p->constant.ci = lp->constblock.constant.ci &
245933256Sbostic 				rp->constblock.constant.ci;
246022812Smckusick 		break;
246122812Smckusick 
246222812Smckusick 	case OPBITOR:
246333256Sbostic 		p->constant.ci = lp->constblock.constant.ci |
246433256Sbostic 				rp->constblock.constant.ci;
246522812Smckusick 		break;
246622812Smckusick 
246722812Smckusick 	case OPBITXOR:
246833256Sbostic 		p->constant.ci = lp->constblock.constant.ci ^
246933256Sbostic 				rp->constblock.constant.ci;
247022812Smckusick 		break;
247122812Smckusick 
247222812Smckusick 	case OPLSHIFT:
247333256Sbostic 		p->constant.ci = lp->constblock.constant.ci <<
247433256Sbostic 				rp->constblock.constant.ci;
247522812Smckusick 		break;
247622812Smckusick 
247722812Smckusick 	case OPRSHIFT:
247833256Sbostic 		p->constant.ci = lp->constblock.constant.ci >>
247933256Sbostic 				rp->constblock.constant.ci;
248022812Smckusick 		break;
248122812Smckusick 
248222812Smckusick 	case OPCONCAT:
248333256Sbostic 		ll = lp->constblock.vleng->constblock.constant.ci;
248433256Sbostic 		lr = rp->constblock.vleng->constblock.constant.ci;
248533256Sbostic 		p->constant.ccp = q = (char *) ckalloc(ll+lr);
248622812Smckusick 		p->vleng = ICON(ll+lr);
248733256Sbostic 		s = lp->constblock.constant.ccp;
248822812Smckusick 		for(i = 0 ; i < ll ; ++i)
248922812Smckusick 			*q++ = *s++;
249033256Sbostic 		s = rp->constblock.constant.ccp;
249122812Smckusick 		for(i = 0; i < lr; ++i)
249222812Smckusick 			*q++ = *s++;
249322812Smckusick 		break;
249422812Smckusick 
249522812Smckusick 
249622812Smckusick 	case OPPOWER:
249722812Smckusick 		if( ! ISINT(rtype) )
249822812Smckusick 			return(e);
249933256Sbostic 		conspower(&(p->constant), lp, rp->constblock.constant.ci);
250022812Smckusick 		break;
250122812Smckusick 
250222812Smckusick 
250322812Smckusick 	default:
250422812Smckusick 		if(ltype == TYCHAR)
250522812Smckusick 			{
250633256Sbostic 			lcon.ci = cmpstr(lp->constblock.constant.ccp,
250733256Sbostic 					rp->constblock.constant.ccp,
250833256Sbostic 					lp->constblock.vleng->constblock.constant.ci,
250933256Sbostic 					rp->constblock.vleng->constblock.constant.ci);
251022812Smckusick 			rcon.ci = 0;
251122812Smckusick 			mtype = tyint;
251222812Smckusick 			}
251322812Smckusick 		else	{
251422812Smckusick 			mtype = maxtype(ltype, rtype);
251533256Sbostic 			consconv(mtype, &lcon, ltype, &(lp->constblock.constant) );
251633256Sbostic 			consconv(mtype, &rcon, rtype, &(rp->constblock.constant) );
251722812Smckusick 			}
251833256Sbostic 		consbinop(opcode, mtype, &(p->constant), &lcon, &rcon);
251922812Smckusick 		break;
252022812Smckusick 	}
252122812Smckusick 
252222812Smckusick frexpr(e);
252322812Smckusick return( (expptr) p );
252422812Smckusick }
252522812Smckusick 
252622812Smckusick 
252722812Smckusick 
252822812Smckusick /* assign constant l = r , doing coercion */
252922812Smckusick 
consconv(lt,lv,rt,rv)253022812Smckusick consconv(lt, lv, rt, rv)
253122812Smckusick int lt, rt;
253222812Smckusick register union Constant *lv, *rv;
253322812Smckusick {
253422812Smckusick switch(lt)
253522812Smckusick 	{
253622812Smckusick 	case TYCHAR:
253722812Smckusick 		*(lv->ccp = (char *) ckalloc(1)) = rv->ci;
253822812Smckusick 		break;
253922812Smckusick 
254022812Smckusick 	case TYSHORT:
254122812Smckusick 	case TYLONG:
254222812Smckusick 		if(rt == TYCHAR)
254322812Smckusick 			lv->ci = rv->ccp[0];
254422812Smckusick 		else if( ISINT(rt) )
254522812Smckusick 			lv->ci = rv->ci;
254622812Smckusick 		else	lv->ci = rv->cd[0];
254722812Smckusick 		break;
254822812Smckusick 
254922812Smckusick 	case TYCOMPLEX:
255022812Smckusick 	case TYDCOMPLEX:
255122812Smckusick 		switch(rt)
255222812Smckusick 			{
255322812Smckusick 			case TYSHORT:
255422812Smckusick 			case TYLONG:
255522812Smckusick 				/* fall through and do real assignment of
255622812Smckusick 				   first element
255722812Smckusick 				*/
255822812Smckusick 			case TYREAL:
255922812Smckusick 			case TYDREAL:
256022812Smckusick 				lv->cd[1] = 0; break;
256122812Smckusick 			case TYCOMPLEX:
256222812Smckusick 			case TYDCOMPLEX:
256322812Smckusick 				lv->cd[1] = rv->cd[1]; break;
256422812Smckusick 			}
256522812Smckusick 
256622812Smckusick 	case TYREAL:
256722812Smckusick 	case TYDREAL:
256822812Smckusick 		if( ISINT(rt) )
256922812Smckusick 			lv->cd[0] = rv->ci;
257022812Smckusick 		else	lv->cd[0] = rv->cd[0];
257122812Smckusick 		if( lt == TYREAL)
257222812Smckusick 			{
257322812Smckusick 			float f = lv->cd[0];
257422812Smckusick 			lv->cd[0] = f;
257522812Smckusick 			}
257622812Smckusick 		break;
257722812Smckusick 
257822812Smckusick 	case TYLOGICAL:
257922812Smckusick 		lv->ci = rv->ci;
258022812Smckusick 		break;
258122812Smckusick 	}
258222812Smckusick }
258322812Smckusick 
258422812Smckusick 
258522812Smckusick 
consnegop(p)258622812Smckusick consnegop(p)
258722812Smckusick register Constp p;
258822812Smckusick {
258925736Sdonn setfpe();
259025736Sdonn 
259122812Smckusick switch(p->vtype)
259222812Smckusick 	{
259322812Smckusick 	case TYSHORT:
259422812Smckusick 	case TYLONG:
259533256Sbostic 		p->constant.ci = - p->constant.ci;
259622812Smckusick 		break;
259722812Smckusick 
259822812Smckusick 	case TYCOMPLEX:
259922812Smckusick 	case TYDCOMPLEX:
260033256Sbostic 		p->constant.cd[1] = - p->constant.cd[1];
260122812Smckusick 		/* fall through and do the real parts */
260222812Smckusick 	case TYREAL:
260322812Smckusick 	case TYDREAL:
260433256Sbostic 		p->constant.cd[0] = - p->constant.cd[0];
260522812Smckusick 		break;
260622812Smckusick 	default:
260722812Smckusick 		badtype("consnegop", p->vtype);
260822812Smckusick 	}
260922812Smckusick }
261022812Smckusick 
261122812Smckusick 
261222812Smckusick 
conspower(powp,ap,n)261322812Smckusick LOCAL conspower(powp, ap, n)
261422812Smckusick register union Constant *powp;
261522812Smckusick Constp ap;
261622812Smckusick ftnint n;
261722812Smckusick {
261822812Smckusick register int type;
261922812Smckusick union Constant x;
262022812Smckusick 
262122812Smckusick switch(type = ap->vtype)	/* pow = 1 */
262222812Smckusick 	{
262322812Smckusick 	case TYSHORT:
262422812Smckusick 	case TYLONG:
262522812Smckusick 		powp->ci = 1;
262622812Smckusick 		break;
262722812Smckusick 	case TYCOMPLEX:
262822812Smckusick 	case TYDCOMPLEX:
262922812Smckusick 		powp->cd[1] = 0;
263022812Smckusick 	case TYREAL:
263122812Smckusick 	case TYDREAL:
263222812Smckusick 		powp->cd[0] = 1;
263322812Smckusick 		break;
263422812Smckusick 	default:
263522812Smckusick 		badtype("conspower", type);
263622812Smckusick 	}
263722812Smckusick 
263822812Smckusick if(n == 0)
263922812Smckusick 	return;
264022812Smckusick if(n < 0)
264122812Smckusick 	{
264222812Smckusick 	if( ISINT(type) )
264322812Smckusick 		{
264433256Sbostic 		if (ap->constant.ci == 0)
264522812Smckusick 			err("zero raised to a negative power");
264633256Sbostic 		else if (ap->constant.ci == 1)
264722812Smckusick 			return;
264833256Sbostic 		else if (ap->constant.ci == -1)
264922812Smckusick 			{
265022812Smckusick 			if (n < -2)
265122812Smckusick 				n = n + 2;
265222812Smckusick 			n = -n;
265322812Smckusick 			if (n % 2 == 1)
265422812Smckusick 				powp->ci = -1;
265522812Smckusick 			}
265622812Smckusick 		else
265722812Smckusick 			powp->ci = 0;
265822812Smckusick 		return;
265922812Smckusick 		}
266022812Smckusick 	n = - n;
266133256Sbostic 	consbinop(OPSLASH, type, &x, powp, &(ap->constant));
266222812Smckusick 	}
266322812Smckusick else
266433256Sbostic 	consbinop(OPSTAR, type, &x, powp, &(ap->constant));
266522812Smckusick 
266622812Smckusick for( ; ; )
266722812Smckusick 	{
266822812Smckusick 	if(n & 01)
266922812Smckusick 		consbinop(OPSTAR, type, powp, powp, &x);
267022812Smckusick 	if(n >>= 1)
267122812Smckusick 		consbinop(OPSTAR, type, &x, &x, &x);
267222812Smckusick 	else
267322812Smckusick 		break;
267422812Smckusick 	}
267522812Smckusick }
267622812Smckusick 
267722812Smckusick 
267822812Smckusick 
267922812Smckusick /* do constant operation cp = a op b */
268022812Smckusick 
268122812Smckusick 
consbinop(opcode,type,cp,ap,bp)268222812Smckusick LOCAL consbinop(opcode, type, cp, ap, bp)
268322812Smckusick int opcode, type;
268422812Smckusick register union Constant *ap, *bp, *cp;
268522812Smckusick {
268622812Smckusick int k;
268722812Smckusick double temp;
268822812Smckusick 
268925736Sdonn setfpe();
269025736Sdonn 
269122812Smckusick switch(opcode)
269222812Smckusick 	{
269322812Smckusick 	case OPPLUS:
269422812Smckusick 		switch(type)
269522812Smckusick 			{
269622812Smckusick 			case TYSHORT:
269722812Smckusick 			case TYLONG:
269822812Smckusick 				cp->ci = ap->ci + bp->ci;
269922812Smckusick 				break;
270022812Smckusick 			case TYCOMPLEX:
270122812Smckusick 			case TYDCOMPLEX:
270222812Smckusick 				cp->cd[1] = ap->cd[1] + bp->cd[1];
270322812Smckusick 			case TYREAL:
270422812Smckusick 			case TYDREAL:
270522812Smckusick 				cp->cd[0] = ap->cd[0] + bp->cd[0];
270622812Smckusick 				break;
270722812Smckusick 			}
270822812Smckusick 		break;
270922812Smckusick 
271022812Smckusick 	case OPMINUS:
271122812Smckusick 		switch(type)
271222812Smckusick 			{
271322812Smckusick 			case TYSHORT:
271422812Smckusick 			case TYLONG:
271522812Smckusick 				cp->ci = ap->ci - bp->ci;
271622812Smckusick 				break;
271722812Smckusick 			case TYCOMPLEX:
271822812Smckusick 			case TYDCOMPLEX:
271922812Smckusick 				cp->cd[1] = ap->cd[1] - bp->cd[1];
272022812Smckusick 			case TYREAL:
272122812Smckusick 			case TYDREAL:
272222812Smckusick 				cp->cd[0] = ap->cd[0] - bp->cd[0];
272322812Smckusick 				break;
272422812Smckusick 			}
272522812Smckusick 		break;
272622812Smckusick 
272722812Smckusick 	case OPSTAR:
272822812Smckusick 		switch(type)
272922812Smckusick 			{
273022812Smckusick 			case TYSHORT:
273122812Smckusick 			case TYLONG:
273222812Smckusick 				cp->ci = ap->ci * bp->ci;
273322812Smckusick 				break;
273422812Smckusick 			case TYREAL:
273522812Smckusick 			case TYDREAL:
273622812Smckusick 				cp->cd[0] = ap->cd[0] * bp->cd[0];
273722812Smckusick 				break;
273822812Smckusick 			case TYCOMPLEX:
273922812Smckusick 			case TYDCOMPLEX:
274022812Smckusick 				temp = ap->cd[0] * bp->cd[0] -
274122812Smckusick 					    ap->cd[1] * bp->cd[1] ;
274222812Smckusick 				cp->cd[1] = ap->cd[0] * bp->cd[1] +
274322812Smckusick 					    ap->cd[1] * bp->cd[0] ;
274422812Smckusick 				cp->cd[0] = temp;
274522812Smckusick 				break;
274622812Smckusick 			}
274722812Smckusick 		break;
274822812Smckusick 	case OPSLASH:
274922812Smckusick 		switch(type)
275022812Smckusick 			{
275122812Smckusick 			case TYSHORT:
275222812Smckusick 			case TYLONG:
275322812Smckusick 				cp->ci = ap->ci / bp->ci;
275422812Smckusick 				break;
275522812Smckusick 			case TYREAL:
275622812Smckusick 			case TYDREAL:
275722812Smckusick 				cp->cd[0] = ap->cd[0] / bp->cd[0];
275822812Smckusick 				break;
275922812Smckusick 			case TYCOMPLEX:
276022812Smckusick 			case TYDCOMPLEX:
276122812Smckusick 				zdiv(cp,ap,bp);
276222812Smckusick 				break;
276322812Smckusick 			}
276422812Smckusick 		break;
276522812Smckusick 
276622812Smckusick 	case OPMOD:
276722812Smckusick 		if( ISINT(type) )
276822812Smckusick 			{
276922812Smckusick 			cp->ci = ap->ci % bp->ci;
277022812Smckusick 			break;
277122812Smckusick 			}
277222812Smckusick 		else
277322812Smckusick 			fatal("inline mod of noninteger");
277422812Smckusick 
277522812Smckusick 	default:	  /* relational ops */
277622812Smckusick 		switch(type)
277722812Smckusick 			{
277822812Smckusick 			case TYSHORT:
277922812Smckusick 			case TYLONG:
278022812Smckusick 				if(ap->ci < bp->ci)
278122812Smckusick 					k = -1;
278222812Smckusick 				else if(ap->ci == bp->ci)
278322812Smckusick 					k = 0;
278422812Smckusick 				else	k = 1;
278522812Smckusick 				break;
278622812Smckusick 			case TYREAL:
278722812Smckusick 			case TYDREAL:
278822812Smckusick 				if(ap->cd[0] < bp->cd[0])
278922812Smckusick 					k = -1;
279022812Smckusick 				else if(ap->cd[0] == bp->cd[0])
279122812Smckusick 					k = 0;
279222812Smckusick 				else	k = 1;
279322812Smckusick 				break;
279422812Smckusick 			case TYCOMPLEX:
279522812Smckusick 			case TYDCOMPLEX:
279622812Smckusick 				if(ap->cd[0] == bp->cd[0] &&
279722812Smckusick 				   ap->cd[1] == bp->cd[1] )
279822812Smckusick 					k = 0;
279922812Smckusick 				else	k = 1;
280022812Smckusick 				break;
280127451Sdonn 			case TYLOGICAL:
280227451Sdonn 				if(ap->ci == bp->ci)
280327451Sdonn 					k = 0;
280427451Sdonn 				else	k = 1;
280527451Sdonn 				break;
280622812Smckusick 			}
280722812Smckusick 
280822812Smckusick 		switch(opcode)
280922812Smckusick 			{
281022812Smckusick 			case OPEQ:
281122812Smckusick 				cp->ci = (k == 0);
281222812Smckusick 				break;
281322812Smckusick 			case OPNE:
281422812Smckusick 				cp->ci = (k != 0);
281522812Smckusick 				break;
281622812Smckusick 			case OPGT:
281722812Smckusick 				cp->ci = (k == 1);
281822812Smckusick 				break;
281922812Smckusick 			case OPLT:
282022812Smckusick 				cp->ci = (k == -1);
282122812Smckusick 				break;
282222812Smckusick 			case OPGE:
282322812Smckusick 				cp->ci = (k >= 0);
282422812Smckusick 				break;
282522812Smckusick 			case OPLE:
282622812Smckusick 				cp->ci = (k <= 0);
282722812Smckusick 				break;
282822812Smckusick 			default:
282922812Smckusick 				badop ("consbinop", opcode);
283022812Smckusick 			}
283122812Smckusick 		break;
283222812Smckusick 	}
283322812Smckusick }
283422812Smckusick 
283522812Smckusick 
283622812Smckusick 
283722812Smckusick 
conssgn(p)283822812Smckusick conssgn(p)
283922812Smckusick register expptr p;
284022812Smckusick {
284122812Smckusick if( ! ISCONST(p) )
284222812Smckusick 	fatal( "sgn(nonconstant)" );
284322812Smckusick 
284422812Smckusick switch(p->headblock.vtype)
284522812Smckusick 	{
284622812Smckusick 	case TYSHORT:
284722812Smckusick 	case TYLONG:
284833256Sbostic 		if(p->constblock.constant.ci > 0) return(1);
284933256Sbostic 		if(p->constblock.constant.ci < 0) return(-1);
285022812Smckusick 		return(0);
285122812Smckusick 
285222812Smckusick 	case TYREAL:
285322812Smckusick 	case TYDREAL:
285433256Sbostic 		if(p->constblock.constant.cd[0] > 0) return(1);
285533256Sbostic 		if(p->constblock.constant.cd[0] < 0) return(-1);
285622812Smckusick 		return(0);
285722812Smckusick 
285822812Smckusick 	case TYCOMPLEX:
285922812Smckusick 	case TYDCOMPLEX:
286033256Sbostic 		return(p->constblock.constant.cd[0]!=0 || p->constblock.constant.cd[1]!=0);
286122812Smckusick 
286222812Smckusick 	default:
286322812Smckusick 		badtype( "conssgn", p->constblock.vtype);
286422812Smckusick 	}
286522812Smckusick /* NOTREACHED */
286622812Smckusick }
286722812Smckusick 
286822812Smckusick char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
286922812Smckusick 
287022812Smckusick 
mkpower(p)287122812Smckusick LOCAL expptr mkpower(p)
287222812Smckusick register expptr p;
287322812Smckusick {
287422812Smckusick register expptr q, lp, rp;
287522812Smckusick int ltype, rtype, mtype;
287624477Sdonn struct Listblock *args, *mklist();
287724477Sdonn Addrp ap;
287822812Smckusick 
287922812Smckusick lp = p->exprblock.leftp;
288022812Smckusick rp = p->exprblock.rightp;
288122812Smckusick ltype = lp->headblock.vtype;
288222812Smckusick rtype = rp->headblock.vtype;
288322812Smckusick 
288422812Smckusick if(ISICON(rp))
288522812Smckusick 	{
288633256Sbostic 	if(rp->constblock.constant.ci == 0)
288722812Smckusick 		{
288822812Smckusick 		frexpr(p);
288922812Smckusick 		if( ISINT(ltype) )
289022812Smckusick 			return( ICON(1) );
289122812Smckusick 		else
289222812Smckusick 			{
289322812Smckusick 			expptr pp;
289422812Smckusick 			pp = mkconv(ltype, ICON(1));
289522812Smckusick 			return( pp );
289622812Smckusick 			}
289722812Smckusick 		}
289833256Sbostic 	if(rp->constblock.constant.ci < 0)
289922812Smckusick 		{
290022812Smckusick 		if( ISINT(ltype) )
290122812Smckusick 			{
290222812Smckusick 			frexpr(p);
290322812Smckusick 			err("integer**negative");
290422812Smckusick 			return( errnode() );
290522812Smckusick 			}
290633256Sbostic 		rp->constblock.constant.ci = - rp->constblock.constant.ci;
290722812Smckusick 		p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
290822812Smckusick 		}
290933256Sbostic 	if(rp->constblock.constant.ci == 1)
291022812Smckusick 		{
291122812Smckusick 		frexpr(rp);
291222812Smckusick 		free( (charptr) p );
291322812Smckusick 		return(lp);
291422812Smckusick 		}
291522812Smckusick 
291622812Smckusick 	if( ONEOF(ltype, MSKINT|MSKREAL) )
291722812Smckusick 		{
291822812Smckusick 		p->exprblock.vtype = ltype;
291922812Smckusick 		return(p);
292022812Smckusick 		}
292122812Smckusick 	}
292222812Smckusick if( ISINT(rtype) )
292322812Smckusick 	{
292422812Smckusick 	if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
292522812Smckusick 		q = call2(TYSHORT, "pow_hh", lp, rp);
292622812Smckusick 	else	{
292722812Smckusick 		if(ltype == TYSHORT)
292822812Smckusick 			{
292922812Smckusick 			ltype = TYLONG;
293022812Smckusick 			lp = mkconv(TYLONG,lp);
293122812Smckusick 			}
293222812Smckusick 		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
293322812Smckusick 		}
293422812Smckusick 	}
293522812Smckusick else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
293624477Sdonn 	{
293724477Sdonn 	args = mklist( mkchain( mkconv(TYDREAL,lp), mkchain( mkconv(TYDREAL,rp), CHNULL ) ) );
293824477Sdonn 	fixargs(YES, args );
293924477Sdonn 	ap = builtin( TYDREAL, "pow" );
294024477Sdonn 	ap->vstg = STGINTR;
294124477Sdonn 	q = fixexpr( mkexpr(OPCCALL, ap, args ));
294224477Sdonn 	q->exprblock.vtype = mtype;
294324477Sdonn 	}
294422812Smckusick else	{
294522812Smckusick 	q  = call2(TYDCOMPLEX, "pow_zz",
294622812Smckusick 		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
294722812Smckusick 	if(mtype == TYCOMPLEX)
294822812Smckusick 		q = mkconv(TYCOMPLEX, q);
294922812Smckusick 	}
295022812Smckusick free( (charptr) p );
295122812Smckusick return(q);
295222812Smckusick }
295322812Smckusick 
295422812Smckusick 
295522812Smckusick 
295622812Smckusick /* Complex Division.  Same code as in Runtime Library
295722812Smckusick */
295822812Smckusick 
295922812Smckusick struct dcomplex { double dreal, dimag; };
296022812Smckusick 
296122812Smckusick 
zdiv(c,a,b)296222812Smckusick LOCAL zdiv(c, a, b)
296322812Smckusick register struct dcomplex *a, *b, *c;
296422812Smckusick {
296522812Smckusick double ratio, den;
296622812Smckusick double abr, abi;
296722812Smckusick 
296825736Sdonn setfpe();
296925736Sdonn 
297022812Smckusick if( (abr = b->dreal) < 0.)
297122812Smckusick 	abr = - abr;
297222812Smckusick if( (abi = b->dimag) < 0.)
297322812Smckusick 	abi = - abi;
297422812Smckusick if( abr <= abi )
297522812Smckusick 	{
297622812Smckusick 	if(abi == 0)
297722812Smckusick 		fatal("complex division by zero");
297822812Smckusick 	ratio = b->dreal / b->dimag ;
297922812Smckusick 	den = b->dimag * (1 + ratio*ratio);
298022812Smckusick 	c->dreal = (a->dreal*ratio + a->dimag) / den;
298122812Smckusick 	c->dimag = (a->dimag*ratio - a->dreal) / den;
298222812Smckusick 	}
298322812Smckusick 
298422812Smckusick else
298522812Smckusick 	{
298622812Smckusick 	ratio = b->dimag / b->dreal ;
298722812Smckusick 	den = b->dreal * (1 + ratio*ratio);
298822812Smckusick 	c->dreal = (a->dreal + a->dimag*ratio) / den;
298922812Smckusick 	c->dimag = (a->dimag - a->dreal*ratio) / den;
299022812Smckusick 	}
299122812Smckusick 
299222812Smckusick }
299322812Smckusick 
oftwo(e)299422812Smckusick expptr oftwo(e)
299522812Smckusick expptr e;
299622812Smckusick {
299722812Smckusick 	int val,res;
299822812Smckusick 
299922812Smckusick 	if (! ISCONST (e))
300022812Smckusick 		return (0);
300122812Smckusick 
300233256Sbostic 	val = e->constblock.constant.ci;
300322812Smckusick 	switch (val)
300422812Smckusick 		{
300522812Smckusick 		case 2:		res = 1; break;
300622812Smckusick 		case 4:		res = 2; break;
300722812Smckusick 		case 8:		res = 3; break;
300822812Smckusick 		case 16:	res = 4; break;
300922812Smckusick 		case 32:	res = 5; break;
301022812Smckusick 		case 64:	res = 6; break;
301122812Smckusick 		case 128:	res = 7; break;
301222812Smckusick 		case 256:	res = 8; break;
301322812Smckusick 		default:	return (0);
301422812Smckusick 		}
301522812Smckusick 	return (ICON (res));
301622812Smckusick }
3017