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