/* Copyright (c) 1979 Regents of the University of California */
static char sccsid
[] = "@(#)lab.c 1.17 2/1/83";
* Label enters the definitions
* of the label declaration part
static bool label_order
= FALSE
;
static bool label_seen
= FALSE
;
register struct nl
*p
, *lp
;
if (parts
[ cbn
] & (CPRT
|TPRT
|VPRT
|RPRT
)){
error("Label declarations should precede const, type, var and routine declarations");
error("Label declarations should precede const, type, var and routine declarations");
if (parts
[ cbn
] & LPRT
) {
error("All labels should be declared in one label part");
error("All labels should be declared in one label part");
for (ll
= r
; ll
!= NIL
; ll
= ll
[2]) {
p
= enter(defnl(ll
[1], LABEL
, 0, l
));
* Get the label for the eventual target
p
->nl_flags
|= (NFORWD
|NMOD
);
p
->value
[NL_GOLEV
] = NOTYET
;
* This operator is between
* the bodies of two procedures
* and provides a target for
* gotos for this label via TRA.
put(2, O_GOTO
| cbn
<<8, (long)p
->value
[1]);
* labels have to be .globl otherwise /lib/c2 may
* throw them away if they aren't used in the function
extlabname( extname
, p
-> symbol
, cbn
);
putprintf(" .globl %s", 0, extname
);
stabglabel( extname
, line
);
pPointer Labels
= LabelDCopy( r
);
pDEF( PorFHeader
[ nesting
] ).PorFLabels
= Labels
;
* we get a statement "goto label"
* and generates the needed tra.
put(2, O_TRA4
, (long)p
->value
[NL_ENTLOC
]);
extlabname( extname
, p
-> symbol
, bn
);
* this is a funny jump because it's to a label that
* has been declared global.
* Although this branch is within this module
* the assembler will complain that the destination
* The complaint arises because the assembler
* doesn't change relative jumps into absolute jumps.
* and this may cause a branch displacement overflow
* when the module is subsequently linked with
* the rest of the program.
putprintf(" jmp %s", 0, extname
);
putprintf(" jra %s", 0, extname
);
* Close all active files between top of stack and
* frame at the destination level. Then call longjmp
* to unwind the stack to the destination level.
* For nested routines the end of the frame
* __disply[bn].fp + sizeof(local frame)
* (adjusted by (sizeof int) to get just past the end).
* The size of the local frame is dumped out by
* the second pass as an assembler constant.
* The main routine may not be compiled in this
* module, so its size may not be available.
* However all of its variables will be globally
* declared, so only the known runtime temporaries
* will be in its stack frame.
parts
[ bn
] |= NONLOCALGOTO
;
putleaf( P2ICON
, 0 , 0 , ADDTYPE( P2FTN
| P2INT
, P2PTR
)
p
= lookup( enclosing
[ bn
- 1 ] );
sprintf( extname
, "%s%d+%d",
FRAME_SIZE_LABEL
, p
-> value
[NL_ENTLOC
], sizeof(int));
putLV( extname
, bn
, 0 , NNLOCAL
, P2PTR
| P2CHAR
);
putLV( 0 , bn
, -( DPOFF1
+ sizeof( int ) ) , LOCALVAR
,
putdot( filename
, line
);
putleaf( P2ICON
, 0 , 0 , ADDTYPE( P2FTN
| P2INT
, P2PTR
)
putLV( 0 , bn
, GOTOENVOFFSET
, NLOCAL
, P2PTR
|P2STRTY
);
extlabname( extname
, p
-> symbol
, bn
);
putLV( extname
, 0 , 0 , NGLOBAL
, P2PTR
|P2STRTY
);
putop( P2LISTOP
, P2INT
);
putdot( filename
, line
);
if (p
->nl_flags
& NFORWD
) {
if (p
->value
[NL_GOLEV
] == NOTYET
) {
p
->value
[NL_GOLEV
] = level
;
p
->value
[NL_GOLINE
] = line
;
if (p
->value
[NL_GOLEV
] == DEAD
) {
error("Goto %s is into a structured statement", p
->symbol
);
* Labeled is called when a label
* definition is encountered, and
* marks that it has been found and
* patches the associated GOTO generated
error("Label %s not defined in correct block", s
);
if ((p
->nl_flags
& NFORWD
) == 0) {
error("Label %s redefined", s
);
patch4(p
->value
[NL_ENTLOC
]);
extlabname( extname
, p
-> symbol
, bn
);
putprintf( "%s:" , 0 , extname
);
if (p
->value
[NL_GOLEV
] != NOTYET
)
if (p
->value
[NL_GOLEV
] < level
) {
error("Goto %s from line %d is into a structured statement", s
, p
->value
[NL_GOLINE
]);
p
->value
[NL_GOLEV
] = level
;
* construct the long name of a label based on it's static nesting.
* into a caller-supplied buffer (that should be about BUFSIZ big).
extlabname( buffer
, name
, level
)
for ( i
= 1 ; i
< level
; i
++ ) {
sprintf( starthere
, EXTFORMAT
, enclosing
[ i
] );
starthere
+= strlen( enclosing
[ i
] ) + 1;
sprintf( starthere
, EXTFORMAT
, "" );
sprintf( starthere
, LABELFORMAT
, name
);
starthere
+= strlen( name
) + 1;
if ( starthere
>= &buffer
[ BUFSIZ
] ) {