#ifndef GCI_HT
#define GCI_HT TRUE

/*========================================================================
 * Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved.
 *
 *  Name - gci.ht
 *
 *  Description: Constant definitions and C type declarations used by
 *               GemBuilder for C Interface (GCI) functions.
 *
 * $Id: gci.ht,v 1.56 2008-01-09 22:51:03 stever Exp $
 *
 *========================================================================
 */

#include "flag.ht"                            /* Host specific constants  */
#include "l2unix.hf"

#include "gcioc.ht"
#ifndef GLOBAL_HT

#include <setjmp.h>

#endif /* !GLOBAL_HT */

/*******  GemStone constants/types defined in this and other modules ********/

/* GCI_FEATURE_LEVEL will be incremented any time a new
 * function is added to the GCI API.
 */
#define GCI_FEATURE_LEVEL 329

/* GCI_COMPAT_LEVEL will be incremented any time
 * a change is made to existing functionality
 * this is not backwards compatible.
 * It will not be changed if new functionality is added.
 *
 * 2 = 2 billion oop repository
 * 3 = gss64 phase 1 (64 bit shared cache, 2 billion oop repository)
 * 4 = gss64 phase 2 (64 bit shared cache, 2^^40 max oops in repository)
 */
#define GCI_COMPAT_LEVEL 4

/*========================================================================
 *  --  GemStone defines and types required for the GCI - shipped without
 *      global.ht
 *========================================================================
 */
#if !defined(GLOBAL_HT)

#if defined(FLG_MSWIN32)
typedef __int64          int64_t;
typedef unsigned __int64 uint64_t;
typedef unsigned int     uintptr_t;
typedef unsigned int     uint;
#endif

typedef uint64_t   OopType;         /* object identifier definition */
typedef uint64_t   OopNumberType;
typedef unsigned char   ByteType;
typedef int             BoolType;

typedef int64_t int64;
typedef uint64_t uint64;

/* Boolean constants, values for BoolType */
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif

#if !defined(FLG_CONST_UNDERSTOOD)
#define const
#endif

#if !defined(FLG_VOLATILE_UNDERSTOOD)
#define volatile
#endif

/* ==================================================================
 * Format strings for printing integers in both 32 and 64 bit builds
 *
 * Using %ld to print an intptr_t is safe regardless of whether compiling
 * for 32 bit pointers or 64 bit pointers , since %ld assumes a
 * 64 bit int in a 64 bit build, and a 32 bit int in a 32 bit build .
 *  However it will give a warning on a 32 bit compile, and you
 *  have to use %d to print a 32 bit intptr_t to avoid the warning.
 *
 * Always use %d to print an  int .
 *
 * FMT_I64 is format string for printing an int64_t
 * Use it only for int64 .
 *
 * Summary of recomended uses:
 *  int          "%d"
 *  unsigned int "%u"
 *  OopType      FMT_OID   (see definition below)
 *  pointer      %p or  FMT_P
 *  int64        FMT_I64
 *  uint64       FMT_U64
 *  intptr_t     FMT_PTR_T
 *  uintptr_t    FMT_UPTR_T
 *
 */
#ifdef _LP64
/* Unix 64 bit address space */
#define FMT_PTR_T  "%ld"
#define FMT_UPTR_T "%lu"

#define FMT_I64 "%ld"
#define FMT_U64 "%lu"
#define FMT_X64 "0x%lx"

#else /* _LP64 */
/* 32 bit address space */
#define FMT_PTR_T  "%d"
#define FMT_UPTR_T "%u"

#if defined(FLG_MSWIN32)
/* Windows */
#define FMT_I64      "%I64d"
#define FMT_U64      "%I64d"
#define FMT_X64      "0x%I64x"
#else 
/* Unix */
#define FMT_I64   "%lld"
#define FMT_U64   "%llu"
#define FMT_X64   "0x%llx"
#endif /* FLG_MSWIN32 */

#endif /* _LP64 */

#define FMT_OID FMT_U64

/* Format string for printing pointers , %p automatically
 *  handles the size of the pointer */
#if defined(FLG_LINUX_UNIX) || defined(FLG_APPLE_UNIX)
/* Linux does the 0x prefix automatically , Solaris does not*/
#define FMT_P "%p"
#else
#define FMT_P "0x%p"
#endif

