/*
 * macros.h
 *
 * rcsid = "$Header: /home/globdev/CVS/globus-packages/nexus/source/nexus/macros.h,v 1.33 1998/08/20 22:04:41 tuecke Exp $"
 */

#ifndef _NEXUS_INCLUDE_MACROS_H
#define _NEXUS_INCLUDE_MACROS_H

/*
 * _nx_context()
 *
 * Get the context for the current thread and save it
 * into *Context (nexus_context_t **).
 */
#ifdef BUILD_LITE
#define _nx_context(Context) \
    *(Context) = _nx_lite_context
#else
#define _nx_context(Context) \
    *(Context) = (nexus_context_t *)nexus_thread_getspecific(_nx_context_key)
#endif


/*
 * _nx_set_context()
 *
 * Set Context to be the context of the current thread.
 */
#ifdef BUILD_LITE
#define _nx_set_context(Context) \
    _nx_lite_context = (Context)
#else
#define _nx_set_context(Context) \
    nexus_thread_setspecific(_nx_context_key, (void *) (Context));
#endif


#ifndef BUILD_LITE

/*
 * _nx_thread_context()
 *
 * Set *Context (nexus_context_t **) to be the context for the passed thread.
 */
#define _nx_thread_context(Thread, Context) \
    *(Context) = ((Thread)->context)

/*
 * _nx_thread_set_context()
 *
 * Set the context (nexus_context_t *) for the passed thread.
 *
 * This may be used by a message handling thread to set itself
 * to the appropriate context before handling a rsr.
 */
#define _nx_thread_set_context(Thread, Context) \
    (Thread)->context = (Context)

#endif /* BUILD_LITE */


/*
 * _nx_context_id()
 *
 * Set *Context_ID (int *) to be the context id for the context
 * of the calling thread.
 */
#define _nx_context_id(Context_ID) \
{ \
    nexus_context_t *__context; \
    _nx_context(&__context); \
    if (__context) \
        *(Context_ID) = __context->id; \
    else \
        *(Context_ID) = -1; \
}


/*
 * Liba packing and unpacking:
 *	unsigned long Endpoint_ID
 */
#define LibaSizeof() (sizeof(globus_i_nexus_endpoint_id_t))

#define LibaPack(Liba, Endpoint_ID)		\
{						\
    globus_i_nexus_endpoint_id_t	__l;	\
						\
    __l = (Endpoint_ID);			\
    memcpy((Liba), &__l, LibaSizeof());		\
}

#define LibaUnpack(Liba, Endpoint_ID)		\
{						\
    globus_i_nexus_endpoint_id_t	__l;	\
						\
    memcpy(&__l, (Liba), LibaSizeof());		\
    (Endpoint_ID) = __l;			\
}


/*
 * PackInt1(nexus_byte_t *Array, int Index, int Integer)
 */
#define PackInt1(Array, Index, Integer) \
{ \
    (Array)[(Index)++] = (nexus_byte_t)  ((Integer) & 0xFF); \
}

/*
 * UnpackInt1(nexus_byte_t *Array, int Index, int Integer)
 */
#define UnpackInt1(Array, Index, Integer) \
{ \
    (Integer) = (int) (Array)[(Index)]; \
    (Index) += 1; \
}


/*
 * PackInt2(nexus_byte_t *Array, int Index, int Integer)
 */
#define PackInt2(Array, Index, Integer) \
{ \
    (Array)[(Index)++] = (nexus_byte_t) (((Integer) & 0xFF00) >> 8); \
    (Array)[(Index)++] = (nexus_byte_t)  ((Integer) & 0xFF); \
}

/*
 * UnpackInt2(nexus_byte_t *Array, int Index, int Integer)
 */
#define UnpackInt2(Array, Index, Integer) \
{ \
    (Integer) = (  ( ((int) (Array)[(Index)]) << 8) \
		 |   ((int) (Array)[(Index)+1]) ); \
    (Index) += 2; \
}


/*
 * PackInt4(nexus_byte_t *Array, int Index, int Integer)
 */
#define PackInt4(Array, Index, Integer) \
{ \
    (Array)[(Index)++] = (nexus_byte_t) (((Integer) & 0xFF000000) >> 24); \
    (Array)[(Index)++] = (nexus_byte_t) (((Integer) & 0xFF0000) >> 16); \
    (Array)[(Index)++] = (nexus_byte_t) (((Integer) & 0xFF00) >> 8); \
    (Array)[(Index)++] = (nexus_byte_t)  ((Integer) & 0xFF); \
}

/*
 * UnpackInt4(nexus_byte_t *Array, int Index, int Integer)
 */
