macro_h

/*
**	Copyright 1991-2017, Fermi Research Alliance, LLC.  All rights reserved.
*/
/******************************************************************************/
/* macro.h
**
**	Miscellaneous macros
*/
/******************************************************************************/

#ifndef CBS_MACRO_DEFINED				/* do this only once */
#define	CBS_MACRO_DEFINED

#include <sys/param.h>
// Implemented as function in clib
#undef setbit
#include "cnsparam.h"

#define	FILT_STOP( a ) ( ((a)&0xbfff)|(((a)&0x8000)>>1) )	/* filter stop bit */
#define	ADD_STOP( a )  ( (a)|0x4000 )		        /* add stop bit */

#define	ROUND( x )     ( ((x) >= 0.0) ? ((int)((x)+ 0.5)) : ((int)((x)- 0.5)) )
#define	UNSIGNED_ROUND( x )     ( (unsigned int) ((x) + 0.5) )

#ifdef  ABS
#undef  ABS
#endif  /* ABS */
#define	ABS( x )       ( (x) < 0 ? (-(x)) : (x) )

#define	IS_ODD(x)	(((x) % 2) != 0)
#define	IS_EVEN(x)	(((x) % 2) == 0)
#define	IS_MULTIPLE_OF(x,y)	(((x) % (y)) == 0)

#define	TV_COLORS(fcol,bcol)	(((fcol) & 7) | (((bcol) & 7) << 3))	/* combine foreground and background TV colors */
#define	TV_COLORS_WBLINK(fcol,bcol,blink)	((fcol) | ((bcol) << 3) | ((blink) << 6))	/* combine TV colors with blink */

#define	EXTRACT_FORECOLOR(color)	( (color) & 7 )
#define	EXTRACT_BACKCOLOR(color)	( ((color) >> 3) & 7 )
#define	EXTRACT_BLINK(color)		( ((color) >> 6) & 1 )

#define	BLINK_COLOR(color)	( (color) | 8 )		/* convert a color to a blinking color */
#define	BLINK_TV_COLOR(color)	( (color) | TV_BLINK_MASK )	/* convert a TV color to a blinking color */
#define	INVERT_COLORS(color)	( (((color) >> 3) & 7) | (((color) & 7) << 3) )

#define	ACNET_FACILITY(e)	((e) & 0xFF)		/* extract ACNET facility code */
#define	ACNET_ERROR(e)		((e) >> 8)		/* extract ACNET error code */

#define	BUILD_ACNET_ERROR(facility,error)	((facility) | ((error) << 8))	/* build ACNET error value */

#define	FREE_IT(x)	if (x) {free((x)); (x) = NULL;}
#define	TALLOC(x)	( (x * ) malloc(sizeof(x)) )
#define	NUMBER_OF(x)	( static_cast<int>(sizeof(x)/sizeof((x)[0])) )

/* RAD50L encodes a six character constant string into a rad-50 longword */
/* RAD50S encodes a three character constant string into a rad-50 word */
/* RAD50C translates a character constant into a rad-50 byte */
#define	RAD50C(char)					\
(((char)==46)			? (28):			\
((char)==32)			? (0):			\
((char)==36)			? (27):			\
(((char)>=65)&&((char)<=90))	? ((char)-64) :		\
(((char)>=97)&&((char)<=122))	? ((char)-96) :		\
(((char)>=48)&&((char)<=57))	? (30+((char)-48)) : (29))

#define	RAD50L(string)			\
(((RAD50C((string)[3])*40*40)<<16)+	\
 ((RAD50C((string)[4])*40)<<16)+		\
 ((RAD50C((string)[5]))<<16)+		\
 (RAD50C((string)[0])*40*40)+		\
 (RAD50C((string)[1])*40)+		\
 (RAD50C((string)[2])))

#define	RAD50S(string)			\
((RAD50C((string)[0])*40*40)+		\
 (RAD50C((string)[1])*40)+		\
 (RAD50C((string)[2])))

/*
 * Why 1024?  I don't know either but ...
 * Well this came over from VMS with NULL instead of 1024, but that caused
 * the following warning when type contained a C++ class with constructors:
 *    test.cpp:109: warning: invalid offsetof from non-POD type struct
 *    main()::test_struct'; use pointer to member instead
 * The same warning results when NULL is replaced with 0.  Curiously,
 * though there is no such warning when 16 or 1024 are used, which are
 * the only two I tried.  I suspect any positive non-zero would suffice.
 * I checked the computation with a short program and the result appears
 * to actually be correct as well.
 */
