new copyright; att/bsd/shared
[unix-history] / usr / src / usr.bin / pascal / src / lab.c
CommitLineData
0fc6e47b
KB
1/*-
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
1259848a 6 */
17f3476e 7
72fbef68 8#ifndef lint
0fc6e47b
KB
9static char sccsid[] = "@(#)lab.c 5.3 (Berkeley) %G%";
10#endif /* not lint */
17f3476e
PK
11
12#include "whoami.h"
13#include "0.h"
14#include "tree.h"
15#include "opcode.h"
16#include "objfmt.h"
17#ifdef PC
18# include "pc.h"
c60bfb0d 19# include <pcc.h>
17f3476e 20#endif PC
72fbef68 21#include "tree_ty.h"
17f3476e
PK
22
23/*
24 * Label enters the definitions
25 * of the label declaration part
26 * into the namelist.
27 */
28label(r, l)
72fbef68
RT
29 struct tnode *r;
30 int l;
17f3476e 31{
7204688c
PK
32 static bool label_order = FALSE;
33 static bool label_seen = FALSE;
c2b6243b
PK
34#ifdef PC
35 char extname[ BUFSIZ ];
36#endif PC
17f3476e 37#ifndef PI0
72fbef68 38 register struct tnode *ll;
17f3476e
PK
39 register struct nl *p, *lp;
40
41 lp = NIL;
42#else
43 send(REVLAB, r);
44#endif
45 if ( ! progseen ) {
46 level1();
47 }
48 line = l;
49#ifndef PI1
af97bcfa
PK
50 if (parts[ cbn ] & (CPRT|TPRT|VPRT|RPRT)){
51 if ( opt( 's' ) ) {
17f3476e 52 standard();
7204688c 53 error("Label declarations should precede const, type, var and routine declarations");
af97bcfa 54 } else {
7204688c
PK
55 if ( !label_order ) {
56 label_order = TRUE;
57 warning();
58 error("Label declarations should precede const, type, var and routine declarations");
59 }
af97bcfa 60 }
17f3476e 61 }
af97bcfa
PK
62 if (parts[ cbn ] & LPRT) {
63 if ( opt( 's' ) ) {
17f3476e 64 standard();
7204688c 65 error("All labels should be declared in one label part");
af97bcfa 66 } else {
7204688c
PK
67 if ( !label_seen ) {
68 label_seen = TRUE;
69 warning();
70 error("All labels should be declared in one label part");
71 }
af97bcfa 72 }
17f3476e 73 }
af97bcfa 74 parts[ cbn ] |= LPRT;
17f3476e
PK
75#endif
76#ifndef PI0
72fbef68
RT
77 for (ll = r; ll != TR_NIL; ll = ll->list_node.next) {
78 l = (int) getlab();
79 p = enter(defnl((char *) ll->list_node.list, LABEL, NLNIL,
80 (int) l));
17f3476e
PK
81 /*
82 * Get the label for the eventual target
83 */
72fbef68 84 p->value[1] = (int) getlab();
17f3476e
PK
85 p->chain = lp;
86 p->nl_flags |= (NFORWD|NMOD);
87 p->value[NL_GOLEV] = NOTYET;
fa5256b7 88 p->value[NL_ENTLOC] = l;
17f3476e
PK
89 lp = p;
90# ifdef OBJ
91 /*
92 * This operator is between
93 * the bodies of two procedures
94 * and provides a target for
95 * gotos for this label via TRA.
96 */
72fbef68
RT
97 (void) putlab((char *) l);
98 (void) put(2, O_GOTO | cbn<<8, (long)p->value[1]);
17f3476e
PK
99# endif OBJ
100# ifdef PC
101 /*
102 * labels have to be .globl otherwise /lib/c2 may
103 * throw them away if they aren't used in the function
104 * which defines them.
105 */
e2345d2c 106 extlabname( extname , p -> symbol , cbn );
72fbef68 107 putprintf(" .globl %s", 0, (int) extname);
c2b6243b
PK
108 if ( cbn == 1 ) {
109 stabglabel( extname , line );
17f3476e
PK
110 }
111# endif PC
112 }
113 gotos[cbn] = lp;
114# ifdef PTREE
115 {
116 pPointer Labels = LabelDCopy( r );
117
118 pDEF( PorFHeader[ nesting ] ).PorFLabels = Labels;
119 }
120# endif PTREE
121#endif
122}
123
124#ifndef PI0
125/*
126 * Gotoop is called when
127 * we get a statement "goto label"
128 * and generates the needed tra.
129 */
130gotoop(s)
131 char *s;
132{
133 register struct nl *p;
c2b6243b
PK
134#ifdef PC
135 char extname[ BUFSIZ ];
136#endif PC
17f3476e
PK
137
138 gocnt++;
139 p = lookup(s);
140 if (p == NIL)
72fbef68 141 return;
17f3476e 142# ifdef OBJ
72fbef68 143 (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]);
17f3476e
PK
144# endif OBJ
145# ifdef PC
199b9670 146 if ( cbn == bn ) {
17f3476e 147 /*
199b9670
KM
148 * local goto.
149 */
150 extlabname( extname , p -> symbol , bn );
b3f9e9d3 151 /*
ebd83b21
PK
152 * this is a funny jump because it's to a label that
153 * has been declared global.
154 * Although this branch is within this module
155 * the assembler will complain that the destination
156 * is a global symbol.
157 * The complaint arises because the assembler
158 * doesn't change relative jumps into absolute jumps.
159 * and this may cause a branch displacement overflow
160 * when the module is subsequently linked with
161 * the rest of the program.
b3f9e9d3 162 */
fe8ff1f7 163# if defined(vax) || defined(tahoe)
72fbef68 164 putprintf(" jmp %s", 0, (int) extname);
fe8ff1f7 165# endif vax || tahoe
ebd83b21 166# ifdef mc68000
72fbef68 167 putprintf(" jra %s", 0, (int) extname);
ebd83b21 168# endif mc68000
199b9670
KM
169 } else {
170 /*
171 * Non-local goto.
172 *
32882102
KM
173 * Close all active files between top of stack and
174 * frame at the destination level. Then call longjmp
175 * to unwind the stack to the destination level.
199b9670 176 *
ebd83b21
PK
177 * For nested routines the end of the frame
178 * is calculated as:
179 * __disply[bn].fp + sizeof(local frame)
180 * (adjusted by (sizeof int) to get just past the end).
199b9670
KM
181 * The size of the local frame is dumped out by
182 * the second pass as an assembler constant.
183 * The main routine may not be compiled in this
184 * module, so its size may not be available.
185 * However all of its variables will be globally
186 * declared, so only the known runtime temporaries
187 * will be in its stack frame.
17f3476e 188 */
199b9670 189 parts[ bn ] |= NONLOCALGOTO;
c60bfb0d 190 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
32882102 191 , "_PCLOSE" );
32882102
KM
192 if ( bn > 1 ) {
193 p = lookup( enclosing[ bn - 1 ] );
ebd83b21
PK
194 sprintf( extname, "%s%d+%d",
195 FRAME_SIZE_LABEL, p -> value[NL_ENTLOC], sizeof(int));
32882102 196 p = lookup(s);
c60bfb0d 197 putLV( extname , bn , 0 , NNLOCAL , PCCTM_PTR | PCCT_CHAR );
32882102 198 } else {
72fbef68 199 putLV((char *) 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR ,
c60bfb0d 200 PCCTM_PTR | PCCT_CHAR );
32882102 201 }
c60bfb0d 202 putop( PCC_CALL , PCCT_INT );
17f3476e 203 putdot( filename , line );
c60bfb0d 204 putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
32882102 205 , "_longjmp" );
c60bfb0d 206 putLV((char *) 0 , bn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
32882102 207 extlabname( extname , p -> symbol , bn );
c60bfb0d
RC
208 putLV( extname , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
209 putop( PCC_CM , PCCT_INT );
210 putop( PCC_CALL , PCCT_INT );
32882102 211 putdot( filename , line );
17f3476e 212 }
17f3476e
PK
213# endif PC
214 if (bn == cbn)
215 if (p->nl_flags & NFORWD) {
216 if (p->value[NL_GOLEV] == NOTYET) {
217 p->value[NL_GOLEV] = level;
218 p->value[NL_GOLINE] = line;
219 }
220 } else
221 if (p->value[NL_GOLEV] == DEAD) {
222 recovered();
223 error("Goto %s is into a structured statement", p->symbol);
224 }
225}
226
227/*
228 * Labeled is called when a label
229 * definition is encountered, and
230 * marks that it has been found and
231 * patches the associated GOTO generated
232 * by gotoop.
233 */
234labeled(s)
235 char *s;
236{
237 register struct nl *p;
c2b6243b
PK
238#ifdef PC
239 char extname[ BUFSIZ ];
240#endif PC
17f3476e
PK
241
242 p = lookup(s);
243 if (p == NIL)
72fbef68 244 return;
17f3476e
PK
245 if (bn != cbn) {
246 error("Label %s not defined in correct block", s);
247 return;
248 }
249 if ((p->nl_flags & NFORWD) == 0) {
250 error("Label %s redefined", s);
251 return;
252 }
253 p->nl_flags &= ~NFORWD;
254# ifdef OBJ
72fbef68 255 patch4((PTR_DCL) p->value[NL_ENTLOC]);
17f3476e
PK
256# endif OBJ
257# ifdef PC
e2345d2c 258 extlabname( extname , p -> symbol , bn );
72fbef68 259 putprintf( "%s:" , 0 , (int) extname );
17f3476e
PK
260# endif PC
261 if (p->value[NL_GOLEV] != NOTYET)
262 if (p->value[NL_GOLEV] < level) {
263 recovered();
72fbef68 264 error("Goto %s from line %d is into a structured statement", s, (char *) p->value[NL_GOLINE]);
17f3476e
PK
265 }
266 p->value[NL_GOLEV] = level;
267}
268#endif
e2345d2c
PK
269
270#ifdef PC
271 /*
272 * construct the long name of a label based on it's static nesting.
273 * into a caller-supplied buffer (that should be about BUFSIZ big).
274 */
275extlabname( buffer , name , level )
276 char buffer[];
277 char *name;
278 int level;
279{
280 char *starthere;
281 int i;
282
283 starthere = &buffer[0];
284 for ( i = 1 ; i < level ; i++ ) {
285 sprintf( starthere , EXTFORMAT , enclosing[ i ] );
286 starthere += strlen( enclosing[ i ] ) + 1;
287 }
288 sprintf( starthere , EXTFORMAT , "" );
289 starthere += 1;
290 sprintf( starthere , LABELFORMAT , name );
291 starthere += strlen( name ) + 1;
292 if ( starthere >= &buffer[ BUFSIZ ] ) {
293 panic( "extlabname" );
294 }
295}
296#endif PC