1752Speter /* Copyright (c) 1979 Regents of the University of California */ 2752Speter 3*825Speter static char sccsid[] = "@(#)fdec.c 1.2 08/31/80"; 4752Speter 5752Speter #include "whoami.h" 6752Speter #include "0.h" 7752Speter #include "tree.h" 8752Speter #include "opcode.h" 9752Speter #include "objfmt.h" 10752Speter #include "align.h" 11752Speter 12752Speter /* 13752Speter * this array keeps the pxp counters associated with 14752Speter * functions and procedures, so that they can be output 15752Speter * when their bodies are encountered 16752Speter */ 17752Speter int bodycnts[ DSPLYSZ ]; 18752Speter 19752Speter #ifdef PC 20752Speter # include "pc.h" 21752Speter # include "pcops.h" 22752Speter #endif PC 23752Speter 24752Speter #ifdef OBJ 25752Speter int cntpatch; 26752Speter int nfppatch; 27752Speter #endif OBJ 28752Speter 29752Speter /* 30752Speter * Funchdr inserts 31752Speter * declaration of a the 32752Speter * prog/proc/func into the 33752Speter * namelist. It also handles 34752Speter * the arguments and puts out 35752Speter * a transfer which defines 36752Speter * the entry point of a procedure. 37752Speter */ 38752Speter 39752Speter struct nl * 40752Speter funchdr(r) 41752Speter int *r; 42752Speter { 43752Speter register struct nl *p; 44752Speter register *il, **rl; 45752Speter int *rll; 46752Speter struct nl *cp, *dp, *sp; 47752Speter int s, o, *pp; 48752Speter 49752Speter if (inpflist(r[2])) { 50752Speter opush('l'); 51752Speter yyretrieve(); /* kludge */ 52752Speter } 53752Speter pfcnt++; 54752Speter line = r[1]; 55752Speter if (r[3] == NIL && (p=lookup1(r[2])) != NIL && bn == cbn) { 56752Speter /* 57752Speter * Symbol already defined 58752Speter * in this block. it is either 59752Speter * a redeclared symbol (error) 60752Speter * a forward declaration, 61752Speter * or an external declaration. 62752Speter */ 63752Speter if ((p->class == FUNC || p->class == PROC) && (p->nl_flags & NFORWD) != 0) { 64752Speter /* 65752Speter * Grammar doesnt forbid 66752Speter * types on a resolution 67752Speter * of a forward function 68752Speter * declaration. 69752Speter */ 70752Speter if (p->class == FUNC && r[4]) 71752Speter error("Function type should be given only in forward declaration"); 72752Speter /* 73752Speter * get another counter for the actual 74752Speter */ 75752Speter if ( monflg ) { 76752Speter bodycnts[ cbn ] = getcnt(); 77752Speter } 78752Speter # ifdef PC 79752Speter enclosing[ cbn ] = p -> symbol; 80752Speter # endif PC 81752Speter # ifdef PTREE 82752Speter /* 83752Speter * mark this proc/func as forward 84752Speter * in the pTree. 85752Speter */ 86752Speter pDEF( p -> inTree ).PorFForward = TRUE; 87752Speter # endif PTREE 88752Speter return (p); 89752Speter } 90752Speter } 91752Speter 92752Speter /* if a routine segment is being compiled, 93752Speter * do level one processing. 94752Speter */ 95752Speter 96752Speter if ((r[0] != T_PROG) && (!progseen)) 97752Speter level1(); 98752Speter 99752Speter 100752Speter /* 101752Speter * Declare the prog/proc/func 102752Speter */ 103752Speter switch (r[0]) { 104752Speter case T_PROG: 105752Speter progseen++; 106752Speter if (opt('z')) 107752Speter monflg++; 108752Speter program = p = defnl(r[2], PROG, 0, 0); 109752Speter p->value[3] = r[1]; 110752Speter break; 111752Speter case T_PDEC: 112752Speter if (r[4] != NIL) 113752Speter error("Procedures do not have types, only functions do"); 114752Speter p = enter(defnl(r[2], PROC, 0, 0)); 115752Speter p->nl_flags |= NMOD; 116752Speter # ifdef PC 117752Speter enclosing[ cbn ] = r[2]; 118752Speter # endif PC 119752Speter break; 120752Speter case T_FDEC: 121752Speter il = r[4]; 122752Speter if (il == NIL) 123752Speter error("Function type must be specified"); 124752Speter else if (il[0] != T_TYID) { 125752Speter il = NIL; 126752Speter error("Function type can be specified only by using a type identifier"); 127752Speter } else 128752Speter il = gtype(il); 129752Speter p = enter(defnl(r[2], FUNC, il, NIL)); 130752Speter p->nl_flags |= NMOD; 131752Speter /* 132752Speter * An arbitrary restriction 133752Speter */ 134752Speter switch (o = classify(p->type)) { 135752Speter case TFILE: 136752Speter case TARY: 137752Speter case TREC: 138752Speter case TSET: 139752Speter case TSTR: 140752Speter warning(); 141752Speter if (opt('s')) 142752Speter standard(); 143752Speter error("Functions should not return %ss", clnames[o]); 144752Speter } 145752Speter # ifdef PC 146752Speter enclosing[ cbn ] = r[2]; 147752Speter # endif PC 148752Speter break; 149752Speter default: 150752Speter panic("funchdr"); 151752Speter } 152752Speter if (r[0] != T_PROG) { 153752Speter /* 154752Speter * Mark this proc/func as 155752Speter * being forward declared 156752Speter */ 157752Speter p->nl_flags |= NFORWD; 158752Speter /* 159752Speter * Enter the parameters 160752Speter * in the next block for 161752Speter * the time being 162752Speter */ 163752Speter if (++cbn >= DSPLYSZ) { 164752Speter error("Procedure/function nesting too deep"); 165752Speter pexit(ERRS); 166752Speter } 167752Speter /* 168752Speter * For functions, the function variable 169752Speter */ 170752Speter if (p->class == FUNC) { 171752Speter # ifdef OBJ 172752Speter cp = defnl(r[2], FVAR, p->type, 0); 173752Speter # endif OBJ 174752Speter # ifdef PC 175752Speter /* 176752Speter * fvars used to be allocated and deallocated 177752Speter * by the caller right before the arguments. 178752Speter * the offset of the fvar was kept in 179752Speter * value[NL_OFFS] of function (very wierd, 180752Speter * but see asgnop). 181752Speter * now, they are locals to the function 182752Speter * with the offset kept in the fvar. 183752Speter */ 184752Speter 185752Speter cp = defnl( r[2] , FVAR , p -> type 186752Speter , -( roundup( DPOFF1+width( p -> type ) 187752Speter , align( p -> type ) ) ) ); 188752Speter # endif PC 189752Speter cp->chain = p; 190752Speter p->ptr[NL_FVAR] = cp; 191752Speter } 192752Speter /* 193752Speter * Enter the parameters 194752Speter * and compute total size 195752Speter */ 196752Speter cp = sp = p; 197752Speter 198752Speter # ifdef OBJ 199752Speter o = 0; 200752Speter # endif OBJ 201752Speter # ifdef PC 202752Speter /* 203752Speter * parameters used to be allocated backwards, 204752Speter * then fixed. for pc, they are allocated correctly. 205752Speter * also, they are aligned. 206752Speter */ 207752Speter o = DPOFF2; 208752Speter # endif PC 209752Speter for (rl = r[3]; rl != NIL; rl = rl[2]) { 210752Speter p = NIL; 211752Speter if (rl[1] == NIL) 212752Speter continue; 213752Speter /* 214752Speter * Parametric procedures 215752Speter * don't have types !?! 216752Speter */ 217752Speter if (rl[1][0] != T_PPROC) { 218752Speter rll = rl[1][2]; 219752Speter if (rll[0] != T_TYID) { 220752Speter error("Types for arguments can be specified only by using type identifiers"); 221752Speter p = NIL; 222752Speter } else 223752Speter p = gtype(rll); 224752Speter } 225752Speter for (il = rl[1][1]; il != NIL; il = il[2]) { 226752Speter switch (rl[1][0]) { 227752Speter default: 228752Speter panic("funchdr2"); 229752Speter case T_PVAL: 230752Speter if (p != NIL) { 231752Speter if (p->class == FILET) 232752Speter error("Files cannot be passed by value"); 233752Speter else if (p->nl_flags & NFILES) 234752Speter error("Files cannot be a component of %ss passed by value", 235752Speter nameof(p)); 236752Speter } 237752Speter # ifdef OBJ 238752Speter dp = defnl(il[1], VAR, p, o -= even(width(p))); 239752Speter # endif OBJ 240752Speter # ifdef PC 241752Speter dp = defnl( il[1] , VAR , p 242752Speter , o = roundup( o , A_STACK ) ); 243752Speter o += width( p ); 244752Speter # endif PC 245752Speter dp->nl_flags |= NMOD; 246752Speter break; 247752Speter case T_PVAR: 248752Speter # ifdef OBJ 249752Speter dp = defnl(il[1], REF, p, o -= sizeof ( int * ) ); 250752Speter # endif OBJ 251752Speter # ifdef PC 252752Speter dp = defnl( il[1] , REF , p 253752Speter , o = roundup( o , A_STACK ) ); 254752Speter o += sizeof(char *); 255752Speter # endif PC 256752Speter break; 257752Speter case T_PFUNC: 258752Speter case T_PPROC: 259752Speter error("Procedure/function parameters not implemented"); 260752Speter continue; 261752Speter } 262752Speter if (dp != NIL) { 263752Speter cp->chain = dp; 264752Speter cp = dp; 265752Speter } 266752Speter } 267752Speter } 268752Speter cbn--; 269752Speter p = sp; 270752Speter # ifdef OBJ 271752Speter p->value[NL_OFFS] = -o+DPOFF2; 272752Speter /* 273752Speter * Correct the naivete (naievity) 274752Speter * of our above code to 275752Speter * calculate offsets 276752Speter */ 277752Speter for (il = p->chain; il != NIL; il = il->chain) 278752Speter il->value[NL_OFFS] += p->value[NL_OFFS]; 279752Speter # endif OBJ 280752Speter # ifdef PC 281752Speter p -> value[ NL_OFFS ] = o; 282752Speter # endif PC 283752Speter } else { 284752Speter /* 285752Speter * The wonderful 286752Speter * program statement! 287752Speter */ 288752Speter # ifdef OBJ 289752Speter if (monflg) { 290752Speter put(1, O_PXPBUF); 291752Speter cntpatch = put(2, O_CASE4, 0); 292752Speter nfppatch = put(2, O_CASE4, 0); 293752Speter } 294752Speter # endif OBJ 295752Speter cp = p; 296752Speter for (rl = r[3]; rl; rl = rl[2]) { 297752Speter if (rl[1] == NIL) 298752Speter continue; 299752Speter dp = defnl(rl[1], VAR, 0, 0); 300752Speter cp->chain = dp; 301752Speter cp = dp; 302752Speter } 303752Speter } 304752Speter /* 305752Speter * Define a branch at 306752Speter * the "entry point" of 307752Speter * the prog/proc/func. 308752Speter */ 309752Speter p->entloc = getlab(); 310752Speter if (monflg) { 311752Speter bodycnts[ cbn ] = getcnt(); 312752Speter p->value[ NL_CNTR ] = 0; 313752Speter } 314752Speter # ifdef OBJ 315752Speter put(2, O_TRA4, p->entloc); 316752Speter # endif OBJ 317752Speter # ifdef PTREE 318752Speter { 319752Speter pPointer PF = tCopy( r ); 320752Speter 321752Speter pSeize( PorFHeader[ nesting ] ); 322752Speter if ( r[0] != T_PROG ) { 323752Speter pPointer *PFs; 324752Speter 325752Speter PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 326752Speter *PFs = ListAppend( *PFs , PF ); 327752Speter } else { 328752Speter pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 329752Speter } 330752Speter pRelease( PorFHeader[ nesting ] ); 331752Speter } 332752Speter # endif PTREE 333752Speter return (p); 334752Speter } 335752Speter 336752Speter funcfwd(fp) 337752Speter struct nl *fp; 338752Speter { 339752Speter 340752Speter /* 341752Speter * save the counter for this function 342752Speter */ 343752Speter if ( monflg ) { 344752Speter fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; 345752Speter } 346752Speter return (fp); 347752Speter } 348752Speter 349752Speter /* 350752Speter * Funcext marks the procedure or 351752Speter * function external in the symbol 352752Speter * table. Funcext should only be 353752Speter * called if PC, and is an error 354752Speter * otherwise. 355752Speter */ 356752Speter 357752Speter funcext(fp) 358752Speter struct nl *fp; 359752Speter { 360752Speter 361752Speter #ifdef PC 362752Speter if (opt('s')) { 363752Speter standard(); 364752Speter error("External procedures and functions are not standard"); 365752Speter } else { 366752Speter if (cbn == 1) { 367752Speter fp->ext_flags |= NEXTERN; 368*825Speter stabefunc( fp -> symbol , fp -> class , line ); 369752Speter } 370752Speter else 371752Speter error("External procedures and functions can only be declared at the outermost level."); 372752Speter } 373752Speter #endif PC 374752Speter #ifdef OBJ 375752Speter error("Procedures or functions cannot be declared external."); 376752Speter #endif OBJ 377752Speter 378752Speter return(fp); 379752Speter } 380752Speter 381752Speter /* 382752Speter * Funcbody is called 383752Speter * when the actual (resolved) 384752Speter * declaration of a procedure is 385752Speter * encountered. It puts the names 386752Speter * of the (function) and parameters 387752Speter * into the symbol table. 388752Speter */ 389752Speter funcbody(fp) 390752Speter struct nl *fp; 391752Speter { 392752Speter register struct nl *q, *p; 393752Speter 394752Speter cbn++; 395752Speter if (cbn >= DSPLYSZ) { 396752Speter error("Too many levels of function/procedure nesting"); 397752Speter pexit(ERRS); 398752Speter } 399752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 400752Speter gotos[cbn] = NIL; 401752Speter errcnt[cbn] = syneflg; 402752Speter parts = NIL; 403752Speter dfiles[ cbn ] = FALSE; 404752Speter if (fp == NIL) 405752Speter return (NIL); 406752Speter /* 407752Speter * Save the virtual name 408752Speter * list stack pointer so 409752Speter * the space can be freed 410752Speter * later (funcend). 411752Speter */ 412752Speter fp->ptr[2] = nlp; 413752Speter # ifdef PC 414752Speter if ( fp -> class != PROG ) { 415*825Speter stabfunc( fp -> symbol , fp -> class , line , cbn - 1 ); 416752Speter } else { 417*825Speter stabfunc( "program" , fp -> class , line , 0 ); 418752Speter } 419752Speter # endif PC 420752Speter if (fp->class != PROG) { 421752Speter for (q = fp->chain; q != NIL; q = q->chain) { 422752Speter enter(q); 423752Speter # ifdef PC 424752Speter stabparam( q -> symbol , p2type( q -> type ) 425752Speter , q -> value[ NL_OFFS ] 426752Speter , lwidth( q -> type ) ); 427752Speter # endif PC 428752Speter } 429752Speter } 430752Speter if (fp->class == FUNC) { 431752Speter /* 432752Speter * For functions, enter the fvar 433752Speter */ 434752Speter enter(fp->ptr[NL_FVAR]); 435752Speter # ifdef PC 436752Speter q = fp -> ptr[ NL_FVAR ]; 437752Speter sizes[cbn].om_off -= lwidth( q -> type ); 438752Speter sizes[cbn].om_max = sizes[cbn].om_off; 439*825Speter stabvar( q -> symbol , p2type( q -> type ) , cbn 440*825Speter , q -> value[ NL_OFFS ] , lwidth( q -> type ) 441*825Speter , line ); 442752Speter # endif PC 443752Speter } 444752Speter # ifdef PTREE 445752Speter /* 446752Speter * pick up the pointer to porf declaration 447752Speter */ 448752Speter PorFHeader[ ++nesting ] = fp -> inTree; 449752Speter # endif PTREE 450752Speter return (fp); 451752Speter } 452752Speter 453752Speter struct nl *Fp; 454752Speter int pnumcnt; 455752Speter /* 456752Speter * Funcend is called to 457752Speter * finish a block by generating 458752Speter * the code for the statements. 459752Speter * It then looks for unresolved declarations 460752Speter * of labels, procedures and functions, 461752Speter * and cleans up the name list. 462752Speter * For the program, it checks the 463752Speter * semantics of the program 464752Speter * statement (yuchh). 465752Speter */ 466752Speter funcend(fp, bundle, endline) 467752Speter struct nl *fp; 468752Speter int *bundle; 469752Speter int endline; 470752Speter { 471752Speter register struct nl *p; 472752Speter register int i, b; 473752Speter int var, inp, out, chkref, *blk; 474752Speter struct nl *iop; 475752Speter char *cp; 476752Speter extern int cntstat; 477752Speter # ifdef PC 478752Speter int toplabel = getlab(); 479752Speter int botlabel = getlab(); 480752Speter # endif PC 481752Speter 482752Speter cntstat = 0; 483752Speter /* 484752Speter * yyoutline(); 485752Speter */ 486752Speter if (program != NIL) 487752Speter line = program->value[3]; 488752Speter blk = bundle[2]; 489752Speter if (fp == NIL) { 490752Speter cbn--; 491752Speter # ifdef PTREE 492752Speter nesting--; 493752Speter # endif PTREE 494752Speter return; 495752Speter } 496752Speter #ifdef OBJ 497752Speter /* 498752Speter * Patch the branch to the 499752Speter * entry point of the function 500752Speter */ 501752Speter patch4(fp->entloc); 502752Speter /* 503752Speter * Put out the block entrance code and the block name. 504752Speter * the CONG is overlaid by a patch later! 505752Speter */ 506752Speter var = put(2, (lenstr(fp->symbol,0) << 8) 507752Speter | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), 0); 508752Speter put(2, O_CASE2, bundle[1]); 509752Speter putstr(fp->symbol, 0); 510752Speter #endif OBJ 511752Speter #ifdef PC 512752Speter /* 513752Speter * put out the procedure entry code 514752Speter */ 515752Speter if ( fp -> class == PROG ) { 516752Speter putprintf( " .text" , 0 ); 517752Speter putprintf( " .align 1" , 0 ); 518752Speter putprintf( " .globl _main" , 0 ); 519752Speter putprintf( "_main:" , 0 ); 520752Speter putprintf( " .word 0" , 0 ); 521752Speter putprintf( " calls $0,_PCSTART" , 0 ); 522752Speter putprintf( " movl 4(ap),__argc" , 0 ); 523752Speter putprintf( " movl 8(ap),__argv" , 0 ); 524752Speter putprintf( " calls $0,_program" , 0 ); 525752Speter putprintf( " calls $0,_PCEXIT" , 0 ); 526752Speter ftnno = fp -> entloc; 527752Speter putprintf( " .text" , 0 ); 528752Speter putprintf( " .align 1" , 0 ); 529752Speter putprintf( " .globl _program" , 0 ); 530752Speter putprintf( "_program:" , 0 ); 531752Speter } else { 532752Speter ftnno = fp -> entloc; 533752Speter putprintf( " .text" , 0 ); 534752Speter putprintf( " .align 1" , 0 ); 535752Speter putprintf( " .globl " , 1 ); 536752Speter for ( i = 1 ; i < cbn ; i++ ) { 537752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 538752Speter } 539752Speter putprintf( "" , 0 ); 540752Speter for ( i = 1 ; i < cbn ; i++ ) { 541752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 542752Speter } 543752Speter putprintf( ":" , 0 ); 544752Speter } 545752Speter stablbrac( cbn ); 546752Speter /* 547752Speter * register save mask 548752Speter */ 549752Speter if ( opt( 't' ) ) { 550752Speter putprintf( " .word 0x%x" , 0 , RUNCHECK | RSAVEMASK ); 551752Speter } else { 552752Speter putprintf( " .word 0x%x" , 0 , RSAVEMASK ); 553752Speter } 554752Speter putjbr( botlabel ); 555752Speter putlab( toplabel ); 556752Speter if ( profflag ) { 557752Speter /* 558752Speter * call mcount for profiling 559752Speter */ 560752Speter putprintf( " moval 1f,r0" , 0 ); 561752Speter putprintf( " jsb mcount" , 0 ); 562752Speter putprintf( " .data" , 0 ); 563752Speter putprintf( " .align 2" , 0 ); 564752Speter putprintf( "1:" , 0 ); 565752Speter putprintf( " .long 0" , 0 ); 566752Speter putprintf( " .text" , 0 ); 567752Speter } 568752Speter /* 569752Speter * set up unwind exception vector. 570752Speter */ 571752Speter putprintf( " moval %s,%d(%s)" , 0 572752Speter , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); 573752Speter /* 574752Speter * save address of display entry, for unwind. 575752Speter */ 576752Speter putprintf( " moval %s+%d,%d(%s)" , 0 577752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 578752Speter , DPTROFFSET , P2FPNAME ); 579752Speter /* 580752Speter * save old display 581752Speter */ 582752Speter putprintf( " movq %s+%d,%d(%s)" , 0 583752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 584752Speter , DSAVEOFFSET , P2FPNAME ); 585752Speter /* 586752Speter * set up new display by saving AP and FP in appropriate 587752Speter * slot in display structure. 588752Speter */ 589752Speter putprintf( " movq %s,%s+%d" , 0 590752Speter , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 591752Speter /* 592752Speter * ask second pass to allocate known locals 593752Speter */ 594752Speter putlbracket( ftnno , -sizes[ cbn ].om_max ); 595752Speter /* 596752Speter * and zero them if checking is on 597752Speter * by calling zframe( bytes of locals , highest local address ); 598752Speter */ 599752Speter if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 600752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 601752Speter , "_ZFRAME" ); 602752Speter putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 603752Speter , 0 , P2INT , 0 ); 604752Speter putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); 605752Speter putop( P2LISTOP , P2INT ); 606752Speter putop( P2CALL , P2INT ); 607752Speter putdot( filename , line ); 608752Speter } 609752Speter #endif PC 610752Speter if ( monflg ) { 611752Speter if ( fp -> value[ NL_CNTR ] != 0 ) { 612752Speter inccnt( fp -> value [ NL_CNTR ] ); 613752Speter } 614752Speter inccnt( bodycnts[ fp -> nl_block & 037 ] ); 615752Speter } 616752Speter if (fp->class == PROG) { 617752Speter /* 618752Speter * The glorious buffers option. 619752Speter * 0 = don't buffer output 620752Speter * 1 = line buffer output 621752Speter * 2 = 512 byte buffer output 622752Speter */ 623752Speter # ifdef OBJ 624752Speter if (opt('b') != 1) 625752Speter put(1, O_BUFF | opt('b') << 8); 626752Speter # endif OBJ 627752Speter # ifdef PC 628752Speter if ( opt( 'b' ) != 1 ) { 629752Speter putleaf( P2ICON , 0 , 0 630752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 631752Speter putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 632752Speter putop( P2CALL , P2INT ); 633752Speter putdot( filename , line ); 634752Speter } 635752Speter # endif PC 636752Speter out = 0; 637752Speter for (p = fp->chain; p != NIL; p = p->chain) { 638752Speter if (strcmp(p->symbol, "input") == 0) { 639752Speter inp++; 640752Speter continue; 641752Speter } 642752Speter if (strcmp(p->symbol, "output") == 0) { 643752Speter out++; 644752Speter continue; 645752Speter } 646752Speter iop = lookup1(p->symbol); 647752Speter if (iop == NIL || bn != cbn) { 648752Speter error("File %s listed in program statement but not declared", p->symbol); 649752Speter continue; 650752Speter } 651752Speter if (iop->class != VAR) { 652752Speter error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 653752Speter continue; 654752Speter } 655752Speter if (iop->type == NIL) 656752Speter continue; 657752Speter if (iop->type->class != FILET) { 658752Speter error("File %s listed in program statement but defined as %s", 659752Speter p->symbol, nameof(iop->type)); 660752Speter continue; 661752Speter } 662752Speter # ifdef OBJ 663752Speter put(2, O_LV | bn << 8+INDX, iop->value[NL_OFFS]); 664752Speter i = lenstr(p->symbol,0); 665752Speter put(2, O_LVCON, i); 666752Speter putstr(p->symbol, 0); 667752Speter do { 668752Speter i--; 669752Speter } while (p->symbol+i == 0); 670752Speter put(2, O_CON24, i+1); 671752Speter put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 672752Speter put(1, O_DEFNAME); 673752Speter # endif OBJ 674752Speter # ifdef PC 675752Speter putleaf( P2ICON , 0 , 0 676752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 677752Speter , "_DEFNAME" ); 678752Speter putLV( p -> symbol , bn , iop -> value[NL_OFFS] 679752Speter , p2type( iop ) ); 680752Speter putCONG( p -> symbol , strlen( p -> symbol ) 681752Speter , LREQ ); 682752Speter putop( P2LISTOP , P2INT ); 683752Speter putleaf( P2ICON , strlen( p -> symbol ) 684752Speter , 0 , P2INT , 0 ); 685752Speter putop( P2LISTOP , P2INT ); 686752Speter putleaf( P2ICON 687752Speter , text(iop->type) ? 0 : width(iop->type->type) 688752Speter , 0 , P2INT , 0 ); 689752Speter putop( P2LISTOP , P2INT ); 690752Speter putop( P2CALL , P2INT ); 691752Speter putdot( filename , line ); 692752Speter # endif PC 693752Speter } 694752Speter if (out == 0 && fp->chain != NIL) { 695752Speter recovered(); 696752Speter error("The file output must appear in the program statement file list"); 697752Speter } 698752Speter } 699752Speter /* 700752Speter * Process the prog/proc/func body 701752Speter */ 702752Speter noreach = 0; 703752Speter line = bundle[1]; 704752Speter statlist(blk); 705752Speter # ifdef PTREE 706752Speter { 707752Speter pPointer Body = tCopy( blk ); 708752Speter 709752Speter pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 710752Speter } 711752Speter # endif PTREE 712752Speter # ifdef OBJ 713752Speter if (cbn== 1 && monflg != 0) { 714752Speter patchfil(cntpatch - 2, cnts, 2); 715752Speter patchfil(nfppatch - 2, pfcnt, 2); 716752Speter } 717752Speter # endif OBJ 718752Speter # ifdef PC 719752Speter if ( fp -> class == PROG && monflg ) { 720752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 721752Speter , "_PMFLUSH" ); 722752Speter putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 723752Speter putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 724752Speter putop( P2LISTOP , P2INT ); 725752Speter putop( P2CALL , P2INT ); 726752Speter putdot( filename , line ); 727752Speter } 728752Speter # endif PC 729752Speter if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 730752Speter recovered(); 731752Speter error("Input is used but not defined in the program statement"); 732752Speter } 733752Speter /* 734752Speter * Clean up the symbol table displays and check for unresolves 735752Speter */ 736752Speter line = endline; 737752Speter b = cbn; 738752Speter Fp = fp; 739752Speter chkref = syneflg == errcnt[cbn] && opt('w') == 0; 740752Speter for (i = 0; i <= 077; i++) { 741752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 742752Speter /* 743752Speter * Check for variables defined 744752Speter * but not referenced 745752Speter */ 746752Speter if (chkref && p->symbol != NIL) 747752Speter switch (p->class) { 748752Speter case FIELD: 749752Speter /* 750752Speter * If the corresponding record is 751752Speter * unused, we shouldn't complain about 752752Speter * the fields. 753752Speter */ 754752Speter default: 755752Speter if ((p->nl_flags & (NUSED|NMOD)) == 0) { 756752Speter warning(); 757752Speter nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 758752Speter break; 759752Speter } 760752Speter /* 761752Speter * If a var parameter is either 762752Speter * modified or used that is enough. 763752Speter */ 764752Speter if (p->class == REF) 765752Speter continue; 766752Speter # ifdef OBJ 767752Speter if ((p->nl_flags & NUSED) == 0) { 768752Speter warning(); 769752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 770752Speter break; 771752Speter } 772752Speter # endif OBJ 773752Speter # ifdef PC 774752Speter if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { 775752Speter warning(); 776752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 777752Speter break; 778752Speter } 779752Speter # endif PC 780752Speter if ((p->nl_flags & NMOD) == 0) { 781752Speter warning(); 782752Speter nerror("%s %s is used but never set", classes[p->class], p->symbol); 783752Speter break; 784752Speter } 785752Speter case LABEL: 786752Speter case FVAR: 787752Speter case BADUSE: 788752Speter break; 789752Speter } 790752Speter switch (p->class) { 791752Speter case BADUSE: 792752Speter cp = "s"; 793752Speter if (p->chain->ud_next == NIL) 794752Speter cp++; 795752Speter eholdnl(); 796752Speter if (p->value[NL_KINDS] & ISUNDEF) 797752Speter nerror("%s undefined on line%s", p->symbol, cp); 798752Speter else 799752Speter nerror("%s improperly used on line%s", p->symbol, cp); 800752Speter pnumcnt = 10; 801752Speter pnums(p->chain); 802752Speter pchr('\n'); 803752Speter break; 804752Speter 805752Speter case FUNC: 806752Speter case PROC: 807752Speter # ifdef OBJ 808752Speter if ((p->nl_flags & NFORWD)) 809752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 810752Speter # endif OBJ 811752Speter # ifdef PC 812752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 813752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 814752Speter # endif PC 815752Speter break; 816752Speter 817752Speter case LABEL: 818752Speter if (p->nl_flags & NFORWD) 819752Speter nerror("label %s was declared but not defined", p->symbol); 820752Speter break; 821752Speter case FVAR: 822752Speter if ((p->nl_flags & NMOD) == 0) 823752Speter nerror("No assignment to the function variable"); 824752Speter break; 825752Speter } 826752Speter } 827752Speter /* 828752Speter * Pop this symbol 829752Speter * table slot 830752Speter */ 831752Speter disptab[i] = p; 832752Speter } 833752Speter 834752Speter # ifdef OBJ 835752Speter put(1, O_END); 836752Speter # endif OBJ 837752Speter # ifdef PC 838752Speter /* 839752Speter * if there were file variables declared at this level 840752Speter * call pclose( &__disply[ cbn ] ) to clean them up. 841752Speter */ 842752Speter if ( dfiles[ cbn ] ) { 843752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 844752Speter , "_PCLOSE" ); 845752Speter putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) 846752Speter , P2PTR | P2CHAR ); 847752Speter putop( P2CALL , P2INT ); 848752Speter putdot( filename , line ); 849752Speter } 850752Speter /* 851752Speter * if this is a function, 852752Speter * the function variable is the return value. 853752Speter * if it's a scalar valued function, return scalar, 854752Speter * else, return a pointer to the structure value. 855752Speter */ 856752Speter if ( fp -> class == FUNC ) { 857752Speter struct nl *fvar = fp -> ptr[ NL_FVAR ]; 858752Speter long fvartype = p2type( fvar -> type ); 859752Speter 860752Speter switch ( classify( fvar -> type ) ) { 861752Speter case TBOOL: 862752Speter case TCHAR: 863752Speter case TINT: 864752Speter case TSCAL: 865752Speter case TDOUBLE: 866752Speter case TPTR: 867752Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 868752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 869752Speter break; 870752Speter default: 871752Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 872752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 873752Speter break; 874752Speter } 875752Speter putop( P2FORCE , fvartype ); 876752Speter putdot( filename , line ); 877752Speter } 878752Speter /* 879752Speter * restore old display entry from save area 880752Speter */ 881752Speter 882752Speter putprintf( " movq %d(%s),%s+%d" , 0 883752Speter , DSAVEOFFSET , P2FPNAME 884752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 885752Speter stabrbrac( cbn ); 886752Speter putprintf( " ret" , 0 ); 887752Speter /* 888752Speter * let the second pass allocate locals 889752Speter */ 890752Speter putlab( botlabel ); 891752Speter putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 892752Speter putrbracket( ftnno ); 893752Speter putjbr( toplabel ); 894752Speter /* 895752Speter * declare pcp counters, if any 896752Speter */ 897752Speter if ( monflg && fp -> class == PROG ) { 898752Speter putprintf( " .data" , 0 ); 899752Speter putprintf( " .comm " , 1 ); 900752Speter putprintf( PCPCOUNT , 1 ); 901752Speter putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 902752Speter putprintf( " .text" , 0 ); 903752Speter } 904752Speter # endif PC 905752Speter #ifdef DEBUG 906752Speter dumpnl(fp->ptr[2], fp->symbol); 907752Speter #endif 908752Speter /* 909752Speter * Restore the 910752Speter * (virtual) name list 911752Speter * position 912752Speter */ 913752Speter nlfree(fp->ptr[2]); 914752Speter /* 915752Speter * Proc/func has been 916752Speter * resolved 917752Speter */ 918752Speter fp->nl_flags &= ~NFORWD; 919752Speter /* 920752Speter * Patch the beg 921752Speter * of the proc/func to 922752Speter * the proper variable size 923752Speter */ 924752Speter if (Fp == NIL) 925752Speter elineon(); 926752Speter # ifdef OBJ 927752Speter patchfil(var, sizes[cbn].om_max, 2); 928752Speter # endif OBJ 929752Speter cbn--; 930752Speter if (inpflist(fp->symbol)) { 931752Speter opop('l'); 932752Speter } 933752Speter } 934752Speter 935752Speter 936752Speter /* 937752Speter * Segend is called to check for 938752Speter * unresolved variables, funcs and 939752Speter * procs, and deliver unresolved and 940752Speter * baduse error diagnostics at the 941752Speter * end of a routine segment (a separately 942752Speter * compiled segment that is not the 943752Speter * main program) for PC. This 944752Speter * routine should only be called 945752Speter * by PC (not standard). 946752Speter */ 947752Speter segend() 948752Speter { 949752Speter register struct nl *p; 950752Speter register int i,b; 951752Speter char *cp; 952752Speter 953752Speter #ifdef PC 954752Speter if (opt('s')) { 955752Speter standard(); 956752Speter error("Separately compiled routine segments are not standard."); 957752Speter } else { 958752Speter b = cbn; 959752Speter for (i=0; i<077; i++) { 960752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 961752Speter switch (p->class) { 962752Speter case BADUSE: 963752Speter cp = 's'; 964752Speter if (p->chain->ud_next == NIL) 965752Speter cp++; 966752Speter eholdnl(); 967752Speter if (p->value[NL_KINDS] & ISUNDEF) 968752Speter nerror("%s undefined on line%s", p->symbol, cp); 969752Speter else 970752Speter nerror("%s improperly used on line%s", p->symbol, cp); 971752Speter pnumcnt = 10; 972752Speter pnums(p->chain); 973752Speter pchr('\n'); 974752Speter break; 975752Speter 976752Speter case FUNC: 977752Speter case PROC: 978752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 979752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 980752Speter break; 981752Speter 982752Speter case FVAR: 983752Speter if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0)) 984752Speter nerror("No assignment to the function variable"); 985752Speter break; 986752Speter } 987752Speter } 988752Speter disptab[i] = p; 989752Speter } 990752Speter } 991752Speter #endif PC 992752Speter #ifdef OBJ 993752Speter error("Missing program statement and program body"); 994752Speter #endif OBJ 995752Speter 996752Speter } 997752Speter 998752Speter 999752Speter /* 1000752Speter * Level1 does level one processing for 1001752Speter * separately compiled routine segments 1002752Speter */ 1003752Speter level1() 1004752Speter { 1005752Speter 1006752Speter # ifdef OBJ 1007752Speter error("Missing program statement"); 1008752Speter # endif OBJ 1009752Speter # ifdef PC 1010752Speter if (opt('s')) { 1011752Speter standard(); 1012752Speter error("Missing program statement"); 1013752Speter } 1014752Speter # endif PC 1015752Speter 1016752Speter cbn++; 1017752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 1018752Speter parts = NIL; 1019752Speter progseen++; 1020752Speter } 1021752Speter 1022752Speter 1023752Speter 1024752Speter pnums(p) 1025752Speter struct udinfo *p; 1026752Speter { 1027752Speter 1028752Speter if (p->ud_next != NIL) 1029752Speter pnums(p->ud_next); 1030752Speter if (pnumcnt == 0) { 1031752Speter printf("\n\t"); 1032752Speter pnumcnt = 20; 1033752Speter } 1034752Speter pnumcnt--; 1035752Speter printf(" %d", p->ud_line); 1036752Speter } 1037752Speter 1038752Speter nerror(a1, a2, a3) 1039752Speter { 1040752Speter 1041752Speter if (Fp != NIL) { 1042752Speter yySsync(); 1043752Speter #ifndef PI1 1044752Speter if (opt('l')) 1045752Speter yyoutline(); 1046752Speter #endif 1047752Speter yysetfile(filename); 1048752Speter printf("In %s %s:\n", classes[Fp->class], Fp->symbol); 1049752Speter Fp = NIL; 1050752Speter elineoff(); 1051752Speter } 1052752Speter error(a1, a2, a3); 1053752Speter } 1054