xref: /original-bsd/usr.bin/f77/pass1.tahoe/expr.c (revision b8be84b8)
1*b8be84b8Sbostic /*-
2*b8be84b8Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*b8be84b8Sbostic  * All rights reserved.
4*b8be84b8Sbostic  *
5*b8be84b8Sbostic  * %sccs.include.proprietary.c%
688cbd795Sdonn  */
788cbd795Sdonn 
888cbd795Sdonn #ifndef lint
9*b8be84b8Sbostic static char sccsid[] = "@(#)expr.c	1.4 (Berkeley) 04/12/91";
10*b8be84b8Sbostic #endif /* not lint */
1188cbd795Sdonn 
1288cbd795Sdonn /*
1388cbd795Sdonn  * expr.c
1488cbd795Sdonn  *
1588cbd795Sdonn  * Routines for handling expressions, f77 compiler pass 1.
1688cbd795Sdonn  *
1788cbd795Sdonn  * University of Utah CS Dept modification history:
1888cbd795Sdonn  *
1988cbd795Sdonn  * $Log:	expr.c,v $
2088cbd795Sdonn  * Revision 1.3  86/02/26  17:13:37  rcs
2188cbd795Sdonn  * Correct COFR 411.
2288cbd795Sdonn  * P. Wong
2388cbd795Sdonn  *
2488cbd795Sdonn  * Revision 3.16  85/06/21  16:38:09  donn
2588cbd795Sdonn  * The fix to mkprim() didn't handle null substring parameters (sigh).
2688cbd795Sdonn  *
2788cbd795Sdonn  * Revision 3.15  85/06/04  04:37:03  donn
2888cbd795Sdonn  * Changed mkprim() to force substring parameters to be integral types.
2988cbd795Sdonn  *
3088cbd795Sdonn  * Revision 3.14  85/06/04  03:41:52  donn
3188cbd795Sdonn  * Change impldcl() to handle functions of type 'undefined'.
3288cbd795Sdonn  *
3388cbd795Sdonn  * Revision 3.13  85/05/06  23:14:55  donn
3488cbd795Sdonn  * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
3588cbd795Sdonn  * a temporary when converting character strings to integers; previously we
3688cbd795Sdonn  * were having problems because mkconv() was called after tempalloc().
3788cbd795Sdonn  *
3888cbd795Sdonn  * Revision 3.12  85/03/18  08:07:47  donn
3988cbd795Sdonn  * Fixes to help out with short integers -- if integers are by default short,
4088cbd795Sdonn  * then so are constants; and if addresses can't be stored in shorts, complain.
4188cbd795Sdonn  *
4288cbd795Sdonn  * Revision 3.11  85/03/16  22:31:27  donn
4388cbd795Sdonn  * Added hack to mkconv() to allow character values of length > 1 to be
4488cbd795Sdonn  * converted to numeric types, for Helge Skrivervik.  Note that this does
4588cbd795Sdonn  * not affect use of the intrinsic ichar() conversion.
4688cbd795Sdonn  *
4788cbd795Sdonn  * Revision 3.10  85/01/15  21:06:47  donn
4888cbd795Sdonn  * Changed mkconv() to comment on implicit conversions; added intrconv() for
4988cbd795Sdonn  * use with explicit conversions by intrinsic functions.
5088cbd795Sdonn  *
5188cbd795Sdonn  * Revision 3.9  85/01/11  21:05:49  donn
5288cbd795Sdonn  * Added changes to implement SAVE statements.
5388cbd795Sdonn  *
5488cbd795Sdonn  * Revision 3.8  84/12/17  02:21:06  donn
5588cbd795Sdonn  * Added a test to prevent constant folding from being done on expressions
5688cbd795Sdonn  * whose type is not known at that point in mkexpr().
5788cbd795Sdonn  *
5888cbd795Sdonn  * Revision 3.7  84/12/11  21:14:17  donn
5988cbd795Sdonn  * Removed obnoxious 'excess precision' warning.
6088cbd795Sdonn  *
6188cbd795Sdonn  * Revision 3.6  84/11/23  01:00:36  donn
6288cbd795Sdonn  * Added code to trim excess precision from single-precision constants, and
6388cbd795Sdonn  * to warn the user when this occurs.
6488cbd795Sdonn  *
6588cbd795Sdonn  * Revision 3.5  84/11/23  00:10:39  donn
6688cbd795Sdonn  * Changed stfcall() to remark on argument type clashes in 'calls' to
6788cbd795Sdonn  * statement functions.
6888cbd795Sdonn  *
6988cbd795Sdonn  * Revision 3.4  84/11/22  21:21:17  donn
7088cbd795Sdonn  * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
7188cbd795Sdonn  *
7288cbd795Sdonn  * Revision 3.3  84/11/12  18:26:14  donn
7388cbd795Sdonn  * Shuffled some code around so that the compiler remembers to free some vleng
7488cbd795Sdonn  * structures which used to just sit around.
7588cbd795Sdonn  *
7688cbd795Sdonn  * Revision 3.2  84/10/16  19:24:15  donn
7788cbd795Sdonn  * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
7888cbd795Sdonn  * core dumps by replacing bad subscripts with good ones.
7988cbd795Sdonn  *
8088cbd795Sdonn  * Revision 3.1  84/10/13  01:31:32  donn
8188cbd795Sdonn  * Merged Jerry Berkman's version into mine.
8288cbd795Sdonn  *
8388cbd795Sdonn  * Revision 2.7  84/09/27  15:42:52  donn
8488cbd795Sdonn  * The last fix for multiplying undeclared variables by 0 isn't sufficient,
8588cbd795Sdonn  * since the type of the 0 may not be the (implicit) type of the variable.
8688cbd795Sdonn  * I added a hack to check the implicit type of implicitly declared
8788cbd795Sdonn  * variables...
8888cbd795Sdonn  *
8988cbd795Sdonn  * Revision 2.6  84/09/14  19:34:03  donn
9088cbd795Sdonn  * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
9188cbd795Sdonn  * 0 to type UNKNOWN, which is illegal.  Fix is to use native type instead.
9288cbd795Sdonn  * Not sure how correct (or important) this is...
9388cbd795Sdonn  *
9488cbd795Sdonn  * Revision 2.5  84/08/05  23:05:27  donn
9588cbd795Sdonn  * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
9688cbd795Sdonn  * with two operands.
9788cbd795Sdonn  *
9888cbd795Sdonn  * Revision 2.4  84/08/05  17:34:48  donn
9988cbd795Sdonn  * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
10088cbd795Sdonn  * and assign constant length 1 to them.
10188cbd795Sdonn  *
10288cbd795Sdonn  * Revision 2.3  84/07/19  19:38:33  donn
10388cbd795Sdonn  * Added a typecast to the last fix.  Somehow I missed it the first time...
10488cbd795Sdonn  *
10588cbd795Sdonn  * Revision 2.2  84/07/19  17:19:57  donn
10688cbd795Sdonn  * Caused OPPAREN expressions to inherit the length of their operands, so
10788cbd795Sdonn  * that parenthesized character expressions work correctly.
10888cbd795Sdonn  *
10988cbd795Sdonn  * Revision 2.1  84/07/19  12:03:02  donn
11088cbd795Sdonn  * Changed comment headers for UofU.
11188cbd795Sdonn  *
11288cbd795Sdonn  * Revision 1.2  84/04/06  20:12:17  donn
11388cbd795Sdonn  * Fixed bug which caused programs with mixed-type multiplications involving
11488cbd795Sdonn  * the constant 0 to choke the compiler.
11588cbd795Sdonn  *
11688cbd795Sdonn  */
11788cbd795Sdonn 
11888cbd795Sdonn #include "defs.h"
11988cbd795Sdonn 
12088cbd795Sdonn 
12188cbd795Sdonn /* little routines to create constant blocks */
12288cbd795Sdonn 
mkconst(t)12388cbd795Sdonn Constp mkconst(t)
12488cbd795Sdonn register int t;
12588cbd795Sdonn {
12688cbd795Sdonn register Constp p;
12788cbd795Sdonn 
12888cbd795Sdonn p = ALLOC(Constblock);
12988cbd795Sdonn p->tag = TCONST;
13088cbd795Sdonn p->vtype = t;
13188cbd795Sdonn return(p);
13288cbd795Sdonn }
13388cbd795Sdonn 
13488cbd795Sdonn 
mklogcon(l)13588cbd795Sdonn expptr mklogcon(l)
13688cbd795Sdonn register int l;
13788cbd795Sdonn {
13888cbd795Sdonn register Constp  p;
13988cbd795Sdonn 
14088cbd795Sdonn p = mkconst(TYLOGICAL);
14176ad5316Sbostic p->constant.ci = l;
14288cbd795Sdonn return( (expptr) p );
14388cbd795Sdonn }
14488cbd795Sdonn 
14588cbd795Sdonn 
14688cbd795Sdonn 
mkintcon(l)14788cbd795Sdonn expptr mkintcon(l)
14888cbd795Sdonn ftnint l;
14988cbd795Sdonn {
15088cbd795Sdonn register Constp p;
15188cbd795Sdonn int usetype;
15288cbd795Sdonn 
15388cbd795Sdonn if(tyint == TYSHORT)
15488cbd795Sdonn   {
15588cbd795Sdonn     short s = l;
15688cbd795Sdonn     if(l != s)
15788cbd795Sdonn       usetype = TYLONG;
15888cbd795Sdonn     else
15988cbd795Sdonn       usetype = TYSHORT;
16088cbd795Sdonn   }
16188cbd795Sdonn else
16288cbd795Sdonn   usetype = tyint;
16388cbd795Sdonn p = mkconst(usetype);
16476ad5316Sbostic p->constant.ci = l;
16588cbd795Sdonn return( (expptr) p );
16688cbd795Sdonn }
16788cbd795Sdonn 
16888cbd795Sdonn 
16988cbd795Sdonn 
mkaddcon(l)17088cbd795Sdonn expptr mkaddcon(l)
17188cbd795Sdonn register int l;
17288cbd795Sdonn {
17388cbd795Sdonn register Constp p;
17488cbd795Sdonn 
17588cbd795Sdonn p = mkconst(TYADDR);
17676ad5316Sbostic p->constant.ci = l;
17788cbd795Sdonn return( (expptr) p );
17888cbd795Sdonn }
17988cbd795Sdonn 
18088cbd795Sdonn 
18188cbd795Sdonn 
mkrealcon(t,d)18288cbd795Sdonn expptr mkrealcon(t, d)
18388cbd795Sdonn register int t;
18488cbd795Sdonn double d;
18588cbd795Sdonn {
18688cbd795Sdonn register Constp p;
18788cbd795Sdonn 
18888cbd795Sdonn p = mkconst(t);
18976ad5316Sbostic p->constant.cd[0] = d;
19088cbd795Sdonn return( (expptr) p );
19188cbd795Sdonn }
19288cbd795Sdonn 
mkbitcon(shift,leng,s)19388cbd795Sdonn expptr mkbitcon(shift, leng, s)
19488cbd795Sdonn int shift;
19588cbd795Sdonn register int leng;
19688cbd795Sdonn register char *s;
19788cbd795Sdonn {
19888cbd795Sdonn   Constp p;
19988cbd795Sdonn   register int i, j, k;
20088cbd795Sdonn   register char *bp;
20188cbd795Sdonn   int size;
20288cbd795Sdonn 
20388cbd795Sdonn   size = (shift*leng + BYTESIZE -1)/BYTESIZE;
20488cbd795Sdonn   bp = (char *) ckalloc(size);
20588cbd795Sdonn 
20688cbd795Sdonn   i = 0;
20788cbd795Sdonn 
20888cbd795Sdonn #if (HERE == PDP11 || HERE == VAX)
20988cbd795Sdonn   j = 0;
21088cbd795Sdonn #else
21188cbd795Sdonn   j = size;
21288cbd795Sdonn #endif
21388cbd795Sdonn 
21488cbd795Sdonn   k = 0;
21588cbd795Sdonn 
21688cbd795Sdonn   while (leng > 0)
21788cbd795Sdonn     {
21888cbd795Sdonn       k |= (hextoi(s[--leng]) << i);
21988cbd795Sdonn       i += shift;
22088cbd795Sdonn       if (i >= BYTESIZE)
22188cbd795Sdonn 	{
22288cbd795Sdonn #if (HERE == PDP11 || HERE == VAX)
22388cbd795Sdonn 	  bp[j++] = k & MAXBYTE;
22488cbd795Sdonn #else
22588cbd795Sdonn 	  bp[--j] = k & MAXBYTE;
22688cbd795Sdonn #endif
22788cbd795Sdonn 	  k = k >> BYTESIZE;
22888cbd795Sdonn 	  i -= BYTESIZE;
22988cbd795Sdonn 	}
23088cbd795Sdonn     }
23188cbd795Sdonn 
23288cbd795Sdonn   if (k != 0)
23388cbd795Sdonn #if (HERE == PDP11 || HERE == VAX)
23488cbd795Sdonn     bp[j++] = k;
23588cbd795Sdonn #else
23688cbd795Sdonn     bp[--j] = k;
23788cbd795Sdonn #endif
23888cbd795Sdonn 
23988cbd795Sdonn   p = mkconst(TYBITSTR);
24088cbd795Sdonn   p->vleng = ICON(size);
24176ad5316Sbostic   p->constant.ccp = bp;
24288cbd795Sdonn 
24388cbd795Sdonn   return ((expptr) p);
24488cbd795Sdonn }
24588cbd795Sdonn 
24688cbd795Sdonn 
24788cbd795Sdonn 
mkstrcon(l,v)24888cbd795Sdonn expptr mkstrcon(l,v)
24988cbd795Sdonn int l;
25088cbd795Sdonn register char *v;
25188cbd795Sdonn {
25288cbd795Sdonn register Constp p;
25388cbd795Sdonn register char *s;
25488cbd795Sdonn 
25588cbd795Sdonn p = mkconst(TYCHAR);
25688cbd795Sdonn p->vleng = ICON(l);
25776ad5316Sbostic p->constant.ccp = s = (char *) ckalloc(l);
25888cbd795Sdonn while(--l >= 0)
25988cbd795Sdonn 	*s++ = *v++;
26088cbd795Sdonn return( (expptr) p );
26188cbd795Sdonn }
26288cbd795Sdonn 
26388cbd795Sdonn 
mkcxcon(realp,imagp)26488cbd795Sdonn expptr mkcxcon(realp,imagp)
26588cbd795Sdonn register expptr realp, imagp;
26688cbd795Sdonn {
26788cbd795Sdonn int rtype, itype;
26888cbd795Sdonn register Constp p;
26988cbd795Sdonn 
27088cbd795Sdonn rtype = realp->headblock.vtype;
27188cbd795Sdonn itype = imagp->headblock.vtype;
27288cbd795Sdonn 
27388cbd795Sdonn if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
27488cbd795Sdonn 	{
27588cbd795Sdonn 	p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
27688cbd795Sdonn 	if( ISINT(rtype) )
27776ad5316Sbostic 		p->constant.cd[0] = realp->constblock.constant.ci;
27876ad5316Sbostic 	else	p->constant.cd[0] = realp->constblock.constant.cd[0];
27988cbd795Sdonn 	if( ISINT(itype) )
28076ad5316Sbostic 		p->constant.cd[1] = imagp->constblock.constant.ci;
28176ad5316Sbostic 	else	p->constant.cd[1] = imagp->constblock.constant.cd[0];
28288cbd795Sdonn 	}
28388cbd795Sdonn else
28488cbd795Sdonn 	{
28588cbd795Sdonn 	err("invalid complex constant");
28688cbd795Sdonn 	p = (Constp) errnode();
28788cbd795Sdonn 	}
28888cbd795Sdonn 
28988cbd795Sdonn frexpr(realp);
29088cbd795Sdonn frexpr(imagp);
29188cbd795Sdonn return( (expptr) p );
29288cbd795Sdonn }
29388cbd795Sdonn 
29488cbd795Sdonn 
errnode()29588cbd795Sdonn expptr errnode()
29688cbd795Sdonn {
29788cbd795Sdonn struct Errorblock *p;
29888cbd795Sdonn p = ALLOC(Errorblock);
29988cbd795Sdonn p->tag = TERROR;
30088cbd795Sdonn p->vtype = TYERROR;
30188cbd795Sdonn return( (expptr) p );
30288cbd795Sdonn }
30388cbd795Sdonn 
30488cbd795Sdonn 
30588cbd795Sdonn 
30688cbd795Sdonn 
30788cbd795Sdonn 
mkconv(t,p)30888cbd795Sdonn expptr mkconv(t, p)
30988cbd795Sdonn register int t;
31088cbd795Sdonn register expptr p;
31188cbd795Sdonn {
31288cbd795Sdonn register expptr q;
31388cbd795Sdonn Addrp r, s;
31488cbd795Sdonn register int pt;
31588cbd795Sdonn expptr opconv();
31688cbd795Sdonn 
31788cbd795Sdonn if(t==TYUNKNOWN || t==TYERROR)
31888cbd795Sdonn 	badtype("mkconv", t);
31988cbd795Sdonn pt = p->headblock.vtype;
32088cbd795Sdonn if(t == pt)
32188cbd795Sdonn 	return(p);
32288cbd795Sdonn 
32388cbd795Sdonn if( pt == TYCHAR && ISNUMERIC(t) )
32488cbd795Sdonn 	{
32588cbd795Sdonn 	warn("implicit conversion of character to numeric type");
32688cbd795Sdonn 
32788cbd795Sdonn 	/*
32888cbd795Sdonn 	 * Ugly kluge to copy character values into numerics.
32988cbd795Sdonn 	 */
33088cbd795Sdonn 	s = mkaltemp(t, ENULL);
33188cbd795Sdonn 	r = (Addrp) cpexpr(s);
33288cbd795Sdonn 	r->vtype = TYCHAR;
33388cbd795Sdonn 	r->varleng = typesize[t];
33488cbd795Sdonn 	r->vleng = mkintcon(r->varleng);
33588cbd795Sdonn 	q = mkexpr(OPASSIGN, r, p);
33688cbd795Sdonn 	q = mkexpr(OPCOMMA, q, s);
33788cbd795Sdonn 	return(q);
33888cbd795Sdonn 	}
33988cbd795Sdonn 
34088cbd795Sdonn #if SZADDR > SZSHORT
34188cbd795Sdonn if( pt == TYADDR && t == TYSHORT)
34288cbd795Sdonn 	{
34388cbd795Sdonn 	err("insufficient precision to hold address type");
34488cbd795Sdonn 	return( errnode() );
34588cbd795Sdonn 	}
34688cbd795Sdonn #endif
34788cbd795Sdonn if( pt == TYADDR && ISNUMERIC(t) )
34888cbd795Sdonn 	warn("implicit conversion of address to numeric type");
34988cbd795Sdonn 
35088cbd795Sdonn if( ISCONST(p) && pt!=TYADDR)
35188cbd795Sdonn 	{
35288cbd795Sdonn 	q = (expptr) mkconst(t);
35376ad5316Sbostic 	consconv(t, &(q->constblock.constant),
35476ad5316Sbostic 		p->constblock.vtype, &(p->constblock.constant) );
35588cbd795Sdonn 	frexpr(p);
35688cbd795Sdonn 	}
35788cbd795Sdonn #if TARGET == PDP11
35888cbd795Sdonn else if(ISINT(t) && pt==TYCHAR)
35988cbd795Sdonn 	{
36088cbd795Sdonn 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
36188cbd795Sdonn 	if(t == TYLONG)
36288cbd795Sdonn 		q = opconv(q, TYLONG);
36388cbd795Sdonn 	}
36488cbd795Sdonn #endif
36588cbd795Sdonn else
36688cbd795Sdonn 	q = opconv(p, t);
36788cbd795Sdonn 
36888cbd795Sdonn if(t == TYCHAR)
36988cbd795Sdonn 	q->constblock.vleng = ICON(1);
37088cbd795Sdonn return(q);
37188cbd795Sdonn }
37288cbd795Sdonn 
37388cbd795Sdonn 
37488cbd795Sdonn 
37588cbd795Sdonn /* intrinsic conversions */
intrconv(t,p)37688cbd795Sdonn expptr intrconv(t, p)
37788cbd795Sdonn register int t;
37888cbd795Sdonn register expptr p;
37988cbd795Sdonn {
38088cbd795Sdonn register expptr q;
38188cbd795Sdonn register int pt;
38288cbd795Sdonn expptr opconv();
38388cbd795Sdonn 
38488cbd795Sdonn if(t==TYUNKNOWN || t==TYERROR)
38588cbd795Sdonn 	badtype("intrconv", t);
38688cbd795Sdonn pt = p->headblock.vtype;
38788cbd795Sdonn if(t == pt)
38888cbd795Sdonn 	return(p);
38988cbd795Sdonn 
39088cbd795Sdonn else if( ISCONST(p) && pt!=TYADDR)
39188cbd795Sdonn 	{
39288cbd795Sdonn 	q = (expptr) mkconst(t);
39376ad5316Sbostic 	consconv(t, &(q->constblock.constant),
39476ad5316Sbostic 		p->constblock.vtype, &(p->constblock.constant) );
39588cbd795Sdonn 	frexpr(p);
39688cbd795Sdonn 	}
39788cbd795Sdonn #if TARGET == PDP11
39888cbd795Sdonn else if(ISINT(t) && pt==TYCHAR)
39988cbd795Sdonn 	{
40088cbd795Sdonn 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
40188cbd795Sdonn 	if(t == TYLONG)
40288cbd795Sdonn 		q = opconv(q, TYLONG);
40388cbd795Sdonn 	}
40488cbd795Sdonn #endif
40588cbd795Sdonn else
40688cbd795Sdonn 	q = opconv(p, t);
40788cbd795Sdonn 
40888cbd795Sdonn if(t == TYCHAR)
40988cbd795Sdonn 	q->constblock.vleng = ICON(1);
41088cbd795Sdonn return(q);
41188cbd795Sdonn }
41288cbd795Sdonn 
41388cbd795Sdonn 
41488cbd795Sdonn 
opconv(p,t)41588cbd795Sdonn expptr opconv(p, t)
41688cbd795Sdonn expptr p;
41788cbd795Sdonn int t;
41888cbd795Sdonn {
41988cbd795Sdonn register expptr q;
42088cbd795Sdonn 
42188cbd795Sdonn q = mkexpr(OPCONV, p, PNULL);
42288cbd795Sdonn q->headblock.vtype = t;
42388cbd795Sdonn return(q);
42488cbd795Sdonn }
42588cbd795Sdonn 
42688cbd795Sdonn 
42788cbd795Sdonn 
addrof(p)42888cbd795Sdonn expptr addrof(p)
42988cbd795Sdonn expptr p;
43088cbd795Sdonn {
43188cbd795Sdonn return( mkexpr(OPADDR, p, PNULL) );
43288cbd795Sdonn }
43388cbd795Sdonn 
43488cbd795Sdonn 
43588cbd795Sdonn 
cpexpr(p)43688cbd795Sdonn tagptr cpexpr(p)
43788cbd795Sdonn register tagptr p;
43888cbd795Sdonn {
43988cbd795Sdonn register tagptr e;
44088cbd795Sdonn int tag;
44188cbd795Sdonn register chainp ep, pp;
44288cbd795Sdonn tagptr cpblock();
44388cbd795Sdonn 
44488cbd795Sdonn static int blksize[ ] =
44588cbd795Sdonn 	{	0,
44688cbd795Sdonn 		sizeof(struct Nameblock),
44788cbd795Sdonn 		sizeof(struct Constblock),
44888cbd795Sdonn 		sizeof(struct Exprblock),
44988cbd795Sdonn 		sizeof(struct Addrblock),
45088cbd795Sdonn 		sizeof(struct Tempblock),
45188cbd795Sdonn 		sizeof(struct Primblock),
45288cbd795Sdonn 		sizeof(struct Listblock),
45388cbd795Sdonn 		sizeof(struct Errorblock)
45488cbd795Sdonn 	};
45588cbd795Sdonn 
45688cbd795Sdonn if(p == NULL)
45788cbd795Sdonn 	return(NULL);
45888cbd795Sdonn 
45988cbd795Sdonn if( (tag = p->tag) == TNAME)
46088cbd795Sdonn 	return(p);
46188cbd795Sdonn 
46288cbd795Sdonn e = cpblock( blksize[p->tag] , p);
46388cbd795Sdonn 
46488cbd795Sdonn switch(tag)
46588cbd795Sdonn 	{
46688cbd795Sdonn 	case TCONST:
46788cbd795Sdonn 		if(e->constblock.vtype == TYCHAR)
46888cbd795Sdonn 			{
46976ad5316Sbostic 			e->constblock.constant.ccp =
47076ad5316Sbostic 				copyn(1+strlen(e->constblock.constant.ccp),
47176ad5316Sbostic 					e->constblock.constant.ccp);
47288cbd795Sdonn 			e->constblock.vleng =
47388cbd795Sdonn 				(expptr) cpexpr(e->constblock.vleng);
47488cbd795Sdonn 			}
47588cbd795Sdonn 	case TERROR:
47688cbd795Sdonn 		break;
47788cbd795Sdonn 
47888cbd795Sdonn 	case TEXPR:
47988cbd795Sdonn 		e->exprblock.leftp =  (expptr) cpexpr(p->exprblock.leftp);
48088cbd795Sdonn 		e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
48188cbd795Sdonn 		break;
48288cbd795Sdonn 
48388cbd795Sdonn 	case TLIST:
48488cbd795Sdonn 		if(pp = p->listblock.listp)
48588cbd795Sdonn 			{
48688cbd795Sdonn 			ep = e->listblock.listp =
48788cbd795Sdonn 				mkchain( cpexpr(pp->datap), CHNULL);
48888cbd795Sdonn 			for(pp = pp->nextp ; pp ; pp = pp->nextp)
48988cbd795Sdonn 				ep = ep->nextp =
49088cbd795Sdonn 					mkchain( cpexpr(pp->datap), CHNULL);
49188cbd795Sdonn 			}
49288cbd795Sdonn 		break;
49388cbd795Sdonn 
49488cbd795Sdonn 	case TADDR:
49588cbd795Sdonn 		e->addrblock.vleng = (expptr)  cpexpr(e->addrblock.vleng);
49688cbd795Sdonn 		e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
49788cbd795Sdonn 		e->addrblock.istemp = NO;
49888cbd795Sdonn 		break;
49988cbd795Sdonn 
50088cbd795Sdonn 	case TTEMP:
50188cbd795Sdonn 		e->tempblock.vleng = (expptr)  cpexpr(e->tempblock.vleng);
50288cbd795Sdonn 		e->tempblock.istemp = NO;
50388cbd795Sdonn 		break;
50488cbd795Sdonn 
50588cbd795Sdonn 	case TPRIM:
50688cbd795Sdonn 		e->primblock.argsp = (struct Listblock *)
50788cbd795Sdonn 					cpexpr(e->primblock.argsp);
50888cbd795Sdonn 		e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
50988cbd795Sdonn 		e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
51088cbd795Sdonn 		break;
51188cbd795Sdonn 
51288cbd795Sdonn 	default:
51388cbd795Sdonn 		badtag("cpexpr", tag);
51488cbd795Sdonn 	}
51588cbd795Sdonn 
51688cbd795Sdonn return(e);
51788cbd795Sdonn }
51888cbd795Sdonn 
frexpr(p)51988cbd795Sdonn frexpr(p)
52088cbd795Sdonn register tagptr p;
52188cbd795Sdonn {
52288cbd795Sdonn register chainp q;
52388cbd795Sdonn 
52488cbd795Sdonn if(p == NULL)
52588cbd795Sdonn 	return;
52688cbd795Sdonn 
52788cbd795Sdonn switch(p->tag)
52888cbd795Sdonn 	{
52988cbd795Sdonn 	case TCONST:
53088cbd795Sdonn 		switch (p->constblock.vtype)
53188cbd795Sdonn 			{
53288cbd795Sdonn 			case TYBITSTR:
53388cbd795Sdonn 			case TYCHAR:
53488cbd795Sdonn 			case TYHOLLERITH:
53576ad5316Sbostic 				free( (charptr) (p->constblock.constant.ccp) );
53688cbd795Sdonn 				frexpr(p->constblock.vleng);
53788cbd795Sdonn 			}
53888cbd795Sdonn 		break;
53988cbd795Sdonn 
54088cbd795Sdonn 	case TADDR:
54188cbd795Sdonn 		if (!optimflag && p->addrblock.istemp)
54288cbd795Sdonn 			{
54388cbd795Sdonn 			frtemp(p);
54488cbd795Sdonn 			return;
54588cbd795Sdonn 			}
54688cbd795Sdonn 		frexpr(p->addrblock.vleng);
54788cbd795Sdonn 		frexpr(p->addrblock.memoffset);
54888cbd795Sdonn 		break;
54988cbd795Sdonn 
55088cbd795Sdonn 	case TTEMP:
55188cbd795Sdonn 		frexpr(p->tempblock.vleng);
55288cbd795Sdonn 		break;
55388cbd795Sdonn 
55488cbd795Sdonn 	case TERROR:
55588cbd795Sdonn 		break;
55688cbd795Sdonn 
55788cbd795Sdonn 	case TNAME:
55888cbd795Sdonn 		return;
55988cbd795Sdonn 
56088cbd795Sdonn 	case TPRIM:
56188cbd795Sdonn 		frexpr(p->primblock.argsp);
56288cbd795Sdonn 		frexpr(p->primblock.fcharp);
56388cbd795Sdonn 		frexpr(p->primblock.lcharp);
56488cbd795Sdonn 		break;
56588cbd795Sdonn 
56688cbd795Sdonn 	case TEXPR:
56788cbd795Sdonn 		frexpr(p->exprblock.leftp);
56888cbd795Sdonn 		if(p->exprblock.rightp)
56988cbd795Sdonn 			frexpr(p->exprblock.rightp);
57088cbd795Sdonn 		break;
57188cbd795Sdonn 
57288cbd795Sdonn 	case TLIST:
57388cbd795Sdonn 		for(q = p->listblock.listp ; q ; q = q->nextp)
57488cbd795Sdonn 			frexpr(q->datap);
57588cbd795Sdonn 		frchain( &(p->listblock.listp) );
57688cbd795Sdonn 		break;
57788cbd795Sdonn 
57888cbd795Sdonn 	default:
57988cbd795Sdonn 		badtag("frexpr", p->tag);
58088cbd795Sdonn 	}
58188cbd795Sdonn 
58288cbd795Sdonn free( (charptr) p );
58388cbd795Sdonn }
58488cbd795Sdonn 
58588cbd795Sdonn /* fix up types in expression; replace subtrees and convert
58688cbd795Sdonn    names to address blocks */
58788cbd795Sdonn 
fixtype(p)58888cbd795Sdonn expptr fixtype(p)
58988cbd795Sdonn register tagptr p;
59088cbd795Sdonn {
59188cbd795Sdonn 
59288cbd795Sdonn if(p == 0)
59388cbd795Sdonn 	return(0);
59488cbd795Sdonn 
59588cbd795Sdonn switch(p->tag)
59688cbd795Sdonn 	{
59788cbd795Sdonn 	case TCONST:
59888cbd795Sdonn 		return( (expptr) p );
59988cbd795Sdonn 
60088cbd795Sdonn 	case TADDR:
60188cbd795Sdonn 		p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
60288cbd795Sdonn 		return( (expptr) p);
60388cbd795Sdonn 
60488cbd795Sdonn 	case TTEMP:
60588cbd795Sdonn 		return( (expptr) p);
60688cbd795Sdonn 
60788cbd795Sdonn 	case TERROR:
60888cbd795Sdonn 		return( (expptr) p);
60988cbd795Sdonn 
61088cbd795Sdonn 	default:
61188cbd795Sdonn 		badtag("fixtype", p->tag);
61288cbd795Sdonn 
61388cbd795Sdonn 	case TEXPR:
61488cbd795Sdonn 		return( fixexpr(p) );
61588cbd795Sdonn 
61688cbd795Sdonn 	case TLIST:
61788cbd795Sdonn 		return( (expptr) p );
61888cbd795Sdonn 
61988cbd795Sdonn 	case TPRIM:
62088cbd795Sdonn 		if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
62188cbd795Sdonn 			{
62288cbd795Sdonn 			if(p->primblock.namep->vtype == TYSUBR)
62388cbd795Sdonn 				{
62488cbd795Sdonn 				err("function invocation of subroutine");
62588cbd795Sdonn 				return( errnode() );
62688cbd795Sdonn 				}
62788cbd795Sdonn 			else
62888cbd795Sdonn 				return( mkfunct(p) );
62988cbd795Sdonn 			}
63088cbd795Sdonn 		else	return( mklhs(p) );
63188cbd795Sdonn 	}
63288cbd795Sdonn }
63388cbd795Sdonn 
63488cbd795Sdonn 
63588cbd795Sdonn 
63688cbd795Sdonn 
63788cbd795Sdonn 
63888cbd795Sdonn /* special case tree transformations and cleanups of expression trees */
63988cbd795Sdonn 
fixexpr(p)64088cbd795Sdonn expptr fixexpr(p)
64188cbd795Sdonn register Exprp p;
64288cbd795Sdonn {
64388cbd795Sdonn expptr lp;
64488cbd795Sdonn register expptr rp;
64588cbd795Sdonn register expptr q;
64688cbd795Sdonn int opcode, ltype, rtype, ptype, mtype;
64788cbd795Sdonn expptr lconst, rconst;
64888cbd795Sdonn expptr mkpower();
64988cbd795Sdonn 
65088cbd795Sdonn if( ISERROR(p) )
65188cbd795Sdonn 	return( (expptr) p );
65288cbd795Sdonn else if(p->tag != TEXPR)
65388cbd795Sdonn 	badtag("fixexpr", p->tag);
65488cbd795Sdonn opcode = p->opcode;
65588cbd795Sdonn if (ISCONST(p->leftp))
65688cbd795Sdonn 	lconst = (expptr) cpexpr(p->leftp);
65788cbd795Sdonn else
65888cbd795Sdonn 	lconst = NULL;
65988cbd795Sdonn if (p->rightp && ISCONST(p->rightp))
66088cbd795Sdonn 	rconst = (expptr) cpexpr(p->rightp);
66188cbd795Sdonn else
66288cbd795Sdonn 	rconst = NULL;
66388cbd795Sdonn lp = p->leftp = fixtype(p->leftp);
66488cbd795Sdonn ltype = lp->headblock.vtype;
66588cbd795Sdonn if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
66688cbd795Sdonn 	{
66788cbd795Sdonn 	err("left side of assignment must be variable");
66888cbd795Sdonn 	frexpr(p);
66988cbd795Sdonn 	return( errnode() );
67088cbd795Sdonn 	}
67188cbd795Sdonn 
67288cbd795Sdonn if(p->rightp)
67388cbd795Sdonn 	{
67488cbd795Sdonn 	rp = p->rightp = fixtype(p->rightp);
67588cbd795Sdonn 	rtype = rp->headblock.vtype;
67688cbd795Sdonn 	}
67788cbd795Sdonn else
67888cbd795Sdonn 	{
67988cbd795Sdonn 	rp = NULL;
68088cbd795Sdonn 	rtype = 0;
68188cbd795Sdonn 	}
68288cbd795Sdonn 
68388cbd795Sdonn if(ltype==TYERROR || rtype==TYERROR)
68488cbd795Sdonn 	{
68588cbd795Sdonn 	frexpr(p);
68688cbd795Sdonn 	frexpr(lconst);
68788cbd795Sdonn 	frexpr(rconst);
68888cbd795Sdonn 	return( errnode() );
68988cbd795Sdonn 	}
69088cbd795Sdonn 
69188cbd795Sdonn /* force folding if possible */
69288cbd795Sdonn if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
69388cbd795Sdonn 	{
69488cbd795Sdonn 	q = mkexpr(opcode, lp, rp);
69588cbd795Sdonn 	if( ISCONST(q) )
69688cbd795Sdonn 		{
69788cbd795Sdonn 		frexpr(lconst);
69888cbd795Sdonn 		frexpr(rconst);
69988cbd795Sdonn 		return(q);
70088cbd795Sdonn 		}
70188cbd795Sdonn 	free( (charptr) q );	/* constants did not fold */
70288cbd795Sdonn 	}
70388cbd795Sdonn 
70488cbd795Sdonn if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
70588cbd795Sdonn 	{
70688cbd795Sdonn 	frexpr(p);
70788cbd795Sdonn 	frexpr(lconst);
70888cbd795Sdonn 	frexpr(rconst);
70988cbd795Sdonn 	return( errnode() );
71088cbd795Sdonn 	}
71188cbd795Sdonn 
71288cbd795Sdonn switch(opcode)
71388cbd795Sdonn 	{
71488cbd795Sdonn 	case OPCONCAT:
71588cbd795Sdonn 		if(p->vleng == NULL)
71688cbd795Sdonn 			p->vleng = mkexpr(OPPLUS,
71788cbd795Sdonn 				cpexpr(lp->headblock.vleng),
71888cbd795Sdonn 				cpexpr(rp->headblock.vleng) );
71988cbd795Sdonn 		break;
72088cbd795Sdonn 
72188cbd795Sdonn 	case OPASSIGN:
72288cbd795Sdonn 	case OPPLUSEQ:
72388cbd795Sdonn 	case OPSTAREQ:
72488cbd795Sdonn 		if(ltype == rtype)
72588cbd795Sdonn 			break;
72688cbd795Sdonn #if TARGET == VAX
72788cbd795Sdonn 		if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
72888cbd795Sdonn 			break;
72988cbd795Sdonn #endif
73088cbd795Sdonn 		if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
73188cbd795Sdonn 			break;
73288cbd795Sdonn 		if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
73388cbd795Sdonn #if FAMILY==PCC
73488cbd795Sdonn 		    && typesize[ltype]>=typesize[rtype] )
73588cbd795Sdonn #else
73688cbd795Sdonn 		    && typesize[ltype]==typesize[rtype] )
73788cbd795Sdonn #endif
73888cbd795Sdonn 			break;
73988cbd795Sdonn 		if (rconst)
74088cbd795Sdonn 			{
74188cbd795Sdonn 			p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
74288cbd795Sdonn 			frexpr(rp);
74388cbd795Sdonn 			}
74488cbd795Sdonn 		else
74588cbd795Sdonn 			p->rightp = fixtype(mkconv(ptype, rp));
74688cbd795Sdonn 		break;
74788cbd795Sdonn 
74888cbd795Sdonn 	case OPSLASH:
74988cbd795Sdonn 		if( ISCOMPLEX(rtype) )
75088cbd795Sdonn 			{
75188cbd795Sdonn 			p = (Exprp) call2(ptype,
75288cbd795Sdonn 				ptype==TYCOMPLEX? "c_div" : "z_div",
75388cbd795Sdonn 				mkconv(ptype, lp), mkconv(ptype, rp) );
75488cbd795Sdonn 			break;
75588cbd795Sdonn 			}
75688cbd795Sdonn 	case OPPLUS:
75788cbd795Sdonn 	case OPMINUS:
75888cbd795Sdonn 	case OPSTAR:
75988cbd795Sdonn 	case OPMOD:
76088cbd795Sdonn #if TARGET == VAX
76188cbd795Sdonn 		if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
76288cbd795Sdonn 		    (rtype==TYREAL && ! rconst ) ))
76388cbd795Sdonn 			break;
76488cbd795Sdonn #endif
76588cbd795Sdonn 		if( ISCOMPLEX(ptype) )
76688cbd795Sdonn 			break;
76788cbd795Sdonn 		if(ltype != ptype)
76888cbd795Sdonn 			if (lconst)
76988cbd795Sdonn 				{
77088cbd795Sdonn 				p->leftp = fixtype(mkconv(ptype,
77188cbd795Sdonn 						cpexpr(lconst)));
77288cbd795Sdonn 				frexpr(lp);
77388cbd795Sdonn 				}
77488cbd795Sdonn 			else
77588cbd795Sdonn 				p->leftp = fixtype(mkconv(ptype,lp));
77688cbd795Sdonn 		if(rtype != ptype)
77788cbd795Sdonn 			if (rconst)
77888cbd795Sdonn 				{
77988cbd795Sdonn 				p->rightp = fixtype(mkconv(ptype,
78088cbd795Sdonn 						cpexpr(rconst)));
78188cbd795Sdonn 				frexpr(rp);
78288cbd795Sdonn 				}
78388cbd795Sdonn 			else
78488cbd795Sdonn 				p->rightp = fixtype(mkconv(ptype,rp));
78588cbd795Sdonn 		break;
78688cbd795Sdonn 
78788cbd795Sdonn 	case OPPOWER:
78888cbd795Sdonn 		return( mkpower(p) );
78988cbd795Sdonn 
79088cbd795Sdonn 	case OPLT:
79188cbd795Sdonn 	case OPLE:
79288cbd795Sdonn 	case OPGT:
79388cbd795Sdonn 	case OPGE:
79488cbd795Sdonn 	case OPEQ:
79588cbd795Sdonn 	case OPNE:
79688cbd795Sdonn 		if(ltype == rtype)
79788cbd795Sdonn 			break;
79888cbd795Sdonn 		mtype = cktype(OPMINUS, ltype, rtype);
79988cbd795Sdonn #if TARGET == VAX
80088cbd795Sdonn 		if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
80188cbd795Sdonn 		    (rtype==TYREAL && ! rconst) ))
80288cbd795Sdonn 			break;
80388cbd795Sdonn #endif
80488cbd795Sdonn 		if( ISCOMPLEX(mtype) )
80588cbd795Sdonn 			break;
80688cbd795Sdonn 		if(ltype != mtype)
80788cbd795Sdonn 			if (lconst)
80888cbd795Sdonn 				{
80988cbd795Sdonn 				p->leftp = fixtype(mkconv(mtype,
81088cbd795Sdonn 						cpexpr(lconst)));
81188cbd795Sdonn 				frexpr(lp);
81288cbd795Sdonn 				}
81388cbd795Sdonn 			else
81488cbd795Sdonn 				p->leftp = fixtype(mkconv(mtype,lp));
81588cbd795Sdonn 		if(rtype != mtype)
81688cbd795Sdonn 			if (rconst)
81788cbd795Sdonn 				{
81888cbd795Sdonn 				p->rightp = fixtype(mkconv(mtype,
81988cbd795Sdonn 						cpexpr(rconst)));
82088cbd795Sdonn 				frexpr(rp);
82188cbd795Sdonn 				}
82288cbd795Sdonn 			else
82388cbd795Sdonn 				p->rightp = fixtype(mkconv(mtype,rp));
82488cbd795Sdonn 		break;
82588cbd795Sdonn 
82688cbd795Sdonn 
82788cbd795Sdonn 	case OPCONV:
82888cbd795Sdonn 		if(ISCOMPLEX(p->vtype))
82988cbd795Sdonn 			{
83088cbd795Sdonn 			ptype = cktype(OPCONV, p->vtype, ltype);
83188cbd795Sdonn 			if(p->rightp)
83288cbd795Sdonn 				ptype = cktype(OPCONV, ptype, rtype);
83388cbd795Sdonn 			break;
83488cbd795Sdonn 			}
83588cbd795Sdonn 		ptype = cktype(OPCONV, p->vtype, ltype);
83688cbd795Sdonn 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
83788cbd795Sdonn 			{
83888cbd795Sdonn 			lp->exprblock.rightp =
83988cbd795Sdonn 				fixtype( mkconv(ptype, lp->exprblock.rightp) );
84088cbd795Sdonn 			free( (charptr) p );
84188cbd795Sdonn 			p = (Exprp) lp;
84288cbd795Sdonn 			}
84388cbd795Sdonn 		break;
84488cbd795Sdonn 
84588cbd795Sdonn 	case OPADDR:
84688cbd795Sdonn 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
84788cbd795Sdonn 			fatal("addr of addr");
84888cbd795Sdonn 		break;
84988cbd795Sdonn 
85088cbd795Sdonn 	case OPCOMMA:
85188cbd795Sdonn 	case OPQUEST:
85288cbd795Sdonn 	case OPCOLON:
85388cbd795Sdonn 		break;
85488cbd795Sdonn 
85588cbd795Sdonn 	case OPPAREN:
85688cbd795Sdonn 		p->vleng = (expptr) cpexpr( lp->headblock.vleng );
85788cbd795Sdonn 		break;
85888cbd795Sdonn 
85988cbd795Sdonn 	case OPMIN:
86088cbd795Sdonn 	case OPMAX:
86188cbd795Sdonn 		ptype = p->vtype;
86288cbd795Sdonn 		break;
86388cbd795Sdonn 
86488cbd795Sdonn 	default:
86588cbd795Sdonn 		break;
86688cbd795Sdonn 	}
86788cbd795Sdonn 
86888cbd795Sdonn p->vtype = ptype;
86988cbd795Sdonn frexpr(lconst);
87088cbd795Sdonn frexpr(rconst);
87188cbd795Sdonn return((expptr) p);
87288cbd795Sdonn }
87388cbd795Sdonn 
87488cbd795Sdonn #if SZINT < SZLONG
87588cbd795Sdonn /*
87688cbd795Sdonn    for efficient subscripting, replace long ints by shorts
87788cbd795Sdonn    in easy places
87888cbd795Sdonn */
87988cbd795Sdonn 
shorten(p)88088cbd795Sdonn expptr shorten(p)
88188cbd795Sdonn register expptr p;
88288cbd795Sdonn {
88388cbd795Sdonn register expptr q;
88488cbd795Sdonn 
88588cbd795Sdonn if(p->headblock.vtype != TYLONG)
88688cbd795Sdonn 	return(p);
88788cbd795Sdonn 
88888cbd795Sdonn switch(p->tag)
88988cbd795Sdonn 	{
89088cbd795Sdonn 	case TERROR:
89188cbd795Sdonn 	case TLIST:
89288cbd795Sdonn 		return(p);
89388cbd795Sdonn 
89488cbd795Sdonn 	case TCONST:
89588cbd795Sdonn 	case TADDR:
89688cbd795Sdonn 		return( mkconv(TYINT,p) );
89788cbd795Sdonn 
89888cbd795Sdonn 	case TEXPR:
89988cbd795Sdonn 		break;
90088cbd795Sdonn 
90188cbd795Sdonn 	default:
90288cbd795Sdonn 		badtag("shorten", p->tag);
90388cbd795Sdonn 	}
90488cbd795Sdonn 
90588cbd795Sdonn switch(p->exprblock.opcode)
90688cbd795Sdonn 	{
90788cbd795Sdonn 	case OPPLUS:
90888cbd795Sdonn 	case OPMINUS:
90988cbd795Sdonn 	case OPSTAR:
91088cbd795Sdonn 		q = shorten( cpexpr(p->exprblock.rightp) );
91188cbd795Sdonn 		if(q->headblock.vtype == TYINT)
91288cbd795Sdonn 			{
91388cbd795Sdonn 			p->exprblock.leftp = shorten(p->exprblock.leftp);
91488cbd795Sdonn 			if(p->exprblock.leftp->headblock.vtype == TYLONG)
91588cbd795Sdonn 				frexpr(q);
91688cbd795Sdonn 			else
91788cbd795Sdonn 				{
91888cbd795Sdonn 				frexpr(p->exprblock.rightp);
91988cbd795Sdonn 				p->exprblock.rightp = q;
92088cbd795Sdonn 				p->exprblock.vtype = TYINT;
92188cbd795Sdonn 				}
92288cbd795Sdonn 			}
92388cbd795Sdonn 		break;
92488cbd795Sdonn 
92588cbd795Sdonn 	case OPNEG:
92688cbd795Sdonn 	case OPPAREN:
92788cbd795Sdonn 		p->exprblock.leftp = shorten(p->exprblock.leftp);
92888cbd795Sdonn 		if(p->exprblock.leftp->headblock.vtype == TYINT)
92988cbd795Sdonn 			p->exprblock.vtype = TYINT;
93088cbd795Sdonn 		break;
93188cbd795Sdonn 
93288cbd795Sdonn 	case OPCALL:
93388cbd795Sdonn 	case OPCCALL:
93488cbd795Sdonn 		p = mkconv(TYINT,p);
93588cbd795Sdonn 		break;
93688cbd795Sdonn 	default:
93788cbd795Sdonn 		break;
93888cbd795Sdonn 	}
93988cbd795Sdonn 
94088cbd795Sdonn return(p);
94188cbd795Sdonn }
94288cbd795Sdonn #endif
94388cbd795Sdonn /* fix an argument list, taking due care for special first level cases */
94488cbd795Sdonn 
fixargs(doput,p0)94588cbd795Sdonn fixargs(doput, p0)
94688cbd795Sdonn int doput;	/* doput is true if the function is not intrinsic;
94788cbd795Sdonn 		   was used to decide whether to do a putconst,
94888cbd795Sdonn 		   but this is no longer done here (Feb82)*/
94988cbd795Sdonn struct Listblock *p0;
95088cbd795Sdonn {
95188cbd795Sdonn register chainp p;
95288cbd795Sdonn register tagptr q, t;
95388cbd795Sdonn register int qtag;
95488cbd795Sdonn int nargs;
95588cbd795Sdonn Addrp mkscalar();
95688cbd795Sdonn 
95788cbd795Sdonn nargs = 0;
95888cbd795Sdonn if(p0)
95988cbd795Sdonn     for(p = p0->listp ; p ; p = p->nextp)
96088cbd795Sdonn 	{
96188cbd795Sdonn 	++nargs;
96288cbd795Sdonn 	q = p->datap;
96388cbd795Sdonn 	qtag = q->tag;
96488cbd795Sdonn 	if(qtag == TCONST)
96588cbd795Sdonn 		{
96688cbd795Sdonn 
96788cbd795Sdonn /*
96888cbd795Sdonn 		if(q->constblock.vtype == TYSHORT)
96988cbd795Sdonn 			q = (tagptr) mkconv(tyint, q);
97088cbd795Sdonn */
97188cbd795Sdonn 		p->datap = q ;
97288cbd795Sdonn 		}
97388cbd795Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
97488cbd795Sdonn 		q->primblock.namep->vclass==CLPROC)
97588cbd795Sdonn 			p->datap = (tagptr) mkaddr(q->primblock.namep);
97688cbd795Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
97788cbd795Sdonn 		q->primblock.namep->vdim!=NULL)
97888cbd795Sdonn 			p->datap = (tagptr) mkscalar(q->primblock.namep);
97988cbd795Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
98088cbd795Sdonn 		q->primblock.namep->vdovar &&
98188cbd795Sdonn 		(t = (tagptr) memversion(q->primblock.namep)) )
98288cbd795Sdonn 			p->datap = (tagptr) fixtype(t);
98388cbd795Sdonn 	else
98488cbd795Sdonn 		p->datap = (tagptr) fixtype(q);
98588cbd795Sdonn 	}
98688cbd795Sdonn return(nargs);
98788cbd795Sdonn }
98888cbd795Sdonn 
98988cbd795Sdonn 
mkscalar(np)99088cbd795Sdonn Addrp mkscalar(np)
99188cbd795Sdonn register Namep np;
99288cbd795Sdonn {
99388cbd795Sdonn register Addrp ap;
99488cbd795Sdonn 
99588cbd795Sdonn vardcl(np);
99688cbd795Sdonn ap = mkaddr(np);
99788cbd795Sdonn 
99888cbd795Sdonn #if TARGET == VAX || TARGET == TAHOE
99988cbd795Sdonn 	/* on the VAX, prolog causes array arguments
100088cbd795Sdonn 	   to point at the (0,...,0) element, except when
100188cbd795Sdonn 	   subscript checking is on
100288cbd795Sdonn 	*/
100388cbd795Sdonn #ifdef SDB
100488cbd795Sdonn 	if( !checksubs && !sdbflag && np->vstg==STGARG)
100588cbd795Sdonn #else
100688cbd795Sdonn 	if( !checksubs && np->vstg==STGARG)
100788cbd795Sdonn #endif
100888cbd795Sdonn 		{
100988cbd795Sdonn 		register struct Dimblock *dp;
101088cbd795Sdonn 		dp = np->vdim;
101188cbd795Sdonn 		frexpr(ap->memoffset);
101288cbd795Sdonn 		ap->memoffset = mkexpr(OPSTAR,
101388cbd795Sdonn 				(np->vtype==TYCHAR ?
101488cbd795Sdonn 					cpexpr(np->vleng) :
101588cbd795Sdonn 					(tagptr)ICON(typesize[np->vtype]) ),
101688cbd795Sdonn 				cpexpr(dp->baseoffset) );
101788cbd795Sdonn 		}
101888cbd795Sdonn #endif
101988cbd795Sdonn return(ap);
102088cbd795Sdonn }
102188cbd795Sdonn 
102288cbd795Sdonn 
102388cbd795Sdonn 
102488cbd795Sdonn 
102588cbd795Sdonn 
mkfunct(p)102688cbd795Sdonn expptr mkfunct(p)
102788cbd795Sdonn register struct Primblock *p;
102888cbd795Sdonn {
102988cbd795Sdonn struct Entrypoint *ep;
103088cbd795Sdonn Addrp ap;
103188cbd795Sdonn struct Extsym *extp;
103288cbd795Sdonn register Namep np;
103388cbd795Sdonn register expptr q;
103488cbd795Sdonn expptr intrcall(), stfcall();
103588cbd795Sdonn int k, nargs;
103688cbd795Sdonn int class;
103788cbd795Sdonn 
103888cbd795Sdonn if(p->tag != TPRIM)
103988cbd795Sdonn 	return( errnode() );
104088cbd795Sdonn 
104188cbd795Sdonn np = p->namep;
104288cbd795Sdonn class = np->vclass;
104388cbd795Sdonn 
104488cbd795Sdonn if(class == CLUNKNOWN)
104588cbd795Sdonn 	{
104688cbd795Sdonn 	np->vclass = class = CLPROC;
104788cbd795Sdonn 	if(np->vstg == STGUNKNOWN)
104888cbd795Sdonn 		{
104988cbd795Sdonn 		if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
105088cbd795Sdonn 			{
105188cbd795Sdonn 			np->vstg = STGINTR;
105288cbd795Sdonn 			np->vardesc.varno = k;
105388cbd795Sdonn 			np->vprocclass = PINTRINSIC;
105488cbd795Sdonn 			}
105588cbd795Sdonn 		else
105688cbd795Sdonn 			{
105788cbd795Sdonn 			extp = mkext( varunder(VL,np->varname) );
105888cbd795Sdonn 			if(extp->extstg == STGCOMMON)
105988cbd795Sdonn 				warn("conflicting declarations", np->varname);
106088cbd795Sdonn 			extp->extstg = STGEXT;
106188cbd795Sdonn 			np->vstg = STGEXT;
106288cbd795Sdonn 			np->vardesc.varno = extp - extsymtab;
106388cbd795Sdonn 			np->vprocclass = PEXTERNAL;
106488cbd795Sdonn 			}
106588cbd795Sdonn 		}
106688cbd795Sdonn 	else if(np->vstg==STGARG)
106788cbd795Sdonn 		{
106888cbd795Sdonn 		if(np->vtype!=TYCHAR && !ftn66flag)
106988cbd795Sdonn 		    warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
107088cbd795Sdonn 		np->vprocclass = PEXTERNAL;
107188cbd795Sdonn 		}
107288cbd795Sdonn 	}
107388cbd795Sdonn 
107488cbd795Sdonn if(class != CLPROC)
107588cbd795Sdonn 	fatali("invalid class code %d for function", class);
107688cbd795Sdonn if(p->fcharp || p->lcharp)
107788cbd795Sdonn 	{
107888cbd795Sdonn 	err("no substring of function call");
107988cbd795Sdonn 	goto error;
108088cbd795Sdonn 	}
108188cbd795Sdonn impldcl(np);
108288cbd795Sdonn nargs = fixargs( np->vprocclass!=PINTRINSIC,  p->argsp);
108388cbd795Sdonn 
108488cbd795Sdonn switch(np->vprocclass)
108588cbd795Sdonn 	{
108688cbd795Sdonn 	case PEXTERNAL:
108788cbd795Sdonn 		ap = mkaddr(np);
108888cbd795Sdonn 	call:
108988cbd795Sdonn 		q = mkexpr(OPCALL, ap, p->argsp);
109088cbd795Sdonn 		if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
109188cbd795Sdonn 			{
109288cbd795Sdonn 			err("attempt to use untyped function");
109388cbd795Sdonn 			goto error;
109488cbd795Sdonn 			}
109588cbd795Sdonn 		if(np->vleng)
109688cbd795Sdonn 			q->exprblock.vleng = (expptr) cpexpr(np->vleng);
109788cbd795Sdonn 		break;
109888cbd795Sdonn 
109988cbd795Sdonn 	case PINTRINSIC:
110088cbd795Sdonn 		q = intrcall(np, p->argsp, nargs);
110188cbd795Sdonn 		break;
110288cbd795Sdonn 
110388cbd795Sdonn 	case PSTFUNCT:
110488cbd795Sdonn 		q = stfcall(np, p->argsp);
110588cbd795Sdonn 		break;
110688cbd795Sdonn 
110788cbd795Sdonn 	case PTHISPROC:
110888cbd795Sdonn 		warn("recursive call");
110988cbd795Sdonn 		for(ep = entries ; ep ; ep = ep->entnextp)
111088cbd795Sdonn 			if(ep->enamep == np)
111188cbd795Sdonn 				break;
111288cbd795Sdonn 		if(ep == NULL)
111388cbd795Sdonn 			fatal("mkfunct: impossible recursion");
111488cbd795Sdonn 		ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
111588cbd795Sdonn 		goto call;
111688cbd795Sdonn 
111788cbd795Sdonn 	default:
111888cbd795Sdonn 		fatali("mkfunct: impossible vprocclass %d",
111988cbd795Sdonn 			(int) (np->vprocclass) );
112088cbd795Sdonn 	}
112188cbd795Sdonn free( (charptr) p );
112288cbd795Sdonn return(q);
112388cbd795Sdonn 
112488cbd795Sdonn error:
112588cbd795Sdonn 	frexpr(p);
112688cbd795Sdonn 	return( errnode() );
112788cbd795Sdonn }
112888cbd795Sdonn 
112988cbd795Sdonn 
113088cbd795Sdonn 
stfcall(np,actlist)113188cbd795Sdonn LOCAL expptr stfcall(np, actlist)
113288cbd795Sdonn Namep np;
113388cbd795Sdonn struct Listblock *actlist;
113488cbd795Sdonn {
113588cbd795Sdonn register chainp actuals;
113688cbd795Sdonn int nargs;
113788cbd795Sdonn chainp oactp, formals;
113888cbd795Sdonn int type;
113988cbd795Sdonn expptr q, rhs, ap;
114088cbd795Sdonn Namep tnp;
114188cbd795Sdonn register struct Rplblock *rp;
114288cbd795Sdonn struct Rplblock *tlist;
114388cbd795Sdonn 
114488cbd795Sdonn if(actlist)
114588cbd795Sdonn 	{
114688cbd795Sdonn 	actuals = actlist->listp;
114788cbd795Sdonn 	free( (charptr) actlist);
114888cbd795Sdonn 	}
114988cbd795Sdonn else
115088cbd795Sdonn 	actuals = NULL;
115188cbd795Sdonn oactp = actuals;
115288cbd795Sdonn 
115388cbd795Sdonn nargs = 0;
115488cbd795Sdonn tlist = NULL;
115588cbd795Sdonn if( (type = np->vtype) == TYUNKNOWN)
115688cbd795Sdonn 	{
115788cbd795Sdonn 	err("attempt to use untyped statement function");
115888cbd795Sdonn 	q = errnode();
115988cbd795Sdonn 	goto ret;
116088cbd795Sdonn 	}
116188cbd795Sdonn formals = (chainp) (np->varxptr.vstfdesc->datap);
116288cbd795Sdonn rhs = (expptr) (np->varxptr.vstfdesc->nextp);
116388cbd795Sdonn 
116488cbd795Sdonn /* copy actual arguments into temporaries */
116588cbd795Sdonn while(actuals!=NULL && formals!=NULL)
116688cbd795Sdonn 	{
116788cbd795Sdonn 	rp = ALLOC(Rplblock);
116888cbd795Sdonn 	rp->rplnp = tnp = (Namep) (formals->datap);
116988cbd795Sdonn 	ap = fixtype(actuals->datap);
117088cbd795Sdonn 	if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
117188cbd795Sdonn 	   && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
117288cbd795Sdonn 		{
117388cbd795Sdonn 		rp->rplvp = (expptr) ap;
117488cbd795Sdonn 		rp->rplxp = NULL;
117588cbd795Sdonn 		rp->rpltag = ap->tag;
117688cbd795Sdonn 		}
117788cbd795Sdonn 	else	{
117888cbd795Sdonn 		rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
117988cbd795Sdonn 		rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
118088cbd795Sdonn 		if( (rp->rpltag = rp->rplxp->tag) == TERROR)
118188cbd795Sdonn 			err("disagreement of argument types in statement function call");
118288cbd795Sdonn 		else if(tnp->vtype!=ap->headblock.vtype)
118388cbd795Sdonn 			warn("argument type mismatch in statement function");
118488cbd795Sdonn 		}
118588cbd795Sdonn 	rp->rplnextp = tlist;
118688cbd795Sdonn 	tlist = rp;
118788cbd795Sdonn 	actuals = actuals->nextp;
118888cbd795Sdonn 	formals = formals->nextp;
118988cbd795Sdonn 	++nargs;
119088cbd795Sdonn 	}
119188cbd795Sdonn 
119288cbd795Sdonn if(actuals!=NULL || formals!=NULL)
119388cbd795Sdonn 	err("statement function definition and argument list differ");
119488cbd795Sdonn 
119588cbd795Sdonn /*
119688cbd795Sdonn    now push down names involved in formal argument list, then
119788cbd795Sdonn    evaluate rhs of statement function definition in this environment
119888cbd795Sdonn */
119988cbd795Sdonn 
120088cbd795Sdonn if(tlist)	/* put tlist in front of the rpllist */
120188cbd795Sdonn 	{
120288cbd795Sdonn 	for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
120388cbd795Sdonn 		;
120488cbd795Sdonn 	rp->rplnextp = rpllist;
120588cbd795Sdonn 	rpllist = tlist;
120688cbd795Sdonn 	}
120788cbd795Sdonn 
120888cbd795Sdonn q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
120988cbd795Sdonn 
121088cbd795Sdonn /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
121188cbd795Sdonn while(--nargs >= 0)
121288cbd795Sdonn 	{
121388cbd795Sdonn 	if(rpllist->rplxp)
121488cbd795Sdonn 		q = mkexpr(OPCOMMA, rpllist->rplxp, q);
121588cbd795Sdonn 	rp = rpllist->rplnextp;
121688cbd795Sdonn 	frexpr(rpllist->rplvp);
121788cbd795Sdonn 	free(rpllist);
121888cbd795Sdonn 	rpllist = rp;
121988cbd795Sdonn 	}
122088cbd795Sdonn 
122188cbd795Sdonn ret:
122288cbd795Sdonn 	frchain( &oactp );
122388cbd795Sdonn 	return(q);
122488cbd795Sdonn }
122588cbd795Sdonn 
122688cbd795Sdonn 
122788cbd795Sdonn 
122888cbd795Sdonn 
mkplace(np)122988cbd795Sdonn Addrp mkplace(np)
123088cbd795Sdonn register Namep np;
123188cbd795Sdonn {
123288cbd795Sdonn register Addrp s;
123388cbd795Sdonn register struct Rplblock *rp;
123488cbd795Sdonn int regn;
123588cbd795Sdonn 
123688cbd795Sdonn /* is name on the replace list? */
123788cbd795Sdonn 
123888cbd795Sdonn for(rp = rpllist ; rp ; rp = rp->rplnextp)
123988cbd795Sdonn 	{
124088cbd795Sdonn 	if(np == rp->rplnp)
124188cbd795Sdonn 		{
124288cbd795Sdonn 		if(rp->rpltag == TNAME)
124388cbd795Sdonn 			{
124488cbd795Sdonn 			np = (Namep) (rp->rplvp);
124588cbd795Sdonn 			break;
124688cbd795Sdonn 			}
124788cbd795Sdonn 		else	return( (Addrp) cpexpr(rp->rplvp) );
124888cbd795Sdonn 		}
124988cbd795Sdonn 	}
125088cbd795Sdonn 
125188cbd795Sdonn /* is variable a DO index in a register ? */
125288cbd795Sdonn 
125388cbd795Sdonn if(np->vdovar && ( (regn = inregister(np)) >= 0) )
125488cbd795Sdonn 	if(np->vtype == TYERROR)
125588cbd795Sdonn 		return( (Addrp) errnode() );
125688cbd795Sdonn 	else
125788cbd795Sdonn 		{
125888cbd795Sdonn 		s = ALLOC(Addrblock);
125988cbd795Sdonn 		s->tag = TADDR;
126088cbd795Sdonn 		s->vstg = STGREG;
126188cbd795Sdonn 		s->vtype = TYIREG;
126288cbd795Sdonn 		s->issaved = np->vsave;
126388cbd795Sdonn 		s->memno = regn;
126488cbd795Sdonn 		s->memoffset = ICON(0);
126588cbd795Sdonn 		return(s);
126688cbd795Sdonn 		}
126788cbd795Sdonn 
126888cbd795Sdonn vardcl(np);
126988cbd795Sdonn return(mkaddr(np));
127088cbd795Sdonn }
127188cbd795Sdonn 
127288cbd795Sdonn 
127388cbd795Sdonn 
127488cbd795Sdonn 
mklhs(p)127588cbd795Sdonn expptr mklhs(p)
127688cbd795Sdonn register struct Primblock *p;
127788cbd795Sdonn {
127888cbd795Sdonn expptr suboffset();
127988cbd795Sdonn register Addrp s;
128088cbd795Sdonn Namep np;
128188cbd795Sdonn 
128288cbd795Sdonn if(p->tag != TPRIM)
128388cbd795Sdonn 	return( (expptr) p );
128488cbd795Sdonn np = p->namep;
128588cbd795Sdonn 
128688cbd795Sdonn s = mkplace(np);
128788cbd795Sdonn if(s->tag!=TADDR || s->vstg==STGREG)
128888cbd795Sdonn 	{
128988cbd795Sdonn 	free( (charptr) p );
129088cbd795Sdonn 	return( (expptr) s );
129188cbd795Sdonn 	}
129288cbd795Sdonn 
129388cbd795Sdonn /* compute the address modified by subscripts */
129488cbd795Sdonn 
129588cbd795Sdonn s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
129688cbd795Sdonn frexpr(p->argsp);
129788cbd795Sdonn p->argsp = NULL;
129888cbd795Sdonn 
129988cbd795Sdonn /* now do substring part */
130088cbd795Sdonn 
130188cbd795Sdonn if(p->fcharp || p->lcharp)
130288cbd795Sdonn 	{
130388cbd795Sdonn 	if(np->vtype != TYCHAR)
130488cbd795Sdonn 		errstr("substring of noncharacter %s", varstr(VL,np->varname));
130588cbd795Sdonn 	else	{
130688cbd795Sdonn 		if(p->lcharp == NULL)
130788cbd795Sdonn 			p->lcharp = (expptr) cpexpr(s->vleng);
130888cbd795Sdonn 		frexpr(s->vleng);
130988cbd795Sdonn 		if(p->fcharp)
131088cbd795Sdonn 			{
131188cbd795Sdonn 			if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
131288cbd795Sdonn 			&& p->fcharp->primblock.namep == p->lcharp->primblock.namep)
131388cbd795Sdonn 				/* A trivial optimization -- upper == lower */
131488cbd795Sdonn 				s->vleng = ICON(1);
131588cbd795Sdonn 			else
131688cbd795Sdonn 				s->vleng = mkexpr(OPMINUS, p->lcharp,
131788cbd795Sdonn 					mkexpr(OPMINUS, p->fcharp, ICON(1) ));
131888cbd795Sdonn 			}
131988cbd795Sdonn 		else
132088cbd795Sdonn 			s->vleng = p->lcharp;
132188cbd795Sdonn 		}
132288cbd795Sdonn 	}
132388cbd795Sdonn 
132488cbd795Sdonn s->vleng = fixtype( s->vleng );
132588cbd795Sdonn s->memoffset = fixtype( s->memoffset );
132688cbd795Sdonn free( (charptr) p );
132788cbd795Sdonn return( (expptr) s );
132888cbd795Sdonn }
132988cbd795Sdonn 
133088cbd795Sdonn 
133188cbd795Sdonn 
133288cbd795Sdonn 
133388cbd795Sdonn 
deregister(np)133488cbd795Sdonn deregister(np)
133588cbd795Sdonn Namep np;
133688cbd795Sdonn {
133788cbd795Sdonn if(nregvar>0 && regnamep[nregvar-1]==np)
133888cbd795Sdonn 	{
133988cbd795Sdonn 	--nregvar;
134088cbd795Sdonn #if FAMILY == DMR
134188cbd795Sdonn 	putnreg();
134288cbd795Sdonn #endif
134388cbd795Sdonn 	}
134488cbd795Sdonn }
134588cbd795Sdonn 
134688cbd795Sdonn 
134788cbd795Sdonn 
134888cbd795Sdonn 
memversion(np)134988cbd795Sdonn Addrp memversion(np)
135088cbd795Sdonn register Namep np;
135188cbd795Sdonn {
135288cbd795Sdonn register Addrp s;
135388cbd795Sdonn 
135488cbd795Sdonn if(np->vdovar==NO || (inregister(np)<0) )
135588cbd795Sdonn 	return(NULL);
135688cbd795Sdonn np->vdovar = NO;
135788cbd795Sdonn s = mkplace(np);
135888cbd795Sdonn np->vdovar = YES;
135988cbd795Sdonn return(s);
136088cbd795Sdonn }
136188cbd795Sdonn 
136288cbd795Sdonn 
136388cbd795Sdonn 
inregister(np)136488cbd795Sdonn inregister(np)
136588cbd795Sdonn register Namep np;
136688cbd795Sdonn {
136788cbd795Sdonn register int i;
136888cbd795Sdonn 
136988cbd795Sdonn for(i = 0 ; i < nregvar ; ++i)
137088cbd795Sdonn 	if(regnamep[i] == np)
137188cbd795Sdonn 		return( regnum[i] );
137288cbd795Sdonn return(-1);
137388cbd795Sdonn }
137488cbd795Sdonn 
137588cbd795Sdonn 
137688cbd795Sdonn 
137788cbd795Sdonn 
enregister(np)137888cbd795Sdonn enregister(np)
137988cbd795Sdonn Namep np;
138088cbd795Sdonn {
138188cbd795Sdonn if( inregister(np) >= 0)
138288cbd795Sdonn 	return(YES);
138388cbd795Sdonn if(nregvar >= maxregvar)
138488cbd795Sdonn 	return(NO);
138588cbd795Sdonn vardcl(np);
138688cbd795Sdonn if( ONEOF(np->vtype, MSKIREG) )
138788cbd795Sdonn 	{
138888cbd795Sdonn 	regnamep[nregvar++] = np;
138988cbd795Sdonn 	if(nregvar > highregvar)
139088cbd795Sdonn 		highregvar = nregvar;
139188cbd795Sdonn #if FAMILY == DMR
139288cbd795Sdonn 	putnreg();
139388cbd795Sdonn #endif
139488cbd795Sdonn 	return(YES);
139588cbd795Sdonn 	}
139688cbd795Sdonn else
139788cbd795Sdonn 	return(NO);
139888cbd795Sdonn }
139988cbd795Sdonn 
140088cbd795Sdonn 
140188cbd795Sdonn 
140288cbd795Sdonn 
suboffset(p)140388cbd795Sdonn expptr suboffset(p)
140488cbd795Sdonn register struct Primblock *p;
140588cbd795Sdonn {
140688cbd795Sdonn int n;
140788cbd795Sdonn expptr size;
140888cbd795Sdonn expptr oftwo();
140988cbd795Sdonn chainp cp;
141088cbd795Sdonn expptr offp, prod;
141188cbd795Sdonn expptr subcheck();
141288cbd795Sdonn struct Dimblock *dimp;
141388cbd795Sdonn expptr sub[MAXDIM+1];
141488cbd795Sdonn register Namep np;
141588cbd795Sdonn 
141688cbd795Sdonn np = p->namep;
141788cbd795Sdonn offp = ICON(0);
141888cbd795Sdonn n = 0;
141988cbd795Sdonn if(p->argsp)
142088cbd795Sdonn 	for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
142188cbd795Sdonn 		{
142288cbd795Sdonn 		sub[n] = fixtype(cpexpr(cp->datap));
142388cbd795Sdonn 		if ( ! ISINT(sub[n]->headblock.vtype)) {
142488cbd795Sdonn 			errstr("%s: non-integer subscript expression",
142588cbd795Sdonn 				varstr(VL, np->varname) );
142688cbd795Sdonn 			/* Provide a substitute -- go on to find more errors */
142788cbd795Sdonn 			frexpr(sub[n]);
142888cbd795Sdonn 			sub[n] = ICON(1);
142988cbd795Sdonn 		}
143088cbd795Sdonn 		if(n > maxdim)
143188cbd795Sdonn 			{
143288cbd795Sdonn 			   char str[28+VL];
143388cbd795Sdonn 			   sprintf(str, "%s: more than %d subscripts",
143488cbd795Sdonn 				varstr(VL, np->varname), maxdim );
143588cbd795Sdonn 			   err( str );
143688cbd795Sdonn 			break;
143788cbd795Sdonn 			}
143888cbd795Sdonn 		}
143988cbd795Sdonn 
144088cbd795Sdonn dimp = np->vdim;
144188cbd795Sdonn if(n>0 && dimp==NULL)
144288cbd795Sdonn 	errstr("%s: subscripts on scalar variable",
144388cbd795Sdonn 		varstr(VL, np->varname), maxdim );
144488cbd795Sdonn else if(dimp && dimp->ndim!=n)
144588cbd795Sdonn 	errstr("wrong number of subscripts on %s",
144688cbd795Sdonn 		varstr(VL, np->varname) );
144788cbd795Sdonn else if(n > 0)
144888cbd795Sdonn 	{
144988cbd795Sdonn 	prod = sub[--n];
145088cbd795Sdonn 	while( --n >= 0)
145188cbd795Sdonn 		prod = mkexpr(OPPLUS, sub[n],
145288cbd795Sdonn 			mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
145388cbd795Sdonn #if TARGET == VAX || TARGET == TAHOE
145488cbd795Sdonn #ifdef SDB
145588cbd795Sdonn 	if(checksubs || np->vstg!=STGARG || sdbflag)
145688cbd795Sdonn #else
145788cbd795Sdonn 	if(checksubs || np->vstg!=STGARG)
145888cbd795Sdonn #endif
145988cbd795Sdonn 		prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146088cbd795Sdonn #else
146188cbd795Sdonn 	prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146288cbd795Sdonn #endif
146388cbd795Sdonn 	if(checksubs)
146488cbd795Sdonn 		prod = subcheck(np, prod);
146588cbd795Sdonn 	size = np->vtype == TYCHAR ?
146688cbd795Sdonn 		(expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
146788cbd795Sdonn 	if (!oftwo(size))
146888cbd795Sdonn 		prod = mkexpr(OPSTAR, prod, size);
146988cbd795Sdonn 	else
147088cbd795Sdonn 		prod = mkexpr(OPLSHIFT,prod,oftwo(size));
147188cbd795Sdonn 
147288cbd795Sdonn 	offp = mkexpr(OPPLUS, offp, prod);
147388cbd795Sdonn 	}
147488cbd795Sdonn 
147588cbd795Sdonn if(p->fcharp && np->vtype==TYCHAR)
147688cbd795Sdonn 	offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
147788cbd795Sdonn 
147888cbd795Sdonn return(offp);
147988cbd795Sdonn }
148088cbd795Sdonn 
148188cbd795Sdonn 
148288cbd795Sdonn 
148388cbd795Sdonn 
subcheck(np,p)148488cbd795Sdonn expptr subcheck(np, p)
148588cbd795Sdonn Namep np;
148688cbd795Sdonn register expptr p;
148788cbd795Sdonn {
148888cbd795Sdonn struct Dimblock *dimp;
148988cbd795Sdonn expptr t, checkvar, checkcond, badcall;
149088cbd795Sdonn 
149188cbd795Sdonn dimp = np->vdim;
149288cbd795Sdonn if(dimp->nelt == NULL)
149388cbd795Sdonn 	return(p);	/* don't check arrays with * bounds */
149488cbd795Sdonn checkvar = NULL;
149588cbd795Sdonn checkcond = NULL;
149688cbd795Sdonn if( ISICON(p) )
149788cbd795Sdonn 	{
149876ad5316Sbostic 	if(p->constblock.constant.ci < 0)
149988cbd795Sdonn 		goto badsub;
150088cbd795Sdonn 	if( ISICON(dimp->nelt) )
150176ad5316Sbostic 		if(p->constblock.constant.ci <
150276ad5316Sbostic 		    dimp->nelt->constblock.constant.ci)
150388cbd795Sdonn 			return(p);
150488cbd795Sdonn 		else
150588cbd795Sdonn 			goto badsub;
150688cbd795Sdonn 	}
150788cbd795Sdonn if(p->tag==TADDR && p->addrblock.vstg==STGREG)
150888cbd795Sdonn 	{
150988cbd795Sdonn 	checkvar = (expptr) cpexpr(p);
151088cbd795Sdonn 	t = p;
151188cbd795Sdonn 	}
151288cbd795Sdonn else	{
151388cbd795Sdonn 	checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
151488cbd795Sdonn 	t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
151588cbd795Sdonn 	}
151688cbd795Sdonn checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
151788cbd795Sdonn if( ! ISICON(p) )
151888cbd795Sdonn 	checkcond = mkexpr(OPAND, checkcond,
151988cbd795Sdonn 			mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
152088cbd795Sdonn 
152188cbd795Sdonn badcall = call4(p->headblock.vtype, "s_rnge",
152288cbd795Sdonn 		mkstrcon(VL, np->varname),
152388cbd795Sdonn 		mkconv(TYLONG,  cpexpr(checkvar)),
152488cbd795Sdonn 		mkstrcon(XL, procname),
152588cbd795Sdonn 		ICON(lineno) );
152688cbd795Sdonn badcall->exprblock.opcode = OPCCALL;
152788cbd795Sdonn p = mkexpr(OPQUEST, checkcond,
152888cbd795Sdonn 	mkexpr(OPCOLON, checkvar, badcall));
152988cbd795Sdonn 
153088cbd795Sdonn return(p);
153188cbd795Sdonn 
153288cbd795Sdonn badsub:
153388cbd795Sdonn 	frexpr(p);
153488cbd795Sdonn 	errstr("subscript on variable %s out of range", varstr(VL,np->varname));
153588cbd795Sdonn 	return ( ICON(0) );
153688cbd795Sdonn }
153788cbd795Sdonn 
153888cbd795Sdonn 
153988cbd795Sdonn 
154088cbd795Sdonn 
mkaddr(p)154188cbd795Sdonn Addrp mkaddr(p)
154288cbd795Sdonn register Namep p;
154388cbd795Sdonn {
154488cbd795Sdonn struct Extsym *extp;
154588cbd795Sdonn register Addrp t;
154688cbd795Sdonn Addrp intraddr();
154788cbd795Sdonn 
154888cbd795Sdonn switch( p->vstg)
154988cbd795Sdonn 	{
155088cbd795Sdonn 	case STGUNKNOWN:
155188cbd795Sdonn 		if(p->vclass != CLPROC)
155288cbd795Sdonn 			break;
155388cbd795Sdonn 		extp = mkext( varunder(VL, p->varname) );
155488cbd795Sdonn 		extp->extstg = STGEXT;
155588cbd795Sdonn 		p->vstg = STGEXT;
155688cbd795Sdonn 		p->vardesc.varno = extp - extsymtab;
155788cbd795Sdonn 		p->vprocclass = PEXTERNAL;
155888cbd795Sdonn 
155988cbd795Sdonn 	case STGCOMMON:
156088cbd795Sdonn 	case STGEXT:
156188cbd795Sdonn 	case STGBSS:
156288cbd795Sdonn 	case STGINIT:
156388cbd795Sdonn 	case STGEQUIV:
156488cbd795Sdonn 	case STGARG:
156588cbd795Sdonn 	case STGLENG:
156688cbd795Sdonn 	case STGAUTO:
156788cbd795Sdonn 		t = ALLOC(Addrblock);
156888cbd795Sdonn 		t->tag = TADDR;
156988cbd795Sdonn 		if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
157088cbd795Sdonn 			t->vclass = CLVAR;
157188cbd795Sdonn 		else
157288cbd795Sdonn 			t->vclass = p->vclass;
157388cbd795Sdonn 		t->vtype = p->vtype;
157488cbd795Sdonn 		t->vstg = p->vstg;
157588cbd795Sdonn 		t->memno = p->vardesc.varno;
157688cbd795Sdonn 		t->issaved = p->vsave;
157788cbd795Sdonn                 if(p->vdim) t->isarray = YES;
157888cbd795Sdonn 		t->memoffset = ICON(p->voffset);
157988cbd795Sdonn 		if(p->vleng)
158088cbd795Sdonn 			{
158188cbd795Sdonn 			t->vleng = (expptr) cpexpr(p->vleng);
158288cbd795Sdonn 			if( ISICON(t->vleng) )
158376ad5316Sbostic 				t->varleng = t->vleng->constblock.constant.ci;
158488cbd795Sdonn 			}
158588cbd795Sdonn 		if (p->vstg == STGBSS)
158688cbd795Sdonn 			t->varsize = p->varsize;
158788cbd795Sdonn 		else if (p->vstg == STGEQUIV)
158888cbd795Sdonn 			t->varsize = eqvclass[t->memno].eqvleng;
158988cbd795Sdonn 		return(t);
159088cbd795Sdonn 
159188cbd795Sdonn 	case STGINTR:
159288cbd795Sdonn 		return( intraddr(p) );
159388cbd795Sdonn 
159488cbd795Sdonn 	}
159588cbd795Sdonn /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
159688cbd795Sdonn badstg("mkaddr", p->vstg);
159788cbd795Sdonn /* NOTREACHED */
159888cbd795Sdonn }
159988cbd795Sdonn 
160088cbd795Sdonn 
160188cbd795Sdonn 
160288cbd795Sdonn 
mkarg(type,argno)160388cbd795Sdonn Addrp mkarg(type, argno)
160488cbd795Sdonn int type, argno;
160588cbd795Sdonn {
160688cbd795Sdonn register Addrp p;
160788cbd795Sdonn 
160888cbd795Sdonn p = ALLOC(Addrblock);
160988cbd795Sdonn p->tag = TADDR;
161088cbd795Sdonn p->vtype = type;
161188cbd795Sdonn p->vclass = CLVAR;
161288cbd795Sdonn p->vstg = (type==TYLENG ? STGLENG : STGARG);
161388cbd795Sdonn p->memno = argno;
161488cbd795Sdonn return(p);
161588cbd795Sdonn }
161688cbd795Sdonn 
161788cbd795Sdonn 
161888cbd795Sdonn 
161988cbd795Sdonn 
162088cbd795Sdonn expptr mkprim(v, args, substr)
162188cbd795Sdonn register union
162288cbd795Sdonn 	{
162388cbd795Sdonn 	struct Paramblock paramblock;
162488cbd795Sdonn 	struct Nameblock nameblock;
162588cbd795Sdonn 	struct Headblock headblock;
162688cbd795Sdonn 	} *v;
162788cbd795Sdonn struct Listblock *args;
162888cbd795Sdonn chainp substr;
162988cbd795Sdonn {
163088cbd795Sdonn register struct Primblock *p;
163188cbd795Sdonn 
163288cbd795Sdonn if(v->headblock.vclass == CLPARAM)
163388cbd795Sdonn 	{
163488cbd795Sdonn 	if(args || substr)
163588cbd795Sdonn 		{
163688cbd795Sdonn 		errstr("no qualifiers on parameter name %s",
163788cbd795Sdonn 			varstr(VL,v->paramblock.varname));
163888cbd795Sdonn 		frexpr(args);
163988cbd795Sdonn 		if(substr)
164088cbd795Sdonn 			{
164188cbd795Sdonn 			frexpr(substr->datap);
164288cbd795Sdonn 			frexpr(substr->nextp->datap);
164388cbd795Sdonn 			frchain(&substr);
164488cbd795Sdonn 			}
164588cbd795Sdonn 		frexpr(v);
164688cbd795Sdonn 		return( errnode() );
164788cbd795Sdonn 		}
164888cbd795Sdonn 	return( (expptr) cpexpr(v->paramblock.paramval) );
164988cbd795Sdonn 	}
165088cbd795Sdonn 
165188cbd795Sdonn p = ALLOC(Primblock);
165288cbd795Sdonn p->tag = TPRIM;
165388cbd795Sdonn p->vtype = v->nameblock.vtype;
165488cbd795Sdonn p->namep = (Namep) v;
165588cbd795Sdonn p->argsp = args;
165688cbd795Sdonn if(substr)
165788cbd795Sdonn 	{
165888cbd795Sdonn 	p->fcharp = (expptr) substr->datap;
16596b05b513Sdonn 	if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
166088cbd795Sdonn 		p->fcharp = mkconv(TYINT, p->fcharp);
166188cbd795Sdonn 	p->lcharp = (expptr) substr->nextp->datap;
16626b05b513Sdonn 	if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
166388cbd795Sdonn 		p->lcharp = mkconv(TYINT, p->lcharp);
166488cbd795Sdonn 	frchain(&substr);
166588cbd795Sdonn 	}
166688cbd795Sdonn return( (expptr) p);
166788cbd795Sdonn }
166888cbd795Sdonn 
166988cbd795Sdonn 
167088cbd795Sdonn 
vardcl(v)167188cbd795Sdonn vardcl(v)
167288cbd795Sdonn register Namep v;
167388cbd795Sdonn {
167488cbd795Sdonn int nelt;
167588cbd795Sdonn struct Dimblock *t;
167688cbd795Sdonn Addrp p;
167788cbd795Sdonn expptr neltp;
167888cbd795Sdonn int eltsize;
167988cbd795Sdonn int varsize;
168088cbd795Sdonn int tsize;
168188cbd795Sdonn int align;
168288cbd795Sdonn 
168388cbd795Sdonn if(v->vdcldone)
168488cbd795Sdonn 	return;
168588cbd795Sdonn if(v->vclass == CLNAMELIST)
168688cbd795Sdonn 	return;
168788cbd795Sdonn 
168888cbd795Sdonn if(v->vtype == TYUNKNOWN)
168988cbd795Sdonn 	impldcl(v);
169088cbd795Sdonn if(v->vclass == CLUNKNOWN)
169188cbd795Sdonn 	v->vclass = CLVAR;
169288cbd795Sdonn else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
169388cbd795Sdonn 	{
169488cbd795Sdonn 	dclerr("used both as variable and non-variable", v);
169588cbd795Sdonn 	return;
169688cbd795Sdonn 	}
169788cbd795Sdonn if(v->vstg==STGUNKNOWN)
169888cbd795Sdonn 	v->vstg = implstg[ letter(v->varname[0]) ];
169988cbd795Sdonn 
170088cbd795Sdonn switch(v->vstg)
170188cbd795Sdonn 	{
170288cbd795Sdonn 	case STGBSS:
170388cbd795Sdonn 		v->vardesc.varno = ++lastvarno;
170488cbd795Sdonn 		if (v->vclass != CLVAR)
170588cbd795Sdonn 			break;
170688cbd795Sdonn 		nelt = 1;
170788cbd795Sdonn 		t = v->vdim;
170888cbd795Sdonn 		if (t)
170988cbd795Sdonn 			{
171088cbd795Sdonn 			neltp = t->nelt;
171188cbd795Sdonn 			if (neltp && ISICON(neltp))
171276ad5316Sbostic 				nelt = neltp->constblock.constant.ci;
171388cbd795Sdonn 			else
171488cbd795Sdonn 				dclerr("improperly dimensioned array", v);
171588cbd795Sdonn 			}
171688cbd795Sdonn 
171788cbd795Sdonn 		if (v->vtype == TYCHAR)
171888cbd795Sdonn 			{
171988cbd795Sdonn 			v->vleng = fixtype(v->vleng);
172088cbd795Sdonn 			if (v->vleng == NULL)
172188cbd795Sdonn 				eltsize = typesize[TYCHAR];
172288cbd795Sdonn 			else if (ISICON(v->vleng))
172388cbd795Sdonn 				eltsize = typesize[TYCHAR] *
172476ad5316Sbostic 					v->vleng->constblock.constant.ci;
172588cbd795Sdonn 			else if (v->vleng->tag != TERROR)
172688cbd795Sdonn 				{
172788cbd795Sdonn 				errstr("nonconstant string length on %s",
172888cbd795Sdonn 					varstr(VL, v->varname));
172988cbd795Sdonn 				eltsize = 0;
173088cbd795Sdonn 				}
173188cbd795Sdonn 			}
173288cbd795Sdonn 		else
173388cbd795Sdonn 			eltsize = typesize[v->vtype];
173488cbd795Sdonn 
173588cbd795Sdonn 		v->varsize = nelt * eltsize;
173688cbd795Sdonn 		break;
173788cbd795Sdonn 	case STGAUTO:
173888cbd795Sdonn 		if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
173988cbd795Sdonn 			break;
174088cbd795Sdonn 		nelt = 1;
174188cbd795Sdonn 		if(t = v->vdim)
174288cbd795Sdonn 			if( (neltp = t->nelt) && ISCONST(neltp) )
174376ad5316Sbostic 				nelt = neltp->constblock.constant.ci;
174488cbd795Sdonn 			else
174588cbd795Sdonn 				dclerr("adjustable automatic array", v);
174688cbd795Sdonn 		p = autovar(nelt, v->vtype, v->vleng);
174788cbd795Sdonn 		v->vardesc.varno = p->memno;
174876ad5316Sbostic 		v->voffset = p->memoffset->constblock.constant.ci;
174988cbd795Sdonn 		frexpr(p);
175088cbd795Sdonn 		break;
175188cbd795Sdonn 
175288cbd795Sdonn 	default:
175388cbd795Sdonn 		break;
175488cbd795Sdonn 	}
175588cbd795Sdonn v->vdcldone = YES;
175688cbd795Sdonn }
175788cbd795Sdonn 
175888cbd795Sdonn 
175988cbd795Sdonn 
176088cbd795Sdonn 
impldcl(p)176188cbd795Sdonn impldcl(p)
176288cbd795Sdonn register Namep p;
176388cbd795Sdonn {
176488cbd795Sdonn register int k;
176588cbd795Sdonn int type, leng;
176688cbd795Sdonn 
176788cbd795Sdonn if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
176888cbd795Sdonn 	return;
176988cbd795Sdonn if(p->vtype == TYUNKNOWN)
177088cbd795Sdonn 	{
177188cbd795Sdonn 	k = letter(p->varname[0]);
177288cbd795Sdonn 	type = impltype[ k ];
177388cbd795Sdonn 	leng = implleng[ k ];
177488cbd795Sdonn 	if(type == TYUNKNOWN)
177588cbd795Sdonn 		{
177688cbd795Sdonn 		if(p->vclass == CLPROC)
177788cbd795Sdonn 			dclerr("attempt to use function of undefined type", p);
177888cbd795Sdonn 		else
177988cbd795Sdonn 			dclerr("attempt to use undefined variable", p);
178088cbd795Sdonn 		type = TYERROR;
178188cbd795Sdonn 		leng = 1;
178288cbd795Sdonn 		}
178388cbd795Sdonn 	settype(p, type, leng);
178488cbd795Sdonn 	}
178588cbd795Sdonn }
178688cbd795Sdonn 
178788cbd795Sdonn 
178888cbd795Sdonn 
178988cbd795Sdonn 
letter(c)179088cbd795Sdonn LOCAL letter(c)
179188cbd795Sdonn register int c;
179288cbd795Sdonn {
179388cbd795Sdonn if( isupper(c) )
179488cbd795Sdonn 	c = tolower(c);
179588cbd795Sdonn return(c - 'a');
179688cbd795Sdonn }
179788cbd795Sdonn 
179876ad5316Sbostic #define ICONEQ(z, c)  (ISICON(z) && z->constblock.constant.ci==c)
179988cbd795Sdonn #define COMMUTE	{ e = lp;  lp = rp;  rp = e; }
180088cbd795Sdonn 
180188cbd795Sdonn 
mkexpr(opcode,lp,rp)180288cbd795Sdonn expptr mkexpr(opcode, lp, rp)
180388cbd795Sdonn int opcode;
180488cbd795Sdonn register expptr lp, rp;
180588cbd795Sdonn {
180688cbd795Sdonn register expptr e, e1;
180788cbd795Sdonn int etype;
180888cbd795Sdonn int ltype, rtype;
180988cbd795Sdonn int ltag, rtag;
181088cbd795Sdonn expptr q, q1;
181188cbd795Sdonn expptr fold();
181288cbd795Sdonn int k;
181388cbd795Sdonn 
181488cbd795Sdonn ltype = lp->headblock.vtype;
181588cbd795Sdonn ltag = lp->tag;
181688cbd795Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL)
181788cbd795Sdonn 	{
181888cbd795Sdonn 	rtype = rp->headblock.vtype;
181988cbd795Sdonn 	rtag = rp->tag;
182088cbd795Sdonn 	}
182188cbd795Sdonn else	{
182288cbd795Sdonn 	rtype = 0;
182388cbd795Sdonn 	rtag = 0;
182488cbd795Sdonn 	}
182588cbd795Sdonn 
182688cbd795Sdonn /*
182788cbd795Sdonn  * Yuck.  Why can't we fold constants AFTER
182888cbd795Sdonn  * variables are implicitly declared???
182988cbd795Sdonn  */
183088cbd795Sdonn if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
183188cbd795Sdonn 	{
183288cbd795Sdonn 	k = letter(lp->primblock.namep->varname[0]);
183388cbd795Sdonn 	ltype = impltype[ k ];
183488cbd795Sdonn 	}
183588cbd795Sdonn if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
183688cbd795Sdonn 	{
183788cbd795Sdonn 	k = letter(rp->primblock.namep->varname[0]);
183888cbd795Sdonn 	rtype = impltype[ k ];
183988cbd795Sdonn 	}
184088cbd795Sdonn 
184188cbd795Sdonn etype = cktype(opcode, ltype, rtype);
184288cbd795Sdonn if(etype == TYERROR)
184388cbd795Sdonn 	goto error;
184488cbd795Sdonn 
184588cbd795Sdonn if(etype != TYUNKNOWN)
184688cbd795Sdonn switch(opcode)
184788cbd795Sdonn 	{
184888cbd795Sdonn 	/* check for multiplication by 0 and 1 and addition to 0 */
184988cbd795Sdonn 
185088cbd795Sdonn 	case OPSTAR:
185188cbd795Sdonn 		if( ISCONST(lp) )
185288cbd795Sdonn 			COMMUTE
185388cbd795Sdonn 
185488cbd795Sdonn 		if( ISICON(rp) )
185588cbd795Sdonn 			{
185676ad5316Sbostic 			if(rp->constblock.constant.ci == 0)
185788cbd795Sdonn 				{
185888cbd795Sdonn 				if(etype == TYUNKNOWN)
185988cbd795Sdonn 					break;
186088cbd795Sdonn 				rp = mkconv(etype, rp);
186188cbd795Sdonn 				goto retright;
186288cbd795Sdonn 				}
186388cbd795Sdonn 			if ((lp->tag == TEXPR) &&
186488cbd795Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
186588cbd795Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
186688cbd795Sdonn 			    ISCONST(lp->exprblock.rightp) &&
186788cbd795Sdonn 			    ISINT(lp->exprblock.rightp->constblock.vtype))
186888cbd795Sdonn 				{
186988cbd795Sdonn 				q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
187088cbd795Sdonn 					   cpexpr(rp));
187188cbd795Sdonn 				q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
187288cbd795Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
187388cbd795Sdonn 				free ((char *) lp);
187488cbd795Sdonn 				return q;
187588cbd795Sdonn 				}
187688cbd795Sdonn 			else
187788cbd795Sdonn 				goto mulop;
187888cbd795Sdonn 			}
187988cbd795Sdonn 		break;
188088cbd795Sdonn 
188188cbd795Sdonn 	case OPSLASH:
188288cbd795Sdonn 	case OPMOD:
188388cbd795Sdonn 		if( ICONEQ(rp, 0) )
188488cbd795Sdonn 			{
188588cbd795Sdonn 			err("attempted division by zero");
188688cbd795Sdonn 			rp = ICON(1);
188788cbd795Sdonn 			break;
188888cbd795Sdonn 			}
188988cbd795Sdonn 		if(opcode == OPMOD)
189088cbd795Sdonn 			break;
189188cbd795Sdonn 
189288cbd795Sdonn 
189388cbd795Sdonn 	mulop:
189488cbd795Sdonn 		if( ISICON(rp) )
189588cbd795Sdonn 			{
189676ad5316Sbostic 			if(rp->constblock.constant.ci == 1)
189788cbd795Sdonn 				goto retleft;
189888cbd795Sdonn 
189976ad5316Sbostic 			if(rp->constblock.constant.ci == -1)
190088cbd795Sdonn 				{
190188cbd795Sdonn 				frexpr(rp);
190288cbd795Sdonn 				return( mkexpr(OPNEG, lp, PNULL) );
190388cbd795Sdonn 				}
190488cbd795Sdonn 			}
190588cbd795Sdonn 
190688cbd795Sdonn 		if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
190788cbd795Sdonn 			{
190888cbd795Sdonn 			if(opcode == OPSTAR)
190988cbd795Sdonn 				e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
191088cbd795Sdonn 			else  if(ISICON(rp) &&
191176ad5316Sbostic 				(lp->exprblock.rightp->constblock.constant.ci %
191276ad5316Sbostic 					rp->constblock.constant.ci) == 0)
191388cbd795Sdonn 				e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
191488cbd795Sdonn 			else	break;
191588cbd795Sdonn 
191688cbd795Sdonn 			e1 = lp->exprblock.leftp;
191788cbd795Sdonn 			free( (charptr) lp );
191888cbd795Sdonn 			return( mkexpr(OPSTAR, e1, e) );
191988cbd795Sdonn 			}
192088cbd795Sdonn 		break;
192188cbd795Sdonn 
192288cbd795Sdonn 
192388cbd795Sdonn 	case OPPLUS:
192488cbd795Sdonn 		if( ISCONST(lp) )
192588cbd795Sdonn 			COMMUTE
192688cbd795Sdonn 		goto addop;
192788cbd795Sdonn 
192888cbd795Sdonn 	case OPMINUS:
192988cbd795Sdonn 		if( ICONEQ(lp, 0) )
193088cbd795Sdonn 			{
193188cbd795Sdonn 			frexpr(lp);
193288cbd795Sdonn 			return( mkexpr(OPNEG, rp, ENULL) );
193388cbd795Sdonn 			}
193488cbd795Sdonn 
193588cbd795Sdonn 		if( ISCONST(rp) )
193688cbd795Sdonn 			{
193788cbd795Sdonn 			opcode = OPPLUS;
193888cbd795Sdonn 			consnegop(rp);
193988cbd795Sdonn 			}
194088cbd795Sdonn 
194188cbd795Sdonn 	addop:
194288cbd795Sdonn 		if( ISICON(rp) )
194388cbd795Sdonn 			{
194476ad5316Sbostic 			if(rp->constblock.constant.ci == 0)
194588cbd795Sdonn 				goto retleft;
194688cbd795Sdonn 			if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
194788cbd795Sdonn 				{
194888cbd795Sdonn 				e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
194988cbd795Sdonn 				e1 = lp->exprblock.leftp;
195088cbd795Sdonn 				free( (charptr) lp );
195188cbd795Sdonn 				return( mkexpr(OPPLUS, e1, e) );
195288cbd795Sdonn 				}
195388cbd795Sdonn 			}
195488cbd795Sdonn 		break;
195588cbd795Sdonn 
195688cbd795Sdonn 
195788cbd795Sdonn 	case OPPOWER:
195888cbd795Sdonn 		break;
195988cbd795Sdonn 
196088cbd795Sdonn 	case OPNEG:
196188cbd795Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
196288cbd795Sdonn 			{
196388cbd795Sdonn 			e = lp->exprblock.leftp;
196488cbd795Sdonn 			free( (charptr) lp );
196588cbd795Sdonn 			return(e);
196688cbd795Sdonn 			}
196788cbd795Sdonn 		break;
196888cbd795Sdonn 
196988cbd795Sdonn 	case OPNOT:
197088cbd795Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
197188cbd795Sdonn 			{
197288cbd795Sdonn 			e = lp->exprblock.leftp;
197388cbd795Sdonn 			free( (charptr) lp );
197488cbd795Sdonn 			return(e);
197588cbd795Sdonn 			}
197688cbd795Sdonn 		break;
197788cbd795Sdonn 
197888cbd795Sdonn 	case OPCALL:
197988cbd795Sdonn 	case OPCCALL:
198088cbd795Sdonn 		etype = ltype;
198188cbd795Sdonn 		if(rp!=NULL && rp->listblock.listp==NULL)
198288cbd795Sdonn 			{
198388cbd795Sdonn 			free( (charptr) rp );
198488cbd795Sdonn 			rp = NULL;
198588cbd795Sdonn 			}
198688cbd795Sdonn 		break;
198788cbd795Sdonn 
198888cbd795Sdonn 	case OPAND:
198988cbd795Sdonn 	case OPOR:
199088cbd795Sdonn 		if( ISCONST(lp) )
199188cbd795Sdonn 			COMMUTE
199288cbd795Sdonn 
199388cbd795Sdonn 		if( ISCONST(rp) )
199488cbd795Sdonn 			{
199576ad5316Sbostic 			if(rp->constblock.constant.ci == 0)
199688cbd795Sdonn 				if(opcode == OPOR)
199788cbd795Sdonn 					goto retleft;
199888cbd795Sdonn 				else
199988cbd795Sdonn 					goto retright;
200088cbd795Sdonn 			else if(opcode == OPOR)
200188cbd795Sdonn 				goto retright;
200288cbd795Sdonn 			else
200388cbd795Sdonn 				goto retleft;
200488cbd795Sdonn 			}
200588cbd795Sdonn 	case OPLSHIFT:
200688cbd795Sdonn 		if (ISICON(rp))
200788cbd795Sdonn 			{
200876ad5316Sbostic 			if (rp->constblock.constant.ci == 0)
200988cbd795Sdonn 				goto retleft;
201088cbd795Sdonn 			if ((lp->tag == TEXPR) &&
201188cbd795Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
201288cbd795Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
201388cbd795Sdonn 			    ISICON(lp->exprblock.rightp))
201488cbd795Sdonn 				{
201588cbd795Sdonn 				q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
201688cbd795Sdonn 					cpexpr(rp));
201788cbd795Sdonn 				q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
201888cbd795Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
201988cbd795Sdonn 				free((char *) lp);
202088cbd795Sdonn 				return q;
202188cbd795Sdonn 				}
202288cbd795Sdonn 			}
202388cbd795Sdonn 
202488cbd795Sdonn 	case OPEQV:
202588cbd795Sdonn 	case OPNEQV:
202688cbd795Sdonn 
202788cbd795Sdonn 	case OPBITAND:
202888cbd795Sdonn 	case OPBITOR:
202988cbd795Sdonn 	case OPBITXOR:
203088cbd795Sdonn 	case OPBITNOT:
203188cbd795Sdonn 	case OPRSHIFT:
203288cbd795Sdonn 
203388cbd795Sdonn 	case OPLT:
203488cbd795Sdonn 	case OPGT:
203588cbd795Sdonn 	case OPLE:
203688cbd795Sdonn 	case OPGE:
203788cbd795Sdonn 	case OPEQ:
203888cbd795Sdonn 	case OPNE:
203988cbd795Sdonn 
204088cbd795Sdonn 	case OPCONCAT:
204188cbd795Sdonn 		break;
204288cbd795Sdonn 	case OPMIN:
204388cbd795Sdonn 	case OPMAX:
204488cbd795Sdonn 
204588cbd795Sdonn 	case OPASSIGN:
204688cbd795Sdonn 	case OPPLUSEQ:
204788cbd795Sdonn 	case OPSTAREQ:
204888cbd795Sdonn 
204988cbd795Sdonn 	case OPCONV:
205088cbd795Sdonn 	case OPADDR:
205188cbd795Sdonn 
205288cbd795Sdonn 	case OPCOMMA:
205388cbd795Sdonn 	case OPQUEST:
205488cbd795Sdonn 	case OPCOLON:
205588cbd795Sdonn 
205688cbd795Sdonn 	case OPPAREN:
205788cbd795Sdonn 		break;
205888cbd795Sdonn 
205988cbd795Sdonn 	default:
206088cbd795Sdonn 		badop("mkexpr", opcode);
206188cbd795Sdonn 	}
206288cbd795Sdonn 
206388cbd795Sdonn e = (expptr) ALLOC(Exprblock);
206488cbd795Sdonn e->exprblock.tag = TEXPR;
206588cbd795Sdonn e->exprblock.opcode = opcode;
206688cbd795Sdonn e->exprblock.vtype = etype;
206788cbd795Sdonn e->exprblock.leftp = lp;
206888cbd795Sdonn e->exprblock.rightp = rp;
206988cbd795Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) )
207088cbd795Sdonn 	e = fold(e);
207188cbd795Sdonn return(e);
207288cbd795Sdonn 
207388cbd795Sdonn retleft:
207488cbd795Sdonn 	frexpr(rp);
207588cbd795Sdonn 	return(lp);
207688cbd795Sdonn 
207788cbd795Sdonn retright:
207888cbd795Sdonn 	frexpr(lp);
207988cbd795Sdonn 	return(rp);
208088cbd795Sdonn 
208188cbd795Sdonn error:
208288cbd795Sdonn 	frexpr(lp);
208388cbd795Sdonn 	if(rp && opcode!=OPCALL && opcode!=OPCCALL)
208488cbd795Sdonn 		frexpr(rp);
208588cbd795Sdonn 	return( errnode() );
208688cbd795Sdonn }
208788cbd795Sdonn 
208888cbd795Sdonn #define ERR(s)   { errs = s; goto error; }
208988cbd795Sdonn 
cktype(op,lt,rt)209088cbd795Sdonn cktype(op, lt, rt)
209188cbd795Sdonn register int op, lt, rt;
209288cbd795Sdonn {
209388cbd795Sdonn char *errs;
209488cbd795Sdonn 
209588cbd795Sdonn if(lt==TYERROR || rt==TYERROR)
209688cbd795Sdonn 	goto error1;
209788cbd795Sdonn 
209888cbd795Sdonn if(lt==TYUNKNOWN)
209988cbd795Sdonn 	return(TYUNKNOWN);
210088cbd795Sdonn if(rt==TYUNKNOWN)
210188cbd795Sdonn 	if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
210288cbd795Sdonn 	    op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
210388cbd795Sdonn 		return(TYUNKNOWN);
210488cbd795Sdonn 
210588cbd795Sdonn switch(op)
210688cbd795Sdonn 	{
210788cbd795Sdonn 	case OPPLUS:
210888cbd795Sdonn 	case OPMINUS:
210988cbd795Sdonn 	case OPSTAR:
211088cbd795Sdonn 	case OPSLASH:
211188cbd795Sdonn 	case OPPOWER:
211288cbd795Sdonn 	case OPMOD:
211388cbd795Sdonn 		if( ISNUMERIC(lt) && ISNUMERIC(rt) )
211488cbd795Sdonn 			return( maxtype(lt, rt) );
211588cbd795Sdonn 		ERR("nonarithmetic operand of arithmetic operator")
211688cbd795Sdonn 
211788cbd795Sdonn 	case OPNEG:
211888cbd795Sdonn 		if( ISNUMERIC(lt) )
211988cbd795Sdonn 			return(lt);
212088cbd795Sdonn 		ERR("nonarithmetic operand of negation")
212188cbd795Sdonn 
212288cbd795Sdonn 	case OPNOT:
212388cbd795Sdonn 		if(lt == TYLOGICAL)
212488cbd795Sdonn 			return(TYLOGICAL);
212588cbd795Sdonn 		ERR("NOT of nonlogical")
212688cbd795Sdonn 
212788cbd795Sdonn 	case OPAND:
212888cbd795Sdonn 	case OPOR:
212988cbd795Sdonn 	case OPEQV:
213088cbd795Sdonn 	case OPNEQV:
213188cbd795Sdonn 		if(lt==TYLOGICAL && rt==TYLOGICAL)
213288cbd795Sdonn 			return(TYLOGICAL);
213388cbd795Sdonn 		ERR("nonlogical operand of logical operator")
213488cbd795Sdonn 
213588cbd795Sdonn 	case OPLT:
213688cbd795Sdonn 	case OPGT:
213788cbd795Sdonn 	case OPLE:
213888cbd795Sdonn 	case OPGE:
213988cbd795Sdonn 	case OPEQ:
214088cbd795Sdonn 	case OPNE:
214188cbd795Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
214288cbd795Sdonn 			{
214388cbd795Sdonn 			if(lt != rt)
214488cbd795Sdonn 				ERR("illegal comparison")
214588cbd795Sdonn 			}
214688cbd795Sdonn 
214788cbd795Sdonn 		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
214888cbd795Sdonn 			{
214988cbd795Sdonn 			if(op!=OPEQ && op!=OPNE)
215088cbd795Sdonn 				ERR("order comparison of complex data")
215188cbd795Sdonn 			}
215288cbd795Sdonn 
215388cbd795Sdonn 		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
215488cbd795Sdonn 			ERR("comparison of nonarithmetic data")
215588cbd795Sdonn 		return(TYLOGICAL);
215688cbd795Sdonn 
215788cbd795Sdonn 	case OPCONCAT:
215888cbd795Sdonn 		if(lt==TYCHAR && rt==TYCHAR)
215988cbd795Sdonn 			return(TYCHAR);
216088cbd795Sdonn 		ERR("concatenation of nonchar data")
216188cbd795Sdonn 
216288cbd795Sdonn 	case OPCALL:
216388cbd795Sdonn 	case OPCCALL:
216488cbd795Sdonn 		return(lt);
216588cbd795Sdonn 
216688cbd795Sdonn 	case OPADDR:
216788cbd795Sdonn 		return(TYADDR);
216888cbd795Sdonn 
216988cbd795Sdonn 	case OPCONV:
217088cbd795Sdonn 		if(ISCOMPLEX(lt))
217188cbd795Sdonn 			{
217288cbd795Sdonn 			if(ISNUMERIC(rt))
217388cbd795Sdonn 				return(lt);
217488cbd795Sdonn 			ERR("impossible conversion")
217588cbd795Sdonn 			}
217688cbd795Sdonn 		if(rt == 0)
217788cbd795Sdonn 			return(0);
217888cbd795Sdonn 		if(lt==TYCHAR && ISINT(rt) )
217988cbd795Sdonn 			return(TYCHAR);
218088cbd795Sdonn 	case OPASSIGN:
218188cbd795Sdonn 	case OPPLUSEQ:
218288cbd795Sdonn 	case OPSTAREQ:
218388cbd795Sdonn 		if( ISINT(lt) && rt==TYCHAR)
218488cbd795Sdonn 			return(lt);
218588cbd795Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
218688cbd795Sdonn 			if(op!=OPASSIGN || lt!=rt)
218788cbd795Sdonn 				{
218888cbd795Sdonn /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
218988cbd795Sdonn /* debug fatal("impossible conversion.  possible compiler bug"); */
219088cbd795Sdonn 				ERR("impossible conversion")
219188cbd795Sdonn 				}
219288cbd795Sdonn 		return(lt);
219388cbd795Sdonn 
219488cbd795Sdonn 	case OPMIN:
219588cbd795Sdonn 	case OPMAX:
219688cbd795Sdonn 	case OPBITOR:
219788cbd795Sdonn 	case OPBITAND:
219888cbd795Sdonn 	case OPBITXOR:
219988cbd795Sdonn 	case OPBITNOT:
220088cbd795Sdonn 	case OPLSHIFT:
220188cbd795Sdonn 	case OPRSHIFT:
220288cbd795Sdonn 	case OPPAREN:
220388cbd795Sdonn 		return(lt);
220488cbd795Sdonn 
220588cbd795Sdonn 	case OPCOMMA:
220688cbd795Sdonn 	case OPQUEST:
220788cbd795Sdonn 	case OPCOLON:
220888cbd795Sdonn 		return(rt);
220988cbd795Sdonn 
221088cbd795Sdonn 	default:
221188cbd795Sdonn 		badop("cktype", op);
221288cbd795Sdonn 	}
221388cbd795Sdonn error:	err(errs);
221488cbd795Sdonn error1:	return(TYERROR);
221588cbd795Sdonn }
221688cbd795Sdonn 
fold(e)221788cbd795Sdonn LOCAL expptr fold(e)
221888cbd795Sdonn register expptr e;
221988cbd795Sdonn {
222088cbd795Sdonn Constp p;
222188cbd795Sdonn register expptr lp, rp;
222288cbd795Sdonn int etype, mtype, ltype, rtype, opcode;
222388cbd795Sdonn int i, ll, lr;
222488cbd795Sdonn char *q, *s;
222588cbd795Sdonn union Constant lcon, rcon;
222688cbd795Sdonn 
222788cbd795Sdonn opcode = e->exprblock.opcode;
222888cbd795Sdonn etype = e->exprblock.vtype;
222988cbd795Sdonn 
223088cbd795Sdonn lp = e->exprblock.leftp;
223188cbd795Sdonn ltype = lp->headblock.vtype;
223288cbd795Sdonn rp = e->exprblock.rightp;
223388cbd795Sdonn 
223488cbd795Sdonn if(rp == 0)
223588cbd795Sdonn 	switch(opcode)
223688cbd795Sdonn 		{
223788cbd795Sdonn 		case OPNOT:
223876ad5316Sbostic 			lp->constblock.constant.ci =
223976ad5316Sbostic 			    ! lp->constblock.constant.ci;
224088cbd795Sdonn 			return(lp);
224188cbd795Sdonn 
224288cbd795Sdonn 		case OPBITNOT:
224376ad5316Sbostic 			lp->constblock.constant.ci =
224476ad5316Sbostic 			    ~ lp->constblock.constant.ci;
224588cbd795Sdonn 			return(lp);
224688cbd795Sdonn 
224788cbd795Sdonn 		case OPNEG:
224888cbd795Sdonn 			consnegop(lp);
224988cbd795Sdonn 			return(lp);
225088cbd795Sdonn 
225188cbd795Sdonn 		case OPCONV:
225288cbd795Sdonn 		case OPADDR:
225388cbd795Sdonn 		case OPPAREN:
225488cbd795Sdonn 			return(e);
225588cbd795Sdonn 
225688cbd795Sdonn 		default:
225788cbd795Sdonn 			badop("fold", opcode);
225888cbd795Sdonn 		}
225988cbd795Sdonn 
226088cbd795Sdonn rtype = rp->headblock.vtype;
226188cbd795Sdonn 
226288cbd795Sdonn p = ALLOC(Constblock);
226388cbd795Sdonn p->tag = TCONST;
226488cbd795Sdonn p->vtype = etype;
226588cbd795Sdonn p->vleng = e->exprblock.vleng;
226688cbd795Sdonn 
226788cbd795Sdonn switch(opcode)
226888cbd795Sdonn 	{
226988cbd795Sdonn 	case OPCOMMA:
227088cbd795Sdonn 	case OPQUEST:
227188cbd795Sdonn 	case OPCOLON:
227288cbd795Sdonn 		return(e);
227388cbd795Sdonn 
227488cbd795Sdonn 	case OPAND:
227576ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci &&
227676ad5316Sbostic 				rp->constblock.constant.ci;
227788cbd795Sdonn 		break;
227888cbd795Sdonn 
227988cbd795Sdonn 	case OPOR:
228076ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci ||
228176ad5316Sbostic 				rp->constblock.constant.ci;
228288cbd795Sdonn 		break;
228388cbd795Sdonn 
228488cbd795Sdonn 	case OPEQV:
228576ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci ==
228676ad5316Sbostic 				rp->constblock.constant.ci;
228788cbd795Sdonn 		break;
228888cbd795Sdonn 
228988cbd795Sdonn 	case OPNEQV:
229076ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci !=
229176ad5316Sbostic 				rp->constblock.constant.ci;
229288cbd795Sdonn 		break;
229388cbd795Sdonn 
229488cbd795Sdonn 	case OPBITAND:
229576ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci &
229676ad5316Sbostic 				rp->constblock.constant.ci;
229788cbd795Sdonn 		break;
229888cbd795Sdonn 
229988cbd795Sdonn 	case OPBITOR:
230076ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci |
230176ad5316Sbostic 				rp->constblock.constant.ci;
230288cbd795Sdonn 		break;
230388cbd795Sdonn 
230488cbd795Sdonn 	case OPBITXOR:
230576ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci ^
230676ad5316Sbostic 				rp->constblock.constant.ci;
230788cbd795Sdonn 		break;
230888cbd795Sdonn 
230988cbd795Sdonn 	case OPLSHIFT:
231076ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci <<
231176ad5316Sbostic 				rp->constblock.constant.ci;
231288cbd795Sdonn 		break;
231388cbd795Sdonn 
231488cbd795Sdonn 	case OPRSHIFT:
231576ad5316Sbostic 		p->constant.ci = lp->constblock.constant.ci >>
231676ad5316Sbostic 				rp->constblock.constant.ci;
231788cbd795Sdonn 		break;
231888cbd795Sdonn 
231988cbd795Sdonn 	case OPCONCAT:
232076ad5316Sbostic 		ll = lp->constblock.vleng->constblock.constant.ci;
232176ad5316Sbostic 		lr = rp->constblock.vleng->constblock.constant.ci;
232276ad5316Sbostic 		p->constant.ccp = q = (char *) ckalloc(ll+lr);
232388cbd795Sdonn 		p->vleng = ICON(ll+lr);
232476ad5316Sbostic 		s = lp->constblock.constant.ccp;
232588cbd795Sdonn 		for(i = 0 ; i < ll ; ++i)
232688cbd795Sdonn 			*q++ = *s++;
232776ad5316Sbostic 		s = rp->constblock.constant.ccp;
232888cbd795Sdonn 		for(i = 0; i < lr; ++i)
232988cbd795Sdonn 			*q++ = *s++;
233088cbd795Sdonn 		break;
233188cbd795Sdonn 
233288cbd795Sdonn 
233388cbd795Sdonn 	case OPPOWER:
233488cbd795Sdonn 		if( ! ISINT(rtype) )
233588cbd795Sdonn 			return(e);
233676ad5316Sbostic 		conspower(&(p->constant), lp, rp->constblock.constant.ci);
233788cbd795Sdonn 		break;
233888cbd795Sdonn 
233988cbd795Sdonn 
234088cbd795Sdonn 	default:
234188cbd795Sdonn 		if(ltype == TYCHAR)
234288cbd795Sdonn 			{
234376ad5316Sbostic 			lcon.ci = cmpstr(lp->constblock.constant.ccp,
234476ad5316Sbostic 				rp->constblock.constant.ccp,
234576ad5316Sbostic 				lp->constblock.vleng->constblock.constant.ci,
234676ad5316Sbostic 				rp->constblock.vleng->constblock.constant.ci);
234788cbd795Sdonn 			rcon.ci = 0;
234888cbd795Sdonn 			mtype = tyint;
234988cbd795Sdonn 			}
235088cbd795Sdonn 		else	{
235188cbd795Sdonn 			mtype = maxtype(ltype, rtype);
235276ad5316Sbostic 			consconv(mtype, &lcon, ltype,
235376ad5316Sbostic 				&(lp->constblock.constant) );
235476ad5316Sbostic 			consconv(mtype, &rcon, rtype,
235576ad5316Sbostic 				&(rp->constblock.constant) );
235688cbd795Sdonn 			}
235776ad5316Sbostic 		consbinop(opcode, mtype, &(p->constant), &lcon, &rcon);
235888cbd795Sdonn 		break;
235988cbd795Sdonn 	}
236088cbd795Sdonn 
236188cbd795Sdonn frexpr(e);
236288cbd795Sdonn return( (expptr) p );
236388cbd795Sdonn }
236488cbd795Sdonn 
236588cbd795Sdonn 
236688cbd795Sdonn 
236788cbd795Sdonn /* assign constant l = r , doing coercion */
236888cbd795Sdonn 
consconv(lt,lv,rt,rv)236988cbd795Sdonn consconv(lt, lv, rt, rv)
237088cbd795Sdonn int lt, rt;
237188cbd795Sdonn register union Constant *lv, *rv;
237288cbd795Sdonn {
237388cbd795Sdonn switch(lt)
237488cbd795Sdonn 	{
237588cbd795Sdonn 	case TYCHAR:
237688cbd795Sdonn 		*(lv->ccp = (char *) ckalloc(1)) = rv->ci;
237788cbd795Sdonn 		break;
237888cbd795Sdonn 
237988cbd795Sdonn 	case TYSHORT:
238088cbd795Sdonn 	case TYLONG:
238188cbd795Sdonn 		if(rt == TYCHAR)
238288cbd795Sdonn 			lv->ci = rv->ccp[0];
238388cbd795Sdonn 		else if( ISINT(rt) )
238488cbd795Sdonn 			lv->ci = rv->ci;
238588cbd795Sdonn 		else	lv->ci = rv->cd[0];
238688cbd795Sdonn 		break;
238788cbd795Sdonn 
238888cbd795Sdonn 	case TYCOMPLEX:
238988cbd795Sdonn 	case TYDCOMPLEX:
239088cbd795Sdonn 		switch(rt)
239188cbd795Sdonn 			{
239288cbd795Sdonn 			case TYSHORT:
239388cbd795Sdonn 			case TYLONG:
239488cbd795Sdonn 				/* fall through and do real assignment of
239588cbd795Sdonn 				   first element
239688cbd795Sdonn 				*/
239788cbd795Sdonn 			case TYREAL:
239888cbd795Sdonn 			case TYDREAL:
239988cbd795Sdonn 				lv->cd[1] = 0; break;
240088cbd795Sdonn 			case TYCOMPLEX:
240188cbd795Sdonn 			case TYDCOMPLEX:
240288cbd795Sdonn 				lv->cd[1] = rv->cd[1]; break;
240388cbd795Sdonn 			}
240488cbd795Sdonn 
240588cbd795Sdonn 	case TYREAL:
240688cbd795Sdonn 	case TYDREAL:
240788cbd795Sdonn 		if( ISINT(rt) )
240888cbd795Sdonn 			lv->cd[0] = rv->ci;
240988cbd795Sdonn 		else	lv->cd[0] = rv->cd[0];
241088cbd795Sdonn 		if( lt == TYREAL)
241188cbd795Sdonn 			{
241288cbd795Sdonn 			float f = lv->cd[0];
241388cbd795Sdonn 			lv->cd[0] = f;
241488cbd795Sdonn 			}
241588cbd795Sdonn 		break;
241688cbd795Sdonn 
241788cbd795Sdonn 	case TYLOGICAL:
241888cbd795Sdonn 		lv->ci = rv->ci;
241988cbd795Sdonn 		break;
242088cbd795Sdonn 	}
242188cbd795Sdonn }
242288cbd795Sdonn 
242388cbd795Sdonn 
242488cbd795Sdonn 
consnegop(p)242588cbd795Sdonn consnegop(p)
242688cbd795Sdonn register Constp p;
242788cbd795Sdonn {
242888cbd795Sdonn switch(p->vtype)
242988cbd795Sdonn 	{
243088cbd795Sdonn 	case TYSHORT:
243188cbd795Sdonn 	case TYLONG:
243276ad5316Sbostic 		p->constant.ci = - p->constant.ci;
243388cbd795Sdonn 		break;
243488cbd795Sdonn 
243588cbd795Sdonn 	case TYCOMPLEX:
243688cbd795Sdonn 	case TYDCOMPLEX:
243776ad5316Sbostic 		p->constant.cd[1] = - p->constant.cd[1];
243888cbd795Sdonn 		/* fall through and do the real parts */
243988cbd795Sdonn 	case TYREAL:
244088cbd795Sdonn 	case TYDREAL:
244176ad5316Sbostic 		p->constant.cd[0] = - p->constant.cd[0];
244288cbd795Sdonn 		break;
244388cbd795Sdonn 	default:
244488cbd795Sdonn 		badtype("consnegop", p->vtype);
244588cbd795Sdonn 	}
244688cbd795Sdonn }
244788cbd795Sdonn 
244888cbd795Sdonn 
244988cbd795Sdonn 
conspower(powp,ap,n)245088cbd795Sdonn LOCAL conspower(powp, ap, n)
245188cbd795Sdonn register union Constant *powp;
245288cbd795Sdonn Constp ap;
245388cbd795Sdonn ftnint n;
245488cbd795Sdonn {
245588cbd795Sdonn register int type;
245688cbd795Sdonn union Constant x;
245788cbd795Sdonn 
245888cbd795Sdonn switch(type = ap->vtype)	/* pow = 1 */
245988cbd795Sdonn 	{
246088cbd795Sdonn 	case TYSHORT:
246188cbd795Sdonn 	case TYLONG:
246288cbd795Sdonn 		powp->ci = 1;
246388cbd795Sdonn 		break;
246488cbd795Sdonn 	case TYCOMPLEX:
246588cbd795Sdonn 	case TYDCOMPLEX:
246688cbd795Sdonn 		powp->cd[1] = 0;
246788cbd795Sdonn 	case TYREAL:
246888cbd795Sdonn 	case TYDREAL:
246988cbd795Sdonn 		powp->cd[0] = 1;
247088cbd795Sdonn 		break;
247188cbd795Sdonn 	default:
247288cbd795Sdonn 		badtype("conspower", type);
247388cbd795Sdonn 	}
247488cbd795Sdonn 
247588cbd795Sdonn if(n == 0)
247688cbd795Sdonn 	return;
247788cbd795Sdonn if(n < 0)
247888cbd795Sdonn 	{
247988cbd795Sdonn 	if( ISINT(type) )
248088cbd795Sdonn 		{
248176ad5316Sbostic 		if (ap->constant.ci == 0)
248288cbd795Sdonn 			err("zero raised to a negative power");
248376ad5316Sbostic 		else if (ap->constant.ci == 1)
248488cbd795Sdonn 			return;
248576ad5316Sbostic 		else if (ap->constant.ci == -1)
248688cbd795Sdonn 			{
248788cbd795Sdonn 			if (n < -2)
248888cbd795Sdonn 				n = n + 2;
248988cbd795Sdonn 			n = -n;
249088cbd795Sdonn 			if (n % 2 == 1)
249188cbd795Sdonn 				powp->ci = -1;
249288cbd795Sdonn 			}
249388cbd795Sdonn 		else
249488cbd795Sdonn 			powp->ci = 0;
249588cbd795Sdonn 		return;
249688cbd795Sdonn 		}
249788cbd795Sdonn 	n = - n;
249876ad5316Sbostic 	consbinop(OPSLASH, type, &x, powp, &(ap->constant));
249988cbd795Sdonn 	}
250088cbd795Sdonn else
250176ad5316Sbostic 	consbinop(OPSTAR, type, &x, powp, &(ap->constant));
250288cbd795Sdonn 
250388cbd795Sdonn for( ; ; )
250488cbd795Sdonn 	{
250588cbd795Sdonn 	if(n & 01)
250688cbd795Sdonn 		consbinop(OPSTAR, type, powp, powp, &x);
250788cbd795Sdonn 	if(n >>= 1)
250888cbd795Sdonn 		consbinop(OPSTAR, type, &x, &x, &x);
250988cbd795Sdonn 	else
251088cbd795Sdonn 		break;
251188cbd795Sdonn 	}
251288cbd795Sdonn }
251388cbd795Sdonn 
251488cbd795Sdonn 
251588cbd795Sdonn 
251688cbd795Sdonn /* do constant operation cp = a op b */
251788cbd795Sdonn 
251888cbd795Sdonn 
consbinop(opcode,type,cp,ap,bp)251988cbd795Sdonn LOCAL consbinop(opcode, type, cp, ap, bp)
252088cbd795Sdonn int opcode, type;
252188cbd795Sdonn register union Constant *ap, *bp, *cp;
252288cbd795Sdonn {
252388cbd795Sdonn int k;
252488cbd795Sdonn double temp;
252588cbd795Sdonn 
252688cbd795Sdonn switch(opcode)
252788cbd795Sdonn 	{
252888cbd795Sdonn 	case OPPLUS:
252988cbd795Sdonn 		switch(type)
253088cbd795Sdonn 			{
253188cbd795Sdonn 			case TYSHORT:
253288cbd795Sdonn 			case TYLONG:
253388cbd795Sdonn 				cp->ci = ap->ci + bp->ci;
253488cbd795Sdonn 				break;
253588cbd795Sdonn 			case TYCOMPLEX:
253688cbd795Sdonn 			case TYDCOMPLEX:
253788cbd795Sdonn 				cp->cd[1] = ap->cd[1] + bp->cd[1];
253888cbd795Sdonn 			case TYREAL:
253988cbd795Sdonn 			case TYDREAL:
254088cbd795Sdonn 				cp->cd[0] = ap->cd[0] + bp->cd[0];
254188cbd795Sdonn 				break;
254288cbd795Sdonn 			}
254388cbd795Sdonn 		break;
254488cbd795Sdonn 
254588cbd795Sdonn 	case OPMINUS:
254688cbd795Sdonn 		switch(type)
254788cbd795Sdonn 			{
254888cbd795Sdonn 			case TYSHORT:
254988cbd795Sdonn 			case TYLONG:
255088cbd795Sdonn 				cp->ci = ap->ci - bp->ci;
255188cbd795Sdonn 				break;
255288cbd795Sdonn 			case TYCOMPLEX:
255388cbd795Sdonn 			case TYDCOMPLEX:
255488cbd795Sdonn 				cp->cd[1] = ap->cd[1] - bp->cd[1];
255588cbd795Sdonn 			case TYREAL:
255688cbd795Sdonn 			case TYDREAL:
255788cbd795Sdonn 				cp->cd[0] = ap->cd[0] - bp->cd[0];
255888cbd795Sdonn 				break;
255988cbd795Sdonn 			}
256088cbd795Sdonn 		break;
256188cbd795Sdonn 
256288cbd795Sdonn 	case OPSTAR:
256388cbd795Sdonn 		switch(type)
256488cbd795Sdonn 			{
256588cbd795Sdonn 			case TYSHORT:
256688cbd795Sdonn 			case TYLONG:
256788cbd795Sdonn 				cp->ci = ap->ci * bp->ci;
256888cbd795Sdonn 				break;
256988cbd795Sdonn 			case TYREAL:
257088cbd795Sdonn 			case TYDREAL:
257188cbd795Sdonn 				cp->cd[0] = ap->cd[0] * bp->cd[0];
257288cbd795Sdonn 				break;
257388cbd795Sdonn 			case TYCOMPLEX:
257488cbd795Sdonn 			case TYDCOMPLEX:
257588cbd795Sdonn 				temp = ap->cd[0] * bp->cd[0] -
257688cbd795Sdonn 					    ap->cd[1] * bp->cd[1] ;
257788cbd795Sdonn 				cp->cd[1] = ap->cd[0] * bp->cd[1] +
257888cbd795Sdonn 					    ap->cd[1] * bp->cd[0] ;
257988cbd795Sdonn 				cp->cd[0] = temp;
258088cbd795Sdonn 				break;
258188cbd795Sdonn 			}
258288cbd795Sdonn 		break;
258388cbd795Sdonn 	case OPSLASH:
258488cbd795Sdonn 		switch(type)
258588cbd795Sdonn 			{
258688cbd795Sdonn 			case TYSHORT:
258788cbd795Sdonn 			case TYLONG:
258888cbd795Sdonn 				cp->ci = ap->ci / bp->ci;
258988cbd795Sdonn 				break;
259088cbd795Sdonn 			case TYREAL:
259188cbd795Sdonn 			case TYDREAL:
259288cbd795Sdonn 				cp->cd[0] = ap->cd[0] / bp->cd[0];
259388cbd795Sdonn 				break;
259488cbd795Sdonn 			case TYCOMPLEX:
259588cbd795Sdonn 			case TYDCOMPLEX:
259688cbd795Sdonn 				zdiv(cp,ap,bp);
259788cbd795Sdonn 				break;
259888cbd795Sdonn 			}
259988cbd795Sdonn 		break;
260088cbd795Sdonn 
260188cbd795Sdonn 	case OPMOD:
260288cbd795Sdonn 		if( ISINT(type) )
260388cbd795Sdonn 			{
260488cbd795Sdonn 			cp->ci = ap->ci % bp->ci;
260588cbd795Sdonn 			break;
260688cbd795Sdonn 			}
260788cbd795Sdonn 		else
260888cbd795Sdonn 			fatal("inline mod of noninteger");
260988cbd795Sdonn 
261088cbd795Sdonn 	default:	  /* relational ops */
261188cbd795Sdonn 		switch(type)
261288cbd795Sdonn 			{
261388cbd795Sdonn 			case TYSHORT:
261488cbd795Sdonn 			case TYLONG:
261588cbd795Sdonn 				if(ap->ci < bp->ci)
261688cbd795Sdonn 					k = -1;
261788cbd795Sdonn 				else if(ap->ci == bp->ci)
261888cbd795Sdonn 					k = 0;
261988cbd795Sdonn 				else	k = 1;
262088cbd795Sdonn 				break;
262188cbd795Sdonn 			case TYREAL:
262288cbd795Sdonn 			case TYDREAL:
262388cbd795Sdonn 				if(ap->cd[0] < bp->cd[0])
262488cbd795Sdonn 					k = -1;
262588cbd795Sdonn 				else if(ap->cd[0] == bp->cd[0])
262688cbd795Sdonn 					k = 0;
262788cbd795Sdonn 				else	k = 1;
262888cbd795Sdonn 				break;
262988cbd795Sdonn 			case TYCOMPLEX:
263088cbd795Sdonn 			case TYDCOMPLEX:
263188cbd795Sdonn 				if(ap->cd[0] == bp->cd[0] &&
263288cbd795Sdonn 				   ap->cd[1] == bp->cd[1] )
263388cbd795Sdonn 					k = 0;
263488cbd795Sdonn 				else	k = 1;
263588cbd795Sdonn 				break;
263688cbd795Sdonn 			}
263788cbd795Sdonn 
263888cbd795Sdonn 		switch(opcode)
263988cbd795Sdonn 			{
264088cbd795Sdonn 			case OPEQ:
264188cbd795Sdonn 				cp->ci = (k == 0);
264288cbd795Sdonn 				break;
264388cbd795Sdonn 			case OPNE:
264488cbd795Sdonn 				cp->ci = (k != 0);
264588cbd795Sdonn 				break;
264688cbd795Sdonn 			case OPGT:
264788cbd795Sdonn 				cp->ci = (k == 1);
264888cbd795Sdonn 				break;
264988cbd795Sdonn 			case OPLT:
265088cbd795Sdonn 				cp->ci = (k == -1);
265188cbd795Sdonn 				break;
265288cbd795Sdonn 			case OPGE:
265388cbd795Sdonn 				cp->ci = (k >= 0);
265488cbd795Sdonn 				break;
265588cbd795Sdonn 			case OPLE:
265688cbd795Sdonn 				cp->ci = (k <= 0);
265788cbd795Sdonn 				break;
265888cbd795Sdonn 			default:
265988cbd795Sdonn 				badop ("consbinop", opcode);
266088cbd795Sdonn 			}
266188cbd795Sdonn 		break;
266288cbd795Sdonn 	}
266388cbd795Sdonn }
266488cbd795Sdonn 
266588cbd795Sdonn 
266688cbd795Sdonn 
266788cbd795Sdonn 
conssgn(p)266888cbd795Sdonn conssgn(p)
266988cbd795Sdonn register expptr p;
267088cbd795Sdonn {
267188cbd795Sdonn if( ! ISCONST(p) )
267288cbd795Sdonn 	fatal( "sgn(nonconstant)" );
267388cbd795Sdonn 
267488cbd795Sdonn switch(p->headblock.vtype)
267588cbd795Sdonn 	{
267688cbd795Sdonn 	case TYSHORT:
267788cbd795Sdonn 	case TYLONG:
267876ad5316Sbostic 		if(p->constblock.constant.ci > 0) return(1);
267976ad5316Sbostic 		if(p->constblock.constant.ci < 0) return(-1);
268088cbd795Sdonn 		return(0);
268188cbd795Sdonn 
268288cbd795Sdonn 	case TYREAL:
268388cbd795Sdonn 	case TYDREAL:
268476ad5316Sbostic 		if(p->constblock.constant.cd[0] > 0) return(1);
268576ad5316Sbostic 		if(p->constblock.constant.cd[0] < 0) return(-1);
268688cbd795Sdonn 		return(0);
268788cbd795Sdonn 
268888cbd795Sdonn 	case TYCOMPLEX:
268988cbd795Sdonn 	case TYDCOMPLEX:
269076ad5316Sbostic 		return(p->constblock.constant.cd[0]!=0 ||
269176ad5316Sbostic 			p->constblock.constant.cd[1]!=0);
269288cbd795Sdonn 
269388cbd795Sdonn 	default:
269488cbd795Sdonn 		badtype( "conssgn", p->constblock.vtype);
269588cbd795Sdonn 	}
269688cbd795Sdonn /* NOTREACHED */
269788cbd795Sdonn }
269888cbd795Sdonn 
269988cbd795Sdonn char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
270088cbd795Sdonn 
270188cbd795Sdonn 
mkpower(p)270288cbd795Sdonn LOCAL expptr mkpower(p)
270388cbd795Sdonn register expptr p;
270488cbd795Sdonn {
270588cbd795Sdonn register expptr q, lp, rp;
270688cbd795Sdonn int ltype, rtype, mtype;
270788cbd795Sdonn 
270888cbd795Sdonn lp = p->exprblock.leftp;
270988cbd795Sdonn rp = p->exprblock.rightp;
271088cbd795Sdonn ltype = lp->headblock.vtype;
271188cbd795Sdonn rtype = rp->headblock.vtype;
271288cbd795Sdonn 
271388cbd795Sdonn if(ISICON(rp))
271488cbd795Sdonn 	{
271576ad5316Sbostic 	if(rp->constblock.constant.ci == 0)
271688cbd795Sdonn 		{
271788cbd795Sdonn 		frexpr(p);
271888cbd795Sdonn 		if( ISINT(ltype) )
271988cbd795Sdonn 			return( ICON(1) );
272088cbd795Sdonn 		else
272188cbd795Sdonn 			{
272288cbd795Sdonn 			expptr pp;
272388cbd795Sdonn 			pp = mkconv(ltype, ICON(1));
272488cbd795Sdonn 			return( pp );
272588cbd795Sdonn 			}
272688cbd795Sdonn 		}
272776ad5316Sbostic 	if(rp->constblock.constant.ci < 0)
272888cbd795Sdonn 		{
272988cbd795Sdonn 		if( ISINT(ltype) )
273088cbd795Sdonn 			{
273188cbd795Sdonn 			frexpr(p);
273288cbd795Sdonn 			err("integer**negative");
273388cbd795Sdonn 			return( errnode() );
273488cbd795Sdonn 			}
273576ad5316Sbostic 		rp->constblock.constant.ci = - rp->constblock.constant.ci;
273688cbd795Sdonn 		p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
273788cbd795Sdonn 		}
273876ad5316Sbostic 	if(rp->constblock.constant.ci == 1)
273988cbd795Sdonn 		{
274088cbd795Sdonn 		frexpr(rp);
274188cbd795Sdonn 		free( (charptr) p );
274288cbd795Sdonn 		return(lp);
274388cbd795Sdonn 		}
274488cbd795Sdonn 
274588cbd795Sdonn 	if( ONEOF(ltype, MSKINT|MSKREAL) )
274688cbd795Sdonn 		{
274788cbd795Sdonn 		p->exprblock.vtype = ltype;
274888cbd795Sdonn 		return(p);
274988cbd795Sdonn 		}
275088cbd795Sdonn 	}
275188cbd795Sdonn if( ISINT(rtype) )
275288cbd795Sdonn 	{
275388cbd795Sdonn 	if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
275488cbd795Sdonn 		q = call2(TYSHORT, "pow_hh", lp, rp);
275588cbd795Sdonn 	else	{
275688cbd795Sdonn 		if(ltype == TYSHORT)
275788cbd795Sdonn 			{
275888cbd795Sdonn 			ltype = TYLONG;
275988cbd795Sdonn 			lp = mkconv(TYLONG,lp);
276088cbd795Sdonn 			}
276188cbd795Sdonn 		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
276288cbd795Sdonn 		}
276388cbd795Sdonn 	}
276488cbd795Sdonn else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
276588cbd795Sdonn 	q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
276688cbd795Sdonn else	{
276788cbd795Sdonn 	q  = call2(TYDCOMPLEX, "pow_zz",
276888cbd795Sdonn 		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
276988cbd795Sdonn 	if(mtype == TYCOMPLEX)
277088cbd795Sdonn 		q = mkconv(TYCOMPLEX, q);
277188cbd795Sdonn 	}
277288cbd795Sdonn free( (charptr) p );
277388cbd795Sdonn return(q);
277488cbd795Sdonn }
277588cbd795Sdonn 
277688cbd795Sdonn 
277788cbd795Sdonn 
277888cbd795Sdonn /* Complex Division.  Same code as in Runtime Library
277988cbd795Sdonn */
278088cbd795Sdonn 
278188cbd795Sdonn struct dcomplex { double dreal, dimag; };
278288cbd795Sdonn 
278388cbd795Sdonn 
zdiv(c,a,b)278488cbd795Sdonn LOCAL zdiv(c, a, b)
278588cbd795Sdonn register struct dcomplex *a, *b, *c;
278688cbd795Sdonn {
278788cbd795Sdonn double ratio, den;
278888cbd795Sdonn double abr, abi;
278988cbd795Sdonn 
279088cbd795Sdonn if( (abr = b->dreal) < 0.)
279188cbd795Sdonn 	abr = - abr;
279288cbd795Sdonn if( (abi = b->dimag) < 0.)
279388cbd795Sdonn 	abi = - abi;
279488cbd795Sdonn if( abr <= abi )
279588cbd795Sdonn 	{
279688cbd795Sdonn 	if(abi == 0)
279788cbd795Sdonn 		fatal("complex division by zero");
279888cbd795Sdonn 	ratio = b->dreal / b->dimag ;
279988cbd795Sdonn 	den = b->dimag * (1 + ratio*ratio);
280088cbd795Sdonn 	c->dreal = (a->dreal*ratio + a->dimag) / den;
280188cbd795Sdonn 	c->dimag = (a->dimag*ratio - a->dreal) / den;
280288cbd795Sdonn 	}
280388cbd795Sdonn 
280488cbd795Sdonn else
280588cbd795Sdonn 	{
280688cbd795Sdonn 	ratio = b->dimag / b->dreal ;
280788cbd795Sdonn 	den = b->dreal * (1 + ratio*ratio);
280888cbd795Sdonn 	c->dreal = (a->dreal + a->dimag*ratio) / den;
280988cbd795Sdonn 	c->dimag = (a->dimag - a->dreal*ratio) / den;
281088cbd795Sdonn 	}
281188cbd795Sdonn 
281288cbd795Sdonn }
281388cbd795Sdonn 
oftwo(e)281488cbd795Sdonn expptr oftwo(e)
281588cbd795Sdonn expptr e;
281688cbd795Sdonn {
281788cbd795Sdonn 	int val,res;
281888cbd795Sdonn 
281988cbd795Sdonn 	if (! ISCONST (e))
282088cbd795Sdonn 		return (0);
282188cbd795Sdonn 
282276ad5316Sbostic 	val = e->constblock.constant.ci;
282388cbd795Sdonn 	switch (val)
282488cbd795Sdonn 		{
282588cbd795Sdonn 		case 2:		res = 1; break;
282688cbd795Sdonn 		case 4:		res = 2; break;
282788cbd795Sdonn 		case 8:		res = 3; break;
282888cbd795Sdonn 		case 16:	res = 4; break;
282988cbd795Sdonn 		case 32:	res = 5; break;
283088cbd795Sdonn 		case 64:	res = 6; break;
283188cbd795Sdonn 		case 128:	res = 7; break;
283288cbd795Sdonn 		case 256:	res = 8; break;
283388cbd795Sdonn 		default:	return (0);
283488cbd795Sdonn 		}
283588cbd795Sdonn 	return (ICON (res));
283688cbd795Sdonn }
2837