/*----------------------------------------------------------------------------------------
  Module header file for: ut module
----------------------------------------------------------------------------------------*/
#ifndef UTDATABASE_H

#define UTDATABASE_H

#if defined __cplusplus
extern "C" {
#endif

#ifndef DD_UTIL_H
#include "ddutil.h"
#endif

/* Class reference definitions */

#if defined(DD_DEBUG) && !defined(DD_NOSTRICT)
typedef struct _struct_utSymtab{char val;} *utSymtab;
#define utSymtabNull ((utSymtab)(UINT32_MAX))
#define utSymtab2Index(Symtab) ((uint32)((Symtab) - (utSymtab)(0)))
#define utSymtab2ValidIndex(Symtab) ((uint32)(utValidSymtab(Symtab) - (utSymtab)(0)))
#define utIndex2Symtab(xSymtab) ((utSymtab)((xSymtab) + (utSymtab)(0)))
typedef struct _struct_utSym{char val;} *utSym;
#define utSymNull ((utSym)(UINT32_MAX))
#define utSym2Index(Sym) ((uint32)((Sym) - (utSym)(0)))
#define utSym2ValidIndex(Sym) ((uint32)(utValidSym(Sym) - (utSym)(0)))
#define utIndex2Sym(xSym) ((utSym)((xSym) + (utSym)(0)))
typedef struct _struct_utDynarray{char val;} *utDynarray;
#define utDynarrayNull ((utDynarray)(UINT32_MAX))
#define utDynarray2Index(Dynarray) ((uint32)((Dynarray) - (utDynarray)(0)))
#define utDynarray2ValidIndex(Dynarray) ((uint32)(utValidDynarray(Dynarray) - (utDynarray)(0)))
#define utIndex2Dynarray(xDynarray) ((utDynarray)((xDynarray) + (utDynarray)(0)))
typedef struct _struct_utSymArray{char val;} *utSymArray;
#define utSymArrayNull ((utSymArray)(UINT32_MAX))
#define utSymArray2Index(SymArray) ((uint32)((SymArray) - (utSymArray)(0)))
#define utSymArray2ValidIndex(SymArray) ((uint32)(utValidSymArray(SymArray) - (utSymArray)(0)))
#define utIndex2SymArray(xSymArray) ((utSymArray)((xSymArray) + (utSymArray)(0)))
#else
typedef uint32 utSymtab;
#define utSymtabNull UINT32_MAX
#define utSymtab2Index(Symtab) (Symtab)
#define utSymtab2ValidIndex(Symtab) (utValidSymtab(Symtab))
#define utIndex2Symtab(xSymtab) ((xSymtab))
typedef uint32 utSym;
#define utSymNull UINT32_MAX
#define utSym2Index(Sym) (Sym)
#define utSym2ValidIndex(Sym) (utValidSym(Sym))
#define utIndex2Sym(xSym) ((xSym))
typedef uint32 utDynarray;
#define utDynarrayNull UINT32_MAX
#define utDynarray2Index(Dynarray) (Dynarray)
#define utDynarray2ValidIndex(Dynarray) (utValidDynarray(Dynarray))
#define utIndex2Dynarray(xDynarray) ((xDynarray))
typedef uint32 utSymArray;
#define utSymArrayNull UINT32_MAX
#define utSymArray2Index(SymArray) (SymArray)
#define utSymArray2ValidIndex(SymArray) (utValidSymArray(SymArray))
#define utIndex2SymArray(xSymArray) ((xSymArray))
#endif

/* FieldType enumerated type */
typedef enum {
    UT_BIT = 0,
    UT_BOOL = 1,
    UT_INT = 2,
    UT_UINT = 3,
    UT_CHAR = 4,
    UT_FLOAT = 5,
    UT_DOUBLE = 6,
    UT_POINTER = 7,
    UT_TYPEDEF = 8,
    UT_ENUM = 9,
    UT_SYM = 10,
    UT_UNION = 11
} utFieldType;

/* Validate macros */
#if defined(DD_DEBUG)
#define utValidSymtab(Symtab) (utLikely((uint32)((Symtab) - (utSymtab)0) < \
    utRootData.usedSymtab)? (Symtab) : (utExit("Invalid Symtab"), (utSymtab)0))
#define utValidSym(Sym) (utLikely((uint32)((Sym) - (utSym)0) < \
    utRootData.usedSym)? (Sym) : (utExit("Invalid Sym"), (utSym)0))
#define utValidDynarray(Dynarray) (utLikely((uint32)((Dynarray) - (utDynarray)0) < \
    utRootData.usedDynarray)? (Dynarray) : (utExit("Invalid Dynarray"), (utDynarray)0))
#define utValidSymArray(SymArray) (utLikely((uint32)((SymArray) - (utSymArray)0) < \
    utRootData.usedSymArray)? (SymArray) : (utExit("Invalid SymArray"), (utSymArray)0))
#else
#define utValidSymtab(Symtab) (Symtab)
#define utValidSym(Sym) (Sym)
#define utValidDynarray(Dynarray) (Dynarray)
#define utValidSymArray(SymArray) (SymArray)
#endif

