/* Copyright 1984 by the Massachusetts Institute of Technology */

/* Useful macros */

#define	roundup(x)	(((x) + 1) & ~1)
#define	min(a, b)	(((a) < (b)) ? (a) : (b))
#define	max(a, b)	(((a) > (b)) ? (a) : (b))

#define	bytobi(x)	((x) << 3)
#define	bitoby(x)	((x) >> 3)	/* Use with care! */


/* The following macros hack FIFO queues. clrq initializes a queue, addq and
 * rmq add/return items from the end/start of the queue, addhq puts an item
 * on the start of a queue, and rmmq removes a specific item from the
 * middle of a queue (this latter takes as args a pointer to the pointer
 * to the IORB that's being removed and a pointer to the IORB. The format
 * of queues is simple; they have head and tail pointers and a count.
 * When the queue is empty the head is NULL and the tail points to the
 * head; this makes insertions quick.
 */

#define	clrq(q)	{ (q)->q_hd = NULL; (q)->q_tl = &(q)->q_hd; (q)->q_nq = 0; }

#define	addq(q, itm) { (itm)->i_link = NULL; *(q)->q_tl = (itm); \
			(q)->q_tl = &(itm)->i_link; (q)->q_nq++; }

#define	addhq(q, itm) { if (((itm)->i_link = (q)->q_hd) == NULL) \
				(q)->q_tl = &(itm)->i_link; \
			(q)->q_hd = (itm); (q)->q_nq++; }

#define	rmq(q)	( ((qtmp = (q)->q_hd) == NULL) ? NULL : \
		   (( (((q)->q_hd = qtmp->i_link) == NULL) ? \
			(((q)->q_tl = &(q)->q_hd), (q)->q_nq--) : \
			(q)->q_nq--), qtmp))

#define	rmmq(q, itmsl, itmr)	{ if ((*(itmsl) = (itmr)->i_link) == NULL) \
					(q)->q_tl = (itmsl); \
				 (q)->q_nq--; }

#define	gethq(q) ((q)->q_hd)

#define	tsteq(q) ((q)->q_hd == NULL)
#define	tstneq(q) ((q)->q_hd != NULL)

#define	numq(q)	((q)->q_nq)


/* These macros are the start of some half-heated attempts at
 * portability.
 */

#define	mkunsb(x)		((x) & 0377)
#define	loworder(x)		(unss)(x)
#define	hiorder(x)		(unss)(x>>16)

/* Big endian machines don't need the bytes in the headers swapped.
 */
#ifdef	BIG_ENDIAN
#define	swab(x)	(x)
#endif	BIG_ENDIAN

/* The macros below are so that the algorithms may be changed
 * or expanded without touching the code in a lot of places.
 */
#define	freemem(siz, pnt)	mem_free((siz), (pnt))
#define getmem(siz)		mem_alloc((siz))
#define	freebuf(pnt)		{ (pnt)->i_link = bfrlst; bfrlst = (pnt); \
				  nbfree++; }
#define getbuf()		( ((qtmp = bfrlst) == NULL) ? NULL : \
				  (bfrlst = qtmp->i_link, nbfree--, qtmp)) \
				   


/* This is here so that the optimizer will collapse all the
 * calls to bughlt() and make the code somewhat smaller.
 */

/*#define	bughalt(s)	{ bughlt((s)); return; }*/


/* Useful for putting interface's full name in log arguments */

#define	mksnet(netpnt)	(netpnt)->n_net, netnm[(netpnt)->n_type], (netpnt)->n_int


/* This macro to do logging sucks. It ought to have the string and args as
 * well so that the entire method of doing tracing can be changed invisibly,
 * but since macros can't take multiple arguments, I have to do it in two
 * parts. Also, the dolog() routine is a real kludge, since I don't feel
 * like copying arguments around for trace(); it's written in assembler
 * and if the level (stored in msglvl so that it can see it) is not a fatal
 * one it just jumps to trace, otherwise it crashes the system. I use this
 * awful kludge because the one before it produced mind-bogglingly bad code.
 */

#define	iflog(level)	if (((msglvl = (level)) & msgflg) != 0)

/* This logging macro is so each code package can have its own message
 * flag variable.  For consistency, the low bits of the flag should
 * have the same meaning as for the current msgflg.  Before using this
 * macro, MSGFLG must be defined to be the message flag variable for
 * that code package.
 */
#define niflog(level)	if ((MSGFLG & (level)) != 0)
