4.3BSD/usr/contrib/icon/operators/unioncs.c

Compare this file to the similar file:
Show the results in this format:

#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,"++")