4.3BSD/usr/contrib/icon/operators/unioncs.c
#include "../h/rt.h"
/*
* x ++ y - union of csets x and y or of sets x and y.
*/
unioncs(nargs, arg2, arg1, arg0)
int nargs;
struct descrip arg2, arg1, arg0;
{
DclSave
register int i;
union block *bp;
int *cs1, *cs2, csbuf1[CSETSIZE], csbuf2[CSETSIZE];
extern struct b_cset *alccset();
#ifdef SETS
int res;
struct b_set *srcp, *tstp, *dstp;
struct b_selem *ep;
struct descrip *dp, *hook;
extern struct b_set *alcset();
extern struct b_selem *alcselem();
extern struct descrip *memb();
#endif SETS
SetBound;
#ifdef SETS
DeRef(arg1)
DeRef(arg2)
if (QUAL(arg1) || QUAL(arg2))
goto skipsets;
if (TYPE(arg1) == T_SET && TYPE(arg2) != T_SET)
runerr(119,&arg2);
if (TYPE(arg2) == T_SET && TYPE(arg1) != T_SET)
runerr(119,&arg1);
if (TYPE(arg1) == T_SET && TYPE(arg2) == T_SET) {
/*
* Both x and y are sets - do set union
* get enough space for a set as big as x + y.
*/
hneed(sizeof(struct b_set) + (BLKLOC(arg1)->set.setsize +
BLKLOC(arg2)->set.setsize) * sizeof(struct b_selem));
/*
* Select the larger of the two sets as the source
* copy each element to a new set for the result
* then insert each member of the second set into the
* result set if it is not already there.
*/
if (BLKLOC(arg1)->set.setsize >= BLKLOC(arg2)->set.setsize) {
srcp = (struct b_set *) BLKLOC(arg1);
tstp = (struct b_set *) BLKLOC(arg2);
}
else {
srcp = (struct b_set *) BLKLOC(arg2);
tstp = (struct b_set *) BLKLOC(arg1);
}
arg0.type = D_SET;
dstp = alcset();
BLKLOC(arg0) = (union block *) dstp;
for (i = 0; i < NBUCKETS; i++) {
ep = (struct b_selem *) BLKLOC(srcp->sbucks[i]);
dp = &dstp->sbucks[i];
while (ep != NULL) {
dp->type = D_SELEM;
BLKLOC(*dp) = (union block *) alcselem(&ep->setmem, ep->hnum);
dp = &BLKLOC(*dp)->selem.sblink;
dstp->setsize++;
ep = (struct b_selem *) BLKLOC(ep->sblink);
}
}
for (i = 0; i < NBUCKETS; i++) {
ep = (struct b_selem *) BLKLOC(tstp->sbucks[i]);
while (ep != NULL) {
hook = memb(dstp, &ep->setmem, ep->hnum, &res);
if (res == 0)
addmem(dstp, alcselem(&ep->setmem, ep->hnum), hook);
ep = (struct b_selem *) BLKLOC(ep->sblink);
}
}
}
else {
skipsets:
#endif SETS
hneed(sizeof(struct b_cset));
/*
* x and y must be csets.
*/
if (cvcset(&arg1, &cs1, csbuf1) == NULL)
runerr(104, &arg1);
if (cvcset(&arg2, &cs2, csbuf2) == NULL)
runerr(104, &arg2);
/*
* Allocate a new cset and in each word of it, compute the value
* of the bitwise union of the corresponding words in the
* x and y csets.
*/
bp = (union block *) alccset();
for (i = 0; i < CSETSIZE; i++)
bp->cset.bits[i] = cs1[i] | cs2[i];
arg0.type = D_CSET;
BLKLOC(arg0) = bp;
#ifdef SETS
}
#endif SETS
ClearBound;
}
Opblock(unioncs,2,"++")