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