change program name to pc
[unix-history] / usr / src / usr.bin / pascal / src / fdec.c
CommitLineData
99878838
PK
1/* Copyright (c) 1979 Regents of the University of California */
2
b721c131 3static char sccsid[] = "@(#)fdec.c 1.2 %G%";
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++;
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
336funcfwd(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
357funcext(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;
b721c131 368 stabefunc( fp -> symbol , fp -> class , line );
99878838
PK
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 */
389funcbody(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 ) {
b721c131 415 stabfunc( fp -> symbol , fp -> class , line , cbn - 1 );
99878838 416 } else {
b721c131 417 stabfunc( "program" , fp -> class , line , 0 );
99878838
PK
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;
b721c131
PK
439 stabvar( q -> symbol , p2type( q -> type ) , cbn
440 , q -> value[ NL_OFFS ] , lwidth( q -> type )
441 , line );
99878838
PK
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
453struct nl *Fp;
454int 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 */
466funcend(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 */
1003level1()
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
1024pnums(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
1038nerror(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}