xref: /csrg-svn/usr.bin/pascal/src/fend.c (revision 9121)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)fend.c 1.14 11/10/82";
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 struct	nl *Fp;
30 int	pnumcnt;
31 /*
32  * Funcend is called to
33  * finish a block by generating
34  * the code for the statements.
35  * It then looks for unresolved declarations
36  * of labels, procedures and functions,
37  * and cleans up the name list.
38  * For the program, it checks the
39  * semantics of the program
40  * statement (yuchh).
41  */
42 funcend(fp, bundle, endline)
43 	struct nl *fp;
44 	int *bundle;
45 	int endline;
46 {
47 	register struct nl *p;
48 	register int i, b;
49 	int var, inp, out, *blk;
50 	bool chkref;
51 	struct nl *iop;
52 	char *cp;
53 	extern int cntstat;
54 #	ifdef PC
55 	    int		savlabel = getlab();
56 	    int		toplabel = getlab();
57 	    int		botlabel = getlab();
58 	    int		proflabel = getlab();
59 	    int		skip = getlab();
60 	    char	extname[ BUFSIZ ];
61 #	endif PC
62 
63 	cntstat = 0;
64 /*
65  *	yyoutline();
66  */
67 	if (program != NIL)
68 		line = program->value[3];
69 	blk = bundle[2];
70 	if (fp == NIL) {
71 		cbn--;
72 #		ifdef PTREE
73 		    nesting--;
74 #		endif PTREE
75 		return;
76 	}
77 #ifdef OBJ
78 	/*
79 	 * Patch the branch to the
80 	 * entry point of the function
81 	 */
82 	patch4(fp->value[NL_ENTLOC]);
83 	/*
84 	 * Put out the block entrance code and the block name.
85 	 * HDRSZE is the number of bytes of info in the static
86 	 * BEG data area exclusive of the proc name. It is
87 	 * currently defined as:
88 	/*	struct hdr {
89 	/*		long framesze;	/* number of bytes of local vars */
90 	/*		long nargs;	/* number of bytes of arguments */
91 	/*		bool tests;	/* TRUE => perform runtime tests */
92 	/*		short offset;	/* offset of procedure in source file */
93 	/*		char name[1];	/* name of active procedure */
94 	/*	};
95 	 */
96 #	define HDRSZE (2 * sizeof(long) + sizeof(short) + sizeof(bool))
97 	var = put(2, ((lenstr(fp->symbol,0) + HDRSZE) << 8)
98 		| (cbn == 1 && opt('p') == 0 ? O_NODUMP: O_BEG), (long)0);
99 	    /*
100 	     *  output the number of bytes of arguments
101 	     *  this is only checked on formal calls.
102 	     */
103 	put(2, O_CASE4, cbn == 1 ? (long)0 : (long)(fp->value[NL_OFFS]-DPOFF2));
104 	    /*
105 	     *	Output the runtime test mode for the routine
106 	     */
107 	put(2, sizeof(bool) == 2 ? O_CASE2 : O_CASE4, opt('t') ? TRUE : FALSE);
108 	    /*
109 	     *	Output line number and routine name
110 	     */
111 	put(2, O_CASE2, bundle[1]);
112 	putstr(fp->symbol, 0);
113 #endif OBJ
114 #ifdef PC
115 	/*
116 	 * put out the procedure entry code
117 	 */
118 	if ( fp -> class == PROG ) {
119 	    putprintf( "	.text" , 0 );
120 	    putprintf( "	.align	1" , 0 );
121 	    putprintf( "	.globl	_main" , 0 );
122 	    putprintf( "_main:" , 0 );
123 	    putprintf( "	.word	0" , 0 );
124 	    if ( opt ( 't' ) ) {
125 	        putprintf( "	pushl	$1" , 0 );
126 	    } else {
127 	        putprintf( "	pushl	$0" , 0 );
128 	    }
129 	    putprintf( "	calls	$1,_PCSTART" , 0 );
130 	    putprintf( "	movl	4(ap),__argc" , 0 );
131 	    putprintf( "	movl	8(ap),__argv" , 0 );
132 	    putprintf( "	calls	$0,_program" , 0 );
133 	    putprintf( "	pushl	$0" , 0 );
134 	    putprintf( "	calls	$1,_PCEXIT" , 0 );
135 	    ftnno = fp -> value[NL_ENTLOC];
136 	    putprintf( "	.text" , 0 );
137 	    putprintf( "	.align	1" , 0 );
138 	    putprintf( "	.globl	_program" , 0 );
139 	    putprintf( "_program:" , 0 );
140 	    stabfunc( "program" , fp -> class , bundle[1] , 0 );
141 	} else {
142 	    ftnno = fp -> value[NL_ENTLOC];
143 	    putprintf( "	.text" , 0 );
144 	    putprintf( "	.align	1" , 0 );
145 	    sextname( extname , fp -> symbol , cbn - 1 );
146 	    putprintf( "	.globl	%s%s" , 0 , FORMALPREFIX , extname );
147 	    putprintf( "	.globl	%s" , 0 , extname );
148 	    putprintf( "%s:" , 0 , extname );
149 	    stabfunc( fp -> symbol , fp -> class , bundle[1] , cbn - 1 );
150 	    for ( p = fp -> chain ; p != NIL ; p = p -> chain ) {
151 		stabparam( p -> symbol , p2type( p -> type )
152 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
153 	    }
154 	    if ( fp -> class == FUNC ) {
155 		    /*
156 		     *	stab the function variable
157 		     */
158 		p = fp -> ptr[ NL_FVAR ];
159 		stablvar( p -> symbol , p2type( p -> type ) , cbn
160 			, p -> value[ NL_OFFS ] , lwidth( p -> type ) );
161 	    }
162 		/*
163 		 *	stab local variables
164 		 *	rummage down hash chain links.
165 		 */
166 	    for ( i = 0 ; i <= 077 ; i++ ) {
167 		for ( p = disptab[ i ] ; p != NIL ; p = p->nl_next) {
168 		    if ( ( p -> nl_block & 037 ) != cbn ) {
169 			break;
170 		    }
171 		    /*
172 		     *	stab local variables
173 		     *	that's named variables, but not params
174 		     */
175 		    if (   ( p -> symbol != NIL )
176 			&& ( p -> class == VAR )
177 			&& ( p -> value[ NL_OFFS ] < 0 ) ) {
178 			stablvar( p -> symbol , p2type( p -> type ) , cbn
179 			    , p -> value[ NL_OFFS ] , lwidth( p -> type ) );
180 		    }
181 		}
182 	    }
183 	}
184 	stablbrac( cbn );
185 	    /*
186 	     *	register save mask
187 	     */
188 	putprintf( "	.word	" , 1 );
189         putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel );
190 	putjbr( botlabel );
191 	putlab( toplabel );
192 	if ( profflag ) {
193 		/*
194 		 *	call mcount for profiling
195 		 */
196 	    putprintf( "	moval	" , 1 );
197 	    putprintf( PREFIXFORMAT , 1 , LABELPREFIX , proflabel );
198 	    putprintf( ",r0" , 0 );
199 	    putprintf( "	jsb	mcount" , 0 );
200 	    putprintf( "	.data" , 0 );
201 	    putprintf( "	.align	2" , 0 );
202 	    putlab( proflabel );
203 	    putprintf( "	.long	0" , 0 );
204 	    putprintf( "	.text" , 0 );
205 	}
206 	    /*
207 	     *	save old display
208 	     */
209 	putprintf( "	movq	%s+%d,%d(%s)" , 0
210 		, DISPLAYNAME , cbn * sizeof(struct dispsave)
211 		, DSAVEOFFSET , P2FPNAME );
212 	    /*
213 	     *	set up new display by saving AP and FP in appropriate
214 	     *	slot in display structure.
215 	     */
216 	putprintf( "	movq	%s,%s+%d" , 0
217 		, P2APNAME , DISPLAYNAME , cbn * sizeof(struct dispsave) );
218 	    /*
219 	     *	set underflow checking if runtime tests
220 	     */
221 	if ( opt( 't' ) ) {
222 	    putprintf( "	bispsw	$0xe0" , 0 );
223 	}
224 	    /*
225 	     *	ask second pass to allocate known locals
226 	     */
227 	putlbracket( ftnno , -sizes[ cbn ].om_max );
228 	    /*
229 	     *	and zero them if checking is on
230 	     *	by calling blkclr( bytes of locals , starting local address );
231 	     */
232 	if ( opt( 't' ) && ( -sizes[ cbn ].om_max ) > DPOFF1 ) {
233 	    putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
234 		    , "_blkclr" );
235 	    putleaf( P2ICON ,  ( -sizes[ cbn ].om_max ) - DPOFF1
236 		    , 0 , P2INT , 0 );
237 	    putLV( 0 , cbn , sizes[ cbn ].om_max , NLOCAL , P2CHAR );
238 	    putop( P2LISTOP , P2INT );
239 	    putop( P2CALL , P2INT );
240 	    putdot( filename , line );
241 	}
242 	    /*
243 	     *  set up goto vector in case of non-local goto to this frame
244 	     */
245 	putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
246 		, "_setjmp" );
247 	putLV( 0 , cbn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY );
248 	putop( P2CALL , P2INT );
249 	putleaf( P2ICON , 0 , 0 , P2INT , 0 );
250 	putop( P2NE , P2INT );
251 	putleaf( P2ICON , skip , 0 , P2INT , 0 );
252 	putop( P2CBRANCH , P2INT );
253 	putdot( filename , line );
254 	putprintf( "	jmp	(r0)" , 0 );
255 	putlab(skip);
256 #endif PC
257 	if ( monflg ) {
258 		if ( fp -> value[ NL_CNTR ] != 0 ) {
259 			inccnt( fp -> value [ NL_CNTR ] );
260 		}
261 		inccnt( bodycnts[ fp -> nl_block & 037 ] );
262 	}
263 	if (fp->class == PROG) {
264 		/*
265 		 * The glorious buffers option.
266 		 *          0 = don't buffer output
267 		 *          1 = line buffer output
268 		 *          2 = 512 byte buffer output
269 		 */
270 #		ifdef OBJ
271 		    if (opt('b') != 1)
272 			    put(1, O_BUFF | opt('b') << 8);
273 #		endif OBJ
274 #		ifdef PC
275 		    if ( opt( 'b' ) != 1 ) {
276 			putleaf( P2ICON , 0 , 0
277 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_BUFF" );
278 			putleaf( P2ICON , opt( 'b' ) , 0 , P2INT , 0 );
279 			putop( P2CALL , P2INT );
280 			putdot( filename , line );
281 		    }
282 #		endif PC
283 		inp = 0;
284 		out = 0;
285 		for (p = fp->chain; p != NIL; p = p->chain) {
286 			if (strcmp(p->symbol, input->symbol) == 0) {
287 				inp++;
288 				continue;
289 			}
290 			if (strcmp(p->symbol, output->symbol) == 0) {
291 				out++;
292 				continue;
293 			}
294 			iop = lookup1(p->symbol);
295 			if (iop == NIL || bn != cbn) {
296 				error("File %s listed in program statement but not declared", p->symbol);
297 				continue;
298 			}
299 			if (iop->class != VAR) {
300 				error("File %s listed in program statement but declared as a %s", p->symbol, classes[iop->class]);
301 				continue;
302 			}
303 			if (iop->type == NIL)
304 				continue;
305 			if (iop->type->class != FILET) {
306 				error("File %s listed in program statement but defined as %s",
307 					p->symbol, nameof(iop->type));
308 				continue;
309 			}
310 #			ifdef OBJ
311 			    put(2, O_CON24, text(iop->type) ? 0 : width(iop->type->type));
312 			    i = lenstr(p->symbol,0);
313 			    put(2, O_CON24, i);
314 			    put(2, O_LVCON, i);
315 			    putstr(p->symbol, 0);
316 			    put(2, O_LV | bn<<8+INDX, (int)iop->value[NL_OFFS]);
317 			    put(1, O_DEFNAME);
318 #			endif OBJ
319 #			ifdef PC
320 			    putleaf( P2ICON , 0 , 0
321 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
322 				    , "_DEFNAME" );
323 			    putLV( p -> symbol , bn , iop -> value[NL_OFFS] ,
324 				    iop -> extra_flags , p2type( iop ) );
325 			    putCONG( p -> symbol , strlen( p -> symbol )
326 				    , LREQ );
327 			    putop( P2LISTOP , P2INT );
328 			    putleaf( P2ICON , strlen( p -> symbol )
329 				    , 0 , P2INT , 0 );
330 			    putop( P2LISTOP , P2INT );
331 			    putleaf( P2ICON
332 				, text(iop->type) ? 0 : width(iop->type->type)
333 				, 0 , P2INT , 0 );
334 			    putop( P2LISTOP , P2INT );
335 			    putop( P2CALL , P2INT );
336 			    putdot( filename , line );
337 #			endif PC
338 		}
339 	}
340 	/*
341 	 * Process the prog/proc/func body
342 	 */
343 	noreach = 0;
344 	line = bundle[1];
345 	statlist(blk);
346 #	ifdef PTREE
347 	    {
348 		pPointer Body = tCopy( blk );
349 
350 		pDEF( PorFHeader[ nesting -- ] ).PorFBody = Body;
351 	    }
352 #	endif PTREE
353 #	ifdef OBJ
354 	    if (cbn== 1 && monflg != 0) {
355 		    patchfil(cntpatch - 2, (long)cnts, 2);
356 		    patchfil(nfppatch - 2, (long)pfcnt, 2);
357 	    }
358 #	endif OBJ
359 #	ifdef PC
360 	    if ( fp -> class == PROG && monflg ) {
361 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
362 			, "_PMFLUSH" );
363 		putleaf( P2ICON , cnts , 0 , P2INT , 0 );
364 		putleaf( P2ICON , pfcnt , 0 , P2INT , 0 );
365 		putop( P2LISTOP , P2INT );
366 		putLV( PCPCOUNT , 0 , 0 , NGLOBAL , P2INT );
367 		putop( P2LISTOP , P2INT );
368 		putop( P2CALL , P2INT );
369 		putdot( filename , line );
370 	    }
371 #	endif PC
372 	/*
373 	 * Clean up the symbol table displays and check for unresolves
374 	 */
375 	line = endline;
376 	if (fp->class == PROG && inp == 0 && (input->nl_flags & (NUSED|NMOD)) != 0) {
377 		recovered();
378 		error("Input is used but not defined in the program statement");
379 	}
380 	if (fp->class == PROG && out == 0 && (output->nl_flags & (NUSED|NMOD)) != 0) {
381 		recovered();
382 		error("Output is used but not defined in the program statement");
383 	}
384 	b = cbn;
385 	Fp = fp;
386 	chkref = syneflg == errcnt[cbn] && opt('w') == 0;
387 	for (i = 0; i <= 077; i++) {
388 		for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) {
389 			/*
390 			 * Check for variables defined
391 			 * but not referenced
392 			 */
393 			if (chkref && p->symbol != NIL)
394 			switch (p->class) {
395 				case FIELD:
396 					/*
397 					 * If the corresponding record is
398 					 * unused, we shouldn't complain about
399 					 * the fields.
400 					 */
401 				default:
402 					if ((p->nl_flags & (NUSED|NMOD)) == 0) {
403 						warning();
404 						nerror("%s %s is neither used nor set", classes[p->class], p->symbol);
405 						break;
406 					}
407 					/*
408 					 * If a var parameter is either
409 					 * modified or used that is enough.
410 					 */
411 					if (p->class == REF)
412 						continue;
413 #					ifdef OBJ
414 					    if ((p->nl_flags & NUSED) == 0) {
415 						warning();
416 						nerror("%s %s is never used", classes[p->class], p->symbol);
417 						break;
418 					    }
419 #					endif OBJ
420 #					ifdef PC
421 					    if (((p->nl_flags & NUSED) == 0) && ((p->extra_flags & NEXTERN) == 0)) {
422 						warning();
423 						nerror("%s %s is never used", classes[p->class], p->symbol);
424 						break;
425 					    }
426 #					endif PC
427 					if ((p->nl_flags & NMOD) == 0) {
428 						warning();
429 						nerror("%s %s is used but never set", classes[p->class], p->symbol);
430 						break;
431 					}
432 				case LABEL:
433 				case FVAR:
434 				case BADUSE:
435 					break;
436 			}
437 			switch (p->class) {
438 				case BADUSE:
439 					cp = "s";
440 					if (p->chain->ud_next == NIL)
441 						cp++;
442 					eholdnl();
443 					if (p->value[NL_KINDS] & ISUNDEF)
444 						nerror("%s undefined on line%s", p->symbol, cp);
445 					else
446 						nerror("%s improperly used on line%s", p->symbol, cp);
447 					pnumcnt = 10;
448 					pnums(p->chain);
449 					pchr('\n');
450 					break;
451 
452 				case FUNC:
453 				case PROC:
454 #					ifdef OBJ
455 					    if ((p->nl_flags & NFORWD))
456 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
457 #					endif OBJ
458 #					ifdef PC
459 					    if ((p->nl_flags & NFORWD) && ((p->extra_flags & NEXTERN) == 0))
460 						nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol);
461 #					endif PC
462 					break;
463 
464 				case LABEL:
465 					if (p->nl_flags & NFORWD)
466 						nerror("label %s was declared but not defined", p->symbol);
467 					break;
468 				case FVAR:
469 					if ((p->nl_flags & NMOD) == 0)
470 						nerror("No assignment to the function variable");
471 					break;
472 			}
473 		}
474 		/*
475 		 * Pop this symbol
476 		 * table slot
477 		 */
478 		disptab[i] = p;
479 	}
480 
481 #	ifdef OBJ
482 	    put(1, O_END);
483 #	endif OBJ
484 #	ifdef PC
485 		/*
486 		 *	if there were file variables declared at this level
487 		 *	call pclose( &__disply[ cbn ] ) to clean them up.
488 		 */
489 	    if ( dfiles[ cbn ] ) {
490 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR )
491 			, "_PCLOSE" );
492 		putRV( DISPLAYNAME , 0 , cbn * sizeof( struct dispsave ) ,
493 			NGLOBAL , P2PTR | P2CHAR );
494 		putop( P2CALL , P2INT );
495 		putdot( filename , line );
496 	    }
497 		/*
498 		 *	if this is a function,
499 		 *	the function variable is the return value.
500 		 *	if it's a scalar valued function, return scalar,
501 		 *	else, return a pointer to the structure value.
502 		 */
503 	    if ( fp -> class == FUNC ) {
504 		struct nl	*fvar = fp -> ptr[ NL_FVAR ];
505 		long		fvartype = p2type( fvar -> type );
506 		long		label;
507 		char		labelname[ BUFSIZ ];
508 
509 		switch ( classify( fvar -> type ) ) {
510 		    case TBOOL:
511 		    case TCHAR:
512 		    case TINT:
513 		    case TSCAL:
514 		    case TDOUBLE:
515 		    case TPTR:
516 			putRV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
517 				fvar -> value[ NL_OFFS ] ,
518 				fvar -> extra_flags ,
519 				fvartype );
520 			break;
521 		    default:
522 			label = getlab();
523 			sprintf( labelname , PREFIXFORMAT ,
524 				LABELPREFIX , label );
525 			putprintf( "	.data" , 0 );
526 			putprintf( "	.lcomm	%s,%d" , 0 ,
527 				    labelname , lwidth( fvar -> type ) );
528 			putprintf( "	.text" , 0 );
529 			putleaf( P2NAME , 0 , 0 , fvartype , labelname );
530 			putLV( fvar -> symbol , ( fvar -> nl_block ) & 037 ,
531 				fvar -> value[ NL_OFFS ] ,
532 				fvar -> extra_flags ,
533 				fvartype );
534 			putstrop( P2STASG , fvartype , lwidth( fvar -> type ) ,
535 				align( fvar -> type ) );
536 			putdot( filename , line );
537 			putleaf( P2ICON , 0 , 0 , fvartype , labelname );
538 			break;
539 		}
540 		putop( P2FORCE , fvartype );
541 		putdot( filename , line );
542 	    }
543 		/*
544 		 *	restore old display entry from save area
545 		 */
546 
547 	    putprintf( "	movq	%d(%s),%s+%d" , 0
548 		, DSAVEOFFSET , P2FPNAME
549 		, DISPLAYNAME , cbn * sizeof(struct dispsave) );
550 	    stabrbrac( cbn );
551 	    putprintf( "	ret" , 0 );
552 		/*
553 		 *	let the second pass allocate locals
554 		 * 	and registers
555 		 */
556 	    putprintf( "	.set	" , 1 );
557 	    putprintf( PREFIXFORMAT , 1 , LABELPREFIX , savlabel );
558 	    putprintf( ", 0x%x" , 0 , savmask() );
559 	    putlab( botlabel );
560 	    putprintf( "	subl2	$LF%d,sp" , 0 , ftnno );
561 	    putrbracket( ftnno );
562 	    putjbr( toplabel );
563 		/*
564 		 *  put down the entry point for formal calls
565 		 *  the arguments for FCALL have been passed to us
566 		 *  as hidden parameters after the regular arguments.
567 		 */
568 	    if ( fp -> class != PROG ) {
569 		putprintf( "%s%s:" , 0 , FORMALPREFIX , extname );
570 		putprintf( "	.word	" , 1 );
571 		putprintf( PREFIXFORMAT , 0 , LABELPREFIX , savlabel );
572 		putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) ,
573 			"_FCALL" );
574 		putRV( 0 , cbn ,
575 		    fp -> value[ NL_OFFS ] + sizeof( struct formalrtn * ) ,
576 		    NPARAM ,
577 		    P2PTR | P2STRTY );
578 		putRV( 0 , cbn , fp -> value[ NL_OFFS ] ,
579 			NPARAM , P2PTR|P2STRTY );
580 		putop( P2LISTOP , P2INT );
581 		putop( P2CALL , P2INT );
582 		putdot( filename , line );
583 		putjbr( botlabel );
584 	    }
585 		/*
586 		 *	declare pcp counters, if any
587 		 */
588 	    if ( monflg && fp -> class == PROG ) {
589 		putprintf( "	.data" , 0 );
590 		putprintf( "	.comm	" , 1 );
591 		putprintf( PCPCOUNT , 1 );
592 		putprintf( ",%d" , 0 , ( cnts + 1 ) * sizeof (long) );
593 		putprintf( "	.text" , 0 );
594 	    }
595 #	endif PC
596 #ifdef DEBUG
597 	dumpnl(fp->ptr[2], fp->symbol);
598 #endif
599 
600 #ifdef OBJ
601 	/*
602 	 * save the namelist for the debugger pdx
603 	 */
604 
605 	savenl(fp->ptr[2], fp->symbol);
606 #endif
607 
608 	/*
609 	 * Restore the
610 	 * (virtual) name list
611 	 * position
612 	 */
613 	nlfree(fp->ptr[2]);
614 	/*
615 	 * Proc/func has been
616 	 * resolved
617 	 */
618 	fp->nl_flags &= ~NFORWD;
619 	/*
620 	 * Patch the beg
621 	 * of the proc/func to
622 	 * the proper variable size
623 	 */
624 	if (Fp == NIL)
625 		elineon();
626 #	ifdef OBJ
627 	    patchfil(var, (long)(-sizes[cbn].om_max), 2);
628 #	endif OBJ
629 	cbn--;
630 	if (inpflist(fp->symbol)) {
631 		opop('l');
632 	}
633 }
634 
635 #ifdef PC
636     /*
637      *	construct the long name of a function based on it's static nesting.
638      *	into a caller-supplied buffer (that should be about BUFSIZ big).
639      */
640 sextname( buffer , name , level )
641     char	buffer[];
642     char	*name;
643     int		level;
644 {
645     char	*starthere;
646     int	i;
647 
648     starthere = &buffer[0];
649     for ( i = 1 ; i < level ; i++ ) {
650 	sprintf( starthere , EXTFORMAT , enclosing[ i ] );
651 	starthere += strlen( enclosing[ i ] ) + 1;
652     }
653     sprintf( starthere , EXTFORMAT , name );
654     starthere += strlen( name ) + 1;
655     if ( starthere >= &buffer[ BUFSIZ ] ) {
656 	panic( "sextname" );
657     }
658 }
659 #endif PC
660