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