|
|
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.