source: mainline/uspace/app/pcc/f77/fcom/expr.c@ c6a7b3a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c6a7b3a was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

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