#ifndef __GISH__
#define __GISH__

#include <gishsys.h>

typedef struct {
		long	user;
		long	system;
		time_t	real;
	} Cputime_t;

typedef enum {
		ANY_NONE = 0,
		ANY_UNDEFINED = 0,
		ANY_CHAR = 1,
		ANY_UCHAR,
		ANY_SHORT,
		ANY_USHORT,
		ANY_INT,
		ANY_UINT,
		ANY_LONG,
		ANY_ULONG,
		ANY_FLOAT,
		ANY_DOUBLE,
		ANY_CHARPTR,
		ANY_VOIDPTR,
		ANY_CSTR,
		ANY_BUFFER
	} AnyType, PNTR AnyTypePtr;

typedef struct _any_value {
		struct _any_value	PNTR next;
		int		usertype;
		AnyType	type;
		union {
			char			c;
			unsigned char	uc;
			short			s;
			unsigned short	us;
			int				i;
			unsigned		u;
			unsigned long	ul;
			long			l;
			double			d;
			float			f;
			Nlm_VoidPtr		vp;
			CharPtr			cp;
			CharPtr			cstr; /* NUL terminated string */
			struct {
				size_t		len;
				Nlm_VoidPtr	ptr;
			} buf;
		} value;
	} AnyData, PNTR AnyDataPtr;

typedef struct _poolitem {
		struct _poolitem	PNTR next;
	} PoolItem, PNTR PoolItemPtr;

typedef struct _poolblk {
		PoolItemPtr	avail; /* next free item available */
		size_t	nextoff; /* offset of "next" field within Item's structure */
		PoolItemPtr	item0; /* start of current block of allocated items */
		struct _poolblk	PNTR nextblkp;
		size_t	nelem, size, totsize;
		AnyData	pid; /* user-definable pool i.d. */
	} PoolBlk, PNTR PoolBlkPtr;


#ifdef MPROC_AVAIL
#define THREADS_MAX	36
#define PROC_RESERVE	0
#define NCHUNKS	500

#ifdef SGI_MPROC_AVAIL
#define M_LOCK m_lock()
#define M_UNLOCK m_unlock()
#endif /* SGI_MPROC_AVAIL */

#ifdef SOLARIS_THREADS_AVAIL
mutex_t	_gish_mutex;
#define M_LOCK mutex_lock(&_gish_mutex)
#define M_UNLOCK mutex_unlock(&_gish_mutex)
#endif /* SOLARIS_THREADS_AVAIL */

#ifdef DCE_THREADS_AVAIL
pthread_mutex_t	_gish_mutex;
#define M_LOCK pthread_mutex_lock(&_gish_mutex)
#define M_UNLOCK pthread_mutex_unlock(&_gish_mutex)
#endif /* DCE_THREADS_AVAIL */

#else /* !MPROC_AVAIL */

#define THREADS_MAX	1
#define PROC_RESERVE	0
#define NCHUNKS	1
#define M_LOCK
#define M_UNLOCK
#endif /* !MPROC_AVAIL */


#if !defined(MAXCOPYTYPE) && !defined(PROC_YMP)
/* Largest chunk to copy from one memory area to another (must be **2) */
#define MAXCOPYTYPE	double
#endif
#if !defined(MAXINITTYPE) && !defined(PROC_YMP)
/* Largest chunk to initialize memory (must be **2) */
#define MAXINITTYPE	long
#endif

typedef struct {
		unsigned		id, nprocs, proc_max;
		unsigned long	ntasks, task_cur, task_max, nchunks, chunksize;
		unsigned long	nticks, tick_incr;
		unsigned long	tick_cnt, tick_out;
		unsigned long	PNTR gtick_cnt, PNTR gtick_out;
		void		(*tickproc)();
		void		(*ticknext)();
		long		(*tasknext)();
		Nlm_VoidPtr	userp;
	} TaskBlk, PNTR TaskBlkPtr;



#ifdef SYSV_IPC_AVAIL
typedef struct shm_dat {
		FILE	*fp;
		CharPtr	filename;
		key_t	key;
		long	filesize;
		int		shmid, semid, msqid;
		VoidPtr	shmaddr;
	} shm_dat;
#else
typedef CharPtr	shm_dat;
#endif


#if (defined(OS_UNIX_SYSV) || defined(OS_UNIX_SUN) || defined(OS_UNIX_OSF1)) && !defined(OS_UNIX_ULTRIX)
#define MMAP_AVAIL
#endif

#if !defined(NOMFILE) && (defined(MMAP_AVAIL) || defined(SYSV_IPC_AVAIL))
#define YESMFILE
typedef struct mfile {
		FILE	PNTR fp;
		CharPtr	sp;
		off_t	offset;
		off_t	filesize;
		int		maplen;
		char	mode;
		shm_dat	PNTR shmdp;
	} MFILE;
#define MFILE_FP(F) ((F)->fp)
#define MFILE_SP(F) ((F)->sp)
#else /* !YESMFILE */
#define MFILE	FILE
#define MFILE_FP(F) (F)
#define MFILE_SP(F) (NULL)
#define mfil_open(fname,mode,flags) fopen(fname,mode)
#define mfil_close fclose
#define mfil_seek fseek
#define mfil_read fread
#define mfil_write fwrite
#define mfil_tell ftell
#define mfil_eof feof
#endif /* !YESMFILE */

