* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)cset.c 5.1 (Berkeley) 6/5/85";
* CONSETS causes compile time constant sets to be constructed here.
* COMPSETSZE defines the maximum number of longs to be used in
* constant set construction
* rummage through a `constant' set (i.e. anything within [ ]'s) tree
* and decide if this is a compile time constant set or a runtime set.
* this information is returned in a structure passed from the caller.
* while rummaging, this also reorders the tree so that all ranges
* preceed all singletons.
precset( r
, settype
, csetp
)
register struct tnode
*e
;
register struct nl
*exptype
;
register struct tnode
*el
;
register struct tnode
*pairp
;
register struct tnode
*singp
;
csetp
-> comptime
= TRUE
;
if ( settype
-> class == SET
) {
* the easy case, we are told the type of the set.
exptype
= settype
-> type
;
* we are told the type, but it's not a set
* supposedly possible if someone tries
* e.g string context [1,2] = 'abc'
error("Constant set involved in non set context");
return csetp
-> comptime
;
* So far we have no indication
* of what the set type should be.
* We "look ahead" and try to infer
* The type of the constant set
* by evaluating one of its members.
e
= r
->cset_node
.el_list
;
* tentative for [], return type of `intset'
settype
= lookup( (char *) intset
);
settype
= settype
-> type
;
return csetp
-> comptime
;
if ( isnta( settype
, "t" ) ) {
error("Set default type \"intset\" is not a set");
return csetp
-> comptime
;
csetp
-> csettype
= settype
;
setran( settype
-> type
);
if (((set
.uprbp
+ 1) >> LG2BITSLONG
) >= COMPSETSZE
)
csetp
-> comptime
= FALSE
;
return csetp
-> comptime
;
return csetp
-> comptime
;
t
= rvalue(e
, NLNIL
, RREQ
);
return csetp
-> comptime
;
* The type of the set, settype, is
* deemed to be a set of the base type
* of t, which we call exptype. If,
* however, this would involve a
* "set of integer", we cop out
* and use "intset"'s current scoped
error("Sets may not have 'real' elements");
return csetp
-> comptime
;
error("Set elements must be scalars, not %ss", nameof(t
));
return csetp
-> comptime
;
settype
= lookup((char *) intset
);
return csetp
-> comptime
;
if (isnta(settype
, "t")) {
error("Set default type \"intset\" is not a set");
return csetp
-> comptime
;
* say we are doing an intset
* but, if we get out of range errors for intset
* we punt constructing the set at compile time.
return csetp
-> comptime
;
if (exptype
->class != RANGE
)
settype
= defnl((char *) 0, SET
, exptype
, 0);
csetp
-> csettype
= settype
;
csetp
-> comptime
= FALSE
;
if (((set
.uprbp
+ 1) >> LG2BITSLONG
) >= COMPSETSZE
)
csetp
-> comptime
= FALSE
;
upper
= set
.lwrb
+ set
.uprbp
;
while ( el
= r
->cset_node
.el_list
) {
* don't hang this one anywhere.
r
->cset_node
.el_list
= el
->list_node
.next
;
if ( csetp
-> comptime
&& constval( e
->rang
.expr2
) ) {
if ( con
.crval
< lower
|| con
.crval
> upper
) {
csetp
-> comptime
= FALSE
;
error("Range upper bound of %D out of set bounds" , ((long)con
.crval
) );
csetp
-> comptime
= FALSE
;
t
= rvalue(e
->rang
.expr2
, NLNIL
, RREQ
);
(void) rvalue(e
->rang
.expr1
, NLNIL
, RREQ
);
if (incompat(t
, exptype
, e
->rang
.expr2
)) {
cerror("Upper bound of element type clashed with set type in constant set");
if ( csetp
-> comptime
&& constval( e
->rang
.expr1
) ) {
if ( con
.crval
< lower
|| con
.crval
> upper
) {
csetp
-> comptime
= FALSE
;
error("Range lower bound of %D out of set bounds" , ((long)con
.crval
) );
csetp
-> comptime
= FALSE
;
t
= rvalue(e
->rang
.expr1
, NLNIL
, RREQ
);
if (incompat(t
, exptype
, e
->rang
.expr1
)) {
cerror("Lower bound of element type clashed with set type in constant set");
* remove this range from the tree list and
* hang it on the pairs list.
el
->list_node
.next
= pairp
;
pairp
= r
->cset_node
.el_list
;
r
->cset_node
.el_list
= ip
;
if ( csetp
-> comptime
&& constval( e
) ) {
if ( con
.crval
< lower
|| con
.crval
> upper
) {
csetp
-> comptime
= FALSE
;
error("Value of %D out of set bounds" , ((long)con
.crval
) );
csetp
-> comptime
= FALSE
;
t
= rvalue( e
, NLNIL
, RREQ
);
if (incompat(t
, exptype
, e
)) {
cerror("Element type clashed with set type in constant set");
* take this expression off the tree list and
* hang it on the list of singletons.
el
->list_node
.next
= singp
;
singp
= r
->cset_node
.el_list
;
r
->cset_node
.el_list
= ip
;
for ( el
= pairp
; el
->list_node
.next
!= NIL
; el
= el
->list_node
.next
) /* void */;
el
->list_node
.next
= singp
;
r
->cset_node
.el_list
= pairp
;
r
->cset_node
.el_list
= singp
;
for ( el
= singp
; el
->list_node
.next
!= NIL
; el
= el
->list_node
.next
) /* void */;
el
->list_node
.next
= pairp
;
r
->cset_node
.el_list
= singp
;
r
->cset_node
.el_list
= pairp
;
if ( csetp
-> csettype
== NIL
) {
csetp
-> comptime
= TRUE
;
return csetp
-> comptime
;
* mask[i] has the low i bits turned off.
0xffffffff , 0xfffffffe , 0xfffffffc , 0xfffffff8 ,
0xfffffff0 , 0xffffffe0 , 0xffffffc0 , 0xffffff80 ,
0xffffff00 , 0xfffffe00 , 0xfffffc00 , 0xfffff800 ,
0xfffff000 , 0xffffe000 , 0xffffc000 , 0xffff8000 ,
0xffff0000 , 0xfffe0000 , 0xfffc0000 , 0xfff80000 ,
0xfff00000 , 0xffe00000 , 0xffc00000 , 0xff800000 ,
0xff000000 , 0xfe000000 , 0xfc000000 , 0xf8000000 ,
0xf0000000 , 0xe0000000 , 0xc0000000 , 0x80000000 ,
0xffffffff , 0xfeffffff , 0xfcffffff , 0xf8ffffff ,
0xf0ffffff , 0xe0ffffff , 0xc0ffffff , 0x80ffffff ,
0x00ffffff , 0x00feffff , 0x00fcffff , 0x00f8ffff ,
0x00f0ffff , 0x00e0ffff , 0x00c0ffff , 0x0080ffff ,
0x0000ffff , 0x0000feff , 0x0000fcff , 0x0000f8ff ,
0x0000f0ff , 0x0000e0ff , 0x0000c0ff , 0x000080ff ,
0x000000ff , 0x000000fe , 0x000000fc , 0x000000f8 ,
0x000000f0 , 0x000000e0 , 0x000000c0 , 0x00000080 ,
* given a csetstr, either
* put out a compile time constant set and an lvalue to it.
* put out rvalues for the singletons and the pairs
register struct tnode
*el
;
register struct tnode
*e
;
long tempset
[ COMPSETSZE
];
char labelname
[ BUFSIZ
];
if ( csetp
-> comptime
) {
setran( ( csetp
-> csettype
) -> type
);
limit
= &tempset
[ ( set
.uprbp
>> LG2BITSLONG
) + 1 ];
for ( lp
= &tempset
[0] ; lp
< limit
; lp
++ ) {
for ( el
= r
->cset_node
.el_list
; el
!= NIL
; el
= el
->list_node
.next
) {
if ( e
->tag
== T_RANG
) {
(void) constval( e
->rang
.expr1
);
(void) constval( e
->rang
.expr2
);
lowerdiv
= ( lower
- set
.lwrb
) >> LG2BITSLONG
;
lowermod
= ( lower
- set
.lwrb
) & MSKBITSLONG
;
upperdiv
= ( upper
- set
.lwrb
) >> LG2BITSLONG
;
uppermod
= ( upper
- set
.lwrb
) & MSKBITSLONG
;
if ( lowerdiv
== upperdiv
) {
temp
&= ~mask
[ uppermod
+ 1 ];
tempset
[ lowerdiv
] |= temp
;
limit
= &tempset
[ upperdiv
-1 ];
for ( lp
= &tempset
[ lowerdiv
+1 ] ; lp
<= limit
; lp
++ ) {
if ( lowerdiv
!= upperdiv
) {
tempset
[ upperdiv
] |= ~mask
[ uppermod
+ 1 ];
temp
= con
.crval
- set
.lwrb
;
cp
[temp
>> LG2BITSBYTE
] |= (1 << (temp
& MSKBITSBYTE
));
putprintf(" .data" , 0 );
(void) putlab( (char *) label
);
limit
= &tempset
[ ( set
.uprbp
>> LG2BITSLONG
) + 1 ];
putprintf(" .long 0x%x", 1, (int) (*lp
++));
for (temp
= 2 ; temp
<= 8 && lp
< limit
; temp
++) {
putprintf(",0x%x", 1, (int) (*lp
++));
sprintf( labelname
, PREFIXFORMAT
, LABELPREFIX
, (char *) label
);
putleaf( PCC_ICON
, 0 , 0 , PCCTM_PTR
| PCCT_STRTY
, labelname
);
(void) put(2, O_CON
, (int)(((set
.uprbp
>> LG2BITSLONG
) + 1) *
(BITSPERLONG
>> LG2BITSBYTE
)));
limit
= &tempset
[ ( set
.uprbp
>> LG2BITSLONG
) + 1 ];
(void) put(2, O_CASE4
, (int) (*lp
++));
putleaf( PCC_ICON
, (int) csetp
-> paircnt
, 0 , PCCT_INT
, (char *) 0 );
putop( PCC_CM
, PCCT_INT
);
putleaf( PCC_ICON
, (int) csetp
-> singcnt
, 0 , PCCT_INT
, (char *) 0 );
putop( PCC_CM
, PCCT_INT
);
for ( el
= r
->cset_node
.el_list
; el
!= NIL
; el
= el
->list_node
.next
) {
if ( e
->tag
== T_RANG
) {
(void) rvalue( e
->rang
.expr2
, NLNIL
, RREQ
);
putop( PCC_CM
, PCCT_INT
);
(void) rvalue( e
->rang
.expr1
, NLNIL
, RREQ
);
putop( PCC_CM
, PCCT_INT
);
(void) rvalue( e
, NLNIL
, RREQ
);
putop( PCC_CM
, PCCT_INT
);
for ( el
= r
->cset_node
.el_list
; el
!= NIL
; el
= el
->list_node
.next
) {
if ( e
->tag
== T_RANG
) {
(void) stkrval( e
->rang
.expr1
, NLNIL
, (long) RREQ
);
(void) stkrval( e
->rang
.expr2
, NLNIL
, (long) RREQ
);
(void) stkrval( e
, NLNIL
, (long) RREQ
);
(void) put(2 , O_CON24
, (int)csetp
-> singcnt
);
(void) put(2 , O_CON24
, (int)csetp
-> paircnt
);