1752Speter /* Copyright (c) 1979 Regents of the University of California */ 2752Speter 3*1196Speter static char sccsid[] = "@(#)fdec.c 1.4 10/03/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++; 54834Speter 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: 141*1196Speter if (opt('s')) { 142752Speter standard(); 143*1196Speter error("Functions should not return %ss", clnames[o]); 144*1196Speter } 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: 259*1196Speter # ifdef OBJ 260*1196Speter dp = defnl(il[1], FFUNC, p, o -= sizeof ( int * ) ); 261*1196Speter # endif OBJ 262*1196Speter # ifdef PC 263*1196Speter dp = defnl( il[1] , FFUNC , p 264*1196Speter , o = roundup( o , A_STACK ) ); 265*1196Speter o += sizeof(char *); 266*1196Speter # endif PC 267*1196Speter dp -> nl_flags |= NMOD; 268*1196Speter break; 269752Speter case T_PPROC: 270*1196Speter # ifdef OBJ 271*1196Speter dp = defnl(il[1], FPROC, p, o -= sizeof ( int * ) ); 272*1196Speter # endif OBJ 273*1196Speter # ifdef PC 274*1196Speter dp = defnl( il[1] , FPROC , p 275*1196Speter , o = roundup( o , A_STACK ) ); 276*1196Speter o += sizeof(char *); 277*1196Speter # endif PC 278*1196Speter dp -> nl_flags |= NMOD; 279*1196Speter break; 280752Speter } 281752Speter if (dp != NIL) { 282752Speter cp->chain = dp; 283752Speter cp = dp; 284752Speter } 285752Speter } 286752Speter } 287752Speter cbn--; 288752Speter p = sp; 289752Speter # ifdef OBJ 290752Speter p->value[NL_OFFS] = -o+DPOFF2; 291752Speter /* 292752Speter * Correct the naivete (naievity) 293752Speter * of our above code to 294752Speter * calculate offsets 295752Speter */ 296752Speter for (il = p->chain; il != NIL; il = il->chain) 297752Speter il->value[NL_OFFS] += p->value[NL_OFFS]; 298752Speter # endif OBJ 299752Speter # ifdef PC 300752Speter p -> value[ NL_OFFS ] = o; 301752Speter # endif PC 302752Speter } else { 303752Speter /* 304752Speter * The wonderful 305752Speter * program statement! 306752Speter */ 307752Speter # ifdef OBJ 308752Speter if (monflg) { 309752Speter put(1, O_PXPBUF); 310752Speter cntpatch = put(2, O_CASE4, 0); 311752Speter nfppatch = put(2, O_CASE4, 0); 312752Speter } 313752Speter # endif OBJ 314752Speter cp = p; 315752Speter for (rl = r[3]; rl; rl = rl[2]) { 316752Speter if (rl[1] == NIL) 317752Speter continue; 318752Speter dp = defnl(rl[1], VAR, 0, 0); 319752Speter cp->chain = dp; 320752Speter cp = dp; 321752Speter } 322752Speter } 323752Speter /* 324752Speter * Define a branch at 325752Speter * the "entry point" of 326752Speter * the prog/proc/func. 327752Speter */ 328752Speter p->entloc = getlab(); 329752Speter if (monflg) { 330752Speter bodycnts[ cbn ] = getcnt(); 331752Speter p->value[ NL_CNTR ] = 0; 332752Speter } 333752Speter # ifdef OBJ 334752Speter put(2, O_TRA4, p->entloc); 335752Speter # endif OBJ 336752Speter # ifdef PTREE 337752Speter { 338752Speter pPointer PF = tCopy( r ); 339752Speter 340752Speter pSeize( PorFHeader[ nesting ] ); 341752Speter if ( r[0] != T_PROG ) { 342752Speter pPointer *PFs; 343752Speter 344752Speter PFs = &( pDEF( PorFHeader[ nesting ] ).PorFPFs ); 345752Speter *PFs = ListAppend( *PFs , PF ); 346752Speter } else { 347752Speter pDEF( PorFHeader[ nesting ] ).GlobProg = PF; 348752Speter } 349752Speter pRelease( PorFHeader[ nesting ] ); 350752Speter } 351752Speter # endif PTREE 352752Speter return (p); 353752Speter } 354752Speter 355752Speter funcfwd(fp) 356752Speter struct nl *fp; 357752Speter { 358752Speter 359752Speter /* 360752Speter * save the counter for this function 361752Speter */ 362752Speter if ( monflg ) { 363752Speter fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; 364752Speter } 365752Speter return (fp); 366752Speter } 367752Speter 368752Speter /* 369752Speter * Funcext marks the procedure or 370752Speter * function external in the symbol 371752Speter * table. Funcext should only be 372752Speter * called if PC, and is an error 373752Speter * otherwise. 374752Speter */ 375752Speter 376752Speter funcext(fp) 377752Speter struct nl *fp; 378752Speter { 379752Speter 380752Speter #ifdef PC 381752Speter if (opt('s')) { 382752Speter standard(); 383752Speter error("External procedures and functions are not standard"); 384752Speter } else { 385752Speter if (cbn == 1) { 386752Speter fp->ext_flags |= NEXTERN; 387825Speter stabefunc( fp -> symbol , fp -> class , line ); 388752Speter } 389752Speter else 390752Speter error("External procedures and functions can only be declared at the outermost level."); 391752Speter } 392752Speter #endif PC 393752Speter #ifdef OBJ 394752Speter error("Procedures or functions cannot be declared external."); 395752Speter #endif OBJ 396752Speter 397752Speter return(fp); 398752Speter } 399752Speter 400752Speter /* 401752Speter * Funcbody is called 402752Speter * when the actual (resolved) 403752Speter * declaration of a procedure is 404752Speter * encountered. It puts the names 405752Speter * of the (function) and parameters 406752Speter * into the symbol table. 407752Speter */ 408752Speter funcbody(fp) 409752Speter struct nl *fp; 410752Speter { 411752Speter register struct nl *q, *p; 412752Speter 413752Speter cbn++; 414752Speter if (cbn >= DSPLYSZ) { 415752Speter error("Too many levels of function/procedure nesting"); 416752Speter pexit(ERRS); 417752Speter } 418752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 419752Speter gotos[cbn] = NIL; 420752Speter errcnt[cbn] = syneflg; 421834Speter parts[ cbn ] = NIL; 422752Speter dfiles[ cbn ] = FALSE; 423752Speter if (fp == NIL) 424752Speter return (NIL); 425752Speter /* 426752Speter * Save the virtual name 427752Speter * list stack pointer so 428752Speter * the space can be freed 429752Speter * later (funcend). 430752Speter */ 431752Speter fp->ptr[2] = nlp; 432752Speter # ifdef PC 433752Speter if ( fp -> class != PROG ) { 434825Speter stabfunc( fp -> symbol , fp -> class , line , cbn - 1 ); 435752Speter } else { 436825Speter stabfunc( "program" , fp -> class , line , 0 ); 437752Speter } 438752Speter # endif PC 439752Speter if (fp->class != PROG) { 440752Speter for (q = fp->chain; q != NIL; q = q->chain) { 441752Speter enter(q); 442752Speter # ifdef PC 443752Speter stabparam( q -> symbol , p2type( q -> type ) 444752Speter , q -> value[ NL_OFFS ] 445752Speter , lwidth( q -> type ) ); 446752Speter # endif PC 447752Speter } 448752Speter } 449752Speter if (fp->class == FUNC) { 450752Speter /* 451752Speter * For functions, enter the fvar 452752Speter */ 453752Speter enter(fp->ptr[NL_FVAR]); 454752Speter # ifdef PC 455752Speter q = fp -> ptr[ NL_FVAR ]; 456752Speter sizes[cbn].om_off -= lwidth( q -> type ); 457752Speter sizes[cbn].om_max = sizes[cbn].om_off; 458825Speter stabvar( q -> symbol , p2type( q -> type ) , cbn 459825Speter , q -> value[ NL_OFFS ] , lwidth( q -> type ) 460825Speter , line ); 461752Speter # endif PC 462752Speter } 463752Speter # ifdef PTREE 464752Speter /* 465752Speter * pick up the pointer to porf declaration 466752Speter */ 467752Speter PorFHeader[ ++nesting ] = fp -> inTree; 468752Speter # endif PTREE 469752Speter return (fp); 470752Speter } 471752Speter 472752Speter struct nl *Fp; 473752Speter int pnumcnt; 474752Speter /* 475752Speter * Funcend is called to 476752Speter * finish a block by generating 477752Speter * the code for the statements. 478752Speter * It then looks for unresolved declarations 479752Speter * of labels, procedures and functions, 480752Speter * and cleans up the name list. 481752Speter * For the program, it checks the 482752Speter * semantics of the program 483752Speter * statement (yuchh). 484752Speter */ 485752Speter funcend(fp, bundle, endline) 486752Speter struct nl *fp; 487752Speter int *bundle; 488752Speter int endline; 489752Speter { 490752Speter register struct nl *p; 491752Speter register int i, b; 492752Speter int var, inp, out, chkref, *blk; 493752Speter struct nl *iop; 494752Speter char *cp; 495752Speter extern int cntstat; 496752Speter # ifdef PC 497752Speter int toplabel = getlab(); 498752Speter int botlabel = getlab(); 499752Speter # endif PC 500752Speter 501752Speter cntstat = 0; 502752Speter /* 503752Speter * yyoutline(); 504752Speter */ 505752Speter if (program != NIL) 506752Speter line = program->value[3]; 507752Speter blk = bundle[2]; 508752Speter if (fp == NIL) { 509752Speter cbn--; 510752Speter # ifdef PTREE 511752Speter nesting--; 512752Speter # endif PTREE 513752Speter return; 514752Speter } 515752Speter #ifdef OBJ 516752Speter /* 517752Speter * Patch the branch to the 518752Speter * entry point of the function 519752Speter */ 520752Speter patch4(fp->entloc); 521752Speter /* 522752Speter * Put out the block entrance code and the block name. 523752Speter * the CONG is overlaid by a patch later! 524752Speter */ 525752Speter var = put(2, (lenstr(fp->symbol,0) << 8) 526752Speter | (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), 0); 527*1196Speter /* 528*1196Speter * output the number of bytes of arguments 529*1196Speter * this is only checked on formal calls. 530*1196Speter */ 531*1196Speter put(2, O_CASE4, cbn == 1 ? 0 : fp->value[NL_OFFS]-DPOFF2); 532752Speter put(2, O_CASE2, bundle[1]); 533752Speter putstr(fp->symbol, 0); 534752Speter #endif OBJ 535752Speter #ifdef PC 536752Speter /* 537752Speter * put out the procedure entry code 538752Speter */ 539752Speter if ( fp -> class == PROG ) { 540752Speter putprintf( " .text" , 0 ); 541752Speter putprintf( " .align 1" , 0 ); 542752Speter putprintf( " .globl _main" , 0 ); 543752Speter putprintf( "_main:" , 0 ); 544752Speter putprintf( " .word 0" , 0 ); 545752Speter putprintf( " calls $0,_PCSTART" , 0 ); 546752Speter putprintf( " movl 4(ap),__argc" , 0 ); 547752Speter putprintf( " movl 8(ap),__argv" , 0 ); 548752Speter putprintf( " calls $0,_program" , 0 ); 549752Speter putprintf( " calls $0,_PCEXIT" , 0 ); 550752Speter ftnno = fp -> entloc; 551752Speter putprintf( " .text" , 0 ); 552752Speter putprintf( " .align 1" , 0 ); 553752Speter putprintf( " .globl _program" , 0 ); 554752Speter putprintf( "_program:" , 0 ); 555752Speter } else { 556752Speter ftnno = fp -> entloc; 557752Speter putprintf( " .text" , 0 ); 558752Speter putprintf( " .align 1" , 0 ); 559752Speter putprintf( " .globl " , 1 ); 560752Speter for ( i = 1 ; i < cbn ; i++ ) { 561752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 562752Speter } 563752Speter putprintf( "" , 0 ); 564752Speter for ( i = 1 ; i < cbn ; i++ ) { 565752Speter putprintf( EXTFORMAT , 1 , enclosing[ i ] ); 566752Speter } 567752Speter putprintf( ":" , 0 ); 568752Speter } 569752Speter stablbrac( cbn ); 570752Speter /* 571752Speter * register save mask 572752Speter */ 573752Speter if ( opt( 't' ) ) { 574752Speter putprintf( " .word 0x%x" , 0 , RUNCHECK | RSAVEMASK ); 575752Speter } else { 576752Speter putprintf( " .word 0x%x" , 0 , RSAVEMASK ); 577752Speter } 578752Speter putjbr( botlabel ); 579752Speter putlab( toplabel ); 580752Speter if ( profflag ) { 581752Speter /* 582752Speter * call mcount for profiling 583752Speter */ 584752Speter putprintf( " moval 1f,r0" , 0 ); 585752Speter putprintf( " jsb mcount" , 0 ); 586752Speter putprintf( " .data" , 0 ); 587752Speter putprintf( " .align 2" , 0 ); 588752Speter putprintf( "1:" , 0 ); 589752Speter putprintf( " .long 0" , 0 ); 590752Speter putprintf( " .text" , 0 ); 591752Speter } 592752Speter /* 593752Speter * set up unwind exception vector. 594752Speter */ 595752Speter putprintf( " moval %s,%d(%s)" , 0 596752Speter , UNWINDNAME , UNWINDOFFSET , P2FPNAME ); 597752Speter /* 598752Speter * save address of display entry, for unwind. 599752Speter */ 600752Speter putprintf( " moval %s+%d,%d(%s)" , 0 601752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 602752Speter , DPTROFFSET , P2FPNAME ); 603752Speter /* 604752Speter * save old display 605752Speter */ 606752Speter putprintf( " movq %s+%d,%d(%s)" , 0 607752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) 608752Speter , DSAVEOFFSET , P2FPNAME ); 609752Speter /* 610752Speter * set up new display by saving AP and FP in appropriate 611752Speter * slot in display structure. 612752Speter */ 613752Speter putprintf( " movq %s,%s+%d" , 0 614752Speter , P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 615752Speter /* 616752Speter * ask second pass to allocate known locals 617752Speter */ 618752Speter putlbracket( ftnno , -sizes[ cbn ].om_max ); 619752Speter /* 620752Speter * and zero them if checking is on 621752Speter * by calling zframe( bytes of locals , highest local address ); 622752Speter */ 623*1196Speter if ( opt( 't' ) ) { 624*1196Speter if ( ( -sizes[ cbn ].om_max ) > DPOFF1 ) { 625*1196Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 626*1196Speter , "_ZFRAME" ); 627*1196Speter putleaf( P2ICON , ( -sizes[ cbn ].om_max ) - DPOFF1 628*1196Speter , 0 , P2INT , 0 ); 629*1196Speter putLV( 0 , cbn , sizes[ cbn ].om_max , P2CHAR ); 630*1196Speter putop( P2LISTOP , P2INT ); 631*1196Speter putop( P2CALL , P2INT ); 632*1196Speter putdot( filename , line ); 633*1196Speter } 634*1196Speter /* 635*1196Speter * check number of longs of arguments 636*1196Speter * this can only be wrong for formal calls. 637*1196Speter */ 638*1196Speter if ( fp -> class != PROG ) { 639*1196Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2PTR , P2FTN | P2INT ) , 640*1196Speter "_NARGCHK" ); 641*1196Speter putleaf( P2ICON , 642*1196Speter (fp->value[NL_OFFS] - DPOFF2) / sizeof(long) , 643*1196Speter 0 , P2INT , 0 ); 644*1196Speter putop( P2CALL , P2INT ); 645*1196Speter putdot( filename , line ); 646*1196Speter } 647752Speter } 648752Speter #endif PC 649752Speter if ( monflg ) { 650752Speter if ( fp -> value[ NL_CNTR ] != 0 ) { 651752Speter inccnt( fp -> value [ NL_CNTR ] ); 652752Speter } 653752Speter inccnt( bodycnts[ fp -> nl_block & 037 ] ); 654752Speter } 655752Speter if (fp->class == PROG) { 656752Speter /* 657752Speter * The glorious buffers option. 658752Speter * 0 = don't buffer output 659752Speter * 1 = line buffer output 660752Speter * 2 = 512 byte buffer output 661752Speter */ 662752Speter # ifdef OBJ 663752Speter if (opt('b') != 1) 664752Speter put(1, O_BUFF | opt('b') << 8); 665752Speter # endif OBJ 666752Speter # ifdef PC 667752Speter if ( opt( 'b' ) != 1 ) { 668752Speter putleaf( P2ICON , 0 , 0 669752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" ); 670752Speter putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 ); 671752Speter putop( P2CALL , P2INT ); 672752Speter putdot( filename , line ); 673752Speter } 674752Speter # endif PC 675752Speter out = 0; 676752Speter for (p = fp->chain; p != NIL; p = p->chain) { 677752Speter if (strcmp(p->symbol, "input") == 0) { 678752Speter inp++; 679752Speter continue; 680752Speter } 681752Speter if (strcmp(p->symbol, "output") == 0) { 682752Speter out++; 683752Speter continue; 684752Speter } 685752Speter iop = lookup1(p->symbol); 686752Speter if (iop == NIL || bn != cbn) { 687752Speter error("File %s listed in program statement but not declared", p->symbol); 688752Speter continue; 689752Speter } 690752Speter if (iop->class != VAR) { 691752Speter error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]); 692752Speter continue; 693752Speter } 694752Speter if (iop->type == NIL) 695752Speter continue; 696752Speter if (iop->type->class != FILET) { 697752Speter error("File %s listed in program statement but defined as %s", 698752Speter p->symbol, nameof(iop->type)); 699752Speter continue; 700752Speter } 701752Speter # ifdef OBJ 702752Speter put(2, O_LV | bn << 8+INDX, iop->value[NL_OFFS]); 703752Speter i = lenstr(p->symbol,0); 704752Speter put(2, O_LVCON, i); 705752Speter putstr(p->symbol, 0); 706752Speter do { 707752Speter i--; 708752Speter } while (p->symbol+i == 0); 709752Speter put(2, O_CON24, i+1); 710752Speter put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type)); 711752Speter put(1, O_DEFNAME); 712752Speter # endif OBJ 713752Speter # ifdef PC 714752Speter putleaf( P2ICON , 0 , 0 715752Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 716752Speter , "_DEFNAME" ); 717752Speter putLV( p -> symbol , bn , iop -> value[NL_OFFS] 718752Speter , p2type( iop ) ); 719752Speter putCONG( p -> symbol , strlen( p -> symbol ) 720752Speter , LREQ ); 721752Speter putop( P2LISTOP , P2INT ); 722752Speter putleaf( P2ICON , strlen( p -> symbol ) 723752Speter , 0 , P2INT , 0 ); 724752Speter putop( P2LISTOP , P2INT ); 725752Speter putleaf( P2ICON 726752Speter , text(iop->type) ? 0 : width(iop->type->type) 727752Speter , 0 , P2INT , 0 ); 728752Speter putop( P2LISTOP , P2INT ); 729752Speter putop( P2CALL , P2INT ); 730752Speter putdot( filename , line ); 731752Speter # endif PC 732752Speter } 733752Speter if (out == 0 && fp->chain != NIL) { 734752Speter recovered(); 735752Speter error("The file output must appear in the program statement file list"); 736752Speter } 737752Speter } 738752Speter /* 739752Speter * Process the prog/proc/func body 740752Speter */ 741752Speter noreach = 0; 742752Speter line = bundle[1]; 743752Speter statlist(blk); 744752Speter # ifdef PTREE 745752Speter { 746752Speter pPointer Body = tCopy( blk ); 747752Speter 748752Speter pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body; 749752Speter } 750752Speter # endif PTREE 751752Speter # ifdef OBJ 752752Speter if (cbn== 1 && monflg != 0) { 753752Speter patchfil(cntpatch - 2, cnts, 2); 754752Speter patchfil(nfppatch - 2, pfcnt, 2); 755752Speter } 756752Speter # endif OBJ 757752Speter # ifdef PC 758752Speter if ( fp -> class == PROG && monflg ) { 759752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 760752Speter , "_PMFLUSH" ); 761752Speter putleaf( P2ICON , cnts , 0 , P2INT , 0 ); 762752Speter putleaf( P2ICON , pfcnt , 0 , P2INT , 0 ); 763752Speter putop( P2LISTOP , P2INT ); 764752Speter putop( P2CALL , P2INT ); 765752Speter putdot( filename , line ); 766752Speter } 767752Speter # endif PC 768752Speter if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) { 769752Speter recovered(); 770752Speter error("Input is used but not defined in the program statement"); 771752Speter } 772752Speter /* 773752Speter * Clean up the symbol table displays and check for unresolves 774752Speter */ 775752Speter line = endline; 776752Speter b = cbn; 777752Speter Fp = fp; 778752Speter chkref = syneflg == errcnt[cbn] && opt('w') == 0; 779752Speter for (i = 0; i <= 077; i++) { 780752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 781752Speter /* 782752Speter * Check for variables defined 783752Speter * but not referenced 784752Speter */ 785752Speter if (chkref && p->symbol != NIL) 786752Speter switch (p->class) { 787752Speter case FIELD: 788752Speter /* 789752Speter * If the corresponding record is 790752Speter * unused, we shouldn't complain about 791752Speter * the fields. 792752Speter */ 793752Speter default: 794752Speter if ((p->nl_flags & (NUSED|NMOD)) == 0) { 795752Speter warning(); 796752Speter nerror("%s %s is neither used nor set", classes[p->class], p->symbol); 797752Speter break; 798752Speter } 799752Speter /* 800752Speter * If a var parameter is either 801752Speter * modified or used that is enough. 802752Speter */ 803752Speter if (p->class == REF) 804752Speter continue; 805752Speter # ifdef OBJ 806752Speter if ((p->nl_flags & NUSED) == 0) { 807752Speter warning(); 808752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 809752Speter break; 810752Speter } 811752Speter # endif OBJ 812752Speter # ifdef PC 813752Speter if (((p->nl_flags & NUSED) == 0) && ((p->ext_flags & NEXTERN) == 0)) { 814752Speter warning(); 815752Speter nerror("%s %s is never used", classes[p->class], p->symbol); 816752Speter break; 817752Speter } 818752Speter # endif PC 819752Speter if ((p->nl_flags & NMOD) == 0) { 820752Speter warning(); 821752Speter nerror("%s %s is used but never set", classes[p->class], p->symbol); 822752Speter break; 823752Speter } 824752Speter case LABEL: 825752Speter case FVAR: 826752Speter case BADUSE: 827752Speter break; 828752Speter } 829752Speter switch (p->class) { 830752Speter case BADUSE: 831752Speter cp = "s"; 832752Speter if (p->chain->ud_next == NIL) 833752Speter cp++; 834752Speter eholdnl(); 835752Speter if (p->value[NL_KINDS] & ISUNDEF) 836752Speter nerror("%s undefined on line%s", p->symbol, cp); 837752Speter else 838752Speter nerror("%s improperly used on line%s", p->symbol, cp); 839752Speter pnumcnt = 10; 840752Speter pnums(p->chain); 841752Speter pchr('\n'); 842752Speter break; 843752Speter 844752Speter case FUNC: 845752Speter case PROC: 846752Speter # ifdef OBJ 847752Speter if ((p->nl_flags & NFORWD)) 848752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 849752Speter # endif OBJ 850752Speter # ifdef PC 851752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 852752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 853752Speter # endif PC 854752Speter break; 855752Speter 856752Speter case LABEL: 857752Speter if (p->nl_flags & NFORWD) 858752Speter nerror("label %s was declared but not defined", p->symbol); 859752Speter break; 860752Speter case FVAR: 861752Speter if ((p->nl_flags & NMOD) == 0) 862752Speter nerror("No assignment to the function variable"); 863752Speter break; 864752Speter } 865752Speter } 866752Speter /* 867752Speter * Pop this symbol 868752Speter * table slot 869752Speter */ 870752Speter disptab[i] = p; 871752Speter } 872752Speter 873752Speter # ifdef OBJ 874752Speter put(1, O_END); 875752Speter # endif OBJ 876752Speter # ifdef PC 877752Speter /* 878752Speter * if there were file variables declared at this level 879752Speter * call pclose( &__disply[ cbn ] ) to clean them up. 880752Speter */ 881752Speter if ( dfiles[ cbn ] ) { 882752Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 883752Speter , "_PCLOSE" ); 884752Speter putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) 885752Speter , P2PTR | P2CHAR ); 886752Speter putop( P2CALL , P2INT ); 887752Speter putdot( filename , line ); 888752Speter } 889752Speter /* 890752Speter * if this is a function, 891752Speter * the function variable is the return value. 892752Speter * if it's a scalar valued function, return scalar, 893752Speter * else, return a pointer to the structure value. 894752Speter */ 895752Speter if ( fp -> class == FUNC ) { 896752Speter struct nl *fvar = fp -> ptr[ NL_FVAR ]; 897752Speter long fvartype = p2type( fvar -> type ); 898*1196Speter long label; 899*1196Speter char labelname[ BUFSIZ ]; 900752Speter 901752Speter switch ( classify( fvar -> type ) ) { 902752Speter case TBOOL: 903752Speter case TCHAR: 904752Speter case TINT: 905752Speter case TSCAL: 906752Speter case TDOUBLE: 907752Speter case TPTR: 908752Speter putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 909752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 910752Speter break; 911752Speter default: 912*1196Speter label = getlab(); 913*1196Speter sprintf( labelname , PREFIXFORMAT , 914*1196Speter LABELPREFIX , label ); 915*1196Speter putprintf( " .data" , 0 ); 916*1196Speter putprintf( " .lcomm %s,%d" , 0 , 917*1196Speter labelname , lwidth( fvar -> type ) ); 918*1196Speter putprintf( " .text" , 0 ); 919*1196Speter putRV( labelname , 0 , 0 , fvartype ); 920752Speter putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 921752Speter , fvar -> value[ NL_OFFS ] , fvartype ); 922*1196Speter putstrop( P2STASG , fvartype , lwidth( fvar -> type ) , 923*1196Speter align( fvar -> type ) ); 924*1196Speter putLV( labelname , 0 , 0 , fvartype ); 925752Speter break; 926752Speter } 927752Speter putop( P2FORCE , fvartype ); 928752Speter putdot( filename , line ); 929752Speter } 930752Speter /* 931752Speter * restore old display entry from save area 932752Speter */ 933752Speter 934752Speter putprintf( " movq %d(%s),%s+%d" , 0 935752Speter , DSAVEOFFSET , P2FPNAME 936752Speter , DISPLAYNAME , cbn * sizeof(struct dispsave) ); 937752Speter stabrbrac( cbn ); 938752Speter putprintf( " ret" , 0 ); 939752Speter /* 940752Speter * let the second pass allocate locals 941752Speter */ 942752Speter putlab( botlabel ); 943752Speter putprintf( " subl2 $LF%d,sp" , 0 , ftnno ); 944752Speter putrbracket( ftnno ); 945752Speter putjbr( toplabel ); 946752Speter /* 947752Speter * declare pcp counters, if any 948752Speter */ 949752Speter if ( monflg && fp -> class == PROG ) { 950752Speter putprintf( " .data" , 0 ); 951752Speter putprintf( " .comm " , 1 ); 952752Speter putprintf( PCPCOUNT , 1 ); 953752Speter putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) ); 954752Speter putprintf( " .text" , 0 ); 955752Speter } 956752Speter # endif PC 957752Speter #ifdef DEBUG 958752Speter dumpnl(fp->ptr[2], fp->symbol); 959752Speter #endif 960752Speter /* 961752Speter * Restore the 962752Speter * (virtual) name list 963752Speter * position 964752Speter */ 965752Speter nlfree(fp->ptr[2]); 966752Speter /* 967752Speter * Proc/func has been 968752Speter * resolved 969752Speter */ 970752Speter fp->nl_flags &= ~NFORWD; 971752Speter /* 972752Speter * Patch the beg 973752Speter * of the proc/func to 974752Speter * the proper variable size 975752Speter */ 976752Speter if (Fp == NIL) 977752Speter elineon(); 978752Speter # ifdef OBJ 979752Speter patchfil(var, sizes[cbn].om_max, 2); 980752Speter # endif OBJ 981752Speter cbn--; 982752Speter if (inpflist(fp->symbol)) { 983752Speter opop('l'); 984752Speter } 985752Speter } 986752Speter 987752Speter 988752Speter /* 989752Speter * Segend is called to check for 990752Speter * unresolved variables, funcs and 991752Speter * procs, and deliver unresolved and 992752Speter * baduse error diagnostics at the 993752Speter * end of a routine segment (a separately 994752Speter * compiled segment that is not the 995752Speter * main program) for PC. This 996752Speter * routine should only be called 997752Speter * by PC (not standard). 998752Speter */ 999752Speter segend() 1000752Speter { 1001752Speter register struct nl *p; 1002752Speter register int i,b; 1003752Speter char *cp; 1004752Speter 1005752Speter #ifdef PC 1006752Speter if (opt('s')) { 1007752Speter standard(); 1008752Speter error("Separately compiled routine segments are not standard."); 1009752Speter } else { 1010752Speter b = cbn; 1011752Speter for (i=0; i<077; i++) { 1012752Speter for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 1013752Speter switch (p->class) { 1014752Speter case BADUSE: 1015752Speter cp = 's'; 1016752Speter if (p->chain->ud_next == NIL) 1017752Speter cp++; 1018752Speter eholdnl(); 1019752Speter if (p->value[NL_KINDS] & ISUNDEF) 1020752Speter nerror("%s undefined on line%s", p->symbol, cp); 1021752Speter else 1022752Speter nerror("%s improperly used on line%s", p->symbol, cp); 1023752Speter pnumcnt = 10; 1024752Speter pnums(p->chain); 1025752Speter pchr('\n'); 1026752Speter break; 1027752Speter 1028752Speter case FUNC: 1029752Speter case PROC: 1030752Speter if ((p->nl_flags & NFORWD) && ((p->ext_flags & NEXTERN) == 0)) 1031752Speter nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 1032752Speter break; 1033752Speter 1034752Speter case FVAR: 1035752Speter if (((p->nl_flags & NMOD) == 0) && ((p->chain->ext_flags & NEXTERN) == 0)) 1036752Speter nerror("No assignment to the function variable"); 1037752Speter break; 1038752Speter } 1039752Speter } 1040752Speter disptab[i] = p; 1041752Speter } 1042752Speter } 1043752Speter #endif PC 1044752Speter #ifdef OBJ 1045752Speter error("Missing program statement and program body"); 1046752Speter #endif OBJ 1047752Speter 1048752Speter } 1049752Speter 1050752Speter 1051752Speter /* 1052752Speter * Level1 does level one processing for 1053752Speter * separately compiled routine segments 1054752Speter */ 1055752Speter level1() 1056752Speter { 1057752Speter 1058752Speter # ifdef OBJ 1059752Speter error("Missing program statement"); 1060752Speter # endif OBJ 1061752Speter # ifdef PC 1062752Speter if (opt('s')) { 1063752Speter standard(); 1064752Speter error("Missing program statement"); 1065752Speter } 1066752Speter # endif PC 1067752Speter 1068752Speter cbn++; 1069752Speter sizes[cbn].om_max = sizes[cbn].om_off = -DPOFF1; 1070834Speter gotos[cbn] = NIL; 1071834Speter errcnt[cbn] = syneflg; 1072834Speter parts[ cbn ] = NIL; 1073834Speter dfiles[ cbn ] = FALSE; 1074752Speter progseen++; 1075752Speter } 1076752Speter 1077752Speter 1078752Speter 1079752Speter pnums(p) 1080752Speter struct udinfo *p; 1081752Speter { 1082752Speter 1083752Speter if (p->ud_next != NIL) 1084752Speter pnums(p->ud_next); 1085752Speter if (pnumcnt == 0) { 1086752Speter printf("\n\t"); 1087752Speter pnumcnt = 20; 1088752Speter } 1089752Speter pnumcnt--; 1090752Speter printf(" %d", p->ud_line); 1091752Speter } 1092752Speter 1093752Speter nerror(a1, a2, a3) 1094752Speter { 1095752Speter 1096752Speter if (Fp != NIL) { 1097752Speter yySsync(); 1098752Speter #ifndef PI1 1099752Speter if (opt('l')) 1100752Speter yyoutline(); 1101752Speter #endif 1102752Speter yysetfile(filename); 1103752Speter printf("In %s %s:\n", classes[Fp->class], Fp->symbol); 1104752Speter Fp = NIL; 1105752Speter elineoff(); 1106752Speter } 1107752Speter error(a1, a2, a3); 1108752Speter } 1109