#define MFIL_MAPLEN_DEFAULT	(50*KBYTE*KBYTE)
#define MFIL_OPT_NONE	0
#define MFIL_OPT_SHM	(1)
#define MFIL_OPT_MMAP	(2)
#define MFIL_OPT_ALL	(MFIL_OPT_SHM|MFIL_OPT_MMAP)

#ifndef SHM_LOCK
#define SHM_LOCK	3
#endif
#ifndef SHM_UNLOCK
#define SHM_UNLOCK	4
#endif

typedef struct _link1blk {
	struct _link1blk	PNTR next;
	CharPtr	cp;
	} Link1Blk, PNTR Link1BlkPtr;

typedef struct _link2blk {
	struct _link2blk	PNTR previous, PNTR next;
	CharPtr	cp;
	} Link2Blk, PNTR Link2Blkptr;

typedef struct _alarmblk {
	struct _alarmblk	PNTR next;
	time_t	period;
	time_t	dingdong;
	FnPtr	func;
	VoidPtr	arg;
	} AlarmBlk, PNTR AlarmBlkPtr;

typedef struct patnode {
	struct patnode	PNTR llink, PNTR rlink;
	unsigned long	skip;
	VoidPtr		key;
	} PatNode, PNTR PatNodePtr;

typedef struct pattree {
	PoolBlkPtr	node_pool;
	PatNode		head;
	VoidPtr		(*keyfunc) PROTO((Nlm_VoidPtr));
	} PatTree, PNTR PatTreePtr;


	/************ MISC COMMON MACROS **************/

#ifndef HOWMANY
/* How many B's does it take to consume A? */
#define HOWMANY(A,B)	(((size_t)(A)+((size_t)(B)-1))/(size_t)(B))
#endif

#ifndef SAFENCPY
/* Ensure destination area is null-terminated */
#define SAFENCPY(D, S, L) strncpy((D), (S), (L)), (D)[(L)-1]=NULLB;
#endif

#ifndef TOUPPER
#define TOUPPER(c)	_ucasemap[(c)]
#endif
#ifndef TOLOWER
#define TOLOWER(c)	_lcasemap[(c)]
#endif

#define BO_LONG_SIZE	4
#define BO_SHORT_SIZE	2
#define BO_ULONG_SIZE	BO_LONG_SIZE
#define BO_USHORT_SIZE	BO_SHORT_SIZE
#define BO_LONG_MAX	0x7fffffff
#define BO_LONG_MIN	(-0x80000000)
#define BO_SHORT_MAX (0x7fff)
#define BO_SHORT_MIN (-0x8000)
#define BO_ULONG_MAX 0xffffffff
#define BO_ULONG_MIN 0
#define BO_USHORT_MAX 0xffff
#define BO_USHORT_MIN 0

#if BYTE_ORDER == BIG_ENDIAN
#define LONG_BIGENDIAN(i)
#define SHORT_BIGENDIAN(i)
#define ULONG_BIGENDIAN(i)
#define USHORT_BIGENDIAN(i)
#define LONG_LITTLEENDIAN(i)	i = swap_long(i)
#define SHORT_LITTLEENDIAN(i)	i = swap_short(i)
#define ULONG_LITTLEENDIAN(i)	i = (unsigned long)swap_long((long)i)
#define USHORT_LITTLEENDIAN(i)	i = (unsigned short)swap_short((int)i)
#else
#define LONG_BIGENDIAN(i)	i = swap_long(i)
#define SHORT_BIGENDIAN(i)	i = swap_short(i)
#define ULONG_BIGENDIAN(i)	i = (unsigned long)swap_long((long)i)
#define USHORT_BIGENDIAN(i)	i = (unsigned short)swap_short((int)i)
#define LONG_LITTLEENDIAN(i)
#define SHORT_LITTLEENDIAN(i)
#define ULONG_LITTLEENDIAN(i)
#define USHORT_LITTLEENDIAN(i)
#endif

	/************** BIT TWIDDLERS *****************/

/* Create a single bit (lowest-order bit is numbered 0) */
#define BIT(b)	(1<<(b))

/* Generate a bitmask with the n least-significant bits set, where n > 0 */
#define BITMASK(n)    (BIT((n)-1)|(BIT((n)-1)-1))

#ifndef MUNGE_BIT
#ifdef PROC_YMP /* Cray YMP */
#define MUNGE_BIT	(1<<30)
#else
#define MUNGE_BIT	1
#endif
#endif /* !MUNGE_BIT */

#define ISMUNGED(i)	((unsigned int)(i) & MUNGE_BIT)
#define MUNGED(p)	((unsigned long)(p) | MUNGE_BIT)
#define UNMUNGED(p)	((unsigned long)(p) & ~(long)MUNGE_BIT)

	/************** COMMON DATA *****************/

extern int *_lcasemap;
extern int *_ucasemap;

	/************** ERROR CODES *****************/

#define GISH_ERR_INVAL	1

#endif /* !__GISH__ */
