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