#ifndef lint
static char *RCSid = "$Header: /users/empire/EMP/client/RCS/bit.c,v 1.2 89/06/09 23:47:40 jeffw Exp $";
#endif /* not lint */
/*
 * bits.c
 *
 * allocate and search select-style bitfields
 *
 */

#include "bit.h"

int	bit_nfile;
int	bit_nbytes;

bit_fdmask
bit_newfdmask()
{
	extern	char *malloc();
	bit_fdmask	mask;

	if (bit_nfile == 0) {
		bit_nfile = getfdtablesize();
		bit_nbytes = (bit_nfile + (BIT_BITSPERMASK-1)) / BIT_NBBY;
	}
	mask = (bit_fdmask) malloc(bit_nbytes);
	(void) bit_zero(mask);
	return mask;
}

/*
 * zero the bitfield
 */
bit_zero(bitp)
	bit_fdmask bitp;
{
	bit_mask *mask;
	register int i;
	register int nwords;

	mask = bitp;
	nwords = bit_nbytes / sizeof(*mask);
	for (i=0; i<nwords; i++)
		*mask++ = 0;
}

/*
 * zero the bitfield
 */
bit_not(bitp)
	bit_fdmask bitp;
{
	register bit_mask *mask;
	register int i;
	register int nwords;

	mask = bitp;
	nwords = bit_nbytes / sizeof(*mask);
	for (i=0; i<nwords; i++,mask++)
		*mask = ~(*mask);
}

/*
 * zero the bitfield
 */
bit_copy(bitsrc, bitdst)
	bit_fdmask bitsrc;
	bit_fdmask bitdst;
{
	register bit_mask *src;
	register bit_mask *dst;
	register int i;
	register int nwords;

	dst = bitdst;
	src = bitsrc;
	nwords = bit_nbytes / sizeof(*dst);
	for (i=0; i<nwords; i++)
		*dst++ = *src++;
}

/*
 * zero the bitfield
 */
bit_or(bitsrc, bitdst)
	bit_fdmask bitsrc;
	bit_fdmask bitdst;
{
	register bit_mask *src;
	register bit_mask *dst;
	register int i;
	register int nwords;

	nwords = bit_nbytes / sizeof(*dst);
	src = bitsrc;
	dst = bitdst;
	for (i=0; i<nwords; i++)
		*dst++ |= *src++;
}

/*
 * zero the bitfield
 */
bit_or3(bitsrc1, bitsrc2, bitdst)
	bit_fdmask bitsrc1;
	bit_fdmask bitsrc2;
	bit_fdmask bitdst;
{
	register bit_mask *src1;
	register bit_mask *src2;
	register bit_mask *dst;
	register int i;
	register int nwords;

	src1 = bitsrc1;
	src2 = bitsrc2;
	dst = bitdst;
	nwords = bit_nbytes / sizeof(*dst);
	for (i=0; i<nwords; i++)
		*dst++ = *src1++ | *src2++;
}

/*
 * zero the bitfield
 */
bit_and(bitsrc, bitdst)
	bit_fdmask bitsrc;
	bit_fdmask bitdst;
{
	register bit_mask *src;
	register bit_mask *dst;
	register int i;
	register int nwords;

	nwords = bit_nbytes / sizeof(*src);
	src = bitsrc;
	dst = bitdst;
	for (i=0; i<nwords; i++)
		*dst++ &= *src++;
}

/*
 * zero the bitfield
 */
bit_and3(bitsrc1, bitsrc2, bitdst)
	bit_fdmask bitsrc1;
	bit_fdmask bitsrc2;
	bit_fdmask bitdst;
{
	register bit_mask *src1;
	register bit_mask *src2;
	register bit_mask *dst;
	register int i;
	register int nwords;

	src1 = bitsrc1;
	src2 = bitsrc2;
	dst = bitdst;
	nwords = bit_nbytes / sizeof(*dst);
	for (i=0; i<nwords; i++)
		*dst++ = *src1++ & *src2++;
}

/*
 * Return first bit set in fd mask.
 * speedy version, not using BIT_ISSETB()
 */
int
bit_fd(bitp)
	bit_fdmask bitp;
{
	register bit_mask *mask;
	register int j;
	register bit_mask m;
	register int i;
	int	nwords;

	mask = bitp;
	nwords = bit_nbytes / sizeof(m);
	for (i=0; i<nwords; i++,mask++) {
		if ((m = *mask) == 0)
			continue;
		for (j=0; j<BIT_BITSPERMASK; j++) {
			if (m & bit(j))
				return i*BIT_BITSPERMASK + j;
		}
		/*NOTREACHED*/
	}
	return -1;
}