#define	STRUCT_OFFSET(type,field) \
( (unsigned int) (((char *) (&(((type *) 1024)->field)))- ((char *) 1024)) )

#define	BUILD_STANC(stanc,type,aspect,entry,count,byte_count,seq_flag)	\
	stanc[0] = (short) (byte_count);				\
	stanc[1] = (short) (((aspect) << 8) + ((type) & 0xFF));		\
	stanc[2] = (short) entry;					\
	stanc[3] = (short) count;					\
	if (seq_flag) stanc[3] += 0x8000;

#define	IS_FAMILY_DI(device_index)	( ((device_index) & 0x800000) != 0 )

#define	IS_ONE_SHOT_FTD(ftd)		( ((ftd) == 0) || \
					  (((ftd) & FTD_ONESHOT_MASK) != 0) )

#define	IS_EVENT_FTD(ftd)		( ((ftd) & FTD_EVENT_MASK) != 0 )

#define	IS_STATE_FTD(ftd)		( ((ftd) & FTD_STATE_MASK) != 0 )

#define	IS_PERIODIC_FTD(ftd)		( (((ftd) & FTD_EVENT_MASK) == 0) && \
					  (((ftd) & FTD_ONESHOT_MASK) == 0) )

#define	EXTRACT_FTD_EVENT(ftd)		( (ftd) & 0xFF )

#define	EXTRACT_FTD_EVENT_DELAY(ftd)	( ((((ftd) >> 8) & 0x7F) * 10) )

#define	BUILD_EVENT_FTD(evt)		( FTD_EVENT_MASK | (evt) )

#define	BUILD_EVENT_PLUS_DELAY_FTD(evt,delay)	( (FTD_EVENT_MASK | (evt)) | ((((delay) / 10) & 0x7F) << 8) )

#define	BUILD_PERIODIC_FTD(hz)		( (int) ROUND((double) 60.0 / (double) (hz)) )

#define	EXTRACT_FTD_STATE_INDEX(ftd)	( (ftd) & 0x7F )

#define	EXTRACT_FTD_STATE_VALUE(ftd)	( ((ftd) >> 7) & 0x1F )

#define	EXTRACT_FTD_STATE_CONDITION(ftd)	( (((ftd) >> 12) & 0x1) | \
						  (((ftd) >> 13) & 0x6) )

#define	BUILD_STATE_FTD(idx,state,op)	( FTD_STATE_MASK | ((idx) & 0x7F) | \
					  (((state) & 0x1F) << 7) | \
					  (((op) & 0x1) << 12) | \
					  (((op) & 0x6) << 13) )

#define	IS_SYSTEM_ERROR(status)		( ((status) & 1) == 0 )
 
#define	EXTRACT_NODE_NUMBER(node)	((node) & 0xFF)	/* extract node number ACNET node */
#define	EXTRACT_TRUNK(node)	(((node) >> 8) & 0xFF)	/* extract trunk from ACNET node */

#define	BUILD_ACNET_NODE(node,trunk)	((node) | ((trunk) << 8))	/* build ACNET node */

#define	PIDI_BLD(di, pi) (((di) & 0xFFFFFF) | ((int) (pi) << 24))	/* build di-pi key */
#define	UNPACK_DI(x) ((x) & 0xFFFFFF)		/* extract the DI from a DI/PI key */
#define	UNPACK_PI(x) (((x) >> 24) & 0x3F)	/* extract the PI from a DI/PI key */

#define	EXTRACT_DI(x) ((x) & 0xFFFFFF)		/* extract the DI from a DI/PI key */
#define	EXTRACT_PI(x) (((x) >> 24) & 0x3F)	/* extract the PI from a DI/PI key */

#define	EXTRACT_FERMI_KEY_DI(x) ((x) & 0x7FFFFFF)	/* extract the DI from a Fermi name key */
#define	EXTRACT_FERMI_KEY_PI(x) ((x) / 0x8000000)	/* extract the PI from a Fermi name key */