#if defined FLG_UNIX
#define I64_CONST(arg)  ( arg##LL )
#else
#define I64_CONST(arg)  ( arg##i64 )
#endif

#endif /* !defined(GLOBAL_HT */
/*======================================================================== */

typedef int  GciSessionIdType;
#define      GCI_INVALID_SESSION_ID  ((GciSessionIdType)(0))
#define      GCI_LNK_SESSION_ID      ((GciSessionIdType)(1))
#define      GCI_LNK_SERVICE      "gcilnkobj"
#define      GCI_RPC_SERVICE      "gemnetobject"

enum { 	GCI_ERR_STR_SIZE      =  1024,       /* Max size of an error str   */
	GCI_MAX_ERR_ARGS      =  10,        /* Max num args for error str */
	GCI_MAX_ACTION_NAME   =  31,        /* Max User Action name len   */
	GCI_MAX_ACTION_ARGS   =  8,         /* Max User action num args   */

	GCI_SMALL_OBJ_BYTE_SIZE = 16000 /* approximation of max small obj */
  };

#include "gcioop.ht"
#include "gcierr.ht"                          /* GemStone errors */

/* Nonblocking status constants , 
 *  must agree with hydra GciCalls.java , do not reorder */
typedef enum {
  GCI_RESULT_NOT_READY = 0,		/* nothing happened */
  GCI_RESULT_PROGRESSED = 1,	/* a packet was received */
  GCI_RESULT_READY = 2, /* your result is now ready */
  GCI_RESULT_HAS_ERROR = 3 /* result is ready with error, used in hydra */
  } GciNbProgressEType;


/* =============================================================================
 * GCI_ALIGN macro
 *   Align an address to an 8-byte boundary.
 *
 * Arguments:
 *   (1) The address to align.
 *
 * Result value:
 *   A aligned uintptr_t that is >= the address argument .
 *==============================================================================
 */
#if !defined(UTL_ALIGN)
#define UTL_ALIGN(val, alignSize) \
 (((uintptr_t)(val) + ((alignSize) - 1)) & ~((uintptr_t)(alignSize) - 1) )
#endif

#define GCI_ALIGN(address)  UTL_ALIGN((address), sizeof(OopType) )

/*========================================================================
 *  --  GciDbgEstablish: typedef for name of application's debug function
 *
 *      char message[] - is a null terminated str passed to the application's
 *                       debugging function (that is "established" with
 *                       GciDbgEstablish) it contains the name of the GCI
 *                       function about to be executed.
 *
 *========================================================================
 */
typedef void GciDbgFuncType( const char message[] );

/*========================================================================
 *  GCI Error message specification
 *========================================================================
 */
typedef struct {
  OopType       category;                      /* error dictionary       */
  OopType       context;  /* GemStone Smalltalk execution state , a GsProcess */
  OopType       args[GCI_MAX_ERR_ARGS];        /* arguments to error text */
  int          number;                        /* GemStone error number  */
  int          argCount;                      /* num of arg in the args[]*/
  unsigned char fatal;                         /* nonzero if err is fatal */
  char          message[GCI_ERR_STR_SIZE + 1]; /* null-term. str of err text */
} GciErrSType;

/*========================================================================
 * GCI object report data structure  , result of GciTraverseObjs, etc.
 *========================================================================
 */

class CLS_EXPORT GciObjRepHdrSType 
{   /* object report header struct */
 public:
  int          valueBuffSize;    /* size in bytes of obj's value buff */
  short         namedSize;       /* number of named instVars */
  unsigned short segmentId; // 
      // For store traversals, segmentId == UNDEFINED_SEGMENT_ID means
      // segment of object should not be changed , or that for
      // object creation the current default segment will be used.
  OopType       objId;       /* OOP of the object  */
  OopType       oclass;      /* OOP of the class of the object  */
  int64         firstOffset; /* absolute offset of first instVar in the value 
                       buffer, 1 means first instVar is first named instVar */
 private:
  int64 _idxSizeBits; 

