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