/*static char *SCCSID = "@(#)basemac.h 6.1 90/11/15";*/
/*** BASEMAC.H
*
* SCCSID = @(#)basemac.h 13.20 90/09/06
*
* Macros required for other include files
* Copyright (c) 1988,1989 Microsoft Corporation
*
*
* MODIFICATION HISTORY
* 10/14/88 JTP Created.
* 12/04/88 JTP Added OS/2-specific macros.
*/
/*** Generic macros
*/
#define NElements(array) ((sizeof array)/(sizeof array[0]))
#define SWAP(a,b,tmp) (tmp=b, b=a, a=tmp)
// Assorted macros from STDLIB.H...
#define min(a, b) (((a) < (b))? (a) : (b))
#define max(a, b) (((a) > (b))? (a) : (b))
// To extract offset or selector from a FAR32 (16:32) pointer
#define OFFSETOF32(p) (((PDWORD)&(p))[0])
#define SEGMENTOF32(p) (((PWORD)&(p))[2])
// To extract offset or selector from any FAR (16:16) pointer
#define OFFSETOF16(p) (((PWORD)&(p))[0])
#define SEGMENTOF16(p) (((PWORD)&(p))[1])
// For now, the default operators assume they're working on 16:16 pointers
#define OFFSETOF OFFSETOF16
#define SEGMENTOF SEGMENTOF16
// To convert a tiled 16:16 address to a 0:32 address
#define MAKEFLATP(fp) ((PVOID)((SEGMENTOF(fp)&~7)<<13 | OFFSETOF(fp)))
// To extract any byte, word, dword, pfn, etc. from the given item
#define BYTEOF(p,i) (((PBYTE)&(p))[i])
#define WORDOF(p,i) (((PWORD)&(p))[i])
#define DWORDOF(p,i) (((PDWORD)&(p))[i])
#define PFNOF(p,i) (((PPFN)&(p))[i])
// To test/set bits
#define TESTBIT(i,b) (((i)&(b)) != 0)
#define SETBIT(i,b,f) (i = ((i)&~(b)) | (b)*(!!(f)))
#define SETBITB(i,b,f) (i = (BYTE)(((i)&~(b)) | (b)*(!!(f))))
// ZEROBITS returns the number of low zero bits in a 32-bit constant
#define _Z2(l) ((l)&1?0:(l)&2?1:2)
#define _Z4(l) ((l)&3?_Z2(l):_Z2((l)>>2)+2)
#define _Z8(l) ((l)&15?_Z4(l):_Z4((l)>>4)+4)
#define _Z16(l) ((l)&255?_Z8(l):_Z8((l)>>8)+8)
#define _Z32(l) ((l)&65535?_Z16(l):_Z16((l)>>16)+16)
#define ZEROBITS(l) _Z32(l)
// LOG2 returns the nearest base-2 log of a 32-bit constant, rounded up
#define _L2(l) ((l)&~1?2:(l)&1)
#define _L4(l) ((l)&~3?_L2((l)>>2)+2:_L2(l))
#define _L8(l) ((l)&~15?_L4((l)>>4)+4:_L4(l))
#define _L16(l) ((l)&~255?_L8((l)>>8)+8:_L8(l))
#define _L32(l) ((l)&~65535?_L16((l)>>16)+16:_L16(l))
#define LOG2(l) _L32((l)-1)
// EXP2 returns 2 raised to the given power
#define EXP2(l) (1 << (l))
// Unit conversion macros
#define KBFROMBYTES(nb) (((nb)+KSIZE-1)/KSIZE)
#define BYTESFROMKB(nkb) ((nkb)*KSIZE)
#define PAGESFROMBYTES(nb) (((nb)+PAGESIZE-1)/PAGESIZE)
// To obtain a pointer to the page containing the given linear address
#define PPAGEFROMP(p) ((PVOID)((ULONG)(p) & ~(PAGESIZE-1)))
#define PPAGEFROMPGNO(p) ((PVOID)((ULONG)(p) * PAGESIZE))
#define PGNOFROMP(p) ((ULONG)(p) / PAGESIZE)
// To create a usable FAR pointer from an unusable FAR16 pointer
#define FPFROMF16P(fp,f16p) OFFSETOF32(fp) = OFFSETOF16(f16p),\
SEGMENTOF32(fp) = SEGMENTOF16(f16p)
// To create pointers from V86-mode segments+offsets
// Note the validity of these pointers depends on the context they're used in
#define PFROMVP(vp) ((PVOID)((WORDOF(vp,1)<<4)+WORDOF(vp,0)))
#define PFROMVADDR(seg,off) ((PVOID)(((WORD)(seg)<<4)+(WORD)(off)))
#define VPFROMVADDR(seg,off) ((VPVOID)(((WORD)(seg)<<16)|(WORD)(off)))
// To create V86 pointers from normal (flat) pointers
#define HISEG(p) ((USHORT)((ULONG)(p)>>4))
#define LOOFF(p) ((USHORT)((ULONG)(p)&0xf))
#define VPFROMP(p) ((VPVOID)((((ULONG)(p)&~0xf)<<12)|((ULONG)(p)&0xf)))
#define LOSEG(p) (((ULONG)(p)-HIOFF(p))>>4)
#define HIOFF(p) (min(0xfff0,(ULONG)(p)&0xffff0)|((ULONG)(p)&0xf))
#define LOSEGVPFROMP(p) ((VPVOID)((LOSEG(p)<<16)|HIOFF(p)))
// To calculate the byte offset of a field in a structure of type "type"
#define FIELDOFFSET(type,field) ((ULONG)&(((type *)0)->field))
/*** Older stuff (discouraged -JTP)
*/
// To extract high and low order parts of a 32-bit quantity
#define LOUSHORT(l) (((PUSHORT)&(l))[0])
#define HIUSHORT(l) (((PUSHORT)&(l))[1])
// To create pointer from V86-mode segment+offset
#define SEGOFF2P(seg,off) ((PVOID)((seg<<4)+(USHORT)off))
/*** OS/2-specific macros
*/
#ifdef INCL_SSTODS
#define SSToDS(p) ((void *) (TKSSBase + (unsigned) (p)))
extern char *TKSSBase;
#endif