#define	IS_DEVICE_NAME(string)	( ((((string)[0] >= 'A') &&	\
				  ((string)[0] <= 'Z')) ||	\
				  ((string)[0] >= 'a') &&	\
				  ((string)[0] <= 'z'))) &&	\
				  (((string)[1] == ':') ||	\
				  ((string)[1] == '_') ||	\
				  ((string)[1] == '|') ||	\
				  ((string)[1] == '&') ||	\
				  ((string)[1] == '@') ||	\
				  ((string)[1] == '$')) &&	\
				  ((((string)[2] >= 'A') &&	\
				  ((string)[2] <= 'Z')) ||	\
				  (((string)[2] >= 'a') &&	\
				  ((string)[2] <= 'z')) ||	\
				  (((string)[2] >= '0') &&	\
				  ((string)[2] <= '9'))) &&	\
				  ((string)[2] >= '0') &&	\
				  ((string)[2] <= '9') &&	\
				  ((((string)[3] >= 'A') &&	\
				  ((string)[3] <= 'Z')) ||	\
				  (((string)[3] >= 'a') &&	\
				  ((string)[3] <= 'z')) ||	\
				  (((string)[3] >= '0') &&	\
				  ((string)[3] <= '9')) ||	\
				  ((string)[3] == ' ')) &&	\
				  ((((string)[4] >= 'A') &&	\
				  ((string)[4] <= 'Z')) ||	\
				  (((string)[4] >= 'a') &&	\
				  ((string)[4] <= 'z')) ||	\
				  (((string)[4] >= '0') &&	\
				  ((string)[4] <= '9')) ||	\
				  ((string)[4] == ' ')) &&	\
				  ((((string)[5] >= 'A') &&	\
				  ((string)[5] <= 'Z')) ||	\
				  (((string)[5] >= 'a') &&	\
				  ((string)[5] <= 'z')) ||	\
				  (((string)[5] >= '0') &&	\
				  ((string)[5] <= '9')) ||	\
				  ((string)[5] == ' ')) &&	\
				  ((((string)[6] >= 'A') &&	\
				  ((string)[6] <= 'Z')) ||	\
				  (((string)[6] >= 'a') &&	\
				  ((string)[6] <= 'z')) ||	\
				  (((string)[6] >= '0') &&	\
				  ((string)[6] <= '9')) ||	\
				  ((string)[6] == ' ')) &&	\
				  ((((string)[7] >= 'A') &&	\
				  ((string)[7] <= 'Z')) ||	\
				  (((string)[7] >= 'a') &&	\
				  ((string)[7] <= 'z')) ||	\
				  (((string)[7] >= '0') &&	\
				  ((string)[7] <= '9')) ||	\
				  ((string)[7] == ' ')) )

#define	IS_PA_NAME(string)	( (((string)[0] == 'P') ||	\
				  ((string)[0] == 'p')) &&	\
				  ((((string)[1] >= 'A') &&	\
				  ((string)[1] <= 'O')) ||	\
				  (((string)[1] >= 'a') &&	\
				  ((string)[1] <= 'o'))) &&	\
				  ((string)[2] >= '0') &&	\
				  ((string)[2] <= '9') &&	\
				  ((string)[3] >= '0') &&	\
				  ((string)[3] <= '9') &&	\
				  ((string)[4] >= '0') &&	\
				  ((string)[4] <= '9') &&	\
				  ((string)[5] >= '0') &&	\
				  ((string)[5] <= '9') )

#define	IS_TEST_PA_NAME(string)	( (((string)[0] == 'P') ||	\
				  ((string)[0] == 'p')) &&	\
				  ((((string)[1] >= 'A') &&	\
				  ((string)[1] <= 'O')) ||	\
				  (((string)[1] >= 'a') &&	\
				  ((string)[1] <= 'o'))) &&	\
				  ((string)[2] == '9') &&	\
				  ((string)[3] == '9') &&	\
				  ((string)[4] >= '0') &&	\
				  ((string)[4] <= '9') &&	\
				  ((string)[5] >= '0') &&	\
				  ((string)[5] <= '9') )