 public:
  enum {  // definitions of bottom 8 bits within _idxSizeBits
  	 implem_mask    = GC_IMPLEMENTATION_MASK, // 0x03
	 indexable_mask = GC_INDEXABLE_MASK,      // 0x04
         invariant_mask = GC_INVARIANT_MASK,      // 0x08
         partial_mask   = 0x10,                
         overlay_mask   = 0x20,
      no_read_auth_mask = 0x40,
         clamped_mask   = 0x80,
         unused_mask  = 0xFF00,
        all_bits_mask = 0xFFFF
       };

  inline int64 idxSize() const {  /* number of indexable or varying instVars */
     return _idxSizeBits >> 16; 
  }

  inline void setIdxSize(int64 size) {
    _idxSizeBits = (size << 16) | (_idxSizeBits & all_bits_mask)  ;
  }

  inline void setIdxSizeBits(int64 size, unsigned char bits) {
    // bits must conform to bits defined in the the  enum above
    _idxSizeBits = (size << 16) | bits ;
  }

  inline int objImpl() const {  
    /* return implementation format 0..3 , one of GC_FORMAT_OOP..GC_FORMAT_SPECIAL */
    return _idxSizeBits & GC_IMPLEMENTATION_MASK; 
  }

  inline void setObjImpl(int v) {  
    /* arg is format 0..3 , one of GC_FORMAT_OOP..GC_FORMAT_SPECIAL */
    uint64 mask = GC_IMPLEMENTATION_MASK;
    _idxSizeBits = ( _idxSizeBits & ~ mask) | (v & mask) ;
  }

  inline int64 objSize() const {   /* total number of instVars in the object */
    return idxSize() + namedSize; 
  }

  inline void clearBits() {
    uint64 mask = all_bits_mask ;
    _idxSizeBits &= ~ mask;
  }

  inline unsigned char isClamped() const { return _idxSizeBits & clamped_mask; }
  inline unsigned char noReadAuthorization() const { return _idxSizeBits & no_read_auth_mask; }
  inline unsigned char isInvariant() const { return _idxSizeBits & invariant_mask; }
  inline unsigned char isIndexable() const { return _idxSizeBits & indexable_mask; }
  inline unsigned char isPartial()   const { return _idxSizeBits & partial_mask; }
  inline unsigned char isOverlayed() const { return _idxSizeBits & overlay_mask; }

  inline void setIsClamped(unsigned char val) {
    uint64 mask = clamped_mask;
    if (val) { _idxSizeBits |= mask; } else { _idxSizeBits &= ~mask;} 
  }
  inline void setNoReadAuth(unsigned char val) {
    uint64 mask = no_read_auth_mask;
    if (val) { _idxSizeBits |= mask; } else { _idxSizeBits &= ~mask;} 
  }
  inline void setInvariant(unsigned char val) {
    uint64 mask = invariant_mask;
    if (val) { _idxSizeBits |= mask; } else { _idxSizeBits &= ~mask;} 
  }
  inline void setIndexable(unsigned char val) {
    uint64 mask = indexable_mask;
    if (val) { _idxSizeBits |= mask; } else { _idxSizeBits &= ~mask;} 
  }
  inline void setPartial(unsigned char val) {
    uint64 mask = partial_mask;
    if (val) { _idxSizeBits |= mask; } else { _idxSizeBits &= ~mask;} 
  }
  inline void setOverlayed(unsigned char val) {
    uint64 mask = overlay_mask;
    if (val) { _idxSizeBits |= mask; } else { _idxSizeBits &= ~mask;} 
  }

  inline void setIsClamped() {
    uint64 mask = clamped_mask;
    _idxSizeBits |= mask;
  }
  inline void setPartial() {
    uint64 mask = partial_mask;
    _idxSizeBits |= mask;
  }
  inline void clearPartial() {
    uint64 mask = partial_mask;
    _idxSizeBits &= ~ mask;
  }

  inline int64 usedBytes() const {
    return sizeof(*this) + GCI_ALIGN(this->valueBuffSize);
  }

  inline int64 valueBufNumOops() const {
    return this->valueBuffSize / sizeof(OopType);
  }

  static intptr_t usedBytes(int valueBuffSize) {
    return sizeof(GciObjRepHdrSType) + GCI_ALIGN(valueBuffSize);
  }

