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