/*static char *SCCSID = "@(#)pbmacros.h 6.1 90/11/18";*/
/*static char *SCCSID = "@(#)pbmacros.h 13.7 90/02/28";*/
/*************************************************************************\
*                                                                         *
*                               M a c r o s                               *
*                                                                         *
*       HISTORY                                                           *
*           30-Oct-1989 18:40:04 by Jon Parati [jonpa]                    *
*               - added PTR_SUB                                           *
*           24-Apr-1989 - JR (John Rogers, JohnRo@Microsoft)              *
*               - Renamed macros to reflect safe/unsafe versions:         *
*                 ROUND_UP_DIV is now UNSAFE_ROUND_UP_DIV                 *
*                 ROUND_UP_TO is now UNAFE_ROUND_UP_TO                    *
*                 SHRT_ROUND_UP_DIV is now SAFE_ROUND_UP_DIV              *
*               - Added safe version of round up to macro.                *
*                                                                         *
\*************************************************************************/


/*  This macro simply performs pointer subtraction.  It can only be used on
 *  pointers withing the same segment.
 */
#define POINTER_SUBTRACT(p1,p2) (OFFSETOF(p1)-OFFSETOF(p2))

/*  This macro simply performs pointer subtraction.  It can only be used on
 *  pointers withing the same segment.  It differs from POINTER_SUBTRACT
 *  in that the pointers can be obtained with the '&' function.
 */
#define PTR_SUB(p1,p2) ((USHORT)((PBYTE)(p1)-(PBYTE)(p2)))

/**     USSHIFTRUL - shift a ULONG right a constant amount and give a USHORT
 */
#define USSHIFTRUL(ul,n)    ((HIUSHORT(ul) << (16-(n))) + (LOUSHORT(ul) >> (n)))


/*
 * This macro evaluates to a pointer to the buffer header associated with
 * the given buffer (block).
 */

#define BH(pdb) (&(abufCache [pusBlockMap [SEL_INDEX (SELECTOROF (pdb)) -   \
                                             pusBlockMap [0]                \
                                            ] +                             \
                                OFFSETOF (pdb)/sizeof (BLOCK)               \
                               ]))

/*
 * This macro gives the byte offset of the dirent into the dirblk.
 */

#define DIRENT_OFFSET(pdb,pde)  (OFFSETOF(pde)-OFFSETOF(pdb))

/*
 * This macro gives the relative sector number (0 - SPB-1) of a sector
 * in a BLOCK with pbuf as the PBUFNODE
 */
#define SECTOR_IN_BLOCK( psec, pbuf ) \
         ((OFFSETOF(psec) - OFFSETOF ((pbuf)->pblkData)) >> SECSHIFT)


/*
 * This macro will return the logical sector number of a piece of data
 * stored in a BLOCK that has a BUFNODE of *pbuf
 */

#define LSN_OF_BLKDATA( psec, pbuf )    \
                        ((pbuf)->lsnSec + SECTOR_IN_BLOCK( (psec), (pbuf) ))


/*
 * This macro gets the lsn of a dirblk.  It does this by getting the index
 * into a block that holds the dirblk, then it adds this index onto the
 * lsn in the buffer header.
 */

#define LSN_OF_DIRBLK(pdb)      \
                ((BH (pdb) -> lsnSec) + SECTOR_IN_BLOCK (pdb, BH (pdb)))

/*
 * The following macro copys cusX longwords from pulSrc to pulDest without
 * changing the values of pulSrc and pulDest.  Returns next place to store.
 */

#define LONG_COPY(pulSrc, pulDest, cusX)        \
                BYTE_COPY ((PVOID)(pulSrc), (PVOID)(pulDst), (cusX) << 2)

/*
 * Divide (a) by (b) but round up any remainder.  This macro is unsafe because
 * it may overflow if (a) + (b) is too large for their data type.  Also,
 * (b) must not be zero.
 */
#define UNSAFE_ROUND_UP_DIV( a, b )     ( ((a) + (b) - 1) / (b) )

/*
 * Same as above, but fixes the bug if (a) is a short such that
 *      (a + b - 1) > 0xFFFF
 * (I.e. this macro is safe from overflow.)  Note that (b) must not be zero.
 */
#define SAFE_ROUND_UP_DIV( a, b )   ( ((a) / (b)) + ((a) % (b) ? 1 : 0) )

/*
 * Simple macro to roundup the given value (a) to a multiple of value (b).
 * This macro is unsafe because it may overflow if (a) + (b) is too large
 * for their data type.  Also, (b) must not be zero.
 */