  inline GciObjRepHdrSType *nextReport() const {
    return (GciObjRepHdrSType*)((char*)this + this->usedBytes());
  }

  inline ByteType* valueBufferBytes() const {
    return (ByteType*)((char*)this + sizeof(*this));
  }
  inline OopType* valueBufferOops() const {
    return (OopType*)((char*)this + sizeof(*this));
  }

} ;

/*========================================================================*/
class CLS_EXPORT GciObjRepSType { /* object report struct */
 public:
  GciObjRepHdrSType hdr;                /* object report header */
  union {
    ByteType        bytes[1];           /* Byte obj impl. obj's value buff   */
    OopType         oops[1];            /* Pointer obj impl. obj's value buff*/
  } u;

  inline int64 usedBytes() const {
    return this->hdr.usedBytes(); 
  }

  inline GciObjRepSType* nextReport() const {
    return (GciObjRepSType*) this->hdr.nextReport();
  }

  inline ByteType* valueBufferBytes() const {
    return (ByteType*)this->u.bytes;
  }

  inline OopType* valueBufferOops() const {
    return (OopType*)this->u.oops;
  }
};


/*========================================================================
 *  GciObjInfoSType struct, result of GciFetchObjInfo function
 *========================================================================
 */
class CLS_EXPORT GciObjInfoSType {
 public:
  OopType       objId;                  /* OOP of the obj */
  OopType       objClass;                  /* OOP of the class of the obj */
  int64         objSize;                /* obj's total size, in bytes or OOPs*/
  int           namedSize;              /* num of named inst vars in the obj */
  unsigned short  segmentId;
 private:
  unsigned short  _bits;
 public:
  enum {  // definitions of bits within _bits
         implem_mask    = GC_IMPLEMENTATION_MASK, // 0x03
         indexable_mask = GC_INDEXABLE_MASK,      // 0x04
         invariant_mask = GC_INVARIANT_MASK,      // 0x08
         partial_mask   = 0x10,                
         overlay_mask   = 0x20
       };

  inline unsigned char isInvariant() { return _bits & invariant_mask; }
  inline unsigned char isIndexable() { return _bits & indexable_mask; }
  inline unsigned char isPartial()   { return _bits & partial_mask; }
  inline unsigned char isOverlayed() { return _bits & overlay_mask; }

  inline unsigned char objImpl() {
    /* implementation format 0..3 , one of GC_FORMAT_OOP..GC_FORMAT_SPECIAL */
    return _bits & GC_IMPLEMENTATION_MASK;
  }
  inline void clearBits() { _bits = 0; }

  inline void setBits(unsigned char b) { _bits = b; }

  inline void setObjImpl(unsigned char f) { 
    _bits = (_bits & ~ implem_mask) | (f & implem_mask) ; 
  }

  inline void setInvariant(unsigned char val) {
    if (val) { _bits |= invariant_mask; } else { _bits &= ~invariant_mask;} 
  }
  inline void setIndexable(unsigned char val) {
    if (val) { _bits |= indexable_mask; } else { _bits &= ~indexable_mask;} 
  }
  inline void setPartial(unsigned char val) {
    if (val) { _bits |= partial_mask; } else { _bits &= ~partial_mask;} 
  }
  inline void setOverlayed(unsigned char val) {
    if (val) { _bits |= overlay_mask; } else { _bits &= ~overlay_mask;} 
  }
};

/*========================================================================
 * GCI   User Action typedef and data structure
 *                  The name must be the first element of the
 *                  GciUserActionSType; because the hash table utilities
 *                  depend upon it.
 *========================================================================
 */

/* this type MUST NOT have a function prototype; it is invoked with zero
   or more args */

typedef OopType (*GciUserActionFType)
#if defined(FLG_GNUC)
      (void)
#else
      ()
#endif
    ; /* pointer to user action function */

enum {
  UAFLAG_SESSION = 0x01, /* If set then it is a session user action */
  UAFLAG_SYSTEM  = 0x02  /* If set then it is a system user action
			  * This attribute is used for builtin user
			  * actions so that the do not show up in
			  * a System|userActionReport.
			  */
};

