|
|
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: /* INTERMEDIATE CODE GENERATION FOR S. C. JOHNSON C COMPILERS */
25: /* NEW VERSION USING BINARY POLISH POSTFIX INTERMEDIATE */
26:
27: #include "defs.h"
28: #include "pccdefs.h"
29: #include "output.h" /* for nice_printf */
30: #include "names.h"
31: #include "p1defs.h"
32:
33: Addrp realpart();
34: LOCAL Addrp intdouble(), putcx1(), putcxeq (), putch1 ();
35: LOCAL putct1 ();
36:
37: expptr putcxop();
38: LOCAL expptr putcall (), putmnmx (), putcheq(), putcat ();
39: LOCAL expptr putaddr(), putchcmp (), putpower(), putop();
40: LOCAL expptr putcxcmp ();
41: expptr imagpart();
42: ftnint lencat();
43:
44: #define FOUR 4
45: extern int ops2[];
46: extern int proc_argchanges, proc_protochanges;
47: extern int krparens;
48:
49: #define P2BUFFMAX 128
50:
51: /* Puthead -- output the header information about subroutines, functions
52: and entry points */
53:
54: puthead(s, class)
55: char *s;
56: int class;
57: {
58: if (headerdone == NO) {
59: if (class == CLMAIN)
60: s = "MAIN__";
61: p1_head (class, s);
62: headerdone = YES;
63: }
64: }
65:
66: putif(p, else_if_p)
67: register expptr p;
68: int else_if_p;
69: {
70: register int k;
71: int n;
72: long where;
73:
74: if (else_if_p) {
75: p1put(P1_ELSEIFSTART);
76: where = ftell(pass1_file);
77: }
78: if( !ISLOGICAL((k = (p = fixtype(p))->headblock.vtype )) )
79: {
80: if(k != TYERROR)
81: err("non-logical expression in IF statement");
82: }
83: else {
84: if (else_if_p) {
85: if (ei_next >= ei_last)
86: {
87: k = ei_last - ei_first;
88: n = k + 100;
89: ei_next = mem(n,0);
90: ei_last = ei_first + n;
91: if (k)
92: memcpy(ei_next, ei_first, k);
93: ei_first = ei_next;
94: ei_next += k;
95: ei_last = ei_first + n;
96: }
97: p = putx(p);
98: if (*ei_next++ = ftell(pass1_file) > where) {
99: p1_if(p);
100: new_endif();
101: }
102: else
103: p1_elif(p);
104: }
105: else {
106: p = putx(p);
107: p1_if(p);
108: }
109: }
110: }
111:
112:
113: putout(p)
114: expptr p;
115: {
116: p1_expr (p);
117:
118: /* Used to make temporaries in holdtemps available here, but they */
119: /* may be reused too soon (e.g. when multiple **'s are involved). */
120: }
121:
122:
123:
124: putcmgo(index, nlab, labs)
125: expptr index;
126: int nlab;
127: struct Labelblock *labs[];
128: {
129: if(! ISINT(index->headblock.vtype) )
130: {
131: execerr("computed goto index must be integer", CNULL);
132: return;
133: }
134:
135: p1comp_goto (index, nlab, labs);
136: }
137:
138: static expptr
139: krput(p)
140: register expptr p;
141: {
142: register expptr e, e1;
143: register unsigned op;
144: int t = krparens == 2 ? TYDREAL : p->exprblock.vtype;
145:
146: op = p->exprblock.opcode;
147: e = p->exprblock.leftp;
148: if (e->tag == TEXPR && e->exprblock.opcode == op) {
149: e1 = (expptr)mktmp(t, ENULL);
150: putout(putassign(cpexpr(e1), e));
151: p->exprblock.leftp = e1;
152: }
153: else
154: p->exprblock.leftp = putx(e);
155:
156: e = p->exprblock.rightp;
157: if (e->tag == TEXPR && e->exprblock.opcode == op) {
158: e1 = (expptr)mktmp(t, ENULL);
159: putout(putassign(cpexpr(e1), e));
160: p->exprblock.rightp = e1;
161: }
162: else
163: p->exprblock.rightp = putx(e);
164: return p;
165: }
166:
167: expptr putx(p)
168: register expptr p;
169: {
170: int opc;
171: int k;
172:
173: if (p)
174: switch(p->tag)
175: {
176: case TERROR:
177: break;
178:
179: case TCONST:
180: switch(p->constblock.vtype)
181: {
182: case TYLOGICAL1:
183: case TYLOGICAL2:
184: case TYLOGICAL:
185: #ifdef TYQUAD
186: case TYQUAD:
187: #endif
188: case TYLONG:
189: case TYSHORT:
190: case TYINT1:
191: break;
192:
193: case TYADDR:
194: break;
195: case TYREAL:
196: case TYDREAL:
197:
198: /* Don't write it out to the p2 file, since you'd need to call putconst,
199: which is just what we need to avoid in the translator */
200:
201: break;
202: default:
203: p = putx( (expptr)putconst((Constp)p) );
204: break;
205: }
206: break;
207:
208: case TEXPR:
209: switch(opc = p->exprblock.opcode)
210: {
211: case OPCALL:
212: case OPCCALL:
213: if( ISCOMPLEX(p->exprblock.vtype) )
214: p = putcxop(p);
215: else p = putcall(p, (Addrp *)NULL);
216: break;
217:
218: case OPMIN:
219: case OPMAX:
220: p = putmnmx(p);
221: break;
222:
223:
224: case OPASSIGN:
225: if(ISCOMPLEX(p->exprblock.leftp->headblock.vtype)
226: || ISCOMPLEX(p->exprblock.rightp->headblock.vtype)) {
227: (void) putcxeq(p);
228: p = ENULL;
229: } else if( ISCHAR(p) )
230: p = putcheq(p);
231: else
232: goto putopp;
233: break;
234:
235: case OPEQ:
236: case OPNE:
237: if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) ||
238: ISCOMPLEX(p->exprblock.rightp->headblock.vtype) )
239: {
240: p = putcxcmp(p);
241: break;
242: }
243: case OPLT:
244: case OPLE:
245: case OPGT:
246: case OPGE:
247: if(ISCHAR(p->exprblock.leftp))
248: {
249: p = putchcmp(p);
250: break;
251: }
252: goto putopp;
253:
254: case OPPOWER:
255: p = putpower(p);
256: break;
257:
258: case OPSTAR:
259: /* m * (2**k) -> m<<k */
260: if(INT(p->exprblock.leftp->headblock.vtype) &&
261: ISICON(p->exprblock.rightp) &&
262: ( (k = log_2(p->exprblock.rightp->constblock.Const.ci))>0) )
263: {
264: p->exprblock.opcode = OPLSHIFT;
265: frexpr(p->exprblock.rightp);
266: p->exprblock.rightp = ICON(k);
267: goto putopp;
268: }
269: if (krparens && ISREAL(p->exprblock.vtype))
270: return krput(p);
271:
272: case OPMOD:
273: goto putopp;
274: case OPPLUS:
275: if (krparens && ISREAL(p->exprblock.vtype))
276: return krput(p);
277: case OPMINUS:
278: case OPSLASH:
279: case OPNEG:
280: case OPNEG1:
281: case OPABS:
282: case OPDABS:
283: if( ISCOMPLEX(p->exprblock.vtype) )
284: p = putcxop(p);
285: else goto putopp;
286: break;
287:
288: case OPCONV:
289: if( ISCOMPLEX(p->exprblock.vtype) )
290: p = putcxop(p);
291: else if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) )
292: {
293: p = putx( mkconv(p->exprblock.vtype,
294: (expptr)realpart(putcx1(p->exprblock.leftp))));
295: }
296: else goto putopp;
297: break;
298:
299: case OPNOT:
300: case OPOR:
301: case OPAND:
302: case OPEQV:
303: case OPNEQV:
304: case OPADDR:
305: case OPPLUSEQ:
306: case OPSTAREQ:
307: case OPCOMMA:
308: case OPQUEST:
309: case OPCOLON:
310: case OPBITOR:
311: case OPBITAND:
312: case OPBITXOR:
313: case OPBITNOT:
314: case OPLSHIFT:
315: case OPRSHIFT:
316: case OPASSIGNI:
317: case OPIDENTITY:
318: case OPCHARCAST:
319: case OPMIN2:
320: case OPMAX2:
321: case OPDMIN:
322: case OPDMAX:
323: putopp:
324: p = putop(p);
325: break;
326:
327: case OPCONCAT:
328: /* weird things like ichar(a//a) */
329: p = (expptr)putch1(p);
330: break;
331:
332: default:
333: badop("putx", opc);
334: p = errnode ();
335: }
336: break;
337:
338: case TADDR:
339: p = putaddr(p);
340: break;
341:
342: default:
343: badtag("putx", p->tag);
344: p = errnode ();
345: }
346:
347: return p;
348: }
349:
350:
351:
352: LOCAL expptr putop(p)
353: expptr p;
354: {
355: expptr lp, tp;
356: int pt, lt, lt1;
357: int comma;
358:
359: switch(p->exprblock.opcode) /* check for special cases and rewrite */
360: {
361: case OPCONV:
362: pt = p->exprblock.vtype;
363: lp = p->exprblock.leftp;
364: lt = lp->headblock.vtype;
365:
366: /* Simplify nested type casts */
367:
368: while(p->tag==TEXPR && p->exprblock.opcode==OPCONV &&
369: ( (ISREAL(pt)&&ONEOF(lt,MSKREAL|MSKCOMPLEX)) ||
370: (INT(pt)&&(ONEOF(lt,MSKINT|MSKADDR|MSKCHAR|M(TYSUBR)))) ))
371: {
372: if(pt==TYDREAL && lt==TYREAL)
373: {
374: if(lp->tag==TEXPR
375: && lp->exprblock.opcode == OPCONV) {
376: lt1 = lp->exprblock.leftp->headblock.vtype;
377: if (lt1 == TYDREAL) {
378: lp->exprblock.leftp =
379: putx(lp->exprblock.leftp);
380: return p;
381: }
382: if (lt1 == TYDCOMPLEX) {
383: lp->exprblock.leftp = putx(
384: (expptr)realpart(
385: putcx1(lp->exprblock.leftp)));
386: return p;
387: }
388: }
389: break;
390: }
391: else if (ISREAL(pt) && ISCOMPLEX(lt)) {
392: p->exprblock.leftp = putx(mkconv(pt,
393: (expptr)realpart(
394: putcx1(p->exprblock.leftp))));
395: break;
396: }
397: if(lt==TYCHAR && lp->tag==TEXPR &&
398: lp->exprblock.opcode==OPCALL)
399: {
400:
401: /* May want to make a comma expression here instead. I had one, but took
402: it out for my convenience, not for the convenience of the end user */
403:
404: putout (putcall (lp, (Addrp *) &(p ->
405: exprblock.leftp)));
406: return putop (p);
407: }
408: if (lt == TYCHAR) {
409: p->exprblock.leftp = putx(p->exprblock.leftp);
410: return p;
411: }
412: frexpr(p->exprblock.vleng);
413: free( (charptr) p );
414: p = lp;
415: if (p->tag != TEXPR)
416: goto retputx;
417: pt = lt;
418: lp = p->exprblock.leftp;
419: lt = lp->headblock.vtype;
420: } /* while */
421: if(p->tag==TEXPR && p->exprblock.opcode==OPCONV)
422: break;
423: retputx:
424: return putx(p);
425:
426: case OPADDR:
427: comma = NO;
428: lp = p->exprblock.leftp;
429: free( (charptr) p );
430: if(lp->tag != TADDR)
431: {
432: tp = (expptr)
433: mktmp(lp->headblock.vtype,lp->headblock.vleng);
434: p = putx( mkexpr(OPASSIGN, cpexpr(tp), lp) );
435: lp = tp;
436: comma = YES;
437: }
438: if(comma)
439: p = mkexpr(OPCOMMA, p, putaddr(lp));
440: else
441: p = (expptr)putaddr(lp);
442: return p;
443:
444: case OPASSIGN:
445: case OPASSIGNI:
446: case OPLT:
447: case OPLE:
448: case OPGT:
449: case OPGE:
450: case OPEQ:
451: case OPNE:
452: ;
453: }
454:
455: if( ops2[p->exprblock.opcode] <= 0)
456: badop("putop", p->exprblock.opcode);
457: p -> exprblock.leftp = putx (p -> exprblock.leftp);
458: if (p -> exprblock.rightp)
459: p -> exprblock.rightp = putx (p -> exprblock.rightp);
460: return p;
461: }
462:
463: LOCAL expptr putpower(p)
464: expptr p;
465: {
466: expptr base;
467: Addrp t1, t2;
468: ftnint k;
469: int type;
470: char buf[80]; /* buffer for text of comment */
471:
472: if(!ISICON(p->exprblock.rightp) ||
473: (k = p->exprblock.rightp->constblock.Const.ci)<2)
474: Fatal("putpower: bad call");
475: base = p->exprblock.leftp;
476: type = base->headblock.vtype;
477: t1 = mktmp(type, ENULL);
478: t2 = NULL;
479:
480: free ((charptr) p);
481: p = putassign (cpexpr((expptr) t1), base);
482:
483: sprintf (buf, "Computing %ld%s power", k,
484: k == 2 ? "nd" : k == 3 ? "rd" : "th");
485: p1_comment (buf);
486:
487: for( ; (k&1)==0 && k>2 ; k>>=1 )
488: {
489: p = mkexpr (OPCOMMA, p, putsteq(t1, t1));
490: }
491:
492: if(k == 2) {
493:
494: /* Write the power computation out immediately */
495: putout (p);
496: p = putx( mkexpr(OPSTAR, cpexpr((expptr)t1), cpexpr((expptr)t1)));
497: } else {
498: t2 = mktmp(type, ENULL);
499: p = mkexpr (OPCOMMA, p, putassign(cpexpr((expptr)t2),
500: cpexpr((expptr)t1)));
501:
502: for(k>>=1 ; k>1 ; k>>=1)
503: {
504: p = mkexpr (OPCOMMA, p, putsteq(t1, t1));
505: if(k & 1)
506: {
507: p = mkexpr (OPCOMMA, p, putsteq(t2, t1));
508: }
509: }
510: /* Write the power computation out immediately */
511: putout (p);
512: p = putx( mkexpr(OPSTAR, cpexpr((expptr)t2),
513: mkexpr(OPSTAR, cpexpr((expptr)t1), cpexpr((expptr)t1))));
514: }
515: frexpr((expptr)t1);
516: if(t2)
517: frexpr((expptr)t2);
518: return p;
519: }
520:
521:
522:
523:
524: LOCAL Addrp intdouble(p)
525: Addrp p;
526: {
527: register Addrp t;
528:
529: t = mktmp(TYDREAL, ENULL);
530: putout (putassign(cpexpr((expptr)t), (expptr)p));
531: return(t);
532: }
533:
534:
535:
536:
537:
538: /* Complex-type variable assignment */
539:
540: LOCAL Addrp putcxeq(p)
541: register expptr p;
542: {
543: register Addrp lp, rp;
544: expptr code;
545:
546: if(p->tag != TEXPR)
547: badtag("putcxeq", p->tag);
548:
549: lp = putcx1(p->exprblock.leftp);
550: rp = putcx1(p->exprblock.rightp);
551: code = putassign ( (expptr)realpart(lp), (expptr)realpart(rp));
552:
553: if( ISCOMPLEX(p->exprblock.vtype) )
554: {
555: code = mkexpr (OPCOMMA, code, putassign
556: (imagpart(lp), imagpart(rp)));
557: }
558: putout (code);
559: frexpr((expptr)rp);
560: free ((charptr) p);
561: return lp;
562: }
563:
564:
565:
566: /* putcxop -- used to write out embedded calls to complex functions, and
567: complex arguments to procedures */
568:
569: expptr putcxop(p)
570: expptr p;
571: {
572: return (expptr)putaddr((expptr)putcx1(p));
573: }
574:
575: #define PAIR(x,y) mkexpr (OPCOMMA, (x), (y))
576:
577: LOCAL Addrp putcx1(p)
578: register expptr p;
579: {
580: expptr q;
581: Addrp lp, rp;
582: register Addrp resp;
583: int opcode;
584: int ltype, rtype;
585: long ts, tskludge;
586: expptr mkrealcon();
587:
588: if(p == NULL)
589: return(NULL);
590:
591: switch(p->tag)
592: {
593: case TCONST:
594: if( ISCOMPLEX(p->constblock.vtype) )
595: p = (expptr) putconst((Constp)p);
596: return( (Addrp) p );
597:
598: case TADDR:
599: resp = &p->addrblock;
600: if (addressable(p))
601: return (Addrp) p;
602: ts = tskludge = 0;
603: if (q = resp->memoffset) {
604: if (resp->uname_tag == UNAM_REF) {
605: q = cpexpr((tagptr)resp);
606: q->addrblock.vtype = tyint;
607: q->addrblock.cmplx_sub = 1;
608: p->addrblock.skip_offset = 1;
609: resp->user.name->vsubscrused = 1;
610: resp->uname_tag = UNAM_NAME;
611: tskludge = typesize[resp->vtype]
612: * (resp->Field ? 2 : 1);
613: }
614: else if (resp->isarray
615: && resp->vtype != TYCHAR) {
616: if (ONEOF(resp->vstg, M(STGCOMMON)|M(STGEQUIV))
617: && resp->uname_tag == UNAM_NAME)
618: q = mkexpr(OPMINUS, q,
619: mkintcon(resp->user.name->voffset));
620: ts = typesize[resp->vtype]
621: * (resp->Field ? 2 : 1);
622: q = resp->memoffset = mkexpr(OPSLASH, q,
623: ICON(ts));
624: }
625: }
626: resp = mktmp(tyint, ENULL);
627: putout(putassign(cpexpr((expptr)resp), q));
628: p->addrblock.memoffset = tskludge
629: ? mkexpr(OPSTAR, resp, ICON(tskludge))
630: : (expptr)resp;
631: if (ts) {
632: resp = &p->addrblock;
633: q = mkexpr(OPSTAR, resp->memoffset, ICON(ts));
634: if (ONEOF(resp->vstg, M(STGCOMMON)|M(STGEQUIV))
635: && resp->uname_tag == UNAM_NAME)
636: q = mkexpr(OPPLUS, q,
637: mkintcon(resp->user.name->voffset));
638: resp->memoffset = q;
639: }
640: return (Addrp) p;
641:
642: case TEXPR:
643: if( ISCOMPLEX(p->exprblock.vtype) )
644: break;
645: resp = mktmp(TYDREAL, ENULL);
646: putout (putassign( cpexpr((expptr)resp), p));
647: return(resp);
648:
649: default:
650: badtag("putcx1", p->tag);
651: }
652:
653: opcode = p->exprblock.opcode;
654: if(opcode==OPCALL || opcode==OPCCALL)
655: {
656: Addrp t;
657: p = putcall(p, &t);
658: putout(p);
659: return t;
660: }
661: else if(opcode == OPASSIGN)
662: {
663: return putcxeq (p);
664: }
665:
666: /* BUG (inefficient) Generates too many temporary variables */
667:
668: resp = mktmp(p->exprblock.vtype, ENULL);
669: if(lp = putcx1(p->exprblock.leftp) )
670: ltype = lp->vtype;
671: if(rp = putcx1(p->exprblock.rightp) )
672: rtype = rp->vtype;
673:
674: switch(opcode)
675: {
676: case OPCOMMA:
677: frexpr((expptr)resp);
678: resp = rp;
679: rp = NULL;
680: break;
681:
682: case OPNEG:
683: case OPNEG1:
684: putout (PAIR (
685: putassign( (expptr)realpart(resp),
686: mkexpr(OPNEG, (expptr)realpart(lp), ENULL)),
687: putassign( imagpart(resp),
688: mkexpr(OPNEG, imagpart(lp), ENULL))));
689: break;
690:
691: case OPPLUS:
692: case OPMINUS: { expptr r;
693: r = putassign( (expptr)realpart(resp),
694: mkexpr(opcode, (expptr)realpart(lp), (expptr)realpart(rp) ));
695: if(rtype < TYCOMPLEX)
696: q = putassign( imagpart(resp), imagpart(lp) );
697: else if(ltype < TYCOMPLEX)
698: {
699: if(opcode == OPPLUS)
700: q = putassign( imagpart(resp), imagpart(rp) );
701: else
702: q = putassign( imagpart(resp),
703: mkexpr(OPNEG, imagpart(rp), ENULL) );
704: }
705: else
706: q = putassign( imagpart(resp),
707: mkexpr(opcode, imagpart(lp), imagpart(rp) ));
708: r = PAIR (r, q);
709: putout (r);
710: break;
711: } /* case OPPLUS, OPMINUS: */
712: case OPSTAR:
713: if(ltype < TYCOMPLEX)
714: {
715: if( ISINT(ltype) )
716: lp = intdouble(lp);
717: putout (PAIR (
718: putassign( (expptr)realpart(resp),
719: mkexpr(OPSTAR, cpexpr((expptr)lp),
720: (expptr)realpart(rp))),
721: putassign( imagpart(resp),
722: mkexpr(OPSTAR, cpexpr((expptr)lp), imagpart(rp)))));
723: }
724: else if(rtype < TYCOMPLEX)
725: {
726: if( ISINT(rtype) )
727: rp = intdouble(rp);
728: putout (PAIR (
729: putassign( (expptr)realpart(resp),
730: mkexpr(OPSTAR, cpexpr((expptr)rp),
731: (expptr)realpart(lp))),
732: putassign( imagpart(resp),
733: mkexpr(OPSTAR, cpexpr((expptr)rp), imagpart(lp)))));
734: }
735: else {
736: putout (PAIR (
737: putassign( (expptr)realpart(resp), mkexpr(OPMINUS,
738: mkexpr(OPSTAR, (expptr)realpart(lp),
739: (expptr)realpart(rp)),
740: mkexpr(OPSTAR, imagpart(lp), imagpart(rp)))),
741: putassign( imagpart(resp), mkexpr(OPPLUS,
742: mkexpr(OPSTAR, (expptr)realpart(lp), imagpart(rp)),
743: mkexpr(OPSTAR, imagpart(lp),
744: (expptr)realpart(rp))))));
745: }
746: break;
747:
748: case OPSLASH:
749: /* fixexpr has already replaced all divisions
750: * by a complex by a function call
751: */
752: if( ISINT(rtype) )
753: rp = intdouble(rp);
754: putout (PAIR (
755: putassign( (expptr)realpart(resp),
756: mkexpr(OPSLASH, (expptr)realpart(lp), cpexpr((expptr)rp))),
757: putassign( imagpart(resp),
758: mkexpr(OPSLASH, imagpart(lp), cpexpr((expptr)rp)))));
759: break;
760:
761: case OPCONV:
762: if( ISCOMPLEX(lp->vtype) )
763: q = imagpart(lp);
764: else if(rp != NULL)
765: q = (expptr) realpart(rp);
766: else
767: q = mkrealcon(TYDREAL, "0");
768: putout (PAIR (
769: putassign( (expptr)realpart(resp), (expptr)realpart(lp)),
770: putassign( imagpart(resp), q)));
771: break;
772:
773: default:
774: badop("putcx1", opcode);
775: }
776:
777: frexpr((expptr)lp);
778: frexpr((expptr)rp);
779: free( (charptr) p );
780: return(resp);
781: }
782:
783:
784:
785:
786: /* Only .EQ. and .NE. may be performed on COMPLEX data, other relations
787: are not defined */
788:
789: LOCAL expptr putcxcmp(p)
790: register expptr p;
791: {
792: int opcode;
793: register Addrp lp, rp;
794: expptr q;
795:
796: if(p->tag != TEXPR)
797: badtag("putcxcmp", p->tag);
798:
799: opcode = p->exprblock.opcode;
800: lp = putcx1(p->exprblock.leftp);
801: rp = putcx1(p->exprblock.rightp);
802:
803: q = mkexpr( opcode==OPEQ ? OPAND : OPOR ,
804: mkexpr(opcode, (expptr)realpart(lp), (expptr)realpart(rp)),
805: mkexpr(opcode, imagpart(lp), imagpart(rp)) );
806:
807: free( (charptr) lp);
808: free( (charptr) rp);
809: free( (charptr) p );
810: return putx( fixexpr((Exprp)q) );
811: }
812:
813: /* putch1 -- Forces constants into the literal pool, among other things */
814:
815: LOCAL Addrp putch1(p)
816: register expptr p;
817: {
818: Addrp t;
819: expptr e;
820:
821: switch(p->tag)
822: {
823: case TCONST:
824: return( putconst((Constp)p) );
825:
826: case TADDR:
827: return( (Addrp) p );
828:
829: case TEXPR:
830: switch(p->exprblock.opcode)
831: {
832: expptr q;
833:
834: case OPCALL:
835: case OPCCALL:
836:
837: p = putcall(p, &t);
838: putout (p);
839: break;
840:
841: case OPCONCAT:
842: t = mktmp(TYCHAR, ICON(lencat(p)));
843: q = (expptr) cpexpr(p->headblock.vleng);
844: p = putcat( cpexpr((expptr)t), p );
845: /* put the correct length on the block */
846: frexpr(t->vleng);
847: t->vleng = q;
848: putout (p);
849: break;
850:
851: case OPCONV:
852: if(!ISICON(p->exprblock.vleng)
853: || p->exprblock.vleng->constblock.Const.ci!=1
854: || ! INT(p->exprblock.leftp->headblock.vtype) )
855: Fatal("putch1: bad character conversion");
856: t = mktmp(TYCHAR, ICON(1));
857: e = mkexpr(OPCONV, (expptr)t, ENULL);
858: e->headblock.vtype = TYCHAR;
859: p = putop( mkexpr(OPASSIGN, cpexpr(e), p));
860: putout (p);
861: break;
862: default:
863: badop("putch1", p->exprblock.opcode);
864: }
865: return(t);
866:
867: default:
868: badtag("putch1", p->tag);
869: }
870: /* NOT REACHED */ return 0;
871: }
872:
873:
874: /* putchop -- Write out a character actual parameter; that is, this is
875: part of a procedure invocation */
876:
877: Addrp putchop(p)
878: expptr p;
879: {
880: p = putaddr((expptr)putch1(p));
881: return (Addrp)p;
882: }
883:
884:
885:
886:
887: LOCAL expptr putcheq(p)
888: register expptr p;
889: {
890: expptr lp, rp;
891: int nbad;
892:
893: if(p->tag != TEXPR)
894: badtag("putcheq", p->tag);
895:
896: lp = p->exprblock.leftp;
897: rp = p->exprblock.rightp;
898: frexpr(p->exprblock.vleng);
899: free( (charptr) p );
900:
901: /* If s = t // u, don't bother copying the result, write it directly into
902: this buffer */
903:
904: nbad = badchleng(lp) + badchleng(rp);
905: if( rp->tag==TEXPR && rp->exprblock.opcode==OPCONCAT )
906: p = putcat(lp, rp);
907: else if( !nbad
908: && ISONE(lp->headblock.vleng)
909: && ISONE(rp->headblock.vleng) ) {
910: lp = mkexpr(OPCONV, lp, ENULL);
911: rp = mkexpr(OPCONV, rp, ENULL);
912: lp->headblock.vtype = rp->headblock.vtype = TYCHAR;
913: p = putop(mkexpr(OPASSIGN, lp, rp));
914: }
915: else
916: p = putx( call2(TYSUBR, "s_copy", lp, rp) );
917: return p;
918: }
919:
920:
921:
922:
923: LOCAL expptr putchcmp(p)
924: register expptr p;
925: {
926: expptr lp, rp;
927:
928: if(p->tag != TEXPR)
929: badtag("putchcmp", p->tag);
930:
931: lp = p->exprblock.leftp;
932: rp = p->exprblock.rightp;
933:
934: if(ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) ) {
935: lp = mkexpr(OPCONV, lp, ENULL);
936: rp = mkexpr(OPCONV, rp, ENULL);
937: lp->headblock.vtype = rp->headblock.vtype = TYCHAR;
938: }
939: else {
940: lp = call2(TYINT,"s_cmp", lp, rp);
941: rp = ICON(0);
942: }
943: p->exprblock.leftp = lp;
944: p->exprblock.rightp = rp;
945: p = putop(p);
946: return p;
947: }
948:
949:
950:
951:
952:
953: /* putcat -- Writes out a concatenation operation. Two temporary arrays
954: are allocated, putct1() is called to initialize them, and then a
955: call to runtime library routine s_cat() is inserted.
956:
957: This routine generates code which will perform an (nconc lhs rhs)
958: at runtime. The runtime funciton does not return a value, the routine
959: that calls this putcat must remember the name of lhs.
960: */
961:
962:
963: LOCAL expptr putcat(lhs0, rhs)
964: expptr lhs0;
965: register expptr rhs;
966: {
967: register Addrp lhs = (Addrp)lhs0;
968: int n, tyi;
969: Addrp length_var, string_var;
970: expptr p;
971: static char Writing_concatenation[] = "Writing concatenation";
972:
973: /* Create the temporary arrays */
974:
975: n = ncat(rhs);
976: length_var = mktmpn(n, tyioint, ENULL);
977: string_var = mktmpn(n, TYADDR, ENULL);
978: frtemp((Addrp)cpexpr((expptr)length_var));
979: frtemp((Addrp)cpexpr((expptr)string_var));
980:
981: /* Initialize the arrays */
982:
983: n = 0;
984: /* p1_comment scribbles on its argument, so we
985: * cannot safely pass a string literal here. */
986: p1_comment(Writing_concatenation);
987: putct1(rhs, length_var, string_var, &n);
988:
989: /* Create the invocation */
990:
991: tyi = tyint;
992: tyint = tyioint; /* for -I2 */
993: p = putx (call4 (TYSUBR, "s_cat",
994: (expptr)lhs,
995: (expptr)string_var,
996: (expptr)length_var,
997: (expptr)putconst((Constp)ICON(n))));
998: tyint = tyi;
999:
1000: return p;
1001: }
1002:
1003:
1004:
1005:
1006:
1007: LOCAL putct1(q, length_var, string_var, ip)
1008: register expptr q;
1009: register Addrp length_var, string_var;
1010: int *ip;
1011: {
1012: int i;
1013: Addrp length_copy, string_copy;
1014: expptr e;
1015: extern int szleng;
1016:
1017: if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT)
1018: {
1019: putct1(q->exprblock.leftp, length_var, string_var,
1020: ip);
1021: putct1(q->exprblock.rightp, length_var, string_var,
1022: ip);
1023: frexpr (q -> exprblock.vleng);
1024: free ((charptr) q);
1025: }
1026: else
1027: {
1028: i = (*ip)++;
1029: e = cpexpr(q->headblock.vleng);
1030: if (!e)
1031: return; /* error -- character*(*) */
1032: length_copy = (Addrp) cpexpr((expptr)length_var);
1033: length_copy->memoffset =
1034: mkexpr(OPPLUS,length_copy->memoffset, ICON(i*szleng));
1035: string_copy = (Addrp) cpexpr((expptr)string_var);
1036: string_copy->memoffset =
1037: mkexpr(OPPLUS, string_copy->memoffset,
1038: ICON(i*typesize[TYADDR]));
1039: putout (PAIR (putassign((expptr)length_copy, e),
1040: putassign((expptr)string_copy, addrof((expptr)putch1(q)))));
1041: }
1042: }
1043:
1044: /* putaddr -- seems to write out function invocation actual parameters */
1045:
1046: LOCAL expptr putaddr(p0)
1047: expptr p0;
1048: {
1049: register Addrp p;
1050: chainp cp;
1051:
1052: if (!(p = (Addrp)p0))
1053: return ENULL;
1054:
1055: if( p->tag==TERROR || (p->memoffset!=NULL && ISERROR(p->memoffset)) )
1056: {
1057: frexpr((expptr)p);
1058: return ENULL;
1059: }
1060: if (p->isarray && p->memoffset)
1061: if (p->uname_tag == UNAM_REF) {
1062: cp = p->memoffset->listblock.listp;
1063: for(; cp; cp = cp->nextp)
1064: cp->datap = (char *)fixtype((tagptr)cp->datap);
1065: }
1066: else
1067: p->memoffset = putx(p->memoffset);
1068: return (expptr) p;
1069: }
1070:
1071: LOCAL expptr
1072: addrfix(e) /* fudge character string length if it's a TADDR */
1073: expptr e;
1074: {
1075: return e->tag == TADDR ? mkexpr(OPIDENTITY, e, ENULL) : e;
1076: }
1077:
1078: LOCAL int
1079: typekludge(ccall, q, at, j)
1080: int ccall;
1081: register expptr q;
1082: Atype *at;
1083: int j; /* alternate type */
1084: {
1085: register int i, k;
1086: extern int iocalladdr;
1087: register Namep np;
1088:
1089: /* Return value classes:
1090: * < 100 ==> Fortran arg (pointer to type)
1091: * < 200 ==> C arg
1092: * < 300 ==> procedure arg
1093: * < 400 ==> external, no explicit type
1094: * < 500 ==> arg that may turn out to be
1095: * either a variable or a procedure
1096: */
1097:
1098: k = q->headblock.vtype;
1099: if (ccall) {
1100: if (k == TYREAL)
1101: k = TYDREAL; /* force double for library routines */
1102: return k + 100;
1103: }
1104: if (k == TYADDR)
1105: return iocalladdr;
1106: i = q->tag;
1107: if ((i == TEXPR && q->exprblock.opcode != OPCOMMA_ARG)
1108: || (i == TADDR && q->addrblock.charleng)
1109: || i == TCONST)
1110: k = TYFTNLEN + 100;
1111: else if (i == TADDR)
1112: switch(q->addrblock.vclass) {
1113: case CLPROC:
1114: if (q->addrblock.uname_tag != UNAM_NAME)
1115: k += 200;
1116: else if ((np = q->addrblock.user.name)->vprocclass
1117: != PTHISPROC) {
1118: if (k && !np->vimpltype)
1119: k += 200;
1120: else {
1121: if (j > 200 && infertypes && j < 300) {
1122: k = j;
1123: inferdcl(np, j-200);
1124: }
1125: else k = (np->vstg == STGEXT
1126: ? extsymtab[np->vardesc.varno].extype
1127: : 0) + 200;
1128: at->cp = mkchain((char *)np, at->cp);
1129: }
1130: }
1131: else if (k == TYSUBR)
1132: k += 200;
1133: break;
1134:
1135: case CLUNKNOWN:
1136: if (q->addrblock.vstg == STGARG
1137: && q->addrblock.uname_tag == UNAM_NAME) {
1138: k += 400;
1139: at->cp = mkchain((char *)q->addrblock.user.name,
1140: at->cp);
1141: }
1142: }
1143: else if (i == TNAME && q->nameblock.vstg == STGARG) {
1144: np = &q->nameblock;
1145: switch(np->vclass) {
1146: case CLPROC:
1147: if (!np->vimpltype)
1148: k += 200;
1149: else if (j <= 200 || !infertypes || j >= 300)
1150: k += 300;
1151: else {
1152: k = j;
1153: inferdcl(np, j-200);
1154: }
1155: goto add2chain;
1156:
1157: case CLUNKNOWN:
1158: /* argument may be a scalar variable or a function */
1159: if (np->vimpltype && j && infertypes
1160: && j < 300) {
1161: inferdcl(np, j % 100);
1162: k = j;
1163: }
1164: else
1165: k += 400;
1166:
1167: /* to handle procedure args only so far known to be
1168: * external, save a pointer to the symbol table entry...
1169: */
1170: add2chain:
1171: at->cp = mkchain((char *)np, at->cp);
1172: }
1173: }
1174: return k;
1175: }
1176:
1177: char *
1178: Argtype(k, buf)
1179: int k;
1180: char *buf;
1181: {
1182: if (k < 100) {
1183: sprintf(buf, "%s variable", ftn_types[k]);
1184: return buf;
1185: }
1186: if (k < 200) {
1187: k -= 100;
1188: return ftn_types[k];
1189: }
1190: if (k < 300) {
1191: k -= 200;
1192: if (k == TYSUBR)
1193: return ftn_types[TYSUBR];
1194: sprintf(buf, "%s function", ftn_types[k]);
1195: return buf;
1196: }
1197: if (k < 400)
1198: return "external argument";
1199: k -= 400;
1200: sprintf(buf, "%s argument", ftn_types[k]);
1201: return buf;
1202: }
1203:
1204: static void
1205: atype_squawk(at, msg)
1206: Argtypes *at;
1207: char *msg;
1208: {
1209: register Atype *a, *ae;
1210: warn(msg);
1211: for(a = at->atypes, ae = a + at->nargs; a < ae; a++)
1212: frchain(&a->cp);
1213: at->nargs = -1;
1214: if (at->changes & 2 && !at->defined)
1215: proc_protochanges++;
1216: }
1217:
1218: static char inconsist[] = "inconsistent calling sequences for ";
1219:
1220: void
1221: bad_atypes(at, fname, i, j, k, here, prev)
1222: Argtypes *at;
1223: char *fname, *here, *prev;
1224: int i, j, k;
1225: {
1226: char buf[208], buf1[32], buf2[32];
1227:
1228: sprintf(buf, "%s%.90s,\n\targ %d: %s%s%s %s.",
1229: inconsist, fname, i, here, Argtype(k, buf1),
1230: prev, Argtype(j, buf2));
1231: atype_squawk(at, buf);
1232: }
1233:
1234: int
1235: type_fixup(at,a,k)
1236: Argtypes *at;
1237: Atype *a;
1238: int k;
1239: {
1240: register struct Entrypoint *ep;
1241: if (!infertypes)
1242: return 0;
1243: for(ep = entries; ep; ep = ep->entnextp)
1244: if (at == ep->entryname->arginfo) {
1245: a->type = k % 100;
1246: return proc_argchanges = 1;
1247: }
1248: return 0;
1249: }
1250:
1251:
1252: void
1253: save_argtypes(arglist, at0, at1, ccall, fname, stg, nchargs, type, zap)
1254: chainp arglist;
1255: Argtypes **at0, **at1;
1256: int ccall, stg, nchargs, type, zap;
1257: char *fname;
1258: {
1259: Argtypes *at;
1260: chainp cp;
1261: int i, i0, j, k, nargs, nbad, *t, *te;
1262: Atype *atypes;
1263: expptr q;
1264: char buf[208], buf1[32], buf2[32];
1265: static int initargs[4] = {TYCOMPLEX, TYDCOMPLEX, TYCHAR, TYFTNLEN+100};
1266: static int *init_ap[TYSUBR+1] = {0,0,0,0,0,0,0,
1267: #ifdef TYQUAD
1268: 0,
1269: #endif
1270: initargs, initargs+1,0,0,0,initargs+2};
1271: extern int init_ac[TYSUBR+1];
1272:
1273: i0 = init_ac[type];
1274: t = init_ap[type];
1275: te = t + i0;
1276: if (at = *at0) {
1277: *at1 = at;
1278: nargs = at->nargs;
1279: if (nargs < 0 && type && at->changes & 2 && !at->defined)
1280: --proc_protochanges;
1281: if (at->dnargs >= 0 && zap != 2)
1282: type = 0;
1283: if (nargs < 0) { /* inconsistent usage seen */
1284: if (type)
1285: goto newlist;
1286: return;
1287: }
1288: atypes = at->atypes;
1289: i = nchargs;
1290: for(nbad = 0; t < te; atypes++) {
1291: if (++i > nargs) {
1292: toomany:
1293: i = nchargs + i0;
1294: for(cp = arglist; cp; cp = cp->nextp)
1295: i++;
1296: toofew:
1297: switch(zap) {
1298: case 2: zap = 6; break;
1299: case 1: if (at->defined & 4)
1300: return;
1301: }
1302: sprintf(buf,
1303: "%s%.90s:\n\there %d, previously %d args and string lengths.",
1304: inconsist, fname, i, nargs);
1305: atype_squawk(at, buf);
1306: if (type)
1307: goto newlist;
1308: return;
1309: }
1310: j = atypes->type;
1311: k = *t++;
1312: if (j != k)
1313: goto badtypes;
1314: }
1315: for(cp = arglist; cp; atypes++, cp = cp->nextp) {
1316: if (++i > nargs)
1317: goto toomany;
1318: j = atypes->type;
1319: if (!(q = (expptr)cp->datap))
1320: continue;
1321: k = typekludge(ccall, q, atypes, j);
1322: if (k >= 300 || k == j)
1323: continue;
1324: if (j >= 300) {
1325: if (k >= 200) {
1326: if (k == TYUNKNOWN + 200)
1327: continue;
1328: if (j % 100 != k - 200
1329: && k != TYSUBR + 200
1330: && j != TYUNKNOWN + 300
1331: && !type_fixup(at,atypes,k))
1332: goto badtypes;
1333: }
1334: else if (j % 100 % TYSUBR != k % TYSUBR
1335: && !type_fixup(at,atypes,k))
1336: goto badtypes;
1337: }
1338: else if (k < 200 || j < 200)
1339: if (j) {
1340: if (k == TYUNKNOWN
1341: && q->tag == TNAME
1342: && q->nameblock.vinfproc) {
1343: q->nameblock.vdcldone = 0;
1344: impldcl((Namep)q);
1345: }
1346: goto badtypes;
1347: }
1348: else ; /* fall through to update */
1349: else if (k == TYUNKNOWN+200)
1350: continue;
1351: else if (j != TYUNKNOWN+200)
1352: {
1353: badtypes:
1354: if (++nbad == 1)
1355: bad_atypes(at, fname, i, j, k, "here ",
1356: ", previously");
1357: else
1358: fprintf(stderr,
1359: "\targ %d: here %s, previously %s.\n",
1360: i, Argtype(k,buf1),
1361: Argtype(j,buf2));
1362: continue;
1363: }
1364: /* We've subsequently learned the right type,
1365: as in the call on zoo below...
1366:
1367: subroutine foo(x, zap)
1368: external zap
1369: call goo(zap)
1370: x = zap(3)
1371: call zoo(zap)
1372: end
1373: */
1374: if (!nbad) {
1375: atypes->type = k;
1376: at->changes |= 1;
1377: }
1378: }
1379: if (i < nargs)
1380: goto toofew;
1381: if (nbad) {
1382: if (type) {
1383: /* we're defining the procedure */
1384: t = init_ap[type];
1385: te = t + i0;
1386: proc_argchanges = 1;
1387: goto newlist;
1388: }
1389: return;
1390: }
1391: if (zap == 1 && (at->changes & 5) != 5)
1392: at->changes = 0;
1393: return;
1394: }
1395: newlist:
1396: i = i0 + nchargs;
1397: for(cp = arglist; cp; cp = cp->nextp)
1398: i++;
1399: k = sizeof(Argtypes) + (i-1)*sizeof(Atype);
1400: *at0 = *at1 = at = stg == STGEXT ? (Argtypes *)gmem(k,1)
1401: : (Argtypes *) mem(k,1);
1402: at->dnargs = at->nargs = i;
1403: at->defined = zap & 6;
1404: at->changes = type ? 0 : 4;
1405: atypes = at->atypes;
1406: for(; t < te; atypes++) {
1407: atypes->type = *t++;
1408: atypes->cp = 0;
1409: }
1410: for(cp = arglist; cp; atypes++, cp = cp->nextp) {
1411: atypes->cp = 0;
1412: atypes->type = (q = (expptr)cp->datap)
1413: ? typekludge(ccall, q, atypes, 0)
1414: : 0;
1415: }
1416: for(; --nchargs >= 0; atypes++) {
1417: atypes->type = TYFTNLEN + 100;
1418: atypes->cp = 0;
1419: }
1420: }
1421:
1422: void
1423: saveargtypes(p) /* for writing prototypes */
1424: register Exprp p;
1425: {
1426: Addrp a;
1427: Argtypes **at0, **at1;
1428: Namep np;
1429: chainp arglist;
1430: expptr rp;
1431: Extsym *e;
1432: char *fname;
1433:
1434: a = (Addrp)p->leftp;
1435: switch(a->vstg) {
1436: case STGEXT:
1437: switch(a->uname_tag) {
1438: case UNAM_EXTERN: /* e.g., sqrt() */
1439: e = extsymtab + a->memno;
1440: at0 = at1 = &e->arginfo;
1441: fname = e->fextname;
1442: break;
1443: case UNAM_NAME:
1444: np = a->user.name;
1445: at0 = &extsymtab[np->vardesc.varno].arginfo;
1446: at1 = &np->arginfo;
1447: fname = np->fvarname;
1448: break;
1449: default:
1450: goto bug;
1451: }
1452: break;
1453: case STGARG:
1454: if (a->uname_tag != UNAM_NAME)
1455: goto bug;
1456: np = a->user.name;
1457: at0 = at1 = &np->arginfo;
1458: fname = np->fvarname;
1459: break;
1460: default:
1461: bug:
1462: Fatal("Confusion in saveargtypes");
1463: }
1464: rp = p->rightp;
1465: arglist = rp && rp->tag == TLIST ? rp->listblock.listp : 0;
1466: save_argtypes(arglist, at0, at1, p->opcode == OPCCALL,
1467: fname, a->vstg, 0, 0, 0);
1468: }
1469:
1470: /* putcall - fix up the argument list, and write out the invocation. p
1471: is expected to be initialized and point to an OPCALL or OPCCALL
1472: expression. The return value is a pointer to a temporary holding the
1473: result of a COMPLEX or CHARACTER operation, or NULL. */
1474:
1475: LOCAL expptr putcall(p0, temp)
1476: expptr p0;
1477: Addrp *temp;
1478: {
1479: register Exprp p = (Exprp)p0;
1480: chainp arglist; /* Pointer to actual arguments, if any */
1481: chainp charsp; /* List of copies of the variables which
1482: hold the lengths of character
1483: parameters (other than procedure
1484: parameters) */
1485: chainp cp; /* Iterator over argument lists */
1486: register expptr q; /* Pointer to the current argument */
1487: Addrp fval; /* Function return value */
1488: int type; /* type of the call - presumably this was
1489: set elsewhere */
1490: int byvalue; /* True iff we don't want to massage the
1491: parameter list, since we're calling a C
1492: library routine */
1493: char *s;
1494: extern struct Listblock *mklist();
1495:
1496: type = p -> vtype;
1497: charsp = NULL;
1498: byvalue = (p->opcode == OPCCALL);
1499:
1500: /* Verify the actual parameters */
1501:
1502: if (p == (Exprp) NULL)
1503: err ("putcall: NULL call expression");
1504: else if (p -> tag != TEXPR)
1505: erri ("putcall: expected TEXPR, got '%d'", p -> tag);
1506:
1507: /* Find the argument list */
1508:
1509: if(p->rightp && p -> rightp -> tag == TLIST)
1510: arglist = p->rightp->listblock.listp;
1511: else
1512: arglist = NULL;
1513:
1514: /* Count the number of explicit arguments, including lengths of character
1515: variables */
1516:
1517: for(cp = arglist ; cp ; cp = cp->nextp)
1518: if(!byvalue) {
1519: q = (expptr) cp->datap;
1520: if( ISCONST(q) )
1521: {
1522:
1523: /* Even constants are passed by reference, so we need to put them in the
1524: literal table */
1525:
1526: q = (expptr) putconst((Constp)q);
1527: cp->datap = (char *) q;
1528: }
1529:
1530: /* Save the length expression of character variables (NOT character
1531: procedures) for the end of the argument list */
1532:
1533: if( ISCHAR(q) &&
1534: (q->headblock.vclass != CLPROC
1535: || q->headblock.vstg == STGARG
1536: && q->tag == TADDR
1537: && q->addrblock.uname_tag == UNAM_NAME
1538: && q->addrblock.user.name->vprocclass == PTHISPROC))
1539: {
1540: p0 = cpexpr(q->headblock.vleng);
1541: charsp = mkchain((char *)p0, charsp);
1542: if (q->headblock.vclass == CLUNKNOWN
1543: && q->headblock.vstg == STGARG)
1544: q->addrblock.user.name->vpassed = 1;
1545: else if (q->tag == TADDR
1546: && q->addrblock.uname_tag == UNAM_CONST)
1547: p0->constblock.Const.ci
1548: += q->addrblock.user.Const.ccp1.blanks;
1549: }
1550: }
1551: charsp = revchain(charsp);
1552:
1553: /* If the routine is a CHARACTER function ... */
1554:
1555: if(type == TYCHAR)
1556: {
1557: if( ISICON(p->vleng) )
1558: {
1559:
1560: /* Allocate a temporary to hold the return value of the function */
1561:
1562: fval = mktmp(TYCHAR, p->vleng);
1563: }
1564: else {
1565: err("adjustable character function");
1566: if (temp)
1567: *temp = 0;
1568: return 0;
1569: }
1570: }
1571:
1572: /* If the routine is a COMPLEX function ... */
1573:
1574: else if( ISCOMPLEX(type) )
1575: fval = mktmp(type, ENULL);
1576: else
1577: fval = NULL;
1578:
1579: /* Write the function name, without taking its address */
1580:
1581: p -> leftp = putx(fixtype(putaddr(p->leftp)));
1582:
1583: if(fval)
1584: {
1585: chainp prepend;
1586:
1587: /* Prepend a copy of the function return value buffer out as the first
1588: argument. */
1589:
1590: prepend = mkchain((char *)putx(putaddr(cpexpr((expptr)fval))), arglist);
1591:
1592: /* If it's a character function, also prepend the length of the result */
1593:
1594: if(type==TYCHAR)
1595: {
1596:
1597: prepend->nextp = mkchain((char *)putx(mkconv(TYLENG,
1598: p->vleng)), arglist);
1599: }
1600: if (!(q = p->rightp))
1601: p->rightp = q = (expptr)mklist(CHNULL);
1602: q->listblock.listp = prepend;
1603: }
1604:
1605: /* Scan through the fortran argument list */
1606:
1607: for(cp = arglist ; cp ; cp = cp->nextp)
1608: {
1609: q = (expptr) (cp->datap);
1610: if (q == ENULL)
1611: err ("putcall: NULL argument");
1612:
1613: /* call putaddr only when we've got a parameter for a C routine or a
1614: memory resident parameter */
1615:
1616: if (q -> tag == TCONST && !byvalue)
1617: q = (expptr) putconst ((Constp)q);
1618:
1619: if(q->tag==TADDR && (byvalue || q->addrblock.vstg!=STGREG) ) {
1620: if (q->addrblock.parenused
1621: && !byvalue && q->headblock.vtype != TYCHAR)
1622: goto make_copy;
1623: cp->datap = (char *)putaddr(q);
1624: }
1625: else if( ISCOMPLEX(q->headblock.vtype) )
1626: cp -> datap = (char *) putx (fixtype(putcxop(q)));
1627: else if (ISCHAR(q) )
1628: cp -> datap = (char *) putx (fixtype((expptr)putchop(q)));
1629: else if( ! ISERROR(q) )
1630: {
1631: if(byvalue
1632: || q->tag == TEXPR && q->exprblock.opcode == OPCHARCAST)
1633: cp -> datap = (char *) putx(q);
1634: else {
1635: expptr t, t1;
1636:
1637: /* If we've got a register parameter, or (maybe?) a constant, save it in a
1638: temporary first */
1639: make_copy:
1640: t = (expptr) mktmp(q->headblock.vtype, q->headblock.vleng);
1641:
1642: /* Assign to temporary variables before invoking the subroutine or
1643: function */
1644:
1645: t1 = putassign( cpexpr(t), q );
1646: if (doin_setbound)
1647: t = mkexpr(OPCOMMA_ARG, t1, t);
1648: else
1649: putout(t1);
1650: cp -> datap = (char *) t;
1651: } /* else */
1652: } /* if !ISERROR(q) */
1653: }
1654:
1655: /* Now adjust the lengths of the CHARACTER parameters */
1656:
1657: for(cp = charsp ; cp ; cp = cp->nextp)
1658: cp->datap = (char *)addrfix(putx(
1659: /* in case MAIN has a character*(*)... */
1660: (s = cp->datap) ? mkconv(TYLENG,(expptr)s)
1661: : ICON(0)));
1662:
1663: /* ... and add them to the end of the argument list */
1664:
1665: hookup (arglist, charsp);
1666:
1667: /* Return the name of the temporary used to hold the results, if any was
1668: necessary. */
1669:
1670: if (temp) *temp = fval;
1671: else frexpr ((expptr)fval);
1672:
1673: saveargtypes(p);
1674:
1675: return (expptr) p;
1676: }
1677:
1678:
1679:
1680: /* putmnmx -- Put min or max. p must point to an EXPR, not just a
1681: CONST */
1682:
1683: LOCAL expptr putmnmx(p)
1684: register expptr p;
1685: {
1686: int op, op2, type;
1687: expptr arg, qp, temp;
1688: chainp p0, p1;
1689: Addrp sp, tp;
1690: char comment_buf[80];
1691: char *what;
1692:
1693: if(p->tag != TEXPR)
1694: badtag("putmnmx", p->tag);
1695:
1696: type = p->exprblock.vtype;
1697: op = p->exprblock.opcode;
1698: op2 = op == OPMIN ? OPMIN2 : OPMAX2;
1699: p0 = p->exprblock.leftp->listblock.listp;
1700: free( (charptr) (p->exprblock.leftp) );
1701: free( (charptr) p );
1702:
1703: /* special case for two addressable operands */
1704:
1705: if (addressable((expptr)p0->datap)
1706: && (p1 = p0->nextp)
1707: && addressable((expptr)p1->datap)
1708: && !p1->nextp) {
1709: if (type == TYREAL && forcedouble)
1710: op2 = op == OPMIN ? OPDMIN : OPDMAX;
1711: p = mkexpr(op2, mkconv(type, cpexpr((expptr)p0->datap)),
1712: mkconv(type, cpexpr((expptr)p1->datap)));
1713: frchain(&p0);
1714: return p;
1715: }
1716:
1717: /* general case */
1718:
1719: sp = mktmp(type, ENULL);
1720:
1721: /* We only need a second temporary if the arg list has an unaddressable
1722: value */
1723:
1724: tp = (Addrp) NULL;
1725: qp = ENULL;
1726: for (p1 = p0 -> nextp; p1; p1 = p1 -> nextp)
1727: if (!addressable ((expptr) p1 -> datap)) {
1728: tp = mktmp(type, ENULL);
1729: qp = mkexpr(op2, cpexpr((expptr)sp), cpexpr((expptr)tp));
1730: qp = fixexpr((Exprp)qp);
1731: break;
1732: } /* if */
1733:
1734: /* Now output the appropriate number of assignments and comparisons. Min
1735: and max are implemented by the simple O(n) algorithm:
1736:
1737: min (a, b, c, d) ==>
1738: { <type> t1, t2;
1739:
1740: t1 = a;
1741: t2 = b; t1 = (t1 < t2) ? t1 : t2;
1742: t2 = c; t1 = (t1 < t2) ? t1 : t2;
1743: t2 = d; t1 = (t1 < t2) ? t1 : t2;
1744: }
1745: */
1746:
1747: if (!doin_setbound) {
1748: switch(op) {
1749: case OPLT:
1750: case OPMIN:
1751: case OPDMIN:
1752: case OPMIN2:
1753: what = "IN";
1754: break;
1755: default:
1756: what = "AX";
1757: }
1758: sprintf (comment_buf, "Computing M%s", what);
1759: p1_comment (comment_buf);
1760: }
1761:
1762: p1 = p0->nextp;
1763: temp = (expptr)p0->datap;
1764: if (addressable(temp) && addressable((expptr)p1->datap)) {
1765: p = mkconv(type, cpexpr(temp));
1766: arg = mkconv(type, cpexpr((expptr)p1->datap));
1767: temp = mkexpr(op2, p, arg);
1768: if (!ISCONST(temp))
1769: temp = fixexpr((Exprp)temp);
1770: p1 = p1->nextp;
1771: }
1772: p = putassign (cpexpr((expptr)sp), temp);
1773:
1774: for(; p1 ; p1 = p1->nextp)
1775: {
1776: if (addressable ((expptr) p1 -> datap)) {
1777: arg = mkconv(type, cpexpr((expptr)p1->datap));
1778: temp = mkexpr(op2, cpexpr((expptr)sp), arg);
1779: temp = fixexpr((Exprp)temp);
1780: } else {
1781: temp = (expptr) cpexpr (qp);
1782: p = mkexpr(OPCOMMA, p,
1783: putassign(cpexpr((expptr)tp), (expptr)p1->datap));
1784: } /* else */
1785:
1786: if(p1->nextp)
1787: p = mkexpr(OPCOMMA, p,
1788: putassign(cpexpr((expptr)sp), temp));
1789: else {
1790: if (type == TYREAL && forcedouble)
1791: temp->exprblock.opcode =
1792: op == OPMIN ? OPDMIN : OPDMAX;
1793: if (doin_setbound)
1794: p = mkexpr(OPCOMMA, p, temp);
1795: else {
1796: putout (p);
1797: p = putx(temp);
1798: }
1799: if (qp)
1800: frexpr (qp);
1801: } /* else */
1802: } /* for */
1803:
1804: frchain( &p0 );
1805: return p;
1806: }
1807:
1808:
1809: void
1810: putwhile(p)
1811: expptr p;
1812: {
1813: long where;
1814: int k, n;
1815:
1816: if (wh_next >= wh_last)
1817: {
1818: k = wh_last - wh_first;
1819: n = k + 100;
1820: wh_next = mem(n,0);
1821: wh_last = wh_first + n;
1822: if (k)
1823: memcpy(wh_next, wh_first, k);
1824: wh_first = wh_next;
1825: wh_next += k;
1826: wh_last = wh_first + n;
1827: }
1828: if( !ISLOGICAL((k = (p = fixtype(p))->headblock.vtype)))
1829: {
1830: if(k != TYERROR)
1831: err("non-logical expression in DO WHILE statement");
1832: }
1833: else {
1834: p1put(P1_WHILE1START);
1835: where = ftell(pass1_file);
1836: p = putx(p);
1837: *wh_next++ = ftell(pass1_file) > where;
1838: p1put(P1_WHILE2START);
1839: p1_expr(p);
1840: }
1841: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.