/*
//
// varstore.h
//
// Variable store functions (implemented with a splay tree)
//
// Copyright (c) 1995-96 Jim Nelson.
// Copyright (c) 2002 Jochen Hoenicke.
// Released under Artistic License.
//
*/

#ifndef VARSTORE_H
#define VARSTORE_H

/*
// maximum length for the variable name and the variables value
*/
#define MAX_VARNAME_LEN         (256)
#define MAX_VARVALUE_LEN        (1024)

/*
// variable destructor callback ... set to NULL if no callback required when
// destroyed
*/
typedef void (*VAR_DESTRUCTOR)(const char *name, void *value,
    uint type, uint flag, void *param);

/*
// a variable held in the store
*/
typedef struct tagVARIABLE
{
    struct tagVARIABLE  *left;
    struct tagVARIABLE  *right;
    char                *name;
    void                *value;
    uint                type;
    uint                flag;
    void                *param;
    VAR_DESTRUCTOR      destructor;
} VARIABLE;

/*
// variable store structure
//
// parent and child refers to scope ... when traversing the chain for a
// particular macro, always look to parent scope if not found in current
*/
typedef struct tagVARSTORE
{
    struct tagVARSTORE      *parent;
    struct tagVARSTORE      *child;
    VARIABLE                *root;
    BOOL                    isGlobal;
} VARSTORE;

/*
// statistics for performance measurement
*/
#if DEBUG
extern uint variableLookups;
extern uint variableStringCompares;
extern uint variableRotations;
#endif

/*
// GetVariableType() will return this value if the variable is not found
*/
#define VAR_TYPE_UNKNOWN        ((uint) -1)

/*
// GetVariableFlag() will return this value if the variable is not found
*/
#define VAR_FLAG_UNKNOWN        ((uint) -1)

/*
// initialize a VARSTORE
*/
BOOL InitializeVariableStore(VARSTORE *varstore);

/*
// destroys a variable store and ALL child scope stores
*/
void DestroyVariableStore(VARSTORE *varstore);

/*
// Push, pop, and get current varstore context ... note that for pop and
// get, simply passing a variable store somewhere in the context will get
// or pop the topmost one, and for push it will find the topmost context
// before adding the new context
*/
void PushVariableStoreContext(VARSTORE *parent, VARSTORE *varstore);
VARSTORE *PopVariableStoreContext(VARSTORE *varstore);

/*
// add a variable to a store ... the store will keep its
// own copy of the variable kept, no need to maintain name and
// value once added
//
// Set destructor to NULL if no additional processing required before
// destroying the variable.  Otherwise, pass a pointer to a function.
//
// Returns FALSE if unable to add variable into the store
*/
BOOL StoreVariable(VARSTORE *varstore, const char *name, void *value,
    uint type, uint flag, void *param, VAR_DESTRUCTOR destructor);

/*
// Returns TRUE if variable found in store (case-insensitive)
*/
BOOL VariableExists(VARSTORE *varstore, const char *name);

/*
// A variable's destructor will be called from the context of these
// functions
*/
BOOL RemoveVariable(VARSTORE *varstore, const char *name);

/*
// Get variable information ... returns NULL for GetVariableValue(),
// VAR_TYPE_UNKNOWN for GetVariableType(), and VAR_FLAG_UNKNOWN for
// GetVariableFlag() if variable not in list
//
// GetVariableParam() returns NULL if not found ... since this is a valid
// return value, caller should really use VariableExists() first!
*/
void *GetVariableValue(VARSTORE *varstore, const char *name);
BOOL UpdateVariableValue(VARSTORE *varstore, const char *name, void* value);
uint GetVariableType(VARSTORE *varstore, const char *name);
uint GetVariableFlag(VARSTORE *varstore, const char *name);
void *GetVariableParam(VARSTORE *varstore, const char *name);

#endif