#define	IS_FOREIGN_PA_NAME(string)	( (((string)[0] == 'F') ||	\
					  ((string)[0] == 'f')) &&	\
					  ((((string)[1] >= 'A') &&	\
					  ((string)[1] <= 'O')) ||	\
					  (((string)[1] >= 'a') &&	\
					  ((string)[1] <= 'o'))) &&	\
					  ((string)[2] >= '0') &&	\
					  ((string)[2] <= '9') &&	\
					  ((string)[3] >= '0') &&	\
					  ((string)[3] <= '9') &&	\
					  ((string)[4] >= '0') &&	\
					  ((string)[4] <= '9') &&	\
					  ((string)[5] >= '0') &&	\
					  ((string)[5] <= '9') )

#define	IS_SA_NAME(string)	( (((string)[0] == 'S') ||	\
				  ((string)[0] == 's')) &&	\
				  ((((string)[1] >= 'A') &&	\
				  ((string)[1] <= 'O')) ||	\
				  (((string)[1] >= 'a') &&	\
				  ((string)[1] <= 'o'))) &&	\
				  ((string)[2] >= '0') &&	\
				  ((string)[2] <= '9') &&	\
				  ((string)[3] >= '0') &&	\
				  ((string)[3] <= '9') &&	\
				  ((string)[4] >= '0') &&	\
				  ((string)[4] <= '9') &&	\
				  ((string)[5] >= '0') &&	\
				  ((string)[5] <= '9') )

#define	IS_TEST_SA_NAME(string)	( (((string)[0] == 'S') ||	\
				  ((string)[0] == 's')) &&	\
				  ((((string)[1] >= 'A') &&	\
				  ((string)[1] <= 'O')) ||	\
				  (((string)[1] >= 'a') &&	\
				  ((string)[1] <= 'o'))) &&	\
				  ((string)[2] == '9') &&	\
				  ((string)[3] == '9') &&	\
				  ((string)[4] >= '0') &&	\
				  ((string)[4] <= '9') &&	\
				  ((string)[5] >= '0') &&	\
				  ((string)[5] <= '9') )

#define	IS_FOREIGN_SA_NAME(string)	( (((string)[0] == 'I') ||	\
					  ((string)[0] == 'i') ||	\
					  ((string)[0] == 'H') ||	\
					  ((string)[0] == 'h')) &&	\
					  ((((string)[1] >= 'A') &&	\
					  ((string)[1] <= 'O')) ||	\
					  (((string)[1] >= 'a') &&	\
					  ((string)[1] <= 'o'))) &&	\
					  ((string)[2] >= '0') &&	\
					  ((string)[2] <= '9') &&	\
					  ((string)[3] >= '0') &&	\
					  ((string)[3] <= '9') &&	\
					  ((string)[4] >= '0') &&	\
					  ((string)[4] <= '9') &&	\
					  ((string)[5] >= '0') &&	\
					  ((string)[5] <= '9') )

#define	IS_PAGE_NAME(string)	( (((string)[0] == 'B') ||	\
				  ((string)[0] == 'b') ||	\
				  ((string)[0] == 'C') ||	\
				  ((string)[0] == 'c') ||	\
				  ((string)[0] == 'D') ||	\
				  ((string)[0] == 'd') ||	\
				  ((string)[0] == 'E') ||	\
				  ((string)[0] == 'e') ||	\
				  ((string)[0] == 'F') ||	\
				  ((string)[0] == 'f') ||	\
				  ((string)[0] == 'H') ||	\
				  ((string)[0] == 'h') ||	\
				  ((string)[0] == 'I') ||	\
				  ((string)[0] == 'i') ||	\
				  ((string)[0] == 'L') ||	\
				  ((string)[0] == 'l') ||	\
				  ((string)[0] == 'M') ||	\
				  ((string)[0] == 'm') ||	\
				  ((string)[0] == 'N') ||	\
				  ((string)[0] == 'n') ||	\
				  ((string)[0] == 'P') ||	\
				  ((string)[0] == 'p') ||	\
				  ((string)[0] == 'R') ||	\
				  ((string)[0] == 'r') ||	\
				  ((string)[0] == 'S') ||	\
				  ((string)[0] == 's') ||	\
				  ((string)[0] == 'T') ||	\
				  ((string)[0] == 't') ||	\
				  ((string)[0] == 'W') ||	\
				  ((string)[0] == 'w') ||	\
				  ((string)[0] == 'X') ||	\
				  ((string)[0] == 'x')) &&	\
				  ((string)[1] >= '0') &&	\
				  ((string)[1] <= '9') &&	\
				  (((string)[2] == ' ') ||	\
				  (((string)[2] >= '0') &&	\
				  ((string)[2] <= '9'))) &&	\
				  (((string)[3] == ' ') ||	\
				  (((string)[3] >= '0') &&	\
				  ((string)[3] <= '9'))) )

