|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)proc.c 5.2 (Berkeley) 6/9/85"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * proc.c ! 13: * ! 14: * Routines for handling procedures, f77 compiler, pass 1. ! 15: * ! 16: * University of Utah CS Dept modification history: ! 17: * ! 18: * $Header: proc.c,v 3.11 85/06/04 03:45:29 donn Exp $ ! 19: * $Log: proc.c,v $ ! 20: * Revision 3.11 85/06/04 03:45:29 donn ! 21: * Changed retval() to recognize that a function declaration might have ! 22: * bombed out earlier, leaving an error node behind... ! 23: * ! 24: * Revision 3.10 85/03/08 23:13:06 donn ! 25: * Finally figured out why function calls and array elements are not legal ! 26: * dummy array dimension declarator elements. Hacked safedim() to stop 'em. ! 27: * ! 28: * Revision 3.9 85/02/02 00:26:10 donn ! 29: * Removed the call to entrystab() in enddcl() -- this was redundant (it was ! 30: * also done in startproc()) and confusing to dbx to boot. ! 31: * ! 32: * Revision 3.8 85/01/14 04:21:53 donn ! 33: * Added changes to implement Jerry's '-q' option. ! 34: * ! 35: * Revision 3.7 85/01/11 21:10:35 donn ! 36: * In conjunction with other changes to implement SAVE statements, function ! 37: * nameblocks were changed to make it appear that they are 'saved' too -- ! 38: * this arranges things so that function return values are forced out of ! 39: * register before a return. ! 40: * ! 41: * Revision 3.6 84/12/10 19:27:20 donn ! 42: * comblock() signals an illegal common block name by returning a null pointer, ! 43: * but incomm() wasn't able to handle it, leading to core dumps. I put the ! 44: * fix in incomm() to pick up null common blocks. ! 45: * ! 46: * Revision 3.5 84/11/21 20:33:31 donn ! 47: * It seems that I/O elements are treated as character strings so that their ! 48: * length can be passed to the I/O routines... Unfortunately the compiler ! 49: * assumes that no temporaries can be of type CHARACTER and casually tosses ! 50: * length and type info away when removing TEMP blocks. This has been fixed... ! 51: * ! 52: * Revision 3.4 84/11/05 22:19:30 donn ! 53: * Fixed a silly bug in the last fix. ! 54: * ! 55: * Revision 3.3 84/10/29 08:15:23 donn ! 56: * Added code to check the type and shape of subscript declarations, ! 57: * per Jerry Berkman's suggestion. ! 58: * ! 59: * Revision 3.2 84/10/29 05:52:07 donn ! 60: * Added change suggested by Jerry Berkman to report an error when an array ! 61: * is redimensioned. ! 62: * ! 63: * Revision 3.1 84/10/13 02:12:31 donn ! 64: * Merged Jerry Berkman's version into mine. ! 65: * ! 66: * Revision 2.1 84/07/19 12:04:09 donn ! 67: * Changed comment headers for UofU. ! 68: * ! 69: * Revision 1.6 84/07/19 11:32:15 donn ! 70: * Incorporated fix to setbound() to detect backward array subscript limits. ! 71: * The fix is by Bob Corbett, donated by Jerry Berkman. ! 72: * ! 73: * Revision 1.5 84/07/18 18:25:50 donn ! 74: * Fixed problem with doentry() where a placeholder for a return value ! 75: * was not allocated if the first entry didn't require one but a later ! 76: * entry did. ! 77: * ! 78: * Revision 1.4 84/05/24 20:52:09 donn ! 79: * Installed firewall #ifdef around the code that recycles stack temporaries, ! 80: * since it seems to be broken and lacks a good fix for the time being. ! 81: * ! 82: * Revision 1.3 84/04/16 09:50:46 donn ! 83: * Fixed mkargtemp() so that it only passes back a copy of a temporary, keeping ! 84: * the original for its own use. This fixes a set of bugs that are caused by ! 85: * elements in the argtemplist getting stomped on. ! 86: * ! 87: * Revision 1.2 84/02/28 21:12:58 donn ! 88: * Added Berkeley changes for subroutine call argument temporaries fix. ! 89: * ! 90: */ ! 91: ! 92: #include "defs.h" ! 93: ! 94: #ifdef SDB ! 95: # include <a.out.h> ! 96: # ifndef N_SO ! 97: # include <stab.h> ! 98: # endif ! 99: #endif ! 100: ! 101: extern flag namesflag; ! 102: ! 103: typedef ! 104: struct SizeList ! 105: { ! 106: struct SizeList *next; ! 107: ftnint size; ! 108: struct VarList *vars; ! 109: } ! 110: sizelist; ! 111: ! 112: ! 113: typedef ! 114: struct VarList ! 115: { ! 116: struct VarList *next; ! 117: Namep np; ! 118: struct Equivblock *ep; ! 119: } ! 120: varlist; ! 121: ! 122: ! 123: LOCAL sizelist *varsizes; ! 124: ! 125: ! 126: /* start a new procedure */ ! 127: ! 128: newproc() ! 129: { ! 130: if(parstate != OUTSIDE) ! 131: { ! 132: execerr("missing end statement", CNULL); ! 133: endproc(); ! 134: } ! 135: ! 136: parstate = INSIDE; ! 137: procclass = CLMAIN; /* default */ ! 138: } ! 139: ! 140: ! 141: ! 142: /* end of procedure. generate variables, epilogs, and prologs */ ! 143: ! 144: endproc() ! 145: { ! 146: struct Labelblock *lp; ! 147: ! 148: if(parstate < INDATA) ! 149: enddcl(); ! 150: if(ctlstack >= ctls) ! 151: err("DO loop or BLOCK IF not closed"); ! 152: for(lp = labeltab ; lp < labtabend ; ++lp) ! 153: if(lp->stateno!=0 && lp->labdefined==NO) ! 154: errstr("missing statement number %s", convic(lp->stateno) ); ! 155: ! 156: if (optimflag) ! 157: optimize(); ! 158: ! 159: outiodata(); ! 160: epicode(); ! 161: procode(); ! 162: donmlist(); ! 163: dobss(); ! 164: ! 165: #if FAMILY == PCC ! 166: putbracket(); ! 167: #endif ! 168: procinit(); /* clean up for next procedure */ ! 169: } ! 170: ! 171: ! 172: ! 173: /* End of declaration section of procedure. Allocate storage. */ ! 174: ! 175: enddcl() ! 176: { ! 177: register struct Entrypoint *ep; ! 178: ! 179: parstate = INEXEC; ! 180: docommon(); ! 181: doequiv(); ! 182: docomleng(); ! 183: for(ep = entries ; ep ; ep = ep->entnextp) { ! 184: doentry(ep); ! 185: } ! 186: } ! 187: ! 188: /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */ ! 189: ! 190: /* Main program or Block data */ ! 191: ! 192: startproc(prgname, class) ! 193: Namep prgname; ! 194: int class; ! 195: { ! 196: struct Extsym *progname; ! 197: register struct Entrypoint *p; ! 198: ! 199: if(prgname) ! 200: procname = prgname->varname; ! 201: if(namesflag == YES) { ! 202: fprintf(diagfile, " %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") ); ! 203: if(prgname) ! 204: fprintf(diagfile, " %s", varstr(XL, procname) ); ! 205: fprintf(diagfile, ":\n"); ! 206: } ! 207: ! 208: if( prgname ) ! 209: progname = newentry( prgname ); ! 210: else ! 211: progname = NULL; ! 212: ! 213: p = ALLOC(Entrypoint); ! 214: if(class == CLMAIN) ! 215: puthead("MAIN_", CLMAIN); ! 216: else ! 217: puthead(CNULL, CLBLOCK); ! 218: if(class == CLMAIN) ! 219: newentry( mkname(5, "MAIN") ); ! 220: p->entryname = progname; ! 221: p->entrylabel = newlabel(); ! 222: entries = p; ! 223: ! 224: procclass = class; ! 225: retlabel = newlabel(); ! 226: #ifdef SDB ! 227: if(sdbflag) { ! 228: entrystab(p,class); ! 229: } ! 230: #endif ! 231: } ! 232: ! 233: /* subroutine or function statement */ ! 234: ! 235: struct Extsym *newentry(v) ! 236: register Namep v; ! 237: { ! 238: register struct Extsym *p; ! 239: ! 240: p = mkext( varunder(VL, v->varname) ); ! 241: ! 242: if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) ) ! 243: { ! 244: if(p == 0) ! 245: dclerr("invalid entry name", v); ! 246: else dclerr("external name already used", v); ! 247: return(0); ! 248: } ! 249: v->vstg = STGAUTO; ! 250: v->vprocclass = PTHISPROC; ! 251: v->vclass = CLPROC; ! 252: p->extstg = STGEXT; ! 253: p->extinit = YES; ! 254: return(p); ! 255: } ! 256: ! 257: ! 258: entrypt(class, type, length, entname, args) ! 259: int class, type; ! 260: ftnint length; ! 261: Namep entname; ! 262: chainp args; ! 263: { ! 264: struct Extsym *entry; ! 265: register Namep q; ! 266: register struct Entrypoint *p, *ep; ! 267: ! 268: if(namesflag == YES) { ! 269: if(class == CLENTRY) ! 270: fprintf(diagfile, " entry "); ! 271: if(entname) ! 272: fprintf(diagfile, " %s", varstr(XL, entname->varname) ); ! 273: fprintf(diagfile, ":\n"); ! 274: } ! 275: ! 276: if( entname->vclass == CLPARAM ) { ! 277: errstr("entry name %s used in 'parameter' statement", ! 278: varstr(XL, entname->varname) ); ! 279: return; ! 280: } ! 281: if( ((type == TYSUBR) || (class == CLENTRY && proctype == TYSUBR)) ! 282: && (entname->vtype != TYUNKNOWN && entname->vtype != TYSUBR) ) { ! 283: errstr("subroutine entry %s previously declared", ! 284: varstr(XL, entname->varname) ); ! 285: return; ! 286: } ! 287: if( (entname->vstg != STGEXT && entname->vstg != STGUNKNOWN) ! 288: || (entname->vdim != NULL) ) { ! 289: errstr("subroutine or function entry %s previously declared", ! 290: varstr(XL, entname->varname) ); ! 291: return; ! 292: } ! 293: ! 294: if( (class == CLPROC || class == CLENTRY) && type != TYSUBR ) ! 295: /* arrange to save function return values */ ! 296: entname->vsave = YES; ! 297: ! 298: entry = newentry( entname ); ! 299: ! 300: if(class != CLENTRY) ! 301: puthead( varstr(XL, procname = entry->extname), class); ! 302: q = mkname(VL, nounder(XL,entry->extname) ); ! 303: ! 304: if( (type = lengtype(type, (int) length)) != TYCHAR) ! 305: length = 0; ! 306: if(class == CLPROC) ! 307: { ! 308: procclass = CLPROC; ! 309: proctype = type; ! 310: procleng = length; ! 311: ! 312: retlabel = newlabel(); ! 313: if(type == TYSUBR) ! 314: ret0label = newlabel(); ! 315: } ! 316: ! 317: p = ALLOC(Entrypoint); ! 318: if(entries) /* put new block at end of entries list */ ! 319: { ! 320: for(ep = entries; ep->entnextp; ep = ep->entnextp) ! 321: ; ! 322: ep->entnextp = p; ! 323: } ! 324: else ! 325: entries = p; ! 326: ! 327: p->entryname = entry; ! 328: p->arglist = args; ! 329: p->entrylabel = newlabel(); ! 330: p->enamep = q; ! 331: ! 332: if(class == CLENTRY) ! 333: { ! 334: class = CLPROC; ! 335: if(proctype == TYSUBR) ! 336: type = TYSUBR; ! 337: } ! 338: ! 339: q->vclass = class; ! 340: q->vprocclass = PTHISPROC; ! 341: settype(q, type, (int) length); ! 342: /* hold all initial entry points till end of declarations */ ! 343: if(parstate >= INDATA) { ! 344: doentry(p); ! 345: } ! 346: #ifdef SDB ! 347: if(sdbflag) ! 348: { /* may need to preserve CLENTRY here */ ! 349: entrystab(p,class); ! 350: } ! 351: #endif ! 352: } ! 353: ! 354: /* generate epilogs */ ! 355: ! 356: LOCAL epicode() ! 357: { ! 358: register int i; ! 359: ! 360: if(procclass==CLPROC) ! 361: { ! 362: if(proctype==TYSUBR) ! 363: { ! 364: putlabel(ret0label); ! 365: if(substars) ! 366: putforce(TYINT, ICON(0) ); ! 367: putlabel(retlabel); ! 368: goret(TYSUBR); ! 369: } ! 370: else { ! 371: putlabel(retlabel); ! 372: if(multitype) ! 373: { ! 374: typeaddr = autovar(1, TYADDR, PNULL); ! 375: putbranch( cpexpr(typeaddr) ); ! 376: for(i = 0; i < NTYPES ; ++i) ! 377: if(rtvlabel[i] != 0) ! 378: { ! 379: putlabel(rtvlabel[i]); ! 380: retval(i); ! 381: } ! 382: } ! 383: else ! 384: retval(proctype); ! 385: } ! 386: } ! 387: ! 388: else if(procclass != CLBLOCK) ! 389: { ! 390: putlabel(retlabel); ! 391: goret(TYSUBR); ! 392: } ! 393: } ! 394: ! 395: ! 396: /* generate code to return value of type t */ ! 397: ! 398: LOCAL retval(t) ! 399: register int t; ! 400: { ! 401: register Addrp p; ! 402: ! 403: switch(t) ! 404: { ! 405: case TYCHAR: ! 406: case TYCOMPLEX: ! 407: case TYDCOMPLEX: ! 408: break; ! 409: ! 410: case TYLOGICAL: ! 411: t = tylogical; ! 412: case TYADDR: ! 413: case TYSHORT: ! 414: case TYLONG: ! 415: p = (Addrp) cpexpr(retslot); ! 416: p->vtype = t; ! 417: putforce(t, p); ! 418: break; ! 419: ! 420: case TYREAL: ! 421: case TYDREAL: ! 422: p = (Addrp) cpexpr(retslot); ! 423: p->vtype = t; ! 424: putforce(t, p); ! 425: break; ! 426: ! 427: case TYERROR: ! 428: return; /* someone else already complained */ ! 429: ! 430: default: ! 431: badtype("retval", t); ! 432: } ! 433: goret(t); ! 434: } ! 435: ! 436: ! 437: /* Allocate extra argument array if needed. Generate prologs. */ ! 438: ! 439: LOCAL procode() ! 440: { ! 441: register struct Entrypoint *p; ! 442: Addrp argvec; ! 443: ! 444: #if TARGET==GCOS ! 445: argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL); ! 446: #else ! 447: if(lastargslot>0 && nentry>1) ! 448: #if TARGET == VAX || TARGET == TAHOE ! 449: argvec = autovar(1 + lastargslot/SZADDR, TYADDR, PNULL); ! 450: #else ! 451: argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL); ! 452: #endif ! 453: else ! 454: argvec = NULL; ! 455: #endif ! 456: ! 457: ! 458: #if TARGET == PDP11 ! 459: /* for the optimizer */ ! 460: if(fudgelabel) ! 461: putlabel(fudgelabel); ! 462: #endif ! 463: ! 464: for(p = entries ; p ; p = p->entnextp) ! 465: prolog(p, argvec); ! 466: ! 467: #if FAMILY == PCC ! 468: putrbrack(procno); ! 469: #endif ! 470: ! 471: prendproc(); ! 472: } ! 473: ! 474: ! 475: /* ! 476: manipulate argument lists (allocate argument slot positions) ! 477: * keep track of return types and labels ! 478: */ ! 479: ! 480: LOCAL doentry(ep) ! 481: struct Entrypoint *ep; ! 482: { ! 483: register int type; ! 484: register Namep np; ! 485: chainp p; ! 486: register Namep q; ! 487: Addrp mkarg(); ! 488: ! 489: ++nentry; ! 490: if(procclass == CLMAIN) ! 491: { ! 492: if (optimflag) ! 493: optbuff (SKLABEL, 0, ep->entrylabel, 0); ! 494: else ! 495: putlabel(ep->entrylabel); ! 496: return; ! 497: } ! 498: else if(procclass == CLBLOCK) ! 499: return; ! 500: ! 501: impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) ); ! 502: type = np->vtype; ! 503: if(proctype == TYUNKNOWN) ! 504: if( (proctype = type) == TYCHAR) ! 505: procleng = (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)); ! 506: ! 507: if(proctype == TYCHAR) ! 508: { ! 509: if(type != TYCHAR) ! 510: err("noncharacter entry of character function"); ! 511: else if( (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)) != procleng) ! 512: err("mismatched character entry lengths"); ! 513: } ! 514: else if(type == TYCHAR) ! 515: err("character entry of noncharacter function"); ! 516: else if(type != proctype) ! 517: multitype = YES; ! 518: if(rtvlabel[type] == 0) ! 519: rtvlabel[type] = newlabel(); ! 520: ep->typelabel = rtvlabel[type]; ! 521: ! 522: if(type == TYCHAR) ! 523: { ! 524: if(chslot < 0) ! 525: { ! 526: chslot = nextarg(TYADDR); ! 527: chlgslot = nextarg(TYLENG); ! 528: } ! 529: np->vstg = STGARG; ! 530: np->vardesc.varno = chslot; ! 531: if(procleng < 0) ! 532: np->vleng = (expptr) mkarg(TYLENG, chlgslot); ! 533: } ! 534: else if( ISCOMPLEX(type) ) ! 535: { ! 536: np->vstg = STGARG; ! 537: if(cxslot < 0) ! 538: cxslot = nextarg(TYADDR); ! 539: np->vardesc.varno = cxslot; ! 540: } ! 541: else if(type != TYSUBR) ! 542: { ! 543: if(retslot == NULL) ! 544: retslot = autovar(1, TYDREAL, PNULL); ! 545: np->vstg = STGAUTO; ! 546: np->voffset = retslot->memoffset->constblock.const.ci; ! 547: } ! 548: ! 549: for(p = ep->arglist ; p ; p = p->nextp) ! 550: if(! (( q = (Namep) (p->datap) )->vdcldone) ) ! 551: q->vardesc.varno = nextarg(TYADDR); ! 552: ! 553: for(p = ep->arglist ; p ; p = p->nextp) ! 554: if(! (( q = (Namep) (p->datap) )->vdcldone) ) ! 555: { ! 556: impldcl(q); ! 557: q->vdcldone = YES; ! 558: if(q->vtype == TYCHAR) ! 559: { ! 560: if(q->vleng == NULL) /* character*(*) */ ! 561: q->vleng = (expptr) ! 562: mkarg(TYLENG, nextarg(TYLENG) ); ! 563: else if(nentry == 1) ! 564: nextarg(TYLENG); ! 565: } ! 566: else if(q->vclass==CLPROC && nentry==1) ! 567: nextarg(TYLENG) ; ! 568: #ifdef SDB ! 569: if(sdbflag) { ! 570: namestab(q); ! 571: } ! 572: #endif ! 573: } ! 574: ! 575: if (optimflag) ! 576: optbuff (SKLABEL, 0, ep->entrylabel, 0); ! 577: else ! 578: putlabel(ep->entrylabel); ! 579: } ! 580: ! 581: ! 582: ! 583: LOCAL nextarg(type) ! 584: int type; ! 585: { ! 586: int k; ! 587: k = lastargslot; ! 588: lastargslot += typesize[type]; ! 589: return(k); ! 590: } ! 591: ! 592: /* generate variable references */ ! 593: ! 594: LOCAL dobss() ! 595: { ! 596: register struct Hashentry *p; ! 597: register Namep q; ! 598: register int i; ! 599: int align; ! 600: ftnint leng, iarrl; ! 601: char *memname(); ! 602: int qstg, qclass, qtype; ! 603: ! 604: pruse(asmfile, USEBSS); ! 605: varsizes = NULL; ! 606: ! 607: for(p = hashtab ; p<lasthash ; ++p) ! 608: if(q = p->varp) ! 609: { ! 610: qstg = q->vstg; ! 611: qtype = q->vtype; ! 612: qclass = q->vclass; ! 613: ! 614: if( (qclass==CLUNKNOWN && qstg!=STGARG) || ! 615: (qclass==CLVAR && qstg==STGUNKNOWN) ) ! 616: warn1("local variable %s never used", varstr(VL,q->varname) ); ! 617: else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG) ! 618: mkext(varunder(VL, q->varname)) ->extstg = STGEXT; ! 619: ! 620: if (qclass == CLVAR && qstg == STGBSS) ! 621: { ! 622: if (SMALLVAR(q->varsize)) ! 623: { ! 624: enlist(q->varsize, q, NULL); ! 625: q->inlcomm = NO; ! 626: } ! 627: else ! 628: { ! 629: if (q->init == NO) ! 630: { ! 631: preven(ALIDOUBLE); ! 632: prlocvar(memname(qstg, q->vardesc.varno), q->varsize); ! 633: q->inlcomm = YES; ! 634: } ! 635: else ! 636: prlocdata(memname(qstg, q->vardesc.varno), q->varsize, ! 637: q->vtype, q->initoffset, &(q->inlcomm)); ! 638: } ! 639: } ! 640: else if(qclass==CLVAR && qstg!=STGARG) ! 641: { ! 642: if(q->vdim && !ISICON(q->vdim->nelt) ) ! 643: dclerr("adjustable dimension on non-argument", q); ! 644: if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng))) ! 645: dclerr("adjustable leng on nonargument", q); ! 646: } ! 647: ! 648: chkdim(q); ! 649: } ! 650: ! 651: for (i = 0 ; i < nequiv ; ++i) ! 652: if ( (leng = eqvclass[i].eqvleng) != 0 ) ! 653: { ! 654: if (SMALLVAR(leng)) ! 655: enlist(leng, NULL, eqvclass + i); ! 656: else if (eqvclass[i].init == NO) ! 657: { ! 658: preven(ALIDOUBLE); ! 659: prlocvar(memname(STGEQUIV, i), leng); ! 660: eqvclass[i].inlcomm = YES; ! 661: } ! 662: else ! 663: prlocdata(memname(STGEQUIV, i), leng, TYDREAL, ! 664: eqvclass[i].initoffset, &(eqvclass[i].inlcomm)); ! 665: } ! 666: ! 667: outlocvars(); ! 668: #ifdef SDB ! 669: if(sdbflag) { ! 670: for(p = hashtab ; p<lasthash ; ++p) if(q = p->varp) { ! 671: qstg = q->vstg; ! 672: qclass = q->vclass; ! 673: if( ONEOF(qclass, M(CLVAR))) { ! 674: if (! ONEOF(qstg,M(STGCOMMON)|M(STGARG) ) ) namestab(q); ! 675: } ! 676: } ! 677: } ! 678: #endif ! 679: ! 680: close(vdatafile); ! 681: close(vchkfile); ! 682: unlink(vdatafname); ! 683: unlink(vchkfname); ! 684: vdatahwm = 0; ! 685: } ! 686: ! 687: ! 688: ! 689: donmlist() ! 690: { ! 691: register struct Hashentry *p; ! 692: register Namep q; ! 693: ! 694: pruse(asmfile, USEINIT); ! 695: ! 696: for(p=hashtab; p<lasthash; ++p) ! 697: if( (q = p->varp) && q->vclass==CLNAMELIST) ! 698: namelist(q); ! 699: } ! 700: ! 701: ! 702: doext() ! 703: { ! 704: struct Extsym *p; ! 705: ! 706: for(p = extsymtab ; p<nextext ; ++p) ! 707: prext(p); ! 708: } ! 709: ! 710: ! 711: ! 712: ! 713: ftnint iarrlen(q) ! 714: register Namep q; ! 715: { ! 716: ftnint leng; ! 717: ! 718: leng = typesize[q->vtype]; ! 719: if(leng <= 0) ! 720: return(-1); ! 721: if(q->vdim) ! 722: if( ISICON(q->vdim->nelt) ) ! 723: leng *= q->vdim->nelt->constblock.const.ci; ! 724: else return(-1); ! 725: if(q->vleng) ! 726: if( ISICON(q->vleng) ) ! 727: leng *= q->vleng->constblock.const.ci; ! 728: else return(-1); ! 729: return(leng); ! 730: } ! 731: ! 732: /* This routine creates a static block representing the namelist. ! 733: An equivalent declaration of the structure produced is: ! 734: struct namelist ! 735: { ! 736: char namelistname[16]; ! 737: struct namelistentry ! 738: { ! 739: char varname[16]; ! 740: char *varaddr; ! 741: int type; # negative means -type= number of chars ! 742: struct dimensions *dimp; # null means scalar ! 743: } names[]; ! 744: }; ! 745: ! 746: struct dimensions ! 747: { ! 748: int numberofdimensions; ! 749: int numberofelements ! 750: int baseoffset; ! 751: int span[numberofdimensions]; ! 752: }; ! 753: where the namelistentry list terminates with a null varname ! 754: If dimp is not null, then the corner element of the array is at ! 755: varaddr. However, the element with subscripts (i1,...,in) is at ! 756: varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...) ! 757: */ ! 758: ! 759: namelist(np) ! 760: Namep np; ! 761: { ! 762: register chainp q; ! 763: register Namep v; ! 764: register struct Dimblock *dp; ! 765: char *memname(); ! 766: int type, dimno, dimoffset; ! 767: flag bad; ! 768: ! 769: ! 770: preven(ALILONG); ! 771: fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno)); ! 772: putstr(asmfile, varstr(VL, np->varname), 16); ! 773: dimno = ++lastvarno; ! 774: dimoffset = 0; ! 775: bad = NO; ! 776: ! 777: for(q = np->varxptr.namelist ; q ; q = q->nextp) ! 778: { ! 779: vardcl( v = (Namep) (q->datap) ); ! 780: type = v->vtype; ! 781: if( ONEOF(v->vstg, MSKSTATIC) ) ! 782: { ! 783: preven(ALILONG); ! 784: putstr(asmfile, varstr(VL,v->varname), 16); ! 785: praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset); ! 786: prconi(asmfile, TYINT, ! 787: type==TYCHAR ? ! 788: -(v->vleng->constblock.const.ci) : (ftnint) type); ! 789: if(v->vdim) ! 790: { ! 791: praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset); ! 792: dimoffset += 3 + v->vdim->ndim; ! 793: } ! 794: else ! 795: praddr(asmfile, STGNULL,0,(ftnint) 0); ! 796: } ! 797: else ! 798: { ! 799: dclerr("may not appear in namelist", v); ! 800: bad = YES; ! 801: } ! 802: } ! 803: ! 804: if(bad) ! 805: return; ! 806: ! 807: putstr(asmfile, "", 16); ! 808: ! 809: if(dimoffset > 0) ! 810: { ! 811: fprintf(asmfile, LABELFMT, memname(STGINIT,dimno)); ! 812: for(q = np->varxptr.namelist ; q ; q = q->nextp) ! 813: if(dp = q->datap->nameblock.vdim) ! 814: { ! 815: int i; ! 816: prconi(asmfile, TYINT, (ftnint) (dp->ndim) ); ! 817: prconi(asmfile, TYINT, ! 818: (ftnint) (dp->nelt->constblock.const.ci) ); ! 819: prconi(asmfile, TYINT, ! 820: (ftnint) (dp->baseoffset->constblock.const.ci)); ! 821: for(i=0; i<dp->ndim ; ++i) ! 822: prconi(asmfile, TYINT, ! 823: dp->dims[i].dimsize->constblock.const.ci); ! 824: } ! 825: } ! 826: ! 827: } ! 828: ! 829: LOCAL docommon() ! 830: { ! 831: register struct Extsym *p; ! 832: register chainp q; ! 833: struct Dimblock *t; ! 834: expptr neltp; ! 835: register Namep v; ! 836: ftnint size; ! 837: int type; ! 838: ! 839: for(p = extsymtab ; p<nextext ; ++p) ! 840: if(p->extstg==STGCOMMON) ! 841: { ! 842: #ifdef SDB ! 843: if(sdbflag) ! 844: prstab(varstr(XL,p->extname), N_BCOMM, 0, 0); ! 845: #endif ! 846: for(q = p->extp ; q ; q = q->nextp) ! 847: { ! 848: v = (Namep) (q->datap); ! 849: if(v->vdcldone == NO) ! 850: vardcl(v); ! 851: type = v->vtype; ! 852: if(p->extleng % typealign[type] != 0) ! 853: { ! 854: dclerr("common alignment", v); ! 855: p->extleng = roundup(p->extleng, typealign[type]); ! 856: } ! 857: v->voffset = p->extleng; ! 858: v->vardesc.varno = p - extsymtab; ! 859: if(type == TYCHAR) ! 860: size = v->vleng->constblock.const.ci; ! 861: else size = typesize[type]; ! 862: if(t = v->vdim) ! 863: if( (neltp = t->nelt) && ISCONST(neltp) ) ! 864: size *= neltp->constblock.const.ci; ! 865: else ! 866: dclerr("adjustable array in common", v); ! 867: p->extleng += size; ! 868: #ifdef SDB ! 869: if(sdbflag) ! 870: { ! 871: namestab(v); ! 872: } ! 873: #endif ! 874: } ! 875: ! 876: frchain( &(p->extp) ); ! 877: #ifdef SDB ! 878: if(sdbflag) ! 879: prstab(varstr(XL,p->extname), N_ECOMM, 0, 0); ! 880: #endif ! 881: } ! 882: } ! 883: ! 884: ! 885: ! 886: ! 887: ! 888: LOCAL docomleng() ! 889: { ! 890: register struct Extsym *p; ! 891: ! 892: for(p = extsymtab ; p < nextext ; ++p) ! 893: if(p->extstg == STGCOMMON) ! 894: { ! 895: if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng ! 896: && !eqn(XL,"_BLNK__ ",p->extname) ) ! 897: warn1("incompatible lengths for common block %s", ! 898: nounder(XL, p->extname) ); ! 899: if(p->maxleng < p->extleng) ! 900: p->maxleng = p->extleng; ! 901: p->extleng = 0; ! 902: } ! 903: } ! 904: ! 905: ! 906: ! 907: ! 908: /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */ ! 909: ! 910: /* frees a temporary block */ ! 911: ! 912: frtemp(p) ! 913: Tempp p; ! 914: { ! 915: Addrp t; ! 916: ! 917: if (optimflag) ! 918: { ! 919: if (p->tag != TTEMP) ! 920: badtag ("frtemp",p->tag); ! 921: t = p->memalloc; ! 922: } ! 923: else ! 924: t = (Addrp) p; ! 925: ! 926: /* restore clobbered character string lengths */ ! 927: if(t->vtype==TYCHAR && t->varleng!=0) ! 928: { ! 929: frexpr(t->vleng); ! 930: t->vleng = ICON(t->varleng); ! 931: } ! 932: ! 933: /* put block on chain of temps to be reclaimed */ ! 934: holdtemps = mkchain(t, holdtemps); ! 935: } ! 936: ! 937: ! 938: ! 939: /* allocate an automatic variable slot */ ! 940: ! 941: Addrp autovar(nelt, t, lengp) ! 942: register int nelt, t; ! 943: expptr lengp; ! 944: { ! 945: ftnint leng; ! 946: register Addrp q; ! 947: ! 948: if(lengp) ! 949: if( ISICON(lengp) ) ! 950: leng = lengp->constblock.const.ci; ! 951: else { ! 952: fatal("automatic variable of nonconstant length"); ! 953: } ! 954: else ! 955: leng = typesize[t]; ! 956: autoleng = roundup( autoleng, typealign[t]); ! 957: ! 958: q = ALLOC(Addrblock); ! 959: q->tag = TADDR; ! 960: q->vtype = t; ! 961: if(lengp) ! 962: { ! 963: q->vleng = ICON(leng); ! 964: q->varleng = leng; ! 965: } ! 966: q->vstg = STGAUTO; ! 967: q->memno = newlabel(); ! 968: q->ntempelt = nelt; ! 969: #if TARGET==PDP11 || TARGET==VAX || TARGET == TAHOE ! 970: /* stack grows downward */ ! 971: autoleng += nelt*leng; ! 972: q->memoffset = ICON( - autoleng ); ! 973: #else ! 974: q->memoffset = ICON( autoleng ); ! 975: autoleng += nelt*leng; ! 976: #endif ! 977: ! 978: return(q); ! 979: } ! 980: ! 981: ! 982: ! 983: /* ! 984: * create a temporary block (TTEMP) when optimizing, ! 985: * an ordinary TADDR block when not optimizing ! 986: */ ! 987: ! 988: Tempp mktmpn(nelt, type, lengp) ! 989: int nelt; ! 990: register int type; ! 991: expptr lengp; ! 992: { ! 993: ftnint leng; ! 994: chainp p, oldp; ! 995: register Tempp q; ! 996: Addrp altemp; ! 997: ! 998: if (! optimflag) ! 999: return ( (Tempp) mkaltmpn(nelt,type,lengp) ); ! 1000: if(type==TYUNKNOWN || type==TYERROR) ! 1001: badtype("mktmpn", type); ! 1002: ! 1003: if(type==TYCHAR) ! 1004: if( ISICON(lengp) ) ! 1005: leng = lengp->constblock.const.ci; ! 1006: else { ! 1007: err("adjustable length"); ! 1008: return( (Tempp) errnode() ); ! 1009: } ! 1010: else ! 1011: leng = typesize[type]; ! 1012: ! 1013: q = ALLOC(Tempblock); ! 1014: q->tag = TTEMP; ! 1015: q->vtype = type; ! 1016: if(type == TYCHAR) ! 1017: { ! 1018: q->vleng = ICON(leng); ! 1019: q->varleng = leng; ! 1020: } ! 1021: ! 1022: altemp = ALLOC(Addrblock); ! 1023: altemp->tag = TADDR; ! 1024: altemp->vstg = STGUNKNOWN; ! 1025: q->memalloc = altemp; ! 1026: ! 1027: q->ntempelt = nelt; ! 1028: q->istemp = YES; ! 1029: return(q); ! 1030: } ! 1031: ! 1032: ! 1033: ! 1034: Addrp mktemp(type, lengp) ! 1035: int type; ! 1036: expptr lengp; ! 1037: { ! 1038: return( (Addrp) mktmpn(1,type,lengp) ); ! 1039: } ! 1040: ! 1041: ! 1042: ! 1043: /* allocate a temporary location for the given temporary block; ! 1044: if already allocated, return its location */ ! 1045: ! 1046: Addrp altmpn(tp) ! 1047: Tempp tp; ! 1048: ! 1049: { ! 1050: Addrp t, q; ! 1051: ! 1052: if (tp->tag != TTEMP) ! 1053: badtag ("altmpn",tp->tag); ! 1054: ! 1055: t = tp->memalloc; ! 1056: if (t->vstg != STGUNKNOWN) ! 1057: { ! 1058: if (tp->vtype == TYCHAR) ! 1059: { ! 1060: /* ! 1061: * Unformatted I/O parameters are treated like character ! 1062: * strings (sigh) -- propagate type and length. ! 1063: */ ! 1064: t = (Addrp) cpexpr(t); ! 1065: t->vtype = tp->vtype; ! 1066: t->vleng = tp->vleng; ! 1067: t->varleng = tp->varleng; ! 1068: } ! 1069: return (t); ! 1070: } ! 1071: ! 1072: q = mkaltmpn (tp->ntempelt, tp->vtype, tp->vleng); ! 1073: cpn (sizeof(struct Addrblock), (char*)q, (char*)t); ! 1074: free ( (charptr) q); ! 1075: return(t); ! 1076: } ! 1077: ! 1078: ! 1079: ! 1080: /* create and allocate space immediately for a temporary */ ! 1081: ! 1082: Addrp mkaltemp(type,lengp) ! 1083: int type; ! 1084: expptr lengp; ! 1085: { ! 1086: return (mkaltmpn(1,type,lengp)); ! 1087: } ! 1088: ! 1089: ! 1090: ! 1091: Addrp mkaltmpn(nelt,type,lengp) ! 1092: int nelt; ! 1093: register int type; ! 1094: expptr lengp; ! 1095: { ! 1096: ftnint leng; ! 1097: chainp p, oldp; ! 1098: register Addrp q; ! 1099: ! 1100: if(type==TYUNKNOWN || type==TYERROR) ! 1101: badtype("mkaltmpn", type); ! 1102: ! 1103: if(type==TYCHAR) ! 1104: if( ISICON(lengp) ) ! 1105: leng = lengp->constblock.const.ci; ! 1106: else { ! 1107: err("adjustable length"); ! 1108: return( (Addrp) errnode() ); ! 1109: } ! 1110: ! 1111: /* ! 1112: * if a temporary of appropriate shape is on the templist, ! 1113: * remove it from the list and return it ! 1114: */ ! 1115: ! 1116: #ifdef notdef ! 1117: /* ! 1118: * This code is broken until SKFRTEMP slots can be processed in putopt() ! 1119: * instead of in optimize() -- all kinds of things in putpcc.c can ! 1120: * bomb because of this. Sigh. ! 1121: */ ! 1122: for(oldp=CHNULL, p=templist ; p ; oldp=p, p=p->nextp) ! 1123: { ! 1124: q = (Addrp) (p->datap); ! 1125: if(q->vtype==type && q->ntempelt==nelt && ! 1126: (type!=TYCHAR || q->vleng->constblock.const.ci==leng) ) ! 1127: { ! 1128: if(oldp) ! 1129: oldp->nextp = p->nextp; ! 1130: else ! 1131: templist = p->nextp; ! 1132: free( (charptr) p); ! 1133: ! 1134: if (debugflag[14]) ! 1135: fprintf(diagfile,"mkaltmpn reusing offset %d\n", ! 1136: q->memoffset->constblock.const.ci); ! 1137: return(q); ! 1138: } ! 1139: } ! 1140: #endif notdef ! 1141: q = autovar(nelt, type, lengp); ! 1142: q->istemp = YES; ! 1143: ! 1144: if (debugflag[14]) ! 1145: fprintf(diagfile,"mkaltmpn new offset %d\n", ! 1146: q->memoffset->constblock.const.ci); ! 1147: return(q); ! 1148: } ! 1149: ! 1150: ! 1151: ! 1152: /* The following routine is a patch which is only needed because the */ ! 1153: /* code for processing actual arguments for calls does not allocate */ ! 1154: /* the temps it needs before optimization takes place. A better */ ! 1155: /* solution is possible, but I do not have the time to implement it */ ! 1156: /* now. */ ! 1157: /* */ ! 1158: /* Robert P. Corbett */ ! 1159: ! 1160: Addrp ! 1161: mkargtemp(type, lengp) ! 1162: int type; ! 1163: expptr lengp; ! 1164: { ! 1165: ftnint leng; ! 1166: chainp oldp, p; ! 1167: Addrp q; ! 1168: ! 1169: if (type == TYUNKNOWN || type == TYERROR) ! 1170: badtype("mkargtemp", type); ! 1171: ! 1172: if (type == TYCHAR) ! 1173: { ! 1174: if (ISICON(lengp)) ! 1175: leng = lengp->constblock.const.ci; ! 1176: else ! 1177: { ! 1178: err("adjustable length"); ! 1179: return ((Addrp) errnode()); ! 1180: } ! 1181: } ! 1182: ! 1183: oldp = CHNULL; ! 1184: p = argtemplist; ! 1185: ! 1186: while (p) ! 1187: { ! 1188: q = (Addrp) (p->datap); ! 1189: if (q->vtype == type ! 1190: && (type != TYCHAR || q->vleng->constblock.const.ci == leng)) ! 1191: { ! 1192: if (oldp) ! 1193: oldp->nextp = p->nextp; ! 1194: else ! 1195: argtemplist = p->nextp; ! 1196: ! 1197: p->nextp = activearglist; ! 1198: activearglist = p; ! 1199: ! 1200: return ((Addrp) cpexpr(q)); ! 1201: } ! 1202: ! 1203: oldp = p; ! 1204: p = p->nextp; ! 1205: } ! 1206: ! 1207: q = autovar(1, type, lengp); ! 1208: activearglist = mkchain(q, activearglist); ! 1209: return ((Addrp) cpexpr(q)); ! 1210: } ! 1211: ! 1212: /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */ ! 1213: ! 1214: struct Extsym *comblock(len, s) ! 1215: register int len; ! 1216: register char *s; ! 1217: { ! 1218: struct Extsym *p; ! 1219: ! 1220: if(len == 0) ! 1221: { ! 1222: s = BLANKCOMMON; ! 1223: len = strlen(s); ! 1224: } ! 1225: p = mkext( varunder(len, s) ); ! 1226: if(p->extstg == STGUNKNOWN) ! 1227: p->extstg = STGCOMMON; ! 1228: else if(p->extstg != STGCOMMON) ! 1229: { ! 1230: errstr("%s cannot be a common block name", s); ! 1231: return(0); ! 1232: } ! 1233: ! 1234: return( p ); ! 1235: } ! 1236: ! 1237: ! 1238: incomm(c, v) ! 1239: struct Extsym *c; ! 1240: Namep v; ! 1241: { ! 1242: if(v->vstg != STGUNKNOWN) ! 1243: dclerr("incompatible common declaration", v); ! 1244: else ! 1245: { ! 1246: if(c == (struct Extsym *) 0) ! 1247: return; /* Illegal common block name upstream */ ! 1248: v->vstg = STGCOMMON; ! 1249: c->extp = hookup(c->extp, mkchain(v,CHNULL) ); ! 1250: } ! 1251: } ! 1252: ! 1253: ! 1254: ! 1255: ! 1256: settype(v, type, length) ! 1257: register Namep v; ! 1258: register int type; ! 1259: register int length; ! 1260: { ! 1261: if(type == TYUNKNOWN) ! 1262: return; ! 1263: ! 1264: if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG) ! 1265: { ! 1266: v->vtype = TYSUBR; ! 1267: frexpr(v->vleng); ! 1268: } ! 1269: else if(type < 0) /* storage class set */ ! 1270: { ! 1271: if(v->vstg == STGUNKNOWN) ! 1272: v->vstg = - type; ! 1273: else if(v->vstg != -type) ! 1274: dclerr("incompatible storage declarations", v); ! 1275: } ! 1276: else if(v->vtype == TYUNKNOWN) ! 1277: { ! 1278: if( (v->vtype = lengtype(type, length))==TYCHAR && length>=0) ! 1279: v->vleng = ICON(length); ! 1280: } ! 1281: else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.const.ci!=length) ) ! 1282: dclerr("incompatible type declarations", v); ! 1283: } ! 1284: ! 1285: ! 1286: ! 1287: ! 1288: ! 1289: lengtype(type, length) ! 1290: register int type; ! 1291: register int length; ! 1292: { ! 1293: switch(type) ! 1294: { ! 1295: case TYREAL: ! 1296: if(length == 8) ! 1297: return(TYDREAL); ! 1298: if(length == 4) ! 1299: goto ret; ! 1300: break; ! 1301: ! 1302: case TYCOMPLEX: ! 1303: if(length == 16) ! 1304: return(TYDCOMPLEX); ! 1305: if(length == 8) ! 1306: goto ret; ! 1307: break; ! 1308: ! 1309: case TYSHORT: ! 1310: case TYDREAL: ! 1311: case TYDCOMPLEX: ! 1312: case TYCHAR: ! 1313: case TYUNKNOWN: ! 1314: case TYSUBR: ! 1315: case TYERROR: ! 1316: goto ret; ! 1317: ! 1318: case TYLOGICAL: ! 1319: if(length == typesize[TYLOGICAL]) ! 1320: goto ret; ! 1321: break; ! 1322: ! 1323: case TYLONG: ! 1324: if(length == 0 ) ! 1325: return(tyint); ! 1326: if(length == 2) ! 1327: return(TYSHORT); ! 1328: if(length == 4 ) ! 1329: goto ret; ! 1330: break; ! 1331: default: ! 1332: badtype("lengtype", type); ! 1333: } ! 1334: ! 1335: if(length != 0) ! 1336: err("incompatible type-length combination"); ! 1337: ! 1338: ret: ! 1339: return(type); ! 1340: } ! 1341: ! 1342: ! 1343: ! 1344: ! 1345: ! 1346: setintr(v) ! 1347: register Namep v; ! 1348: { ! 1349: register int k; ! 1350: ! 1351: if(v->vstg == STGUNKNOWN) ! 1352: v->vstg = STGINTR; ! 1353: else if(v->vstg!=STGINTR) ! 1354: dclerr("incompatible use of intrinsic function", v); ! 1355: if(v->vclass==CLUNKNOWN) ! 1356: v->vclass = CLPROC; ! 1357: if(v->vprocclass == PUNKNOWN) ! 1358: v->vprocclass = PINTRINSIC; ! 1359: else if(v->vprocclass != PINTRINSIC) ! 1360: dclerr("invalid intrinsic declaration", v); ! 1361: if(k = intrfunct(v->varname)) ! 1362: v->vardesc.varno = k; ! 1363: else ! 1364: dclerr("unknown intrinsic function", v); ! 1365: } ! 1366: ! 1367: ! 1368: ! 1369: setext(v) ! 1370: register Namep v; ! 1371: { ! 1372: if(v->vclass == CLUNKNOWN) ! 1373: v->vclass = CLPROC; ! 1374: else if(v->vclass != CLPROC) ! 1375: dclerr("conflicting declarations", v); ! 1376: ! 1377: if(v->vprocclass == PUNKNOWN) ! 1378: v->vprocclass = PEXTERNAL; ! 1379: else if(v->vprocclass != PEXTERNAL) ! 1380: dclerr("conflicting declarations", v); ! 1381: } ! 1382: ! 1383: ! 1384: ! 1385: ! 1386: /* create dimensions block for array variable */ ! 1387: ! 1388: setbound(v, nd, dims) ! 1389: register Namep v; ! 1390: int nd; ! 1391: struct { expptr lb, ub; } dims[ ]; ! 1392: { ! 1393: register expptr q, t; ! 1394: register struct Dimblock *p; ! 1395: int i; ! 1396: ! 1397: if(v->vclass == CLUNKNOWN) ! 1398: v->vclass = CLVAR; ! 1399: else if(v->vclass != CLVAR) ! 1400: { ! 1401: dclerr("only variables may be arrays", v); ! 1402: return; ! 1403: } ! 1404: if(v->vdim) ! 1405: { ! 1406: dclerr("redimensioned array", v); ! 1407: return; ! 1408: } ! 1409: ! 1410: v->vdim = p = (struct Dimblock *) ! 1411: ckalloc( sizeof(int) + (3+6*nd)*sizeof(expptr) ); ! 1412: p->ndim = nd; ! 1413: p->nelt = ICON(1); ! 1414: ! 1415: for(i=0 ; i<nd ; ++i) ! 1416: { ! 1417: #ifdef SDB ! 1418: if(sdbflag) { ! 1419: /* Save the bounds trees built up by the grammar routines for use in stabs */ ! 1420: ! 1421: if(dims[i].lb == NULL) p->dims[i].lb=ICON(1); ! 1422: else p->dims[i].lb= (expptr) cpexpr(dims[i].lb); ! 1423: if(ISCONST(p->dims[i].lb)) p->dims[i].lbaddr = (expptr) PNULL; ! 1424: else p->dims[i].lbaddr = (expptr) autovar(1, tyint, PNULL); ! 1425: ! 1426: if(dims[i].ub == NULL) p->dims[i].ub=ICON(1); ! 1427: else p->dims[i].ub = (expptr) cpexpr(dims[i].ub); ! 1428: if(ISCONST(p->dims[i].ub)) p->dims[i].ubaddr = (expptr) PNULL; ! 1429: else p->dims[i].ubaddr = (expptr) autovar(1, tyint, PNULL); ! 1430: } ! 1431: #endif ! 1432: if( (q = dims[i].ub) == NULL) ! 1433: { ! 1434: if(i == nd-1) ! 1435: { ! 1436: frexpr(p->nelt); ! 1437: p->nelt = NULL; ! 1438: } ! 1439: else ! 1440: err("only last bound may be asterisk"); ! 1441: p->dims[i].dimsize = ICON(1);; ! 1442: p->dims[i].dimexpr = NULL; ! 1443: } ! 1444: else ! 1445: { ! 1446: if(dims[i].lb) ! 1447: { ! 1448: q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb)); ! 1449: q = mkexpr(OPPLUS, q, ICON(1) ); ! 1450: } ! 1451: if( ISCONST(q) ) ! 1452: { ! 1453: if (!ISINT(q->headblock.vtype)) { ! 1454: dclerr("dimension bounds must be integer expression", v); ! 1455: frexpr(q); ! 1456: q = ICON(0); ! 1457: } ! 1458: if ( q->constblock.const.ci <= 0) ! 1459: { ! 1460: dclerr("array bounds out of sequence", v); ! 1461: frexpr(q); ! 1462: q = ICON(0); ! 1463: } ! 1464: p->dims[i].dimsize = q; ! 1465: p->dims[i].dimexpr = (expptr) PNULL; ! 1466: } ! 1467: else { ! 1468: p->dims[i].dimsize = (expptr) autovar(1, tyint, PNULL); ! 1469: p->dims[i].dimexpr = q; ! 1470: } ! 1471: if(p->nelt) ! 1472: p->nelt = mkexpr(OPSTAR, p->nelt, ! 1473: cpexpr(p->dims[i].dimsize) ); ! 1474: } ! 1475: } ! 1476: ! 1477: q = dims[nd-1].lb; ! 1478: if(q == NULL) ! 1479: q = ICON(1); ! 1480: ! 1481: for(i = nd-2 ; i>=0 ; --i) ! 1482: { ! 1483: t = dims[i].lb; ! 1484: if(t == NULL) ! 1485: t = ICON(1); ! 1486: if(p->dims[i].dimsize) ! 1487: q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) ); ! 1488: } ! 1489: ! 1490: if( ISCONST(q) ) ! 1491: { ! 1492: p->baseoffset = q; ! 1493: p->basexpr = NULL; ! 1494: } ! 1495: else ! 1496: { ! 1497: p->baseoffset = (expptr) autovar(1, tyint, PNULL); ! 1498: p->basexpr = q; ! 1499: } ! 1500: } ! 1501: ! 1502: ! 1503: ! 1504: /* ! 1505: * Check the dimensions of q to ensure that they are appropriately defined. ! 1506: */ ! 1507: LOCAL chkdim(q) ! 1508: register Namep q; ! 1509: { ! 1510: register struct Dimblock *p; ! 1511: register int i; ! 1512: expptr e; ! 1513: ! 1514: if (q == NULL) ! 1515: return; ! 1516: if (q->vclass != CLVAR) ! 1517: return; ! 1518: if (q->vdim == NULL) ! 1519: return; ! 1520: p = q->vdim; ! 1521: for (i = 0; i < p->ndim; ++i) ! 1522: { ! 1523: #ifdef SDB ! 1524: if (sdbflag) ! 1525: { ! 1526: if (e = p->dims[i].lb) ! 1527: chkdime(e, q); ! 1528: if (e = p->dims[i].ub) ! 1529: chkdime(e, q); ! 1530: } ! 1531: else ! 1532: #endif SDB ! 1533: if (e = p->dims[i].dimexpr) ! 1534: chkdime(e, q); ! 1535: } ! 1536: } ! 1537: ! 1538: ! 1539: ! 1540: /* ! 1541: * The actual checking for chkdim() -- examines each expression. ! 1542: */ ! 1543: LOCAL chkdime(expr, q) ! 1544: expptr expr; ! 1545: Namep q; ! 1546: { ! 1547: register expptr e; ! 1548: ! 1549: e = fixtype(cpexpr(expr)); ! 1550: if (!ISINT(e->exprblock.vtype)) ! 1551: dclerr("non-integer dimension", q); ! 1552: else if (!safedim(e)) ! 1553: dclerr("undefined dimension", q); ! 1554: frexpr(e); ! 1555: return; ! 1556: } ! 1557: ! 1558: ! 1559: ! 1560: /* ! 1561: * A recursive routine to find undefined variables in dimension expressions. ! 1562: */ ! 1563: LOCAL safedim(e) ! 1564: expptr e; ! 1565: { ! 1566: chainp cp; ! 1567: ! 1568: if (e == NULL) ! 1569: return 1; ! 1570: switch (e->tag) ! 1571: { ! 1572: case TEXPR: ! 1573: if (e->exprblock.opcode == OPCALL || e->exprblock.opcode == OPCCALL) ! 1574: return 0; ! 1575: return safedim(e->exprblock.leftp) && safedim(e->exprblock.rightp); ! 1576: case TADDR: ! 1577: switch (e->addrblock.vstg) ! 1578: { ! 1579: case STGCOMMON: ! 1580: case STGARG: ! 1581: case STGCONST: ! 1582: case STGEQUIV: ! 1583: if (e->addrblock.isarray) ! 1584: return 0; ! 1585: return safedim(e->addrblock.memoffset); ! 1586: default: ! 1587: return 0; ! 1588: } ! 1589: case TCONST: ! 1590: case TTEMP: ! 1591: return 1; ! 1592: } ! 1593: return 0; ! 1594: } ! 1595: ! 1596: ! 1597: ! 1598: LOCAL enlist(size, np, ep) ! 1599: ftnint size; ! 1600: Namep np; ! 1601: struct Equivblock *ep; ! 1602: { ! 1603: register sizelist *sp; ! 1604: register sizelist *t; ! 1605: register varlist *p; ! 1606: ! 1607: sp = varsizes; ! 1608: ! 1609: if (sp == NULL) ! 1610: { ! 1611: sp = ALLOC(SizeList); ! 1612: sp->size = size; ! 1613: varsizes = sp; ! 1614: } ! 1615: else ! 1616: { ! 1617: while (sp->size != size) ! 1618: { ! 1619: if (sp->next != NULL && sp->next->size <= size) ! 1620: sp = sp->next; ! 1621: else ! 1622: { ! 1623: t = sp; ! 1624: sp = ALLOC(SizeList); ! 1625: sp->size = size; ! 1626: sp->next = t->next; ! 1627: t->next = sp; ! 1628: } ! 1629: } ! 1630: } ! 1631: ! 1632: p = ALLOC(VarList); ! 1633: p->next = sp->vars; ! 1634: p->np = np; ! 1635: p->ep = ep; ! 1636: ! 1637: sp->vars = p; ! 1638: ! 1639: return; ! 1640: } ! 1641: ! 1642: ! 1643: ! 1644: outlocvars() ! 1645: { ! 1646: ! 1647: register varlist *first, *last; ! 1648: register varlist *vp, *t; ! 1649: register sizelist *sp, *sp1; ! 1650: register Namep np; ! 1651: register struct Equivblock *ep; ! 1652: register int i; ! 1653: register int alt; ! 1654: register int type; ! 1655: char sname[100]; ! 1656: char setbuff[100]; ! 1657: ! 1658: sp = varsizes; ! 1659: if (sp == NULL) ! 1660: return; ! 1661: ! 1662: vp = sp->vars; ! 1663: if (vp->np != NULL) ! 1664: { ! 1665: np = vp->np; ! 1666: sprintf(setbuff, "\t.set\tv.%d,v.%d\n", bsslabel, ! 1667: np->vardesc.varno); ! 1668: } ! 1669: else ! 1670: { ! 1671: i = vp->ep - eqvclass; ! 1672: sprintf(setbuff, "\t.set\tv.%d,q.%d\n", bsslabel, i + eqvstart); ! 1673: } ! 1674: ! 1675: first = last = NULL; ! 1676: alt = NO; ! 1677: ! 1678: while (sp != NULL) ! 1679: { ! 1680: vp = sp->vars; ! 1681: while (vp != NULL) ! 1682: { ! 1683: t = vp->next; ! 1684: if (alt == YES) ! 1685: { ! 1686: alt = NO; ! 1687: vp->next = first; ! 1688: first = vp; ! 1689: } ! 1690: else ! 1691: { ! 1692: alt = YES; ! 1693: if (last != NULL) ! 1694: last->next = vp; ! 1695: else ! 1696: first = vp; ! 1697: vp->next = NULL; ! 1698: last = vp; ! 1699: } ! 1700: vp = t; ! 1701: } ! 1702: sp1 = sp; ! 1703: sp = sp->next; ! 1704: free((char *) sp1); ! 1705: } ! 1706: ! 1707: vp = first; ! 1708: while(vp != NULL) ! 1709: { ! 1710: if (vp->np != NULL) ! 1711: { ! 1712: np = vp->np; ! 1713: sprintf(sname, "v.%d", np->vardesc.varno); ! 1714: pralign(typealign[np->vtype]); ! 1715: if (np->init) ! 1716: prlocdata(sname, np->varsize, np->vtype, np->initoffset, ! 1717: &(np->inlcomm)); ! 1718: else ! 1719: { ! 1720: if (typealign[np->vtype] == 1) ! 1721: pralign(3); ! 1722: fprintf(initfile, "%s:\n\t.space\t%d\n", sname, ! 1723: np->varsize); ! 1724: } ! 1725: np->inlcomm = NO; ! 1726: } ! 1727: else ! 1728: { ! 1729: ep = vp->ep; ! 1730: i = ep - eqvclass; ! 1731: if (ep->eqvleng >= 8) ! 1732: type = TYDREAL; ! 1733: else if (ep->eqvleng >= 4) ! 1734: type = TYLONG; ! 1735: else if (ep->eqvleng >= 2) ! 1736: type = TYSHORT; ! 1737: else ! 1738: type = TYCHAR; ! 1739: sprintf(sname, "q.%d", i + eqvstart); ! 1740: if (ep->init) ! 1741: prlocdata(sname, ep->eqvleng, type, ep->initoffset, ! 1742: &(ep->inlcomm)); ! 1743: else ! 1744: { ! 1745: pralign(typealign[type]); ! 1746: fprintf(initfile, "%s:\n\t.space\t%d\n", sname, ep->eqvleng); ! 1747: } ! 1748: ep->inlcomm = NO; ! 1749: } ! 1750: t = vp; ! 1751: vp = vp->next; ! 1752: free((char *) t); ! 1753: } ! 1754: fprintf(initfile, "%s\n", setbuff); ! 1755: return; ! 1756: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.