typedef struct {
  char               userActionName[GCI_MAX_ACTION_NAME+1];  /* function name */
  int               userActionNumArgs; 
  GciUserActionFType userAction;     /* pointer to funct */
  unsigned int      userActionFlags; /* See the UAFLAG_* constants */
} GciUserActionSType;

/*========================================================================
 *
 *  GciStoreTrav - definitions for "flag" argument
 *
 *========================================================================
 */
enum { GCI_STORE_TRAV_DEFAULT = 0,
    /* default behavior: 
     *   use "add" sematics for varying instvars of Nsc's.
     *   if object to be stored into does not exist, give error
     */

  /* The following flags are orthogonal to each other; any combination of them
   * is allowed
   */
   GCI_STORE_TRAV_NSC_REP = 0x1,
   /*  use REPLACE semantics for varying instvars of Nsc's */

   GCI_STORE_TRAV_CREATE =  0x2,
   /*  If an object to be stored into does not exist, use GciCreate to
    *  semantics to create the object. such created objects are added to
    *  the PureExportSet .
    */

   GCI_STORE_TRAV_CREATE_PERMANENT = 0x4,
   /* This flag has no effect in this release */

   GCI_STORE_TRAV_FINISH_UPDATES = 0x8
  /* After processing the last object report in the traversal buffer,
   * automatically execute GciProcessDeferredUpdates
   */
  };

/*========================================================================*/

typedef void GciLogFuncType(const char str[]);

typedef void GciCallBackFType(void);

typedef BoolType GciGetCmdFType(const char *prompt, BoolType skipWhite);

/* Flags for GciLoginEx */
enum { GCI_LOGIN_PW_ENCRYPTED = 1, /* The gemstonePassword is encrypted. */
       GCI_LOGIN_IS_SUBORDINATE = 2, /* Session created by this login
				    * is a child of the current session
				    * and will be terminated if the
				    * current session terminates.
				    */
       GCI_LOGIN_FULL_COMPRESSION_ENABLED = 4, /*support for full compression */
       GCI_LOGIN_ERRS_USE_REF_SET = 8  /* oop fields of GciErrSType 
                                  * added to ReferencedSet instead of PureExportSet */
  };



/* enumerated type that defines the possible kinds of an IEEE binary float.
 * The ordering in this list matches the GemStone Smalltalk list given in 
 * the method  Number(C)/_kindList
 */
typedef enum {
  GCI_FLOAT_KIND_INVALID,  /* 0 is not used in this enumerated type */
  GCI_FLOAT_KIND_NORMAL,
  GCI_FLOAT_KIND_SUB_NORMAL,
  GCI_FLOAT_KIND_INFINITY,
  GCI_FLOAT_KIND_ZERO,
  GCI_FLOAT_KIND_QUIET_NAN,
  GCI_FLOAT_KIND_SIGNALLING_NAN
  } GciFloatKindEType;

/* ================================================================ 
 * GciJmpBufSType, Gci jump buffer type .
 *
 * Instances of this type must be initialized by using Gci_SETJMP()
 */

typedef struct {
  jmp_buf buf;
  } GciJmpBufSType;

/* ================================================================ 
 *  Gci_SETJMP   
 *     except for difference in argument type, the
 *     semantics are the same as setjmp() on Solaris and Win32,
 *     semantics are the same as _setjmp() on HPUX  .
 *
 *   The argument is expected to be of type   GciJmpBufSType*
 *
 * new in Gemstone64, replaces GCI_SETJMP
 */
#if defined(FLG_SETJMP_BSD)
#define Gci_SETJMP(aBuf) _setjmp((aBuf)->buf)
#else
#define Gci_SETJMP(aBuf) setjmp((aBuf)->buf)
#endif

 
typedef uint64 GciClientDataType;
typedef void GciLoginCallbackFuncType(GciSessionIdType id, BoolType isLogin,
				      GciClientDataType clientData);

typedef void* GciOopMapEntryType;
typedef void* GciOopMapType;
typedef BoolType GciOopMapCallbackFuncType(GciOopMapEntryType entry, 
	int64 *arg1, int64* arg2);

#if !defined(UTL_HT)
typedef struct {
  char msg[100];
}  GciCTimeStringType;
#endif



#endif /* GCI_HT */