/*----------------------------------------------------------------------------------------
  Fields for class Symtab.
----------------------------------------------------------------------------------------*/
struct utSymtabFields {
    uint32 *TableIndex;
    uint32 *NumTable;
    utSym *Table;
    uint32 *NumSym;
};
extern struct utSymtabFields utSymtabs;

#define utSymtabGetTableIndex(_Symtab) (utSymtabs.TableIndex[utSymtab2ValidIndex(_Symtab)])
#define utSymtabSetTableIndex(_Symtab, value) ( \
    (void)utRecordField(utModuleID, 0, utSymtab2ValidIndex(_Symtab), true), \
    (utSymtabs.TableIndex)[utSymtab2ValidIndex(_Symtab)] = (value), \
    (void)utRecordField(utModuleID, 0, utSymtab2ValidIndex(_Symtab), false))
#define utSymtabGetNumTable(_Symtab) (utSymtabs.NumTable[utSymtab2ValidIndex(_Symtab)])
#define utSymtabSetNumTable(_Symtab, value) ( \
    (void)utRecordField(utModuleID, 1, utSymtab2ValidIndex(_Symtab), true), \
    (utSymtabs.NumTable)[utSymtab2ValidIndex(_Symtab)] = (value), \
    (void)utRecordField(utModuleID, 1, utSymtab2ValidIndex(_Symtab), false))
#if defined(DD_DEBUG)
#define utSymtabCheckTableIndex(Symtab, x) ((uint32)(x) < utSymtabGetNumTable(Symtab)? (x) : \
    (utAssert(false),(x)))
#else
#define utSymtabCheckTableIndex(Symtab, x) (x)
#endif
#define utSymtabGetiTable(_Symtab, x) ((utSymtabs.Table)[ \
    utSymtabGetTableIndex(_Symtab) + utSymtabCheckTableIndex(_Symtab, (x))])
#define utSymtabGetTable(Symtab) (utSymtabs.Table + utSymtabGetTableIndex(Symtab))
#define utSymtabGetTables utSymtabGetTable
#define utSymtabSetTable(Symtab, valuePtr, numTable) (utSymtabResizeTables(Symtab, numTable),  \
    (void)utRecordArray(utModuleID, 2, utSymtabGetTableIndex(Symtab), utSymtabGetNumTable(Symtab), true), \
    memcpy(utSymtabGetTables(Symtab), valuePtr, \
    numTable*sizeof(utSym)), \
    (void)utRecordArray(utModuleID, 2, utSymtabGetTableIndex(Symtab), utSymtabGetNumTable(Symtab), false))
#define utSymtabSetiTable(Symtab, x, value) ( \
    (void)utRecordField(utModuleID, 2, utSymtabGetTableIndex(Symtab) + (x), true), \
    (utSymtabs.Table)[ \
    utSymtabGetTableIndex(Symtab) + utSymtabCheckTableIndex(Symtab, (x))] = (value), \
    (void)utRecordField(utModuleID, 2, utSymtabGetTableIndex(Symtab) + (x), false))
#define utSymtabGetNumSym(_Symtab) (utSymtabs.NumSym[utSymtab2ValidIndex(_Symtab)])
#define utSymtabSetNumSym(_Symtab, value) ( \
    (void)utRecordField(utModuleID, 3, utSymtab2ValidIndex(_Symtab), true), \
    (utSymtabs.NumSym)[utSymtab2ValidIndex(_Symtab)] = (value), \
    (void)utRecordField(utModuleID, 3, utSymtab2ValidIndex(_Symtab), false))
#define utSymtabSetConstructorCallback(func) (utSymtabConstructorCallback = (func))
#define utSymtabGetConstructorCallback() (utSymtabConstructorCallback)
#define utFirstSymtab() (utRootData.usedSymtab == 0? utSymtabNull : utIndex2Symtab(0))
#define utLastSymtab() (utRootData.usedSymtab == 0? utSymtabNull : \
    utIndex2Symtab(utRootData.usedSymtab - 1))
#define utNextSymtab(Symtab) (utSymtab2ValidIndex(Symtab) + 1 == utRootData.usedSymtab? utSymtabNull : \
    (Symtab) + 1)
#define utPrevSymtab(Symtab) (utSymtab2ValidIndex(Symtab) == 0? utSymtabNull : (Symtab) - 1)
#define utForeachSymtab(var) \
    for(var = utIndex2Symtab(0); utSymtab2Index(var) != utRootData.usedSymtab; var++)
#define utEndSymtab
#define utSymtabFreeAll() (utSetUsedSymtab(0), utSetUsedSymtabTable(0))
#define utSymtabAllocRaw() ( \
    utRootData.usedSymtab == utRootData.allocatedSymtab && (utSymtabAllocMore(), true), \
    utTemp_.Symtab = utIndex2Symtab(utRootData.usedSymtab), \
    utSetUsedSymtab(utUsedSymtab() + 1), \
    utTemp_.Symtab)