#if NEXUS_DC_FORMAT_LOCAL == NEXUS_DC_FORMAT_32BIT_BE || NEXUS_DC_FORMAT_LOCAL == NEXUS_DC_FORMAT_32BIT_LE
#define UnpackInt4(Array, Index, Integer) \
{ \
    (Integer) = (  ( ((int) (Array)[(Index)])   << 24) \
		 | ( ((int) (Array)[(Index)+1]) << 16) \
		 | ( ((int) (Array)[(Index)+2]) << 8) \
		 |   ((int) (Array)[(Index)+3]) ); \
    (Index) += 4; \
}
#else
#define UnpackInt4(Array, Index, Integer) \
{ \
    (Integer) = (  ( ((int) (Array)[(Index)])   << 24) \
		 | ( ((int) (Array)[(Index)+1]) << 16) \
		 | ( ((int) (Array)[(Index)+2]) << 8) \
		 |   ((int) (Array)[(Index)+3]) ); \
    if ((Integer) & 0x80000000) /* Sign extend */ \
    { \
	(Integer) |= 0xFFFFFFFF00000000; \
    } \
    (Index) += 4; \
}
#endif


/*
 * SizeofMIProtoEntry(int Proto_entry_size)
 */
#define SizeofMIProtoEntry(Proto_entry_size) (4 + (Proto_entry_size))


/*
 * PackMIProtoEntry(nexus_byte_t *Array,
 *                  int Index,
 *                  nexus_proto_type_t Type,
 *                  int Size,
 *                  nexus_byte_t *SubArray)
 */
#define PackMIProtoEntry(Array, Index, Type, Size, SubArray) \
{ \
    PackInt2(Array, Index, (int) (Type)); \
    PackInt2(Array, Index, Size); \
    memcpy(&((Array)[(Index)]), SubArray, Size) ; \
    (Index) += (Size); \
}


/*
 * UnpackMIProtoEntry(nexus_byte_t *Array,
 *                    int Index,
 *                    nexus_proto_type_t Type,
 *                    int Size,
 *                    nexus_byte_t *SubArray)
 */
#define UnpackMIProtoEntry(Array, Index, Type, Size, SubArray) \
{ \
    int __i; \
    UnpackInt2(Array, Index, __i); \
    (Type) = (nexus_proto_type_t) __i; \
    UnpackInt2(Array, Index, Size); \
    (SubArray) = &((Array)[(Index)]); \
    (Index) += (Size); \
}


/*
 * SizeofMIProtoHeader(int Hostname_length)
 */
#define SizeofMIProtoHeader(Hostname_length) (6 + (Hostname_length))


/*
 * PackMIProtoHeader(nexus_byte_t *Array, int Index,
 *                   int Context_differentiator,
 *                   char *Hostname,
 *                   int Hostname_length,
 *                   int Version)
 */
#define PackMIProtoHeader(Array, Index, Context_differentiator, Hostname, Hostname_length, Version) \
{ \
    (Array)[(Index)++] = (nexus_byte_t) (Version); \
    PackInt4(Array, Index, Context_differentiator); \
    memcpy(&((Array)[(Index)]), Hostname, (Hostname_length) + 1); \
    (Index) += (Hostname_length) + 1; \
}


/*
 * UnpackMIProtoHeader(nexus_byte_t *Array, int Index,
 *                     int Context_differentiator,
 *                     char *Hostname,
 *                     int Version)
 */
#define UnpackMIProtoHeader(Array, Index, Context_differentiator, Hostname, Version) \
{ \
    (Version) = (int) ((Array)[(Index)++]); \
    UnpackInt4(Array, Index, Context_differentiator); \
    (Hostname) = (char *) &((Array)[(Index)]); \
    (Index) += (strlen(Hostname) + 1); \
}


#ifdef BUILD_DEBUG
#define NexusDebug(Level) (_nx_debug_level >= (Level))
#endif

#ifdef BUILD_DEBUG
#define nexus_debug_printf(level, message) \
do { \
    if (NexusDebug(level)) \
    { \
	globus_libc_printf message; \
    } \
} while (0)
#else
#define nexus_debug_printf(level, message)
#endif

#ifdef BUILD_DEBUG
#define NexusBufferMagicCheck(func, buf) \
{ \
    if ((buf) == (nexus_buffer_t *) NULL) \
	globus_fatal(#func ": NULL nexus_buffer_t*\n"); \
    if (*(buf) == (nexus_buffer_t) NULL) \
	globus_fatal(#func ": NULL nexus_buffer_t\n"); \
    if ((*(buf))->magic != NEXUS_BUFFER_MAGIC) \
	globus_fatal(#func ": Bad magic number %x on buffer %x\n", \
		    (*(buf))->magic, buf); \
}
#else
#define NexusBufferMagicCheck(func, buf)
#endif


#ifdef BUILD_LITE
/*
 * We need to spoof a few functions in the NexusLite version.
 */
#define _nx_thread_id(Thread_ID) *(Thread_ID) = 0;
#endif /* BUILD_LITE */

#endif /* _NEXUS_INCLUDE_MACROS_H */
