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