#define utSymtabAlloc() ( \
    utRootData.usedSymtab == utRootData.allocatedSymtab && (utSymtabAllocMore(), true), \
    utTemp_.Symtab = utIndex2Symtab(utRootData.usedSymtab), \
    utSetUsedSymtab(utUsedSymtab() + 1), \
    utSymtabSetTableIndex(utTemp_.Symtab, 0), \
    utSymtabSetNumTable(utTemp_.Symtab, 0), \
    utSymtabSetNumTable(utTemp_.Symtab, 0), \
    utSymtabSetNumSym(utTemp_.Symtab, 0), \
    utSymtabConstructorCallback != NULL && (utSymtabConstructorCallback(utTemp_.Symtab), true), \
    utTemp_.Symtab)

void utSymtabAllocMore(void);
void utSymtabCopyProps(utSymtab utOldSymtab, utSymtab utNewSymtab);
void utSymtabAllocTables(utSymtab Symtab, uint32 numTables);
void utSymtabResizeTables(utSymtab Symtab, uint32 numTables);
void utSymtabFreeTables(utSymtab Symtab);
void utCompactSymtabTables(void);

/*----------------------------------------------------------------------------------------
  Fields for class Sym.
----------------------------------------------------------------------------------------*/
struct utSymFields {
    uint32 *NameIndex;
    uint32 *NumName;
    char *Name;
    uint32 *HashValue;
    utSym *Next;
};
extern struct utSymFields utSyms;

#define utSymGetNameIndex(_Sym) (utSyms.NameIndex[utSym2ValidIndex(_Sym)])
#define utSymSetNameIndex(_Sym, value) ( \
    (void)utRecordField(utModuleID, 4, utSym2ValidIndex(_Sym), true), \
    (utSyms.NameIndex)[utSym2ValidIndex(_Sym)] = (value), \
    (void)utRecordField(utModuleID, 4, utSym2ValidIndex(_Sym), false))
#define utSymGetNumName(_Sym) (utSyms.NumName[utSym2ValidIndex(_Sym)])
#define utSymSetNumName(_Sym, value) ( \
    (void)utRecordField(utModuleID, 5, utSym2ValidIndex(_Sym), true), \
    (utSyms.NumName)[utSym2ValidIndex(_Sym)] = (value), \
    (void)utRecordField(utModuleID, 5, utSym2ValidIndex(_Sym), false))
#if defined(DD_DEBUG)
#define utSymCheckNameIndex(Sym, x) ((uint32)(x) < utSymGetNumName(Sym)? (x) : \
    (utAssert(false),(x)))
#else
#define utSymCheckNameIndex(Sym, x) (x)
#endif
#define utSymGetiName(_Sym, x) ((utSyms.Name)[ \
    utSymGetNameIndex(_Sym) + utSymCheckNameIndex(_Sym, (x))])
#define utSymGetName(Sym) (utSyms.Name + utSymGetNameIndex(Sym))
#define utSymGetNames utSymGetName
#define utSymSetName(Sym, valuePtr, numName) (utSymResizeNames(Sym, numName),  \
    (void)utRecordArray(utModuleID, 6, utSymGetNameIndex(Sym), utSymGetNumName(Sym), true), \
    memcpy(utSymGetNames(Sym), valuePtr, \
    numName*sizeof(char)), \
    (void)utRecordArray(utModuleID, 6, utSymGetNameIndex(Sym), utSymGetNumName(Sym), false))
#define utSymSetiName(Sym, x, value) ( \
    (void)utRecordField(utModuleID, 6, utSymGetNameIndex(Sym) + (x), true), \
    (utSyms.Name)[ \
    utSymGetNameIndex(Sym) + utSymCheckNameIndex(Sym, (x))] = (value), \
    (void)utRecordField(utModuleID, 6, utSymGetNameIndex(Sym) + (x), false))
#define utSymGetHashValue(_Sym) (utSyms.HashValue[utSym2ValidIndex(_Sym)])
#define utSymSetHashValue(_Sym, value) ( \
    (void)utRecordField(utModuleID, 7, utSym2ValidIndex(_Sym), true), \
    (utSyms.HashValue)[utSym2ValidIndex(_Sym)] = (value), \
    (void)utRecordField(utModuleID, 7, utSym2ValidIndex(_Sym), false))
#define utSymGetNext(_Sym) (utSyms.Next[utSym2ValidIndex(_Sym)])
#define utSymSetNext(_Sym, value) ( \
    (void)utRecordField(utModuleID, 8, utSym2ValidIndex(_Sym), true), \
    (utSyms.Next)[utSym2ValidIndex(_Sym)] = (value), \
    (void)utRecordField(utModuleID, 8, utSym2ValidIndex(_Sym), false))
#define utSymSetConstructorCallback(func) (utSymConstructorCallback = (func))
#define utSymGetConstructorCallback() (utSymConstructorCallback)
#define utFirstSym() (utRootData.usedSym == 0? utSymNull : utIndex2Sym(0))
#define utLastSym() (utRootData.usedSym == 0? utSymNull : \
    utIndex2Sym(utRootData.usedSym - 1))