#define	IS_PAGE_STRING(string,len)	( (((string)[0] == 'B') ||	\
					  ((string)[0] == 'b') ||	\
					  ((string)[0] == 'C') ||	\
					  ((string)[0] == 'c') ||	\
					  ((string)[0] == 'D') ||	\
					  ((string)[0] == 'd') ||	\
					  ((string)[0] == 'E') ||	\
					  ((string)[0] == 'e') ||	\
					  ((string)[0] == 'F') ||	\
					  ((string)[0] == 'f') ||	\
					  ((string)[0] == 'H') ||	\
					  ((string)[0] == 'h') ||	\
					  ((string)[0] == 'I') ||	\
					  ((string)[0] == 'i') ||	\
					  ((string)[0] == 'L') ||	\
					  ((string)[0] == 'l') ||	\
					  ((string)[0] == 'M') ||	\
					  ((string)[0] == 'm') ||	\
					  ((string)[0] == 'N') ||	\
					  ((string)[0] == 'n') ||	\
					  ((string)[0] == 'P') ||	\
					  ((string)[0] == 'p') ||	\
					  ((string)[0] == 'R') ||	\
					  ((string)[0] == 'r') ||	\
					  ((string)[0] == 'S') ||	\
					  ((string)[0] == 's') ||	\
					  ((string)[0] == 'T') ||	\
					  ((string)[0] == 't') ||	\
					  ((string)[0] == 'W') ||	\
					  ((string)[0] == 'w') ||	\
					  ((string)[0] == 'X') ||	\
					  ((string)[0] == 'x')) &&	\
					  ((string)[1] >= '1') &&	\
					  ((string)[1] <= '9') &&	\
					  (((len) < 3) ||		\
					  ((string)[2] == ' ') ||	\
					  (((string)[2] >= '0') &&	\
					  ((string)[2] <= '9'))) &&	\
					  (((len) < 4) ||		\
					  ((string)[3] == ' ') ||	\
					  (((string)[3] >= '0') &&	\
					  ((string)[3] <= '9'))) )

#define	IS_TEST_PAGE_NAME(string)	( (((string)[0] == 'Z') ||	\
					  ((string)[0] == 'z')) &&	\
					  ((string)[1] >= '1') &&	\
					  ((string)[1] <= '9') &&	\
					  (((string)[2] == ' ') ||	\
					  (((string)[2] >= '0') &&	\
					  ((string)[2] <= '9'))) &&	\
					  (((string)[3] == ' ') ||	\
					  (((string)[3] >= '0') &&	\
					  ((string)[3] <= '9'))) )

#define	IS_UTIL_NAME(string)	( (((string)[0] == 'U') ||	\
				  ((string)[0] == 'u')) &&	\
				  (((string)[1] == 'T') ||	\
				  ((string)[1] == 't')) &&	\
				  (((string)[2] == 'I') ||	\
				  ((string)[2] == 'i')) &&	\
				  (((string)[3] == 'L') ||	\
				  ((string)[3] == 'l')) &&	\
				  (((string)[4] == 'I') ||	\
				  ((string)[4] == 'i')) &&	\
				  ((string)[5] >= '0') &&	\
				  ((string)[5] <= '2') )

#define	SR_IS_BIG_SAVE_FILE(file)	((((file) >= 900) && ((file) <= 999)) || \
					(((file) >= 1100) && ((file) <= 1199)))
#define	SR_IS_SCHEDULED_SAVE_FILE(file)	((((file) >= 900) && ((file) <= 999)) || \
					(((file) >= 1200) && ((file) <= 1299)))

#define	WINDOW_EXTRACT_ID(coord)	((coord) & 0xFFFF)
#define	WINDOW_EXTRACT_COORD(coord)	(((coord) >> 16) & 0xFF)
#define	WINDOW_CENTER_COORD(wid)	((wid) | \
					 WMNGR_CENTER_TO_WIN | \
					 WMNGR_ALIGN_TO_WHOLE_WIN)	/* create coordinate to center to another window */