#define UNSAFE_ROUND_UP_TO( a, b )      (UNSAFE_ROUND_UP_DIV( a, b ) * (b))

/*
 * Simple macro to roundup the given value (a) to a multiple of value (b).
 * (b) must not be zero.
 */
#define SAFE_ROUND_UP_TO( a, b )        (SAFE_ROUND_UP_DIV( a, b ) * (b))

/*
 * Most of the times we do rounding, we are actually doing a round
 * up to a sector size.  We can do this since SECSIZE is a power of
 * two simpler by using the following macro.
 */
#if SECSIZE != 512
#error SECSIZE changed, macro may not work
#endif

#define ROUND_TO_SECSIZE(a)             (((a)+SECSIZE-1) & (~(SECSIZE-1)))

#define ROUND_TO_POW_OF_2(a,b)          (((a)+b-1) & (~(b-1)))


/*  Gets size of specified field of specified struct */
#define FIELDSIZE(type, field)  (sizeof (((type *)0)->field))


/* MAYBLOCK now resides in frame.h (19-Dec-1989 markh) */

/*** Macro to inc/dec hold count.  If debug is turned on then
 *      we check to see that we are not decrementing below 0.
 */

// @76193 - DON'T USE THIS, PUT IT IN LOG.H
//#ifndef DEBUG_HOLDS
//#define DECR_HOLDS(pobj)        ((pobj) -> cusHolds--)
//#else
//#define DECR_HOLDS(pobj)                                                    \
//    if (MAKETYPE ((pobj) -> cusHolds, INT) > 0) {                           \
//        if (flFastFile & FF_HOLDLOG)                                        \
//            dprintf (__FILE__ "(%d): %p-- \n", __LINE__, (PVOID)(pobj));      \
//        (pobj) -> cusHolds--;                                               \
//    } else {                                                                \
//        dprintf (__FILE__ "(%d): cusHolds already 0 (%p)\n",                \
//                 __LINE__, (PVOID) (pobj));                                 \
//        Int3 ();                                                            \
//    }
//#endif
//
//#ifndef DEBUG_HOLDS
//#define INCR_HOLDS(pobj)        ((pobj)->cusHolds++)
//#else
//#define INCR_HOLDS(pobj)                                                    \
//    {   if (flFastFile & FF_HOLDLOG)                                        \
//            dprintf (__FILE__ "(%d): %p++ \n", __LINE__, (PVOID) (pobj));     \
//        (pobj) -> cusHolds++;                                               \
//    }
//#endif


/*******************************************************************\
*
* Macro to get the abValue field out of an FEA
*
\*******************************************************************/
#define FEA_AVALUE( fea )  ( (PBYTE)&((fea).abValue[(fea).cbName]) )

#define BUMP_PTR(ptr, offset) ((PBYTE)(ptr) + (offset) )

#define SIZEOF_FEA( fea )   (  sizeof(FEA) + (fea).cbName + \
                               (fea).cbValue - sizeof( (fea).abValue ) )

#define NEXT_PFEA( pfea )   ( (PFEA)BUMP_PTR(pfea, SIZEOF_FEA( *pfea )) )

#define NEXT_PFEA_AND_DECR( pfea, cb )                  \
    {                                                   \
        USHORT cbTmpXXX;                                \
        cb -= (cbTmpXXX = SIZEOF_FEA (*pfea));          \
        pfea = (PFEA) BUMP_PTR (pfea, cbTmpXXX);        \
    }

#ifdef DEBUG
#define PANIC(x) {                                  \
                  dprintf (PanicMessage, __FILE__); \
                  Int3 ();                          \
                  while (TRUE) ;                    \
                 }
#else
#define PANIC(x) INTERR(x)
#endif


/*
 * IS_USER_NULL(p) evaluates to TRUE if the user-supplied
 * pointer p is an rpl-NULL pointer.
 *
 */
#define IS_USER_NULL(p) ( (OFFSETOF(p) == 0) && (SELECTOROF(p) <= 3) )


/*
 * Macro to return the size of a structure field with out having the
 * structure around
 */
#define FIELD_SIZE( typd, fld )  sizeof( ((typd *)NULL)->fld )



/*
 * Macro to yield to all threads, not just hi-priority ones like
 * FSH_YIELD does.
 */
#define LowPriYield()   {                                               \
    ULONG semBogus = 0L;                                                \
    MAYBLOCK( FSH_SEMSETWAIT( (PCHAR)&semBogus, 1L ) ); /*Wait 1msec */ \
}
