|
|
1.1 root 1: /****************************************************************
2: Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
3:
4: Permission to use, copy, modify, and distribute this software
5: and its documentation for any purpose and without fee is hereby
6: granted, provided that the above copyright notice appear in all
7: copies and that both that the copyright notice and this
8: permission notice and warranty disclaimer appear in supporting
9: documentation, and that the names of AT&T Bell Laboratories or
10: Bellcore or any of their entities not be used in advertising or
11: publicity pertaining to distribution of the software without
12: specific, written prior permission.
13:
14: AT&T and Bellcore disclaim all warranties with regard to this
15: software, including all implied warranties of merchantability
16: and fitness. In no event shall AT&T or Bellcore be liable for
17: any special, indirect or consequential damages or any damages
18: whatsoever resulting from loss of use, data or profits, whether
19: in an action of contract, negligence or other tortious action,
20: arising out of or in connection with the use or performance of
21: this software.
22: ****************************************************************/
23:
24: #include "defs.h"
25: #include "output.h"
26: #include "names.h"
27:
28: LOCAL void conspower(), consbinop(), zdiv();
29: LOCAL expptr fold(), mkpower(), stfcall();
30: #ifndef stfcall_MAX
31: #define stfcall_MAX 144
32: #endif
33:
34: typedef struct { double dreal, dimag; } dcomplex;
35:
36: extern char dflttype[26];
37: extern int htype;
38:
39: /* little routines to create constant blocks */
40:
41: Constp mkconst(t)
42: register int t;
43: {
44: register Constp p;
45:
46: p = ALLOC(Constblock);
47: p->tag = TCONST;
48: p->vtype = t;
49: return(p);
50: }
51:
52:
53: /* mklogcon -- Make Logical Constant */
54:
55: expptr mklogcon(l)
56: register int l;
57: {
58: register Constp p;
59:
60: p = mkconst(tylog);
61: p->Const.ci = l;
62: return( (expptr) p );
63: }
64:
65:
66:
67: /* mkintcon -- Make Integer Constant */
68:
69: expptr mkintcon(l)
70: ftnint l;
71: {
72: register Constp p;
73:
74: p = mkconst(tyint);
75: p->Const.ci = l;
76: return( (expptr) p );
77: }
78:
79:
80:
81:
82: /* mkaddcon -- Make Address Constant, given integer value */
83:
84: expptr mkaddcon(l)
85: register long l;
86: {
87: register Constp p;
88:
89: p = mkconst(TYADDR);
90: p->Const.ci = l;
91: return( (expptr) p );
92: }
93:
94:
95:
96: /* mkrealcon -- Make Real Constant. The type t is assumed
97: to be TYREAL or TYDREAL */
98:
99: expptr mkrealcon(t, d)
100: register int t;
101: char *d;
102: {
103: register Constp p;
104:
105: p = mkconst(t);
106: p->Const.cds[0] = cds(d,CNULL);
107: p->vstg = 1;
108: return( (expptr) p );
109: }
110:
111:
112: /* mkbitcon -- Make bit constant. Reads the input string, which is
113: assumed to correctly specify a number in base 2^shift (where shift
114: is the input parameter). shift may not exceed 4, i.e. only binary,
115: quad, octal and hex bases may be input. Constants may not exceed 32
116: bits, or whatever the size of (struct Constblock).ci may be. */
117:
118: expptr mkbitcon(shift, leng, s)
119: int shift;
120: int leng;
121: char *s;
122: {
123: register Constp p;
124: register long x;
125:
126: p = mkconst(TYLONG);
127: x = 0;
128: while(--leng >= 0)
129: if(*s != ' ')
130: x = (x << shift) | hextoi(*s++);
131: /* mwm wanted to change the type to short for short constants,
132: * but this is dangerous -- there is no syntax for long constants
133: * with small values.
134: */
135: p->Const.ci = x;
136: return( (expptr) p );
137: }
138:
139:
140:
141:
142:
143: /* mkstrcon -- Make string constant. Allocates storage and initializes
144: the memory for a copy of the input Fortran-string. */
145:
146: expptr mkstrcon(l,v)
147: int l;
148: register char *v;
149: {
150: register Constp p;
151: register char *s;
152:
153: p = mkconst(TYCHAR);
154: p->vleng = ICON(l);
155: p->Const.ccp = s = (char *) ckalloc(l+1);
156: p->Const.ccp1.blanks = 0;
157: while(--l >= 0)
158: *s++ = *v++;
159: *s = '\0';
160: return( (expptr) p );
161: }
162:
163:
164:
165: /* mkcxcon -- Make complex contsant. A complex number is a pair of
166: values, each of which may be integer, real or double. */
167:
168: expptr mkcxcon(realp,imagp)
169: register expptr realp, imagp;
170: {
171: int rtype, itype;
172: register Constp p;
173: expptr errnode();
174:
175: rtype = realp->headblock.vtype;
176: itype = imagp->headblock.vtype;
177:
178: if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
179: {
180: p = mkconst( (rtype==TYDREAL||itype==TYDREAL)
181: ? TYDCOMPLEX : tycomplex);
182: if (realp->constblock.vstg || imagp->constblock.vstg) {
183: p->vstg = 1;
184: p->Const.cds[0] = ISINT(rtype)
185: ? string_num("", realp->constblock.Const.ci)
186: : realp->constblock.vstg
187: ? realp->constblock.Const.cds[0]
188: : dtos(realp->constblock.Const.cd[0]);
189: p->Const.cds[1] = ISINT(itype)
190: ? string_num("", imagp->constblock.Const.ci)
191: : imagp->constblock.vstg
192: ? imagp->constblock.Const.cds[0]
193: : dtos(imagp->constblock.Const.cd[0]);
194: }
195: else {
196: p->Const.cd[0] = ISINT(rtype)
197: ? realp->constblock.Const.ci
198: : realp->constblock.Const.cd[0];
199: p->Const.cd[1] = ISINT(itype)
200: ? imagp->constblock.Const.ci
201: : imagp->constblock.Const.cd[0];
202: }
203: }
204: else
205: {
206: err("invalid complex constant");
207: p = (Constp)errnode();
208: }
209:
210: frexpr(realp);
211: frexpr(imagp);
212: return( (expptr) p );
213: }
214:
215:
216: /* errnode -- Allocate a new error block */
217:
218: expptr errnode()
219: {
220: struct Errorblock *p;
221: p = ALLOC(Errorblock);
222: p->tag = TERROR;
223: p->vtype = TYERROR;
224: return( (expptr) p );
225: }
226:
227:
228:
229:
230:
231: /* mkconv -- Make type conversion. Cast expression p into type t.
232: Note that casting to a character copies only the first sizeof(char)
233: bytes. */
234:
235: expptr mkconv(t, p)
236: register int t;
237: register expptr p;
238: {
239: register expptr q;
240: register int pt, charwarn = 1;
241: expptr opconv();
242:
243: if (t >= 100) {
244: t -= 100;
245: charwarn = 0;
246: }
247: if(t==TYUNKNOWN || t==TYERROR)
248: badtype("mkconv", t);
249: pt = p->headblock.vtype;
250:
251: /* Casting to the same type is a no-op */
252:
253: if(t == pt)
254: return(p);
255:
256: /* If we're casting a constant which is not in the literal table ... */
257:
258: else if( ISCONST(p) && pt!=TYADDR && pt != TYCHAR)
259: {
260: if (ISINT(t) && ISINT(pt) || ISREAL(t) && ISREAL(pt)) {
261: /* avoid trouble with -i2 */
262: p->headblock.vtype = t;
263: return p;
264: }
265: q = (expptr) mkconst(t);
266: consconv(t, &q->constblock, &p->constblock );
267: frexpr(p);
268: }
269: else {
270: if (pt == TYCHAR && t != TYADDR && charwarn
271: && (!halign || p->tag != TADDR
272: || p->addrblock.uname_tag != UNAM_CONST))
273: warn(
274: "ichar([first char. of] char. string) assumed for conversion to numeric");
275: q = opconv(p, t);
276: }
277:
278: if(t == TYCHAR)
279: q->constblock.vleng = ICON(1);
280: return(q);
281: }
282:
283:
284:
285: /* opconv -- Convert expression p to type t using the main
286: expression evaluator; returns an OPCONV expression, I think 14-jun-88 mwm */
287:
288: expptr opconv(p, t)
289: expptr p;
290: int t;
291: {
292: register expptr q;
293:
294: if (t == TYSUBR)
295: err("illegal use of subroutine name");
296: q = mkexpr(OPCONV, p, ENULL);
297: q->headblock.vtype = t;
298: return(q);
299: }
300:
301:
302:
303: /* addrof -- Create an ADDR expression operation */
304:
305: expptr addrof(p)
306: expptr p;
307: {
308: return( mkexpr(OPADDR, p, ENULL) );
309: }
310:
311:
312:
313: /* cpexpr - Returns a new copy of input expression p */
314:
315: tagptr cpexpr(p)
316: register tagptr p;
317: {
318: register tagptr e;
319: int tag;
320: register chainp ep, pp;
321: tagptr cpblock();
322:
323: /* This table depends on the ordering of the T macros, e.g. TNAME */
324:
325: static int blksize[ ] =
326: {
327: 0,
328: sizeof(struct Nameblock),
329: sizeof(struct Constblock),
330: sizeof(struct Exprblock),
331: sizeof(struct Addrblock),
332: sizeof(struct Primblock),
333: sizeof(struct Listblock),
334: sizeof(struct Impldoblock),
335: sizeof(struct Errorblock)
336: };
337:
338: if(p == NULL)
339: return(NULL);
340:
341: /* TNAMEs are special, and don't get copied. Each name in the current
342: symbol table has a unique TNAME structure. */
343:
344: if( (tag = p->tag) == TNAME)
345: return(p);
346:
347: e = cpblock(blksize[p->tag], (char *)p);
348:
349: switch(tag)
350: {
351: case TCONST:
352: if(e->constblock.vtype == TYCHAR)
353: {
354: e->constblock.Const.ccp =
355: copyn((int)e->constblock.vleng->constblock.Const.ci+1,
356: e->constblock.Const.ccp);
357: e->constblock.vleng =
358: (expptr) cpexpr(e->constblock.vleng);
359: }
360: case TERROR:
361: break;
362:
363: case TEXPR:
364: e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp);
365: e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
366: break;
367:
368: case TLIST:
369: if(pp = p->listblock.listp)
370: {
371: ep = e->listblock.listp =
372: mkchain((char *)cpexpr((tagptr)pp->datap), CHNULL);
373: for(pp = pp->nextp ; pp ; pp = pp->nextp)
374: ep = ep->nextp =
375: mkchain((char *)cpexpr((tagptr)pp->datap),
376: CHNULL);
377: }
378: break;
379:
380: case TADDR:
381: e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng);
382: e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
383: e->addrblock.istemp = NO;
384: break;
385:
386: case TPRIM:
387: e->primblock.argsp = (struct Listblock *)
388: cpexpr((expptr)e->primblock.argsp);
389: e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
390: e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
391: break;
392:
393: default:
394: badtag("cpexpr", tag);
395: }
396:
397: return(e);
398: }
399:
400: /* frexpr -- Free expression -- frees up memory used by expression p */
401:
402: frexpr(p)
403: register tagptr p;
404: {
405: register chainp q;
406:
407: if(p == NULL)
408: return;
409:
410: switch(p->tag)
411: {
412: case TCONST:
413: if( ISCHAR(p) )
414: {
415: free( (charptr) (p->constblock.Const.ccp) );
416: frexpr(p->constblock.vleng);
417: }
418: break;
419:
420: case TADDR:
421: if (p->addrblock.vtype > TYERROR) /* i/o block */
422: break;
423: frexpr(p->addrblock.vleng);
424: frexpr(p->addrblock.memoffset);
425: break;
426:
427: case TERROR:
428: break;
429:
430: /* TNAME blocks don't get free'd - probably because they're pointed to in
431: the hash table. 14-Jun-88 -- mwm */
432:
433: case TNAME:
434: return;
435:
436: case TPRIM:
437: frexpr((expptr)p->primblock.argsp);
438: frexpr(p->primblock.fcharp);
439: frexpr(p->primblock.lcharp);
440: break;
441:
442: case TEXPR:
443: frexpr(p->exprblock.leftp);
444: if(p->exprblock.rightp)
445: frexpr(p->exprblock.rightp);
446: break;
447:
448: case TLIST:
449: for(q = p->listblock.listp ; q ; q = q->nextp)
450: frexpr((tagptr)q->datap);
451: frchain( &(p->listblock.listp) );
452: break;
453:
454: default:
455: badtag("frexpr", p->tag);
456: }
457:
458: free( (charptr) p );
459: }
460:
461: void
462: wronginf(np)
463: Namep np;
464: {
465: int c, k;
466: warn1("fixing wrong type inferred for %.65s", np->fvarname);
467: np->vinftype = 0;
468: c = letter(np->fvarname[0]);
469: if ((np->vtype = impltype[c]) == TYCHAR
470: && (k = implleng[c]))
471: np->vleng = ICON(k);
472: }
473:
474: /* fix up types in expression; replace subtrees and convert
475: names to address blocks */
476:
477: expptr fixtype(p)
478: register tagptr p;
479: {
480:
481: if(p == 0)
482: return(0);
483:
484: switch(p->tag)
485: {
486: case TCONST:
487: if(ONEOF(p->constblock.vtype,MSKINT|MSKLOGICAL|MSKADDR|
488: MSKREAL) )
489: return( (expptr) p);
490:
491: return( (expptr) putconst((Constp)p) );
492:
493: case TADDR:
494: p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
495: return( (expptr) p);
496:
497: case TERROR:
498: return( (expptr) p);
499:
500: default:
501: badtag("fixtype", p->tag);
502:
503: /* This case means that fixexpr can't call fixtype with any expr,
504: only a subexpr of its parameter. */
505:
506: case TEXPR:
507: return( fixexpr((Exprp)p) );
508:
509: case TLIST:
510: return( (expptr) p );
511:
512: case TPRIM:
513: if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
514: {
515: if(p->primblock.namep->vtype == TYSUBR)
516: {
517: err("function invocation of subroutine");
518: return( errnode() );
519: }
520: else {
521: if (p->primblock.namep->vinftype)
522: wronginf(p->primblock.namep);
523: return( mkfunct(p) );
524: }
525: }
526:
527: /* The lack of args makes p a function name, substring reference
528: or variable name. */
529:
530: else return mklhs((struct Primblock *) p, keepsubs);
531: }
532: }
533:
534:
535: int
536: badchleng(p) register expptr p;
537: {
538: if (!p->headblock.vleng) {
539: if (p->headblock.tag == TADDR
540: && p->addrblock.uname_tag == UNAM_NAME)
541: errstr("bad use of character*(*) variable %.60s",
542: p->addrblock.user.name->fvarname);
543: else
544: err("Bad use of character*(*)");
545: return 1;
546: }
547: return 0;
548: }
549:
550:
551: static expptr
552: cplenexpr(p)
553: expptr p;
554: {
555: expptr rv;
556:
557: if (badchleng(p))
558: return ICON(1);
559: rv = cpexpr(p->headblock.vleng);
560: if (ISCONST(p) && p->constblock.vtype == TYCHAR)
561: rv->constblock.Const.ci += p->constblock.Const.ccp1.blanks;
562: return rv;
563: }
564:
565:
566: /* special case tree transformations and cleanups of expression trees.
567: Parameter p should have a TEXPR tag at its root, else an error is
568: returned */
569:
570: expptr fixexpr(p)
571: register Exprp p;
572: {
573: expptr lp;
574: register expptr rp;
575: register expptr q;
576: int opcode, ltype, rtype, ptype, mtype;
577:
578: if( ISERROR(p) )
579: return( (expptr) p );
580: else if(p->tag != TEXPR)
581: badtag("fixexpr", p->tag);
582: opcode = p->opcode;
583:
584: /* First set the types of the left and right subexpressions */
585:
586: lp = p->leftp;
587: if (!ISCONST(lp) || lp->constblock.vtype != TYCHAR)
588: lp = p->leftp = fixtype(lp);
589: ltype = lp->headblock.vtype;
590:
591: if(opcode==OPASSIGN && lp->tag!=TADDR)
592: {
593: err("left side of assignment must be variable");
594: frexpr((expptr)p);
595: return( errnode() );
596: }
597:
598: if(rp = p->rightp)
599: {
600: if (!ISCONST(rp) || rp->constblock.vtype != TYCHAR)
601: rp = p->rightp = fixtype(rp);
602: rtype = rp->headblock.vtype;
603: }
604: else
605: rtype = 0;
606:
607: if(ltype==TYERROR || rtype==TYERROR)
608: {
609: frexpr((expptr)p);
610: return( errnode() );
611: }
612:
613: /* Now work on the whole expression */
614:
615: /* force folding if possible */
616:
617: if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
618: {
619: q = opcode == OPCONV && lp->constblock.vtype == p->vtype
620: ? lp : mkexpr(opcode, lp, rp);
621:
622: /* mkexpr is expected to reduce constant expressions */
623:
624: if( ISCONST(q) ) {
625: p->leftp = p->rightp = 0;
626: frexpr((expptr)p);
627: return(q);
628: }
629: free( (charptr) q ); /* constants did not fold */
630: }
631:
632: if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
633: {
634: frexpr((expptr)p);
635: return( errnode() );
636: }
637:
638: if (ltype == TYCHAR && ISCONST(lp))
639: p->leftp = lp = (expptr)putconst((Constp)lp);
640: if (rtype == TYCHAR && ISCONST(rp))
641: p->rightp = rp = (expptr)putconst((Constp)rp);
642:
643: switch(opcode)
644: {
645: case OPCONCAT:
646: if(p->vleng == NULL)
647: p->vleng = mkexpr(OPPLUS, cplenexpr(lp),
648: cplenexpr(rp) );
649: break;
650:
651: case OPASSIGN:
652: if (rtype == TYREAL || ISLOGICAL(ptype))
653: break;
654: case OPPLUSEQ:
655: case OPSTAREQ:
656: if(ltype == rtype)
657: break;
658: if( ! ISCONST(rp) && ISREAL(ltype) && ISREAL(rtype) )
659: break;
660: if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
661: break;
662: if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
663: && typesize[ltype]>=typesize[rtype] )
664: break;
665:
666: /* Cast the right hand side to match the type of the expression */
667:
668: p->rightp = fixtype( mkconv(ptype, rp) );
669: break;
670:
671: case OPSLASH:
672: if( ISCOMPLEX(rtype) )
673: {
674: p = (Exprp) call2(ptype,
675:
676: /* Handle double precision complex variables */
677:
678: ptype == TYCOMPLEX ? "c_div" : "z_div",
679: mkconv(ptype, lp), mkconv(ptype, rp) );
680: break;
681: }
682: case OPPLUS:
683: case OPMINUS:
684: case OPSTAR:
685: case OPMOD:
686: if(ptype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp) ) ||
687: (rtype==TYREAL && ! ISCONST(rp) ) ))
688: break;
689: if( ISCOMPLEX(ptype) )
690: break;
691:
692: /* Cast both sides of the expression to match the type of the whole
693: expression. */
694:
695: if(ltype != ptype && (ltype < TYINT1 || ptype > TYDREAL))
696: p->leftp = fixtype(mkconv(ptype,lp));
697: if(rtype != ptype && (rtype < TYINT1 || ptype > TYDREAL))
698: p->rightp = fixtype(mkconv(ptype,rp));
699: break;
700:
701: case OPPOWER:
702: return( mkpower((expptr)p) );
703:
704: case OPLT:
705: case OPLE:
706: case OPGT:
707: case OPGE:
708: case OPEQ:
709: case OPNE:
710: if(ltype == rtype)
711: break;
712: if (htype) {
713: if (ltype == TYCHAR) {
714: p->leftp = fixtype(mkconv(rtype,lp));
715: break;
716: }
717: if (rtype == TYCHAR) {
718: p->rightp = fixtype(mkconv(ltype,rp));
719: break;
720: }
721: }
722: mtype = cktype(OPMINUS, ltype, rtype);
723: if(mtype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp)) ||
724: (rtype==TYREAL && ! ISCONST(rp)) ))
725: break;
726: if( ISCOMPLEX(mtype) )
727: break;
728: if(ltype != mtype)
729: p->leftp = fixtype(mkconv(mtype,lp));
730: if(rtype != mtype)
731: p->rightp = fixtype(mkconv(mtype,rp));
732: break;
733:
734: case OPCONV:
735: ptype = cktype(OPCONV, p->vtype, ltype);
736: if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA
737: && !ISCOMPLEX(ptype))
738: {
739: lp->exprblock.rightp =
740: fixtype( mkconv(ptype, lp->exprblock.rightp) );
741: free( (charptr) p );
742: p = (Exprp) lp;
743: }
744: break;
745:
746: case OPADDR:
747: if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
748: Fatal("addr of addr");
749: break;
750:
751: case OPCOMMA:
752: case OPQUEST:
753: case OPCOLON:
754: break;
755:
756: case OPMIN:
757: case OPMAX:
758: case OPMIN2:
759: case OPMAX2:
760: case OPDMIN:
761: case OPDMAX:
762: case OPABS:
763: case OPDABS:
764: ptype = p->vtype;
765: break;
766:
767: default:
768: break;
769: }
770:
771: p->vtype = ptype;
772: return((expptr) p);
773: }
774:
775:
776: /* fix an argument list, taking due care for special first level cases */
777:
778: fixargs(doput, p0)
779: int doput; /* doput is true if constants need to be passed by reference */
780: struct Listblock *p0;
781: {
782: register chainp p;
783: register tagptr q, t;
784: register int qtag;
785: int nargs;
786: Addrp mkscalar();
787:
788: nargs = 0;
789: if(p0)
790: for(p = p0->listp ; p ; p = p->nextp)
791: {
792: ++nargs;
793: q = (tagptr)p->datap;
794: qtag = q->tag;
795: if(qtag == TCONST)
796: {
797:
798: /* Call putconst() to store values in a constant table. Since even
799: constants must be passed by reference, this can optimize on the storage
800: required */
801:
802: p->datap = doput ? (char *)putconst((Constp)q)
803: : (char *)q;
804: }
805:
806: /* Take a function name and turn it into an Addr. This only happens when
807: nothing else has figured out the function beforehand */
808:
809: else if(qtag==TPRIM && q->primblock.argsp==0 &&
810: q->primblock.namep->vclass==CLPROC &&
811: q->primblock.namep->vprocclass != PTHISPROC)
812: p->datap = (char *)mkaddr(q->primblock.namep);
813:
814: else if(qtag==TPRIM && q->primblock.argsp==0 &&
815: q->primblock.namep->vdim!=NULL)
816: p->datap = (char *)mkscalar(q->primblock.namep);
817:
818: else if(qtag==TPRIM && q->primblock.argsp==0 &&
819: q->primblock.namep->vdovar &&
820: (t = (tagptr) memversion(q->primblock.namep)) )
821: p->datap = (char *)fixtype(t);
822: else
823: p->datap = (char *)fixtype(q);
824: }
825: return(nargs);
826: }
827:
828:
829:
830: /* mkscalar -- only called by fixargs above, and by some routines in
831: io.c */
832:
833: Addrp mkscalar(np)
834: register Namep np;
835: {
836: register Addrp ap;
837:
838: vardcl(np);
839: ap = mkaddr(np);
840:
841: /* The prolog causes array arguments to point to the
842: * (0,...,0) element, unless subscript checking is on.
843: */
844: if( !checksubs && np->vstg==STGARG)
845: {
846: register struct Dimblock *dp;
847: dp = np->vdim;
848: frexpr(ap->memoffset);
849: ap->memoffset = mkexpr(OPSTAR,
850: (np->vtype==TYCHAR ?
851: cpexpr(np->vleng) :
852: (tagptr)ICON(typesize[np->vtype]) ),
853: cpexpr(dp->baseoffset) );
854: }
855: return(ap);
856: }
857:
858:
859: static void
860: adjust_arginfo(np) /* adjust arginfo to omit the length arg for the
861: arg that we now know to be a character-valued
862: function */
863: register Namep np;
864: {
865: struct Entrypoint *ep;
866: register chainp args;
867: Argtypes *at;
868:
869: for(ep = entries; ep; ep = ep->entnextp)
870: for(args = ep->arglist; args; args = args->nextp)
871: if (np == (Namep)args->datap
872: && (at = ep->entryname->arginfo))
873: --at->nargs;
874: }
875:
876:
877:
878: expptr mkfunct(p0)
879: expptr p0;
880: {
881: register struct Primblock *p = (struct Primblock *)p0;
882: struct Entrypoint *ep;
883: Addrp ap;
884: Extsym *extp;
885: register Namep np;
886: register expptr q;
887: expptr intrcall();
888: extern chainp new_procs;
889: int k, nargs;
890: int class;
891:
892: if(p->tag != TPRIM)
893: return( errnode() );
894:
895: np = p->namep;
896: class = np->vclass;
897:
898:
899: if(class == CLUNKNOWN)
900: {
901: np->vclass = class = CLPROC;
902: if(np->vstg == STGUNKNOWN)
903: {
904: if(np->vtype!=TYSUBR && (k = intrfunct(np->fvarname))
905: && (zflag || !(*(struct Intrpacked *)&k).f4
906: || dcomplex_seen))
907: {
908: np->vstg = STGINTR;
909: np->vardesc.varno = k;
910: np->vprocclass = PINTRINSIC;
911: }
912: else
913: {
914: extp = mkext(np->fvarname,
915: addunder(np->cvarname));
916: extp->extstg = STGEXT;
917: np->vstg = STGEXT;
918: np->vardesc.varno = extp - extsymtab;
919: np->vprocclass = PEXTERNAL;
920: }
921: }
922: else if(np->vstg==STGARG)
923: {
924: if(np->vtype == TYCHAR) {
925: adjust_arginfo(np);
926: if (np->vpassed) {
927: char wbuf[160], *who;
928: who = np->fvarname;
929: sprintf(wbuf, "%s%s%s\n\t%s%s%s",
930: "Character-valued dummy procedure ",
931: who, " not declared EXTERNAL.",
932: "Code may be wrong for previous function calls having ",
933: who, " as a parameter.");
934: warn(wbuf);
935: }
936: }
937: np->vprocclass = PEXTERNAL;
938: }
939: }
940:
941: if(class != CLPROC) {
942: if (np->vstg == STGCOMMON)
943: fatalstr(
944: "Cannot invoke common variable %.50s as a function.",
945: np->fvarname);
946: fatali("invalid class code %d for function", class);
947: }
948:
949: /* F77 doesn't allow subscripting of function calls */
950:
951: if(p->fcharp || p->lcharp)
952: {
953: err("no substring of function call");
954: goto error;
955: }
956: impldcl(np);
957: np->vimpltype = 0; /* invoking as function ==> inferred type */
958: np->vcalled = 1;
959: nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp);
960:
961: switch(np->vprocclass)
962: {
963: case PEXTERNAL:
964: if(np->vtype == TYUNKNOWN)
965: {
966: dclerr("attempt to use untyped function", np);
967: np->vtype = dflttype[letter(np->fvarname[0])];
968: }
969: ap = mkaddr(np);
970: if (!extsymtab[np->vardesc.varno].extseen) {
971: new_procs = mkchain((char *)np, new_procs);
972: extsymtab[np->vardesc.varno].extseen = 1;
973: }
974: call:
975: q = mkexpr(OPCALL, (expptr)ap, (expptr)p->argsp);
976: q->exprblock.vtype = np->vtype;
977: if(np->vleng)
978: q->exprblock.vleng = (expptr) cpexpr(np->vleng);
979: break;
980:
981: case PINTRINSIC:
982: q = intrcall(np, p->argsp, nargs);
983: break;
984:
985: case PSTFUNCT:
986: q = stfcall(np, p->argsp);
987: break;
988:
989: case PTHISPROC:
990: warn("recursive call");
991:
992: /* entries is the list of multiple entry points */
993:
994: for(ep = entries ; ep ; ep = ep->entnextp)
995: if(ep->enamep == np)
996: break;
997: if(ep == NULL)
998: Fatal("mkfunct: impossible recursion");
999:
1000: ap = builtin(np->vtype, ep->entryname->cextname, -2);
1001: /* the negative last arg prevents adding */
1002: /* this name to the list of used builtins */
1003: goto call;
1004:
1005: default:
1006: fatali("mkfunct: impossible vprocclass %d",
1007: (int) (np->vprocclass) );
1008: }
1009: free( (charptr) p );
1010: return(q);
1011:
1012: error:
1013: frexpr((expptr)p);
1014: return( errnode() );
1015: }
1016:
1017:
1018:
1019: LOCAL expptr stfcall(np, actlist)
1020: Namep np;
1021: struct Listblock *actlist;
1022: {
1023: register chainp actuals;
1024: int nargs;
1025: chainp oactp, formals;
1026: int type;
1027: expptr Ln, Lq, q, q1, rhs, ap;
1028: Namep tnp;
1029: register struct Rplblock *rp;
1030: struct Rplblock *tlist;
1031: static int inv_count;
1032:
1033: if (++inv_count > stfcall_MAX)
1034: Fatal("Loop invoking recursive statement function?");
1035: if(actlist)
1036: {
1037: actuals = actlist->listp;
1038: free( (charptr) actlist);
1039: }
1040: else
1041: actuals = NULL;
1042: oactp = actuals;
1043:
1044: nargs = 0;
1045: tlist = NULL;
1046: if( (type = np->vtype) == TYUNKNOWN)
1047: {
1048: dclerr("attempt to use untyped statement function", np);
1049: type = np->vtype = dflttype[letter(np->fvarname[0])];
1050: }
1051: formals = (chainp) np->varxptr.vstfdesc->datap;
1052: rhs = (expptr) (np->varxptr.vstfdesc->nextp);
1053:
1054: /* copy actual arguments into temporaries */
1055: while(actuals!=NULL && formals!=NULL)
1056: {
1057: rp = ALLOC(Rplblock);
1058: rp->rplnp = tnp = (Namep) formals->datap;
1059: ap = fixtype((tagptr)actuals->datap);
1060: if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
1061: && (ap->tag==TCONST || ap->tag==TADDR) )
1062: {
1063:
1064: /* If actuals are constants or variable names, no temporaries are required */
1065: rp->rplvp = (expptr) ap;
1066: rp->rplxp = NULL;
1067: rp->rpltag = ap->tag;
1068: }
1069: else {
1070: rp->rplvp = (expptr) mktmp(tnp->vtype, tnp->vleng);
1071: rp -> rplxp = NULL;
1072: putexpr ( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap));
1073: if((rp->rpltag = rp->rplvp->tag) == TERROR)
1074: err("disagreement of argument types in statement function call");
1075: }
1076: rp->rplnextp = tlist;
1077: tlist = rp;
1078: actuals = actuals->nextp;
1079: formals = formals->nextp;
1080: ++nargs;
1081: }
1082:
1083: if(actuals!=NULL || formals!=NULL)
1084: err("statement function definition and argument list differ");
1085:
1086: /*
1087: now push down names involved in formal argument list, then
1088: evaluate rhs of statement function definition in this environment
1089: */
1090:
1091: if(tlist) /* put tlist in front of the rpllist */
1092: {
1093: for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
1094: ;
1095: rp->rplnextp = rpllist;
1096: rpllist = tlist;
1097: }
1098:
1099: /* So when the expression finally gets evaled, that evaluator must read
1100: from the globl rpllist 14-jun-88 mwm */
1101:
1102: q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
1103:
1104: /* get length right of character-valued statement functions... */
1105: if (type == TYCHAR
1106: && (Ln = np->vleng)
1107: && q->tag != TERROR
1108: && (Lq = q->exprblock.vleng)
1109: && (Lq->tag != TCONST
1110: || Ln->constblock.Const.ci != Lq->constblock.Const.ci)) {
1111: q1 = (expptr) mktmp(type, Ln);
1112: putexpr ( mkexpr(OPASSIGN, cpexpr(q1), q));
1113: q = q1;
1114: }
1115:
1116: /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
1117: while(--nargs >= 0)
1118: {
1119: if(rpllist->rplxp)
1120: q = mkexpr(OPCOMMA, rpllist->rplxp, q);
1121: rp = rpllist->rplnextp;
1122: frexpr(rpllist->rplvp);
1123: free((char *)rpllist);
1124: rpllist = rp;
1125: }
1126: frchain( &oactp );
1127: --inv_count;
1128: return(q);
1129: }
1130:
1131:
1132: static int replaced;
1133:
1134: /* mkplace -- Figure out the proper storage class for the input name and
1135: return an addrp with the appropriate stuff */
1136:
1137: Addrp mkplace(np)
1138: register Namep np;
1139: {
1140: register Addrp s;
1141: register struct Rplblock *rp;
1142: int regn;
1143:
1144: /* is name on the replace list? */
1145:
1146: for(rp = rpllist ; rp ; rp = rp->rplnextp)
1147: {
1148: if(np == rp->rplnp)
1149: {
1150: replaced = 1;
1151: if(rp->rpltag == TNAME)
1152: {
1153: np = (Namep) (rp->rplvp);
1154: break;
1155: }
1156: else return( (Addrp) cpexpr(rp->rplvp) );
1157: }
1158: }
1159:
1160: /* is variable a DO index in a register ? */
1161:
1162: if(np->vdovar && ( (regn = inregister(np)) >= 0) )
1163: if(np->vtype == TYERROR)
1164: return((Addrp) errnode() );
1165: else
1166: {
1167: s = ALLOC(Addrblock);
1168: s->tag = TADDR;
1169: s->vstg = STGREG;
1170: s->vtype = TYIREG;
1171: s->memno = regn;
1172: s->memoffset = ICON(0);
1173: s -> uname_tag = UNAM_NAME;
1174: s -> user.name = np;
1175: return(s);
1176: }
1177:
1178: if (np->vclass == CLPROC && np->vprocclass != PTHISPROC)
1179: errstr("external %.60s used as a variable", np->fvarname);
1180: vardcl(np);
1181: return(mkaddr(np));
1182: }
1183:
1184: static expptr
1185: subskept(p,a)
1186: struct Primblock *p;
1187: Addrp a;
1188: {
1189: expptr ep;
1190: struct Listblock *Lb;
1191: chainp cp;
1192:
1193: if (a->uname_tag != UNAM_NAME)
1194: erri("subskept: uname_tag %d", a->uname_tag);
1195: a->user.name->vrefused = 1;
1196: a->user.name->visused = 1;
1197: a->uname_tag = UNAM_REF;
1198: Lb = (struct Listblock *)cpexpr((tagptr)p->argsp);
1199: for(cp = Lb->listp; cp; cp = cp->nextp)
1200: cp->datap = (char *)putx(fixtype((tagptr)cp->datap));
1201: if (a->vtype == TYCHAR) {
1202: ep = p->fcharp ? mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1))
1203: : ICON(0);
1204: Lb->listp = mkchain((char *)ep, Lb->listp);
1205: }
1206: return (expptr)Lb;
1207: }
1208:
1209: static int doing_vleng;
1210:
1211: /* mklhs -- Compute the actual address of the given expression; account
1212: for array subscripts, stack offset, and substring offsets. The f -> C
1213: translator will need this only to worry about the subscript stuff */
1214:
1215: expptr mklhs(p, subkeep)
1216: register struct Primblock *p; int subkeep;
1217: {
1218: expptr suboffset();
1219: register Addrp s;
1220: Namep np;
1221:
1222: if(p->tag != TPRIM)
1223: return( (expptr) p );
1224: np = p->namep;
1225:
1226: replaced = 0;
1227: s = mkplace(np);
1228: if(s->tag!=TADDR || s->vstg==STGREG)
1229: {
1230: free( (charptr) p );
1231: return( (expptr) s );
1232: }
1233: s->parenused = p->parenused;
1234:
1235: /* compute the address modified by subscripts */
1236:
1237: if (!replaced)
1238: s->memoffset = (subkeep && np->vdim
1239: && (np->vdim->ndim > 1 || np->vtype == TYCHAR
1240: && (!ISCONST(np->vleng)
1241: || np->vleng->constblock.Const.ci != 1)))
1242: ? subskept(p,s)
1243: : mkexpr(OPPLUS, s->memoffset, suboffset(p) );
1244: frexpr((expptr)p->argsp);
1245: p->argsp = NULL;
1246:
1247: /* now do substring part */
1248:
1249: if(p->fcharp || p->lcharp)
1250: {
1251: if(np->vtype != TYCHAR)
1252: errstr("substring of noncharacter %s", np->fvarname);
1253: else {
1254: if(p->lcharp == NULL)
1255: p->lcharp = (expptr) cpexpr(s->vleng);
1256: if(p->fcharp) {
1257: doing_vleng = 1;
1258: s->vleng = fixtype(mkexpr(OPMINUS,
1259: p->lcharp,
1260: mkexpr(OPMINUS, p->fcharp, ICON(1) )));
1261: doing_vleng = 0;
1262: }
1263: else {
1264: frexpr(s->vleng);
1265: s->vleng = p->lcharp;
1266: }
1267: }
1268: }
1269:
1270: s->vleng = fixtype( s->vleng );
1271: s->memoffset = fixtype( s->memoffset );
1272: free( (charptr) p );
1273: return( (expptr) s );
1274: }
1275:
1276:
1277:
1278:
1279:
1280: /* deregister -- remove a register allocation from the list; assumes that
1281: names are deregistered in stack order (LIFO order - Last In First Out) */
1282:
1283: deregister(np)
1284: Namep np;
1285: {
1286: if(nregvar>0 && regnamep[nregvar-1]==np)
1287: {
1288: --nregvar;
1289: }
1290: }
1291:
1292:
1293:
1294:
1295: /* memversion -- moves a DO index REGISTER into a memory location; other
1296: objects are passed through untouched */
1297:
1298: Addrp memversion(np)
1299: register Namep np;
1300: {
1301: register Addrp s;
1302:
1303: if(np->vdovar==NO || (inregister(np)<0) )
1304: return(NULL);
1305: np->vdovar = NO;
1306: s = mkplace(np);
1307: np->vdovar = YES;
1308: return(s);
1309: }
1310:
1311:
1312:
1313: /* inregister -- looks for the input name in the global list regnamep */
1314:
1315: inregister(np)
1316: register Namep np;
1317: {
1318: register int i;
1319:
1320: for(i = 0 ; i < nregvar ; ++i)
1321: if(regnamep[i] == np)
1322: return( regnum[i] );
1323: return(-1);
1324: }
1325:
1326:
1327:
1328: /* suboffset -- Compute the offset from the start of the array, given the
1329: subscripts as arguments */
1330:
1331: expptr suboffset(p)
1332: register struct Primblock *p;
1333: {
1334: int n;
1335: expptr si, size;
1336: chainp cp;
1337: expptr e, e1, offp, prod;
1338: expptr subcheck();
1339: struct Dimblock *dimp;
1340: expptr sub[MAXDIM+1];
1341: register Namep np;
1342:
1343: np = p->namep;
1344: offp = ICON(0);
1345: n = 0;
1346: if(p->argsp)
1347: for(cp = p->argsp->listp ; cp ; cp = cp->nextp)
1348: {
1349: si = fixtype(cpexpr((tagptr)cp->datap));
1350: if (!ISINT(si->headblock.vtype)) {
1351: NOEXT("non-integer subscript");
1352: si = mkconv(TYLONG, si);
1353: }
1354: sub[n++] = si;
1355: if(n > maxdim)
1356: {
1357: erri("more than %d subscripts", maxdim);
1358: break;
1359: }
1360: }
1361:
1362: dimp = np->vdim;
1363: if(n>0 && dimp==NULL)
1364: errstr("subscripts on scalar variable %.68s", np->fvarname);
1365: else if(dimp && dimp->ndim!=n)
1366: errstr("wrong number of subscripts on %.68s", np->fvarname);
1367: else if(n > 0)
1368: {
1369: prod = sub[--n];
1370: while( --n >= 0)
1371: prod = mkexpr(OPPLUS, sub[n],
1372: mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
1373: if(checksubs || np->vstg!=STGARG)
1374: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1375:
1376: /* Add in the run-time bounds check */
1377:
1378: if(checksubs)
1379: prod = subcheck(np, prod);
1380: size = np->vtype == TYCHAR ?
1381: (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
1382: prod = mkexpr(OPSTAR, prod, size);
1383: offp = mkexpr(OPPLUS, offp, prod);
1384: }
1385:
1386: /* Check for substring indicator */
1387:
1388: if(p->fcharp && np->vtype==TYCHAR) {
1389: e = p->fcharp;
1390: e1 = mkexpr(OPMINUS, cpexpr(e), ICON(1));
1391: if (!ISCONST(e) && (e->tag != TPRIM || e->primblock.argsp)) {
1392: e = (expptr)mktmp(TYLONG, ENULL);
1393: putout(putassign(cpexpr(e), e1));
1394: p->fcharp = mkexpr(OPPLUS, cpexpr(e), ICON(1));
1395: e1 = e;
1396: }
1397: offp = mkexpr(OPPLUS, offp, e1);
1398: }
1399: return(offp);
1400: }
1401:
1402:
1403:
1404:
1405: expptr subcheck(np, p)
1406: Namep np;
1407: register expptr p;
1408: {
1409: struct Dimblock *dimp;
1410: expptr t, checkvar, checkcond, badcall;
1411:
1412: dimp = np->vdim;
1413: if(dimp->nelt == NULL)
1414: return(p); /* don't check arrays with * bounds */
1415: np->vlastdim = 0;
1416: if( ISICON(p) )
1417: {
1418:
1419: /* check for negative (constant) offset */
1420:
1421: if(p->constblock.Const.ci < 0)
1422: goto badsub;
1423: if( ISICON(dimp->nelt) )
1424:
1425: /* see if constant offset exceeds the array declaration */
1426:
1427: if(p->constblock.Const.ci < dimp->nelt->constblock.Const.ci)
1428: return(p);
1429: else
1430: goto badsub;
1431: }
1432:
1433: /* We know that the subscript offset p or dimp -> nelt is not a constant.
1434: Now find a register to use for run-time bounds checking */
1435:
1436: if(p->tag==TADDR && p->addrblock.vstg==STGREG)
1437: {
1438: checkvar = (expptr) cpexpr(p);
1439: t = p;
1440: }
1441: else {
1442: checkvar = (expptr) mktmp(p->headblock.vtype, ENULL);
1443: t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
1444: }
1445: checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
1446: if( ! ISICON(p) )
1447: checkcond = mkexpr(OPAND, checkcond,
1448: mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
1449:
1450: /* Construct the actual test */
1451:
1452: badcall = call4(p->headblock.vtype, "s_rnge",
1453: mkstrcon(strlen(np->fvarname), np->fvarname),
1454: mkconv(TYLONG, cpexpr(checkvar)),
1455: mkstrcon(strlen(procname), procname),
1456: ICON(lineno) );
1457: badcall->exprblock.opcode = OPCCALL;
1458: p = mkexpr(OPQUEST, checkcond,
1459: mkexpr(OPCOLON, checkvar, badcall));
1460:
1461: return(p);
1462:
1463: badsub:
1464: frexpr(p);
1465: errstr("subscript on variable %s out of range", np->fvarname);
1466: return ( ICON(0) );
1467: }
1468:
1469:
1470:
1471:
1472: Addrp mkaddr(p)
1473: register Namep p;
1474: {
1475: Extsym *extp;
1476: register Addrp t;
1477: Addrp intraddr();
1478: int k;
1479:
1480: switch( p->vstg)
1481: {
1482: case STGAUTO:
1483: if(p->vclass == CLPROC && p->vprocclass == PTHISPROC)
1484: return (Addrp) cpexpr((expptr)xretslot[p->vtype]);
1485: goto other;
1486:
1487: case STGUNKNOWN:
1488: if(p->vclass != CLPROC)
1489: break; /* Error */
1490: extp = mkext(p->fvarname, addunder(p->cvarname));
1491: extp->extstg = STGEXT;
1492: p->vstg = STGEXT;
1493: p->vardesc.varno = extp - extsymtab;
1494: p->vprocclass = PEXTERNAL;
1495: if ((extp->exproto || infertypes)
1496: && (p->vtype == TYUNKNOWN || p->vimpltype)
1497: && (k = extp->extype))
1498: inferdcl(p, k);
1499:
1500:
1501: case STGCOMMON:
1502: case STGEXT:
1503: case STGBSS:
1504: case STGINIT:
1505: case STGEQUIV:
1506: case STGARG:
1507: case STGLENG:
1508: other:
1509: t = ALLOC(Addrblock);
1510: t->tag = TADDR;
1511:
1512: t->vclass = p->vclass;
1513: t->vtype = p->vtype;
1514: t->vstg = p->vstg;
1515: t->memno = p->vardesc.varno;
1516: t->memoffset = ICON(p->voffset);
1517: if (p->vdim)
1518: t->isarray = 1;
1519: if(p->vleng)
1520: {
1521: t->vleng = (expptr) cpexpr(p->vleng);
1522: if( ISICON(t->vleng) )
1523: t->varleng = t->vleng->constblock.Const.ci;
1524: }
1525:
1526: /* Keep the original name around for the C code generation */
1527:
1528: t -> uname_tag = UNAM_NAME;
1529: t -> user.name = p;
1530: return(t);
1531:
1532: case STGINTR:
1533:
1534: return ( intraddr (p));
1535: }
1536: badstg("mkaddr", p->vstg);
1537: /* NOT REACHED */ return 0;
1538: }
1539:
1540:
1541:
1542:
1543: /* mkarg -- create storage for a new parameter. This is called when a
1544: function returns a string (for the return value, which is the first
1545: parameter), or when a variable-length string is passed to a function. */
1546:
1547: Addrp mkarg(type, argno)
1548: int type, argno;
1549: {
1550: register Addrp p;
1551:
1552: p = ALLOC(Addrblock);
1553: p->tag = TADDR;
1554: p->vtype = type;
1555: p->vclass = CLVAR;
1556:
1557: /* TYLENG is the type of the field holding the length of a character string */
1558:
1559: p->vstg = (type==TYLENG ? STGLENG : STGARG);
1560: p->memno = argno;
1561: return(p);
1562: }
1563:
1564:
1565:
1566:
1567: /* mkprim -- Create a PRIM (primary/primitive) block consisting of a
1568: Nameblock (or Paramblock), arguments (actual params or array
1569: subscripts) and substring bounds. Requires that v have lots of
1570: extra (uninitialized) storage, since it could be a paramblock or
1571: nameblock */
1572:
1573: expptr mkprim(v0, args, substr)
1574: Namep v0;
1575: struct Listblock *args;
1576: chainp substr;
1577: {
1578: typedef union {
1579: struct Paramblock paramblock;
1580: struct Nameblock nameblock;
1581: struct Headblock headblock;
1582: } *Primu;
1583: register Primu v = (Primu)v0;
1584: register struct Primblock *p;
1585:
1586: if(v->headblock.vclass == CLPARAM)
1587: {
1588:
1589: /* v is to be a Paramblock */
1590:
1591: if(args || substr)
1592: {
1593: errstr("no qualifiers on parameter name %s",
1594: v->paramblock.fvarname);
1595: frexpr((expptr)args);
1596: if(substr)
1597: {
1598: frexpr((tagptr)substr->datap);
1599: frexpr((tagptr)substr->nextp->datap);
1600: frchain(&substr);
1601: }
1602: frexpr((expptr)v);
1603: return( errnode() );
1604: }
1605: return( (expptr) cpexpr(v->paramblock.paramval) );
1606: }
1607:
1608: p = ALLOC(Primblock);
1609: p->tag = TPRIM;
1610: p->vtype = v->nameblock.vtype;
1611:
1612: /* v is to be a Nameblock */
1613:
1614: p->namep = (Namep) v;
1615: p->argsp = args;
1616: if(substr)
1617: {
1618: p->fcharp = (expptr) substr->datap;
1619: p->lcharp = (expptr) substr->nextp->datap;
1620: frchain(&substr);
1621: }
1622: return( (expptr) p);
1623: }
1624:
1625:
1626:
1627: /* vardcl -- attempt to fill out the Name template for variable v.
1628: This function is called on identifiers known to be variables or
1629: recursive references to the same function */
1630:
1631: vardcl(v)
1632: register Namep v;
1633: {
1634: struct Dimblock *t;
1635: expptr neltp;
1636: extern int doing_stmtfcn;
1637:
1638: if(v->vclass == CLUNKNOWN) {
1639: v->vclass = CLVAR;
1640: if (v->vinftype) {
1641: v->vtype = TYUNKNOWN;
1642: if (v->vdcldone) {
1643: v->vdcldone = 0;
1644: impldcl(v);
1645: }
1646: }
1647: }
1648: if(v->vdcldone)
1649: return;
1650: if(v->vclass == CLNAMELIST)
1651: return;
1652:
1653: if(v->vtype == TYUNKNOWN)
1654: impldcl(v);
1655: else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
1656: {
1657: dclerr("used as variable", v);
1658: return;
1659: }
1660: if(v->vstg==STGUNKNOWN) {
1661: if (doing_stmtfcn) {
1662: /* neither declare this variable if its only use */
1663: /* is in defining a stmt function, nor complain */
1664: /* that it is never used */
1665: v->vimpldovar = 1;
1666: return;
1667: }
1668: v->vstg = implstg[ letter(v->fvarname[0]) ];
1669: v->vimplstg = 1;
1670: }
1671:
1672: /* Compute the actual storage location, i.e. offsets from base addresses,
1673: possibly the stack pointer */
1674:
1675: switch(v->vstg)
1676: {
1677: case STGBSS:
1678: v->vardesc.varno = ++lastvarno;
1679: break;
1680: case STGAUTO:
1681: if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
1682: break;
1683: if(t = v->vdim)
1684: if( (neltp = t->nelt) && ISCONST(neltp) ) ;
1685: else
1686: dclerr("adjustable automatic array", v);
1687: break;
1688:
1689: default:
1690: break;
1691: }
1692: v->vdcldone = YES;
1693: }
1694:
1695:
1696:
1697: /* Set the implicit type declaration of parameter p based on its first
1698: letter */
1699:
1700: impldcl(p)
1701: register Namep p;
1702: {
1703: register int k;
1704: int type;
1705: ftnint leng;
1706:
1707: if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
1708: return;
1709: if(p->vtype == TYUNKNOWN)
1710: {
1711: k = letter(p->fvarname[0]);
1712: type = impltype[ k ];
1713: leng = implleng[ k ];
1714: if(type == TYUNKNOWN)
1715: {
1716: if(p->vclass == CLPROC)
1717: return;
1718: dclerr("attempt to use undefined variable", p);
1719: type = dflttype[k];
1720: leng = 0;
1721: }
1722: settype(p, type, leng);
1723: p->vimpltype = 1;
1724: }
1725: }
1726:
1727: void
1728: inferdcl(np,type)
1729: Namep np;
1730: int type;
1731: {
1732: int k = impltype[letter(np->fvarname[0])];
1733: if (k != type) {
1734: np->vinftype = 1;
1735: np->vtype = type;
1736: frexpr(np->vleng);
1737: np->vleng = 0;
1738: }
1739: np->vimpltype = 0;
1740: np->vinfproc = 1;
1741: }
1742:
1743:
1744: #define ICONEQ(z, c) (ISICON(z) && z->constblock.Const.ci==c)
1745: #define COMMUTE { e = lp; lp = rp; rp = e; }
1746:
1747:
1748:
1749: /* mkexpr -- Make expression, and simplify constant subcomponents (tree
1750: order is not preserved). Assumes that lp is nonempty, and uses
1751: fold() to simplify adjacent constants */
1752:
1753: expptr mkexpr(opcode, lp, rp)
1754: int opcode;
1755: register expptr lp, rp;
1756: {
1757: register expptr e, e1;
1758: int etype;
1759: int ltype, rtype;
1760: int ltag, rtag;
1761: long L;
1762:
1763: ltype = lp->headblock.vtype;
1764: ltag = lp->tag;
1765: if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1766: {
1767: rtype = rp->headblock.vtype;
1768: rtag = rp->tag;
1769: }
1770: else rtype = 0;
1771:
1772: etype = cktype(opcode, ltype, rtype);
1773: if(etype == TYERROR)
1774: goto error;
1775:
1776: switch(opcode)
1777: {
1778: /* check for multiplication by 0 and 1 and addition to 0 */
1779:
1780: case OPSTAR:
1781: if( ISCONST(lp) )
1782: COMMUTE
1783:
1784: if( ISICON(rp) )
1785: {
1786: if(rp->constblock.Const.ci == 0)
1787: goto retright;
1788: goto mulop;
1789: }
1790: break;
1791:
1792: case OPSLASH:
1793: case OPMOD:
1794: if( ICONEQ(rp, 0) )
1795: {
1796: err("attempted division by zero");
1797: rp = ICON(1);
1798: break;
1799: }
1800: if(opcode == OPMOD)
1801: break;
1802:
1803: /* Handle multiplying or dividing by 1, -1 */
1804:
1805: mulop:
1806: if( ISICON(rp) )
1807: {
1808: if(rp->constblock.Const.ci == 1)
1809: goto retleft;
1810:
1811: if(rp->constblock.Const.ci == -1)
1812: {
1813: frexpr(rp);
1814: return( mkexpr(OPNEG, lp, ENULL) );
1815: }
1816: }
1817:
1818: /* Group all constants together. In particular,
1819:
1820: (x * CONST1) * CONST2 ==> x * (CONST1 * CONST2)
1821: (x * CONST1) / CONST2 ==> x * (CONST1 / CONST2)
1822: */
1823:
1824: if (lp->tag != TEXPR || !lp->exprblock.rightp
1825: || !ISICON(lp->exprblock.rightp))
1826: break;
1827:
1828: if (lp->exprblock.opcode == OPLSHIFT) {
1829: L = 1 << lp->exprblock.rightp->constblock.Const.ci;
1830: if (opcode == OPSTAR || ISICON(rp) &&
1831: !(L % rp->constblock.Const.ci)) {
1832: lp->exprblock.opcode = OPSTAR;
1833: lp->exprblock.rightp->constblock.Const.ci = L;
1834: }
1835: }
1836:
1837: if (lp->exprblock.opcode == OPSTAR) {
1838: if(opcode == OPSTAR)
1839: e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
1840: else if(ISICON(rp) &&
1841: (lp->exprblock.rightp->constblock.Const.ci %
1842: rp->constblock.Const.ci) == 0)
1843: e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
1844: else break;
1845:
1846: e1 = lp->exprblock.leftp;
1847: free( (charptr) lp );
1848: return( mkexpr(OPSTAR, e1, e) );
1849: }
1850: break;
1851:
1852:
1853: case OPPLUS:
1854: if( ISCONST(lp) )
1855: COMMUTE
1856: goto addop;
1857:
1858: case OPMINUS:
1859: if( ICONEQ(lp, 0) )
1860: {
1861: frexpr(lp);
1862: return( mkexpr(OPNEG, rp, ENULL) );
1863: }
1864:
1865: if( ISCONST(rp) && is_negatable((Constp)rp))
1866: {
1867: opcode = OPPLUS;
1868: consnegop((Constp)rp);
1869: }
1870:
1871: /* Group constants in an addition expression (also subtraction, since the
1872: subtracted value was negated above). In particular,
1873:
1874: (x + CONST1) + CONST2 ==> x + (CONST1 + CONST2)
1875: */
1876:
1877: addop:
1878: if( ISICON(rp) )
1879: {
1880: if(rp->constblock.Const.ci == 0)
1881: goto retleft;
1882: if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
1883: {
1884: e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
1885: e1 = lp->exprblock.leftp;
1886: free( (charptr) lp );
1887: return( mkexpr(OPPLUS, e1, e) );
1888: }
1889: }
1890: if (opcode == OPMINUS && (ISINT(etype) || doing_vleng)) {
1891: /* check for (i [+const]) - (i [+const]) */
1892: if (lp->tag == TPRIM)
1893: e = lp;
1894: else if (lp->tag == TEXPR && lp->exprblock.opcode == OPPLUS
1895: && lp->exprblock.rightp->tag == TCONST) {
1896: e = lp->exprblock.leftp;
1897: if (e->tag != TPRIM)
1898: break;
1899: }
1900: else
1901: break;
1902: if (e->primblock.argsp)
1903: break;
1904: if (rp->tag == TPRIM)
1905: e1 = rp;
1906: else if (rp->tag == TEXPR && rp->exprblock.opcode == OPPLUS
1907: && rp->exprblock.rightp->tag == TCONST) {
1908: e1 = rp->exprblock.leftp;
1909: if (e1->tag != TPRIM)
1910: break;
1911: }
1912: else
1913: break;
1914: if (e->primblock.namep != e1->primblock.namep
1915: || e1->primblock.argsp)
1916: break;
1917: L = e == lp ? 0 : lp->exprblock.rightp->constblock.Const.ci;
1918: if (e1 != rp)
1919: L -= rp->exprblock.rightp->constblock.Const.ci;
1920: frexpr(lp);
1921: frexpr(rp);
1922: return ICON(L);
1923: }
1924:
1925: break;
1926:
1927:
1928: case OPPOWER:
1929: break;
1930:
1931: /* Eliminate outermost double negations */
1932:
1933: case OPNEG:
1934: case OPNEG1:
1935: if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
1936: {
1937: e = lp->exprblock.leftp;
1938: free( (charptr) lp );
1939: return(e);
1940: }
1941: break;
1942:
1943: /* Eliminate outermost double NOTs */
1944:
1945: case OPNOT:
1946: if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
1947: {
1948: e = lp->exprblock.leftp;
1949: free( (charptr) lp );
1950: return(e);
1951: }
1952: break;
1953:
1954: case OPCALL:
1955: case OPCCALL:
1956: etype = ltype;
1957: if(rp!=NULL && rp->listblock.listp==NULL)
1958: {
1959: free( (charptr) rp );
1960: rp = NULL;
1961: }
1962: break;
1963:
1964: case OPAND:
1965: case OPOR:
1966: if( ISCONST(lp) )
1967: COMMUTE
1968:
1969: if( ISCONST(rp) )
1970: {
1971: if(rp->constblock.Const.ci == 0)
1972: if(opcode == OPOR)
1973: goto retleft;
1974: else
1975: goto retright;
1976: else if(opcode == OPOR)
1977: goto retright;
1978: else
1979: goto retleft;
1980: }
1981: case OPEQV:
1982: case OPNEQV:
1983:
1984: case OPBITAND:
1985: case OPBITOR:
1986: case OPBITXOR:
1987: case OPBITNOT:
1988: case OPLSHIFT:
1989: case OPRSHIFT:
1990:
1991: case OPLT:
1992: case OPGT:
1993: case OPLE:
1994: case OPGE:
1995: case OPEQ:
1996: case OPNE:
1997:
1998: case OPCONCAT:
1999: break;
2000: case OPMIN:
2001: case OPMAX:
2002: case OPMIN2:
2003: case OPMAX2:
2004: case OPDMIN:
2005: case OPDMAX:
2006:
2007: case OPASSIGN:
2008: case OPASSIGNI:
2009: case OPPLUSEQ:
2010: case OPSTAREQ:
2011: case OPMINUSEQ:
2012: case OPSLASHEQ:
2013: case OPMODEQ:
2014: case OPLSHIFTEQ:
2015: case OPRSHIFTEQ:
2016: case OPBITANDEQ:
2017: case OPBITXOREQ:
2018: case OPBITOREQ:
2019:
2020: case OPCONV:
2021: case OPADDR:
2022: case OPWHATSIN:
2023:
2024: case OPCOMMA:
2025: case OPCOMMA_ARG:
2026: case OPQUEST:
2027: case OPCOLON:
2028: case OPDOT:
2029: case OPARROW:
2030: case OPIDENTITY:
2031: case OPCHARCAST:
2032: case OPABS:
2033: case OPDABS:
2034: break;
2035:
2036: default:
2037: badop("mkexpr", opcode);
2038: }
2039:
2040: e = (expptr) ALLOC(Exprblock);
2041: e->exprblock.tag = TEXPR;
2042: e->exprblock.opcode = opcode;
2043: e->exprblock.vtype = etype;
2044: e->exprblock.leftp = lp;
2045: e->exprblock.rightp = rp;
2046: if(ltag==TCONST && (rp==0 || rtag==TCONST) )
2047: e = fold(e);
2048: return(e);
2049:
2050: retleft:
2051: frexpr(rp);
2052: if (lp->tag == TPRIM)
2053: lp->primblock.parenused = 1;
2054: return(lp);
2055:
2056: retright:
2057: frexpr(lp);
2058: if (rp->tag == TPRIM)
2059: rp->primblock.parenused = 1;
2060: return(rp);
2061:
2062: error:
2063: frexpr(lp);
2064: if(rp && opcode!=OPCALL && opcode!=OPCCALL)
2065: frexpr(rp);
2066: return( errnode() );
2067: }
2068:
2069: #define ERR(s) { errs = s; goto error; }
2070:
2071: /* cktype -- Check and return the type of the expression */
2072:
2073: cktype(op, lt, rt)
2074: register int op, lt, rt;
2075: {
2076: char *errs;
2077:
2078: if(lt==TYERROR || rt==TYERROR)
2079: goto error1;
2080:
2081: if(lt==TYUNKNOWN)
2082: return(TYUNKNOWN);
2083: if(rt==TYUNKNOWN)
2084:
2085: /* If not unary operation, return UNKNOWN */
2086:
2087: if(!is_unary_op (op) && op != OPCALL && op != OPCCALL)
2088: return(TYUNKNOWN);
2089:
2090: switch(op)
2091: {
2092: case OPPLUS:
2093: case OPMINUS:
2094: case OPSTAR:
2095: case OPSLASH:
2096: case OPPOWER:
2097: case OPMOD:
2098: if( ISNUMERIC(lt) && ISNUMERIC(rt) )
2099: return( maxtype(lt, rt) );
2100: ERR("nonarithmetic operand of arithmetic operator")
2101:
2102: case OPNEG:
2103: case OPNEG1:
2104: if( ISNUMERIC(lt) )
2105: return(lt);
2106: ERR("nonarithmetic operand of negation")
2107:
2108: case OPNOT:
2109: if(ISLOGICAL(lt))
2110: return(lt);
2111: ERR("NOT of nonlogical")
2112:
2113: case OPAND:
2114: case OPOR:
2115: case OPEQV:
2116: case OPNEQV:
2117: if(ISLOGICAL(lt) && ISLOGICAL(rt))
2118: return( maxtype(lt, rt) );
2119: ERR("nonlogical operand of logical operator")
2120:
2121: case OPLT:
2122: case OPGT:
2123: case OPLE:
2124: case OPGE:
2125: case OPEQ:
2126: case OPNE:
2127: if(lt==TYCHAR || rt==TYCHAR || ISLOGICAL(lt) || ISLOGICAL(rt))
2128: {
2129: if(lt != rt){
2130: if (htype
2131: && (lt == TYCHAR && ISNUMERIC(rt)
2132: || rt == TYCHAR && ISNUMERIC(lt)))
2133: return TYLOGICAL;
2134: ERR("illegal comparison")
2135: }
2136: }
2137:
2138: else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
2139: {
2140: if(op!=OPEQ && op!=OPNE)
2141: ERR("order comparison of complex data")
2142: }
2143:
2144: else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
2145: ERR("comparison of nonarithmetic data")
2146: return(TYLOGICAL);
2147:
2148: case OPCONCAT:
2149: if(lt==TYCHAR && rt==TYCHAR)
2150: return(TYCHAR);
2151: ERR("concatenation of nonchar data")
2152:
2153: case OPCALL:
2154: case OPCCALL:
2155: case OPIDENTITY:
2156: return(lt);
2157:
2158: case OPADDR:
2159: case OPCHARCAST:
2160: return(TYADDR);
2161:
2162: case OPCONV:
2163: if(rt == 0)
2164: return(0);
2165: if(lt==TYCHAR && ISINT(rt) )
2166: return(TYCHAR);
2167: if (ISLOGICAL(lt) && ISLOGICAL(rt))
2168: return lt;
2169: case OPASSIGN:
2170: case OPASSIGNI:
2171: case OPMINUSEQ:
2172: case OPPLUSEQ:
2173: case OPSTAREQ:
2174: case OPSLASHEQ:
2175: case OPMODEQ:
2176: case OPLSHIFTEQ:
2177: case OPRSHIFTEQ:
2178: case OPBITANDEQ:
2179: case OPBITXOREQ:
2180: case OPBITOREQ:
2181: if( ISINT(lt) && rt==TYCHAR)
2182: return(lt);
2183: if (ISLOGICAL(lt) && ISLOGICAL(rt) && op == OPASSIGN)
2184: return lt;
2185: if(lt==TYCHAR || rt==TYCHAR || ISLOGICAL(lt) || ISLOGICAL(rt))
2186: if((op!=OPASSIGN && op != OPPLUSEQ && op != OPMINUSEQ)
2187: || (lt!=rt))
2188: {
2189: ERR("impossible conversion")
2190: }
2191: return(lt);
2192:
2193: case OPMIN:
2194: case OPMAX:
2195: case OPDMIN:
2196: case OPDMAX:
2197: case OPMIN2:
2198: case OPMAX2:
2199: case OPBITOR:
2200: case OPBITAND:
2201: case OPBITXOR:
2202: case OPBITNOT:
2203: case OPLSHIFT:
2204: case OPRSHIFT:
2205: case OPWHATSIN:
2206: case OPABS:
2207: case OPDABS:
2208: return(lt);
2209:
2210: case OPCOMMA:
2211: case OPCOMMA_ARG:
2212: case OPQUEST:
2213: case OPCOLON: /* Only checks the rightmost type because
2214: of C language definition (rightmost
2215: comma-expr is the value of the expr) */
2216: return(rt);
2217:
2218: case OPDOT:
2219: case OPARROW:
2220: return (lt);
2221: break;
2222: default:
2223: badop("cktype", op);
2224: }
2225: error:
2226: err(errs);
2227: error1:
2228: return(TYERROR);
2229: }
2230:
2231: /* fold -- simplifies constant expressions; it assumes that e -> leftp and
2232: e -> rightp are TCONST or NULL */
2233:
2234: LOCAL expptr
2235: fold(e)
2236: register expptr e;
2237: {
2238: Constp p;
2239: register expptr lp, rp;
2240: int etype, mtype, ltype, rtype, opcode;
2241: int i, bl, ll, lr;
2242: char *q, *s;
2243: struct Constblock lcon, rcon;
2244: long L;
2245: double d;
2246:
2247: opcode = e->exprblock.opcode;
2248: etype = e->exprblock.vtype;
2249:
2250: lp = e->exprblock.leftp;
2251: ltype = lp->headblock.vtype;
2252: rp = e->exprblock.rightp;
2253:
2254: if(rp == 0)
2255: switch(opcode)
2256: {
2257: case OPNOT:
2258: lp->constblock.Const.ci = ! lp->constblock.Const.ci;
2259: retlp:
2260: e->exprblock.leftp = 0;
2261: frexpr(e);
2262: return(lp);
2263:
2264: case OPBITNOT:
2265: lp->constblock.Const.ci = ~ lp->constblock.Const.ci;
2266: goto retlp;
2267:
2268: case OPNEG:
2269: case OPNEG1:
2270: consnegop((Constp)lp);
2271: goto retlp;
2272:
2273: case OPCONV:
2274: case OPADDR:
2275: return(e);
2276:
2277: case OPABS:
2278: case OPDABS:
2279: switch(ltype) {
2280: case TYINT1:
2281: case TYSHORT:
2282: case TYLONG:
2283: #ifdef TYQUAD
2284: case TYQUAD:
2285: #endif
2286: if ((L = lp->constblock.Const.ci) < 0)
2287: lp->constblock.Const.ci = -L;
2288: goto retlp;
2289: case TYREAL:
2290: case TYDREAL:
2291: if (lp->constblock.vstg) {
2292: s = lp->constblock.Const.cds[0];
2293: if (*s == '-')
2294: lp->constblock.Const.cds[0] = s + 1;
2295: goto retlp;
2296: }
2297: if ((d = lp->constblock.Const.cd[0]) < 0.)
2298: lp->constblock.Const.cd[0] = -d;
2299: case TYCOMPLEX:
2300: case TYDCOMPLEX:
2301: return e; /* lazy way out */
2302: }
2303: default:
2304: badop("fold", opcode);
2305: }
2306:
2307: rtype = rp->headblock.vtype;
2308:
2309: p = ALLOC(Constblock);
2310: p->tag = TCONST;
2311: p->vtype = etype;
2312: p->vleng = e->exprblock.vleng;
2313:
2314: switch(opcode)
2315: {
2316: case OPCOMMA:
2317: case OPCOMMA_ARG:
2318: case OPQUEST:
2319: case OPCOLON:
2320: return(e);
2321:
2322: case OPAND:
2323: p->Const.ci = lp->constblock.Const.ci &&
2324: rp->constblock.Const.ci;
2325: break;
2326:
2327: case OPOR:
2328: p->Const.ci = lp->constblock.Const.ci ||
2329: rp->constblock.Const.ci;
2330: break;
2331:
2332: case OPEQV:
2333: p->Const.ci = lp->constblock.Const.ci ==
2334: rp->constblock.Const.ci;
2335: break;
2336:
2337: case OPNEQV:
2338: p->Const.ci = lp->constblock.Const.ci !=
2339: rp->constblock.Const.ci;
2340: break;
2341:
2342: case OPBITAND:
2343: p->Const.ci = lp->constblock.Const.ci &
2344: rp->constblock.Const.ci;
2345: break;
2346:
2347: case OPBITOR:
2348: p->Const.ci = lp->constblock.Const.ci |
2349: rp->constblock.Const.ci;
2350: break;
2351:
2352: case OPBITXOR:
2353: p->Const.ci = lp->constblock.Const.ci ^
2354: rp->constblock.Const.ci;
2355: break;
2356:
2357: case OPLSHIFT:
2358: p->Const.ci = lp->constblock.Const.ci <<
2359: rp->constblock.Const.ci;
2360: break;
2361:
2362: case OPRSHIFT:
2363: p->Const.ci = lp->constblock.Const.ci >>
2364: rp->constblock.Const.ci;
2365: break;
2366:
2367: case OPCONCAT:
2368: ll = lp->constblock.vleng->constblock.Const.ci;
2369: lr = rp->constblock.vleng->constblock.Const.ci;
2370: bl = lp->constblock.Const.ccp1.blanks;
2371: p->Const.ccp = q = (char *) ckalloc(ll+lr+bl);
2372: p->Const.ccp1.blanks = rp->constblock.Const.ccp1.blanks;
2373: p->vleng = ICON(ll+lr+bl);
2374: s = lp->constblock.Const.ccp;
2375: for(i = 0 ; i < ll ; ++i)
2376: *q++ = *s++;
2377: for(i = 0 ; i < bl ; i++)
2378: *q++ = ' ';
2379: s = rp->constblock.Const.ccp;
2380: for(i = 0; i < lr; ++i)
2381: *q++ = *s++;
2382: break;
2383:
2384:
2385: case OPPOWER:
2386: if( ! ISINT(rtype) )
2387: return(e);
2388: conspower(p, (Constp)lp, rp->constblock.Const.ci);
2389: break;
2390:
2391:
2392: default:
2393: if(ltype == TYCHAR)
2394: {
2395: lcon.Const.ci = cmpstr(lp->constblock.Const.ccp,
2396: rp->constblock.Const.ccp,
2397: lp->constblock.vleng->constblock.Const.ci,
2398: rp->constblock.vleng->constblock.Const.ci);
2399: rcon.Const.ci = 0;
2400: mtype = tyint;
2401: }
2402: else {
2403: mtype = maxtype(ltype, rtype);
2404: consconv(mtype, &lcon, &lp->constblock);
2405: consconv(mtype, &rcon, &rp->constblock);
2406: }
2407: consbinop(opcode, mtype, p, &lcon, &rcon);
2408: break;
2409: }
2410:
2411: frexpr(e);
2412: return( (expptr) p );
2413: }
2414:
2415:
2416:
2417: /* assign constant l = r , doing coercion */
2418:
2419: consconv(lt, lc, rc)
2420: int lt;
2421: register Constp lc, rc;
2422: {
2423: int rt = rc->vtype;
2424: register union Constant *lv = &lc->Const, *rv = &rc->Const;
2425:
2426: lc->vtype = lt;
2427: if (ONEOF(lt, MSKREAL|MSKCOMPLEX) && ONEOF(rt, MSKREAL|MSKCOMPLEX)) {
2428: memcpy((char *)lv, (char *)rv, sizeof(union Constant));
2429: lc->vstg = rc->vstg;
2430: if (ISCOMPLEX(lt) && ISREAL(rt)) {
2431: if (rc->vstg)
2432: lv->cds[1] = cds("0",CNULL);
2433: else
2434: lv->cd[1] = 0.;
2435: }
2436: return;
2437: }
2438: lc->vstg = 0;
2439:
2440: switch(lt)
2441: {
2442:
2443: /* Casting to character means just copying the first sizeof (character)
2444: bytes into a new 1 character string. This is weird. */
2445:
2446: case TYCHAR:
2447: *(lv->ccp = (char *) ckalloc(1)) = rv->ci;
2448: lv->ccp1.blanks = 0;
2449: break;
2450:
2451: case TYINT1:
2452: case TYSHORT:
2453: case TYLONG:
2454: #ifdef TYQUAD
2455: case TYQUAD:
2456: #endif
2457: if(rt == TYCHAR)
2458: lv->ci = rv->ccp[0];
2459: else if( ISINT(rt) )
2460: lv->ci = rv->ci;
2461: else lv->ci = rc->vstg ? atof(rv->cds[0]) : rv->cd[0];
2462:
2463: break;
2464:
2465: case TYCOMPLEX:
2466: case TYDCOMPLEX:
2467: lv->cd[1] = 0.;
2468: lv->cd[0] = rv->ci;
2469: break;
2470:
2471: case TYREAL:
2472: case TYDREAL:
2473: lv->cd[0] = rv->ci;
2474: break;
2475:
2476: case TYLOGICAL:
2477: case TYLOGICAL1:
2478: case TYLOGICAL2:
2479: lv->ci = rv->ci;
2480: break;
2481: }
2482: }
2483:
2484:
2485:
2486: /* Negate constant value -- changes the input node's value */
2487:
2488: consnegop(p)
2489: register Constp p;
2490: {
2491: register char *s;
2492:
2493: if (p->vstg) {
2494: if (ISCOMPLEX(p->vtype)) {
2495: s = p->Const.cds[1];
2496: p->Const.cds[1] = *s == '-' ? s+1
2497: : *s == '0' ? s : s-1;
2498: }
2499: s = p->Const.cds[0];
2500: p->Const.cds[0] = *s == '-' ? s+1
2501: : *s == '0' ? s : s-1;
2502: return;
2503: }
2504: switch(p->vtype)
2505: {
2506: case TYINT1:
2507: case TYSHORT:
2508: case TYLONG:
2509: #ifdef TYQUAD
2510: case TYQUAD:
2511: #endif
2512: p->Const.ci = - p->Const.ci;
2513: break;
2514:
2515: case TYCOMPLEX:
2516: case TYDCOMPLEX:
2517: p->Const.cd[1] = - p->Const.cd[1];
2518: /* fall through and do the real parts */
2519: case TYREAL:
2520: case TYDREAL:
2521: p->Const.cd[0] = - p->Const.cd[0];
2522: break;
2523: default:
2524: badtype("consnegop", p->vtype);
2525: }
2526: }
2527:
2528:
2529:
2530: /* conspower -- Expand out an exponentiation */
2531:
2532: LOCAL void
2533: conspower(p, ap, n)
2534: Constp p, ap;
2535: ftnint n;
2536: {
2537: register union Constant *powp = &p->Const;
2538: register int type;
2539: struct Constblock x, x0;
2540:
2541: if (n == 1) {
2542: memcpy((char *)powp, (char *)&ap->Const, sizeof(ap->Const));
2543: return;
2544: }
2545:
2546: switch(type = ap->vtype) /* pow = 1 */
2547: {
2548: case TYINT1:
2549: case TYSHORT:
2550: case TYLONG:
2551: #ifdef TYQUAD
2552: case TYQUAD:
2553: #endif
2554: powp->ci = 1;
2555: break;
2556: case TYCOMPLEX:
2557: case TYDCOMPLEX:
2558: powp->cd[1] = 0;
2559: case TYREAL:
2560: case TYDREAL:
2561: powp->cd[0] = 1;
2562: break;
2563: default:
2564: badtype("conspower", type);
2565: }
2566:
2567: if(n == 0)
2568: return;
2569: switch(type) /* x0 = ap */
2570: {
2571: case TYINT1:
2572: case TYSHORT:
2573: case TYLONG:
2574: #ifdef TYQUAD
2575: case TYQUAD:
2576: #endif
2577: x0.Const.ci = ap->Const.ci;
2578: break;
2579: case TYCOMPLEX:
2580: case TYDCOMPLEX:
2581: x0.Const.cd[1] =
2582: ap->vstg ? atof(ap->Const.cds[1]) : ap->Const.cd[1];
2583: case TYREAL:
2584: case TYDREAL:
2585: x0.Const.cd[0] =
2586: ap->vstg ? atof(ap->Const.cds[0]) : ap->Const.cd[0];
2587: break;
2588: }
2589: x0.vtype = type;
2590: x0.vstg = 0;
2591: if(n < 0)
2592: {
2593: if( ISINT(type) )
2594: {
2595: err("integer ** negative number");
2596: return;
2597: }
2598: else if (!x0.Const.cd[0]
2599: && (!ISCOMPLEX(type) || !x0.Const.cd[1])) {
2600: err("0.0 ** negative number");
2601: return;
2602: }
2603: n = -n;
2604: consbinop(OPSLASH, type, &x, p, &x0);
2605: }
2606: else
2607: consbinop(OPSTAR, type, &x, p, &x0);
2608:
2609: for( ; ; )
2610: {
2611: if(n & 01)
2612: consbinop(OPSTAR, type, p, p, &x);
2613: if(n >>= 1)
2614: consbinop(OPSTAR, type, &x, &x, &x);
2615: else
2616: break;
2617: }
2618: }
2619:
2620:
2621:
2622: /* do constant operation cp = a op b -- assumes that ap and bp have data
2623: matching the input type */
2624:
2625: LOCAL void
2626: zerodiv()
2627: { Fatal("division by zero during constant evaluation; cannot recover"); }
2628:
2629: LOCAL void
2630: consbinop(opcode, type, cpp, app, bpp)
2631: int opcode, type;
2632: Constp cpp, app, bpp;
2633: {
2634: register union Constant *ap = &app->Const,
2635: *bp = &bpp->Const,
2636: *cp = &cpp->Const;
2637: int k;
2638: double ad[2], bd[2], temp;
2639:
2640: cpp->vstg = 0;
2641:
2642: if (ONEOF(type, MSKREAL|MSKCOMPLEX)) {
2643: ad[0] = app->vstg ? atof(ap->cds[0]) : ap->cd[0];
2644: bd[0] = bpp->vstg ? atof(bp->cds[0]) : bp->cd[0];
2645: if (ISCOMPLEX(type)) {
2646: ad[1] = app->vstg ? atof(ap->cds[1]) : ap->cd[1];
2647: bd[1] = bpp->vstg ? atof(bp->cds[1]) : bp->cd[1];
2648: }
2649: }
2650: switch(opcode)
2651: {
2652: case OPPLUS:
2653: switch(type)
2654: {
2655: case TYINT1:
2656: case TYSHORT:
2657: case TYLONG:
2658: #ifdef TYQUAD
2659: case TYQUAD:
2660: #endif
2661: cp->ci = ap->ci + bp->ci;
2662: break;
2663: case TYCOMPLEX:
2664: case TYDCOMPLEX:
2665: cp->cd[1] = ad[1] + bd[1];
2666: case TYREAL:
2667: case TYDREAL:
2668: cp->cd[0] = ad[0] + bd[0];
2669: break;
2670: }
2671: break;
2672:
2673: case OPMINUS:
2674: switch(type)
2675: {
2676: case TYINT1:
2677: case TYSHORT:
2678: case TYLONG:
2679: #ifdef TYQUAD
2680: case TYQUAD:
2681: #endif
2682: cp->ci = ap->ci - bp->ci;
2683: break;
2684: case TYCOMPLEX:
2685: case TYDCOMPLEX:
2686: cp->cd[1] = ad[1] - bd[1];
2687: case TYREAL:
2688: case TYDREAL:
2689: cp->cd[0] = ad[0] - bd[0];
2690: break;
2691: }
2692: break;
2693:
2694: case OPSTAR:
2695: switch(type)
2696: {
2697: case TYINT1:
2698: case TYSHORT:
2699: case TYLONG:
2700: #ifdef TYQUAD
2701: case TYQUAD:
2702: #endif
2703: cp->ci = ap->ci * bp->ci;
2704: break;
2705: case TYREAL:
2706: case TYDREAL:
2707: cp->cd[0] = ad[0] * bd[0];
2708: break;
2709: case TYCOMPLEX:
2710: case TYDCOMPLEX:
2711: temp = ad[0] * bd[0] - ad[1] * bd[1] ;
2712: cp->cd[1] = ad[0] * bd[1] + ad[1] * bd[0] ;
2713: cp->cd[0] = temp;
2714: break;
2715: }
2716: break;
2717: case OPSLASH:
2718: switch(type)
2719: {
2720: case TYINT1:
2721: case TYSHORT:
2722: case TYLONG:
2723: #ifdef TYQUAD
2724: case TYQUAD:
2725: #endif
2726: if (!bp->ci)
2727: zerodiv();
2728: cp->ci = ap->ci / bp->ci;
2729: break;
2730: case TYREAL:
2731: case TYDREAL:
2732: if (!bd[0])
2733: zerodiv();
2734: cp->cd[0] = ad[0] / bd[0];
2735: break;
2736: case TYCOMPLEX:
2737: case TYDCOMPLEX:
2738: if (!bd[0] && !bd[1])
2739: zerodiv();
2740: zdiv((dcomplex*)cp, (dcomplex*)ad, (dcomplex*)bd);
2741: break;
2742: }
2743: break;
2744:
2745: case OPMOD:
2746: if( ISINT(type) )
2747: {
2748: cp->ci = ap->ci % bp->ci;
2749: break;
2750: }
2751: else
2752: Fatal("inline mod of noninteger");
2753:
2754: case OPMIN2:
2755: case OPDMIN:
2756: switch(type)
2757: {
2758: case TYINT1:
2759: case TYSHORT:
2760: case TYLONG:
2761: #ifdef TYQUAD
2762: case TYQUAD:
2763: #endif
2764: cp->ci = ap->ci <= bp->ci ? ap->ci : bp->ci;
2765: break;
2766: case TYREAL:
2767: case TYDREAL:
2768: cp->cd[0] = ad[0] <= bd[0] ? ad[0] : bd[0];
2769: break;
2770: default:
2771: Fatal("inline min of exected type");
2772: }
2773: break;
2774:
2775: case OPMAX2:
2776: case OPDMAX:
2777: switch(type)
2778: {
2779: case TYINT1:
2780: case TYSHORT:
2781: case TYLONG:
2782: #ifdef TYQUAD
2783: case TYQUAD:
2784: #endif
2785: cp->ci = ap->ci >= bp->ci ? ap->ci : bp->ci;
2786: break;
2787: case TYREAL:
2788: case TYDREAL:
2789: cp->cd[0] = ad[0] >= bd[0] ? ad[0] : bd[0];
2790: break;
2791: default:
2792: Fatal("inline max of exected type");
2793: }
2794: break;
2795:
2796: default: /* relational ops */
2797: switch(type)
2798: {
2799: case TYINT1:
2800: case TYSHORT:
2801: case TYLONG:
2802: #ifdef TYQUAD
2803: case TYQUAD:
2804: #endif
2805: if(ap->ci < bp->ci)
2806: k = -1;
2807: else if(ap->ci == bp->ci)
2808: k = 0;
2809: else k = 1;
2810: break;
2811: case TYREAL:
2812: case TYDREAL:
2813: if(ad[0] < bd[0])
2814: k = -1;
2815: else if(ad[0] == bd[0])
2816: k = 0;
2817: else k = 1;
2818: break;
2819: case TYCOMPLEX:
2820: case TYDCOMPLEX:
2821: if(ad[0] == bd[0] &&
2822: ad[1] == bd[1] )
2823: k = 0;
2824: else k = 1;
2825: break;
2826: }
2827:
2828: switch(opcode)
2829: {
2830: case OPEQ:
2831: cp->ci = (k == 0);
2832: break;
2833: case OPNE:
2834: cp->ci = (k != 0);
2835: break;
2836: case OPGT:
2837: cp->ci = (k == 1);
2838: break;
2839: case OPLT:
2840: cp->ci = (k == -1);
2841: break;
2842: case OPGE:
2843: cp->ci = (k >= 0);
2844: break;
2845: case OPLE:
2846: cp->ci = (k <= 0);
2847: break;
2848: }
2849: break;
2850: }
2851: }
2852:
2853:
2854:
2855: /* conssgn - returns the sign of a Fortran constant */
2856:
2857: conssgn(p)
2858: register expptr p;
2859: {
2860: register char *s;
2861:
2862: if( ! ISCONST(p) )
2863: Fatal( "sgn(nonconstant)" );
2864:
2865: switch(p->headblock.vtype)
2866: {
2867: case TYINT1:
2868: case TYSHORT:
2869: case TYLONG:
2870: #ifdef TYQUAD
2871: case TYQUAD:
2872: #endif
2873: if(p->constblock.Const.ci > 0) return(1);
2874: if(p->constblock.Const.ci < 0) return(-1);
2875: return(0);
2876:
2877: case TYREAL:
2878: case TYDREAL:
2879: if (p->constblock.vstg) {
2880: s = p->constblock.Const.cds[0];
2881: if (*s == '-')
2882: return -1;
2883: if (*s == '0')
2884: return 0;
2885: return 1;
2886: }
2887: if(p->constblock.Const.cd[0] > 0) return(1);
2888: if(p->constblock.Const.cd[0] < 0) return(-1);
2889: return(0);
2890:
2891:
2892: /* The sign of a complex number is 0 iff the number is 0 + 0i, else it's 1 */
2893:
2894: case TYCOMPLEX:
2895: case TYDCOMPLEX:
2896: if (p->constblock.vstg)
2897: return *p->constblock.Const.cds[0] != '0'
2898: && *p->constblock.Const.cds[1] != '0';
2899: return(p->constblock.Const.cd[0]!=0 || p->constblock.Const.cd[1]!=0);
2900:
2901: default:
2902: badtype( "conssgn", p->constblock.vtype);
2903: }
2904: /* NOT REACHED */ return 0;
2905: }
2906:
2907: char *powint[ ] = {
2908: "pow_ii",
2909: #ifdef TYQUAD
2910: "pow_qi",
2911: #endif
2912: "pow_ri", "pow_di", "pow_ci", "pow_zi" };
2913:
2914: LOCAL expptr mkpower(p)
2915: register expptr p;
2916: {
2917: register expptr q, lp, rp;
2918: int ltype, rtype, mtype, tyi;
2919:
2920: lp = p->exprblock.leftp;
2921: rp = p->exprblock.rightp;
2922: ltype = lp->headblock.vtype;
2923: rtype = rp->headblock.vtype;
2924:
2925: if (lp->tag == TADDR)
2926: lp->addrblock.parenused = 0;
2927:
2928: if (rp->tag == TADDR)
2929: rp->addrblock.parenused = 0;
2930:
2931: if(ISICON(rp))
2932: {
2933: if(rp->constblock.Const.ci == 0)
2934: {
2935: frexpr(p);
2936: if( ISINT(ltype) )
2937: return( ICON(1) );
2938: else if (ISREAL (ltype))
2939: return mkconv (ltype, ICON (1));
2940: else
2941: return( (expptr) putconst((Constp)
2942: mkconv(ltype, ICON(1))) );
2943: }
2944: if(rp->constblock.Const.ci < 0)
2945: {
2946: if( ISINT(ltype) )
2947: {
2948: frexpr(p);
2949: err("integer**negative");
2950: return( errnode() );
2951: }
2952: rp->constblock.Const.ci = - rp->constblock.Const.ci;
2953: p->exprblock.leftp = lp
2954: = fixexpr((Exprp)mkexpr(OPSLASH, ICON(1), lp));
2955: }
2956: if(rp->constblock.Const.ci == 1)
2957: {
2958: frexpr(rp);
2959: free( (charptr) p );
2960: return(lp);
2961: }
2962:
2963: if( ONEOF(ltype, MSKINT|MSKREAL) ) {
2964: p->exprblock.vtype = ltype;
2965: return(p);
2966: }
2967: }
2968: if( ISINT(rtype) )
2969: {
2970: if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
2971: q = call2(TYSHORT, "pow_hh", lp, rp);
2972: else {
2973: if(ONEOF(ltype,M(TYINT1)|M(TYSHORT)))
2974: {
2975: ltype = TYLONG;
2976: lp = mkconv(TYLONG,lp);
2977: }
2978: #ifdef TYQUAD
2979: if (ltype == TYQUAD)
2980: rp = mkconv(TYQUAD,rp);
2981: else
2982: #endif
2983: rp = mkconv(TYLONG,rp);
2984: if (ISCONST(rp)) {
2985: tyi = tyint;
2986: tyint = TYLONG;
2987: rp = (expptr)putconst((Constp)rp);
2988: tyint = tyi;
2989: }
2990: q = call2(ltype, powint[ltype-TYLONG], lp, rp);
2991: }
2992: }
2993: else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) {
2994: extern int callk_kludge;
2995: callk_kludge = TYDREAL;
2996: q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
2997: callk_kludge = 0;
2998: }
2999: else {
3000: q = call2(TYDCOMPLEX, "pow_zz",
3001: mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
3002: if(mtype == TYCOMPLEX)
3003: q = mkconv(TYCOMPLEX, q);
3004: }
3005: free( (charptr) p );
3006: return(q);
3007: }
3008:
3009:
3010: /* Complex Division. Same code as in Runtime Library
3011: */
3012:
3013:
3014: LOCAL void
3015: zdiv(c, a, b)
3016: register dcomplex *a, *b, *c;
3017: {
3018: double ratio, den;
3019: double abr, abi;
3020:
3021: if( (abr = b->dreal) < 0.)
3022: abr = - abr;
3023: if( (abi = b->dimag) < 0.)
3024: abi = - abi;
3025: if( abr <= abi )
3026: {
3027: if(abi == 0)
3028: Fatal("complex division by zero");
3029: ratio = b->dreal / b->dimag ;
3030: den = b->dimag * (1 + ratio*ratio);
3031: c->dreal = (a->dreal*ratio + a->dimag) / den;
3032: c->dimag = (a->dimag*ratio - a->dreal) / den;
3033: }
3034:
3035: else
3036: {
3037: ratio = b->dimag / b->dreal ;
3038: den = b->dreal * (1 + ratio*ratio);
3039: c->dreal = (a->dreal + a->dimag*ratio) / den;
3040: c->dimag = (a->dimag - a->dreal*ratio) / den;
3041: }
3042: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.