xref: /csrg-svn/usr.bin/pascal/src/lab.c (revision 22172)
1*22172Sdist /*
2*22172Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22172Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22172Sdist  * specifies the terms and conditions for redistribution.
5*22172Sdist  */
6756Speter 
714733Sthien #ifndef lint
8*22172Sdist static char sccsid[] = "@(#)lab.c	5.1 (Berkeley) 06/05/85";
9*22172Sdist #endif not lint
10756Speter 
11756Speter #include "whoami.h"
12756Speter #include "0.h"
13756Speter #include "tree.h"
14756Speter #include "opcode.h"
15756Speter #include "objfmt.h"
16756Speter #ifdef PC
17756Speter #   include	"pc.h"
1818460Sralph #   include	<pcc.h>
19756Speter #endif PC
2014733Sthien #include "tree_ty.h"
21756Speter 
22756Speter /*
23756Speter  * Label enters the definitions
24756Speter  * of the label declaration part
25756Speter  * into the namelist.
26756Speter  */
27756Speter label(r, l)
2814733Sthien 	struct tnode *r;
2914733Sthien 	int l;
30756Speter {
317951Speter     static bool	label_order = FALSE;
327951Speter     static bool	label_seen = FALSE;
333366Speter #ifdef PC
343366Speter 	char	extname[ BUFSIZ ];
353366Speter #endif PC
36756Speter #ifndef PI0
3714733Sthien 	register struct tnode *ll;
38756Speter 	register struct nl *p, *lp;
39756Speter 
40756Speter 	lp = NIL;
41756Speter #else
42756Speter 	send(REVLAB, r);
43756Speter #endif
44756Speter 	if ( ! progseen ) {
45756Speter 	    level1();
46756Speter 	}
47756Speter 	line = l;
48756Speter #ifndef PI1
49835Speter 	if (parts[ cbn ] & (CPRT|TPRT|VPRT|RPRT)){
50835Speter 	    if ( opt( 's' ) ) {
51756Speter 		standard();
527951Speter 		error("Label declarations should precede const, type, var and routine declarations");
53835Speter 	    } else {
547951Speter 		if ( !label_order ) {
557951Speter 		    label_order = TRUE;
567951Speter 		    warning();
577951Speter 		    error("Label declarations should precede const, type, var and routine declarations");
587951Speter 		}
59835Speter 	    }
60756Speter 	}
61835Speter 	if (parts[ cbn ] & LPRT) {
62835Speter 	    if ( opt( 's' ) ) {
63756Speter 		standard();
647951Speter 		error("All labels should be declared in one label part");
65835Speter 	    } else {
667951Speter 		if ( !label_seen ) {
677951Speter 		    label_seen = TRUE;
687951Speter 		    warning();
697951Speter 		    error("All labels should be declared in one label part");
707951Speter 		}
71835Speter 	    }
72756Speter 	}
73835Speter 	parts[ cbn ] |= LPRT;
74756Speter #endif
75756Speter #ifndef PI0
7614733Sthien 	for (ll = r; ll != TR_NIL; ll = ll->list_node.next) {
7714733Sthien 		l = (int) getlab();
7814733Sthien 		p = enter(defnl((char *) ll->list_node.list, LABEL, NLNIL,
7914733Sthien 				(int) l));
80756Speter 		/*
81756Speter 		 * Get the label for the eventual target
82756Speter 		 */
8314733Sthien 		p->value[1] = (int) getlab();
84756Speter 		p->chain = lp;
85756Speter 		p->nl_flags |= (NFORWD|NMOD);
86756Speter 		p->value[NL_GOLEV] = NOTYET;
877919Smckusick 		p->value[NL_ENTLOC] = l;
88756Speter 		lp = p;
89756Speter #		ifdef OBJ
90756Speter 		    /*
91756Speter 		     * This operator is between
92756Speter 		     * the bodies of two procedures
93756Speter 		     * and provides a target for
94756Speter 		     * gotos for this label via TRA.
95756Speter 		     */
9614733Sthien 		    (void) putlab((char *) l);
9714733Sthien 		    (void) put(2, O_GOTO | cbn<<8, (long)p->value[1]);
98756Speter #		endif OBJ
99756Speter #		ifdef PC
100756Speter 		    /*
101756Speter 		     *	labels have to be .globl otherwise /lib/c2 may
102756Speter 		     *	throw them away if they aren't used in the function
103756Speter 		     *	which defines them.
104756Speter 		     */
1054880Speter 		    extlabname( extname , p -> symbol , cbn );
10614733Sthien 		    putprintf("	.globl	%s", 0, (int) extname);
1073366Speter 		    if ( cbn == 1 ) {
1083366Speter 			stabglabel( extname , line );
109756Speter 		    }
110756Speter #		endif PC
111756Speter 	}
112756Speter 	gotos[cbn] = lp;
113756Speter #	ifdef PTREE
114756Speter 	    {
115756Speter 		pPointer	Labels = LabelDCopy( r );
116756Speter 
117756Speter 		pDEF( PorFHeader[ nesting ] ).PorFLabels = Labels;
118756Speter 	    }
119756Speter #	endif PTREE
120756Speter #endif
121756Speter }
122756Speter 
123756Speter #ifndef PI0
124756Speter /*
125756Speter  * Gotoop is called when
126756Speter  * we get a statement "goto label"
127756Speter  * and generates the needed tra.
128756Speter  */
129756Speter gotoop(s)
130756Speter 	char *s;
131756Speter {
132756Speter 	register struct nl *p;
1333366Speter #ifdef PC
1343366Speter 	char	extname[ BUFSIZ ];
1353366Speter #endif PC
136756Speter 
137756Speter 	gocnt++;
138756Speter 	p = lookup(s);
139756Speter 	if (p == NIL)
14014733Sthien 		return;
141756Speter #	ifdef OBJ
14214733Sthien 	    (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]);
143756Speter #	endif OBJ
144756Speter #	ifdef PC
1459127Smckusick 	    if ( cbn == bn ) {
146756Speter 		    /*
1479127Smckusick 		     *	local goto.
1489127Smckusick 		     */
1499127Smckusick 		extlabname( extname , p -> symbol , bn );
1509137Smckusick 		    /*
15110655Speter 		     * this is a funny jump because it's to a label that
15210655Speter 		     * has been declared global.
15310655Speter 		     * Although this branch is within this module
15410655Speter 		     * the assembler will complain that the destination
15510655Speter 		     * is a global symbol.
15610655Speter 		     * The complaint arises because the assembler
15710655Speter 		     * doesn't change relative jumps into absolute jumps.
15810655Speter 		     * and this  may cause a branch displacement overflow
15910655Speter 		     * when the module is subsequently linked with
16010655Speter 		     * the rest of the program.
1619137Smckusick 		     */
16210655Speter #		ifdef vax
16314733Sthien 		    putprintf("	jmp	%s", 0, (int) extname);
16410655Speter #		endif vax
16510655Speter #		ifdef mc68000
16614733Sthien 		    putprintf("	jra	%s", 0, (int) extname);
16710655Speter #		endif mc68000
1689127Smckusick 	    } else {
1699127Smckusick 		    /*
1709127Smckusick 		     *	Non-local goto.
1719127Smckusick 		     *
1729120Smckusick 		     *  Close all active files between top of stack and
1739120Smckusick 		     *  frame at the destination level.	Then call longjmp
1749120Smckusick 		     *	to unwind the stack to the destination level.
1759127Smckusick 		     *
17610655Speter 		     *	For nested routines the end of the frame
17710655Speter 		     *	is calculated as:
17810655Speter 		     *	    __disply[bn].fp + sizeof(local frame)
17910655Speter 		     *	(adjusted by (sizeof int) to get just past the end).
1809127Smckusick 		     *	The size of the local frame is dumped out by
1819127Smckusick 		     *	the second pass as an assembler constant.
1829127Smckusick 		     *	The main routine may not be compiled in this
1839127Smckusick 		     *	module, so its size may not be available.
1849127Smckusick 		     * 	However all of its variables will be globally
1859127Smckusick 		     *	declared, so only the known runtime temporaries
1869127Smckusick 		     *	will be in its stack frame.
187756Speter 		     */
1889127Smckusick 		parts[ bn ] |= NONLOCALGOTO;
18918460Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1909120Smckusick 			, "_PCLOSE" );
1919120Smckusick 		if ( bn > 1 ) {
1929120Smckusick 		    p = lookup( enclosing[ bn - 1 ] );
19310655Speter 		    sprintf( extname, "%s%d+%d",
19410655Speter 			FRAME_SIZE_LABEL, p -> value[NL_ENTLOC], sizeof(int));
1959120Smckusick 		    p = lookup(s);
19618460Sralph 		    putLV( extname , bn , 0 , NNLOCAL , PCCTM_PTR | PCCT_CHAR );
1979120Smckusick 		} else {
19814733Sthien 		    putLV((char *) 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR ,
19918460Sralph 			PCCTM_PTR | PCCT_CHAR );
2009120Smckusick 		}
20118460Sralph 		putop( PCC_CALL , PCCT_INT );
202756Speter 		putdot( filename , line );
20318460Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
2049120Smckusick 			, "_longjmp" );
20518460Sralph 		putLV((char *) 0 , bn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
2069120Smckusick 		extlabname( extname , p -> symbol , bn );
20718460Sralph 		putLV( extname , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
20818460Sralph 		putop( PCC_CM , PCCT_INT );
20918460Sralph 		putop( PCC_CALL , PCCT_INT );
2109120Smckusick 		putdot( filename , line );
211756Speter 	    }
212756Speter #	endif PC
213756Speter 	if (bn == cbn)
214756Speter 		if (p->nl_flags & NFORWD) {
215756Speter 			if (p->value[NL_GOLEV] == NOTYET) {
216756Speter 				p->value[NL_GOLEV] = level;
217756Speter 				p->value[NL_GOLINE] = line;
218756Speter 			}
219756Speter 		} else
220756Speter 			if (p->value[NL_GOLEV] == DEAD) {
221756Speter 				recovered();
222756Speter 				error("Goto %s is into a structured statement", p->symbol);
223756Speter 			}
224756Speter }
225756Speter 
226756Speter /*
227756Speter  * Labeled is called when a label
228756Speter  * definition is encountered, and
229756Speter  * marks that it has been found and
230756Speter  * patches the associated GOTO generated
231756Speter  * by gotoop.
232756Speter  */
233756Speter labeled(s)
234756Speter 	char *s;
235756Speter {
236756Speter 	register struct nl *p;
2373366Speter #ifdef PC
2383366Speter 	char	extname[ BUFSIZ ];
2393366Speter #endif PC
240756Speter 
241756Speter 	p = lookup(s);
242756Speter 	if (p == NIL)
24314733Sthien 		return;
244756Speter 	if (bn != cbn) {
245756Speter 		error("Label %s not defined in correct block", s);
246756Speter 		return;
247756Speter 	}
248756Speter 	if ((p->nl_flags & NFORWD) == 0) {
249756Speter 		error("Label %s redefined", s);
250756Speter 		return;
251756Speter 	}
252756Speter 	p->nl_flags &= ~NFORWD;
253756Speter #	ifdef OBJ
25414733Sthien 	    patch4((PTR_DCL) p->value[NL_ENTLOC]);
255756Speter #	endif OBJ
256756Speter #	ifdef PC
2574880Speter 	    extlabname( extname , p -> symbol , bn );
25814733Sthien 	    putprintf( "%s:" , 0 , (int) extname );
259756Speter #	endif PC
260756Speter 	if (p->value[NL_GOLEV] != NOTYET)
261756Speter 		if (p->value[NL_GOLEV] < level) {
262756Speter 			recovered();
26314733Sthien 			error("Goto %s from line %d is into a structured statement", s, (char *) p->value[NL_GOLINE]);
264756Speter 		}
265756Speter 	p->value[NL_GOLEV] = level;
266756Speter }
267756Speter #endif
2684880Speter 
2694880Speter #ifdef PC
2704880Speter     /*
2714880Speter      *	construct the long name of a label based on it's static nesting.
2724880Speter      *	into a caller-supplied buffer (that should be about BUFSIZ big).
2734880Speter      */
2744880Speter extlabname( buffer , name , level )
2754880Speter     char	buffer[];
2764880Speter     char	*name;
2774880Speter     int		level;
2784880Speter {
2794880Speter     char	*starthere;
2804880Speter     int		i;
2814880Speter 
2824880Speter     starthere = &buffer[0];
2834880Speter     for ( i = 1 ; i < level ; i++ ) {
2844880Speter 	sprintf( starthere , EXTFORMAT , enclosing[ i ] );
2854880Speter 	starthere += strlen( enclosing[ i ] ) + 1;
2864880Speter     }
2874880Speter     sprintf( starthere , EXTFORMAT , "" );
2884880Speter     starthere += 1;
2894880Speter     sprintf( starthere , LABELFORMAT , name );
2904880Speter     starthere += strlen( name ) + 1;
2914880Speter     if ( starthere >= &buffer[ BUFSIZ ] ) {
2924880Speter 	panic( "extlabname" );
2934880Speter     }
2944880Speter }
2954880Speter #endif PC
296