xref: /csrg-svn/usr.bin/f77/pass1.tahoe/expr.c (revision 40230)
1*40230Sdonn /*
2*40230Sdonn  * Copyright (c) 1980 Regents of the University of California.
3*40230Sdonn  * All rights reserved.  The Berkeley software License Agreement
4*40230Sdonn  * specifies the terms and conditions for redistribution.
5*40230Sdonn  */
6*40230Sdonn 
7*40230Sdonn #ifndef lint
8*40230Sdonn static char *sccsid[] = "@(#)expr.c	5.3 (Berkeley) 6/23/85";
9*40230Sdonn #endif not lint
10*40230Sdonn 
11*40230Sdonn /*
12*40230Sdonn  * expr.c
13*40230Sdonn  *
14*40230Sdonn  * Routines for handling expressions, f77 compiler pass 1.
15*40230Sdonn  *
16*40230Sdonn  * University of Utah CS Dept modification history:
17*40230Sdonn  *
18*40230Sdonn  * $Log:	expr.c,v $
19*40230Sdonn  * Revision 1.3  86/02/26  17:13:37  rcs
20*40230Sdonn  * Correct COFR 411.
21*40230Sdonn  * P. Wong
22*40230Sdonn  *
23*40230Sdonn  * Revision 3.16  85/06/21  16:38:09  donn
24*40230Sdonn  * The fix to mkprim() didn't handle null substring parameters (sigh).
25*40230Sdonn  *
26*40230Sdonn  * Revision 3.15  85/06/04  04:37:03  donn
27*40230Sdonn  * Changed mkprim() to force substring parameters to be integral types.
28*40230Sdonn  *
29*40230Sdonn  * Revision 3.14  85/06/04  03:41:52  donn
30*40230Sdonn  * Change impldcl() to handle functions of type 'undefined'.
31*40230Sdonn  *
32*40230Sdonn  * Revision 3.13  85/05/06  23:14:55  donn
33*40230Sdonn  * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
34*40230Sdonn  * a temporary when converting character strings to integers; previously we
35*40230Sdonn  * were having problems because mkconv() was called after tempalloc().
36*40230Sdonn  *
37*40230Sdonn  * Revision 3.12  85/03/18  08:07:47  donn
38*40230Sdonn  * Fixes to help out with short integers -- if integers are by default short,
39*40230Sdonn  * then so are constants; and if addresses can't be stored in shorts, complain.
40*40230Sdonn  *
41*40230Sdonn  * Revision 3.11  85/03/16  22:31:27  donn
42*40230Sdonn  * Added hack to mkconv() to allow character values of length > 1 to be
43*40230Sdonn  * converted to numeric types, for Helge Skrivervik.  Note that this does
44*40230Sdonn  * not affect use of the intrinsic ichar() conversion.
45*40230Sdonn  *
46*40230Sdonn  * Revision 3.10  85/01/15  21:06:47  donn
47*40230Sdonn  * Changed mkconv() to comment on implicit conversions; added intrconv() for
48*40230Sdonn  * use with explicit conversions by intrinsic functions.
49*40230Sdonn  *
50*40230Sdonn  * Revision 3.9  85/01/11  21:05:49  donn
51*40230Sdonn  * Added changes to implement SAVE statements.
52*40230Sdonn  *
53*40230Sdonn  * Revision 3.8  84/12/17  02:21:06  donn
54*40230Sdonn  * Added a test to prevent constant folding from being done on expressions
55*40230Sdonn  * whose type is not known at that point in mkexpr().
56*40230Sdonn  *
57*40230Sdonn  * Revision 3.7  84/12/11  21:14:17  donn
58*40230Sdonn  * Removed obnoxious 'excess precision' warning.
59*40230Sdonn  *
60*40230Sdonn  * Revision 3.6  84/11/23  01:00:36  donn
61*40230Sdonn  * Added code to trim excess precision from single-precision constants, and
62*40230Sdonn  * to warn the user when this occurs.
63*40230Sdonn  *
64*40230Sdonn  * Revision 3.5  84/11/23  00:10:39  donn
65*40230Sdonn  * Changed stfcall() to remark on argument type clashes in 'calls' to
66*40230Sdonn  * statement functions.
67*40230Sdonn  *
68*40230Sdonn  * Revision 3.4  84/11/22  21:21:17  donn
69*40230Sdonn  * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
70*40230Sdonn  *
71*40230Sdonn  * Revision 3.3  84/11/12  18:26:14  donn
72*40230Sdonn  * Shuffled some code around so that the compiler remembers to free some vleng
73*40230Sdonn  * structures which used to just sit around.
74*40230Sdonn  *
75*40230Sdonn  * Revision 3.2  84/10/16  19:24:15  donn
76*40230Sdonn  * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
77*40230Sdonn  * core dumps by replacing bad subscripts with good ones.
78*40230Sdonn  *
79*40230Sdonn  * Revision 3.1  84/10/13  01:31:32  donn
80*40230Sdonn  * Merged Jerry Berkman's version into mine.
81*40230Sdonn  *
82*40230Sdonn  * Revision 2.7  84/09/27  15:42:52  donn
83*40230Sdonn  * The last fix for multiplying undeclared variables by 0 isn't sufficient,
84*40230Sdonn  * since the type of the 0 may not be the (implicit) type of the variable.
85*40230Sdonn  * I added a hack to check the implicit type of implicitly declared
86*40230Sdonn  * variables...
87*40230Sdonn  *
88*40230Sdonn  * Revision 2.6  84/09/14  19:34:03  donn
89*40230Sdonn  * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
90*40230Sdonn  * 0 to type UNKNOWN, which is illegal.  Fix is to use native type instead.
91*40230Sdonn  * Not sure how correct (or important) this is...
92*40230Sdonn  *
93*40230Sdonn  * Revision 2.5  84/08/05  23:05:27  donn
94*40230Sdonn  * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
95*40230Sdonn  * with two operands.
96*40230Sdonn  *
97*40230Sdonn  * Revision 2.4  84/08/05  17:34:48  donn
98*40230Sdonn  * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
99*40230Sdonn  * and assign constant length 1 to them.
100*40230Sdonn  *
101*40230Sdonn  * Revision 2.3  84/07/19  19:38:33  donn
102*40230Sdonn  * Added a typecast to the last fix.  Somehow I missed it the first time...
103*40230Sdonn  *
104*40230Sdonn  * Revision 2.2  84/07/19  17:19:57  donn
105*40230Sdonn  * Caused OPPAREN expressions to inherit the length of their operands, so
106*40230Sdonn  * that parenthesized character expressions work correctly.
107*40230Sdonn  *
108*40230Sdonn  * Revision 2.1  84/07/19  12:03:02  donn
109*40230Sdonn  * Changed comment headers for UofU.
110*40230Sdonn  *
111*40230Sdonn  * Revision 1.2  84/04/06  20:12:17  donn
112*40230Sdonn  * Fixed bug which caused programs with mixed-type multiplications involving
113*40230Sdonn  * the constant 0 to choke the compiler.
114*40230Sdonn  *
115*40230Sdonn  */
116*40230Sdonn 
117*40230Sdonn #include "defs.h"
118*40230Sdonn 
119*40230Sdonn 
120*40230Sdonn /* little routines to create constant blocks */
121*40230Sdonn 
122*40230Sdonn Constp mkconst(t)
123*40230Sdonn register int t;
124*40230Sdonn {
125*40230Sdonn register Constp p;
126*40230Sdonn 
127*40230Sdonn p = ALLOC(Constblock);
128*40230Sdonn p->tag = TCONST;
129*40230Sdonn p->vtype = t;
130*40230Sdonn return(p);
131*40230Sdonn }
132*40230Sdonn 
133*40230Sdonn 
134*40230Sdonn expptr mklogcon(l)
135*40230Sdonn register int l;
136*40230Sdonn {
137*40230Sdonn register Constp  p;
138*40230Sdonn 
139*40230Sdonn p = mkconst(TYLOGICAL);
140*40230Sdonn p->const.ci = l;
141*40230Sdonn return( (expptr) p );
142*40230Sdonn }
143*40230Sdonn 
144*40230Sdonn 
145*40230Sdonn 
146*40230Sdonn expptr mkintcon(l)
147*40230Sdonn ftnint l;
148*40230Sdonn {
149*40230Sdonn register Constp p;
150*40230Sdonn int usetype;
151*40230Sdonn 
152*40230Sdonn if(tyint == TYSHORT)
153*40230Sdonn   {
154*40230Sdonn     short s = l;
155*40230Sdonn     if(l != s)
156*40230Sdonn       usetype = TYLONG;
157*40230Sdonn     else
158*40230Sdonn       usetype = TYSHORT;
159*40230Sdonn   }
160*40230Sdonn else
161*40230Sdonn   usetype = tyint;
162*40230Sdonn p = mkconst(usetype);
163*40230Sdonn p->const.ci = l;
164*40230Sdonn return( (expptr) p );
165*40230Sdonn }
166*40230Sdonn 
167*40230Sdonn 
168*40230Sdonn 
169*40230Sdonn expptr mkaddcon(l)
170*40230Sdonn register int l;
171*40230Sdonn {
172*40230Sdonn register Constp p;
173*40230Sdonn 
174*40230Sdonn p = mkconst(TYADDR);
175*40230Sdonn p->const.ci = l;
176*40230Sdonn return( (expptr) p );
177*40230Sdonn }
178*40230Sdonn 
179*40230Sdonn 
180*40230Sdonn 
181*40230Sdonn expptr mkrealcon(t, d)
182*40230Sdonn register int t;
183*40230Sdonn double d;
184*40230Sdonn {
185*40230Sdonn register Constp p;
186*40230Sdonn 
187*40230Sdonn p = mkconst(t);
188*40230Sdonn p->const.cd[0] = d;
189*40230Sdonn return( (expptr) p );
190*40230Sdonn }
191*40230Sdonn 
192*40230Sdonn expptr mkbitcon(shift, leng, s)
193*40230Sdonn int shift;
194*40230Sdonn register int leng;
195*40230Sdonn register char *s;
196*40230Sdonn {
197*40230Sdonn   Constp p;
198*40230Sdonn   register int i, j, k;
199*40230Sdonn   register char *bp;
200*40230Sdonn   int size;
201*40230Sdonn 
202*40230Sdonn   size = (shift*leng + BYTESIZE -1)/BYTESIZE;
203*40230Sdonn   bp = (char *) ckalloc(size);
204*40230Sdonn 
205*40230Sdonn   i = 0;
206*40230Sdonn 
207*40230Sdonn #if (HERE == PDP11 || HERE == VAX)
208*40230Sdonn   j = 0;
209*40230Sdonn #else
210*40230Sdonn   j = size;
211*40230Sdonn #endif
212*40230Sdonn 
213*40230Sdonn   k = 0;
214*40230Sdonn 
215*40230Sdonn   while (leng > 0)
216*40230Sdonn     {
217*40230Sdonn       k |= (hextoi(s[--leng]) << i);
218*40230Sdonn       i += shift;
219*40230Sdonn       if (i >= BYTESIZE)
220*40230Sdonn 	{
221*40230Sdonn #if (HERE == PDP11 || HERE == VAX)
222*40230Sdonn 	  bp[j++] = k & MAXBYTE;
223*40230Sdonn #else
224*40230Sdonn 	  bp[--j] = k & MAXBYTE;
225*40230Sdonn #endif
226*40230Sdonn 	  k = k >> BYTESIZE;
227*40230Sdonn 	  i -= BYTESIZE;
228*40230Sdonn 	}
229*40230Sdonn     }
230*40230Sdonn 
231*40230Sdonn   if (k != 0)
232*40230Sdonn #if (HERE == PDP11 || HERE == VAX)
233*40230Sdonn     bp[j++] = k;
234*40230Sdonn #else
235*40230Sdonn     bp[--j] = k;
236*40230Sdonn #endif
237*40230Sdonn 
238*40230Sdonn   p = mkconst(TYBITSTR);
239*40230Sdonn   p->vleng = ICON(size);
240*40230Sdonn   p->const.ccp = bp;
241*40230Sdonn 
242*40230Sdonn   return ((expptr) p);
243*40230Sdonn }
244*40230Sdonn 
245*40230Sdonn 
246*40230Sdonn 
247*40230Sdonn expptr mkstrcon(l,v)
248*40230Sdonn int l;
249*40230Sdonn register char *v;
250*40230Sdonn {
251*40230Sdonn register Constp p;
252*40230Sdonn register char *s;
253*40230Sdonn 
254*40230Sdonn p = mkconst(TYCHAR);
255*40230Sdonn p->vleng = ICON(l);
256*40230Sdonn p->const.ccp = s = (char *) ckalloc(l);
257*40230Sdonn while(--l >= 0)
258*40230Sdonn 	*s++ = *v++;
259*40230Sdonn return( (expptr) p );
260*40230Sdonn }
261*40230Sdonn 
262*40230Sdonn 
263*40230Sdonn expptr mkcxcon(realp,imagp)
264*40230Sdonn register expptr realp, imagp;
265*40230Sdonn {
266*40230Sdonn int rtype, itype;
267*40230Sdonn register Constp p;
268*40230Sdonn 
269*40230Sdonn rtype = realp->headblock.vtype;
270*40230Sdonn itype = imagp->headblock.vtype;
271*40230Sdonn 
272*40230Sdonn if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
273*40230Sdonn 	{
274*40230Sdonn 	p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
275*40230Sdonn 	if( ISINT(rtype) )
276*40230Sdonn 		p->const.cd[0] = realp->constblock.const.ci;
277*40230Sdonn 	else	p->const.cd[0] = realp->constblock.const.cd[0];
278*40230Sdonn 	if( ISINT(itype) )
279*40230Sdonn 		p->const.cd[1] = imagp->constblock.const.ci;
280*40230Sdonn 	else	p->const.cd[1] = imagp->constblock.const.cd[0];
281*40230Sdonn 	}
282*40230Sdonn else
283*40230Sdonn 	{
284*40230Sdonn 	err("invalid complex constant");
285*40230Sdonn 	p = (Constp) errnode();
286*40230Sdonn 	}
287*40230Sdonn 
288*40230Sdonn frexpr(realp);
289*40230Sdonn frexpr(imagp);
290*40230Sdonn return( (expptr) p );
291*40230Sdonn }
292*40230Sdonn 
293*40230Sdonn 
294*40230Sdonn expptr errnode()
295*40230Sdonn {
296*40230Sdonn struct Errorblock *p;
297*40230Sdonn p = ALLOC(Errorblock);
298*40230Sdonn p->tag = TERROR;
299*40230Sdonn p->vtype = TYERROR;
300*40230Sdonn return( (expptr) p );
301*40230Sdonn }
302*40230Sdonn 
303*40230Sdonn 
304*40230Sdonn 
305*40230Sdonn 
306*40230Sdonn 
307*40230Sdonn expptr mkconv(t, p)
308*40230Sdonn register int t;
309*40230Sdonn register expptr p;
310*40230Sdonn {
311*40230Sdonn register expptr q;
312*40230Sdonn Addrp r, s;
313*40230Sdonn register int pt;
314*40230Sdonn expptr opconv();
315*40230Sdonn 
316*40230Sdonn if(t==TYUNKNOWN || t==TYERROR)
317*40230Sdonn 	badtype("mkconv", t);
318*40230Sdonn pt = p->headblock.vtype;
319*40230Sdonn if(t == pt)
320*40230Sdonn 	return(p);
321*40230Sdonn 
322*40230Sdonn if( pt == TYCHAR && ISNUMERIC(t) )
323*40230Sdonn 	{
324*40230Sdonn 	warn("implicit conversion of character to numeric type");
325*40230Sdonn 
326*40230Sdonn 	/*
327*40230Sdonn 	 * Ugly kluge to copy character values into numerics.
328*40230Sdonn 	 */
329*40230Sdonn 	s = mkaltemp(t, ENULL);
330*40230Sdonn 	r = (Addrp) cpexpr(s);
331*40230Sdonn 	r->vtype = TYCHAR;
332*40230Sdonn 	r->varleng = typesize[t];
333*40230Sdonn 	r->vleng = mkintcon(r->varleng);
334*40230Sdonn 	q = mkexpr(OPASSIGN, r, p);
335*40230Sdonn 	q = mkexpr(OPCOMMA, q, s);
336*40230Sdonn 	return(q);
337*40230Sdonn 	}
338*40230Sdonn 
339*40230Sdonn #if SZADDR > SZSHORT
340*40230Sdonn if( pt == TYADDR && t == TYSHORT)
341*40230Sdonn 	{
342*40230Sdonn 	err("insufficient precision to hold address type");
343*40230Sdonn 	return( errnode() );
344*40230Sdonn 	}
345*40230Sdonn #endif
346*40230Sdonn if( pt == TYADDR && ISNUMERIC(t) )
347*40230Sdonn 	warn("implicit conversion of address to numeric type");
348*40230Sdonn 
349*40230Sdonn if( ISCONST(p) && pt!=TYADDR)
350*40230Sdonn 	{
351*40230Sdonn 	q = (expptr) mkconst(t);
352*40230Sdonn 	consconv(t, &(q->constblock.const),
353*40230Sdonn 		p->constblock.vtype, &(p->constblock.const) );
354*40230Sdonn 	frexpr(p);
355*40230Sdonn 	}
356*40230Sdonn #if TARGET == PDP11
357*40230Sdonn else if(ISINT(t) && pt==TYCHAR)
358*40230Sdonn 	{
359*40230Sdonn 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
360*40230Sdonn 	if(t == TYLONG)
361*40230Sdonn 		q = opconv(q, TYLONG);
362*40230Sdonn 	}
363*40230Sdonn #endif
364*40230Sdonn else
365*40230Sdonn 	q = opconv(p, t);
366*40230Sdonn 
367*40230Sdonn if(t == TYCHAR)
368*40230Sdonn 	q->constblock.vleng = ICON(1);
369*40230Sdonn return(q);
370*40230Sdonn }
371*40230Sdonn 
372*40230Sdonn 
373*40230Sdonn 
374*40230Sdonn /* intrinsic conversions */
375*40230Sdonn expptr intrconv(t, p)
376*40230Sdonn register int t;
377*40230Sdonn register expptr p;
378*40230Sdonn {
379*40230Sdonn register expptr q;
380*40230Sdonn register int pt;
381*40230Sdonn expptr opconv();
382*40230Sdonn 
383*40230Sdonn if(t==TYUNKNOWN || t==TYERROR)
384*40230Sdonn 	badtype("intrconv", t);
385*40230Sdonn pt = p->headblock.vtype;
386*40230Sdonn if(t == pt)
387*40230Sdonn 	return(p);
388*40230Sdonn 
389*40230Sdonn else if( ISCONST(p) && pt!=TYADDR)
390*40230Sdonn 	{
391*40230Sdonn 	q = (expptr) mkconst(t);
392*40230Sdonn 	consconv(t, &(q->constblock.const),
393*40230Sdonn 		p->constblock.vtype, &(p->constblock.const) );
394*40230Sdonn 	frexpr(p);
395*40230Sdonn 	}
396*40230Sdonn #if TARGET == PDP11
397*40230Sdonn else if(ISINT(t) && pt==TYCHAR)
398*40230Sdonn 	{
399*40230Sdonn 	q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
400*40230Sdonn 	if(t == TYLONG)
401*40230Sdonn 		q = opconv(q, TYLONG);
402*40230Sdonn 	}
403*40230Sdonn #endif
404*40230Sdonn else
405*40230Sdonn 	q = opconv(p, t);
406*40230Sdonn 
407*40230Sdonn if(t == TYCHAR)
408*40230Sdonn 	q->constblock.vleng = ICON(1);
409*40230Sdonn return(q);
410*40230Sdonn }
411*40230Sdonn 
412*40230Sdonn 
413*40230Sdonn 
414*40230Sdonn expptr opconv(p, t)
415*40230Sdonn expptr p;
416*40230Sdonn int t;
417*40230Sdonn {
418*40230Sdonn register expptr q;
419*40230Sdonn 
420*40230Sdonn q = mkexpr(OPCONV, p, PNULL);
421*40230Sdonn q->headblock.vtype = t;
422*40230Sdonn return(q);
423*40230Sdonn }
424*40230Sdonn 
425*40230Sdonn 
426*40230Sdonn 
427*40230Sdonn expptr addrof(p)
428*40230Sdonn expptr p;
429*40230Sdonn {
430*40230Sdonn return( mkexpr(OPADDR, p, PNULL) );
431*40230Sdonn }
432*40230Sdonn 
433*40230Sdonn 
434*40230Sdonn 
435*40230Sdonn tagptr cpexpr(p)
436*40230Sdonn register tagptr p;
437*40230Sdonn {
438*40230Sdonn register tagptr e;
439*40230Sdonn int tag;
440*40230Sdonn register chainp ep, pp;
441*40230Sdonn tagptr cpblock();
442*40230Sdonn 
443*40230Sdonn static int blksize[ ] =
444*40230Sdonn 	{	0,
445*40230Sdonn 		sizeof(struct Nameblock),
446*40230Sdonn 		sizeof(struct Constblock),
447*40230Sdonn 		sizeof(struct Exprblock),
448*40230Sdonn 		sizeof(struct Addrblock),
449*40230Sdonn 		sizeof(struct Tempblock),
450*40230Sdonn 		sizeof(struct Primblock),
451*40230Sdonn 		sizeof(struct Listblock),
452*40230Sdonn 		sizeof(struct Errorblock)
453*40230Sdonn 	};
454*40230Sdonn 
455*40230Sdonn if(p == NULL)
456*40230Sdonn 	return(NULL);
457*40230Sdonn 
458*40230Sdonn if( (tag = p->tag) == TNAME)
459*40230Sdonn 	return(p);
460*40230Sdonn 
461*40230Sdonn e = cpblock( blksize[p->tag] , p);
462*40230Sdonn 
463*40230Sdonn switch(tag)
464*40230Sdonn 	{
465*40230Sdonn 	case TCONST:
466*40230Sdonn 		if(e->constblock.vtype == TYCHAR)
467*40230Sdonn 			{
468*40230Sdonn 			e->constblock.const.ccp =
469*40230Sdonn 				copyn(1+strlen(e->constblock.const.ccp),
470*40230Sdonn 					e->constblock.const.ccp);
471*40230Sdonn 			e->constblock.vleng =
472*40230Sdonn 				(expptr) cpexpr(e->constblock.vleng);
473*40230Sdonn 			}
474*40230Sdonn 	case TERROR:
475*40230Sdonn 		break;
476*40230Sdonn 
477*40230Sdonn 	case TEXPR:
478*40230Sdonn 		e->exprblock.leftp =  (expptr) cpexpr(p->exprblock.leftp);
479*40230Sdonn 		e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
480*40230Sdonn 		break;
481*40230Sdonn 
482*40230Sdonn 	case TLIST:
483*40230Sdonn 		if(pp = p->listblock.listp)
484*40230Sdonn 			{
485*40230Sdonn 			ep = e->listblock.listp =
486*40230Sdonn 				mkchain( cpexpr(pp->datap), CHNULL);
487*40230Sdonn 			for(pp = pp->nextp ; pp ; pp = pp->nextp)
488*40230Sdonn 				ep = ep->nextp =
489*40230Sdonn 					mkchain( cpexpr(pp->datap), CHNULL);
490*40230Sdonn 			}
491*40230Sdonn 		break;
492*40230Sdonn 
493*40230Sdonn 	case TADDR:
494*40230Sdonn 		e->addrblock.vleng = (expptr)  cpexpr(e->addrblock.vleng);
495*40230Sdonn 		e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
496*40230Sdonn 		e->addrblock.istemp = NO;
497*40230Sdonn 		break;
498*40230Sdonn 
499*40230Sdonn 	case TTEMP:
500*40230Sdonn 		e->tempblock.vleng = (expptr)  cpexpr(e->tempblock.vleng);
501*40230Sdonn 		e->tempblock.istemp = NO;
502*40230Sdonn 		break;
503*40230Sdonn 
504*40230Sdonn 	case TPRIM:
505*40230Sdonn 		e->primblock.argsp = (struct Listblock *)
506*40230Sdonn 					cpexpr(e->primblock.argsp);
507*40230Sdonn 		e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
508*40230Sdonn 		e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
509*40230Sdonn 		break;
510*40230Sdonn 
511*40230Sdonn 	default:
512*40230Sdonn 		badtag("cpexpr", tag);
513*40230Sdonn 	}
514*40230Sdonn 
515*40230Sdonn return(e);
516*40230Sdonn }
517*40230Sdonn 
518*40230Sdonn frexpr(p)
519*40230Sdonn register tagptr p;
520*40230Sdonn {
521*40230Sdonn register chainp q;
522*40230Sdonn 
523*40230Sdonn if(p == NULL)
524*40230Sdonn 	return;
525*40230Sdonn 
526*40230Sdonn switch(p->tag)
527*40230Sdonn 	{
528*40230Sdonn 	case TCONST:
529*40230Sdonn 		switch (p->constblock.vtype)
530*40230Sdonn 			{
531*40230Sdonn 			case TYBITSTR:
532*40230Sdonn 			case TYCHAR:
533*40230Sdonn 			case TYHOLLERITH:
534*40230Sdonn 				free( (charptr) (p->constblock.const.ccp) );
535*40230Sdonn 				frexpr(p->constblock.vleng);
536*40230Sdonn 			}
537*40230Sdonn 		break;
538*40230Sdonn 
539*40230Sdonn 	case TADDR:
540*40230Sdonn 		if (!optimflag && p->addrblock.istemp)
541*40230Sdonn 			{
542*40230Sdonn 			frtemp(p);
543*40230Sdonn 			return;
544*40230Sdonn 			}
545*40230Sdonn 		frexpr(p->addrblock.vleng);
546*40230Sdonn 		frexpr(p->addrblock.memoffset);
547*40230Sdonn 		break;
548*40230Sdonn 
549*40230Sdonn 	case TTEMP:
550*40230Sdonn 		frexpr(p->tempblock.vleng);
551*40230Sdonn 		break;
552*40230Sdonn 
553*40230Sdonn 	case TERROR:
554*40230Sdonn 		break;
555*40230Sdonn 
556*40230Sdonn 	case TNAME:
557*40230Sdonn 		return;
558*40230Sdonn 
559*40230Sdonn 	case TPRIM:
560*40230Sdonn 		frexpr(p->primblock.argsp);
561*40230Sdonn 		frexpr(p->primblock.fcharp);
562*40230Sdonn 		frexpr(p->primblock.lcharp);
563*40230Sdonn 		break;
564*40230Sdonn 
565*40230Sdonn 	case TEXPR:
566*40230Sdonn 		frexpr(p->exprblock.leftp);
567*40230Sdonn 		if(p->exprblock.rightp)
568*40230Sdonn 			frexpr(p->exprblock.rightp);
569*40230Sdonn 		break;
570*40230Sdonn 
571*40230Sdonn 	case TLIST:
572*40230Sdonn 		for(q = p->listblock.listp ; q ; q = q->nextp)
573*40230Sdonn 			frexpr(q->datap);
574*40230Sdonn 		frchain( &(p->listblock.listp) );
575*40230Sdonn 		break;
576*40230Sdonn 
577*40230Sdonn 	default:
578*40230Sdonn 		badtag("frexpr", p->tag);
579*40230Sdonn 	}
580*40230Sdonn 
581*40230Sdonn free( (charptr) p );
582*40230Sdonn }
583*40230Sdonn 
584*40230Sdonn /* fix up types in expression; replace subtrees and convert
585*40230Sdonn    names to address blocks */
586*40230Sdonn 
587*40230Sdonn expptr fixtype(p)
588*40230Sdonn register tagptr p;
589*40230Sdonn {
590*40230Sdonn 
591*40230Sdonn if(p == 0)
592*40230Sdonn 	return(0);
593*40230Sdonn 
594*40230Sdonn switch(p->tag)
595*40230Sdonn 	{
596*40230Sdonn 	case TCONST:
597*40230Sdonn 		return( (expptr) p );
598*40230Sdonn 
599*40230Sdonn 	case TADDR:
600*40230Sdonn 		p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
601*40230Sdonn 		return( (expptr) p);
602*40230Sdonn 
603*40230Sdonn 	case TTEMP:
604*40230Sdonn 		return( (expptr) p);
605*40230Sdonn 
606*40230Sdonn 	case TERROR:
607*40230Sdonn 		return( (expptr) p);
608*40230Sdonn 
609*40230Sdonn 	default:
610*40230Sdonn 		badtag("fixtype", p->tag);
611*40230Sdonn 
612*40230Sdonn 	case TEXPR:
613*40230Sdonn 		return( fixexpr(p) );
614*40230Sdonn 
615*40230Sdonn 	case TLIST:
616*40230Sdonn 		return( (expptr) p );
617*40230Sdonn 
618*40230Sdonn 	case TPRIM:
619*40230Sdonn 		if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
620*40230Sdonn 			{
621*40230Sdonn 			if(p->primblock.namep->vtype == TYSUBR)
622*40230Sdonn 				{
623*40230Sdonn 				err("function invocation of subroutine");
624*40230Sdonn 				return( errnode() );
625*40230Sdonn 				}
626*40230Sdonn 			else
627*40230Sdonn 				return( mkfunct(p) );
628*40230Sdonn 			}
629*40230Sdonn 		else	return( mklhs(p) );
630*40230Sdonn 	}
631*40230Sdonn }
632*40230Sdonn 
633*40230Sdonn 
634*40230Sdonn 
635*40230Sdonn 
636*40230Sdonn 
637*40230Sdonn /* special case tree transformations and cleanups of expression trees */
638*40230Sdonn 
639*40230Sdonn expptr fixexpr(p)
640*40230Sdonn register Exprp p;
641*40230Sdonn {
642*40230Sdonn expptr lp;
643*40230Sdonn register expptr rp;
644*40230Sdonn register expptr q;
645*40230Sdonn int opcode, ltype, rtype, ptype, mtype;
646*40230Sdonn expptr lconst, rconst;
647*40230Sdonn expptr mkpower();
648*40230Sdonn 
649*40230Sdonn if( ISERROR(p) )
650*40230Sdonn 	return( (expptr) p );
651*40230Sdonn else if(p->tag != TEXPR)
652*40230Sdonn 	badtag("fixexpr", p->tag);
653*40230Sdonn opcode = p->opcode;
654*40230Sdonn if (ISCONST(p->leftp))
655*40230Sdonn 	lconst = (expptr) cpexpr(p->leftp);
656*40230Sdonn else
657*40230Sdonn 	lconst = NULL;
658*40230Sdonn if (p->rightp && ISCONST(p->rightp))
659*40230Sdonn 	rconst = (expptr) cpexpr(p->rightp);
660*40230Sdonn else
661*40230Sdonn 	rconst = NULL;
662*40230Sdonn lp = p->leftp = fixtype(p->leftp);
663*40230Sdonn ltype = lp->headblock.vtype;
664*40230Sdonn if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
665*40230Sdonn 	{
666*40230Sdonn 	err("left side of assignment must be variable");
667*40230Sdonn 	frexpr(p);
668*40230Sdonn 	return( errnode() );
669*40230Sdonn 	}
670*40230Sdonn 
671*40230Sdonn if(p->rightp)
672*40230Sdonn 	{
673*40230Sdonn 	rp = p->rightp = fixtype(p->rightp);
674*40230Sdonn 	rtype = rp->headblock.vtype;
675*40230Sdonn 	}
676*40230Sdonn else
677*40230Sdonn 	{
678*40230Sdonn 	rp = NULL;
679*40230Sdonn 	rtype = 0;
680*40230Sdonn 	}
681*40230Sdonn 
682*40230Sdonn if(ltype==TYERROR || rtype==TYERROR)
683*40230Sdonn 	{
684*40230Sdonn 	frexpr(p);
685*40230Sdonn 	frexpr(lconst);
686*40230Sdonn 	frexpr(rconst);
687*40230Sdonn 	return( errnode() );
688*40230Sdonn 	}
689*40230Sdonn 
690*40230Sdonn /* force folding if possible */
691*40230Sdonn if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
692*40230Sdonn 	{
693*40230Sdonn 	q = mkexpr(opcode, lp, rp);
694*40230Sdonn 	if( ISCONST(q) )
695*40230Sdonn 		{
696*40230Sdonn 		frexpr(lconst);
697*40230Sdonn 		frexpr(rconst);
698*40230Sdonn 		return(q);
699*40230Sdonn 		}
700*40230Sdonn 	free( (charptr) q );	/* constants did not fold */
701*40230Sdonn 	}
702*40230Sdonn 
703*40230Sdonn if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
704*40230Sdonn 	{
705*40230Sdonn 	frexpr(p);
706*40230Sdonn 	frexpr(lconst);
707*40230Sdonn 	frexpr(rconst);
708*40230Sdonn 	return( errnode() );
709*40230Sdonn 	}
710*40230Sdonn 
711*40230Sdonn switch(opcode)
712*40230Sdonn 	{
713*40230Sdonn 	case OPCONCAT:
714*40230Sdonn 		if(p->vleng == NULL)
715*40230Sdonn 			p->vleng = mkexpr(OPPLUS,
716*40230Sdonn 				cpexpr(lp->headblock.vleng),
717*40230Sdonn 				cpexpr(rp->headblock.vleng) );
718*40230Sdonn 		break;
719*40230Sdonn 
720*40230Sdonn 	case OPASSIGN:
721*40230Sdonn 	case OPPLUSEQ:
722*40230Sdonn 	case OPSTAREQ:
723*40230Sdonn 		if(ltype == rtype)
724*40230Sdonn 			break;
725*40230Sdonn #if TARGET == VAX
726*40230Sdonn 		if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
727*40230Sdonn 			break;
728*40230Sdonn #endif
729*40230Sdonn 		if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
730*40230Sdonn 			break;
731*40230Sdonn 		if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
732*40230Sdonn #if FAMILY==PCC
733*40230Sdonn 		    && typesize[ltype]>=typesize[rtype] )
734*40230Sdonn #else
735*40230Sdonn 		    && typesize[ltype]==typesize[rtype] )
736*40230Sdonn #endif
737*40230Sdonn 			break;
738*40230Sdonn 		if (rconst)
739*40230Sdonn 			{
740*40230Sdonn 			p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
741*40230Sdonn 			frexpr(rp);
742*40230Sdonn 			}
743*40230Sdonn 		else
744*40230Sdonn 			p->rightp = fixtype(mkconv(ptype, rp));
745*40230Sdonn 		break;
746*40230Sdonn 
747*40230Sdonn 	case OPSLASH:
748*40230Sdonn 		if( ISCOMPLEX(rtype) )
749*40230Sdonn 			{
750*40230Sdonn 			p = (Exprp) call2(ptype,
751*40230Sdonn 				ptype==TYCOMPLEX? "c_div" : "z_div",
752*40230Sdonn 				mkconv(ptype, lp), mkconv(ptype, rp) );
753*40230Sdonn 			break;
754*40230Sdonn 			}
755*40230Sdonn 	case OPPLUS:
756*40230Sdonn 	case OPMINUS:
757*40230Sdonn 	case OPSTAR:
758*40230Sdonn 	case OPMOD:
759*40230Sdonn #if TARGET == VAX
760*40230Sdonn 		if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
761*40230Sdonn 		    (rtype==TYREAL && ! rconst ) ))
762*40230Sdonn 			break;
763*40230Sdonn #endif
764*40230Sdonn 		if( ISCOMPLEX(ptype) )
765*40230Sdonn 			break;
766*40230Sdonn 		if(ltype != ptype)
767*40230Sdonn 			if (lconst)
768*40230Sdonn 				{
769*40230Sdonn 				p->leftp = fixtype(mkconv(ptype,
770*40230Sdonn 						cpexpr(lconst)));
771*40230Sdonn 				frexpr(lp);
772*40230Sdonn 				}
773*40230Sdonn 			else
774*40230Sdonn 				p->leftp = fixtype(mkconv(ptype,lp));
775*40230Sdonn 		if(rtype != ptype)
776*40230Sdonn 			if (rconst)
777*40230Sdonn 				{
778*40230Sdonn 				p->rightp = fixtype(mkconv(ptype,
779*40230Sdonn 						cpexpr(rconst)));
780*40230Sdonn 				frexpr(rp);
781*40230Sdonn 				}
782*40230Sdonn 			else
783*40230Sdonn 				p->rightp = fixtype(mkconv(ptype,rp));
784*40230Sdonn 		break;
785*40230Sdonn 
786*40230Sdonn 	case OPPOWER:
787*40230Sdonn 		return( mkpower(p) );
788*40230Sdonn 
789*40230Sdonn 	case OPLT:
790*40230Sdonn 	case OPLE:
791*40230Sdonn 	case OPGT:
792*40230Sdonn 	case OPGE:
793*40230Sdonn 	case OPEQ:
794*40230Sdonn 	case OPNE:
795*40230Sdonn 		if(ltype == rtype)
796*40230Sdonn 			break;
797*40230Sdonn 		mtype = cktype(OPMINUS, ltype, rtype);
798*40230Sdonn #if TARGET == VAX
799*40230Sdonn 		if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
800*40230Sdonn 		    (rtype==TYREAL && ! rconst) ))
801*40230Sdonn 			break;
802*40230Sdonn #endif
803*40230Sdonn 		if( ISCOMPLEX(mtype) )
804*40230Sdonn 			break;
805*40230Sdonn 		if(ltype != mtype)
806*40230Sdonn 			if (lconst)
807*40230Sdonn 				{
808*40230Sdonn 				p->leftp = fixtype(mkconv(mtype,
809*40230Sdonn 						cpexpr(lconst)));
810*40230Sdonn 				frexpr(lp);
811*40230Sdonn 				}
812*40230Sdonn 			else
813*40230Sdonn 				p->leftp = fixtype(mkconv(mtype,lp));
814*40230Sdonn 		if(rtype != mtype)
815*40230Sdonn 			if (rconst)
816*40230Sdonn 				{
817*40230Sdonn 				p->rightp = fixtype(mkconv(mtype,
818*40230Sdonn 						cpexpr(rconst)));
819*40230Sdonn 				frexpr(rp);
820*40230Sdonn 				}
821*40230Sdonn 			else
822*40230Sdonn 				p->rightp = fixtype(mkconv(mtype,rp));
823*40230Sdonn 		break;
824*40230Sdonn 
825*40230Sdonn 
826*40230Sdonn 	case OPCONV:
827*40230Sdonn 		if(ISCOMPLEX(p->vtype))
828*40230Sdonn 			{
829*40230Sdonn 			ptype = cktype(OPCONV, p->vtype, ltype);
830*40230Sdonn 			if(p->rightp)
831*40230Sdonn 				ptype = cktype(OPCONV, ptype, rtype);
832*40230Sdonn 			break;
833*40230Sdonn 			}
834*40230Sdonn 		ptype = cktype(OPCONV, p->vtype, ltype);
835*40230Sdonn 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
836*40230Sdonn 			{
837*40230Sdonn 			lp->exprblock.rightp =
838*40230Sdonn 				fixtype( mkconv(ptype, lp->exprblock.rightp) );
839*40230Sdonn 			free( (charptr) p );
840*40230Sdonn 			p = (Exprp) lp;
841*40230Sdonn 			}
842*40230Sdonn 		break;
843*40230Sdonn 
844*40230Sdonn 	case OPADDR:
845*40230Sdonn 		if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
846*40230Sdonn 			fatal("addr of addr");
847*40230Sdonn 		break;
848*40230Sdonn 
849*40230Sdonn 	case OPCOMMA:
850*40230Sdonn 	case OPQUEST:
851*40230Sdonn 	case OPCOLON:
852*40230Sdonn 		break;
853*40230Sdonn 
854*40230Sdonn 	case OPPAREN:
855*40230Sdonn 		p->vleng = (expptr) cpexpr( lp->headblock.vleng );
856*40230Sdonn 		break;
857*40230Sdonn 
858*40230Sdonn 	case OPMIN:
859*40230Sdonn 	case OPMAX:
860*40230Sdonn 		ptype = p->vtype;
861*40230Sdonn 		break;
862*40230Sdonn 
863*40230Sdonn 	default:
864*40230Sdonn 		break;
865*40230Sdonn 	}
866*40230Sdonn 
867*40230Sdonn p->vtype = ptype;
868*40230Sdonn frexpr(lconst);
869*40230Sdonn frexpr(rconst);
870*40230Sdonn return((expptr) p);
871*40230Sdonn }
872*40230Sdonn 
873*40230Sdonn #if SZINT < SZLONG
874*40230Sdonn /*
875*40230Sdonn    for efficient subscripting, replace long ints by shorts
876*40230Sdonn    in easy places
877*40230Sdonn */
878*40230Sdonn 
879*40230Sdonn expptr shorten(p)
880*40230Sdonn register expptr p;
881*40230Sdonn {
882*40230Sdonn register expptr q;
883*40230Sdonn 
884*40230Sdonn if(p->headblock.vtype != TYLONG)
885*40230Sdonn 	return(p);
886*40230Sdonn 
887*40230Sdonn switch(p->tag)
888*40230Sdonn 	{
889*40230Sdonn 	case TERROR:
890*40230Sdonn 	case TLIST:
891*40230Sdonn 		return(p);
892*40230Sdonn 
893*40230Sdonn 	case TCONST:
894*40230Sdonn 	case TADDR:
895*40230Sdonn 		return( mkconv(TYINT,p) );
896*40230Sdonn 
897*40230Sdonn 	case TEXPR:
898*40230Sdonn 		break;
899*40230Sdonn 
900*40230Sdonn 	default:
901*40230Sdonn 		badtag("shorten", p->tag);
902*40230Sdonn 	}
903*40230Sdonn 
904*40230Sdonn switch(p->exprblock.opcode)
905*40230Sdonn 	{
906*40230Sdonn 	case OPPLUS:
907*40230Sdonn 	case OPMINUS:
908*40230Sdonn 	case OPSTAR:
909*40230Sdonn 		q = shorten( cpexpr(p->exprblock.rightp) );
910*40230Sdonn 		if(q->headblock.vtype == TYINT)
911*40230Sdonn 			{
912*40230Sdonn 			p->exprblock.leftp = shorten(p->exprblock.leftp);
913*40230Sdonn 			if(p->exprblock.leftp->headblock.vtype == TYLONG)
914*40230Sdonn 				frexpr(q);
915*40230Sdonn 			else
916*40230Sdonn 				{
917*40230Sdonn 				frexpr(p->exprblock.rightp);
918*40230Sdonn 				p->exprblock.rightp = q;
919*40230Sdonn 				p->exprblock.vtype = TYINT;
920*40230Sdonn 				}
921*40230Sdonn 			}
922*40230Sdonn 		break;
923*40230Sdonn 
924*40230Sdonn 	case OPNEG:
925*40230Sdonn 	case OPPAREN:
926*40230Sdonn 		p->exprblock.leftp = shorten(p->exprblock.leftp);
927*40230Sdonn 		if(p->exprblock.leftp->headblock.vtype == TYINT)
928*40230Sdonn 			p->exprblock.vtype = TYINT;
929*40230Sdonn 		break;
930*40230Sdonn 
931*40230Sdonn 	case OPCALL:
932*40230Sdonn 	case OPCCALL:
933*40230Sdonn 		p = mkconv(TYINT,p);
934*40230Sdonn 		break;
935*40230Sdonn 	default:
936*40230Sdonn 		break;
937*40230Sdonn 	}
938*40230Sdonn 
939*40230Sdonn return(p);
940*40230Sdonn }
941*40230Sdonn #endif
942*40230Sdonn /* fix an argument list, taking due care for special first level cases */
943*40230Sdonn 
944*40230Sdonn fixargs(doput, p0)
945*40230Sdonn int doput;	/* doput is true if the function is not intrinsic;
946*40230Sdonn 		   was used to decide whether to do a putconst,
947*40230Sdonn 		   but this is no longer done here (Feb82)*/
948*40230Sdonn struct Listblock *p0;
949*40230Sdonn {
950*40230Sdonn register chainp p;
951*40230Sdonn register tagptr q, t;
952*40230Sdonn register int qtag;
953*40230Sdonn int nargs;
954*40230Sdonn Addrp mkscalar();
955*40230Sdonn 
956*40230Sdonn nargs = 0;
957*40230Sdonn if(p0)
958*40230Sdonn     for(p = p0->listp ; p ; p = p->nextp)
959*40230Sdonn 	{
960*40230Sdonn 	++nargs;
961*40230Sdonn 	q = p->datap;
962*40230Sdonn 	qtag = q->tag;
963*40230Sdonn 	if(qtag == TCONST)
964*40230Sdonn 		{
965*40230Sdonn 
966*40230Sdonn /*
967*40230Sdonn 		if(q->constblock.vtype == TYSHORT)
968*40230Sdonn 			q = (tagptr) mkconv(tyint, q);
969*40230Sdonn */
970*40230Sdonn 		p->datap = q ;
971*40230Sdonn 		}
972*40230Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
973*40230Sdonn 		q->primblock.namep->vclass==CLPROC)
974*40230Sdonn 			p->datap = (tagptr) mkaddr(q->primblock.namep);
975*40230Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
976*40230Sdonn 		q->primblock.namep->vdim!=NULL)
977*40230Sdonn 			p->datap = (tagptr) mkscalar(q->primblock.namep);
978*40230Sdonn 	else if(qtag==TPRIM && q->primblock.argsp==0 &&
979*40230Sdonn 		q->primblock.namep->vdovar &&
980*40230Sdonn 		(t = (tagptr) memversion(q->primblock.namep)) )
981*40230Sdonn 			p->datap = (tagptr) fixtype(t);
982*40230Sdonn 	else
983*40230Sdonn 		p->datap = (tagptr) fixtype(q);
984*40230Sdonn 	}
985*40230Sdonn return(nargs);
986*40230Sdonn }
987*40230Sdonn 
988*40230Sdonn 
989*40230Sdonn Addrp mkscalar(np)
990*40230Sdonn register Namep np;
991*40230Sdonn {
992*40230Sdonn register Addrp ap;
993*40230Sdonn 
994*40230Sdonn vardcl(np);
995*40230Sdonn ap = mkaddr(np);
996*40230Sdonn 
997*40230Sdonn #if TARGET == VAX || TARGET == TAHOE
998*40230Sdonn 	/* on the VAX, prolog causes array arguments
999*40230Sdonn 	   to point at the (0,...,0) element, except when
1000*40230Sdonn 	   subscript checking is on
1001*40230Sdonn 	*/
1002*40230Sdonn #ifdef SDB
1003*40230Sdonn 	if( !checksubs && !sdbflag && np->vstg==STGARG)
1004*40230Sdonn #else
1005*40230Sdonn 	if( !checksubs && np->vstg==STGARG)
1006*40230Sdonn #endif
1007*40230Sdonn 		{
1008*40230Sdonn 		register struct Dimblock *dp;
1009*40230Sdonn 		dp = np->vdim;
1010*40230Sdonn 		frexpr(ap->memoffset);
1011*40230Sdonn 		ap->memoffset = mkexpr(OPSTAR,
1012*40230Sdonn 				(np->vtype==TYCHAR ?
1013*40230Sdonn 					cpexpr(np->vleng) :
1014*40230Sdonn 					(tagptr)ICON(typesize[np->vtype]) ),
1015*40230Sdonn 				cpexpr(dp->baseoffset) );
1016*40230Sdonn 		}
1017*40230Sdonn #endif
1018*40230Sdonn return(ap);
1019*40230Sdonn }
1020*40230Sdonn 
1021*40230Sdonn 
1022*40230Sdonn 
1023*40230Sdonn 
1024*40230Sdonn 
1025*40230Sdonn expptr mkfunct(p)
1026*40230Sdonn register struct Primblock *p;
1027*40230Sdonn {
1028*40230Sdonn struct Entrypoint *ep;
1029*40230Sdonn Addrp ap;
1030*40230Sdonn struct Extsym *extp;
1031*40230Sdonn register Namep np;
1032*40230Sdonn register expptr q;
1033*40230Sdonn expptr intrcall(), stfcall();
1034*40230Sdonn int k, nargs;
1035*40230Sdonn int class;
1036*40230Sdonn 
1037*40230Sdonn if(p->tag != TPRIM)
1038*40230Sdonn 	return( errnode() );
1039*40230Sdonn 
1040*40230Sdonn np = p->namep;
1041*40230Sdonn class = np->vclass;
1042*40230Sdonn 
1043*40230Sdonn if(class == CLUNKNOWN)
1044*40230Sdonn 	{
1045*40230Sdonn 	np->vclass = class = CLPROC;
1046*40230Sdonn 	if(np->vstg == STGUNKNOWN)
1047*40230Sdonn 		{
1048*40230Sdonn 		if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
1049*40230Sdonn 			{
1050*40230Sdonn 			np->vstg = STGINTR;
1051*40230Sdonn 			np->vardesc.varno = k;
1052*40230Sdonn 			np->vprocclass = PINTRINSIC;
1053*40230Sdonn 			}
1054*40230Sdonn 		else
1055*40230Sdonn 			{
1056*40230Sdonn 			extp = mkext( varunder(VL,np->varname) );
1057*40230Sdonn 			if(extp->extstg == STGCOMMON)
1058*40230Sdonn 				warn("conflicting declarations", np->varname);
1059*40230Sdonn 			extp->extstg = STGEXT;
1060*40230Sdonn 			np->vstg = STGEXT;
1061*40230Sdonn 			np->vardesc.varno = extp - extsymtab;
1062*40230Sdonn 			np->vprocclass = PEXTERNAL;
1063*40230Sdonn 			}
1064*40230Sdonn 		}
1065*40230Sdonn 	else if(np->vstg==STGARG)
1066*40230Sdonn 		{
1067*40230Sdonn 		if(np->vtype!=TYCHAR && !ftn66flag)
1068*40230Sdonn 		    warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
1069*40230Sdonn 		np->vprocclass = PEXTERNAL;
1070*40230Sdonn 		}
1071*40230Sdonn 	}
1072*40230Sdonn 
1073*40230Sdonn if(class != CLPROC)
1074*40230Sdonn 	fatali("invalid class code %d for function", class);
1075*40230Sdonn if(p->fcharp || p->lcharp)
1076*40230Sdonn 	{
1077*40230Sdonn 	err("no substring of function call");
1078*40230Sdonn 	goto error;
1079*40230Sdonn 	}
1080*40230Sdonn impldcl(np);
1081*40230Sdonn nargs = fixargs( np->vprocclass!=PINTRINSIC,  p->argsp);
1082*40230Sdonn 
1083*40230Sdonn switch(np->vprocclass)
1084*40230Sdonn 	{
1085*40230Sdonn 	case PEXTERNAL:
1086*40230Sdonn 		ap = mkaddr(np);
1087*40230Sdonn 	call:
1088*40230Sdonn 		q = mkexpr(OPCALL, ap, p->argsp);
1089*40230Sdonn 		if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
1090*40230Sdonn 			{
1091*40230Sdonn 			err("attempt to use untyped function");
1092*40230Sdonn 			goto error;
1093*40230Sdonn 			}
1094*40230Sdonn 		if(np->vleng)
1095*40230Sdonn 			q->exprblock.vleng = (expptr) cpexpr(np->vleng);
1096*40230Sdonn 		break;
1097*40230Sdonn 
1098*40230Sdonn 	case PINTRINSIC:
1099*40230Sdonn 		q = intrcall(np, p->argsp, nargs);
1100*40230Sdonn 		break;
1101*40230Sdonn 
1102*40230Sdonn 	case PSTFUNCT:
1103*40230Sdonn 		q = stfcall(np, p->argsp);
1104*40230Sdonn 		break;
1105*40230Sdonn 
1106*40230Sdonn 	case PTHISPROC:
1107*40230Sdonn 		warn("recursive call");
1108*40230Sdonn 		for(ep = entries ; ep ; ep = ep->entnextp)
1109*40230Sdonn 			if(ep->enamep == np)
1110*40230Sdonn 				break;
1111*40230Sdonn 		if(ep == NULL)
1112*40230Sdonn 			fatal("mkfunct: impossible recursion");
1113*40230Sdonn 		ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
1114*40230Sdonn 		goto call;
1115*40230Sdonn 
1116*40230Sdonn 	default:
1117*40230Sdonn 		fatali("mkfunct: impossible vprocclass %d",
1118*40230Sdonn 			(int) (np->vprocclass) );
1119*40230Sdonn 	}
1120*40230Sdonn free( (charptr) p );
1121*40230Sdonn return(q);
1122*40230Sdonn 
1123*40230Sdonn error:
1124*40230Sdonn 	frexpr(p);
1125*40230Sdonn 	return( errnode() );
1126*40230Sdonn }
1127*40230Sdonn 
1128*40230Sdonn 
1129*40230Sdonn 
1130*40230Sdonn LOCAL expptr stfcall(np, actlist)
1131*40230Sdonn Namep np;
1132*40230Sdonn struct Listblock *actlist;
1133*40230Sdonn {
1134*40230Sdonn register chainp actuals;
1135*40230Sdonn int nargs;
1136*40230Sdonn chainp oactp, formals;
1137*40230Sdonn int type;
1138*40230Sdonn expptr q, rhs, ap;
1139*40230Sdonn Namep tnp;
1140*40230Sdonn register struct Rplblock *rp;
1141*40230Sdonn struct Rplblock *tlist;
1142*40230Sdonn 
1143*40230Sdonn if(actlist)
1144*40230Sdonn 	{
1145*40230Sdonn 	actuals = actlist->listp;
1146*40230Sdonn 	free( (charptr) actlist);
1147*40230Sdonn 	}
1148*40230Sdonn else
1149*40230Sdonn 	actuals = NULL;
1150*40230Sdonn oactp = actuals;
1151*40230Sdonn 
1152*40230Sdonn nargs = 0;
1153*40230Sdonn tlist = NULL;
1154*40230Sdonn if( (type = np->vtype) == TYUNKNOWN)
1155*40230Sdonn 	{
1156*40230Sdonn 	err("attempt to use untyped statement function");
1157*40230Sdonn 	q = errnode();
1158*40230Sdonn 	goto ret;
1159*40230Sdonn 	}
1160*40230Sdonn formals = (chainp) (np->varxptr.vstfdesc->datap);
1161*40230Sdonn rhs = (expptr) (np->varxptr.vstfdesc->nextp);
1162*40230Sdonn 
1163*40230Sdonn /* copy actual arguments into temporaries */
1164*40230Sdonn while(actuals!=NULL && formals!=NULL)
1165*40230Sdonn 	{
1166*40230Sdonn 	rp = ALLOC(Rplblock);
1167*40230Sdonn 	rp->rplnp = tnp = (Namep) (formals->datap);
1168*40230Sdonn 	ap = fixtype(actuals->datap);
1169*40230Sdonn 	if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
1170*40230Sdonn 	   && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
1171*40230Sdonn 		{
1172*40230Sdonn 		rp->rplvp = (expptr) ap;
1173*40230Sdonn 		rp->rplxp = NULL;
1174*40230Sdonn 		rp->rpltag = ap->tag;
1175*40230Sdonn 		}
1176*40230Sdonn 	else	{
1177*40230Sdonn 		rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
1178*40230Sdonn 		rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
1179*40230Sdonn 		if( (rp->rpltag = rp->rplxp->tag) == TERROR)
1180*40230Sdonn 			err("disagreement of argument types in statement function call");
1181*40230Sdonn 		else if(tnp->vtype!=ap->headblock.vtype)
1182*40230Sdonn 			warn("argument type mismatch in statement function");
1183*40230Sdonn 		}
1184*40230Sdonn 	rp->rplnextp = tlist;
1185*40230Sdonn 	tlist = rp;
1186*40230Sdonn 	actuals = actuals->nextp;
1187*40230Sdonn 	formals = formals->nextp;
1188*40230Sdonn 	++nargs;
1189*40230Sdonn 	}
1190*40230Sdonn 
1191*40230Sdonn if(actuals!=NULL || formals!=NULL)
1192*40230Sdonn 	err("statement function definition and argument list differ");
1193*40230Sdonn 
1194*40230Sdonn /*
1195*40230Sdonn    now push down names involved in formal argument list, then
1196*40230Sdonn    evaluate rhs of statement function definition in this environment
1197*40230Sdonn */
1198*40230Sdonn 
1199*40230Sdonn if(tlist)	/* put tlist in front of the rpllist */
1200*40230Sdonn 	{
1201*40230Sdonn 	for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
1202*40230Sdonn 		;
1203*40230Sdonn 	rp->rplnextp = rpllist;
1204*40230Sdonn 	rpllist = tlist;
1205*40230Sdonn 	}
1206*40230Sdonn 
1207*40230Sdonn q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
1208*40230Sdonn 
1209*40230Sdonn /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
1210*40230Sdonn while(--nargs >= 0)
1211*40230Sdonn 	{
1212*40230Sdonn 	if(rpllist->rplxp)
1213*40230Sdonn 		q = mkexpr(OPCOMMA, rpllist->rplxp, q);
1214*40230Sdonn 	rp = rpllist->rplnextp;
1215*40230Sdonn 	frexpr(rpllist->rplvp);
1216*40230Sdonn 	free(rpllist);
1217*40230Sdonn 	rpllist = rp;
1218*40230Sdonn 	}
1219*40230Sdonn 
1220*40230Sdonn ret:
1221*40230Sdonn 	frchain( &oactp );
1222*40230Sdonn 	return(q);
1223*40230Sdonn }
1224*40230Sdonn 
1225*40230Sdonn 
1226*40230Sdonn 
1227*40230Sdonn 
1228*40230Sdonn Addrp mkplace(np)
1229*40230Sdonn register Namep np;
1230*40230Sdonn {
1231*40230Sdonn register Addrp s;
1232*40230Sdonn register struct Rplblock *rp;
1233*40230Sdonn int regn;
1234*40230Sdonn 
1235*40230Sdonn /* is name on the replace list? */
1236*40230Sdonn 
1237*40230Sdonn for(rp = rpllist ; rp ; rp = rp->rplnextp)
1238*40230Sdonn 	{
1239*40230Sdonn 	if(np == rp->rplnp)
1240*40230Sdonn 		{
1241*40230Sdonn 		if(rp->rpltag == TNAME)
1242*40230Sdonn 			{
1243*40230Sdonn 			np = (Namep) (rp->rplvp);
1244*40230Sdonn 			break;
1245*40230Sdonn 			}
1246*40230Sdonn 		else	return( (Addrp) cpexpr(rp->rplvp) );
1247*40230Sdonn 		}
1248*40230Sdonn 	}
1249*40230Sdonn 
1250*40230Sdonn /* is variable a DO index in a register ? */
1251*40230Sdonn 
1252*40230Sdonn if(np->vdovar && ( (regn = inregister(np)) >= 0) )
1253*40230Sdonn 	if(np->vtype == TYERROR)
1254*40230Sdonn 		return( (Addrp) errnode() );
1255*40230Sdonn 	else
1256*40230Sdonn 		{
1257*40230Sdonn 		s = ALLOC(Addrblock);
1258*40230Sdonn 		s->tag = TADDR;
1259*40230Sdonn 		s->vstg = STGREG;
1260*40230Sdonn 		s->vtype = TYIREG;
1261*40230Sdonn 		s->issaved = np->vsave;
1262*40230Sdonn 		s->memno = regn;
1263*40230Sdonn 		s->memoffset = ICON(0);
1264*40230Sdonn 		return(s);
1265*40230Sdonn 		}
1266*40230Sdonn 
1267*40230Sdonn vardcl(np);
1268*40230Sdonn return(mkaddr(np));
1269*40230Sdonn }
1270*40230Sdonn 
1271*40230Sdonn 
1272*40230Sdonn 
1273*40230Sdonn 
1274*40230Sdonn expptr mklhs(p)
1275*40230Sdonn register struct Primblock *p;
1276*40230Sdonn {
1277*40230Sdonn expptr suboffset();
1278*40230Sdonn register Addrp s;
1279*40230Sdonn Namep np;
1280*40230Sdonn 
1281*40230Sdonn if(p->tag != TPRIM)
1282*40230Sdonn 	return( (expptr) p );
1283*40230Sdonn np = p->namep;
1284*40230Sdonn 
1285*40230Sdonn s = mkplace(np);
1286*40230Sdonn if(s->tag!=TADDR || s->vstg==STGREG)
1287*40230Sdonn 	{
1288*40230Sdonn 	free( (charptr) p );
1289*40230Sdonn 	return( (expptr) s );
1290*40230Sdonn 	}
1291*40230Sdonn 
1292*40230Sdonn /* compute the address modified by subscripts */
1293*40230Sdonn 
1294*40230Sdonn s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
1295*40230Sdonn frexpr(p->argsp);
1296*40230Sdonn p->argsp = NULL;
1297*40230Sdonn 
1298*40230Sdonn /* now do substring part */
1299*40230Sdonn 
1300*40230Sdonn if(p->fcharp || p->lcharp)
1301*40230Sdonn 	{
1302*40230Sdonn 	if(np->vtype != TYCHAR)
1303*40230Sdonn 		errstr("substring of noncharacter %s", varstr(VL,np->varname));
1304*40230Sdonn 	else	{
1305*40230Sdonn 		if(p->lcharp == NULL)
1306*40230Sdonn 			p->lcharp = (expptr) cpexpr(s->vleng);
1307*40230Sdonn 		frexpr(s->vleng);
1308*40230Sdonn 		if(p->fcharp)
1309*40230Sdonn 			{
1310*40230Sdonn 			if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
1311*40230Sdonn 			&& p->fcharp->primblock.namep == p->lcharp->primblock.namep)
1312*40230Sdonn 				/* A trivial optimization -- upper == lower */
1313*40230Sdonn 				s->vleng = ICON(1);
1314*40230Sdonn 			else
1315*40230Sdonn 				s->vleng = mkexpr(OPMINUS, p->lcharp,
1316*40230Sdonn 					mkexpr(OPMINUS, p->fcharp, ICON(1) ));
1317*40230Sdonn 			}
1318*40230Sdonn 		else
1319*40230Sdonn 			s->vleng = p->lcharp;
1320*40230Sdonn 		}
1321*40230Sdonn 	}
1322*40230Sdonn 
1323*40230Sdonn s->vleng = fixtype( s->vleng );
1324*40230Sdonn s->memoffset = fixtype( s->memoffset );
1325*40230Sdonn free( (charptr) p );
1326*40230Sdonn return( (expptr) s );
1327*40230Sdonn }
1328*40230Sdonn 
1329*40230Sdonn 
1330*40230Sdonn 
1331*40230Sdonn 
1332*40230Sdonn 
1333*40230Sdonn deregister(np)
1334*40230Sdonn Namep np;
1335*40230Sdonn {
1336*40230Sdonn if(nregvar>0 && regnamep[nregvar-1]==np)
1337*40230Sdonn 	{
1338*40230Sdonn 	--nregvar;
1339*40230Sdonn #if FAMILY == DMR
1340*40230Sdonn 	putnreg();
1341*40230Sdonn #endif
1342*40230Sdonn 	}
1343*40230Sdonn }
1344*40230Sdonn 
1345*40230Sdonn 
1346*40230Sdonn 
1347*40230Sdonn 
1348*40230Sdonn Addrp memversion(np)
1349*40230Sdonn register Namep np;
1350*40230Sdonn {
1351*40230Sdonn register Addrp s;
1352*40230Sdonn 
1353*40230Sdonn if(np->vdovar==NO || (inregister(np)<0) )
1354*40230Sdonn 	return(NULL);
1355*40230Sdonn np->vdovar = NO;
1356*40230Sdonn s = mkplace(np);
1357*40230Sdonn np->vdovar = YES;
1358*40230Sdonn return(s);
1359*40230Sdonn }
1360*40230Sdonn 
1361*40230Sdonn 
1362*40230Sdonn 
1363*40230Sdonn inregister(np)
1364*40230Sdonn register Namep np;
1365*40230Sdonn {
1366*40230Sdonn register int i;
1367*40230Sdonn 
1368*40230Sdonn for(i = 0 ; i < nregvar ; ++i)
1369*40230Sdonn 	if(regnamep[i] == np)
1370*40230Sdonn 		return( regnum[i] );
1371*40230Sdonn return(-1);
1372*40230Sdonn }
1373*40230Sdonn 
1374*40230Sdonn 
1375*40230Sdonn 
1376*40230Sdonn 
1377*40230Sdonn enregister(np)
1378*40230Sdonn Namep np;
1379*40230Sdonn {
1380*40230Sdonn if( inregister(np) >= 0)
1381*40230Sdonn 	return(YES);
1382*40230Sdonn if(nregvar >= maxregvar)
1383*40230Sdonn 	return(NO);
1384*40230Sdonn vardcl(np);
1385*40230Sdonn if( ONEOF(np->vtype, MSKIREG) )
1386*40230Sdonn 	{
1387*40230Sdonn 	regnamep[nregvar++] = np;
1388*40230Sdonn 	if(nregvar > highregvar)
1389*40230Sdonn 		highregvar = nregvar;
1390*40230Sdonn #if FAMILY == DMR
1391*40230Sdonn 	putnreg();
1392*40230Sdonn #endif
1393*40230Sdonn 	return(YES);
1394*40230Sdonn 	}
1395*40230Sdonn else
1396*40230Sdonn 	return(NO);
1397*40230Sdonn }
1398*40230Sdonn 
1399*40230Sdonn 
1400*40230Sdonn 
1401*40230Sdonn 
1402*40230Sdonn expptr suboffset(p)
1403*40230Sdonn register struct Primblock *p;
1404*40230Sdonn {
1405*40230Sdonn int n;
1406*40230Sdonn expptr size;
1407*40230Sdonn expptr oftwo();
1408*40230Sdonn chainp cp;
1409*40230Sdonn expptr offp, prod;
1410*40230Sdonn expptr subcheck();
1411*40230Sdonn struct Dimblock *dimp;
1412*40230Sdonn expptr sub[MAXDIM+1];
1413*40230Sdonn register Namep np;
1414*40230Sdonn 
1415*40230Sdonn np = p->namep;
1416*40230Sdonn offp = ICON(0);
1417*40230Sdonn n = 0;
1418*40230Sdonn if(p->argsp)
1419*40230Sdonn 	for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
1420*40230Sdonn 		{
1421*40230Sdonn 		sub[n] = fixtype(cpexpr(cp->datap));
1422*40230Sdonn 		if ( ! ISINT(sub[n]->headblock.vtype)) {
1423*40230Sdonn 			errstr("%s: non-integer subscript expression",
1424*40230Sdonn 				varstr(VL, np->varname) );
1425*40230Sdonn 			/* Provide a substitute -- go on to find more errors */
1426*40230Sdonn 			frexpr(sub[n]);
1427*40230Sdonn 			sub[n] = ICON(1);
1428*40230Sdonn 		}
1429*40230Sdonn 		if(n > maxdim)
1430*40230Sdonn 			{
1431*40230Sdonn 			   char str[28+VL];
1432*40230Sdonn 			   sprintf(str, "%s: more than %d subscripts",
1433*40230Sdonn 				varstr(VL, np->varname), maxdim );
1434*40230Sdonn 			   err( str );
1435*40230Sdonn 			break;
1436*40230Sdonn 			}
1437*40230Sdonn 		}
1438*40230Sdonn 
1439*40230Sdonn dimp = np->vdim;
1440*40230Sdonn if(n>0 && dimp==NULL)
1441*40230Sdonn 	errstr("%s: subscripts on scalar variable",
1442*40230Sdonn 		varstr(VL, np->varname), maxdim );
1443*40230Sdonn else if(dimp && dimp->ndim!=n)
1444*40230Sdonn 	errstr("wrong number of subscripts on %s",
1445*40230Sdonn 		varstr(VL, np->varname) );
1446*40230Sdonn else if(n > 0)
1447*40230Sdonn 	{
1448*40230Sdonn 	prod = sub[--n];
1449*40230Sdonn 	while( --n >= 0)
1450*40230Sdonn 		prod = mkexpr(OPPLUS, sub[n],
1451*40230Sdonn 			mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
1452*40230Sdonn #if TARGET == VAX || TARGET == TAHOE
1453*40230Sdonn #ifdef SDB
1454*40230Sdonn 	if(checksubs || np->vstg!=STGARG || sdbflag)
1455*40230Sdonn #else
1456*40230Sdonn 	if(checksubs || np->vstg!=STGARG)
1457*40230Sdonn #endif
1458*40230Sdonn 		prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1459*40230Sdonn #else
1460*40230Sdonn 	prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1461*40230Sdonn #endif
1462*40230Sdonn 	if(checksubs)
1463*40230Sdonn 		prod = subcheck(np, prod);
1464*40230Sdonn 	size = np->vtype == TYCHAR ?
1465*40230Sdonn 		(expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
1466*40230Sdonn 	if (!oftwo(size))
1467*40230Sdonn 		prod = mkexpr(OPSTAR, prod, size);
1468*40230Sdonn 	else
1469*40230Sdonn 		prod = mkexpr(OPLSHIFT,prod,oftwo(size));
1470*40230Sdonn 
1471*40230Sdonn 	offp = mkexpr(OPPLUS, offp, prod);
1472*40230Sdonn 	}
1473*40230Sdonn 
1474*40230Sdonn if(p->fcharp && np->vtype==TYCHAR)
1475*40230Sdonn 	offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
1476*40230Sdonn 
1477*40230Sdonn return(offp);
1478*40230Sdonn }
1479*40230Sdonn 
1480*40230Sdonn 
1481*40230Sdonn 
1482*40230Sdonn 
1483*40230Sdonn expptr subcheck(np, p)
1484*40230Sdonn Namep np;
1485*40230Sdonn register expptr p;
1486*40230Sdonn {
1487*40230Sdonn struct Dimblock *dimp;
1488*40230Sdonn expptr t, checkvar, checkcond, badcall;
1489*40230Sdonn 
1490*40230Sdonn dimp = np->vdim;
1491*40230Sdonn if(dimp->nelt == NULL)
1492*40230Sdonn 	return(p);	/* don't check arrays with * bounds */
1493*40230Sdonn checkvar = NULL;
1494*40230Sdonn checkcond = NULL;
1495*40230Sdonn if( ISICON(p) )
1496*40230Sdonn 	{
1497*40230Sdonn 	if(p->constblock.const.ci < 0)
1498*40230Sdonn 		goto badsub;
1499*40230Sdonn 	if( ISICON(dimp->nelt) )
1500*40230Sdonn 		if(p->constblock.const.ci < dimp->nelt->constblock.const.ci)
1501*40230Sdonn 			return(p);
1502*40230Sdonn 		else
1503*40230Sdonn 			goto badsub;
1504*40230Sdonn 	}
1505*40230Sdonn if(p->tag==TADDR && p->addrblock.vstg==STGREG)
1506*40230Sdonn 	{
1507*40230Sdonn 	checkvar = (expptr) cpexpr(p);
1508*40230Sdonn 	t = p;
1509*40230Sdonn 	}
1510*40230Sdonn else	{
1511*40230Sdonn 	checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
1512*40230Sdonn 	t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
1513*40230Sdonn 	}
1514*40230Sdonn checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
1515*40230Sdonn if( ! ISICON(p) )
1516*40230Sdonn 	checkcond = mkexpr(OPAND, checkcond,
1517*40230Sdonn 			mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
1518*40230Sdonn 
1519*40230Sdonn badcall = call4(p->headblock.vtype, "s_rnge",
1520*40230Sdonn 		mkstrcon(VL, np->varname),
1521*40230Sdonn 		mkconv(TYLONG,  cpexpr(checkvar)),
1522*40230Sdonn 		mkstrcon(XL, procname),
1523*40230Sdonn 		ICON(lineno) );
1524*40230Sdonn badcall->exprblock.opcode = OPCCALL;
1525*40230Sdonn p = mkexpr(OPQUEST, checkcond,
1526*40230Sdonn 	mkexpr(OPCOLON, checkvar, badcall));
1527*40230Sdonn 
1528*40230Sdonn return(p);
1529*40230Sdonn 
1530*40230Sdonn badsub:
1531*40230Sdonn 	frexpr(p);
1532*40230Sdonn 	errstr("subscript on variable %s out of range", varstr(VL,np->varname));
1533*40230Sdonn 	return ( ICON(0) );
1534*40230Sdonn }
1535*40230Sdonn 
1536*40230Sdonn 
1537*40230Sdonn 
1538*40230Sdonn 
1539*40230Sdonn Addrp mkaddr(p)
1540*40230Sdonn register Namep p;
1541*40230Sdonn {
1542*40230Sdonn struct Extsym *extp;
1543*40230Sdonn register Addrp t;
1544*40230Sdonn Addrp intraddr();
1545*40230Sdonn 
1546*40230Sdonn switch( p->vstg)
1547*40230Sdonn 	{
1548*40230Sdonn 	case STGUNKNOWN:
1549*40230Sdonn 		if(p->vclass != CLPROC)
1550*40230Sdonn 			break;
1551*40230Sdonn 		extp = mkext( varunder(VL, p->varname) );
1552*40230Sdonn 		extp->extstg = STGEXT;
1553*40230Sdonn 		p->vstg = STGEXT;
1554*40230Sdonn 		p->vardesc.varno = extp - extsymtab;
1555*40230Sdonn 		p->vprocclass = PEXTERNAL;
1556*40230Sdonn 
1557*40230Sdonn 	case STGCOMMON:
1558*40230Sdonn 	case STGEXT:
1559*40230Sdonn 	case STGBSS:
1560*40230Sdonn 	case STGINIT:
1561*40230Sdonn 	case STGEQUIV:
1562*40230Sdonn 	case STGARG:
1563*40230Sdonn 	case STGLENG:
1564*40230Sdonn 	case STGAUTO:
1565*40230Sdonn 		t = ALLOC(Addrblock);
1566*40230Sdonn 		t->tag = TADDR;
1567*40230Sdonn 		if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
1568*40230Sdonn 			t->vclass = CLVAR;
1569*40230Sdonn 		else
1570*40230Sdonn 			t->vclass = p->vclass;
1571*40230Sdonn 		t->vtype = p->vtype;
1572*40230Sdonn 		t->vstg = p->vstg;
1573*40230Sdonn 		t->memno = p->vardesc.varno;
1574*40230Sdonn 		t->issaved = p->vsave;
1575*40230Sdonn                 if(p->vdim) t->isarray = YES;
1576*40230Sdonn 		t->memoffset = ICON(p->voffset);
1577*40230Sdonn 		if(p->vleng)
1578*40230Sdonn 			{
1579*40230Sdonn 			t->vleng = (expptr) cpexpr(p->vleng);
1580*40230Sdonn 			if( ISICON(t->vleng) )
1581*40230Sdonn 				t->varleng = t->vleng->constblock.const.ci;
1582*40230Sdonn 			}
1583*40230Sdonn 		if (p->vstg == STGBSS)
1584*40230Sdonn 			t->varsize = p->varsize;
1585*40230Sdonn 		else if (p->vstg == STGEQUIV)
1586*40230Sdonn 			t->varsize = eqvclass[t->memno].eqvleng;
1587*40230Sdonn 		return(t);
1588*40230Sdonn 
1589*40230Sdonn 	case STGINTR:
1590*40230Sdonn 		return( intraddr(p) );
1591*40230Sdonn 
1592*40230Sdonn 	}
1593*40230Sdonn /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
1594*40230Sdonn badstg("mkaddr", p->vstg);
1595*40230Sdonn /* NOTREACHED */
1596*40230Sdonn }
1597*40230Sdonn 
1598*40230Sdonn 
1599*40230Sdonn 
1600*40230Sdonn 
1601*40230Sdonn Addrp mkarg(type, argno)
1602*40230Sdonn int type, argno;
1603*40230Sdonn {
1604*40230Sdonn register Addrp p;
1605*40230Sdonn 
1606*40230Sdonn p = ALLOC(Addrblock);
1607*40230Sdonn p->tag = TADDR;
1608*40230Sdonn p->vtype = type;
1609*40230Sdonn p->vclass = CLVAR;
1610*40230Sdonn p->vstg = (type==TYLENG ? STGLENG : STGARG);
1611*40230Sdonn p->memno = argno;
1612*40230Sdonn return(p);
1613*40230Sdonn }
1614*40230Sdonn 
1615*40230Sdonn 
1616*40230Sdonn 
1617*40230Sdonn 
1618*40230Sdonn expptr mkprim(v, args, substr)
1619*40230Sdonn register union
1620*40230Sdonn 	{
1621*40230Sdonn 	struct Paramblock paramblock;
1622*40230Sdonn 	struct Nameblock nameblock;
1623*40230Sdonn 	struct Headblock headblock;
1624*40230Sdonn 	} *v;
1625*40230Sdonn struct Listblock *args;
1626*40230Sdonn chainp substr;
1627*40230Sdonn {
1628*40230Sdonn register struct Primblock *p;
1629*40230Sdonn 
1630*40230Sdonn if(v->headblock.vclass == CLPARAM)
1631*40230Sdonn 	{
1632*40230Sdonn 	if(args || substr)
1633*40230Sdonn 		{
1634*40230Sdonn 		errstr("no qualifiers on parameter name %s",
1635*40230Sdonn 			varstr(VL,v->paramblock.varname));
1636*40230Sdonn 		frexpr(args);
1637*40230Sdonn 		if(substr)
1638*40230Sdonn 			{
1639*40230Sdonn 			frexpr(substr->datap);
1640*40230Sdonn 			frexpr(substr->nextp->datap);
1641*40230Sdonn 			frchain(&substr);
1642*40230Sdonn 			}
1643*40230Sdonn 		frexpr(v);
1644*40230Sdonn 		return( errnode() );
1645*40230Sdonn 		}
1646*40230Sdonn 	return( (expptr) cpexpr(v->paramblock.paramval) );
1647*40230Sdonn 	}
1648*40230Sdonn 
1649*40230Sdonn p = ALLOC(Primblock);
1650*40230Sdonn p->tag = TPRIM;
1651*40230Sdonn p->vtype = v->nameblock.vtype;
1652*40230Sdonn p->namep = (Namep) v;
1653*40230Sdonn p->argsp = args;
1654*40230Sdonn if(substr)
1655*40230Sdonn 	{
1656*40230Sdonn 	p->fcharp = (expptr) substr->datap;
1657*40230Sdonn 	if (p->fcharp != ENULL && ! ISINT(p->fcharp.headblock->vtype))
1658*40230Sdonn 		p->fcharp = mkconv(TYINT, p->fcharp);
1659*40230Sdonn 	p->lcharp = (expptr) substr->nextp->datap;
1660*40230Sdonn 	if (p->lcharp != ENULL && ! ISINT(p->lcharp.headblock->vtype))
1661*40230Sdonn 		p->lcharp = mkconv(TYINT, p->lcharp);
1662*40230Sdonn 	frchain(&substr);
1663*40230Sdonn 	}
1664*40230Sdonn return( (expptr) p);
1665*40230Sdonn }
1666*40230Sdonn 
1667*40230Sdonn 
1668*40230Sdonn 
1669*40230Sdonn vardcl(v)
1670*40230Sdonn register Namep v;
1671*40230Sdonn {
1672*40230Sdonn int nelt;
1673*40230Sdonn struct Dimblock *t;
1674*40230Sdonn Addrp p;
1675*40230Sdonn expptr neltp;
1676*40230Sdonn int eltsize;
1677*40230Sdonn int varsize;
1678*40230Sdonn int tsize;
1679*40230Sdonn int align;
1680*40230Sdonn 
1681*40230Sdonn if(v->vdcldone)
1682*40230Sdonn 	return;
1683*40230Sdonn if(v->vclass == CLNAMELIST)
1684*40230Sdonn 	return;
1685*40230Sdonn 
1686*40230Sdonn if(v->vtype == TYUNKNOWN)
1687*40230Sdonn 	impldcl(v);
1688*40230Sdonn if(v->vclass == CLUNKNOWN)
1689*40230Sdonn 	v->vclass = CLVAR;
1690*40230Sdonn else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
1691*40230Sdonn 	{
1692*40230Sdonn 	dclerr("used both as variable and non-variable", v);
1693*40230Sdonn 	return;
1694*40230Sdonn 	}
1695*40230Sdonn if(v->vstg==STGUNKNOWN)
1696*40230Sdonn 	v->vstg = implstg[ letter(v->varname[0]) ];
1697*40230Sdonn 
1698*40230Sdonn switch(v->vstg)
1699*40230Sdonn 	{
1700*40230Sdonn 	case STGBSS:
1701*40230Sdonn 		v->vardesc.varno = ++lastvarno;
1702*40230Sdonn 		if (v->vclass != CLVAR)
1703*40230Sdonn 			break;
1704*40230Sdonn 		nelt = 1;
1705*40230Sdonn 		t = v->vdim;
1706*40230Sdonn 		if (t)
1707*40230Sdonn 			{
1708*40230Sdonn 			neltp = t->nelt;
1709*40230Sdonn 			if (neltp && ISICON(neltp))
1710*40230Sdonn 				nelt = neltp->constblock.const.ci;
1711*40230Sdonn 			else
1712*40230Sdonn 				dclerr("improperly dimensioned array", v);
1713*40230Sdonn 			}
1714*40230Sdonn 
1715*40230Sdonn 		if (v->vtype == TYCHAR)
1716*40230Sdonn 			{
1717*40230Sdonn 			v->vleng = fixtype(v->vleng);
1718*40230Sdonn 			if (v->vleng == NULL)
1719*40230Sdonn 				eltsize = typesize[TYCHAR];
1720*40230Sdonn 			else if (ISICON(v->vleng))
1721*40230Sdonn 				eltsize = typesize[TYCHAR] *
1722*40230Sdonn 					v->vleng->constblock.const.ci;
1723*40230Sdonn 			else if (v->vleng->tag != TERROR)
1724*40230Sdonn 				{
1725*40230Sdonn 				errstr("nonconstant string length on %s",
1726*40230Sdonn 					varstr(VL, v->varname));
1727*40230Sdonn 				eltsize = 0;
1728*40230Sdonn 				}
1729*40230Sdonn 			}
1730*40230Sdonn 		else
1731*40230Sdonn 			eltsize = typesize[v->vtype];
1732*40230Sdonn 
1733*40230Sdonn 		v->varsize = nelt * eltsize;
1734*40230Sdonn 		break;
1735*40230Sdonn 	case STGAUTO:
1736*40230Sdonn 		if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
1737*40230Sdonn 			break;
1738*40230Sdonn 		nelt = 1;
1739*40230Sdonn 		if(t = v->vdim)
1740*40230Sdonn 			if( (neltp = t->nelt) && ISCONST(neltp) )
1741*40230Sdonn 				nelt = neltp->constblock.const.ci;
1742*40230Sdonn 			else
1743*40230Sdonn 				dclerr("adjustable automatic array", v);
1744*40230Sdonn 		p = autovar(nelt, v->vtype, v->vleng);
1745*40230Sdonn 		v->vardesc.varno = p->memno;
1746*40230Sdonn 		v->voffset = p->memoffset->constblock.const.ci;
1747*40230Sdonn 		frexpr(p);
1748*40230Sdonn 		break;
1749*40230Sdonn 
1750*40230Sdonn 	default:
1751*40230Sdonn 		break;
1752*40230Sdonn 	}
1753*40230Sdonn v->vdcldone = YES;
1754*40230Sdonn }
1755*40230Sdonn 
1756*40230Sdonn 
1757*40230Sdonn 
1758*40230Sdonn 
1759*40230Sdonn impldcl(p)
1760*40230Sdonn register Namep p;
1761*40230Sdonn {
1762*40230Sdonn register int k;
1763*40230Sdonn int type, leng;
1764*40230Sdonn 
1765*40230Sdonn if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
1766*40230Sdonn 	return;
1767*40230Sdonn if(p->vtype == TYUNKNOWN)
1768*40230Sdonn 	{
1769*40230Sdonn 	k = letter(p->varname[0]);
1770*40230Sdonn 	type = impltype[ k ];
1771*40230Sdonn 	leng = implleng[ k ];
1772*40230Sdonn 	if(type == TYUNKNOWN)
1773*40230Sdonn 		{
1774*40230Sdonn 		if(p->vclass == CLPROC)
1775*40230Sdonn 			dclerr("attempt to use function of undefined type", p);
1776*40230Sdonn 		else
1777*40230Sdonn 			dclerr("attempt to use undefined variable", p);
1778*40230Sdonn 		type = TYERROR;
1779*40230Sdonn 		leng = 1;
1780*40230Sdonn 		}
1781*40230Sdonn 	settype(p, type, leng);
1782*40230Sdonn 	}
1783*40230Sdonn }
1784*40230Sdonn 
1785*40230Sdonn 
1786*40230Sdonn 
1787*40230Sdonn 
1788*40230Sdonn LOCAL letter(c)
1789*40230Sdonn register int c;
1790*40230Sdonn {
1791*40230Sdonn if( isupper(c) )
1792*40230Sdonn 	c = tolower(c);
1793*40230Sdonn return(c - 'a');
1794*40230Sdonn }
1795*40230Sdonn 
1796*40230Sdonn #define ICONEQ(z, c)  (ISICON(z) && z->constblock.const.ci==c)
1797*40230Sdonn #define COMMUTE	{ e = lp;  lp = rp;  rp = e; }
1798*40230Sdonn 
1799*40230Sdonn 
1800*40230Sdonn expptr mkexpr(opcode, lp, rp)
1801*40230Sdonn int opcode;
1802*40230Sdonn register expptr lp, rp;
1803*40230Sdonn {
1804*40230Sdonn register expptr e, e1;
1805*40230Sdonn int etype;
1806*40230Sdonn int ltype, rtype;
1807*40230Sdonn int ltag, rtag;
1808*40230Sdonn expptr q, q1;
1809*40230Sdonn expptr fold();
1810*40230Sdonn int k;
1811*40230Sdonn 
1812*40230Sdonn ltype = lp->headblock.vtype;
1813*40230Sdonn ltag = lp->tag;
1814*40230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1815*40230Sdonn 	{
1816*40230Sdonn 	rtype = rp->headblock.vtype;
1817*40230Sdonn 	rtag = rp->tag;
1818*40230Sdonn 	}
1819*40230Sdonn else	{
1820*40230Sdonn 	rtype = 0;
1821*40230Sdonn 	rtag = 0;
1822*40230Sdonn 	}
1823*40230Sdonn 
1824*40230Sdonn /*
1825*40230Sdonn  * Yuck.  Why can't we fold constants AFTER
1826*40230Sdonn  * variables are implicitly declared???
1827*40230Sdonn  */
1828*40230Sdonn if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
1829*40230Sdonn 	{
1830*40230Sdonn 	k = letter(lp->primblock.namep->varname[0]);
1831*40230Sdonn 	ltype = impltype[ k ];
1832*40230Sdonn 	}
1833*40230Sdonn if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
1834*40230Sdonn 	{
1835*40230Sdonn 	k = letter(rp->primblock.namep->varname[0]);
1836*40230Sdonn 	rtype = impltype[ k ];
1837*40230Sdonn 	}
1838*40230Sdonn 
1839*40230Sdonn etype = cktype(opcode, ltype, rtype);
1840*40230Sdonn if(etype == TYERROR)
1841*40230Sdonn 	goto error;
1842*40230Sdonn 
1843*40230Sdonn if(etype != TYUNKNOWN)
1844*40230Sdonn switch(opcode)
1845*40230Sdonn 	{
1846*40230Sdonn 	/* check for multiplication by 0 and 1 and addition to 0 */
1847*40230Sdonn 
1848*40230Sdonn 	case OPSTAR:
1849*40230Sdonn 		if( ISCONST(lp) )
1850*40230Sdonn 			COMMUTE
1851*40230Sdonn 
1852*40230Sdonn 		if( ISICON(rp) )
1853*40230Sdonn 			{
1854*40230Sdonn 			if(rp->constblock.const.ci == 0)
1855*40230Sdonn 				{
1856*40230Sdonn 				if(etype == TYUNKNOWN)
1857*40230Sdonn 					break;
1858*40230Sdonn 				rp = mkconv(etype, rp);
1859*40230Sdonn 				goto retright;
1860*40230Sdonn 				}
1861*40230Sdonn 			if ((lp->tag == TEXPR) &&
1862*40230Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
1863*40230Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
1864*40230Sdonn 			    ISCONST(lp->exprblock.rightp) &&
1865*40230Sdonn 			    ISINT(lp->exprblock.rightp->constblock.vtype))
1866*40230Sdonn 				{
1867*40230Sdonn 				q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
1868*40230Sdonn 					   cpexpr(rp));
1869*40230Sdonn 				q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
1870*40230Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
1871*40230Sdonn 				free ((char *) lp);
1872*40230Sdonn 				return q;
1873*40230Sdonn 				}
1874*40230Sdonn 			else
1875*40230Sdonn 				goto mulop;
1876*40230Sdonn 			}
1877*40230Sdonn 		break;
1878*40230Sdonn 
1879*40230Sdonn 	case OPSLASH:
1880*40230Sdonn 	case OPMOD:
1881*40230Sdonn 		if( ICONEQ(rp, 0) )
1882*40230Sdonn 			{
1883*40230Sdonn 			err("attempted division by zero");
1884*40230Sdonn 			rp = ICON(1);
1885*40230Sdonn 			break;
1886*40230Sdonn 			}
1887*40230Sdonn 		if(opcode == OPMOD)
1888*40230Sdonn 			break;
1889*40230Sdonn 
1890*40230Sdonn 
1891*40230Sdonn 	mulop:
1892*40230Sdonn 		if( ISICON(rp) )
1893*40230Sdonn 			{
1894*40230Sdonn 			if(rp->constblock.const.ci == 1)
1895*40230Sdonn 				goto retleft;
1896*40230Sdonn 
1897*40230Sdonn 			if(rp->constblock.const.ci == -1)
1898*40230Sdonn 				{
1899*40230Sdonn 				frexpr(rp);
1900*40230Sdonn 				return( mkexpr(OPNEG, lp, PNULL) );
1901*40230Sdonn 				}
1902*40230Sdonn 			}
1903*40230Sdonn 
1904*40230Sdonn 		if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
1905*40230Sdonn 			{
1906*40230Sdonn 			if(opcode == OPSTAR)
1907*40230Sdonn 				e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
1908*40230Sdonn 			else  if(ISICON(rp) &&
1909*40230Sdonn 				(lp->exprblock.rightp->constblock.const.ci %
1910*40230Sdonn 					rp->constblock.const.ci) == 0)
1911*40230Sdonn 				e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
1912*40230Sdonn 			else	break;
1913*40230Sdonn 
1914*40230Sdonn 			e1 = lp->exprblock.leftp;
1915*40230Sdonn 			free( (charptr) lp );
1916*40230Sdonn 			return( mkexpr(OPSTAR, e1, e) );
1917*40230Sdonn 			}
1918*40230Sdonn 		break;
1919*40230Sdonn 
1920*40230Sdonn 
1921*40230Sdonn 	case OPPLUS:
1922*40230Sdonn 		if( ISCONST(lp) )
1923*40230Sdonn 			COMMUTE
1924*40230Sdonn 		goto addop;
1925*40230Sdonn 
1926*40230Sdonn 	case OPMINUS:
1927*40230Sdonn 		if( ICONEQ(lp, 0) )
1928*40230Sdonn 			{
1929*40230Sdonn 			frexpr(lp);
1930*40230Sdonn 			return( mkexpr(OPNEG, rp, ENULL) );
1931*40230Sdonn 			}
1932*40230Sdonn 
1933*40230Sdonn 		if( ISCONST(rp) )
1934*40230Sdonn 			{
1935*40230Sdonn 			opcode = OPPLUS;
1936*40230Sdonn 			consnegop(rp);
1937*40230Sdonn 			}
1938*40230Sdonn 
1939*40230Sdonn 	addop:
1940*40230Sdonn 		if( ISICON(rp) )
1941*40230Sdonn 			{
1942*40230Sdonn 			if(rp->constblock.const.ci == 0)
1943*40230Sdonn 				goto retleft;
1944*40230Sdonn 			if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
1945*40230Sdonn 				{
1946*40230Sdonn 				e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
1947*40230Sdonn 				e1 = lp->exprblock.leftp;
1948*40230Sdonn 				free( (charptr) lp );
1949*40230Sdonn 				return( mkexpr(OPPLUS, e1, e) );
1950*40230Sdonn 				}
1951*40230Sdonn 			}
1952*40230Sdonn 		break;
1953*40230Sdonn 
1954*40230Sdonn 
1955*40230Sdonn 	case OPPOWER:
1956*40230Sdonn 		break;
1957*40230Sdonn 
1958*40230Sdonn 	case OPNEG:
1959*40230Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
1960*40230Sdonn 			{
1961*40230Sdonn 			e = lp->exprblock.leftp;
1962*40230Sdonn 			free( (charptr) lp );
1963*40230Sdonn 			return(e);
1964*40230Sdonn 			}
1965*40230Sdonn 		break;
1966*40230Sdonn 
1967*40230Sdonn 	case OPNOT:
1968*40230Sdonn 		if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
1969*40230Sdonn 			{
1970*40230Sdonn 			e = lp->exprblock.leftp;
1971*40230Sdonn 			free( (charptr) lp );
1972*40230Sdonn 			return(e);
1973*40230Sdonn 			}
1974*40230Sdonn 		break;
1975*40230Sdonn 
1976*40230Sdonn 	case OPCALL:
1977*40230Sdonn 	case OPCCALL:
1978*40230Sdonn 		etype = ltype;
1979*40230Sdonn 		if(rp!=NULL && rp->listblock.listp==NULL)
1980*40230Sdonn 			{
1981*40230Sdonn 			free( (charptr) rp );
1982*40230Sdonn 			rp = NULL;
1983*40230Sdonn 			}
1984*40230Sdonn 		break;
1985*40230Sdonn 
1986*40230Sdonn 	case OPAND:
1987*40230Sdonn 	case OPOR:
1988*40230Sdonn 		if( ISCONST(lp) )
1989*40230Sdonn 			COMMUTE
1990*40230Sdonn 
1991*40230Sdonn 		if( ISCONST(rp) )
1992*40230Sdonn 			{
1993*40230Sdonn 			if(rp->constblock.const.ci == 0)
1994*40230Sdonn 				if(opcode == OPOR)
1995*40230Sdonn 					goto retleft;
1996*40230Sdonn 				else
1997*40230Sdonn 					goto retright;
1998*40230Sdonn 			else if(opcode == OPOR)
1999*40230Sdonn 				goto retright;
2000*40230Sdonn 			else
2001*40230Sdonn 				goto retleft;
2002*40230Sdonn 			}
2003*40230Sdonn 	case OPLSHIFT:
2004*40230Sdonn 		if (ISICON(rp))
2005*40230Sdonn 			{
2006*40230Sdonn 			if (rp->constblock.const.ci == 0)
2007*40230Sdonn 				goto retleft;
2008*40230Sdonn 			if ((lp->tag == TEXPR) &&
2009*40230Sdonn 			    ((lp->exprblock.opcode == OPPLUS) ||
2010*40230Sdonn 			     (lp->exprblock.opcode == OPMINUS)) &&
2011*40230Sdonn 			    ISICON(lp->exprblock.rightp))
2012*40230Sdonn 				{
2013*40230Sdonn 				q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
2014*40230Sdonn 					cpexpr(rp));
2015*40230Sdonn 				q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
2016*40230Sdonn 				q = mkexpr(lp->exprblock.opcode, q, q1);
2017*40230Sdonn 				free((char *) lp);
2018*40230Sdonn 				return q;
2019*40230Sdonn 				}
2020*40230Sdonn 			}
2021*40230Sdonn 
2022*40230Sdonn 	case OPEQV:
2023*40230Sdonn 	case OPNEQV:
2024*40230Sdonn 
2025*40230Sdonn 	case OPBITAND:
2026*40230Sdonn 	case OPBITOR:
2027*40230Sdonn 	case OPBITXOR:
2028*40230Sdonn 	case OPBITNOT:
2029*40230Sdonn 	case OPRSHIFT:
2030*40230Sdonn 
2031*40230Sdonn 	case OPLT:
2032*40230Sdonn 	case OPGT:
2033*40230Sdonn 	case OPLE:
2034*40230Sdonn 	case OPGE:
2035*40230Sdonn 	case OPEQ:
2036*40230Sdonn 	case OPNE:
2037*40230Sdonn 
2038*40230Sdonn 	case OPCONCAT:
2039*40230Sdonn 		break;
2040*40230Sdonn 	case OPMIN:
2041*40230Sdonn 	case OPMAX:
2042*40230Sdonn 
2043*40230Sdonn 	case OPASSIGN:
2044*40230Sdonn 	case OPPLUSEQ:
2045*40230Sdonn 	case OPSTAREQ:
2046*40230Sdonn 
2047*40230Sdonn 	case OPCONV:
2048*40230Sdonn 	case OPADDR:
2049*40230Sdonn 
2050*40230Sdonn 	case OPCOMMA:
2051*40230Sdonn 	case OPQUEST:
2052*40230Sdonn 	case OPCOLON:
2053*40230Sdonn 
2054*40230Sdonn 	case OPPAREN:
2055*40230Sdonn 		break;
2056*40230Sdonn 
2057*40230Sdonn 	default:
2058*40230Sdonn 		badop("mkexpr", opcode);
2059*40230Sdonn 	}
2060*40230Sdonn 
2061*40230Sdonn e = (expptr) ALLOC(Exprblock);
2062*40230Sdonn e->exprblock.tag = TEXPR;
2063*40230Sdonn e->exprblock.opcode = opcode;
2064*40230Sdonn e->exprblock.vtype = etype;
2065*40230Sdonn e->exprblock.leftp = lp;
2066*40230Sdonn e->exprblock.rightp = rp;
2067*40230Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) )
2068*40230Sdonn 	e = fold(e);
2069*40230Sdonn return(e);
2070*40230Sdonn 
2071*40230Sdonn retleft:
2072*40230Sdonn 	frexpr(rp);
2073*40230Sdonn 	return(lp);
2074*40230Sdonn 
2075*40230Sdonn retright:
2076*40230Sdonn 	frexpr(lp);
2077*40230Sdonn 	return(rp);
2078*40230Sdonn 
2079*40230Sdonn error:
2080*40230Sdonn 	frexpr(lp);
2081*40230Sdonn 	if(rp && opcode!=OPCALL && opcode!=OPCCALL)
2082*40230Sdonn 		frexpr(rp);
2083*40230Sdonn 	return( errnode() );
2084*40230Sdonn }
2085*40230Sdonn 
2086*40230Sdonn #define ERR(s)   { errs = s; goto error; }
2087*40230Sdonn 
2088*40230Sdonn cktype(op, lt, rt)
2089*40230Sdonn register int op, lt, rt;
2090*40230Sdonn {
2091*40230Sdonn char *errs;
2092*40230Sdonn 
2093*40230Sdonn if(lt==TYERROR || rt==TYERROR)
2094*40230Sdonn 	goto error1;
2095*40230Sdonn 
2096*40230Sdonn if(lt==TYUNKNOWN)
2097*40230Sdonn 	return(TYUNKNOWN);
2098*40230Sdonn if(rt==TYUNKNOWN)
2099*40230Sdonn 	if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
2100*40230Sdonn 	    op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
2101*40230Sdonn 		return(TYUNKNOWN);
2102*40230Sdonn 
2103*40230Sdonn switch(op)
2104*40230Sdonn 	{
2105*40230Sdonn 	case OPPLUS:
2106*40230Sdonn 	case OPMINUS:
2107*40230Sdonn 	case OPSTAR:
2108*40230Sdonn 	case OPSLASH:
2109*40230Sdonn 	case OPPOWER:
2110*40230Sdonn 	case OPMOD:
2111*40230Sdonn 		if( ISNUMERIC(lt) && ISNUMERIC(rt) )
2112*40230Sdonn 			return( maxtype(lt, rt) );
2113*40230Sdonn 		ERR("nonarithmetic operand of arithmetic operator")
2114*40230Sdonn 
2115*40230Sdonn 	case OPNEG:
2116*40230Sdonn 		if( ISNUMERIC(lt) )
2117*40230Sdonn 			return(lt);
2118*40230Sdonn 		ERR("nonarithmetic operand of negation")
2119*40230Sdonn 
2120*40230Sdonn 	case OPNOT:
2121*40230Sdonn 		if(lt == TYLOGICAL)
2122*40230Sdonn 			return(TYLOGICAL);
2123*40230Sdonn 		ERR("NOT of nonlogical")
2124*40230Sdonn 
2125*40230Sdonn 	case OPAND:
2126*40230Sdonn 	case OPOR:
2127*40230Sdonn 	case OPEQV:
2128*40230Sdonn 	case OPNEQV:
2129*40230Sdonn 		if(lt==TYLOGICAL && rt==TYLOGICAL)
2130*40230Sdonn 			return(TYLOGICAL);
2131*40230Sdonn 		ERR("nonlogical operand of logical operator")
2132*40230Sdonn 
2133*40230Sdonn 	case OPLT:
2134*40230Sdonn 	case OPGT:
2135*40230Sdonn 	case OPLE:
2136*40230Sdonn 	case OPGE:
2137*40230Sdonn 	case OPEQ:
2138*40230Sdonn 	case OPNE:
2139*40230Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
2140*40230Sdonn 			{
2141*40230Sdonn 			if(lt != rt)
2142*40230Sdonn 				ERR("illegal comparison")
2143*40230Sdonn 			}
2144*40230Sdonn 
2145*40230Sdonn 		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
2146*40230Sdonn 			{
2147*40230Sdonn 			if(op!=OPEQ && op!=OPNE)
2148*40230Sdonn 				ERR("order comparison of complex data")
2149*40230Sdonn 			}
2150*40230Sdonn 
2151*40230Sdonn 		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
2152*40230Sdonn 			ERR("comparison of nonarithmetic data")
2153*40230Sdonn 		return(TYLOGICAL);
2154*40230Sdonn 
2155*40230Sdonn 	case OPCONCAT:
2156*40230Sdonn 		if(lt==TYCHAR && rt==TYCHAR)
2157*40230Sdonn 			return(TYCHAR);
2158*40230Sdonn 		ERR("concatenation of nonchar data")
2159*40230Sdonn 
2160*40230Sdonn 	case OPCALL:
2161*40230Sdonn 	case OPCCALL:
2162*40230Sdonn 		return(lt);
2163*40230Sdonn 
2164*40230Sdonn 	case OPADDR:
2165*40230Sdonn 		return(TYADDR);
2166*40230Sdonn 
2167*40230Sdonn 	case OPCONV:
2168*40230Sdonn 		if(ISCOMPLEX(lt))
2169*40230Sdonn 			{
2170*40230Sdonn 			if(ISNUMERIC(rt))
2171*40230Sdonn 				return(lt);
2172*40230Sdonn 			ERR("impossible conversion")
2173*40230Sdonn 			}
2174*40230Sdonn 		if(rt == 0)
2175*40230Sdonn 			return(0);
2176*40230Sdonn 		if(lt==TYCHAR && ISINT(rt) )
2177*40230Sdonn 			return(TYCHAR);
2178*40230Sdonn 	case OPASSIGN:
2179*40230Sdonn 	case OPPLUSEQ:
2180*40230Sdonn 	case OPSTAREQ:
2181*40230Sdonn 		if( ISINT(lt) && rt==TYCHAR)
2182*40230Sdonn 			return(lt);
2183*40230Sdonn 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
2184*40230Sdonn 			if(op!=OPASSIGN || lt!=rt)
2185*40230Sdonn 				{
2186*40230Sdonn /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
2187*40230Sdonn /* debug fatal("impossible conversion.  possible compiler bug"); */
2188*40230Sdonn 				ERR("impossible conversion")
2189*40230Sdonn 				}
2190*40230Sdonn 		return(lt);
2191*40230Sdonn 
2192*40230Sdonn 	case OPMIN:
2193*40230Sdonn 	case OPMAX:
2194*40230Sdonn 	case OPBITOR:
2195*40230Sdonn 	case OPBITAND:
2196*40230Sdonn 	case OPBITXOR:
2197*40230Sdonn 	case OPBITNOT:
2198*40230Sdonn 	case OPLSHIFT:
2199*40230Sdonn 	case OPRSHIFT:
2200*40230Sdonn 	case OPPAREN:
2201*40230Sdonn 		return(lt);
2202*40230Sdonn 
2203*40230Sdonn 	case OPCOMMA:
2204*40230Sdonn 	case OPQUEST:
2205*40230Sdonn 	case OPCOLON:
2206*40230Sdonn 		return(rt);
2207*40230Sdonn 
2208*40230Sdonn 	default:
2209*40230Sdonn 		badop("cktype", op);
2210*40230Sdonn 	}
2211*40230Sdonn error:	err(errs);
2212*40230Sdonn error1:	return(TYERROR);
2213*40230Sdonn }
2214*40230Sdonn 
2215*40230Sdonn LOCAL expptr fold(e)
2216*40230Sdonn register expptr e;
2217*40230Sdonn {
2218*40230Sdonn Constp p;
2219*40230Sdonn register expptr lp, rp;
2220*40230Sdonn int etype, mtype, ltype, rtype, opcode;
2221*40230Sdonn int i, ll, lr;
2222*40230Sdonn char *q, *s;
2223*40230Sdonn union Constant lcon, rcon;
2224*40230Sdonn 
2225*40230Sdonn opcode = e->exprblock.opcode;
2226*40230Sdonn etype = e->exprblock.vtype;
2227*40230Sdonn 
2228*40230Sdonn lp = e->exprblock.leftp;
2229*40230Sdonn ltype = lp->headblock.vtype;
2230*40230Sdonn rp = e->exprblock.rightp;
2231*40230Sdonn 
2232*40230Sdonn if(rp == 0)
2233*40230Sdonn 	switch(opcode)
2234*40230Sdonn 		{
2235*40230Sdonn 		case OPNOT:
2236*40230Sdonn 			lp->constblock.const.ci = ! lp->constblock.const.ci;
2237*40230Sdonn 			return(lp);
2238*40230Sdonn 
2239*40230Sdonn 		case OPBITNOT:
2240*40230Sdonn 			lp->constblock.const.ci = ~ lp->constblock.const.ci;
2241*40230Sdonn 			return(lp);
2242*40230Sdonn 
2243*40230Sdonn 		case OPNEG:
2244*40230Sdonn 			consnegop(lp);
2245*40230Sdonn 			return(lp);
2246*40230Sdonn 
2247*40230Sdonn 		case OPCONV:
2248*40230Sdonn 		case OPADDR:
2249*40230Sdonn 		case OPPAREN:
2250*40230Sdonn 			return(e);
2251*40230Sdonn 
2252*40230Sdonn 		default:
2253*40230Sdonn 			badop("fold", opcode);
2254*40230Sdonn 		}
2255*40230Sdonn 
2256*40230Sdonn rtype = rp->headblock.vtype;
2257*40230Sdonn 
2258*40230Sdonn p = ALLOC(Constblock);
2259*40230Sdonn p->tag = TCONST;
2260*40230Sdonn p->vtype = etype;
2261*40230Sdonn p->vleng = e->exprblock.vleng;
2262*40230Sdonn 
2263*40230Sdonn switch(opcode)
2264*40230Sdonn 	{
2265*40230Sdonn 	case OPCOMMA:
2266*40230Sdonn 	case OPQUEST:
2267*40230Sdonn 	case OPCOLON:
2268*40230Sdonn 		return(e);
2269*40230Sdonn 
2270*40230Sdonn 	case OPAND:
2271*40230Sdonn 		p->const.ci = lp->constblock.const.ci &&
2272*40230Sdonn 				rp->constblock.const.ci;
2273*40230Sdonn 		break;
2274*40230Sdonn 
2275*40230Sdonn 	case OPOR:
2276*40230Sdonn 		p->const.ci = lp->constblock.const.ci ||
2277*40230Sdonn 				rp->constblock.const.ci;
2278*40230Sdonn 		break;
2279*40230Sdonn 
2280*40230Sdonn 	case OPEQV:
2281*40230Sdonn 		p->const.ci = lp->constblock.const.ci ==
2282*40230Sdonn 				rp->constblock.const.ci;
2283*40230Sdonn 		break;
2284*40230Sdonn 
2285*40230Sdonn 	case OPNEQV:
2286*40230Sdonn 		p->const.ci = lp->constblock.const.ci !=
2287*40230Sdonn 				rp->constblock.const.ci;
2288*40230Sdonn 		break;
2289*40230Sdonn 
2290*40230Sdonn 	case OPBITAND:
2291*40230Sdonn 		p->const.ci = lp->constblock.const.ci &
2292*40230Sdonn 				rp->constblock.const.ci;
2293*40230Sdonn 		break;
2294*40230Sdonn 
2295*40230Sdonn 	case OPBITOR:
2296*40230Sdonn 		p->const.ci = lp->constblock.const.ci |
2297*40230Sdonn 				rp->constblock.const.ci;
2298*40230Sdonn 		break;
2299*40230Sdonn 
2300*40230Sdonn 	case OPBITXOR:
2301*40230Sdonn 		p->const.ci = lp->constblock.const.ci ^
2302*40230Sdonn 				rp->constblock.const.ci;
2303*40230Sdonn 		break;
2304*40230Sdonn 
2305*40230Sdonn 	case OPLSHIFT:
2306*40230Sdonn 		p->const.ci = lp->constblock.const.ci <<
2307*40230Sdonn 				rp->constblock.const.ci;
2308*40230Sdonn 		break;
2309*40230Sdonn 
2310*40230Sdonn 	case OPRSHIFT:
2311*40230Sdonn 		p->const.ci = lp->constblock.const.ci >>
2312*40230Sdonn 				rp->constblock.const.ci;
2313*40230Sdonn 		break;
2314*40230Sdonn 
2315*40230Sdonn 	case OPCONCAT:
2316*40230Sdonn 		ll = lp->constblock.vleng->constblock.const.ci;
2317*40230Sdonn 		lr = rp->constblock.vleng->constblock.const.ci;
2318*40230Sdonn 		p->const.ccp = q = (char *) ckalloc(ll+lr);
2319*40230Sdonn 		p->vleng = ICON(ll+lr);
2320*40230Sdonn 		s = lp->constblock.const.ccp;
2321*40230Sdonn 		for(i = 0 ; i < ll ; ++i)
2322*40230Sdonn 			*q++ = *s++;
2323*40230Sdonn 		s = rp->constblock.const.ccp;
2324*40230Sdonn 		for(i = 0; i < lr; ++i)
2325*40230Sdonn 			*q++ = *s++;
2326*40230Sdonn 		break;
2327*40230Sdonn 
2328*40230Sdonn 
2329*40230Sdonn 	case OPPOWER:
2330*40230Sdonn 		if( ! ISINT(rtype) )
2331*40230Sdonn 			return(e);
2332*40230Sdonn 		conspower(&(p->const), lp, rp->constblock.const.ci);
2333*40230Sdonn 		break;
2334*40230Sdonn 
2335*40230Sdonn 
2336*40230Sdonn 	default:
2337*40230Sdonn 		if(ltype == TYCHAR)
2338*40230Sdonn 			{
2339*40230Sdonn 			lcon.ci = cmpstr(lp->constblock.const.ccp,
2340*40230Sdonn 					rp->constblock.const.ccp,
2341*40230Sdonn 					lp->constblock.vleng->constblock.const.ci,
2342*40230Sdonn 					rp->constblock.vleng->constblock.const.ci);
2343*40230Sdonn 			rcon.ci = 0;
2344*40230Sdonn 			mtype = tyint;
2345*40230Sdonn 			}
2346*40230Sdonn 		else	{
2347*40230Sdonn 			mtype = maxtype(ltype, rtype);
2348*40230Sdonn 			consconv(mtype, &lcon, ltype, &(lp->constblock.const) );
2349*40230Sdonn 			consconv(mtype, &rcon, rtype, &(rp->constblock.const) );
2350*40230Sdonn 			}
2351*40230Sdonn 		consbinop(opcode, mtype, &(p->const), &lcon, &rcon);
2352*40230Sdonn 		break;
2353*40230Sdonn 	}
2354*40230Sdonn 
2355*40230Sdonn frexpr(e);
2356*40230Sdonn return( (expptr) p );
2357*40230Sdonn }
2358*40230Sdonn 
2359*40230Sdonn 
2360*40230Sdonn 
2361*40230Sdonn /* assign constant l = r , doing coercion */
2362*40230Sdonn 
2363*40230Sdonn consconv(lt, lv, rt, rv)
2364*40230Sdonn int lt, rt;
2365*40230Sdonn register union Constant *lv, *rv;
2366*40230Sdonn {
2367*40230Sdonn switch(lt)
2368*40230Sdonn 	{
2369*40230Sdonn 	case TYCHAR:
2370*40230Sdonn 		*(lv->ccp = (char *) ckalloc(1)) = rv->ci;
2371*40230Sdonn 		break;
2372*40230Sdonn 
2373*40230Sdonn 	case TYSHORT:
2374*40230Sdonn 	case TYLONG:
2375*40230Sdonn 		if(rt == TYCHAR)
2376*40230Sdonn 			lv->ci = rv->ccp[0];
2377*40230Sdonn 		else if( ISINT(rt) )
2378*40230Sdonn 			lv->ci = rv->ci;
2379*40230Sdonn 		else	lv->ci = rv->cd[0];
2380*40230Sdonn 		break;
2381*40230Sdonn 
2382*40230Sdonn 	case TYCOMPLEX:
2383*40230Sdonn 	case TYDCOMPLEX:
2384*40230Sdonn 		switch(rt)
2385*40230Sdonn 			{
2386*40230Sdonn 			case TYSHORT:
2387*40230Sdonn 			case TYLONG:
2388*40230Sdonn 				/* fall through and do real assignment of
2389*40230Sdonn 				   first element
2390*40230Sdonn 				*/
2391*40230Sdonn 			case TYREAL:
2392*40230Sdonn 			case TYDREAL:
2393*40230Sdonn 				lv->cd[1] = 0; break;
2394*40230Sdonn 			case TYCOMPLEX:
2395*40230Sdonn 			case TYDCOMPLEX:
2396*40230Sdonn 				lv->cd[1] = rv->cd[1]; break;
2397*40230Sdonn 			}
2398*40230Sdonn 
2399*40230Sdonn 	case TYREAL:
2400*40230Sdonn 	case TYDREAL:
2401*40230Sdonn 		if( ISINT(rt) )
2402*40230Sdonn 			lv->cd[0] = rv->ci;
2403*40230Sdonn 		else	lv->cd[0] = rv->cd[0];
2404*40230Sdonn 		if( lt == TYREAL)
2405*40230Sdonn 			{
2406*40230Sdonn 			float f = lv->cd[0];
2407*40230Sdonn 			lv->cd[0] = f;
2408*40230Sdonn 			}
2409*40230Sdonn 		break;
2410*40230Sdonn 
2411*40230Sdonn 	case TYLOGICAL:
2412*40230Sdonn 		lv->ci = rv->ci;
2413*40230Sdonn 		break;
2414*40230Sdonn 	}
2415*40230Sdonn }
2416*40230Sdonn 
2417*40230Sdonn 
2418*40230Sdonn 
2419*40230Sdonn consnegop(p)
2420*40230Sdonn register Constp p;
2421*40230Sdonn {
2422*40230Sdonn switch(p->vtype)
2423*40230Sdonn 	{
2424*40230Sdonn 	case TYSHORT:
2425*40230Sdonn 	case TYLONG:
2426*40230Sdonn 		p->const.ci = - p->const.ci;
2427*40230Sdonn 		break;
2428*40230Sdonn 
2429*40230Sdonn 	case TYCOMPLEX:
2430*40230Sdonn 	case TYDCOMPLEX:
2431*40230Sdonn 		p->const.cd[1] = - p->const.cd[1];
2432*40230Sdonn 		/* fall through and do the real parts */
2433*40230Sdonn 	case TYREAL:
2434*40230Sdonn 	case TYDREAL:
2435*40230Sdonn 		p->const.cd[0] = - p->const.cd[0];
2436*40230Sdonn 		break;
2437*40230Sdonn 	default:
2438*40230Sdonn 		badtype("consnegop", p->vtype);
2439*40230Sdonn 	}
2440*40230Sdonn }
2441*40230Sdonn 
2442*40230Sdonn 
2443*40230Sdonn 
2444*40230Sdonn LOCAL conspower(powp, ap, n)
2445*40230Sdonn register union Constant *powp;
2446*40230Sdonn Constp ap;
2447*40230Sdonn ftnint n;
2448*40230Sdonn {
2449*40230Sdonn register int type;
2450*40230Sdonn union Constant x;
2451*40230Sdonn 
2452*40230Sdonn switch(type = ap->vtype)	/* pow = 1 */
2453*40230Sdonn 	{
2454*40230Sdonn 	case TYSHORT:
2455*40230Sdonn 	case TYLONG:
2456*40230Sdonn 		powp->ci = 1;
2457*40230Sdonn 		break;
2458*40230Sdonn 	case TYCOMPLEX:
2459*40230Sdonn 	case TYDCOMPLEX:
2460*40230Sdonn 		powp->cd[1] = 0;
2461*40230Sdonn 	case TYREAL:
2462*40230Sdonn 	case TYDREAL:
2463*40230Sdonn 		powp->cd[0] = 1;
2464*40230Sdonn 		break;
2465*40230Sdonn 	default:
2466*40230Sdonn 		badtype("conspower", type);
2467*40230Sdonn 	}
2468*40230Sdonn 
2469*40230Sdonn if(n == 0)
2470*40230Sdonn 	return;
2471*40230Sdonn if(n < 0)
2472*40230Sdonn 	{
2473*40230Sdonn 	if( ISINT(type) )
2474*40230Sdonn 		{
2475*40230Sdonn 		if (ap->const.ci == 0)
2476*40230Sdonn 			err("zero raised to a negative power");
2477*40230Sdonn 		else if (ap->const.ci == 1)
2478*40230Sdonn 			return;
2479*40230Sdonn 		else if (ap->const.ci == -1)
2480*40230Sdonn 			{
2481*40230Sdonn 			if (n < -2)
2482*40230Sdonn 				n = n + 2;
2483*40230Sdonn 			n = -n;
2484*40230Sdonn 			if (n % 2 == 1)
2485*40230Sdonn 				powp->ci = -1;
2486*40230Sdonn 			}
2487*40230Sdonn 		else
2488*40230Sdonn 			powp->ci = 0;
2489*40230Sdonn 		return;
2490*40230Sdonn 		}
2491*40230Sdonn 	n = - n;
2492*40230Sdonn 	consbinop(OPSLASH, type, &x, powp, &(ap->const));
2493*40230Sdonn 	}
2494*40230Sdonn else
2495*40230Sdonn 	consbinop(OPSTAR, type, &x, powp, &(ap->const));
2496*40230Sdonn 
2497*40230Sdonn for( ; ; )
2498*40230Sdonn 	{
2499*40230Sdonn 	if(n & 01)
2500*40230Sdonn 		consbinop(OPSTAR, type, powp, powp, &x);
2501*40230Sdonn 	if(n >>= 1)
2502*40230Sdonn 		consbinop(OPSTAR, type, &x, &x, &x);
2503*40230Sdonn 	else
2504*40230Sdonn 		break;
2505*40230Sdonn 	}
2506*40230Sdonn }
2507*40230Sdonn 
2508*40230Sdonn 
2509*40230Sdonn 
2510*40230Sdonn /* do constant operation cp = a op b */
2511*40230Sdonn 
2512*40230Sdonn 
2513*40230Sdonn LOCAL consbinop(opcode, type, cp, ap, bp)
2514*40230Sdonn int opcode, type;
2515*40230Sdonn register union Constant *ap, *bp, *cp;
2516*40230Sdonn {
2517*40230Sdonn int k;
2518*40230Sdonn double temp;
2519*40230Sdonn 
2520*40230Sdonn switch(opcode)
2521*40230Sdonn 	{
2522*40230Sdonn 	case OPPLUS:
2523*40230Sdonn 		switch(type)
2524*40230Sdonn 			{
2525*40230Sdonn 			case TYSHORT:
2526*40230Sdonn 			case TYLONG:
2527*40230Sdonn 				cp->ci = ap->ci + bp->ci;
2528*40230Sdonn 				break;
2529*40230Sdonn 			case TYCOMPLEX:
2530*40230Sdonn 			case TYDCOMPLEX:
2531*40230Sdonn 				cp->cd[1] = ap->cd[1] + bp->cd[1];
2532*40230Sdonn 			case TYREAL:
2533*40230Sdonn 			case TYDREAL:
2534*40230Sdonn 				cp->cd[0] = ap->cd[0] + bp->cd[0];
2535*40230Sdonn 				break;
2536*40230Sdonn 			}
2537*40230Sdonn 		break;
2538*40230Sdonn 
2539*40230Sdonn 	case OPMINUS:
2540*40230Sdonn 		switch(type)
2541*40230Sdonn 			{
2542*40230Sdonn 			case TYSHORT:
2543*40230Sdonn 			case TYLONG:
2544*40230Sdonn 				cp->ci = ap->ci - bp->ci;
2545*40230Sdonn 				break;
2546*40230Sdonn 			case TYCOMPLEX:
2547*40230Sdonn 			case TYDCOMPLEX:
2548*40230Sdonn 				cp->cd[1] = ap->cd[1] - bp->cd[1];
2549*40230Sdonn 			case TYREAL:
2550*40230Sdonn 			case TYDREAL:
2551*40230Sdonn 				cp->cd[0] = ap->cd[0] - bp->cd[0];
2552*40230Sdonn 				break;
2553*40230Sdonn 			}
2554*40230Sdonn 		break;
2555*40230Sdonn 
2556*40230Sdonn 	case OPSTAR:
2557*40230Sdonn 		switch(type)
2558*40230Sdonn 			{
2559*40230Sdonn 			case TYSHORT:
2560*40230Sdonn 			case TYLONG:
2561*40230Sdonn 				cp->ci = ap->ci * bp->ci;
2562*40230Sdonn 				break;
2563*40230Sdonn 			case TYREAL:
2564*40230Sdonn 			case TYDREAL:
2565*40230Sdonn 				cp->cd[0] = ap->cd[0] * bp->cd[0];
2566*40230Sdonn 				break;
2567*40230Sdonn 			case TYCOMPLEX:
2568*40230Sdonn 			case TYDCOMPLEX:
2569*40230Sdonn 				temp = ap->cd[0] * bp->cd[0] -
2570*40230Sdonn 					    ap->cd[1] * bp->cd[1] ;
2571*40230Sdonn 				cp->cd[1] = ap->cd[0] * bp->cd[1] +
2572*40230Sdonn 					    ap->cd[1] * bp->cd[0] ;
2573*40230Sdonn 				cp->cd[0] = temp;
2574*40230Sdonn 				break;
2575*40230Sdonn 			}
2576*40230Sdonn 		break;
2577*40230Sdonn 	case OPSLASH:
2578*40230Sdonn 		switch(type)
2579*40230Sdonn 			{
2580*40230Sdonn 			case TYSHORT:
2581*40230Sdonn 			case TYLONG:
2582*40230Sdonn 				cp->ci = ap->ci / bp->ci;
2583*40230Sdonn 				break;
2584*40230Sdonn 			case TYREAL:
2585*40230Sdonn 			case TYDREAL:
2586*40230Sdonn 				cp->cd[0] = ap->cd[0] / bp->cd[0];
2587*40230Sdonn 				break;
2588*40230Sdonn 			case TYCOMPLEX:
2589*40230Sdonn 			case TYDCOMPLEX:
2590*40230Sdonn 				zdiv(cp,ap,bp);
2591*40230Sdonn 				break;
2592*40230Sdonn 			}
2593*40230Sdonn 		break;
2594*40230Sdonn 
2595*40230Sdonn 	case OPMOD:
2596*40230Sdonn 		if( ISINT(type) )
2597*40230Sdonn 			{
2598*40230Sdonn 			cp->ci = ap->ci % bp->ci;
2599*40230Sdonn 			break;
2600*40230Sdonn 			}
2601*40230Sdonn 		else
2602*40230Sdonn 			fatal("inline mod of noninteger");
2603*40230Sdonn 
2604*40230Sdonn 	default:	  /* relational ops */
2605*40230Sdonn 		switch(type)
2606*40230Sdonn 			{
2607*40230Sdonn 			case TYSHORT:
2608*40230Sdonn 			case TYLONG:
2609*40230Sdonn 				if(ap->ci < bp->ci)
2610*40230Sdonn 					k = -1;
2611*40230Sdonn 				else if(ap->ci == bp->ci)
2612*40230Sdonn 					k = 0;
2613*40230Sdonn 				else	k = 1;
2614*40230Sdonn 				break;
2615*40230Sdonn 			case TYREAL:
2616*40230Sdonn 			case TYDREAL:
2617*40230Sdonn 				if(ap->cd[0] < bp->cd[0])
2618*40230Sdonn 					k = -1;
2619*40230Sdonn 				else if(ap->cd[0] == bp->cd[0])
2620*40230Sdonn 					k = 0;
2621*40230Sdonn 				else	k = 1;
2622*40230Sdonn 				break;
2623*40230Sdonn 			case TYCOMPLEX:
2624*40230Sdonn 			case TYDCOMPLEX:
2625*40230Sdonn 				if(ap->cd[0] == bp->cd[0] &&
2626*40230Sdonn 				   ap->cd[1] == bp->cd[1] )
2627*40230Sdonn 					k = 0;
2628*40230Sdonn 				else	k = 1;
2629*40230Sdonn 				break;
2630*40230Sdonn 			}
2631*40230Sdonn 
2632*40230Sdonn 		switch(opcode)
2633*40230Sdonn 			{
2634*40230Sdonn 			case OPEQ:
2635*40230Sdonn 				cp->ci = (k == 0);
2636*40230Sdonn 				break;
2637*40230Sdonn 			case OPNE:
2638*40230Sdonn 				cp->ci = (k != 0);
2639*40230Sdonn 				break;
2640*40230Sdonn 			case OPGT:
2641*40230Sdonn 				cp->ci = (k == 1);
2642*40230Sdonn 				break;
2643*40230Sdonn 			case OPLT:
2644*40230Sdonn 				cp->ci = (k == -1);
2645*40230Sdonn 				break;
2646*40230Sdonn 			case OPGE:
2647*40230Sdonn 				cp->ci = (k >= 0);
2648*40230Sdonn 				break;
2649*40230Sdonn 			case OPLE:
2650*40230Sdonn 				cp->ci = (k <= 0);
2651*40230Sdonn 				break;
2652*40230Sdonn 			default:
2653*40230Sdonn 				badop ("consbinop", opcode);
2654*40230Sdonn 			}
2655*40230Sdonn 		break;
2656*40230Sdonn 	}
2657*40230Sdonn }
2658*40230Sdonn 
2659*40230Sdonn 
2660*40230Sdonn 
2661*40230Sdonn 
2662*40230Sdonn conssgn(p)
2663*40230Sdonn register expptr p;
2664*40230Sdonn {
2665*40230Sdonn if( ! ISCONST(p) )
2666*40230Sdonn 	fatal( "sgn(nonconstant)" );
2667*40230Sdonn 
2668*40230Sdonn switch(p->headblock.vtype)
2669*40230Sdonn 	{
2670*40230Sdonn 	case TYSHORT:
2671*40230Sdonn 	case TYLONG:
2672*40230Sdonn 		if(p->constblock.const.ci > 0) return(1);
2673*40230Sdonn 		if(p->constblock.const.ci < 0) return(-1);
2674*40230Sdonn 		return(0);
2675*40230Sdonn 
2676*40230Sdonn 	case TYREAL:
2677*40230Sdonn 	case TYDREAL:
2678*40230Sdonn 		if(p->constblock.const.cd[0] > 0) return(1);
2679*40230Sdonn 		if(p->constblock.const.cd[0] < 0) return(-1);
2680*40230Sdonn 		return(0);
2681*40230Sdonn 
2682*40230Sdonn 	case TYCOMPLEX:
2683*40230Sdonn 	case TYDCOMPLEX:
2684*40230Sdonn 		return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0);
2685*40230Sdonn 
2686*40230Sdonn 	default:
2687*40230Sdonn 		badtype( "conssgn", p->constblock.vtype);
2688*40230Sdonn 	}
2689*40230Sdonn /* NOTREACHED */
2690*40230Sdonn }
2691*40230Sdonn 
2692*40230Sdonn char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
2693*40230Sdonn 
2694*40230Sdonn 
2695*40230Sdonn LOCAL expptr mkpower(p)
2696*40230Sdonn register expptr p;
2697*40230Sdonn {
2698*40230Sdonn register expptr q, lp, rp;
2699*40230Sdonn int ltype, rtype, mtype;
2700*40230Sdonn 
2701*40230Sdonn lp = p->exprblock.leftp;
2702*40230Sdonn rp = p->exprblock.rightp;
2703*40230Sdonn ltype = lp->headblock.vtype;
2704*40230Sdonn rtype = rp->headblock.vtype;
2705*40230Sdonn 
2706*40230Sdonn if(ISICON(rp))
2707*40230Sdonn 	{
2708*40230Sdonn 	if(rp->constblock.const.ci == 0)
2709*40230Sdonn 		{
2710*40230Sdonn 		frexpr(p);
2711*40230Sdonn 		if( ISINT(ltype) )
2712*40230Sdonn 			return( ICON(1) );
2713*40230Sdonn 		else
2714*40230Sdonn 			{
2715*40230Sdonn 			expptr pp;
2716*40230Sdonn 			pp = mkconv(ltype, ICON(1));
2717*40230Sdonn 			return( pp );
2718*40230Sdonn 			}
2719*40230Sdonn 		}
2720*40230Sdonn 	if(rp->constblock.const.ci < 0)
2721*40230Sdonn 		{
2722*40230Sdonn 		if( ISINT(ltype) )
2723*40230Sdonn 			{
2724*40230Sdonn 			frexpr(p);
2725*40230Sdonn 			err("integer**negative");
2726*40230Sdonn 			return( errnode() );
2727*40230Sdonn 			}
2728*40230Sdonn 		rp->constblock.const.ci = - rp->constblock.const.ci;
2729*40230Sdonn 		p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
2730*40230Sdonn 		}
2731*40230Sdonn 	if(rp->constblock.const.ci == 1)
2732*40230Sdonn 		{
2733*40230Sdonn 		frexpr(rp);
2734*40230Sdonn 		free( (charptr) p );
2735*40230Sdonn 		return(lp);
2736*40230Sdonn 		}
2737*40230Sdonn 
2738*40230Sdonn 	if( ONEOF(ltype, MSKINT|MSKREAL) )
2739*40230Sdonn 		{
2740*40230Sdonn 		p->exprblock.vtype = ltype;
2741*40230Sdonn 		return(p);
2742*40230Sdonn 		}
2743*40230Sdonn 	}
2744*40230Sdonn if( ISINT(rtype) )
2745*40230Sdonn 	{
2746*40230Sdonn 	if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
2747*40230Sdonn 		q = call2(TYSHORT, "pow_hh", lp, rp);
2748*40230Sdonn 	else	{
2749*40230Sdonn 		if(ltype == TYSHORT)
2750*40230Sdonn 			{
2751*40230Sdonn 			ltype = TYLONG;
2752*40230Sdonn 			lp = mkconv(TYLONG,lp);
2753*40230Sdonn 			}
2754*40230Sdonn 		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
2755*40230Sdonn 		}
2756*40230Sdonn 	}
2757*40230Sdonn else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
2758*40230Sdonn 	q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
2759*40230Sdonn else	{
2760*40230Sdonn 	q  = call2(TYDCOMPLEX, "pow_zz",
2761*40230Sdonn 		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
2762*40230Sdonn 	if(mtype == TYCOMPLEX)
2763*40230Sdonn 		q = mkconv(TYCOMPLEX, q);
2764*40230Sdonn 	}
2765*40230Sdonn free( (charptr) p );
2766*40230Sdonn return(q);
2767*40230Sdonn }
2768*40230Sdonn 
2769*40230Sdonn 
2770*40230Sdonn 
2771*40230Sdonn /* Complex Division.  Same code as in Runtime Library
2772*40230Sdonn */
2773*40230Sdonn 
2774*40230Sdonn struct dcomplex { double dreal, dimag; };
2775*40230Sdonn 
2776*40230Sdonn 
2777*40230Sdonn LOCAL zdiv(c, a, b)
2778*40230Sdonn register struct dcomplex *a, *b, *c;
2779*40230Sdonn {
2780*40230Sdonn double ratio, den;
2781*40230Sdonn double abr, abi;
2782*40230Sdonn 
2783*40230Sdonn if( (abr = b->dreal) < 0.)
2784*40230Sdonn 	abr = - abr;
2785*40230Sdonn if( (abi = b->dimag) < 0.)
2786*40230Sdonn 	abi = - abi;
2787*40230Sdonn if( abr <= abi )
2788*40230Sdonn 	{
2789*40230Sdonn 	if(abi == 0)
2790*40230Sdonn 		fatal("complex division by zero");
2791*40230Sdonn 	ratio = b->dreal / b->dimag ;
2792*40230Sdonn 	den = b->dimag * (1 + ratio*ratio);
2793*40230Sdonn 	c->dreal = (a->dreal*ratio + a->dimag) / den;
2794*40230Sdonn 	c->dimag = (a->dimag*ratio - a->dreal) / den;
2795*40230Sdonn 	}
2796*40230Sdonn 
2797*40230Sdonn else
2798*40230Sdonn 	{
2799*40230Sdonn 	ratio = b->dimag / b->dreal ;
2800*40230Sdonn 	den = b->dreal * (1 + ratio*ratio);
2801*40230Sdonn 	c->dreal = (a->dreal + a->dimag*ratio) / den;
2802*40230Sdonn 	c->dimag = (a->dimag - a->dreal*ratio) / den;
2803*40230Sdonn 	}
2804*40230Sdonn 
2805*40230Sdonn }
2806*40230Sdonn 
2807*40230Sdonn expptr oftwo(e)
2808*40230Sdonn expptr e;
2809*40230Sdonn {
2810*40230Sdonn 	int val,res;
2811*40230Sdonn 
2812*40230Sdonn 	if (! ISCONST (e))
2813*40230Sdonn 		return (0);
2814*40230Sdonn 
2815*40230Sdonn 	val = e->constblock.const.ci;
2816*40230Sdonn 	switch (val)
2817*40230Sdonn 		{
2818*40230Sdonn 		case 2:		res = 1; break;
2819*40230Sdonn 		case 4:		res = 2; break;
2820*40230Sdonn 		case 8:		res = 3; break;
2821*40230Sdonn 		case 16:	res = 4; break;
2822*40230Sdonn 		case 32:	res = 5; break;
2823*40230Sdonn 		case 64:	res = 6; break;
2824*40230Sdonn 		case 128:	res = 7; break;
2825*40230Sdonn 		case 256:	res = 8; break;
2826*40230Sdonn 		default:	return (0);
2827*40230Sdonn 		}
2828*40230Sdonn 	return (ICON (res));
2829*40230Sdonn }
2830