|
|
1.1 root 1: #include "defs"
2:
3: #ifdef SDB
4: # include <a.out.h>
5: char *stabline();
6: # ifndef N_SO
7: # include <stab.h>
8: # endif
9: char *stabdline();
10: #endif
11: char *memname();
12: #define ESNULL (struct Extsym *)0
13: #define EXNULL (union Expression *)0
14:
15: LOCAL dobss(), docomleng(), docommon(), doentry(),
16: epicode(), nextarg(), procode(), retval();
17:
18: /* start a new procedure */
19:
20: newproc()
21: {
22: if(parstate != OUTSIDE)
23: {
24: execerr("missing end statement", CNULL);
25: endproc();
26: }
27:
28: parstate = INSIDE;
29: procclass = CLMAIN; /* default */
30: }
31:
32:
33:
34: /* end of procedure. generate variables, epilogs, and prologs */
35:
36: endproc()
37: {
38: struct Labelblock *lp;
39: #if SDB
40: char elab[10];
41: int elnum;
42: #endif
43:
44: if(parstate < INDATA)
45: enddcl();
46: if(ctlstack >= ctls)
47: err("DO loop or BLOCK IF not closed");
48: for(lp = labeltab ; lp < labtabend ; ++lp)
49: if(lp->stateno!=0 && lp->labdefined==NO)
50: errstr("missing statement number %s", convic(lp->stateno) );
51:
52: epicode();
53: procode();
54: donmlist();
55: dobss();
56: prdbginfo();
57: #if SDB
58: if (sdbflag && procclass != CLBLOCK) {
59: sprintf(elab, "L%d", elnum = newlabel());
60: putlabel(elnum);
61: prstab(procclass == CLMAIN ? "MAIN_" : nounder(XL, procname),
62: N_EFUN, lineno, elab);
63: }
64: #endif
65: #if FAMILY == PCC
66: putbracket();
67: #endif
68: fixlwm();
69: procinit(); /* clean up for next procedure */
70: }
71:
72:
73:
74: /* End of declaration section of procedure. Allocate storage. */
75:
76: enddcl()
77: {
78: register struct Entrypoint *ep;
79:
80: #ifdef SDB
81: if( sdbflag )
82: {
83: # ifdef UCBVAXASM
84: p2pass( stabdline(N_SLINE, lineno) );
85: # else
86: char buff[10];
87: sprintf(buff,"LL%d", ++dbglabel);
88: p2pass( stabline(0, N_SLINE, lineno, buff) );
89: p2pi("LL%d:\n", dbglabel);
90: # endif
91: }
92: #endif
93: parstate = INEXEC;
94: docommon();
95: doequiv();
96: docomleng();
97: for(ep = entries ; ep ; ep = ep->entnextp)
98: doentry(ep);
99: }
100:
101: /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
102:
103: /* Main program or Block data */
104:
105: startproc(progname, class)
106: struct Extsym * progname;
107: int class;
108: {
109: register struct Entrypoint *p;
110: char *ftnname();
111:
112: p = ALLOC(Entrypoint);
113: if(class == CLMAIN)
114: puthead("MAIN__", CLMAIN);
115: else
116: puthead(CNULL, CLBLOCK);
117: if(class == CLMAIN)
118: newentry( mkname(5, "MAIN_") );
119: p->entryname = progname;
120: p->entrylabel = newlabel();
121: entries = p;
122:
123: procclass = class;
124: retlabel = newlabel();
125: fprintf(diagfile, " %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") );
126: if(progname)
127: fprintf(diagfile, " %s", nounder(XL, procname = progname->extname) );
128: fprintf(diagfile, ":\n");
129: #ifdef SDB
130: if(sdbflag && class==CLMAIN)
131: {
132: prstab("MAIN__", N_BFUN, lineno, ftnname(STGEXT, "MAIN__"));
133: #if NOTDEF
134: p2pass( stabline("MAIN_", N_FNAME, 0, 0) );
135: #endif
136: if(progname)
137: {
138: prstab(nounder(XL,progname->extname), N_ENTRY, lineno,
139: ftnname(STGEXT, progname->extname));
140: /* p2pass(stabline(nounder(XL,progname->extname),N_FNAME,0,0)); */
141: }
142: }
143: #endif
144: }
145:
146: /* subroutine or function statement */
147:
148: struct Extsym *newentry(v)
149: register Namep v;
150: {
151: register struct Extsym *p;
152:
153: p = mkext( varunder(VL, v->varname) );
154:
155: if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
156: {
157: if(p == 0)
158: dclerr("invalid entry name", v);
159: else dclerr("external name already used", v);
160: return(0);
161: }
162: v->vstg = STGAUTO;
163: v->vprocclass = PTHISPROC;
164: v->vclass = CLPROC;
165: p->extstg = STGEXT;
166: p->extinit = YES;
167: return(p);
168: }
169:
170:
171: entrypt(class, type, length, entry, args)
172: int class, type;
173: ftnint length;
174: struct Extsym *entry;
175: chainp args;
176: {
177: register Namep q;
178: register struct Entrypoint *p, *ep;
179: extern int types3[];
180:
181: if(class != CLENTRY)
182: puthead( varstr(XL, procname = entry->extname), class);
183: if(class == CLENTRY)
184: fprintf(diagfile, " entry ");
185: fprintf(diagfile, " %s:\n", nounder(XL, entry->extname));
186: q = mkname(VL, nounder(XL,entry->extname) );
187:
188: if( (type = lengtype(type, (int) length)) != TYCHAR)
189: length = 0;
190: if(class == CLPROC)
191: {
192: procclass = CLPROC;
193: proctype = type;
194: procleng = length;
195:
196: retlabel = newlabel();
197: if(type == TYSUBR)
198: ret0label = newlabel();
199: }
200:
201: p = ALLOC(Entrypoint);
202:
203: if(entries) /* put new block at end of entries list */
204: {
205: for(ep = entries; ep->entnextp; ep = ep->entnextp)
206: ;
207: ep->entnextp = p;
208: }
209: else
210: entries = p;
211:
212: p->entryname = entry;
213: p->arglist = args;
214: p->entrylabel = newlabel();
215: p->enamep = q;
216:
217: #ifdef SDB
218: if(sdbflag)
219: {
220: /* prstab(nounder(XL, entry->extname),
221: * (class==CLENTRY ? N_ENTRY : N_BFUN),
222: * lineno, ftnname(STGEXT, entry->extname));
223: */
224: prstab(entry->extname,
225: (class==CLENTRY ? N_ENTRY : N_BFUN),
226: lineno, ftnname(STGEXT, entry->extname));
227: if (class != CLENTRY)
228: prstab(entry->extname, N_GSYM, types3[type], CNULL);
229: if(class != CLENTRY) {
230: #if NOTDEF
231: /* p2pass( stabline( nounder(XL,entry->extname), N_FNAME, 0, 0) );
232: */
233: p2pass( stabline( entry->extname, N_FNAME, 0, 0) );
234: #endif
235: }
236: }
237: #endif
238:
239: if(class == CLENTRY)
240: {
241: class = CLPROC;
242: if(proctype == TYSUBR)
243: type = TYSUBR;
244: }
245:
246: q->vclass = class;
247: q->vprocclass = PTHISPROC;
248: settype(q, type, (int) length);
249: /* hold all initial entry points till end of declarations */
250: if(parstate >= INDATA)
251: doentry(p);
252: }
253:
254: /* generate epilogs */
255:
256: LOCAL epicode()
257: {
258: register int i;
259:
260: if(procclass==CLPROC)
261: {
262: if(proctype==TYSUBR)
263: {
264: putlabel(ret0label);
265: if(substars)
266: putforce(TYINT, ICON(0) );
267: putlabel(retlabel);
268: goret(TYSUBR);
269: }
270: else {
271: putlabel(retlabel);
272: if(multitype)
273: {
274: typeaddr = autovar(1, TYADDR, EXNULL);
275: putbranch( cpexpr(typeaddr) );
276: for(i = 0; i < NTYPES ; ++i)
277: if(rtvlabel[i] != 0)
278: {
279: putlabel(rtvlabel[i]);
280: retval(i);
281: }
282: }
283: else
284: retval(proctype);
285: }
286: }
287:
288: else if(procclass != CLBLOCK)
289: {
290: putlabel(retlabel);
291: goret(TYSUBR);
292: }
293: }
294:
295:
296: /* generate code to return value of type t */
297:
298: LOCAL retval(t)
299: register int t;
300: {
301: register Addrp p;
302:
303: switch(t)
304: {
305: case TYCHAR:
306: case TYCOMPLEX:
307: case TYDCOMPLEX:
308: break;
309:
310: case TYLOGICAL:
311: t = tylogical;
312: case TYADDR:
313: case TYSHORT:
314: case TYLONG:
315: p = (Addrp) cpexpr(retslot);
316: p->vtype = t;
317: putforce(t, p);
318: break;
319:
320: case TYREAL:
321: case TYDREAL:
322: p = (Addrp) cpexpr(retslot);
323: p->vtype = t;
324: putforce(t, p);
325: break;
326:
327: default:
328: badtype("retval", t);
329: }
330: goret(t);
331: }
332:
333:
334: /* Allocate extra argument array if needed. Generate prologs. */
335:
336: LOCAL procode()
337: {
338: register struct Entrypoint *p;
339: Addrp argvec;
340:
341: #if TARGET==GCOS
342: argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
343: #else
344: if(lastargslot>0 && nentry>1)
345: #if TARGET == VAX
346: argvec = autovar(1 + lastargslot/SZADDR, TYADDR, EXNULL);
347: #else
348: argvec = autovar(lastargslot/SZADDR, TYADDR, EXNULL);
349: #endif
350: else
351: argvec = NULL;
352: #endif
353:
354:
355: #if TARGET == PDP11
356: /* for the optimizer */
357: if(fudgelabel)
358: putlabel(fudgelabel);
359: #endif
360:
361: for(p = entries ; p ; p = p->entnextp)
362: prolog(p, argvec);
363:
364: #if FAMILY == PCC
365: putrbrack(procno);
366: #endif
367:
368: prendproc();
369: }
370:
371: /*
372: manipulate argument lists (allocate argument slot positions)
373: * keep track of return types and labels
374: */
375:
376: LOCAL doentry(ep)
377: struct Entrypoint *ep;
378: {
379: register int type;
380: register Namep np;
381: chainp p;
382: register Namep q;
383: Addrp mkarg();
384:
385: ++nentry;
386: if(procclass == CLMAIN)
387: {
388: #ifdef SDB
389: if (sdbflag)
390: prstab(CNULL, N_LBRAC, 0, "2");
391: #endif
392: putlabel(ep->entrylabel);
393: return;
394: }
395: else if(procclass == CLBLOCK) {
396: #ifdef SDB
397: if (sdbflag)
398: prstab(CNULL, N_LBRAC, 0, "2");
399: #endif
400: return;
401: }
402:
403: impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) );
404: type = np->vtype;
405: if(proctype == TYUNKNOWN)
406: if( (proctype = type) == TYCHAR)
407: procleng = (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1));
408:
409: if(proctype == TYCHAR)
410: {
411: if(type != TYCHAR)
412: err("noncharacter entry of character function");
413: else if( (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)) != procleng)
414: err("mismatched character entry lengths");
415: }
416: else if(type == TYCHAR)
417: err("character entry of noncharacter function");
418: else if(type != proctype)
419: multitype = YES;
420: if(rtvlabel[type] == 0)
421: rtvlabel[type] = newlabel();
422: ep->typelabel = rtvlabel[type];
423:
424: if(type == TYCHAR)
425: {
426: if(chslot < 0)
427: {
428: chslot = nextarg(TYADDR);
429: chlgslot = nextarg(TYLENG);
430: }
431: np->vstg = STGARG;
432: np->vardesc.varno = chslot;
433: if(procleng < 0)
434: np->vleng = (expptr) mkarg(TYLENG, chlgslot);
435: #ifdef SDB
436: if (sdbflag) {
437: prstab("ret_val", N_PSYM, 34, "4");
438: prstab("ret_val_len", N_PSYM, 5, "8");
439: }
440: #endif
441: }
442: else if( ISCOMPLEX(type) )
443: {
444: np->vstg = STGARG;
445: if(cxslot < 0)
446: cxslot = nextarg(TYADDR);
447: np->vardesc.varno = cxslot;
448: #ifdef SDB
449: if (sdbflag) {
450: prstab("ret_val", N_PSYM, 40, "4");
451: prstab(type == TYCOMPLEX ? "complex" : "dcomplex",
452: N_TYID, 0, CNULL);
453: }
454: #endif
455: }
456: else if(type != TYSUBR)
457: {
458: if(nentry == 1)
459: retslot = autovar(1, TYDREAL, EXNULL);
460: np->vstg = STGAUTO;
461: np->voffset = retslot->memoffset->constblock.const.ci;
462: }
463:
464: for(p = ep->arglist ; p ; p = p->nextp)
465: if(! (( q = (Namep) (p->datap) )->vdcldone) )
466: q->vardesc.varno = nextarg(TYADDR);
467:
468: for(p = ep->arglist ; p ; p = p->nextp)
469: if(! (( q = (Namep) (p->datap) )->vdcldone) )
470: {
471: impldcl(q);
472: q->vdcldone = YES;
473: #ifdef SDB
474: if(sdbflag)
475: prstabtype(ESNULL, q, N_PSYM,
476: convic(q->vardesc.varno + ARGOFFSET));
477: #endif
478: if(q->vtype == TYCHAR)
479: {
480: if(q->vleng == NULL) /* character*(*) */
481: q->vleng = (expptr)
482: mkarg(TYLENG, nextarg(TYLENG) );
483: else if(nentry == 1)
484: nextarg(TYLENG);
485: }
486: else if(q->vclass==CLPROC && nentry==1)
487: nextarg(TYLENG) ;
488: }
489: #ifdef SDB
490: if (sdbflag)
491: prstab(CNULL, N_LBRAC, 0, "2");
492: #endif
493:
494: putlabel(ep->entrylabel);
495: }
496:
497:
498:
499: LOCAL nextarg(type)
500: int type;
501: {
502: int k;
503: k = lastargslot;
504: lastargslot += typesize[type];
505: return(k);
506: }
507:
508: /* generate variable references */
509:
510: /* the following computes an expression that would address an equivalenced
511: * variable -- if only one could have expressions in stab addrs...
512: *
513: * LOCAL char *memplusoff(q)
514: * register Namep q;
515: * { static char buf[32];
516: * char *s;
517: * ftnint offset;
518: * s = memname(STGEQUIV, q->vardesc.varno);
519: * if (!(offset = q->voffset))
520: * return s;
521: * sprintf(buf, offset > 0 ? "%s+%ld" : "%s%ld", s, offset);
522: * return buf;
523: * }
524: */
525:
526: LOCAL dobss()
527: {
528: register struct Hashentry *p;
529: register Namep q;
530: register int i;
531: int align;
532: ftnint leng, iarrl, i1arrlen();
533: int qstg, qclass, qtype;
534: char buf[20];
535:
536: pruse(asmfile, USEBSS);
537:
538: for(p = hashtab ; p<lasthash ; ++p)
539: if(q = p->varp)
540: {
541: qstg = q->vstg;
542: qtype = q->vtype;
543: qclass = q->vclass;
544:
545: #ifdef SDB
546: if(sdbflag && qclass==CLVAR) switch(qstg)
547: {
548: case STGAUTO:
549: prstabtype(ESNULL, q, N_LSYM,
550: convic(-q->voffset));
551: break;
552:
553: case STGBSS:
554: prstabtype(ESNULL, q, N_LCSYM,
555: memname(qstg,q->vardesc.varno));
556: break;
557:
558: case STGINIT:
559: prstabtype(ESNULL, q, N_STSYM,
560: memname(qstg,q->vardesc.varno));
561: break;
562:
563: case STGEQUIV:
564: i = eqvclass[q->vardesc.varno].eqvinit
565: ? N_STSYM : N_LCSYM;
566: /* prstabtype(ESNULL, q, i, memplusoff(q)); */
567: if (!q->voffset)
568: prstabtype(ESNULL, q, i,
569: memname(qstg,q->vardesc.varno));
570: break;
571: }
572: #endif
573:
574: if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
575: (qclass==CLVAR && qstg==STGUNKNOWN) )
576: warn1("local variable %s never used", varstr(VL,q->varname) );
577: else if(qclass==CLVAR && qstg==STGBSS)
578: {
579: align = (qtype==TYCHAR ? ALILONG : typealign[qtype]);
580: if(bssleng % align != 0)
581: {
582: bssleng = roundup(bssleng, align);
583: preven(align);
584: }
585: prlocvar(memname(STGBSS,q->vardesc.varno), iarrl = iarrlen(q) );
586: bssleng += iarrl;
587: }
588: else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG)
589: mkext(varunder(VL, q->varname)) ->extstg = STGEXT;
590:
591: if(qclass==CLVAR && qstg!=STGARG)
592: {
593: if(q->vdim && !ISICON(q->vdim->nelt) )
594: dclerr("adjustable dimension on non-argument", q);
595: if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng)))
596: dclerr("adjustable leng on nonargument", q);
597: }
598: }
599: #ifdef SDB
600: if (sdbflag) {
601: struct Equivblock *p1;
602: struct Eqvchain *q1;
603: Namep np1;
604:
605: for(i = 0, p1 = eqvclass; i < nequiv ; ++i, ++p1) {
606: if (p1->eqvtop && (q1 = p1->equivs)) {
607:
608: /* put out null-named common block describing */
609: /* EQUIVALENCED variables with nonzero offsets */
610:
611: do if ((np1 = q1->eqvitem.eqvname)
612: && np1->voffset) {
613: prstab(CNULL, N_BCOMM, 0, CNULL);
614: prstab(CNULL, p1->eqvinit ? N_STSYM : N_LCSYM,
615: 0, memname(STGEQUIV,
616: np1->vardesc.varno));
617: do if ((np1 = q1->eqvitem.eqvname)
618: && np1->voffset)
619: prstabtype(ESNULL, np1, N_SSYM,
620: convic(np1->voffset));
621: while(q1 = q1->eqvnextp);
622: prstab(CNULL, N_ECOML, 0, CNULL);
623: break;
624: }
625: while(q1 = q1->eqvnextp);
626: }
627: freqchain(p1);
628: }
629: }
630: #endif
631:
632: for(i = 0 ; i < nequiv ; ++i)
633: if(eqvclass[i].eqvinit==NO && (leng = eqvclass[i].eqvleng)!=0 )
634: {
635: bssleng = roundup(bssleng, ALIDOUBLE);
636: preven(ALIDOUBLE);
637: prlocvar( memname(STGEQUIV, i), leng);
638: bssleng += leng;
639: }
640: #ifdef SDB
641: if (sdbflag)
642: prstab(CNULL, N_RBRAC, 0, "2");
643: #endif
644: }
645:
646:
647:
648: donmlist()
649: {
650: register struct Hashentry *p;
651: register Namep q;
652:
653: pruse(asmfile, USEINIT);
654:
655: for(p=hashtab; p<lasthash; ++p)
656: if( (q = p->varp) && q->vclass==CLNAMELIST)
657: namelist(q);
658: }
659:
660:
661: doext()
662: {
663: struct Extsym *p;
664:
665: for(p = extsymtab ; p<nextext ; ++p)
666: prext( varstr(XL, p->extname), p->maxleng, p->extinit);
667: }
668:
669:
670:
671:
672: ftnint iarrlen(q)
673: register Namep q;
674: {
675: ftnint leng;
676:
677: leng = typesize[q->vtype];
678: if(leng <= 0)
679: return(-1);
680: if(q->vdim)
681: if( ISICON(q->vdim->nelt) )
682: leng *= q->vdim->nelt->constblock.const.ci;
683: else return(-1);
684: if(q->vleng)
685: if( ISICON(q->vleng) )
686: leng *= q->vleng->constblock.const.ci;
687: else return(-1);
688: return(leng);
689: }
690:
691:
692: ftnint i1arrlen(q)
693: register Namep q;
694: {
695: ftnint leng;
696:
697: leng = 1;
698: if(q->vdim)
699: if( ISICON(q->vdim->nelt) )
700: leng = q->vdim->nelt->constblock.const.ci;
701: else return(-1);
702: if(q->vleng)
703: if( ISICON(q->vleng) )
704: leng *= q->vleng->constblock.const.ci;
705: else return(-1);
706: return(leng);
707: }
708:
709: /* This routine creates a static block representing the namelist.
710: An equivalent declaration of the structure produced is:
711: struct namelist
712: {
713: char namelistname[16];
714: struct namelistentry
715: {
716: char varname[16];
717: char *varaddr;
718: int type; # negative means -type= number of chars
719: struct dimensions *dimp; # null means scalar
720: } names[];
721: };
722:
723: struct dimensions
724: {
725: int numberofdimensions;
726: int numberofelements
727: int baseoffset;
728: int span[numberofdimensions];
729: };
730: where the namelistentry list terminates with a null varname
731: If dimp is not null, then the corner element of the array is at
732: varaddr. However, the element with subscripts (i1,...,in) is at
733: varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...)
734: */
735:
736: namelist(np)
737: Namep np;
738: {
739: register chainp q;
740: register Namep v;
741: register struct Dimblock *dp;
742: int type, dimno, dimoffset;
743: flag bad;
744:
745:
746: preven(ALILONG);
747: fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno));
748: putstr(asmfile, varstr(VL, np->varname), 16);
749: dimno = ++lastvarno;
750: dimoffset = 0;
751: bad = NO;
752:
753: for(q = np->varxptr.namelist ; q ; q = q->nextp)
754: {
755: vardcl( v = (Namep) (q->datap) );
756: type = v->vtype;
757: if( ONEOF(v->vstg, MSKSTATIC) )
758: {
759: preven(ALILONG);
760: putstr(asmfile, varstr(VL,v->varname), 16);
761: praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset);
762: prconi(asmfile, TYINT,
763: type==TYCHAR ?
764: -(v->vleng->constblock.const.ci) : (ftnint) type);
765: if(v->vdim)
766: {
767: praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset);
768: dimoffset += 3 + v->vdim->ndim;
769: }
770: else
771: praddr(asmfile, STGNULL,0,(ftnint) 0);
772: }
773: else
774: {
775: dclerr("may not appear in namelist", v);
776: bad = YES;
777: }
778: }
779:
780: if(bad)
781: return;
782:
783: putstr(asmfile, "", 16);
784:
785: if(dimoffset > 0)
786: {
787: fprintf(asmfile, LABELFMT, memname(STGINIT,dimno));
788: for(q = np->varxptr.namelist ; q ; q = q->nextp)
789: if(dp = q->datap->nameblock.vdim)
790: {
791: int i;
792: prconi(asmfile, TYINT, (ftnint) (dp->ndim) );
793: prconi(asmfile, TYINT,
794: (ftnint) (dp->nelt->constblock.const.ci) );
795: prconi(asmfile, TYINT,
796: (ftnint) (dp->baseoffset->constblock.const.ci));
797: for(i=0; i<dp->ndim ; ++i)
798: prconi(asmfile, TYINT,
799: dp->dims[i].dimsize->constblock.const.ci);
800: }
801: }
802:
803: }
804:
805: LOCAL docommon()
806: {
807: register struct Extsym *p;
808: register chainp q;
809: struct Dimblock *t;
810: expptr neltp;
811: register Namep v;
812: ftnint size;
813: int type;
814:
815: for(p = extsymtab ; p<nextext ; ++p)
816: if (p->extstg == STGCOMMON && (q = p->extp))
817: {
818: #ifdef SDB
819: if(sdbflag)
820: prstab(varstr(XL, p->extname), N_BCOMM, 0,
821: ftnname(STGCOMMON, p->extname));
822: #endif
823: for(; q ; q = q->nextp)
824: {
825: v = (Namep) (q->datap);
826: if(v->vdcldone == NO)
827: vardcl(v);
828: type = v->vtype;
829: if(p->extleng % typealign[type] != 0)
830: {
831: dclerr("common alignment", v);
832: p->extleng = roundup(p->extleng, typealign[type]);
833: }
834: v->voffset = p->extleng;
835: v->vardesc.varno = p - extsymtab;
836: if(type == TYCHAR)
837: size = v->vleng->constblock.const.ci;
838: else size = typesize[type];
839: if(t = v->vdim)
840: if( (neltp = t->nelt) && ISCONST(neltp) )
841: size *= neltp->constblock.const.ci;
842: else
843: dclerr("adjustable array in common", v);
844: #ifdef SDB
845: if(sdbflag)
846: prcomssym(v, p);
847: #endif
848: p->extleng += size;
849: }
850: frchain( &(p->extp) );
851: #ifdef SDB
852: if(sdbflag)
853: prstab(varstr(XL,p->extname), N_ECOMM, 0, ftnname(STGCOMMON, p->extname));
854: #endif
855: }
856: }
857:
858: #ifdef SDB
859: #define todata() if(first){p2pass(USEDATA);first=0;}
860:
861: commstruct() /* put common blocks into pi's GLOBAL menu */
862: /* also emit complex and dcomplex struct defs if needed */
863: {
864: register struct Extsym *p;
865: register struct Comvar *cv;
866: int first = 1;
867: char cstbuf[XL+10], lenbuf[16], *s;
868:
869: for(p = extsymtab ; p<nextext ; ++p)
870: if (p->extstg == STGCOMMON && (cv = p->cv))
871: {
872: todata();
873: s = varstr(XL, p->extname);
874: strcpy(cstbuf, s);
875: strcat(cstbuf, "COMMON_");
876: prstab(s, N_GSYM, 8, CNULL);
877: prstab(cstbuf, N_TYID, 0, CNULL);
878: prstab(cstbuf, N_BSTR, 8, CNULL);
879: do {
880: sprintf(lenbuf, "%ld", cv->offset);
881: prstab(cv->name, N_SSYM, cv->type, lenbuf);
882: if (cv->tyid)
883: prstab(cv->tyid, N_TYID, 0, CNULL);
884: if (cv->nelt)
885: p2pass(stabdline(N_DIM, cv->nelt));
886: } while(cv = cv->next);
887: sprintf(lenbuf, "%ld", p->maxleng);
888: prstab(cstbuf, N_ESTR, 8, lenbuf);
889: }
890: if (complex_seen) {
891: todata();
892: prstab("complex", N_BSTR, 8, CNULL);
893: prstab("real", N_SSYM, 6, CNULL);
894: prstab("imag", N_SSYM, 6, "4");
895: prstab("complex", N_ESTR, 8, "8");
896: }
897: if (dcomplex_seen) {
898: todata();
899: prstab("dcomplex", N_BSTR, 8, CNULL);
900: prstab("real", N_SSYM, 7, CNULL);
901: prstab("imag", N_SSYM, 7, "8");
902: prstab("dcomplex", N_ESTR, 8, "16");
903: }
904: if (!first)
905: p2pass(USETEXT);
906: }
907: #endif
908:
909:
910:
911: LOCAL docomleng()
912: {
913: register struct Extsym *p;
914:
915: for(p = extsymtab ; p < nextext ; ++p)
916: if(p->extstg == STGCOMMON)
917: {
918: if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
919: && !eqn(XL,"_BLNK__ ",p->extname) )
920: warn1("incompatible lengths for common block %s",
921: nounder(XL, p->extname) );
922: if(p->maxleng < p->extleng)
923: p->maxleng = p->extleng;
924: p->extleng = 0;
925: }
926: }
927:
928:
929:
930:
931: /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
932:
933: frtemp(p)
934: Addrp p;
935: {
936: /* restore clobbered character string lengths */
937: if(p->vtype==TYCHAR && p->varleng!=0)
938: {
939: frexpr(p->vleng);
940: p->vleng = ICON(p->varleng);
941: }
942:
943: /* put block on chain of temps to be reclaimed */
944: holdtemps = mkchain(p, holdtemps);
945: }
946:
947:
948:
949:
950: /* allocate an automatic variable slot */
951:
952: Addrp autovar(nelt, t, lengp)
953: register int nelt, t;
954: expptr lengp;
955: {
956: ftnint leng;
957: register Addrp q;
958:
959: if(t == TYCHAR)
960: if( ISICON(lengp) )
961: leng = lengp->constblock.const.ci;
962: else {
963: fatal("automatic variable of nonconstant length");
964: }
965: else
966: leng = typesize[t];
967: autoleng = roundup( autoleng, typealign[t]);
968:
969: q = ALLOC(Addrblock);
970: q->tag = TADDR;
971: q->vtype = t;
972: if(t == TYCHAR)
973: {
974: q->vleng = ICON(leng);
975: q->varleng = leng;
976: }
977: q->vstg = STGAUTO;
978: q->ntempelt = nelt;
979: #if TARGET==PDP11 || TARGET==VAX
980: /* stack grows downward */
981: autoleng += nelt*leng;
982: q->memoffset = ICON( - autoleng );
983: #else
984: q->memoffset = ICON( autoleng );
985: autoleng += nelt*leng;
986: #endif
987:
988: return(q);
989: }
990:
991:
992: Addrp mktmpn(nelt, type, lengp)
993: int nelt;
994: register int type;
995: expptr lengp;
996: {
997: ftnint leng;
998: chainp p, oldp;
999: register Addrp q;
1000:
1001: if(type==TYUNKNOWN || type==TYERROR)
1002: badtype("mktmpn", type);
1003:
1004: if(type==TYCHAR)
1005: if( ISICON(lengp) )
1006: leng = lengp->constblock.const.ci;
1007: else {
1008: err("adjustable length");
1009: return( (Addrp) errnode() );
1010: }
1011: /*
1012: * if an temporary of appropriate shape is on the templist,
1013: * remove it from the list and return it
1014: */
1015:
1016: for(oldp=CHNULL, p=templist ; p ; oldp=p, p=p->nextp)
1017: {
1018: q = (Addrp) (p->datap);
1019: if(q->vtype==type && q->ntempelt==nelt &&
1020: (type!=TYCHAR || q->vleng->constblock.const.ci==leng) )
1021: {
1022: if(oldp)
1023: oldp->nextp = p->nextp;
1024: else
1025: templist = p->nextp;
1026: free( (charptr) p);
1027: return(q);
1028: }
1029: }
1030: q = autovar(nelt, type, lengp);
1031: q->istemp = YES;
1032: return(q);
1033: }
1034:
1035:
1036:
1037:
1038: Addrp mktemp(type, lengp)
1039: int type;
1040: expptr lengp;
1041: {
1042: return( mktmpn(1,type,lengp) );
1043: }
1044:
1045: /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
1046:
1047: struct Extsym *comblock(len, s)
1048: register int len;
1049: register char *s;
1050: {
1051: struct Extsym *p;
1052:
1053: if(len == 0)
1054: {
1055: s = BLANKCOMMON;
1056: len = strlen(s);
1057: }
1058: p = mkext( varunder(len, s) );
1059: if(p->extstg == STGUNKNOWN)
1060: p->extstg = STGCOMMON;
1061: else if(p->extstg != STGCOMMON)
1062: {
1063: errstr("%s cannot be a common block name", s);
1064: return(0);
1065: }
1066:
1067: return( p );
1068: }
1069:
1070:
1071: incomm(c, v)
1072: struct Extsym *c;
1073: Namep v;
1074: {
1075: if(v->vstg != STGUNKNOWN)
1076: dclerr("incompatible common declaration", v);
1077: else
1078: {
1079: v->vstg = STGCOMMON;
1080: c->extp = hookup(c->extp, mkchain(v,CHNULL) );
1081: }
1082: }
1083:
1084:
1085:
1086:
1087: settype(v, type, length)
1088: register Namep v;
1089: register int type;
1090: register int length;
1091: {
1092: if(type == TYUNKNOWN)
1093: return;
1094:
1095: if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
1096: {
1097: v->vtype = TYSUBR;
1098: frexpr(v->vleng);
1099: }
1100: else if(type < 0) /* storage class set */
1101: {
1102: if(v->vstg == STGUNKNOWN)
1103: v->vstg = - type;
1104: else if(v->vstg != -type)
1105: dclerr("incompatible storage declarations", v);
1106: }
1107: else if(v->vtype == TYUNKNOWN)
1108: {
1109: if( (v->vtype = lengtype(type, length))==TYCHAR && length>=0)
1110: v->vleng = ICON(length);
1111: }
1112: else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.const.ci!=length) )
1113: dclerr("incompatible type declarations", v);
1114: }
1115:
1116:
1117:
1118:
1119:
1120: lengtype(type, length)
1121: register int type;
1122: register int length;
1123: {
1124: switch(type)
1125: {
1126: case TYREAL:
1127: if(length == 8)
1128: return(TYDREAL);
1129: if(length == 4)
1130: goto ret;
1131: break;
1132:
1133: case TYCOMPLEX:
1134: if(length == 16)
1135: return(TYDCOMPLEX);
1136: if(length == 8)
1137: goto ret;
1138: break;
1139:
1140: case TYSHORT:
1141: case TYDREAL:
1142: case TYDCOMPLEX:
1143: case TYCHAR:
1144: case TYUNKNOWN:
1145: case TYSUBR:
1146: case TYERROR:
1147: goto ret;
1148:
1149: case TYLOGICAL:
1150: if(length == typesize[TYLOGICAL])
1151: goto ret;
1152: break;
1153:
1154: case TYLONG:
1155: if(length == 0)
1156: return(tyint);
1157: if(length == 2)
1158: return(TYSHORT);
1159: if(length == 4)
1160: goto ret;
1161: break;
1162: default:
1163: badtype("lengtype", type);
1164: }
1165:
1166: if(length != 0)
1167: err("incompatible type-length combination");
1168:
1169: ret:
1170: return(type);
1171: }
1172:
1173:
1174:
1175:
1176:
1177: setintr(v)
1178: register Namep v;
1179: {
1180: register int k;
1181:
1182: if(v->vstg == STGUNKNOWN)
1183: v->vstg = STGINTR;
1184: else if(v->vstg!=STGINTR)
1185: dclerr("incompatible use of intrinsic function", v);
1186: if(v->vclass==CLUNKNOWN)
1187: v->vclass = CLPROC;
1188: if(v->vprocclass == PUNKNOWN)
1189: v->vprocclass = PINTRINSIC;
1190: else if(v->vprocclass != PINTRINSIC)
1191: dclerr("invalid intrinsic declaration", v);
1192: if(k = intrfunct(v->varname))
1193: v->vardesc.varno = k;
1194: else
1195: dclerr("unknown intrinsic function", v);
1196: }
1197:
1198:
1199:
1200: setext(v)
1201: register Namep v;
1202: {
1203: if(v->vclass == CLUNKNOWN)
1204: v->vclass = CLPROC;
1205: else if(v->vclass != CLPROC)
1206: dclerr("invalid external declaration", v);
1207:
1208: if(v->vprocclass == PUNKNOWN)
1209: v->vprocclass = PEXTERNAL;
1210: else if(v->vprocclass != PEXTERNAL)
1211: dclerr("invalid external declaration", v);
1212: }
1213:
1214:
1215:
1216:
1217: /* create dimensions block for array variable */
1218:
1219: setbound(v, nd, dims)
1220: register Namep v;
1221: int nd;
1222: struct { expptr lb, ub; } dims[ ];
1223: {
1224: register expptr q, t;
1225: register struct Dimblock *p;
1226: int i;
1227:
1228: if(v->vclass == CLUNKNOWN)
1229: v->vclass = CLVAR;
1230: else if(v->vclass != CLVAR)
1231: {
1232: dclerr("only variables may be arrays", v);
1233: return;
1234: }
1235:
1236: v->vdim = p = (struct Dimblock *)
1237: ckalloc( sizeof(int) + (3+2*nd)*sizeof(expptr) );
1238: p->ndim = nd;
1239: p->nelt = ICON(1);
1240:
1241: for(i=0 ; i<nd ; ++i)
1242: {
1243: if( (q = dims[i].ub) == NULL)
1244: {
1245: if(i == nd-1)
1246: {
1247: frexpr(p->nelt);
1248: p->nelt = NULL;
1249: }
1250: else
1251: err("only last bound may be asterisk");
1252: p->dims[i].dimsize = ICON(1);;
1253: p->dims[i].dimexpr = NULL;
1254: }
1255: else
1256: {
1257: if(dims[i].lb)
1258: {
1259: q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
1260: q = mkexpr(OPPLUS, q, ICON(1) );
1261: }
1262: if( ISCONST(q) )
1263: {
1264: p->dims[i].dimsize = q;
1265: p->dims[i].dimexpr = (expptr) PNULL;
1266: }
1267: else {
1268: p->dims[i].dimsize = (expptr) autovar(1, tyint, EXNULL);
1269: p->dims[i].dimexpr = q;
1270: }
1271: if(p->nelt)
1272: p->nelt = mkexpr(OPSTAR, p->nelt,
1273: cpexpr(p->dims[i].dimsize) );
1274: }
1275: }
1276:
1277: q = dims[nd-1].lb;
1278: if(q == NULL)
1279: q = ICON(1);
1280:
1281: for(i = nd-2 ; i>=0 ; --i)
1282: {
1283: t = dims[i].lb;
1284: if(t == NULL)
1285: t = ICON(1);
1286: if(p->dims[i].dimsize)
1287: q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) );
1288: }
1289:
1290: if( ISCONST(q) )
1291: {
1292: p->baseoffset = q;
1293: p->basexpr = NULL;
1294: }
1295: else
1296: {
1297: p->baseoffset = (expptr) autovar(1, tyint, EXNULL);
1298: p->basexpr = q;
1299: }
1300: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.