#define utNextSym(Sym) (utSym2ValidIndex(Sym) + 1 == utRootData.usedSym? utSymNull : \
    (Sym) + 1)
#define utPrevSym(Sym) (utSym2ValidIndex(Sym) == 0? utSymNull : (Sym) - 1)
#define utForeachSym(var) \
    for(var = utIndex2Sym(0); utSym2Index(var) != utRootData.usedSym; var++)
#define utEndSym
#define utSymFreeAll() (utSetUsedSym(0), utSetUsedSymName(0))
#define utSymAllocRaw() ( \
    utRootData.usedSym == utRootData.allocatedSym && (utSymAllocMore(), true), \
    utTemp_.Sym = utIndex2Sym(utRootData.usedSym), \
    utSetUsedSym(utUsedSym() + 1), \
    utTemp_.Sym)
#define utSymAlloc() ( \
    utRootData.usedSym == utRootData.allocatedSym && (utSymAllocMore(), true), \
    utTemp_.Sym = utIndex2Sym(utRootData.usedSym), \
    utSetUsedSym(utUsedSym() + 1), \
    utSymSetNameIndex(utTemp_.Sym, 0), \
    utSymSetNumName(utTemp_.Sym, 0), \
    utSymSetNumName(utTemp_.Sym, 0), \
    utSymSetHashValue(utTemp_.Sym, 0), \
    utSymSetNext(utTemp_.Sym, utSymNull), \
    utSymConstructorCallback != NULL && (utSymConstructorCallback(utTemp_.Sym), true), \
    utTemp_.Sym)

void utSymAllocMore(void);
void utSymCopyProps(utSym utOldSym, utSym utNewSym);
void utSymAllocNames(utSym Sym, uint32 numNames);
void utSymResizeNames(utSym Sym, uint32 numNames);
void utSymFreeNames(utSym Sym);
void utCompactSymNames(void);

/*----------------------------------------------------------------------------------------
  Fields for class Dynarray.
----------------------------------------------------------------------------------------*/
struct utDynarrayFields {
    uint32 *ValueIndex;
    uint32 *NumValue;
    uint8 *Value;
    uint16 *ValueSize;
    uint32 *UsedValue;
    uint32 *Size;
    utDynarray *FreeList;
};
extern struct utDynarrayFields utDynarrays;

#define utDynarrayGetValueIndex(_Dynarray) (utDynarrays.ValueIndex[utDynarray2ValidIndex(_Dynarray)])
#define utDynarraySetValueIndex(_Dynarray, value) ( \
    (void)utRecordField(utModuleID, 9, utDynarray2ValidIndex(_Dynarray), true), \
    (utDynarrays.ValueIndex)[utDynarray2ValidIndex(_Dynarray)] = (value), \
    (void)utRecordField(utModuleID, 9, utDynarray2ValidIndex(_Dynarray), false))
#define utDynarrayGetNumValue(_Dynarray) (utDynarrays.NumValue[utDynarray2ValidIndex(_Dynarray)])
#define utDynarraySetNumValue(_Dynarray, value) ( \
    (void)utRecordField(utModuleID, 10, utDynarray2ValidIndex(_Dynarray), true), \
    (utDynarrays.NumValue)[utDynarray2ValidIndex(_Dynarray)] = (value), \
    (void)utRecordField(utModuleID, 10, utDynarray2ValidIndex(_Dynarray), false))
#if defined(DD_DEBUG)
#define utDynarrayCheckValueIndex(Dynarray, x) ((uint32)(x) < utDynarrayGetNumValue(Dynarray)? (x) : \
    (utAssert(false),(x)))
#else
#define utDynarrayCheckValueIndex(Dynarray, x) (x)
#endif
#define utDynarrayGetiValue(_Dynarray, x) ((utDynarrays.Value)[ \
    utDynarrayGetValueIndex(_Dynarray) + utDynarrayCheckValueIndex(_Dynarray, (x))])
#define utDynarrayGetValue(Dynarray) (utDynarrays.Value + utDynarrayGetValueIndex(Dynarray))
#define utDynarrayGetValues utDynarrayGetValue
#define utDynarraySetValue(Dynarray, valuePtr, numValue) (utDynarrayResizeValues(Dynarray, numValue),  \
    (void)utRecordArray(utModuleID, 11, utDynarrayGetValueIndex(Dynarray), utDynarrayGetNumValue(Dynarray), true), \
    memcpy(utDynarrayGetValues(Dynarray), valuePtr, \
    numValue*sizeof(uint8)), \
    (void)utRecordArray(utModuleID, 11, utDynarrayGetValueIndex(Dynarray), utDynarrayGetNumValue(Dynarray), false))
#define utDynarraySetiValue(Dynarray, x, value) ( \
    (void)utRecordField(utModuleID, 11, utDynarrayGetValueIndex(Dynarray) + (x), true), \
    (utDynarrays.Value)[ \
    utDynarrayGetValueIndex(Dynarray) + utDynarrayCheckValueIndex(Dynarray, (x))] = (value), \
    (void)utRecordField(utModuleID, 11, utDynarrayGetValueIndex(Dynarray) + (x), false))
