xref: /netbsd/external/bsd/pcc/dist/pcc/f77/fcom/expr.c (revision 3eb51a41)
1 /*	Id: expr.c,v 1.20 2008/05/11 15:28:03 ragge Exp 	*/
2 /*	$NetBSD: expr.c,v 1.1.1.2 2010/06/03 18:57:48 plunky Exp $	*/
3 /*
4  * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * Redistributions of source code and documentation must retain the above
11  * copyright notice, this list of conditions and the following disclaimer.
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditionsand the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * All advertising materials mentioning features or use of this software
16  * must display the following acknowledgement:
17  * 	This product includes software developed or owned by Caldera
18  *	International, Inc.
19  * Neither the name of Caldera International, Inc. nor the names of other
20  * contributors may be used to endorse or promote products derived from
21  * this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
28  * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 #include <string.h>
37 
38 #include "defines.h"
39 #include "defs.h"
40 
41 /* little routines to create constant blocks */
42 LOCAL int letter(int c);
43 LOCAL void conspower(union constant *, struct bigblock *, ftnint);
44 LOCAL void consbinop(int, int, union constant *, union constant *,
45 	union constant *);
46 LOCAL void zdiv(struct dcomplex *, struct dcomplex *, struct dcomplex *);
47 LOCAL struct bigblock *stfcall(struct bigblock *, struct bigblock *);
48 LOCAL bigptr mkpower(struct bigblock *p);
49 LOCAL bigptr fold(struct bigblock *e);
50 LOCAL bigptr subcheck(struct bigblock *, bigptr);
51 
mkconst(t)52 struct bigblock *mkconst(t)
53 register int t;
54 {
55 register struct bigblock *p;
56 
57 p = BALLO();
58 p->tag = TCONST;
59 p->vtype = t;
60 return(p);
61 }
62 
63 
mklogcon(l)64 struct bigblock *mklogcon(l)
65 register int l;
66 {
67 register struct bigblock * p;
68 
69 p = mkconst(TYLOGICAL);
70 p->b_const.fconst.ci = l;
71 return(p);
72 }
73 
74 
75 
mkintcon(l)76 struct bigblock *mkintcon(l)
77 ftnint l;
78 {
79 register struct bigblock *p;
80 
81 p = mkconst(TYLONG);
82 p->b_const.fconst.ci = l;
83 #ifdef MAXSHORT
84 	if(l >= -MAXSHORT   &&   l <= MAXSHORT)
85 		p->vtype = TYSHORT;
86 #endif
87 return(p);
88 }
89 
90 
91 
mkaddcon(l)92 struct bigblock *mkaddcon(l)
93 register int l;
94 {
95 register struct bigblock *p;
96 
97 p = mkconst(TYADDR);
98 p->b_const.fconst.ci = l;
99 return(p);
100 }
101 
102 
103 
mkrealcon(t,d)104 struct bigblock *mkrealcon(t, d)
105 register int t;
106 double d;
107 {
108 register struct bigblock *p;
109 
110 p = mkconst(t);
111 p->b_const.fconst.cd[0] = d;
112 return(p);
113 }
114 
115 
mkbitcon(shift,leng,s)116 struct bigblock *mkbitcon(shift, leng, s)
117 int shift;
118 int leng;
119 char *s;
120 {
121 register struct bigblock *p;
122 
123 p = mkconst(TYUNKNOWN);
124 p->b_const.fconst.ci = 0;
125 while(--leng >= 0)
126 	if(*s != ' ')
127 		p->b_const.fconst.ci = (p->b_const.fconst.ci << shift) | hextoi(*s++);
128 return(p);
129 }
130 
131 
132 
133 
134 
mkstrcon(l,v)135 struct bigblock *mkstrcon(l,v)
136 int l;
137 register char *v;
138 {
139 register struct bigblock *p;
140 register char *s;
141 
142 p = mkconst(TYCHAR);
143 p->vleng = MKICON(l);
144 p->b_const.fconst.ccp = s = (char *) ckalloc(l);
145 while(--l >= 0)
146 	*s++ = *v++;
147 return(p);
148 }
149 
150 
mkcxcon(realp,imagp)151 struct bigblock *mkcxcon(realp,imagp)
152 register bigptr realp, imagp;
153 {
154 int rtype, itype;
155 register struct bigblock *p;
156 
157 rtype = realp->vtype;
158 itype = imagp->vtype;
159 
160 if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
161 	{
162 	p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX );
163 	if( ISINT(rtype) )
164 		p->b_const.fconst.cd[0] = realp->b_const.fconst.ci;
165 	else	p->b_const.fconst.cd[0] = realp->b_const.fconst.cd[0];
166 	if( ISINT(itype) )
167 		p->b_const.fconst.cd[1] = imagp->b_const.fconst.ci;
168 	else	p->b_const.fconst.cd[1] = imagp->b_const.fconst.cd[0];
169 	}
170 else
171 	{
172 	err("invalid complex constant");
173 	p = errnode();
174 	}
175 
176 frexpr(realp);
177 frexpr(imagp);
178 return(p);
179 }
180 
181 
errnode()182 struct bigblock *errnode()
183 {
184 struct bigblock *p;
185 p = BALLO();
186 p->tag = TERROR;
187 p->vtype = TYERROR;
188 return(p);
189 }
190 
191 
192 
193 
194 
mkconv(t,p)195 bigptr mkconv(t, p)
196 register int t;
197 register bigptr p;
198 {
199 register bigptr q;
200 
201 if(t==TYUNKNOWN || t==TYERROR)
202 	fatal1("mkconv of impossible type %d", t);
203 if(t == p->vtype)
204 	return(p);
205 
206 else if( ISCONST(p) && p->vtype!=TYADDR)
207 	{
208 	q = mkconst(t);
209 	consconv(t, &(q->b_const.fconst), p->vtype, &(p->b_const.fconst));
210 	frexpr(p);
211 	}
212 else
213 	{
214 	q = mkexpr(OPCONV, p, 0);
215 	q->vtype = t;
216 	}
217 return(q);
218 }
219 
220 
221 
addrof(p)222 struct bigblock *addrof(p)
223 bigptr p;
224 {
225 return( mkexpr(OPADDR, p, NULL) );
226 }
227 
228 
229 
230 bigptr
cpexpr(p)231 cpexpr(p)
232 register bigptr p;
233 {
234 register bigptr e;
235 int tag;
236 register chainp ep, pp;
237 
238 #if 0
239 static int blksize[ ] = { 0, sizeof(struct nameblock), sizeof(struct constblock),
240 		 sizeof(struct exprblock), sizeof(struct addrblock),
241 		 sizeof(struct primblock), sizeof(struct listblock),
242 		 sizeof(struct errorblock)
243 	};
244 #endif
245 
246 if(p == NULL)
247 	return(NULL);
248 
249 if( (tag = p->tag) == TNAME)
250 	return(p);
251 
252 #if 0
253 e = cpblock( blksize[p->tag] , p);
254 #else
255 e = cpblock( sizeof(struct bigblock) , p);
256 #endif
257 
258 switch(tag)
259 	{
260 	case TCONST:
261 		if(e->vtype == TYCHAR)
262 			{
263 			e->b_const.fconst.ccp = copyn(1+strlen(e->b_const.fconst.ccp), e->b_const.fconst.ccp);
264 			e->vleng = cpexpr(e->vleng);
265 			}
266 	case TERROR:
267 		break;
268 
269 	case TEXPR:
270 		e->b_expr.leftp = cpexpr(p->b_expr.leftp);
271 		e->b_expr.rightp = cpexpr(p->b_expr.rightp);
272 		break;
273 
274 	case TLIST:
275 		if((pp = p->b_list.listp))
276 			{
277 			ep = e->b_list.listp = mkchain( cpexpr(pp->chain.datap), NULL);
278 			for(pp = pp->chain.nextp ; pp ; pp = pp->chain.nextp)
279 				ep = ep->chain.nextp = mkchain( cpexpr(pp->chain.datap), NULL);
280 			}
281 		break;
282 
283 	case TADDR:
284 		e->vleng = cpexpr(e->vleng);
285 		e->b_addr.memoffset = cpexpr(e->b_addr.memoffset);
286 		e->b_addr.istemp = NO;
287 		break;
288 
289 	case TPRIM:
290 		e->b_prim.argsp = cpexpr(e->b_prim.argsp);
291 		e->b_prim.fcharp = cpexpr(e->b_prim.fcharp);
292 		e->b_prim.lcharp = cpexpr(e->b_prim.lcharp);
293 		break;
294 
295 	default:
296 		fatal1("cpexpr: impossible tag %d", tag);
297 	}
298 
299 return(e);
300 }
301 
302 void
frexpr(p)303 frexpr(p)
304 register bigptr p;
305 {
306 register chainp q;
307 
308 if(p == NULL)
309 	return;
310 
311 switch(p->tag)
312 	{
313 	case TCONST:
314 		if( ISCHAR(p) )
315 			{
316 			ckfree(p->b_const.fconst.ccp);
317 			frexpr(p->vleng);
318 			}
319 		break;
320 
321 	case TADDR:
322 		if(p->b_addr.istemp)
323 			{
324 			frtemp(p);
325 			return;
326 			}
327 		frexpr(p->vleng);
328 		frexpr(p->b_addr.memoffset);
329 		break;
330 
331 	case TERROR:
332 		break;
333 
334 	case TNAME:
335 		return;
336 
337 	case TPRIM:
338 		frexpr(p->b_prim.argsp);
339 		frexpr(p->b_prim.fcharp);
340 		frexpr(p->b_prim.lcharp);
341 		break;
342 
343 	case TEXPR:
344 		frexpr(p->b_expr.leftp);
345 		if(p->b_expr.rightp)
346 			frexpr(p->b_expr.rightp);
347 		break;
348 
349 	case TLIST:
350 		for(q = p->b_list.listp ; q ; q = q->chain.nextp)
351 			frexpr(q->chain.datap);
352 		frchain( &(p->b_list.listp) );
353 		break;
354 
355 	default:
356 		fatal1("frexpr: impossible tag %d", p->tag);
357 	}
358 
359 ckfree(p);
360 }
361 
362 /* fix up types in expression; replace subtrees and convert
363    names to address blocks */
364 
fixtype(p)365 bigptr fixtype(p)
366 register bigptr p;
367 {
368 
369 if(p == 0)
370 	return(0);
371 
372 switch(p->tag)
373 	{
374 	case TCONST:
375 		if( ! ONEOF(p->vtype, MSKINT|MSKLOGICAL|MSKADDR) )
376 			p = putconst(p);
377 		return(p);
378 
379 	case TADDR:
380 		p->b_addr.memoffset = fixtype(p->b_addr.memoffset);
381 		return(p);
382 
383 	case TERROR:
384 		return(p);
385 
386 	default:
387 		fatal1("fixtype: impossible tag %d", p->tag);
388 
389 	case TEXPR:
390 		return( fixexpr(p) );
391 
392 	case TLIST:
393 		return( p );
394 
395 	case TPRIM:
396 		if(p->b_prim.argsp && p->b_prim.namep->vclass!=CLVAR)
397 			return( mkfunct(p) );
398 		else	return( mklhs(p) );
399 	}
400 }
401 
402 
403 
404 
405 
406 /* special case tree transformations and cleanups of expression trees */
407 
fixexpr(p)408 bigptr fixexpr(p)
409 register struct bigblock *p;
410 {
411 bigptr lp;
412 register bigptr rp;
413 register bigptr q;
414 int opcode, ltype, rtype, ptype, mtype;
415 
416 if(p->tag == TERROR)
417 	return(p);
418 else if(p->tag != TEXPR)
419 	fatal1("fixexpr: invalid tag %d", p->tag);
420 opcode = p->b_expr.opcode;
421 lp = p->b_expr.leftp = fixtype(p->b_expr.leftp);
422 ltype = lp->vtype;
423 if(opcode==OPASSIGN && lp->tag!=TADDR)
424 	{
425 	err("left side of assignment must be variable");
426 	frexpr(p);
427 	return( errnode() );
428 	}
429 
430 if(p->b_expr.rightp)
431 	{
432 	rp = p->b_expr.rightp = fixtype(p->b_expr.rightp);
433 	rtype = rp->vtype;
434 	}
435 else
436 	{
437 	rp = NULL;
438 	rtype = 0;
439 	}
440 
441 /* force folding if possible */
442 if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
443 	{
444 	q = mkexpr(opcode, lp, rp);
445 	if( ISCONST(q) )
446 		return(q);
447 	ckfree(q);	/* constants did not fold */
448 	}
449 
450 if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
451 	{
452 	frexpr(p);
453 	return( errnode() );
454 	}
455 
456 switch(opcode)
457 	{
458 	case OPCONCAT:
459 		if(p->vleng == NULL)
460 			p->vleng = mkexpr(OPPLUS, cpexpr(lp->vleng),
461 				cpexpr(rp->vleng) );
462 		break;
463 
464 	case OPASSIGN:
465 		if(ltype == rtype)
466 			break;
467 		if( ! ISCONST(rp) && ISREAL(ltype) && ISREAL(rtype) )
468 			break;
469 		if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
470 			break;
471 		if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
472 		    && typesize[ltype]>=typesize[rtype] )
473 			break;
474 		p->b_expr.rightp = fixtype( mkconv(ptype, rp) );
475 		break;
476 
477 	case OPSLASH:
478 		if( ISCOMPLEX(rtype) )
479 			{
480 			p = call2(ptype, ptype==TYCOMPLEX? "c_div" : "z_div",
481 				mkconv(ptype, lp), mkconv(ptype, rp) );
482 			break;
483 			}
484 	case OPPLUS:
485 	case OPMINUS:
486 	case OPSTAR:
487 	case OPMOD:
488 		if(ptype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp) ) ||
489 		    (rtype==TYREAL && ! ISCONST(rp) ) ))
490 			break;
491 		if( ISCOMPLEX(ptype) )
492 			break;
493 		if(ltype != ptype)
494 			p->b_expr.leftp = fixtype(mkconv(ptype,lp));
495 		if(rtype != ptype)
496 			p->b_expr.rightp = fixtype(mkconv(ptype,rp));
497 		break;
498 
499 	case OPPOWER:
500 		return( mkpower(p) );
501 
502 	case OPLT:
503 	case OPLE:
504 	case OPGT:
505 	case OPGE:
506 	case OPEQ:
507 	case OPNE:
508 		if(ltype == rtype)
509 			break;
510 		mtype = cktype(OPMINUS, ltype, rtype);
511 		if(mtype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp)) ||
512 		    (rtype==TYREAL && ! ISCONST(rp)) ))
513 			break;
514 		if( ISCOMPLEX(mtype) )
515 			break;
516 		if(ltype != mtype)
517 			p->b_expr.leftp = fixtype(mkconv(mtype,lp));
518 		if(rtype != mtype)
519 			p->b_expr.rightp = fixtype(mkconv(mtype,rp));
520 		break;
521 
522 
523 	case OPCONV:
524 		ptype = cktype(OPCONV, p->vtype, ltype);
525 		if(lp->tag==TEXPR && lp->b_expr.opcode==OPCOMMA)
526 			{
527 			lp->b_expr.rightp = fixtype( mkconv(ptype, lp->b_expr.rightp) );
528 			ckfree(p);
529 			p = lp;
530 			}
531 		break;
532 
533 	case OPADDR:
534 		if(lp->tag==TEXPR && lp->b_expr.opcode==OPADDR)
535 			fatal("addr of addr");
536 		break;
537 
538 	case OPCOMMA:
539 		break;
540 
541 	case OPMIN:
542 	case OPMAX:
543 		ptype = p->vtype;
544 		break;
545 
546 	default:
547 		break;
548 	}
549 
550 p->vtype = ptype;
551 return(p);
552 }
553 
554 #if SZINT < SZLONG
555 /*
556    for efficient subscripting, replace long ints by shorts
557    in easy places
558 */
559 
shorten(p)560 bigptr shorten(p)
561 register bigptr p;
562 {
563 register bigptr q;
564 
565 if(p->vtype != TYLONG)
566 	return(p);
567 
568 switch(p->tag)
569 	{
570 	case TERROR:
571 	case TLIST:
572 		return(p);
573 
574 	case TCONST:
575 	case TADDR:
576 		return( mkconv(TYINT,p) );
577 
578 	case TEXPR:
579 		break;
580 
581 	default:
582 		fatal1("shorten: invalid tag %d", p->tag);
583 	}
584 
585 switch(p->opcode)
586 	{
587 	case OPPLUS:
588 	case OPMINUS:
589 	case OPSTAR:
590 		q = shorten( cpexpr(p->rightp) );
591 		if(q->vtype == TYINT)
592 			{
593 			p->leftp = shorten(p->leftp);
594 			if(p->leftp->vtype == TYLONG)
595 				frexpr(q);
596 			else
597 				{
598 				frexpr(p->rightp);
599 				p->rightp = q;
600 				p->vtype = TYINT;
601 				}
602 			}
603 		break;
604 
605 	case OPNEG:
606 		p->leftp = shorten(p->leftp);
607 		if(p->leftp->vtype == TYINT)
608 			p->vtype = TYINT;
609 		break;
610 
611 	case OPCALL:
612 	case OPCCALL:
613 		p = mkconv(TYINT,p);
614 		break;
615 	default:
616 		break;
617 	}
618 
619 return(p);
620 }
621 #endif
622 
623 int
fixargs(doput,p0)624 fixargs(doput, p0)
625 int doput;
626 struct bigblock *p0;
627 {
628 register chainp p;
629 register bigptr q, t;
630 register int qtag;
631 int nargs;
632 
633 nargs = 0;
634 if(p0)
635     for(p = p0->b_list.listp ; p ; p = p->chain.nextp)
636 	{
637 	++nargs;
638 	q = p->chain.datap;
639 	qtag = q->tag;
640 	if(qtag == TCONST)
641 		{
642 		if(q->vtype == TYSHORT)
643 			q = mkconv(tyint, q);
644 		if(doput)
645 			p->chain.datap = putconst(q);
646 		else
647 			p->chain.datap = q;
648 		}
649 	else if(qtag==TPRIM && q->b_prim.argsp==0 && q->b_prim.namep->vclass==CLPROC)
650 		p->chain.datap = mkaddr(q->b_prim.namep);
651 	else if(qtag==TPRIM && q->b_prim.argsp==0 && q->b_prim.namep->b_name.vdim!=NULL)
652 		p->chain.datap = mkscalar(q->b_prim.namep);
653 	else if(qtag==TPRIM && q->b_prim.argsp==0 && q->b_prim.namep->b_name.vdovar &&
654 		(t = memversion(q->b_prim.namep)) )
655 			p->chain.datap = fixtype(t);
656 	else	p->chain.datap = fixtype(q);
657 	}
658 return(nargs);
659 }
660 
661 struct bigblock *
mkscalar(np)662 mkscalar(np)
663 register struct bigblock *np;
664 {
665 register struct bigblock *ap;
666 
667 vardcl(np);
668 ap = mkaddr(np);
669 
670 #ifdef __vax__
671 	/* on the VAX, prolog causes array arguments
672 	   to point at the (0,...,0) element, except when
673 	   subscript checking is on
674 	*/
675 	if( !checksubs && np->vstg==STGARG)
676 		{
677 		register struct dimblock *dp;
678 		dp = np->vdim;
679 		frexpr(ap->memoffset);
680 		ap->memoffset = mkexpr(OPSTAR, MKICON(typesize[np->vtype]),
681 					cpexpr(dp->baseoffset) );
682 		}
683 #endif
684 return(ap);
685 }
686 
687 
688 
689 
690 
mkfunct(p)691 bigptr mkfunct(p)
692 register struct bigblock * p;
693 {
694 chainp ep;
695 struct bigblock *ap;
696 struct extsym *extp;
697 register struct bigblock *np;
698 register struct bigblock *q;
699 int k, nargs;
700 int class;
701 
702 np = p->b_prim.namep;
703 class = np->vclass;
704 
705 if(class == CLUNKNOWN)
706 	{
707 	np->vclass = class = CLPROC;
708 	if(np->vstg == STGUNKNOWN)
709 		{
710 		if((k = intrfunct(np->b_name.varname)))
711 			{
712 			np->vstg = STGINTR;
713 			np->b_name.vardesc.varno = k;
714 			np->b_name.vprocclass = PINTRINSIC;
715 			}
716 		else
717 			{
718 			extp = mkext( varunder(VL,np->b_name.varname) );
719 			extp->extstg = STGEXT;
720 			np->vstg = STGEXT;
721 			np->b_name.vardesc.varno = extp - extsymtab;
722 			np->b_name.vprocclass = PEXTERNAL;
723 			}
724 		}
725 	else if(np->vstg==STGARG)
726 		{
727 		if(np->vtype!=TYCHAR && !ftn66flag)
728 		    warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
729 		np->b_name.vprocclass = PEXTERNAL;
730 		}
731 	}
732 
733 if(class != CLPROC)
734 	fatal1("invalid class code for function", class);
735 if(p->b_prim.fcharp || p->b_prim.lcharp)
736 	{
737 	err("no substring of function call");
738 	goto error;
739 	}
740 impldcl(np);
741 nargs = fixargs( np->b_name.vprocclass!=PINTRINSIC,  p->b_prim.argsp);
742 
743 switch(np->b_name.vprocclass)
744 	{
745 	case PEXTERNAL:
746 		ap = mkaddr(np);
747 	call:
748 		q = mkexpr(OPCALL, ap, p->b_prim.argsp);
749 		q->vtype = np->vtype;
750 		if(np->vleng)
751 			q->vleng = cpexpr(np->vleng);
752 		break;
753 
754 	case PINTRINSIC:
755 		q = intrcall(np, p->b_prim.argsp, nargs);
756 		break;
757 
758 	case PSTFUNCT:
759 		q = stfcall(np, p->b_prim.argsp);
760 		break;
761 
762 	case PTHISPROC:
763 		warn("recursive call");
764 		for(ep = entries ; ep ; ep = ep->entrypoint.nextp)
765 			if(ep->entrypoint.enamep == np)
766 				break;
767 		if(ep == NULL)
768 			fatal("mkfunct: impossible recursion");
769 		ap = builtin(np->vtype, varstr(XL, ep->entrypoint.entryname->extname) );
770 		goto call;
771 
772 	default:
773 		fatal1("mkfunct: impossible vprocclass %d", np->b_name.vprocclass);
774 		q = 0; /* XXX gcc */
775 	}
776 ckfree(p);
777 return(q);
778 
779 error:
780 	frexpr(p);
781 	return( errnode() );
782 }
783 
784 
785 
786 LOCAL struct bigblock *
stfcall(struct bigblock * np,struct bigblock * actlist)787 stfcall(struct bigblock *np, struct bigblock *actlist)
788 {
789 	register chainp actuals;
790 	int nargs;
791 	chainp oactp, formals;
792 	int type;
793 	struct bigblock *q, *rhs;
794 	bigptr ap;
795 	register chainp rp;
796 	chainp tlist;
797 
798 	if(actlist) {
799 		actuals = actlist->b_list.listp;
800 		ckfree(actlist);
801 	} else
802 		actuals = NULL;
803 	oactp = actuals;
804 
805 	nargs = 0;
806 	tlist = NULL;
807 	type = np->vtype;
808 
809 	formals = (chainp)np->b_name.vardesc.vstfdesc->chain.datap;
810 	rhs = (bigptr)np->b_name.vardesc.vstfdesc->chain.nextp;
811 
812 	/* copy actual arguments into temporaries */
813 	while(actuals!=NULL && formals!=NULL) {
814 		rp = ALLOC(rplblock);
815 		rp->rplblock.rplnp = q = formals->chain.datap;
816 		ap = fixtype(actuals->chain.datap);
817 		if(q->vtype==ap->vtype && q->vtype!=TYCHAR
818 		   && (ap->tag==TCONST || ap->tag==TADDR) ) {
819 			rp->rplblock.rplvp = ap;
820 			rp->rplblock.rplxp = NULL;
821 			rp->rplblock.rpltag = ap->tag;
822 		} else	{
823 			rp->rplblock.rplvp = fmktemp(q->vtype, q->vleng);
824 			rp->rplblock.rplxp = fixtype( mkexpr(OPASSIGN,
825 			    cpexpr(rp->rplblock.rplvp), ap) );
826 			if( (rp->rplblock.rpltag =
827 			    rp->rplblock.rplxp->tag) == TERROR)
828 				err("disagreement of argument types in statement function call");
829 		}
830 		rp->rplblock.nextp = tlist;
831 		tlist = rp;
832 		actuals = actuals->chain.nextp;
833 		formals = formals->chain.nextp;
834 		++nargs;
835 	}
836 
837 	if(actuals!=NULL || formals!=NULL)
838 		err("statement function definition and argument list differ");
839 
840 	/*
841 	   now push down names involved in formal argument list, then
842 	   evaluate rhs of statement function definition in this environment
843 	*/
844 	rpllist = hookup(tlist, rpllist);
845 	q = mkconv(type, fixtype(cpexpr(rhs)) );
846 
847 	/* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
848 	while(--nargs >= 0) {
849 		if(rpllist->rplblock.rplxp)
850 			q = mkexpr(OPCOMMA, rpllist->rplblock.rplxp, q);
851 		rp = rpllist->rplblock.nextp;
852 		frexpr(rpllist->rplblock.rplvp);
853 		ckfree(rpllist);
854 		rpllist = rp;
855 	}
856 
857 	frchain( &oactp );
858 	return(q);
859 }
860 
861 
862 
863 
864 struct bigblock *
mklhs(struct bigblock * p)865 mklhs(struct bigblock *p)
866 {
867 	struct bigblock *s;
868 	struct bigblock *np;
869 	chainp rp;
870 	int regn;
871 
872 	/* first fixup name */
873 
874 	if(p->tag != TPRIM)
875 		return(p);
876 
877 	np = p->b_prim.namep;
878 
879 	/* is name on the replace list? */
880 
881 	for(rp = rpllist ; rp ; rp = rp->rplblock.nextp) {
882 		if(np == rp->rplblock.rplnp) {
883 			if(rp->rplblock.rpltag == TNAME) {
884 				np = p->b_prim.namep = rp->rplblock.rplvp;
885 				break;
886 			} else
887 				return( cpexpr(rp->rplblock.rplvp) );
888 		}
889 	}
890 
891 	/* is variable a DO index in a register ? */
892 
893 	if(np->b_name.vdovar && ( (regn = inregister(np)) >= 0) ) {
894 		if(np->vtype == TYERROR)
895 			return( errnode() );
896 		else {
897 			s = BALLO();
898 			s->tag = TADDR;
899 			s->vstg = STGREG;
900 			s->vtype = TYIREG;
901 			s->b_addr.memno = regn;
902 			s->b_addr.memoffset = MKICON(0);
903 			return(s);
904 		}
905 	}
906 
907 	vardcl(np);
908 	s = mkaddr(np);
909 	s->b_addr.memoffset = mkexpr(OPPLUS, s->b_addr.memoffset, suboffset(p) );
910 	frexpr(p->b_prim.argsp);
911 	p->b_prim.argsp = NULL;
912 
913 	/* now do substring part */
914 
915 	if(p->b_prim.fcharp || p->b_prim.lcharp) {
916 		if(np->vtype != TYCHAR)
917 			err1("substring of noncharacter %s",
918 			    varstr(VL,np->b_name.varname));
919 		else	{
920 			if(p->b_prim.lcharp == NULL)
921 				p->b_prim.lcharp = cpexpr(s->vleng);
922 			if(p->b_prim.fcharp)
923 				s->vleng = mkexpr(OPMINUS, p->b_prim.lcharp,
924 					mkexpr(OPMINUS, p->b_prim.fcharp, MKICON(1) ));
925 			else	{
926 				frexpr(s->vleng);
927 				s->vleng = p->b_prim.lcharp;
928 			}
929 		}
930 	}
931 
932 	s->vleng = fixtype( s->vleng );
933 	s->b_addr.memoffset = fixtype( s->b_addr.memoffset );
934 	ckfree(p);
935 	return(s);
936 }
937 
938 
939 
940 
941 void
deregister(np)942 deregister(np)
943 struct bigblock *np;
944 {
945 }
946 
947 
948 
949 
memversion(np)950 struct bigblock *memversion(np)
951 register struct bigblock *np;
952 {
953 register struct bigblock *s;
954 
955 if(np->b_name.vdovar==NO || (inregister(np)<0) )
956 	return(NULL);
957 np->b_name.vdovar = NO;
958 s = mklhs( mkprim(np, 0,0,0) );
959 np->b_name.vdovar = YES;
960 return(s);
961 }
962 
963 
964 int
inregister(np)965 inregister(np)
966 register struct bigblock *np;
967 {
968 return(-1);
969 }
970 
971 
972 
973 int
enregister(np)974 enregister(np)
975 struct bigblock *np;
976 {
977 	return(NO);
978 }
979 
980 
981 
982 
suboffset(p)983 bigptr suboffset(p)
984 register struct bigblock *p;
985 {
986 int n;
987 bigptr size;
988 chainp cp;
989 bigptr offp, prod;
990 struct dimblock *dimp;
991 bigptr sub[8];
992 register struct bigblock *np;
993 
994 np = p->b_prim.namep;
995 offp = MKICON(0);
996 n = 0;
997 if(p->b_prim.argsp)
998 	for(cp = p->b_prim.argsp->b_list.listp ; cp ; cp = cp->chain.nextp)
999 		{
1000 		sub[n++] = fixtype(cpexpr(cp->chain.datap));
1001 		if(n > 7)
1002 			{
1003 			err("more than 7 subscripts");
1004 			break;
1005 			}
1006 		}
1007 
1008 dimp = np->b_name.vdim;
1009 if(n>0 && dimp==NULL)
1010 	err("subscripts on scalar variable");
1011 else if(dimp && dimp->ndim!=n)
1012 	err1("wrong number of subscripts on %s",
1013 		varstr(VL, np->b_name.varname) );
1014 else if(n > 0)
1015 	{
1016 	prod = sub[--n];
1017 	while( --n >= 0)
1018 		prod = mkexpr(OPPLUS, sub[n],
1019 			mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
1020 #ifdef __vax__
1021 	if(checksubs || np->vstg!=STGARG)
1022 		prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1023 #else
1024 	prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1025 #endif
1026 	if(checksubs)
1027 		prod = subcheck(np, prod);
1028 	if(np->vtype == TYCHAR)
1029 		size = cpexpr(np->vleng);
1030 	else	size = MKICON( typesize[np->vtype] );
1031 	prod = mkexpr(OPSTAR, prod, size);
1032 	offp = mkexpr(OPPLUS, offp, prod);
1033 	}
1034 
1035 if(p->b_prim.fcharp && np->vtype==TYCHAR)
1036 	offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->b_prim.fcharp), MKICON(1) ));
1037 
1038 return(offp);
1039 }
1040 
1041 
1042 /*
1043  * Check if an array is addressed out of bounds.
1044  */
1045 bigptr
subcheck(struct bigblock * np,bigptr p)1046 subcheck(struct bigblock *np, bigptr p)
1047 {
1048 	struct dimblock *dimp;
1049 	bigptr t, badcall;
1050 	int l1, l2;
1051 
1052 	dimp = np->b_name.vdim;
1053 	if(dimp->nelt == NULL)
1054 		return(p);	/* don't check arrays with * bounds */
1055 	if( ISICON(p) ) {
1056 		if(p->b_const.fconst.ci < 0)
1057 			goto badsub;
1058 		if( ISICON(dimp->nelt) ) {
1059 			if(p->b_const.fconst.ci < dimp->nelt->b_const.fconst.ci)
1060 				return(p);
1061 			else
1062 				goto badsub;
1063 		}
1064 	}
1065 
1066 	if (p->tag==TADDR && p->vstg==STGREG) {
1067 		t = p;
1068 	} else {
1069 		t = fmktemp(p->vtype, NULL);
1070 		putexpr(mkexpr(OPASSIGN, cpexpr(t), p));
1071 	}
1072 	/* t now cotains evaluated expression */
1073 
1074 	l1 = newlabel();
1075 	l2 = newlabel();
1076 	putif(mkexpr(OPLT, cpexpr(t), cpexpr(dimp->nelt)), l1);
1077 	putif(mkexpr(OPGE, cpexpr(t), MKICON(0)), l1);
1078 	putgoto(l2);
1079 	putlabel(l1);
1080 
1081 	badcall = call4(t->vtype, "s_rnge", mkstrcon(VL, np->b_name.varname),
1082 		mkconv(TYLONG,  cpexpr(t)),
1083 		mkstrcon(XL, procname), MKICON(lineno));
1084 	badcall->b_expr.opcode = OPCCALL;
1085 
1086 	putexpr(badcall);
1087 	putlabel(l2);
1088 	return t;
1089 
1090 badsub:
1091 	frexpr(p);
1092 	err1("subscript on variable %s out of range",
1093 	    varstr(VL,np->b_name.varname));
1094 	return ( MKICON(0) );
1095 }
1096 
1097 
1098 
1099 
mkaddr(p)1100 struct bigblock *mkaddr(p)
1101 register struct bigblock *p;
1102 {
1103 struct extsym *extp;
1104 register struct bigblock *t;
1105 
1106 switch( p->vstg)
1107 	{
1108 	case STGUNKNOWN:
1109 		if(p->vclass != CLPROC)
1110 			break;
1111 		extp = mkext( varunder(VL, p->b_name.varname) );
1112 		extp->extstg = STGEXT;
1113 		p->vstg = STGEXT;
1114 		p->b_name.vardesc.varno = extp - extsymtab;
1115 		p->b_name.vprocclass = PEXTERNAL;
1116 
1117 	case STGCOMMON:
1118 	case STGEXT:
1119 	case STGBSS:
1120 	case STGINIT:
1121 	case STGEQUIV:
1122 	case STGARG:
1123 	case STGLENG:
1124 	case STGAUTO:
1125 		t = BALLO();
1126 		t->tag = TADDR;
1127 		t->vclass = p->vclass;
1128 		t->vtype = p->vtype;
1129 		t->vstg = p->vstg;
1130 		t->b_addr.memno = p->b_name.vardesc.varno;
1131 		t->b_addr.memoffset = MKICON(p->b_name.voffset);
1132 		if(p->vleng)
1133 			t->vleng = cpexpr(p->vleng);
1134 		return(t);
1135 
1136 	case STGINTR:
1137 		return( intraddr(p) );
1138 
1139 	}
1140 /*debug*/ fprintf(diagfile, "mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
1141 fatal1("mkaddr: impossible storage tag %d", p->vstg);
1142 /* NOTREACHED */
1143 return 0; /* XXX gcc */
1144 }
1145 
1146 
1147 
1148 struct bigblock *
mkarg(type,argno)1149 mkarg(type, argno)
1150 int type, argno;
1151 {
1152 register struct bigblock *p;
1153 
1154 p = BALLO();
1155 p->tag = TADDR;
1156 p->vtype = type;
1157 p->vclass = CLVAR;
1158 p->vstg = (type==TYLENG ? STGLENG : STGARG);
1159 p->b_addr.memno = argno;
1160 return(p);
1161 }
1162 
1163 
1164 
1165 
mkprim(v,args,lstr,rstr)1166 bigptr mkprim(v, args, lstr, rstr)
1167 register bigptr v;
1168 struct bigblock *args;
1169 bigptr lstr, rstr;
1170 {
1171 register struct bigblock *p;
1172 
1173 if(v->vclass == CLPARAM)
1174 	{
1175 	if(args || lstr || rstr)
1176 		{
1177 		err1("no qualifiers on parameter name", varstr(VL,v->b_name.varname));
1178 		frexpr(args);
1179 		frexpr(lstr);
1180 		frexpr(rstr);
1181 		frexpr(v);
1182 		return( errnode() );
1183 		}
1184 	return( cpexpr(v->b_param.paramval) );
1185 	}
1186 
1187 p = BALLO();
1188 p->tag = TPRIM;
1189 p->vtype = v->vtype;
1190 p->b_prim.namep = v;
1191 p->b_prim.argsp = args;
1192 p->b_prim.fcharp = lstr;
1193 p->b_prim.lcharp = rstr;
1194 return(p);
1195 }
1196 
1197 
1198 void
vardcl(v)1199 vardcl(v)
1200 register struct bigblock *v;
1201 {
1202 int nelt;
1203 struct dimblock *t;
1204 struct bigblock *p;
1205 bigptr neltp;
1206 
1207 if(v->b_name.vdcldone) return;
1208 
1209 if(v->vtype == TYUNKNOWN)
1210 	impldcl(v);
1211 if(v->vclass == CLUNKNOWN)
1212 	v->vclass = CLVAR;
1213 else if(v->vclass!=CLVAR && v->b_name.vprocclass!=PTHISPROC)
1214 	{
1215 	dclerr("used as variable", v);
1216 	return;
1217 	}
1218 if(v->vstg==STGUNKNOWN)
1219 	v->vstg = implstg[ letter(v->b_name.varname[0]) ];
1220 
1221 switch(v->vstg)
1222 	{
1223 	case STGBSS:
1224 		v->b_name.vardesc.varno = ++lastvarno;
1225 		break;
1226 	case STGAUTO:
1227 		if(v->vclass==CLPROC && v->b_name.vprocclass==PTHISPROC)
1228 			break;
1229 		nelt = 1;
1230 		if((t = v->b_name.vdim)) {
1231 			if( (neltp = t->nelt) && ISCONST(neltp) )
1232 				nelt = neltp->b_const.fconst.ci;
1233 			else
1234 				dclerr("adjustable automatic array", v);
1235 		}
1236 		p = autovar(nelt, v->vtype, v->vleng);
1237 		v->b_name.voffset = p->b_addr.memoffset->b_const.fconst.ci;
1238 		frexpr(p);
1239 		break;
1240 
1241 	default:
1242 		break;
1243 	}
1244 v->b_name.vdcldone = YES;
1245 }
1246 
1247 
1248 
1249 void
impldcl(p)1250 impldcl(p)
1251 register struct bigblock *p;
1252 {
1253 register int k;
1254 int type, leng;
1255 
1256 if(p->b_name.vdcldone || (p->vclass==CLPROC && p->b_name.vprocclass==PINTRINSIC) )
1257 	return;
1258 if(p->vtype == TYUNKNOWN)
1259 	{
1260 	k = letter(p->b_name.varname[0]);
1261 	type = impltype[ k ];
1262 	leng = implleng[ k ];
1263 	if(type == TYUNKNOWN)
1264 		{
1265 		if(p->vclass == CLPROC)
1266 			return;
1267 		dclerr("attempt to use undefined variable", p);
1268 		type = TYERROR;
1269 		leng = 1;
1270 		}
1271 	settype(p, type, leng);
1272 	}
1273 }
1274 
1275 
1276 
1277 
1278 LOCAL int
letter(c)1279 letter(c)
1280 register int c;
1281 {
1282 if( isupper(c) )
1283 	c = tolower(c);
1284 return(c - 'a');
1285 }
1286 
1287 #define ICONEQ(z, c)  (ISICON(z) && z->b_const.fconst.ci==c)
1288 #define COMMUTE	{ e = lp;  lp = rp;  rp = e; }
1289 
1290 
1291 struct bigblock *
mkexpr(opcode,lp,rp)1292 mkexpr(opcode, lp, rp)
1293 int opcode;
1294 register bigptr lp, rp;
1295 {
1296 register struct bigblock *e, *e1;
1297 int etype;
1298 int ltype, rtype;
1299 int ltag, rtag;
1300 
1301 ltype = lp->vtype;
1302 ltag = lp->tag;
1303 if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1304 	{
1305 	rtype = rp->vtype;
1306 	rtag = rp->tag;
1307 	}
1308 else  rtype = rtag = 0;
1309 
1310 etype = cktype(opcode, ltype, rtype);
1311 if(etype == TYERROR)
1312 	goto error;
1313 
1314 switch(opcode)
1315 	{
1316 	/* check for multiplication by 0 and 1 and addition to 0 */
1317 
1318 	case OPSTAR:
1319 		if( ISCONST(lp) )
1320 			COMMUTE
1321 
1322 		if( ISICON(rp) )
1323 			{
1324 			if(rp->b_const.fconst.ci == 0)
1325 				goto retright;
1326 			goto mulop;
1327 			}
1328 		break;
1329 
1330 	case OPSLASH:
1331 	case OPMOD:
1332 		if( ICONEQ(rp, 0) )
1333 			{
1334 			err("attempted division by zero");
1335 			rp = MKICON(1);
1336 			break;
1337 			}
1338 		if(opcode == OPMOD)
1339 			break;
1340 
1341 
1342 	mulop:
1343 		if( ISICON(rp) )
1344 			{
1345 			if(rp->b_const.fconst.ci == 1)
1346 				goto retleft;
1347 
1348 			if(rp->b_const.fconst.ci == -1)
1349 				{
1350 				frexpr(rp);
1351 				return( mkexpr(OPNEG, lp, 0) );
1352 				}
1353 			}
1354 
1355 		if( ISSTAROP(lp) && ISICON(lp->b_expr.rightp) )
1356 			{
1357 			if(opcode == OPSTAR)
1358 				e = mkexpr(OPSTAR, lp->b_expr.rightp, rp);
1359 			else  if(ISICON(rp) && lp->b_expr.rightp->b_const.fconst.ci % rp->b_const.fconst.ci == 0)
1360 				e = mkexpr(OPSLASH, lp->b_expr.rightp, rp);
1361 			else	break;
1362 
1363 			e1 = lp->b_expr.leftp;
1364 			ckfree(lp);
1365 			return( mkexpr(OPSTAR, e1, e) );
1366 			}
1367 		break;
1368 
1369 
1370 	case OPPLUS:
1371 		if( ISCONST(lp) )
1372 			COMMUTE
1373 		goto addop;
1374 
1375 	case OPMINUS:
1376 		if( ICONEQ(lp, 0) )
1377 			{
1378 			frexpr(lp);
1379 			return( mkexpr(OPNEG, rp, 0) );
1380 			}
1381 
1382 		if( ISCONST(rp) )
1383 			{
1384 			opcode = OPPLUS;
1385 			consnegop(rp);
1386 			}
1387 
1388 	addop:
1389 		if( ISICON(rp) )
1390 			{
1391 			if(rp->b_const.fconst.ci == 0)
1392 				goto retleft;
1393 			if( ISPLUSOP(lp) && ISICON(lp->b_expr.rightp) )
1394 				{
1395 				e = mkexpr(OPPLUS, lp->b_expr.rightp, rp);
1396 				e1 = lp->b_expr.leftp;
1397 				ckfree(lp);
1398 				return( mkexpr(OPPLUS, e1, e) );
1399 				}
1400 			}
1401 		break;
1402 
1403 
1404 	case OPPOWER:
1405 		break;
1406 
1407 	case OPNEG:
1408 		if(ltag==TEXPR && lp->b_expr.opcode==OPNEG)
1409 			{
1410 			e = lp->b_expr.leftp;
1411 			ckfree(lp);
1412 			return(e);
1413 			}
1414 		break;
1415 
1416 	case OPNOT:
1417 		if(ltag==TEXPR && lp->b_expr.opcode==OPNOT)
1418 			{
1419 			e = lp->b_expr.leftp;
1420 			ckfree(lp);
1421 			return(e);
1422 			}
1423 		break;
1424 
1425 	case OPCALL:
1426 	case OPCCALL:
1427 		etype = ltype;
1428 		if(rp!=NULL && rp->b_list.listp==NULL)
1429 			{
1430 			ckfree(rp);
1431 			rp = NULL;
1432 			}
1433 		break;
1434 
1435 	case OPAND:
1436 	case OPOR:
1437 		if( ISCONST(lp) )
1438 			COMMUTE
1439 
1440 		if( ISCONST(rp) )
1441 			{
1442 			if(rp->b_const.fconst.ci == 0)
1443 				if(opcode == OPOR)
1444 					goto retleft;
1445 				else
1446 					goto retright;
1447 			else if(opcode == OPOR)
1448 				goto retright;
1449 			else
1450 				goto retleft;
1451 			}
1452 	case OPEQV:
1453 	case OPNEQV:
1454 
1455 	case OPBITAND:
1456 	case OPBITOR:
1457 	case OPBITXOR:
1458 	case OPBITNOT:
1459 	case OPLSHIFT:
1460 	case OPRSHIFT:
1461 
1462 	case OPLT:
1463 	case OPGT:
1464 	case OPLE:
1465 	case OPGE:
1466 	case OPEQ:
1467 	case OPNE:
1468 
1469 	case OPCONCAT:
1470 		break;
1471 	case OPMIN:
1472 	case OPMAX:
1473 
1474 	case OPASSIGN:
1475 
1476 	case OPCONV:
1477 	case OPADDR:
1478 
1479 	case OPCOMMA:
1480 		break;
1481 
1482 	default:
1483 		fatal1("mkexpr: impossible opcode %d", opcode);
1484 	}
1485 
1486 e = BALLO();
1487 e->tag = TEXPR;
1488 e->b_expr.opcode = opcode;
1489 e->vtype = etype;
1490 e->b_expr.leftp = lp;
1491 e->b_expr.rightp = rp;
1492 if(ltag==TCONST && (rp==0 || rtag==TCONST) )
1493 	e = fold(e);
1494 return(e);
1495 
1496 retleft:
1497 	frexpr(rp);
1498 	return(lp);
1499 
1500 retright:
1501 	frexpr(lp);
1502 	return(rp);
1503 
1504 error:
1505 	frexpr(lp);
1506 	if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1507 		frexpr(rp);
1508 	return( errnode() );
1509 }
1510 
1511 #define ERR(s)   { errs = s; goto error; }
1512 
1513 int
cktype(op,lt,rt)1514 cktype(op, lt, rt)
1515 register int op, lt, rt;
1516 {
1517 char *errs = NULL; /* XXX gcc */
1518 
1519 if(lt==TYERROR || rt==TYERROR)
1520 	goto error1;
1521 
1522 if(lt==TYUNKNOWN)
1523 	return(TYUNKNOWN);
1524 if(rt==TYUNKNOWN)
1525 	if(op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && op!=OPCCALL && op!=OPADDR)
1526 		return(TYUNKNOWN);
1527 
1528 switch(op)
1529 	{
1530 	case OPPLUS:
1531 	case OPMINUS:
1532 	case OPSTAR:
1533 	case OPSLASH:
1534 	case OPPOWER:
1535 	case OPMOD:
1536 		if( ISNUMERIC(lt) && ISNUMERIC(rt) )
1537 			return( maxtype(lt, rt) );
1538 		ERR("nonarithmetic operand of arithmetic operator")
1539 
1540 	case OPNEG:
1541 		if( ISNUMERIC(lt) )
1542 			return(lt);
1543 		ERR("nonarithmetic operand of negation")
1544 
1545 	case OPNOT:
1546 		if(lt == TYLOGICAL)
1547 			return(TYLOGICAL);
1548 		ERR("NOT of nonlogical")
1549 
1550 	case OPAND:
1551 	case OPOR:
1552 	case OPEQV:
1553 	case OPNEQV:
1554 		if(lt==TYLOGICAL && rt==TYLOGICAL)
1555 			return(TYLOGICAL);
1556 		ERR("nonlogical operand of logical operator")
1557 
1558 	case OPLT:
1559 	case OPGT:
1560 	case OPLE:
1561 	case OPGE:
1562 	case OPEQ:
1563 	case OPNE:
1564 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
1565 			{
1566 			if(lt != rt)
1567 				ERR("illegal comparison")
1568 			}
1569 
1570 		else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
1571 			{
1572 			if(op!=OPEQ && op!=OPNE)
1573 				ERR("order comparison of complex data")
1574 			}
1575 
1576 		else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
1577 			ERR("comparison of nonarithmetic data")
1578 		return(TYLOGICAL);
1579 
1580 	case OPCONCAT:
1581 		if(lt==TYCHAR && rt==TYCHAR)
1582 			return(TYCHAR);
1583 		ERR("concatenation of nonchar data")
1584 
1585 	case OPCALL:
1586 	case OPCCALL:
1587 		return(lt);
1588 
1589 	case OPADDR:
1590 		return(TYADDR);
1591 
1592 	case OPCONV:
1593 		if(rt == 0)
1594 			return(0);
1595 	case OPASSIGN:
1596 		if( ISINT(lt) && rt==TYCHAR)
1597 			return(lt);
1598 		if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
1599 			if(op!=OPASSIGN || lt!=rt)
1600 				{
1601 /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
1602 /* debug fatal("impossible conversion.  possible compiler bug"); */
1603 				ERR("impossible conversion")
1604 				}
1605 		return(lt);
1606 
1607 	case OPMIN:
1608 	case OPMAX:
1609 	case OPBITOR:
1610 	case OPBITAND:
1611 	case OPBITXOR:
1612 	case OPBITNOT:
1613 	case OPLSHIFT:
1614 	case OPRSHIFT:
1615 		return(lt);
1616 
1617 	case OPCOMMA:
1618 		return(rt);
1619 
1620 	default:
1621 		fatal1("cktype: impossible opcode %d", op);
1622 	}
1623 error:	err(errs);
1624 error1:	return(TYERROR);
1625 }
1626 
fold(e)1627 LOCAL bigptr fold(e)
1628 register struct bigblock *e;
1629 {
1630 struct bigblock *p;
1631 register bigptr lp, rp;
1632 int etype, mtype, ltype, rtype, opcode;
1633 int i, ll, lr;
1634 char *q, *s;
1635 union constant lcon, rcon;
1636 
1637 opcode = e->b_expr.opcode;
1638 etype = e->vtype;
1639 
1640 lp = e->b_expr.leftp;
1641 ltype = lp->vtype;
1642 rp = e->b_expr.rightp;
1643 
1644 if(rp == 0)
1645 	switch(opcode)
1646 		{
1647 		case OPNOT:
1648 			lp->b_const.fconst.ci = ! lp->b_const.fconst.ci;
1649 			return(lp);
1650 
1651 		case OPBITNOT:
1652 			lp->b_const.fconst.ci = ~ lp->b_const.fconst.ci;
1653 			return(lp);
1654 
1655 		case OPNEG:
1656 			consnegop(lp);
1657 			return(lp);
1658 
1659 		case OPCONV:
1660 		case OPADDR:
1661 			return(e);
1662 
1663 		default:
1664 			fatal1("fold: invalid unary operator %d", opcode);
1665 		}
1666 
1667 rtype = rp->vtype;
1668 
1669 p = BALLO();
1670 p->tag = TCONST;
1671 p->vtype = etype;
1672 p->vleng = e->vleng;
1673 
1674 switch(opcode)
1675 	{
1676 	case OPCOMMA:
1677 		return(e);
1678 
1679 	case OPAND:
1680 		p->b_const.fconst.ci = lp->b_const.fconst.ci && rp->b_const.fconst.ci;
1681 		break;
1682 
1683 	case OPOR:
1684 		p->b_const.fconst.ci = lp->b_const.fconst.ci || rp->b_const.fconst.ci;
1685 		break;
1686 
1687 	case OPEQV:
1688 		p->b_const.fconst.ci = lp->b_const.fconst.ci == rp->b_const.fconst.ci;
1689 		break;
1690 
1691 	case OPNEQV:
1692 		p->b_const.fconst.ci = lp->b_const.fconst.ci != rp->b_const.fconst.ci;
1693 		break;
1694 
1695 	case OPBITAND:
1696 		p->b_const.fconst.ci = lp->b_const.fconst.ci & rp->b_const.fconst.ci;
1697 		break;
1698 
1699 	case OPBITOR:
1700 		p->b_const.fconst.ci = lp->b_const.fconst.ci | rp->b_const.fconst.ci;
1701 		break;
1702 
1703 	case OPBITXOR:
1704 		p->b_const.fconst.ci = lp->b_const.fconst.ci ^ rp->b_const.fconst.ci;
1705 		break;
1706 
1707 	case OPLSHIFT:
1708 		p->b_const.fconst.ci = lp->b_const.fconst.ci << rp->b_const.fconst.ci;
1709 		break;
1710 
1711 	case OPRSHIFT:
1712 		p->b_const.fconst.ci = lp->b_const.fconst.ci >> rp->b_const.fconst.ci;
1713 		break;
1714 
1715 	case OPCONCAT:
1716 		ll = lp->vleng->b_const.fconst.ci;
1717 		lr = rp->vleng->b_const.fconst.ci;
1718 		p->b_const.fconst.ccp = q = (char *) ckalloc(ll+lr);
1719 		p->vleng = MKICON(ll+lr);
1720 		s = lp->b_const.fconst.ccp;
1721 		for(i = 0 ; i < ll ; ++i)
1722 			*q++ = *s++;
1723 		s = rp->b_const.fconst.ccp;
1724 		for(i = 0; i < lr; ++i)
1725 			*q++ = *s++;
1726 		break;
1727 
1728 
1729 	case OPPOWER:
1730 		if( ! ISINT(rtype) )
1731 			return(e);
1732 		conspower(&(p->b_const.fconst), lp, rp->b_const.fconst.ci);
1733 		break;
1734 
1735 
1736 	default:
1737 		if(ltype == TYCHAR)
1738 			{
1739 			lcon.ci = cmpstr(lp->b_const.fconst.ccp, rp->b_const.fconst.ccp,
1740 					lp->vleng->b_const.fconst.ci, rp->vleng->b_const.fconst.ci);
1741 			rcon.ci = 0;
1742 			mtype = tyint;
1743 			}
1744 		else	{
1745 			mtype = maxtype(ltype, rtype);
1746 			consconv(mtype, &lcon, ltype, &(lp->b_const.fconst) );
1747 			consconv(mtype, &rcon, rtype, &(rp->b_const.fconst) );
1748 			}
1749 		consbinop(opcode, mtype, &(p->b_const.fconst), &lcon, &rcon);
1750 		break;
1751 	}
1752 
1753 frexpr(e);
1754 return(p);
1755 }
1756 
1757 
1758 
1759 /* assign constant l = r , doing coercion */
1760 void
consconv(lt,lv,rt,rv)1761 consconv(lt, lv, rt, rv)
1762 int lt, rt;
1763 register union constant *lv, *rv;
1764 {
1765 switch(lt)
1766 	{
1767 	case TYSHORT:
1768 	case TYLONG:
1769 		if( ISINT(rt) )
1770 			lv->ci = rv->ci;
1771 		else	lv->ci = rv->cd[0];
1772 		break;
1773 
1774 	case TYCOMPLEX:
1775 	case TYDCOMPLEX:
1776 		switch(rt)
1777 			{
1778 			case TYSHORT:
1779 			case TYLONG:
1780 				/* fall through and do real assignment of
1781 				   first element
1782 				*/
1783 			case TYREAL:
1784 			case TYDREAL:
1785 				lv->cd[1] = 0; break;
1786 			case TYCOMPLEX:
1787 			case TYDCOMPLEX:
1788 				lv->cd[1] = rv->cd[1]; break;
1789 			}
1790 
1791 	case TYREAL:
1792 	case TYDREAL:
1793 		if( ISINT(rt) )
1794 			lv->cd[0] = rv->ci;
1795 		else	lv->cd[0] = rv->cd[0];
1796 		break;
1797 
1798 	case TYLOGICAL:
1799 		lv->ci = rv->ci;
1800 		break;
1801 	}
1802 }
1803 
1804 
1805 void
consnegop(p)1806 consnegop(p)
1807 register struct bigblock *p;
1808 {
1809 switch(p->vtype)
1810 	{
1811 	case TYSHORT:
1812 	case TYLONG:
1813 		p->b_const.fconst.ci = - p->b_const.fconst.ci;
1814 		break;
1815 
1816 	case TYCOMPLEX:
1817 	case TYDCOMPLEX:
1818 		p->b_const.fconst.cd[1] = - p->b_const.fconst.cd[1];
1819 		/* fall through and do the real parts */
1820 	case TYREAL:
1821 	case TYDREAL:
1822 		p->b_const.fconst.cd[0] = - p->b_const.fconst.cd[0];
1823 		break;
1824 	default:
1825 		fatal1("consnegop: impossible type %d", p->vtype);
1826 	}
1827 }
1828 
1829 
1830 
1831 LOCAL void
conspower(powp,ap,n)1832 conspower(powp, ap, n)
1833 register union constant *powp;
1834 struct bigblock *ap;
1835 ftnint n;
1836 {
1837 register int type;
1838 union constant x;
1839 
1840 switch(type = ap->vtype)	/* pow = 1 */
1841 	{
1842 	case TYSHORT:
1843 	case TYLONG:
1844 		powp->ci = 1;
1845 		break;
1846 	case TYCOMPLEX:
1847 	case TYDCOMPLEX:
1848 		powp->cd[1] = 0;
1849 	case TYREAL:
1850 	case TYDREAL:
1851 		powp->cd[0] = 1;
1852 		break;
1853 	default:
1854 		fatal1("conspower: invalid type %d", type);
1855 	}
1856 
1857 if(n == 0)
1858 	return;
1859 if(n < 0)
1860 	{
1861 	if( ISINT(type) )
1862 		{
1863 		err("integer ** negative power ");
1864 		return;
1865 		}
1866 	n = - n;
1867 	consbinop(OPSLASH, type, &x, powp, &(ap->b_const.fconst));
1868 	}
1869 else
1870 	consbinop(OPSTAR, type, &x, powp, &(ap->b_const.fconst));
1871 
1872 for( ; ; )
1873 	{
1874 	if(n & 01)
1875 		consbinop(OPSTAR, type, powp, powp, &x);
1876 	if(n >>= 1)
1877 		consbinop(OPSTAR, type, &x, &x, &x);
1878 	else
1879 		break;
1880 	}
1881 }
1882 
1883 
1884 
1885 /* do constant operation cp = a op b */
1886 
1887 
1888 LOCAL void
consbinop(opcode,type,cp,ap,bp)1889 consbinop(opcode, type, cp, ap, bp)
1890 int opcode, type;
1891 register union constant *ap, *bp, *cp;
1892 {
1893 int k;
1894 double temp;
1895 
1896 switch(opcode)
1897 	{
1898 	case OPPLUS:
1899 		switch(type)
1900 			{
1901 			case TYSHORT:
1902 			case TYLONG:
1903 				cp->ci = ap->ci + bp->ci;
1904 				break;
1905 			case TYCOMPLEX:
1906 			case TYDCOMPLEX:
1907 				cp->cd[1] = ap->cd[1] + bp->cd[1];
1908 			case TYREAL:
1909 			case TYDREAL:
1910 				cp->cd[0] = ap->cd[0] + bp->cd[0];
1911 				break;
1912 			}
1913 		break;
1914 
1915 	case OPMINUS:
1916 		switch(type)
1917 			{
1918 			case TYSHORT:
1919 			case TYLONG:
1920 				cp->ci = ap->ci - bp->ci;
1921 				break;
1922 			case TYCOMPLEX:
1923 			case TYDCOMPLEX:
1924 				cp->cd[1] = ap->cd[1] - bp->cd[1];
1925 			case TYREAL:
1926 			case TYDREAL:
1927 				cp->cd[0] = ap->cd[0] - bp->cd[0];
1928 				break;
1929 			}
1930 		break;
1931 
1932 	case OPSTAR:
1933 		switch(type)
1934 			{
1935 			case TYSHORT:
1936 			case TYLONG:
1937 				cp->ci = ap->ci * bp->ci;
1938 				break;
1939 			case TYREAL:
1940 			case TYDREAL:
1941 				cp->cd[0] = ap->cd[0] * bp->cd[0];
1942 				break;
1943 			case TYCOMPLEX:
1944 			case TYDCOMPLEX:
1945 				temp = ap->cd[0] * bp->cd[0] -
1946 					    ap->cd[1] * bp->cd[1] ;
1947 				cp->cd[1] = ap->cd[0] * bp->cd[1] +
1948 					    ap->cd[1] * bp->cd[0] ;
1949 				cp->cd[0] = temp;
1950 				break;
1951 			}
1952 		break;
1953 	case OPSLASH:
1954 		switch(type)
1955 			{
1956 			case TYSHORT:
1957 			case TYLONG:
1958 				cp->ci = ap->ci / bp->ci;
1959 				break;
1960 			case TYREAL:
1961 			case TYDREAL:
1962 				cp->cd[0] = ap->cd[0] / bp->cd[0];
1963 				break;
1964 			case TYCOMPLEX:
1965 			case TYDCOMPLEX:
1966 				zdiv(&cp->dc, &ap->dc, &bp->dc);
1967 				break;
1968 			}
1969 		break;
1970 
1971 	case OPMOD:
1972 		if( ISINT(type) )
1973 			{
1974 			cp->ci = ap->ci % bp->ci;
1975 			break;
1976 			}
1977 		else
1978 			fatal("inline mod of noninteger");
1979 
1980 	default:	  /* relational ops */
1981 		switch(type)
1982 			{
1983 			case TYSHORT:
1984 			case TYLONG:
1985 				if(ap->ci < bp->ci)
1986 					k = -1;
1987 				else if(ap->ci == bp->ci)
1988 					k = 0;
1989 				else	k = 1;
1990 				break;
1991 			case TYREAL:
1992 			case TYDREAL:
1993 				if(ap->cd[0] < bp->cd[0])
1994 					k = -1;
1995 				else if(ap->cd[0] == bp->cd[0])
1996 					k = 0;
1997 				else	k = 1;
1998 				break;
1999 			case TYCOMPLEX:
2000 			case TYDCOMPLEX:
2001 				if(ap->cd[0] == bp->cd[0] &&
2002 				   ap->cd[1] == bp->cd[1] )
2003 					k = 0;
2004 				else	k = 1;
2005 				break;
2006 			default: /* XXX gcc */
2007 				k = 0;
2008 				break;
2009 			}
2010 
2011 		switch(opcode)
2012 			{
2013 			case OPEQ:
2014 				cp->ci = (k == 0);
2015 				break;
2016 			case OPNE:
2017 				cp->ci = (k != 0);
2018 				break;
2019 			case OPGT:
2020 				cp->ci = (k == 1);
2021 				break;
2022 			case OPLT:
2023 				cp->ci = (k == -1);
2024 				break;
2025 			case OPGE:
2026 				cp->ci = (k >= 0);
2027 				break;
2028 			case OPLE:
2029 				cp->ci = (k <= 0);
2030 				break;
2031 			}
2032 		break;
2033 	}
2034 }
2035 
2036 
2037 
2038 int
conssgn(p)2039 conssgn(p)
2040 register bigptr p;
2041 {
2042 if( ! ISCONST(p) )
2043 	fatal( "sgn(nonconstant)" );
2044 
2045 switch(p->vtype)
2046 	{
2047 	case TYSHORT:
2048 	case TYLONG:
2049 		if(p->b_const.fconst.ci > 0) return(1);
2050 		if(p->b_const.fconst.ci < 0) return(-1);
2051 		return(0);
2052 
2053 	case TYREAL:
2054 	case TYDREAL:
2055 		if(p->b_const.fconst.cd[0] > 0) return(1);
2056 		if(p->b_const.fconst.cd[0] < 0) return(-1);
2057 		return(0);
2058 
2059 	case TYCOMPLEX:
2060 	case TYDCOMPLEX:
2061 		return(p->b_const.fconst.cd[0]!=0 || p->b_const.fconst.cd[1]!=0);
2062 
2063 	default:
2064 		fatal1( "conssgn(type %d)", p->vtype);
2065 	}
2066 /* NOTREACHED */
2067 return 0; /* XXX gcc */
2068 }
2069 
2070 char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
2071 
2072 
mkpower(p)2073 LOCAL bigptr mkpower(p)
2074 register struct bigblock *p;
2075 {
2076 register bigptr q, lp, rp;
2077 int ltype, rtype, mtype;
2078 
2079 lp = p->b_expr.leftp;
2080 rp = p->b_expr.rightp;
2081 ltype = lp->vtype;
2082 rtype = rp->vtype;
2083 
2084 if(ISICON(rp))
2085 	{
2086 	if(rp->b_const.fconst.ci == 0)
2087 		{
2088 		frexpr(p);
2089 		if( ISINT(ltype) )
2090 			return( MKICON(1) );
2091 		else
2092 			return( putconst( mkconv(ltype, MKICON(1))) );
2093 		}
2094 	if(rp->b_const.fconst.ci < 0)
2095 		{
2096 		if( ISINT(ltype) )
2097 			{
2098 			frexpr(p);
2099 			err("integer**negative");
2100 			return( errnode() );
2101 			}
2102 		rp->b_const.fconst.ci = - rp->b_const.fconst.ci;
2103 		p->b_expr.leftp = lp = fixexpr(mkexpr(OPSLASH, MKICON(1), lp));
2104 		}
2105 	if(rp->b_const.fconst.ci == 1)
2106 		{
2107 		frexpr(rp);
2108 		ckfree(p);
2109 		return(lp);
2110 		}
2111 
2112 	if( ONEOF(ltype, MSKINT|MSKREAL) )
2113 		{
2114 		p->vtype = ltype;
2115 		return(p);
2116 		}
2117 	}
2118 if( ISINT(rtype) )
2119 	{
2120 	if(ltype==TYSHORT && rtype==TYSHORT)
2121 		q = call2(TYSHORT, "pow_hh", lp, rp);
2122 	else	{
2123 		if(ltype == TYSHORT)
2124 			{
2125 			ltype = TYLONG;
2126 			lp = mkconv(TYLONG,lp);
2127 			}
2128 		q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
2129 		}
2130 	}
2131 else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
2132 	q = call2(mtype, "pow_dd",
2133 		mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
2134 else	{
2135 	q = call2(TYDCOMPLEX, "pow_zz",
2136 		mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
2137 	if(mtype == TYCOMPLEX)
2138 		q = mkconv(TYCOMPLEX, q);
2139 	}
2140 ckfree(p);
2141 return(q);
2142 }
2143 
2144 
2145 
2146 /* Complex Division.  Same code as in Runtime Library
2147 */
2148 
2149 
2150 
2151 LOCAL void
zdiv(c,a,b)2152 zdiv(c, a, b)
2153 register struct dcomplex *a, *b, *c;
2154 {
2155 double ratio, den;
2156 double abr, abi;
2157 
2158 if( (abr = b->dreal) < 0.)
2159 	abr = - abr;
2160 if( (abi = b->dimag) < 0.)
2161 	abi = - abi;
2162 if( abr <= abi )
2163 	{
2164 	if(abi == 0)
2165 		fatal("complex division by zero");
2166 	ratio = b->dreal / b->dimag ;
2167 	den = b->dimag * (1 + ratio*ratio);
2168 	c->dreal = (a->dreal*ratio + a->dimag) / den;
2169 	c->dimag = (a->dimag*ratio - a->dreal) / den;
2170 	}
2171 
2172 else
2173 	{
2174 	ratio = b->dimag / b->dreal ;
2175 	den = b->dreal * (1 + ratio*ratio);
2176 	c->dreal = (a->dreal + a->dimag*ratio) / den;
2177 	c->dimag = (a->dimag - a->dreal*ratio) / den;
2178 	}
2179 
2180 }
2181