|
|
1.1 ! root 1: /* Copyright (c) 1979 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)fdec.c 1.7 10/28/80"; ! 4: ! 5: #include "whoami.h" ! 6: #include "0.h" ! 7: #include "tree.h" ! 8: #include "opcode.h" ! 9: #include "objfmt.h" ! 10: #include "align.h" ! 11: ! 12: /* ! 13: * this array keeps the pxp counters associated with ! 14: * functions and procedures, so that they can be output ! 15: * when their bodies are encountered ! 16: */ ! 17: int bodycnts[ DSPLYSZ ]; ! 18: ! 19: #ifdef PC ! 20: # include "pc.h" ! 21: # include "pcops.h" ! 22: #endif PC ! 23: ! 24: #ifdef OBJ ! 25: int cntpatch; ! 26: int nfppatch; ! 27: #endif OBJ ! 28: ! 29: /* ! 30: * Funchdr inserts ! 31: * declaration of a the ! 32: * prog/proc/func into the ! 33: * namelist. It also handles ! 34: * the arguments and puts out ! 35: * a transfer which defines ! 36: * the entry point of a procedure. ! 37: */ ! 38: ! 39: struct nl * ! 40: funchdr(r) ! 41: int *r; ! 42: { ! 43: register struct nl *p; ! 44: register *il, **rl; ! 45: int *rll; ! 46: struct nl *cp, *dp, *sp; ! 47: int s, o, *pp; ! 48: ! 49: if (inpflist(r[2])) { ! 50: opush('l'); ! 51: yyretrieve(); /* kludge */ ! 52: } ! 53: pfcnt++; ! 54: parts[ cbn ] |= RPRT; ! 55: line = r[1]; ! 56: if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) { ! 57: /* ! 58: * Symbol already defined ! 59: * in this block. it is either ! 60: * a redeclared symbol (error) ! 61: * a forward declaration, ! 62: * or an external declaration. ! 63: */ ! 64: if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) { ! 65: /* ! 66: * Grammar doesnt forbid ! 67: * types on a resolution ! 68: * of a forward function ! 69: * declaration. ! 70: */ ! 71: if (p->class == FUNC && r[4]) ! 72: error("Function type should be given only in forward declaration"); ! 73: /* ! 74: * get another counter for the actual ! 75: */ ! 76: if ( monflg ) { ! 77: bodycnts[ cbn ] = getcnt(); ! 78: } ! 79: # ifdef PC ! 80: enclosing[ cbn ] = p -> symbol; ! 81: # endif PC ! 82: # ifdef PTREE ! 83: /* ! 84: * mark this proc/func as forward ! 85: * in the pTree. ! 86: */ ! 87: pDEF( p -> inTree ).PorFForward = TRUE; ! 88: # endif PTREE ! 89: return (p); ! 90: } ! 91: } ! 92: ! 93: /* if a routine segment is being compiled, ! 94: * do level one processing. ! 95: */ ! 96: ! 97: if ((r[0] != T_PROG) && (!progseen)) ! 98: level1(); ! 99: ! 100: ! 101: /* ! 102: * Declare the prog/proc/func ! 103: */ ! 104: switch (r[0]) { ! 105: case T_PROG: ! 106: progseen++; ! 107: if (opt('z')) ! 108: monflg++; ! 109: program = p = defnl(r[2], PROG, 0, 0); ! 110: p->value[3] = r[1]; ! 111: break; ! 112: case T_PDEC: ! 113: if (r[4] != NIL) ! 114: error("Procedures do not have types, only functions do"); ! 115: p = enter(defnl(r[2], PROC, 0, 0)); ! 116: p->nl_flags |= NMOD; ! 117: # ifdef PC ! 118: enclosing[ cbn ] = r[2]; ! 119: # endif PC ! 120: break; ! 121: case T_FDEC: ! 122: il = r[4]; ! 123: if (il == NIL) ! 124: error("Function type must be specified"); ! 125: else if (il[0] != T_TYID) { ! 126: il = NIL; ! 127: error("Function type can be specified only by using a type identifier"); ! 128: } else ! 129: il = gtype(il); ! 130: p = enter(defnl(r[2], FUNC, il, NIL)); ! 131: p->nl_flags |= NMOD; ! 132: /* ! 133: * An arbitrary restriction ! 134: */ ! 135: switch (o = classify(p->type)) { ! 136: case TFILE: ! 137: case TARY: ! 138: case TREC: ! 139: case TSET: ! 140: case TSTR: ! 141: warning(); ! 142: if (opt('s')) { ! 143: standard(); ! 144: } ! 145: error("Functions should not return %ss", clnames[o]); ! 146: } ! 147: # ifdef PC ! 148: enclosing[ cbn ] = r[2]; ! 149: # endif PC ! 150: break; ! 151: default: ! 152: panic("funchdr"); ! 153: } ! 154: if (r[0] != T_PROG) { ! 155: /* ! 156: * Mark this proc/func as ! 157: * being forward declared ! 158: */ ! 159: p->nl_flags |= NFORWD; ! 160: /* ! 161: * Enter the parameters ! 162: * in the next block for ! 163: * the time being ! 164: */ ! 165: if (++cbn >= DSPLYSZ) { ! 166: error("Procedure/function nesting too deep"); ! 167: pexit(ERRS); ! 168: } ! 169: /* ! 170: * For functions, the function variable ! 171: */ ! 172: if (p->class == FUNC) { ! 173: # ifdef OBJ ! 174: cp = defnl(r[2], FVAR, p->type, 0); ! 175: # endif OBJ ! 176: # ifdef PC ! 177: /* ! 178: * fvars used to be allocated and deallocated ! 179: * by the caller right before the arguments. ! 180: * the offset of the fvar was kept in ! 181: * value[NL_OFFS] of function (very wierd, ! 182: * but see asgnop). ! 183: * now, they are locals to the function ! 184: * with the offset kept in the fvar. ! 185: */ ! 186: ! 187: cp = defnl( r[2] , FVAR , p -> type ! 188: , -( roundup( DPOFF1+width( p -> type ) ! 189: , align( p -> type ) ) ) ); ! 190: # endif PC ! 191: cp->chain = p; ! 192: p->ptr[NL_FVAR] = cp; ! 193: } ! 194: /* ! 195: * Enter the parameters ! 196: * and compute total size ! 197: */ ! 198: cp = sp = p; ! 199: ! 200: # ifdef OBJ ! 201: o = 0; ! 202: # endif OBJ ! 203: # ifdef PC ! 204: /* ! 205: * parameters used to be allocated backwards, ! 206: * then fixed. for pc, they are allocated correctly. ! 207: * also, they are aligned. ! 208: */ ! 209: o = DPOFF2; ! 210: # endif PC ! 211: for (rl = r[3]; rl != NIL; rl = rl[2]) { ! 212: p = NIL; ! 213: if (rl[1] == NIL) ! 214: continue; ! 215: /* ! 216: * Parametric procedures ! 217: * don't have types !?! ! 218: */ ! 219: if (rl[1][0] != T_PPROC) { ! 220: rll = rl[1][2]; ! 221: if (rll[0] != T_TYID) { ! 222: error("Types for arguments can be specified only by using type identifiers"); ! 223: p = NIL; ! 224: } else ! 225: p = gtype(rll); ! 226: } ! 227: for (il = rl[1][1]; il != NIL; il = il[2]) { ! 228: switch (rl[1][0]) { ! 229: default: ! 230: panic("funchdr2"); ! 231: case T_PVAL: ! 232: if (p != NIL) { ! 233: if (p->class == FILET) ! 234: error("Files cannot be passed by value"); ! 235: else if (p->nl_flags & NFILES) ! 236: error("Files cannot be a component of %ss passed by value", ! 237: nameof(p)); ! 238: } ! 239: # ifdef OBJ ! 240: dp = defnl(il[1], VAR, p, o -= even(width(p))); ! 241: # endif OBJ ! 242: # ifdef PC ! 243: dp = defnl( il[1] , VAR , p ! 244: , o = roundup( o , A_STACK ) ); ! 245: o += width( p ); ! 246: # endif PC ! 247: dp->nl_flags |= NMOD; ! 248: break; ! 249: case T_PVAR: ! 250: # ifdef OBJ ! 251: dp = defnl(il[1], REF, p, o -= sizeof ( int * ) ); ! 252: # endif OBJ ! 253: # ifdef PC ! 254: dp = defnl( il[1] , REF , p ! 255: , o = roundup( o , A_STACK ) ); ! 256: o += sizeof(char *); ! 257: # endif PC ! 258: break; ! 259: case T_PFUNC: ! 260: # ifdef OBJ ! 261: dp = defnl(il[1], FFUNC, p, o -= sizeof ( int * ) ); ! 262: # endif OBJ ! 263: # ifdef PC ! 264: dp = defnl( il[1] , FFUNC , p ! 265: , o = roundup( o , A_STACK ) ); ! 266: o += sizeof(char *); ! 267: # endif PC ! 268: dp -> nl_flags |= NMOD; ! 269: break; ! 270: case T_PPROC: ! 271: # ifdef OBJ ! 272: dp = defnl(il[1], FPROC, p, o -= sizeof ( int * ) ); ! 273: # endif OBJ ! 274: # ifdef PC ! 275: dp = defnl( il[1] , FPROC , p ! 276: , o = roundup( o , A_STACK ) ); ! 277: o += sizeof(char *); ! 278: # endif PC ! 279: dp -> nl_flags |= NMOD; ! 280: break; ! 281: } ! 282: if (dp != NIL) { ! 283: cp->chain = dp; ! 284: cp = dp; ! 285: } ! 286: } ! 287: } ! 288: cbn--; ! 289: p = sp; ! 290: # ifdef OBJ ! 291: p->value[NL_OFFS] = -o+DPOFF2; ! 292: /* ! 293: * Correct the naivete (naievity) ! 294: * of our above code to ! 295: * calculate offsets ! 296: */ ! 297: for (il = p->chain; il != NIL; il = il->chain) ! 298: il->value[NL_OFFS] += p->value[NL_OFFS]; ! 299: # endif OBJ ! 300: # ifdef PC ! 301: p -> value[ NL_OFFS ] = roundup( o , A_STACK ); ! 302: # endif PC ! 303: } else { ! 304: /* ! 305: * The wonderful ! 306: * program statement! ! 307: */ ! 308: # ifdef OBJ ! 309: if (monflg) { ! 310: put(1, O_PXPBUF); ! 311: cntpatch = put(2, O_CASE4, 0); ! 312: nfppatch = put(2, O_CASE4, 0); ! 313: } ! 314: # endif OBJ ! 315: cp = p; ! 316: for (rl = r[3]; rl; rl = rl[2]) { ! 317: if (rl[1] == NIL) ! 318: continue; ! 319: dp = defnl(rl[1], VAR, 0, 0); ! 320: cp->chain = dp; ! 321: cp = dp; ! 322: } ! 323: } ! 324: /* ! 325: * Define a branch at ! 326: * the "entry point" of ! 327: * the prog/proc/func. ! 328: */ ! 329: p->entloc = getlab(); ! 330: if (monflg) { ! 331: bodycnts[ cbn ] = getcnt(); ! 332: p->value[ NL_CNTR ] = 0; ! 333: } ! 334: # ifdef OBJ ! 335: put(2, O_TRA4, p->entloc); ! 336: # endif OBJ ! 337: # ifdef PTREE ! 338: { ! 339: pPointer PF = tCopy( r ); ! 340: ! 341: pSeize( PorFHeader[ nesting ] ); ! 342: if ( r[0] != T_PROG ) { ! 343: pPointer *PFs; ! 344: ! 345: PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); ! 346: *PFs = ListAppend( *PFs , PF ); ! 347: } else { ! 348: pDEF( PorFHeader[ nesting ] ).GlobProg = PF; ! 349: } ! 350: pRelease( PorFHeader[ nesting ] ); ! 351: } ! 352: # endif PTREE ! 353: return (p); ! 354: } ! 355: ! 356: funcfwd(fp) ! 357: struct nl *fp; ! 358: { ! 359: ! 360: /* ! 361: * save the counter for this function ! 362: */ ! 363: if ( monflg ) { ! 364: fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; ! 365: } ! 366: return (fp); ! 367: } ! 368: ! 369: /* ! 370: * Funcext marks the procedure or ! 371: * function external in the symbol ! 372: * table. Funcext should only be ! 373: * called if PC, and is an error ! 374: * otherwise. ! 375: */ ! 376: ! 377: funcext(fp) ! 378: struct nl *fp; ! 379: { ! 380: ! 381: #ifdef PC ! 382: if (opt('s')) { ! 383: standard(); ! 384: error("External procedures and functions are not standard"); ! 385: } else { ! 386: if (cbn == 1) { ! 387: fp->ext_flags |= NEXTERN; ! 388: stabefunc( fp -> symbol , fp -> class , line ); ! 389: } ! 390: else ! 391: error("External procedures and functions can only be declared at the outermost level."); ! 392: } ! 393: #endif PC ! 394: #ifdef OBJ ! 395: error("Procedures or functions cannot be declared external."); ! 396: #endif OBJ ! 397: ! 398: return(fp); ! 399: } ! 400: ! 401: /* ! 402: * Funcbody is called ! 403: * when the actual (resolved) ! 404: * declaration of a procedure is ! 405: * encountered. It puts the names ! 406: * of the (function) and parameters ! 407: * into the symbol table. ! 408: */ ! 409: funcbody(fp) ! 410: struct nl *fp; ! 411: { ! 412: register struct nl *q, *p; ! 413: ! 414: cbn++; ! 415: if (cbn >= DSPLYSZ) { ! 416: error("Too many levels of function/procedure nesting"); ! 417: pexit(ERRS); ! 418: } ! 419: sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; ! 420: gotos[cbn] = NIL; ! 421: errcnt[cbn] = syneflg; ! 422: parts[ cbn ] = NIL; ! 423: dfiles[ cbn ] = FALSE; ! 424: if (fp == NIL) ! 425: return (NIL); ! 426: /* ! 427: * Save the virtual name ! 428: * list stack pointer so ! 429: * the space can be freed ! 430: * later (funcend). ! 431: */ ! 432: fp->ptr[2] = nlp; ! 433: # ifdef PC ! 434: if ( fp -> class != PROG ) { ! 435: stabfunc( fp -> symbol , fp -> class , line , cbn - 1 ); ! 436: } else { ! 437: stabfunc( "program" , fp -> class , line , 0 ); ! 438: } ! 439: # endif PC ! 440: if (fp->class != PROG) { ! 441: for (q = fp->chain; q != NIL; q = q->chain) { ! 442: enter(q); ! 443: # ifdef PC ! 444: stabparam( q -> symbol , p2type( q -> type ) ! 445: , q -> value[ NL_OFFS ] ! 446: , lwidth( q -> type ) ); ! 447: # endif PC ! 448: } ! 449: } ! 450: if (fp->class == FUNC) { ! 451: /* ! 452: * For functions, enter the fvar ! 453: */ ! 454: enter(fp->ptr[NL_FVAR]); ! 455: # ifdef PC ! 456: q = fp -> ptr[ NL_FVAR ]; ! 457: sizes[cbn].om_off -= lwidth( q -> type ); ! 458: sizes[cbn].om_max = sizes[cbn].om_off; ! 459: stabvar( q -> symbol , p2type( q -> type ) , cbn ! 460: , q -> value[ NL_OFFS ] , lwidth( q -> type ) ! 461: , line ); ! 462: # endif PC ! 463: } ! 464: # ifdef PTREE ! 465: /* ! 466: * pick up the pointer to porf declaration ! 467: */ ! 468: PorFHeader[ ++nesting ] = fp -> inTree; ! 469: # endif PTREE ! 470: return (fp); ! 471: } ! 472: ! 473: struct nl *Fp; ! 474: int pnumcnt; ! 475: /* ! 476: * Funcend is called to ! 477: * finish a block by generating ! 478: * the code for the statements. ! 479: * It then looks for unresolved declarations ! 480: * of labels, procedures and functions, ! 481: * and cleans up the name list. ! 482: * For the program, it checks the ! 483: * semantics of the program ! 484: * statement (yuchh). ! 485: */ ! 486: funcend(fp, bundle, endline) ! 487: struct nl *fp; ! 488: int *bundle; ! 489: int endline; ! 490: { ! 491: register struct nl *p; ! 492: register int i, b; ! 493: int var, inp, out, chkref, *blk; ! 494: struct nl *iop; ! 495: char *cp; ! 496: extern int cntstat; ! 497: # ifdef PC ! 498: int toplabel = getlab(); ! 499: int botlabel = getlab(); ! 500: # endif PC ! 501: ! 502: cntstat = 0; ! 503: /* ! 504: * yyoutline(); ! 505: */ ! 506: if (program != NIL) ! 507: line = program->value[3]; ! 508: blk = bundle[2]; ! 509: if (fp == NIL) { ! 510: cbn--; ! 511: # ifdef PTREE ! 512: nesting--; ! 513: # endif PTREE ! 514: return; ! 515: } ! 516: #ifdef OBJ ! 517: /* ! 518: * Patch the branch to the ! 519: * entry point of the function ! 520: */ ! 521: patch4(fp->entloc); ! 522: /* ! 523: * Put out the block entrance code and the block name. ! 524: * the CONG is overlaid by a patch later! ! 525: */ ! 526: var = put(2, (lenstr(fp->symbol,0) << 8) ! 527: | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), 0); ! 528: /* ! 529: * output the number of bytes of arguments ! 530: * this is only checked on formal calls. ! 531: */ ! 532: put(2, O_CASE4, cbn == 1 ? 0 : fp->value[NL_OFFS]-DPOFF2); ! 533: put(2, O_CASE2, bundle[1]); ! 534: putstr(fp->symbol, 0); ! 535: #endif OBJ ! 536: #ifdef PC ! 537: /* ! 538: * put out the procedure entry code ! 539: */ ! 540: if ( fp -> class == PROG ) { ! 541: putprintf( " .text" , 0 ); ! 542: putprintf( " .align 1" , 0 ); ! 543: putprintf( " .globl _main" , 0 ); ! 544: putprintf( "_main:" , 0 ); ! 545: putprintf( " .word 0" , 0 ); ! 546: putprintf( " calls $0,_PCSTART" , 0 ); ! 547: putprintf( " movl 4(ap),__argc" , 0 ); ! 548: putprintf( " movl 8(ap),__argv" , 0 ); ! 549: putprintf( " calls $0,_program" , 0 ); ! 550: putprintf( " calls $0,_PCEXIT" , 0 ); ! 551: ftnno = fp -> entloc; ! 552: putprintf( " .text" , 0 ); ! 553: putprintf( " .align 1" , 0 ); ! 554: putprintf( " .globl _program" , 0 ); ! 555: putprintf( "_program:" , 0 ); ! 556: } else { ! 557: ftnno = fp -> entloc; ! 558: putprintf( " .text" , 0 ); ! 559: putprintf( " .align 1" , 0 ); ! 560: putprintf( " .globl " , 1 ); ! 561: for ( i = 1 ; i < cbn ; i++ ) { ! 562: putprintf( EXTFORMAT , 1 , enclosing[ i ] ); ! 563: } ! 564: putprintf( "" , 0 ); ! 565: for ( i = 1 ; i < cbn ; i++ ) { ! 566: putprintf( EXTFORMAT , 1 , enclosing[ i ] ); ! 567: } ! 568: putprintf( ":" , 0 ); ! 569: } ! 570: stablbrac( cbn ); ! 571: /* ! 572: * register save mask ! 573: */ ! 574: if ( opt( 't' ) ) { ! 575: putprintf( " .word 0x%x" , 0 , RUNCHECK | RSAVEMASK ); ! 576: } else { ! 577: putprintf( " .word 0x%x" , 0 , RSAVEMASK ); ! 578: } ! 579: putjbr( botlabel ); ! 580: putlab( toplabel ); ! 581: if ( profflag ) { ! 582: /* ! 583: * call mcount for profiling ! 584: */ ! 585: putprintf( " moval 1f,r0" , 0 ); ! 586: putprintf( " jsb mcount" , 0 ); ! 587: putprintf( " .data" , 0 ); ! 588: putprintf( " .align 2" , 0 ); ! 589: putprintf( "1:" , 0 ); ! 590: putprintf( " .long 0" , 0 ); ! 591: putprintf( " .text" , 0 ); ! 592: } ! 593: /* ! 594: * set up unwind exception vector. ! 595: */ ! 596: putprintf( " moval %s,%d(%s)" , 0 ! 597: , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); ! 598: /* ! 599: * save address of display entry, for unwind. ! 600: */ ! 601: putprintf( " moval %s+%d,%d(%s)" , 0 ! 602: , DISPLAYNAME , cbn * sizeof(struct dispsave) ! 603: , DPTROFFSET , P2FPNAME ); ! 604: /* ! 605: * save old display ! 606: */ ! 607: putprintf( " movq %s+%d,%d(%s)" , 0 ! 608: , DISPLAYNAME , cbn * sizeof(struct dispsave) ! 609: , DSAVEOFFSET , P2FPNAME ); ! 610: /* ! 611: * set up new display by saving AP and FP in appropriate ! 612: * slot in display structure. ! 613: */ ! 614: putprintf( " movq %s,%s+%d" , 0 ! 615: , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); ! 616: /* ! 617: * ask second pass to allocate known locals ! 618: */ ! 619: putlbracket( ftnno , -sizes[ cbn ].om_max ); ! 620: /* ! 621: * and zero them if checking is on ! 622: * by calling zframe( bytes of locals , highest local address ); ! 623: */ ! 624: if ( opt( 't' ) ) { ! 625: if ( ( -sizes[ cbn ].om_max ) > DPOFF1 ) { ! 626: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 627: , "_ZFRAME" ); ! 628: putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 ! 629: , 0 , P2INT , 0 ); ! 630: putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); ! 631: putop( P2LISTOP , P2INT ); ! 632: putop( P2CALL , P2INT ); ! 633: putdot( filename , line ); ! 634: } ! 635: /* ! 636: * check number of longs of arguments ! 637: * this can only be wrong for formal calls. ! 638: */ ! 639: if ( fp -> class != PROG ) { ! 640: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2PTR , P2FTN | P2INT ) , ! 641: "_NARGCHK" ); ! 642: putleaf( P2ICON , ! 643: (fp->value[NL_OFFS] - DPOFF2) / sizeof(long) , ! 644: 0 , P2INT , 0 ); ! 645: putop( P2CALL , P2INT ); ! 646: putdot( filename , line ); ! 647: } ! 648: } ! 649: #endif PC ! 650: if ( monflg ) { ! 651: if ( fp -> value[ NL_CNTR ] != 0 ) { ! 652: inccnt( fp -> value [ NL_CNTR ] ); ! 653: } ! 654: inccnt( bodycnts[ fp -> nl_block & 037 ] ); ! 655: } ! 656: if (fp->class == PROG) { ! 657: /* ! 658: * The glorious buffers option. ! 659: * 0 = don't buffer output ! 660: * 1 = line buffer output ! 661: * 2 = 512 byte buffer output ! 662: */ ! 663: # ifdef OBJ ! 664: if (opt('b') != 1) ! 665: put(1, O_BUFF | opt('b') << 8); ! 666: # endif OBJ ! 667: # ifdef PC ! 668: if ( opt( 'b' ) != 1 ) { ! 669: putleaf( P2ICON , 0 , 0 ! 670: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); ! 671: putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); ! 672: putop( P2CALL , P2INT ); ! 673: putdot( filename , line ); ! 674: } ! 675: # endif PC ! 676: out = 0; ! 677: for (p = fp->chain; p != NIL; p = p->chain) { ! 678: if (strcmp(p->symbol, "input") == 0) { ! 679: inp++; ! 680: continue; ! 681: } ! 682: if (strcmp(p->symbol, "output") == 0) { ! 683: out++; ! 684: continue; ! 685: } ! 686: iop = lookup1(p->symbol); ! 687: if (iop == NIL || bn != cbn) { ! 688: error("File %s listed in program statement but not declared", p->symbol); ! 689: continue; ! 690: } ! 691: if (iop->class != VAR) { ! 692: error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); ! 693: continue; ! 694: } ! 695: if (iop->type == NIL) ! 696: continue; ! 697: if (iop->type->class != FILET) { ! 698: error("File %s listed in program statement but defined as %s", ! 699: p->symbol, nameof(iop->type)); ! 700: continue; ! 701: } ! 702: # ifdef OBJ ! 703: put(2, O_LV | bn << 8+INDX, iop->value[NL_OFFS]); ! 704: i = lenstr(p->symbol,0); ! 705: put(2, O_LVCON, i); ! 706: putstr(p->symbol, 0); ! 707: do { ! 708: i--; ! 709: } while (p->symbol+i == 0); ! 710: put(2, O_CON24, i+1); ! 711: put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); ! 712: put(1, O_DEFNAME); ! 713: # endif OBJ ! 714: # ifdef PC ! 715: putleaf( P2ICON , 0 , 0 ! 716: , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 717: , "_DEFNAME" ); ! 718: putLV( p -> symbol , bn , iop -> value[NL_OFFS] ! 719: , p2type( iop ) ); ! 720: putCONG( p -> symbol , strlen( p -> symbol ) ! 721: , LREQ ); ! 722: putop( P2LISTOP , P2INT ); ! 723: putleaf( P2ICON , strlen( p -> symbol ) ! 724: , 0 , P2INT , 0 ); ! 725: putop( P2LISTOP , P2INT ); ! 726: putleaf( P2ICON ! 727: , text(iop->type) ? 0 : width(iop->type->type) ! 728: , 0 , P2INT , 0 ); ! 729: putop( P2LISTOP , P2INT ); ! 730: putop( P2CALL , P2INT ); ! 731: putdot( filename , line ); ! 732: # endif PC ! 733: } ! 734: if (out == 0 && fp->chain != NIL) { ! 735: recovered(); ! 736: error("The file output must appear in the program statement file list"); ! 737: } ! 738: } ! 739: /* ! 740: * Process the prog/proc/func body ! 741: */ ! 742: noreach = 0; ! 743: line = bundle[1]; ! 744: statlist(blk); ! 745: # ifdef PTREE ! 746: { ! 747: pPointer Body = tCopy( blk ); ! 748: ! 749: pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; ! 750: } ! 751: # endif PTREE ! 752: # ifdef OBJ ! 753: if (cbn== 1 && monflg != 0) { ! 754: patchfil(cntpatch - 2, cnts, 2); ! 755: patchfil(nfppatch - 2, pfcnt, 2); ! 756: } ! 757: # endif OBJ ! 758: # ifdef PC ! 759: if ( fp -> class == PROG && monflg ) { ! 760: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 761: , "_PMFLUSH" ); ! 762: putleaf( P2ICON , cnts , 0 , P2INT , 0 ); ! 763: putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); ! 764: putop( P2LISTOP , P2INT ); ! 765: putop( P2CALL , P2INT ); ! 766: putdot( filename , line ); ! 767: } ! 768: # endif PC ! 769: if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { ! 770: recovered(); ! 771: error("Input is used but not defined in the program statement"); ! 772: } ! 773: /* ! 774: * Clean up the symbol table displays and check for unresolves ! 775: */ ! 776: line = endline; ! 777: b = cbn; ! 778: Fp = fp; ! 779: chkref = syneflg == errcnt[cbn] && opt('w') == 0; ! 780: for (i = 0; i <= 077; i++) { ! 781: for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { ! 782: /* ! 783: * Check for variables defined ! 784: * but not referenced ! 785: */ ! 786: if (chkref && p->symbol != NIL) ! 787: switch (p->class) { ! 788: case FIELD: ! 789: /* ! 790: * If the corresponding record is ! 791: * unused, we shouldn't complain about ! 792: * the fields. ! 793: */ ! 794: default: ! 795: if ((p->nl_flags & (NUSED|NMOD)) == 0) { ! 796: warning(); ! 797: nerror("%s %s is neither used nor set", classes[p->class], p->symbol); ! 798: break; ! 799: } ! 800: /* ! 801: * If a var parameter is either ! 802: * modified or used that is enough. ! 803: */ ! 804: if (p->class == REF) ! 805: continue; ! 806: # ifdef OBJ ! 807: if ((p->nl_flags & NUSED) == 0) { ! 808: warning(); ! 809: nerror("%s %s is never used", classes[p->class], p->symbol); ! 810: break; ! 811: } ! 812: # endif OBJ ! 813: # ifdef PC ! 814: if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { ! 815: warning(); ! 816: nerror("%s %s is never used", classes[p->class], p->symbol); ! 817: break; ! 818: } ! 819: # endif PC ! 820: if ((p->nl_flags & NMOD) == 0) { ! 821: warning(); ! 822: nerror("%s %s is used but never set", classes[p->class], p->symbol); ! 823: break; ! 824: } ! 825: case LABEL: ! 826: case FVAR: ! 827: case BADUSE: ! 828: break; ! 829: } ! 830: switch (p->class) { ! 831: case BADUSE: ! 832: cp = "s"; ! 833: if (p->chain->ud_next == NIL) ! 834: cp++; ! 835: eholdnl(); ! 836: if (p->value[NL_KINDS] & ISUNDEF) ! 837: nerror("%s undefined on line%s", p->symbol, cp); ! 838: else ! 839: nerror("%s improperly used on line%s", p->symbol, cp); ! 840: pnumcnt = 10; ! 841: pnums(p->chain); ! 842: pchr('\n'); ! 843: break; ! 844: ! 845: case FUNC: ! 846: case PROC: ! 847: # ifdef OBJ ! 848: if ((p->nl_flags & NFORWD)) ! 849: nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); ! 850: # endif OBJ ! 851: # ifdef PC ! 852: if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) ! 853: nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); ! 854: # endif PC ! 855: break; ! 856: ! 857: case LABEL: ! 858: if (p->nl_flags & NFORWD) ! 859: nerror("label %s was declared but not defined", p->symbol); ! 860: break; ! 861: case FVAR: ! 862: if ((p->nl_flags & NMOD) == 0) ! 863: nerror("No assignment to the function variable"); ! 864: break; ! 865: } ! 866: } ! 867: /* ! 868: * Pop this symbol ! 869: * table slot ! 870: */ ! 871: disptab[i] = p; ! 872: } ! 873: ! 874: # ifdef OBJ ! 875: put(1, O_END); ! 876: # endif OBJ ! 877: # ifdef PC ! 878: /* ! 879: * if there were file variables declared at this level ! 880: * call pclose( &__disply[ cbn ] ) to clean them up. ! 881: */ ! 882: if ( dfiles[ cbn ] ) { ! 883: putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ! 884: , "_PCLOSE" ); ! 885: putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) ! 886: , P2PTR | P2CHAR ); ! 887: putop( P2CALL , P2INT ); ! 888: putdot( filename , line ); ! 889: } ! 890: /* ! 891: * if this is a function, ! 892: * the function variable is the return value. ! 893: * if it's a scalar valued function, return scalar, ! 894: * else, return a pointer to the structure value. ! 895: */ ! 896: if ( fp -> class == FUNC ) { ! 897: struct nl *fvar = fp -> ptr[ NL_FVAR ]; ! 898: long fvartype = p2type( fvar -> type ); ! 899: long label; ! 900: char labelname[ BUFSIZ ]; ! 901: ! 902: switch ( classify( fvar -> type ) ) { ! 903: case TBOOL: ! 904: case TCHAR: ! 905: case TINT: ! 906: case TSCAL: ! 907: case TDOUBLE: ! 908: case TPTR: ! 909: putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 ! 910: , fvar -> value[ NL_OFFS ] , fvartype ); ! 911: break; ! 912: default: ! 913: label = getlab(); ! 914: sprintf( labelname , PREFIXFORMAT , ! 915: LABELPREFIX , label ); ! 916: putprintf( " .data" , 0 ); ! 917: putprintf( " .lcomm %s,%d" , 0 , ! 918: labelname , lwidth( fvar -> type ) ); ! 919: putprintf( " .text" , 0 ); ! 920: putleaf( P2NAME , 0 , 0 , fvartype , labelname ); ! 921: putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 ! 922: , fvar -> value[ NL_OFFS ] , fvartype ); ! 923: putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , ! 924: align( fvar -> type ) ); ! 925: putdot( filename , line ); ! 926: putleaf( P2ICON , 0 , 0 , fvartype , labelname ); ! 927: break; ! 928: } ! 929: putop( P2FORCE , fvartype ); ! 930: putdot( filename , line ); ! 931: } ! 932: /* ! 933: * restore old display entry from save area ! 934: */ ! 935: ! 936: putprintf( " movq %d(%s),%s+%d" , 0 ! 937: , DSAVEOFFSET , P2FPNAME ! 938: , DISPLAYNAME , cbn * sizeof(struct dispsave) ); ! 939: stabrbrac( cbn ); ! 940: putprintf( " ret" , 0 ); ! 941: /* ! 942: * let the second pass allocate locals ! 943: */ ! 944: putlab( botlabel ); ! 945: putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); ! 946: putrbracket( ftnno ); ! 947: putjbr( toplabel ); ! 948: /* ! 949: * declare pcp counters, if any ! 950: */ ! 951: if ( monflg && fp -> class == PROG ) { ! 952: putprintf( " .data" , 0 ); ! 953: putprintf( " .comm " , 1 ); ! 954: putprintf( PCPCOUNT , 1 ); ! 955: putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); ! 956: putprintf( " .text" , 0 ); ! 957: } ! 958: # endif PC ! 959: #ifdef DEBUG ! 960: dumpnl(fp->ptr[2], fp->symbol); ! 961: #endif ! 962: /* ! 963: * Restore the ! 964: * (virtual) name list ! 965: * position ! 966: */ ! 967: nlfree(fp->ptr[2]); ! 968: /* ! 969: * Proc/func has been ! 970: * resolved ! 971: */ ! 972: fp->nl_flags &= ~NFORWD; ! 973: /* ! 974: * Patch the beg ! 975: * of the proc/func to ! 976: * the proper variable size ! 977: */ ! 978: if (Fp == NIL) ! 979: elineon(); ! 980: # ifdef OBJ ! 981: patchfil(var, sizes[cbn].om_max, 2); ! 982: # endif OBJ ! 983: cbn--; ! 984: if (inpflist(fp->symbol)) { ! 985: opop('l'); ! 986: } ! 987: } ! 988: ! 989: ! 990: /* ! 991: * Segend is called to check for ! 992: * unresolved variables, funcs and ! 993: * procs, and deliver unresolved and ! 994: * baduse error diagnostics at the ! 995: * end of a routine segment (a separately ! 996: * compiled segment that is not the ! 997: * main program) for PC. This ! 998: * routine should only be called ! 999: * by PC (not standard). ! 1000: */ ! 1001: segend() ! 1002: { ! 1003: register struct nl *p; ! 1004: register int i,b; ! 1005: char *cp; ! 1006: ! 1007: #ifdef PC ! 1008: if (opt('s')) { ! 1009: standard(); ! 1010: error("Separately compiled routine segments are not standard."); ! 1011: } else { ! 1012: b = cbn; ! 1013: for (i=0; i<077; i++) { ! 1014: for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { ! 1015: switch (p->class) { ! 1016: case BADUSE: ! 1017: cp = 's'; ! 1018: if (p->chain->ud_next == NIL) ! 1019: cp++; ! 1020: eholdnl(); ! 1021: if (p->value[NL_KINDS] & ISUNDEF) ! 1022: nerror("%s undefined on line%s", p->symbol, cp); ! 1023: else ! 1024: nerror("%s improperly used on line%s", p->symbol, cp); ! 1025: pnumcnt = 10; ! 1026: pnums(p->chain); ! 1027: pchr('\n'); ! 1028: break; ! 1029: ! 1030: case FUNC: ! 1031: case PROC: ! 1032: if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) ! 1033: nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); ! 1034: break; ! 1035: ! 1036: case FVAR: ! 1037: if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0)) ! 1038: nerror("No assignment to the function variable"); ! 1039: break; ! 1040: } ! 1041: } ! 1042: disptab[i] = p; ! 1043: } ! 1044: } ! 1045: #endif PC ! 1046: #ifdef OBJ ! 1047: error("Missing program statement and program body"); ! 1048: #endif OBJ ! 1049: ! 1050: } ! 1051: ! 1052: ! 1053: /* ! 1054: * Level1 does level one processing for ! 1055: * separately compiled routine segments ! 1056: */ ! 1057: level1() ! 1058: { ! 1059: ! 1060: # ifdef OBJ ! 1061: error("Missing program statement"); ! 1062: # endif OBJ ! 1063: # ifdef PC ! 1064: if (opt('s')) { ! 1065: standard(); ! 1066: error("Missing program statement"); ! 1067: } ! 1068: # endif PC ! 1069: ! 1070: cbn++; ! 1071: sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; ! 1072: gotos[cbn] = NIL; ! 1073: errcnt[cbn] = syneflg; ! 1074: parts[ cbn ] = NIL; ! 1075: dfiles[ cbn ] = FALSE; ! 1076: progseen++; ! 1077: } ! 1078: ! 1079: ! 1080: ! 1081: pnums(p) ! 1082: struct udinfo *p; ! 1083: { ! 1084: ! 1085: if (p->ud_next != NIL) ! 1086: pnums(p->ud_next); ! 1087: if (pnumcnt == 0) { ! 1088: printf("\n\t"); ! 1089: pnumcnt = 20; ! 1090: } ! 1091: pnumcnt--; ! 1092: printf(" %d", p->ud_line); ! 1093: } ! 1094: ! 1095: nerror(a1, a2, a3) ! 1096: { ! 1097: ! 1098: if (Fp != NIL) { ! 1099: yySsync(); ! 1100: #ifndef PI1 ! 1101: if (opt('l')) ! 1102: yyoutline(); ! 1103: #endif ! 1104: yysetfile(filename); ! 1105: printf("In %s %s:\n", classes[Fp->class], Fp->symbol); ! 1106: Fp = NIL; ! 1107: elineoff(); ! 1108: } ! 1109: error(a1, a2, a3); ! 1110: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.