#define	WINDOW_ABOVE_COORD(wid)		((wid) | \
					 WMNGR_ALIGN_TO_ABOVE | \
					 WMNGR_ALIGN_TO_WHOLE_WIN)	/* create coordinate above another window */
#define	WINDOW_BELOW_COORD(wid)		((wid) | \
					 WMNGR_ALIGN_TO_BELOW | \
					 WMNGR_ALIGN_TO_WHOLE_WIN)	/* create coordinate below another window */
#define	WINDOW_ABOVE_OR_BELOW_COORD(wid)	((wid) | \
					 WMNGR_ALIGN_TO_ABOVE_OR_BELOW | \
					 WMNGR_ALIGN_TO_WHOLE_WIN)	/* create coordinate above or below another window */
#define	WINDOW_LEFT_COORD(wid)		((wid) | \
					 WMNGR_ALIGN_TO_LEFT | \
					 WMNGR_ALIGN_TO_WHOLE_WIN)	/* create coordinate to the left of another window */
#define	WINDOW_RIGHT_COORD(wid)		((wid) | \
					 WMNGR_ALIGN_TO_RIGHT | \
					 WMNGR_ALIGN_TO_WHOLE_WIN)	/* create coordinate to the right of another window */
#define	WINDOW_LEFT_OR_RIGHT_COORD(wid)	((wid) | \
					 WMNGR_ALIGN_TO_LEFT_OR_RIGHT | \
					 WMNGR_ALIGN_TO_WHOLE_WIN)	/* create coordinate to the left or right of another window */
#define	WINDOW_ALIGN_COORD(wid,coord)	((wid) | \
					 ((coord) << 16) | \
					 WMNGR_ALIGN_TO_WIN)		/* align coordinate to window */
#define	WINDOW_ALIGN_CENTER_COORD(wid,coord)	((wid) | \
						 ((coord) << 16) | \
						 WMNGR_CENTER_TO_WIN)	/* center to window coordinate */
#define	WINDOW_ALIGN_ABOVE_COORD(wid,coord)	((wid) | \
						 ((coord) << 16) | \
						 WMNGR_ALIGN_TO_ABOVE)	/* align coordinate above window location */
#define	WINDOW_ALIGN_BELOW_COORD(wid,coord)	((wid) | \
						 ((coord) << 16) | \
						 WMNGR_ALIGN_TO_BELOW)	/* align coordinate below window location */
#define	WINDOW_ALIGN_ABOVE_OR_BELOW_COORD(wid,coord)	((wid) | \
						 ((coord) << 16) | \
						 WMNGR_ALIGN_TO_ABOVE_OR_BELOW)	/* align coordinate above or below window location */
#define	WINDOW_ALIGN_LEFT_COORD(wid,coord)	((wid) | \
						 ((coord) << 16) | \
						 WMNGR_ALIGN_TO_LEFT)	/* align coordinate to the left of a window location */
#define	WINDOW_ALIGN_RIGHT_COORD(wid,coord)	((wid) | \
						 ((coord) << 16) | \
						 WMNGR_ALIGN_TO_RIGHT)	/* align coordinate to the right of a window location */
#define	WINDOW_ALIGN_LEFT_OR_RIGHT_COORD(wid,coord)	((wid) | \
						 ((coord) << 16) | \
						 WMNGR_ALIGN_TO_LEFT_OR_RIGHT)	/* align coordinate to the left or right of a window location */
#define	WINDOW_ALIGN_ABOVE_MENUBAR(wid)		((wid) | \
						 (1 << 16) | \
						 WMNGR_ALIGN_TO_ABOVE | \
						 WMNGR_ALIGN_TO_MENUBAR)	/* align coordinate above menu bar field */
#define	WINDOW_ALIGN_BELOW_MENUBAR(wid)		((wid) | \
						 (1 << 16) | \
						 WMNGR_ALIGN_TO_BELOW | \
						 WMNGR_ALIGN_TO_MENUBAR)	/* align coordinate below menu bar field */
#define	WINDOW_ALIGN_CENTER_MENUBAR(wid,field)	((wid) | \
						 ((field) << 16) | \
						 WMNGR_CENTER_TO_WIN | \
						 WMNGR_ALIGN_TO_MENUBAR)	/* center to menu bar field */

#endif