#define utDynarrayGetValueSize(_Dynarray) (utDynarrays.ValueSize[utDynarray2ValidIndex(_Dynarray)])
#define utDynarraySetValueSize(_Dynarray, value) ( \
    (void)utRecordField(utModuleID, 12, utDynarray2ValidIndex(_Dynarray), true), \
    (utDynarrays.ValueSize)[utDynarray2ValidIndex(_Dynarray)] = (value), \
    (void)utRecordField(utModuleID, 12, utDynarray2ValidIndex(_Dynarray), false))
#define utDynarrayGetUsedValue(_Dynarray) (utDynarrays.UsedValue[utDynarray2ValidIndex(_Dynarray)])
#define utDynarraySetUsedValue(_Dynarray, value) ( \
    (void)utRecordField(utModuleID, 13, utDynarray2ValidIndex(_Dynarray), true), \
    (utDynarrays.UsedValue)[utDynarray2ValidIndex(_Dynarray)] = (value), \
    (void)utRecordField(utModuleID, 13, utDynarray2ValidIndex(_Dynarray), false))
#define utDynarrayGetSize(_Dynarray) (utDynarrays.Size[utDynarray2ValidIndex(_Dynarray)])
#define utDynarraySetSize(_Dynarray, value) ( \
    (void)utRecordField(utModuleID, 14, utDynarray2ValidIndex(_Dynarray), true), \
    (utDynarrays.Size)[utDynarray2ValidIndex(_Dynarray)] = (value), \
    (void)utRecordField(utModuleID, 14, utDynarray2ValidIndex(_Dynarray), false))
#define utDynarrayGetFreeList(_Dynarray) (utDynarrays.FreeList[utDynarray2ValidIndex(_Dynarray)])
#define utDynarraySetFreeList(_Dynarray, value) ( \
    (void)utRecordField(utModuleID, 15, utDynarray2ValidIndex(_Dynarray), true), \
    (utDynarrays.FreeList)[utDynarray2ValidIndex(_Dynarray)] = (value), \
    (void)utRecordField(utModuleID, 15, utDynarray2ValidIndex(_Dynarray), false))
#define utDynarraySetConstructorCallback(func) (utDynarrayConstructorCallback = (func))
#define utDynarrayGetConstructorCallback() (utDynarrayConstructorCallback)
#define utDynarraySetDestructorCallback(func) (utDynarrayDestructorCallback = (func))
#define utDynarrayGetDestructorCallback() (utDynarrayDestructorCallback)
#define utDynarrayNextFree(_Dynarray) (((utDynarray *)(void *)(utDynarrays.FreeList))[utDynarray2ValidIndex(_Dynarray)])
#define utDynarraySetNextFree(_Dynarray, value) ( \
    (void)utRecordField(utModuleID, 15, utDynarray2ValidIndex(Dynarray), true), \
    ((utDynarray *)(void *)(utDynarrays.FreeList)) \
    [utDynarray2ValidIndex(_Dynarray)] = (value), \
    (void)utRecordField(utModuleID, 15, utDynarray2ValidIndex(Dynarray), false))
#define utDynarrayAllocRaw() ( \
    utRootData.firstFreeDynarray != utDynarrayNull? \
        (utTemp_.Dynarray = utRootData.firstFreeDynarray, \
        utSetFirstFreeDynarray(utDynarrayNextFree(utTemp_.Dynarray)), true) \
    : (utRootData.usedDynarray == utRootData.allocatedDynarray && (utDynarrayAllocMore(), true), \
        utTemp_.Dynarray = utIndex2Dynarray(utRootData.usedDynarray), \
        utSetUsedDynarray(utUsedDynarray() + 1)), \
    utTemp_.Dynarray)
#define utDynarrayAlloc() ( \
    utRootData.firstFreeDynarray != utDynarrayNull? \
        (utTemp_.Dynarray = utRootData.firstFreeDynarray, \
        utSetFirstFreeDynarray(utDynarrayNextFree(utTemp_.Dynarray)), true) \
    : (utRootData.usedDynarray == utRootData.allocatedDynarray && (utDynarrayAllocMore(), true), \
        utTemp_.Dynarray = utIndex2Dynarray(utRootData.usedDynarray), \
        utSetUsedDynarray(utUsedDynarray() + 1)), \
    utDynarraySetValueIndex(utTemp_.Dynarray, 0), \
    utDynarraySetNumValue(utTemp_.Dynarray, 0), \
    utDynarraySetNumValue(utTemp_.Dynarray, 0), \
    utDynarraySetValueSize(utTemp_.Dynarray, 0), \
    utDynarraySetUsedValue(utTemp_.Dynarray, 0), \
    utDynarraySetSize(utTemp_.Dynarray, 0), \
    utDynarraySetFreeList(utTemp_.Dynarray, utDynarrayNull), \
    utDynarrayConstructorCallback != NULL && (utDynarrayConstructorCallback(utTemp_.Dynarray), true), \
    utTemp_.Dynarray)

