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