* Copyright (c) 1980 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)case.c 5.3 (Berkeley) 4/16/91";
* pascal case statement code
register struct ct
*ctab
;
register struct tnode
*cs
;
* Obtain selector attributes:
p
= rvalue(rnode
->expr
, NLNIL
, RREQ
);
error("Case selectors cannot be %ss", nameof(p
));
if (p
->class != (char) RANGE
)
} /* local declaration */
struct tnode
*cl
; /* list node */
for (cl
= rnode
->stmnt_list
; cl
!= TR_NIL
;
cl
= cl
->list_node
.next
) {
cs
= cl
->list_node
.list
;;
for (cs
= cs
->c_stmnt
.const_list
; cs
!= TR_NIL
;
} /* local declaration */
* Allocate case table space
i
= malloc((unsigned) n
* sizeof *ctab
);
error("Ran out of memory (case)");
* Check the legality of the
* labels and count the number
register struct tnode
*cl
;
for (cl
= rnode
->stmnt_list
; cl
!= TR_NIL
;
cl
= cl
->list_node
.next
) {
line
= cs
->c_stmnt
.line_no
;
for (cs
= cs
->c_stmnt
.const_list
; cs
!= TR_NIL
;
cs
= cs
->list_node
.next
) {
gconst(cs
->list_node
.list
);
if (p
== NLNIL
|| con
.ctype
== NIL
)
if (incompat(con
.ctype
, p
, TR_NIL
)) {
cerror("Case label type clashed with case selector expression type");
if (con
.crval
< low
|| con
.crval
> high
) {
error("Case label out of range");
ctab
[m
].clong
= con
.crval
;
* Check for duplicate labels
if (ctab
[i
].clong
== ctab
[j
].clong
) {
error("Multiply defined label in case, lines %d and %d", (char *) ctab
[i
].cline
, (char *) ctab
[j
].cline
);
* Put out case operator and
(void) put(2, O_CASE1OP
+ (w
>> 1), n
);
brtab
= ((short *) brtab0
);
(void) put(1, O_CASEBEG
);
(void) put(2 ,O_CASE1
+ (w
>> 1), (int)ctab
[i
].clong
);
(void) put(2 ,O_CASE4
, ctab
[i
].clong
);
(void) put(1, O_CASEEND
);
(void) put(2, O_TRA
, csend
);
* statement. Patch branch
* table to beginning of each
* statement and follow each
* statement with a branch back
register struct tnode
*cl
;
for (cl
= rnode
->stmnt_list
; cl
!= TR_NIL
;
cl
= cl
->list_node
.next
) {
for (cs
= cs
->c_stmnt
.const_list
; cs
!= TR_NIL
;
cs
= cs
->list_node
.next
) {
patchfil(((char *) (brtab
- 1)),
patchfil( ((unsigned long) (brtab
- 1)),
statement(cs
->c_stmnt
.stmnt
);
nr
= (bool)(noreach
&& nr
);
(void) put(2, O_TRA
, csend
);
* Patch the termination branch
patch((unsigned long) csend
);