#define utDynarrayFree(Dynarray) (utDynarrayFreeValues(Dynarray), \
    utDynarraySetNextFree(Dynarray, utRootData.firstFreeDynarray), \
    utSetFirstFreeDynarray(Dynarray))
void utDynarrayDestroy(utDynarray Dynarray);
void utDynarrayAllocMore(void);
void utDynarrayCopyProps(utDynarray utOldDynarray, utDynarray utNewDynarray);
void utDynarrayAllocValues(utDynarray Dynarray, uint32 numValues);
void utDynarrayResizeValues(utDynarray Dynarray, uint32 numValues);
void utDynarrayFreeValues(utDynarray Dynarray);
void utCompactDynarrayValues(void);

/*----------------------------------------------------------------------------------------
  Fields for class SymArray.
----------------------------------------------------------------------------------------*/
struct utSymArrayFields {
    uint32 *SymIndex;
    uint32 *NumSym;
    utSym *Sym;
    uint32 *UsedSym;
    utSymArray *FreeList;
};
extern struct utSymArrayFields utSymArrays;

#define utSymArrayGetSymIndex(_SymArray) (utSymArrays.SymIndex[utSymArray2ValidIndex(_SymArray)])
#define utSymArraySetSymIndex(_SymArray, value) ( \
    (void)utRecordField(utModuleID, 16, utSymArray2ValidIndex(_SymArray), true), \
    (utSymArrays.SymIndex)[utSymArray2ValidIndex(_SymArray)] = (value), \
    (void)utRecordField(utModuleID, 16, utSymArray2ValidIndex(_SymArray), false))
#define utSymArrayGetNumSym(_SymArray) (utSymArrays.NumSym[utSymArray2ValidIndex(_SymArray)])
#define utSymArraySetNumSym(_SymArray, value) ( \
    (void)utRecordField(utModuleID, 17, utSymArray2ValidIndex(_SymArray), true), \
    (utSymArrays.NumSym)[utSymArray2ValidIndex(_SymArray)] = (value), \
    (void)utRecordField(utModuleID, 17, utSymArray2ValidIndex(_SymArray), false))
#if defined(DD_DEBUG)
#define utSymArrayCheckSymIndex(SymArray, x) ((uint32)(x) < utSymArrayGetNumSym(SymArray)? (x) : \
    (utAssert(false),(x)))
#else
#define utSymArrayCheckSymIndex(SymArray, x) (x)
#endif
#define utSymArrayGetiSym(_SymArray, x) ((utSymArrays.Sym)[ \
    utSymArrayGetSymIndex(_SymArray) + utSymArrayCheckSymIndex(_SymArray, (x))])
#define utSymArrayGetSym(SymArray) (utSymArrays.Sym + utSymArrayGetSymIndex(SymArray))
#define utSymArrayGetSyms utSymArrayGetSym
#define utSymArraySetSym(SymArray, valuePtr, numSym) (utSymArrayResizeSyms(SymArray, numSym),  \
    (void)utRecordArray(utModuleID, 18, utSymArrayGetSymIndex(SymArray), utSymArrayGetNumSym(SymArray), true), \
    memcpy(utSymArrayGetSyms(SymArray), valuePtr, \
    numSym*sizeof(utSym)), \
    (void)utRecordArray(utModuleID, 18, utSymArrayGetSymIndex(SymArray), utSymArrayGetNumSym(SymArray), false))
#define utSymArraySetiSym(SymArray, x, value) ( \
    (void)utRecordField(utModuleID, 18, utSymArrayGetSymIndex(SymArray) + (x), true), \
    (utSymArrays.Sym)[ \
    utSymArrayGetSymIndex(SymArray) + utSymArrayCheckSymIndex(SymArray, (x))] = (value), \
    (void)utRecordField(utModuleID, 18, utSymArrayGetSymIndex(SymArray) + (x), false))
#define utSymArrayGetUsedSym(_SymArray) (utSymArrays.UsedSym[utSymArray2ValidIndex(_SymArray)])
#define utSymArraySetUsedSym(_SymArray, value) ( \
    (void)utRecordField(utModuleID, 19, utSymArray2ValidIndex(_SymArray), true), \
    (utSymArrays.UsedSym)[utSymArray2ValidIndex(_SymArray)] = (value), \
    (void)utRecordField(utModuleID, 19, utSymArray2ValidIndex(_SymArray), false))
#define utSymArrayGetFreeList(_SymArray) (utSymArrays.FreeList[utSymArray2ValidIndex(_SymArray)])
#define utSymArraySetFreeList(_SymArray, value) ( \
    (void)utRecordField(utModuleID, 20, utSymArray2ValidIndex(_SymArray), true), \
    (utSymArrays.FreeList)[utSymArray2ValidIndex(_SymArray)] = (value), \
    (void)utRecordField(utModuleID, 20, utSymArray2ValidIndex(_SymArray), false))
