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