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