#define utForeachSymArraySym(pVar, cVar) { \
    uint32 _xSym; \
    for(_xSym = 0; _xSym < utSymArrayGetUsedSym(pVar); _xSym++) { \
        cVar = utSymArrayGetiSym(pVar, _xSym); \
        if(cVar != utSymNull) {
#define utEndSymArraySym }}}
#define utSymArraySetConstructorCallback(func) (utSymArrayConstructorCallback = (func))
#define utSymArrayGetConstructorCallback() (utSymArrayConstructorCallback)
#define utSymArraySetDestructorCallback(func) (utSymArrayDestructorCallback = (func))
#define utSymArrayGetDestructorCallback() (utSymArrayDestructorCallback)
#define utSymArrayNextFree(_SymArray) (((utSymArray *)(void *)(utSymArrays.FreeList))[utSymArray2ValidIndex(_SymArray)])
#define utSymArraySetNextFree(_SymArray, value) ( \
    (void)utRecordField(utModuleID, 20, utSymArray2ValidIndex(SymArray), true), \
    ((utSymArray *)(void *)(utSymArrays.FreeList)) \
    [utSymArray2ValidIndex(_SymArray)] = (value), \
    (void)utRecordField(utModuleID, 20, utSymArray2ValidIndex(SymArray), false))
#define utSymArrayAllocRaw() ( \
    utRootData.firstFreeSymArray != utSymArrayNull? \
        (utTemp_.SymArray = utRootData.firstFreeSymArray, \
        utSetFirstFreeSymArray(utSymArrayNextFree(utTemp_.SymArray)), true) \
    : (utRootData.usedSymArray == utRootData.allocatedSymArray && (utSymArrayAllocMore(), true), \
        utTemp_.SymArray = utIndex2SymArray(utRootData.usedSymArray), \
        utSetUsedSymArray(utUsedSymArray() + 1)), \
    utTemp_.SymArray)
#define utSymArrayAlloc() ( \
    utRootData.firstFreeSymArray != utSymArrayNull? \
        (utTemp_.SymArray = utRootData.firstFreeSymArray, \
        utSetFirstFreeSymArray(utSymArrayNextFree(utTemp_.SymArray)), true) \
    : (utRootData.usedSymArray == utRootData.allocatedSymArray && (utSymArrayAllocMore(), true), \
        utTemp_.SymArray = utIndex2SymArray(utRootData.usedSymArray), \
        utSetUsedSymArray(utUsedSymArray() + 1)), \
    utSymArraySetSymIndex(utTemp_.SymArray, 0), \
    utSymArraySetNumSym(utTemp_.SymArray, 0), \
    utSymArraySetNumSym(utTemp_.SymArray, 0), \
    utSymArraySetUsedSym(utTemp_.SymArray, 0), \
    utSymArraySetFreeList(utTemp_.SymArray, utSymArrayNull), \
    utSymArrayConstructorCallback != NULL && (utSymArrayConstructorCallback(utTemp_.SymArray), true), \
    utTemp_.SymArray)

#define utSymArrayFree(SymArray) (utSymArrayFreeSyms(SymArray), \
    utSymArraySetNextFree(SymArray, utRootData.firstFreeSymArray), \
    utSetFirstFreeSymArray(SymArray))
void utSymArrayDestroy(utSymArray SymArray);
void utSymArrayAllocMore(void);
void utSymArrayCopyProps(utSymArray utOldSymArray, utSymArray utNewSymArray);
void utSymArrayAllocSyms(utSymArray SymArray, uint32 numSyms);
void utSymArrayResizeSyms(utSymArray SymArray, uint32 numSyms);
void utSymArrayFreeSyms(utSymArray SymArray);
void utCompactSymArraySyms(void);
void utSymArrayInsertSym(utSymArray SymArray, uint32 x, utSym _Sym);
void utSymArrayAppendSym(utSymArray SymArray, utSym _Sym);

/*----------------------------------------------------------------------------------------
  Temp Union structure - Macro temp variables, use only one
----------------------------------------------------------------------------------------*/
union utTempType_ {
    utSymtab Symtab;
    utSym Sym;
    utDynarray Dynarray;
    utSymArray SymArray;
};

extern union utTempType_ utTemp_;

/*----------------------------------------------------------------------------------------
  Constructor/Destructor hooks.
----------------------------------------------------------------------------------------*/
extern void(*utSymtabConstructorCallback)(utSymtab);
extern void(*utSymConstructorCallback)(utSym);
extern void(*utDynarrayConstructorCallback)(utDynarray);
extern void(*utDynarrayDestructorCallback)(utDynarray);
extern void(*utSymArrayConstructorCallback)(utSymArray);
extern void(*utSymArrayDestructorCallback)(utSymArray);

/*----------------------------------------------------------------------------------------
  Root structure
----------------------------------------------------------------------------------------*/
struct utRootType_ {
    uint32 hash; /* This depends only on the structure of the database */
    uint32 usedSymtab, allocatedSymtab;
    uint32 usedSymtabTable, allocatedSymtabTable, freeSymtabTable;
    uint32 usedSym, allocatedSym;
    uint32 usedSymName, allocatedSymName, freeSymName;
    utDynarray firstFreeDynarray;
    uint32 usedDynarray, allocatedDynarray;
    uint32 usedDynarrayValue, allocatedDynarrayValue, freeDynarrayValue;
    utSymArray firstFreeSymArray;
    uint32 usedSymArray, allocatedSymArray;
    uint32 usedSymArraySym, allocatedSymArraySym, freeSymArraySym;
};
extern struct utRootType_ utRootData;

