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