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