#define utHash() (utRootData.hash)
#define utUsedSymtab() utRootData.usedSymtab
#define utAllocatedSymtab() utRootData.allocatedSymtab
#define utSetUsedSymtab(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedSymtab, true), \
    utRootData.usedSymtab = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedSymtab, false))
#define utSetAllocatedSymtab(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedSymtab, true), \
    utRootData.allocatedSymtab = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedSymtab, false))
#define utUsedSymtabTable() utRootData.usedSymtabTable
#define utAllocatedSymtabTable() utRootData.allocatedSymtabTable
#define utFreeSymtabTable() utRootData.freeSymtabTable
#define utSetUsedSymtabTable(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedSymtabTable, true), \
    utRootData.usedSymtabTable = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedSymtabTable, false))
#define utSetAllocatedSymtabTable(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedSymtabTable, true), \
    utRootData.allocatedSymtabTable = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedSymtabTable, false))
#define utSetFreeSymtabTable(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeSymtabTable, true), \
    utRootData.freeSymtabTable = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeSymtabTable, false))
#define utUsedSym() utRootData.usedSym
#define utAllocatedSym() utRootData.allocatedSym
#define utSetUsedSym(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedSym, true), \
    utRootData.usedSym = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedSym, false))
#define utSetAllocatedSym(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedSym, true), \
    utRootData.allocatedSym = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedSym, false))
#define utUsedSymName() utRootData.usedSymName
#define utAllocatedSymName() utRootData.allocatedSymName
#define utFreeSymName() utRootData.freeSymName
#define utSetUsedSymName(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedSymName, true), \
    utRootData.usedSymName = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedSymName, false))
#define utSetAllocatedSymName(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedSymName, true), \
    utRootData.allocatedSymName = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedSymName, false))
#define utSetFreeSymName(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeSymName, true), \
    utRootData.freeSymName = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeSymName, false))
#define utFirstFreeDynarray() utRootData.firstFreeDynarray
#define utSetFirstFreeDynarray(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.firstFreeDynarray, true), \
    utRootData.firstFreeDynarray = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.firstFreeDynarray, false))
#define utUsedDynarray() utRootData.usedDynarray
#define utAllocatedDynarray() utRootData.allocatedDynarray
#define utSetUsedDynarray(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedDynarray, true), \
    utRootData.usedDynarray = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedDynarray, false))
#define utSetAllocatedDynarray(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedDynarray, true), \
    utRootData.allocatedDynarray = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedDynarray, false))
#define utUsedDynarrayValue() utRootData.usedDynarrayValue
#define utAllocatedDynarrayValue() utRootData.allocatedDynarrayValue
#define utFreeDynarrayValue() utRootData.freeDynarrayValue
#define utSetUsedDynarrayValue(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedDynarrayValue, true), \
    utRootData.usedDynarrayValue = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedDynarrayValue, false))
#define utSetAllocatedDynarrayValue(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedDynarrayValue, true), \
    utRootData.allocatedDynarrayValue = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedDynarrayValue, false))
#define utSetFreeDynarrayValue(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeDynarrayValue, true), \
    utRootData.freeDynarrayValue = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeDynarrayValue, false))
#define utFirstFreeSymArray() utRootData.firstFreeSymArray
#define utSetFirstFreeSymArray(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.firstFreeSymArray, true), \
    utRootData.firstFreeSymArray = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.firstFreeSymArray, false))
#define utUsedSymArray() utRootData.usedSymArray
#define utAllocatedSymArray() utRootData.allocatedSymArray
#define utSetUsedSymArray(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedSymArray, true), \
    utRootData.usedSymArray = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.usedSymArray, false))
#define utSetAllocatedSymArray(value) ( \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedSymArray, true), \
    utRootData.allocatedSymArray = (value), \
    (void)utRecordGlobal(utModuleID, 4, &utRootData.allocatedSymArray, false))
#define utUsedSymArraySym() utRootData.usedSymArraySym
#define utAllocatedSymArraySym() utRootData.allocatedSymArraySym
#define utFreeSymArraySym() utRootData.freeSymArraySym
#define utSetUsedSymArraySym(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedSymArraySym, true), \
    utRootData.usedSymArraySym = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.usedSymArraySym, false))
#define utSetAllocatedSymArraySym(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedSymArraySym, true), \
    utRootData.allocatedSymArraySym = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.allocatedSymArraySym, false))
#define utSetFreeSymArraySym(value) ( \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeSymArraySym, true), \
    utRootData.freeSymArraySym = (value), \
    (void)utRecordGlobal(utModuleID, sizeof(uint32), &utRootData.freeSymArraySym, false))

extern uint8 utModuleID;
void utDatabaseStart(void);
void utDatabaseStop(void);
#if defined __cplusplus
}
#endif

#endif
