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