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