#ifndef __GISH__
#define __GISH__

#include <gishsys.h>

#ifndef OS_UNIX
#define qsort HeapSort
#endif

#ifndef difftime
/* some ANSI-compliant systems do not seem to provide difftime() */
#define difftime(A,B)	((double)((A)-(B)))
#endif

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

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;
		ValNode	pdata; /* user-definable pool data */
	} PoolBlk, PNTR PoolBlkPtr;


#ifdef MPROC_AVAIL
#define THREADS_MAX	36
#define PROC_RESERVE	0
#define NCHUNKS	500
#else /* !MPROC_AVAIL */
#define THREADS_MAX	1
#define PROC_RESERVE	0
#define NCHUNKS	1
#define mproc_lock()
#define mproc_unlock()
#define mproc_sync(A)
#endif /* !MPROC_AVAIL */
#ifndef getc_unlocked
#define getc_unlocked getc
#endif
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
#ifndef putc_unlocked
#define putc_unlocked putc
#endif
#ifndef putchar_unlocked
#define putchar_unlocked putchar
#endif


#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 taskblk {
		struct taskblk	PNTR root;
		unsigned		id, nprocs, proc_max;
		long			ntasks, task_cur, task_max, nchunks, chunksize;
		unsigned long	nticks, tick_incr;
		unsigned long	PNTR pos_cnt;
		Boolean			PNTR flag;
		unsigned long	tick_cnt, tick_out; /* local tick counts */
		unsigned long	PNTR gtick_cnt, PNTR gtick_out; /* global tick counts */
		void		(*tickproc)();
		void		(*ticknext)();
		long		(*tasknext)();
		unsigned long	_gtick_cnt,	/* items only used in root block ... */
					_gtick_out;
		volatile unsigned long	next_cnt;
#ifdef OS_UNIX_IRIX
		pid_t		tid[THREADS_MAX];
#endif
#ifdef SOLARIS_THREADS_AVAIL
		mutex_t		next_mutex;
		volatile int	sync_cnt;
		volatile sig_atomic_t	sync_flag;
		mutex_t		sync_mutex;
		cond_t		parent_cond;
		cond_t		sync_cond;
		thread_t	tid[THREADS_MAX];
#endif
#ifdef DCE_THREADS_AVAIL
		pthread_mutex_t	next_mutex;
		volatile int	sync_cnt;
		volatile sig_atomic_t	sync_flag;
		pthread_mutex_t	sync_mutex;
		pthread_cond_t	parent_cond;
		pthread_cond_t	sync_cond;
		pthread_t	tid[THREADS_MAX];
#endif
		Nlm_VoidPtr	userp;
		Boolean		flag_ray[THREADS_MAX]; /* only used in head item */
		unsigned long	pos_ray[THREADS_MAX]; /* only used in head item */
	} TaskBlk, PNTR TaskBlkPtr;


#ifdef SYSV_IPC_AVAIL
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/msg.h>
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;
typedef int	key_t;
#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, /* current pointer */
				spmax, /* max. pointer mapped into process address space */
				sp0, /* beginning of mapped area */
				spend; /* end of file (end of instantiated data) */
		off_t	filesize;
		int		maplen;
		char	mode;
		shm_dat	PNTR shmdp;
		struct mfile	PNTR root;
		int		link_count;
	} MFILE;
#define MFILE_FP(F) ((F)->fp)
#define MFILE_SP(F) ((F)->sp)
#define MFILE_SPGETC(F)	((F)->sp < (F)->spend ? *((UcharPtr)((F)->sp)++) : EOF)
#define MFILE_SPUNGETC(C,F)	((C) != EOF ? (F)->sp--)
#else /* !YESMFILE */
#define MFILE	FILE
#define MFILE_FP(F) (F)
#define MFILE_SP(F) (NULL)
#define MFILE_SPGETC(F)	(EOF)
#define MFILE_SPUNGETC(C,F)
#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
#define mfil_getc getc
#define mfil_ungetc ungetc
#define mfil_fgetc fgetc
#define mfil_flush	fflush
#define mfil_rewind rewind
#define mfil_gets fgets
#define mfil_vgets vfgets
#endif /* !YESMFILE */

#define MFIL_MAPLEN_DEFAULT	(100*KBYTE*KBYTE)
#define MFIL_OPT_NONE	0
#define MFIL_OPT_SHM	(1)
#define MFIL_OPT_MMAP	(2)
#define MFIL_OPT_LOCK	(4)
#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 long)(i) & MUNGE_BIT)
#define MUNGED(p)	((unsigned long)(p) | MUNGE_BIT)
#define UNMUNGED(p)	((unsigned long)(p) & ~(unsigned long)MUNGE_BIT)

	/************** AVL BALANCED BINARY TREES (Vixie & Wirth) *****************/

typedef struct	avl_tree {
		struct avl_tree	PNTR avl_l, PNTR avl_r;
		CharPtr	avl_p;
		short	avl_b;
	} avl_tree;

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

extern int *_lcasemap;
extern int *_ucasemap;

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

#define GISH_ERR_INVAL	1

#endif /* !__GISH__ */
