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