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