typedef enum {
    SYM_GLOBAL,
    SYM_LOCAL,
    SYM_UNKNOWN
} SYM_CLASS_TYPE;

#define MAX_SUBSTRUCTURES 8
/* number of possible levels of structure definition for variable component
   referencing; e.g. a.b.c.d.  A decision needs to be made as to what the
   maximum depth of substructures is to be supported. (Are there limits made
   by compiler?) */

typedef struct {
    U16 nameCount;                        /* number of valid name strings */
    LPSTR symbolName[MAX_SUBSTRUCTURES];  /* name strings making up symbol */
} SYM_NAME_STRUCT;                        /* name */

typedef struct {
    LPSTR moduleName;
    LPSTR functionName;
    SYM_NAME_STRUCT *nameListPtr; /* ptr to struct of number of sub-names
                                     and a list of the parsed sub-names
                                     that make up the complete name. These
                                     names can include additional nested
                                     function names (e.g. Pascal) */
    SYM_TYPE_TYPE basicSymType;
    SYM_CLASS_TYPE symbolClass;   /* this is info that may be known by some
                                      callers */
} SYM_NAME_CONTEXT;


/*************************************
 ** ADD: CONSTANT, NUMERIC & STRING **
 *************************************/

/*--------------------------------------------------------------------------*/
/* SymAddConstNumericValue
**
/*
** Purpose:
**    Add a numeric constant to the open context.
**
** Input parameters:
**    constName: name of constant
**    constNumericValue: (binary) value of numeric constant
**
** Output parameters:
** 
** Error:  None
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddConstNumericValue(LPSTR constName,
                        U32 constNumericValue);


/*--------------------------------------------------------------------------*/
/* SymAddConstStringValue
**
** Purpose:
**    Add a string constant to the open context.
**
** Input parameters:
**    constName: name of constant
**    constStringValue: string value
**
** Output parameters:
**
** Error: None
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddConstStringValue(LPSTR constName,
                       LPSTR constStringValue);


/***********************************
 *** ADD: FUNCTION EXIT ADDRESS  ***
 ***********************************/

/*--------------------------------------------------------------------------*/
/* SymAddFuncExitAddr
**
** Purpose:
**    Add a exit address to the open function context
**
** Input parameter:
**    exitAddrValue: logical address of function exit point
**
** Output parameters:
**
** Error:
**    Reports error if there is no function open context.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddFuncExitAddr(OFFSET_ADDR_TYPE exitAddrValue);


/****************************
 ** (G) GENERALIZED STRUCT **
 ****************************/

/*--------------------------------------------------------------------------*/
/* SymAddTypeGeneralStruct
**
** Purpose:
**    Given a type index, add a (G) generalized data structured component.
**    SW must increment the local component count.
**
** Input parameters:
**    typeIndex: index of type
**    generalStruct: 4 elements making up the general component
**
** Output parameters:
**
**
** Error: Reports error if:
**    <typeIndex> doesn't point to an entry in the type table or to a
**      general structure type
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddTypeGeneralStruct(TYPE_INDEX    typeIndex,
                        TYPE_G_STRUCT *generalStruct);


/************************************
 ** (R) RANGE OF ANOTHER TYPE TYPE **
 ************************************/

/*--------------------------------------------------------------------------*/
/* SymAddTypeRange
**
** Purpose:
**    Given an index to a (R) range of another type, add the low, high bound
**    and sign.  This is actually a Pascal or Ada type; C doesn't support
**    subranging and checking a variable value.
**
** Input parameters:
**    typeIndex: index of type      
**    rangeStruct: structure holding information about range
**
** Output parameters:
**
** Error: Reports error if:
**    <typeIndex> doesn't point to a (R) range type
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddTypeRange(TYPE_INDEX    typeIndex,
                TYPE_R_STRUCT *rangeStruct);


/*********************************
 ** ADD: USER SYMBOL OPERATIONS **
 *********************************/

/*--------------------------------------------------------------------------*/
/* SymAddUserSymCreateLabel
**
** Purpose:
**    Create a user-defined program symbol label.
**    User symbols are considered global symbols.
**
** Input parameters:
**    userSymName: name of symbol to be added
**    userSymAddr:
**        address attached to label.  Base can be legit or an undefined value.
**
** Output parameter: None
**
** Error:
**    Reports error if symbol name already exists globally, either
**    as a user symbol or other (prevents user from mis-typing a symbol name
**    and having it created).  A separate command must be used to create
**    and access a user-defined symbol.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddUserSymCreateLabel(LPSTR userSymName,
                         ADDR  *userSymAddr);


/*--------------------------------------------------------------------------*/
/* SymAddUserSymCreateVar
**
** Purpose:
**    Create a user-defined program symbol variable and assign it an address.
**    Assign it a simple type that defines the type of variable it is.
**    User symbols are considered global symbols.
**
** Input parameters:
**    userSymName: name of symbol to be added
**    userSymAddr:
**        address attached to variable.  Base can be legit or an undefined
**        value.
**    simpleType: the type of the variable, for display purposes.
**
** Output parameter: None
**
** Error:
**    Reports error if symbol name already exists in the global table, either
**    as a user symbol or other (prevents user from mis-typing a symbol name
**    and having it created).  A separate command must be used to create
**    a user-defined symbol.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddUserSymCreateVar(LPSTR       userSymName,
                       ADDR        *userSymAddr,
                       SIMPLE_TYPE simpleType);

/*--------------------------------------------------------------------------*/
/* SymAddUserSymModifyLabel
**
** Purpose:
**    Modify an existing user-defined program symbol label.
**
** Input parameters:
**    userSymName: name of symbol to be added
**    userSymAddr:
**        address to change it to.
**
** Output parameter: None
**
** Error:
**    Reports error if user symbol name cannot be found.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddUserSymModifyLabel(LPSTR userSymName,
                         ADDR  *userSymAddr);


/*--------------------------------------------------------------------------*/
/* SymAddUserSymModifyVar
**
** Purpose:
**    Change the address of a user defined symbol variable
**
** Input parameters:
**    userSymName: name of symbol to be added
**    userSymAddr:
**        new address valiue
**
** Output parameter: None
**
** Error:
**    Reports error if user symbol name cannot be found.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddUserSymModifyVar(LPSTR userSymName,
                       ADDR  *userSymAddr);


/*--------------------------------------------------------------------------*/
/* SymAddUserSymRemove
**
** Purpose:
**    Remove a user-defined program symbol.
**
** Input parameters:
**    userSymName: name of symbol to be added
**
** Output parameter: None
**
** Error:
**    Reports error if symbol name not found.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddUserSymRemove(LPSTR userSymName);


/*--------------------------------------------------------------------------*/
/* SymAddUserSymRestore
**
** Purpose:
**    Load back user-defined symbols.  If a user-symbol name
**    already exist, the value of the symbol in the file will over-write
**    old (existing) symbol value.
**
** Input parameter: fileDescriptor - descriptor to file
**
** Error: standard file read errors; e.g. file not found, directory not found
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddUserSymRestore(FILE fileDescriptor);


/*--------------------------------------------------------------------------*/
/* SymAddUserSymSave
**
** Purpose:
**    Save the user-defined program symbols to a file.  The file format is
**    left to the implementor.  (No loaded symbols are savable).
**
** Input parameter: fileDescriptor - descriptor to file
**
** Error: standard file write errors; e.g. disk full, file entry invalid, ...
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymAddUserSymSave(FILE fileDescriptor);


/*********************
 ** ERROR REPORTING **
 *********************/

/*--------------------------------------------------------------------------*/
/* SymErrorCodeMap
**
** Purpose:
**    Given an error code originating with this component, return a designator
**    of the correct string table and index to obtain the corresponding error
**    message text string.
**
** Input parameter:
**    errorCode: error ID of failed operation
**
** Output parameter:
**    stringTableId: error message index within component's string table
**    stringTableIndex: allows access to component's string table
**
** Error:
**    Reports error if errorCode doesn't exist in the table
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymErrorCodeMap(RETCODE errorCode,
                U32     *stringTableId,
                U32     *stringTableIndex);


/***************************
 ** CONSTANT GET ROUTINES **
 ***************************/

/*--------------------------------------------------------------------------*/
/* SymGetConstType
**
** Purpose:
**    Given a descriptor to a constant, get the constant's type.  This routine
**    must be called before getting the constant value.
**
** Input parameters:
**    inputSymbol:
**        descriptor to constant
**
** Output parameters:
**    constType: enumeration of constant type
**
** Error:
**    Reports error if <inputSymbol> doesn't point to a constant
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetConstType(SYM_DESCRIPTOR inputSymbol,
                CONSTANT_TYPE  *constType);


/*--------------------------------------------------------------------------*/
/* SymGetConstNumericValue
**
** Purpose:
**    Given a descriptor to a numeric constant, get the numeric value
**
** Input parameters:
**    inputSymbol:
**        descriptor to constant
**
** Output parameters:
**    constNumericValue: value of numeric constant (binary)
**
** Error:
**    Reports error if <inputSymbol> doesn't point to a constant
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetConstNumericValue(SYM_DESCRIPTOR inputSymbol,
                        U32            *constNumericValue);


/*--------------------------------------------------------------------------*/
/* SymGetConstStringValue
**
** Purpose:
**    Given a descriptor to a string constant, get the string.
**
** Input parameters:
**    inputSymbol:
**        descriptor to constant
**
** Output parameters:
**    constName: constant's string value
**
** Error:
**    Reports error if <inputSymbol> doesn't point to a constant
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetConstStringValue(SYM_DESCRIPTOR inputSymbol,
                       LPSTR          constName);


/*--------------------------------------------------------------------------*/
/* SymGetFuncExitAddr
**
** Purpose:
**    Given a descriptor to one component in a function's exit address list,
**    return the exit address value and descriptor to next item.
**
** Input parameter:
**    exitSymbol: descriptor to item in function exit list
**
** Output parameters:
**    exitAddrValue: composite address value of exit address
**    nextExitSymbol:
**        descriptor to next exit symbol in linked list; NULL if at end of
**        list
**
** Error:
**    Reports error if <inputSymbol> does not point to a function exit address
**    list (defensive programming).
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetFuncExitAddr(SYM_DESCRIPTOR exitSymbol,
                   DESCRIPTOR     *exitAddrValue,
                   SYM_DESCRIPTOR *nextExitSymbol);


/*--------------------------------------------------------------------------*/
/* SymGetSymbolByName
**
** Purpose:
**    Given a symbol name, retrieve a symbol's basic type information, address
**    range (if any) and its descriptor.  The descriptor is used for
**    subsequent access to the symbol for additional information (if needed)
**    and traversal of types, etc.  For example, following a
**    SymGetSymbolByName call might be SymGetTypeXxx (where Xxx is the symbol
**    type), SymGetSymbolHeadList, SymGetSymbolChild, or others.
**
** Input parameters:
**    symNameContext:
**        pointer to information defining the symbol to look up (allocated by
**        caller).  Included are:
**            <moduleName>, <functionName>, pointer to
**            a list of names (and how many) that make up the components of
**            of symbol, <basicSymType> (set to SYM_UNDEFINED if not known),
**            and <symbolClass> (set to SYM_UNKNOWN if not known).
**        Some of the fields can be empty; i.e string pointers are NULL
**        if there is no information available or if it is not appropriate.
**        The lookup algorithm is dependent on what information is present.
**        A non-exhaustive list of conditions:
**           moduleName empty -> look up name in global list
**           functionName empty -> look up within module context
**           moduleName known -> with no function, it is
**               possible to sequentially scan all functions, blocks,
**               local vars for a name match if it not found in the global
**               symbol list.  This could be slow, however.
**
**        The SYM_NAME_STRUCT containing an array of string pointers and a
**        count of how many are valid in the array.  In the simple case, there
**        is only one symbol name requested.  However, a component of a
**        structure is accessed by the . operator.  An example is: h.z.q.
**        Each field name is passed via this array.  The parsing of the names
**        is done by a language-cognizant program such as a source evaluator.
**
** Output parameters:
**    symNameContext:
**        if the symbol is found, the input structure will be filled wherever
**        information was not given.  This includes the name fields,
**        <basicSymType>, and <symbolClass>.
**    addrRange:
**        the start and end address of the symbol. End address=0 ==> a label
**        or user-defined symbol
**    outputSymbol:
**        descriptor (an opaque structure) treated as a handle to the
**        area of the symbol table that matched the input; it can
**        be used in subsequent call to get detailed information
**
** Error:
**    reports symbol not found.  There are many cases where a symbol will
**    not be found:
**       -  user typed a name incorrectly
**       -  library symbols not loaded (or supplied by compiler)
**       -  requested symbol not a generated symbol; e.g. macro names,
**            constants (sometimes), enumeration names, structure elements
**       -  not enough context to look up; e.g. local function without
**            module name, user did not select entire name of symbol
**            reference
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetSymbolByName(SYM_NAME_CONTEXT   *symNameContext,
                   DESCRIPTOR         *addrRange,
                   SYM_DESCRIPTOR FAR *outputSymbol);


/*--------------------------------------------------------------------------*/
/* SymGetSymbolStruct
**
** Purpose:
**    Given a symbol "path" for a structure contained in <symNameStruct>
**    (e.g. a.b.c), return its address start and end.
**    Assumes that <inputSymbol> is the variable with the structure to be
**    looked up.
**
** Input parameters:
**    inputSymbol: pointer to variable
**    symNameStruct:
**        sequence of strings parsed from an x.y.z format.  Defines the nested
**        search path for the structure.
**
** Output parameters:
**    addrRange:
**        the start and end address of the symbol final structure.
**
** Error:
**    reports error if:
**        <inputSymbol> does not point to variable.
**        structure lookup not successful
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetSymbolStruct(SYM_DESCRIPTOR  inputSymbol,
                   SYM_NAME_STRUCT *symNameStruct,
                   DESCRIPTOR      *addrRange);

       
/*********************************
 ** GET: (G) GENERALIZED STRUCT **
 *********************************/

/*--------------------------------------------------------------------------*/
/* SymGetTypeGeneralStruct
**
** Purpose:
**    Look up the name of a structure component given an index to the general
**    structure type.  Return the component's information and the component
**    index (where 0 is the first index).
**
** Input parameters:
**    typeIndex: index of type
**    structName: name of structure component to be looked up
**
** Output parameters:
**    generalStruct: 4 elements making up the general component
**    componentIndex: component index, where first is 0
**    noMatch: FALSE if name didn't match any stored name
**
**
** Error: Reports error if:
**    <typeIndex> doesn't point to an entry in the type table or to a
**      general structure type
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetTypeGeneralStruct(TYPE_INDEX    typeIndex,
                        LPSTR         structName,
                        TYPE_G_STRUCT *generalStruct,
                        U16           *componentIndex,
                        BOOLEAN       *noMatch);


/*--------------------------------------------------------------------------*/
/* SymGetTypeGeneralStructNth
**
** Purpose:
**    Given a general structure (G), retrieve nth component
**
** Input parameters:
**    typeIndex: index of type      
**    n: component number where 0 is first
**
** Output parameters:
**    generalStruct: 4 elements of nth general component
**
** Error: Reports error if:
**    <typeIndex> doesn't point to an entry in the type table or to an
**      unknown type
**    Value of n beyond the number of components
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetTypeGeneralStructNth(TYPE_INDEX    typeIndex,
                           U16           n,
                           TYPE_G_STRUCT *generalStruct);


/*****************************************
 ** GET: (R) RANGE OF ANOTHER TYPE TYPE **
 *****************************************/

/*--------------------------------------------------------------------------*/
/* SymGetTypeRange
**
** Purpose:
**    Given an index to a (R) range of another type, retrieve its information.
**    This is actually a Pascal or Ada type; C doesn't support subranging and
**    checking a variable value.
**
** Input parameters:
**    typeIndex: index of type      
**
** Output parameters:
**    rangeStruct: structure holding information about range
**
** Error: Reports error if:
**    <typeIndex> doesn't point to a (R) range type
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymGetTypeRange(TYPE_INDEX    typeIndex,       
                TYPE_R_STRUCT *rangeStruct);


/***********
 ** HINTS **
 ***********/

/*--------------------------------------------------------------------------*/
/* SymHintAdd
**
** Purpose:
**    Adds <addrRange> of type <addrClass> to the present HINTS
**    list.  This can be used to stretch an existing range or create a
**    new contiguous one. To reduce an address range, use SymRemoveHint.
**
** Input parameters:
**    addrClass: enum of memory classes; illegal defines memory that is
**                 mapped as illegal to access.
**    addrRange: start-end addresses
**
** Error:
**    There cannot be any overlap of addresses of different classes;
**    i.e. there cannot be an address that maps to more than one class.
**    An error is reported if adding an address range will cause an
**    overlap, and the function aborts (no addresses are added).
**    The caller must remove the address range(s) that overlap before the
**    new one can be added.  
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymHintAdd(MEM_ADDR_CLASS         addrClass,
           OFFSET_ADDR_RANGE_TYPE *addrRange);


/*--------------------------------------------------------------------------*/
/* SymHintGetClass
**
** Purpose: Given a physical address, return its address class
**
** Input parameters:
**    physAddr: address to be looked up for its class.  There will always be
**       one and only one match.  The database defines ADR_UNDEFINED as any
**       address not a memory of defined by the SymHintAdd function.
**
** Output parameters:
**    addrClass: which class matched the address.
**
** Error: None
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymHintGetClass(U32            physAddr,
                MEM_ADDR_CLASS addrClass);


/*--------------------------------------------------------------------------*/
/* SymHintGetList
**
** Purpose: Get a list of all addr ranges defined for that class
**  
** Input parameters:
**    addrClass: enum of memory class
**
** Output parameters:
**    rangeList: (allocated memory) list of address ranges that match
**               <addrClass>.  rangeList.itemCount can equal 0.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymHintGetList(MEM_ADDR_CLASS  addrClass,
               RANGE_LIST_TYPE *rangeList);


/*--------------------------------------------------------------------------*/
/* SymHintRemove
**
** Purpose:
**   Removes <addrRange> of class <addrClass> from the present HINTS list.
**
** Input parameters:
**      addrClass:
**          enum of memory classes; illegal defines memory that is mapped as
**          illegal to access.
**      addrRange: start-end addresses
**
** Error: report error if no address is included in the address range
**        specified for that <addrClass> or there are no ranges for that
**        type.
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymHintRemove(MEM_ADDR_CLASS         addrClass,
              OFFSET_ADDR_RANGE_TYPE *addrRange);


/********************************
 ** HIGH LEVEL SYMBOL ROUTINES **
 ********************************/
/* These routines provide a high level access to the symbol table.  Some
   are source language dependent and make calls to the language server. */

/*--------------------------------------------------------------------------*/
/* SymHLGetSymbolByName
**
** Purpose:
**    Retrieve a symbol's basic type information, address range (if any)
**    and its descriptor given a single string that includes the symbol "path"
**    and its name.  The string can include language specific operators such
**    as "." or "->".  
**           Example: symPresenter:displayName:localVar1.structComponent
**    SymHLGetSymbolByName will call the language parser, break up
**    the path into component strings, then call the correct functions to
**    get the information.
**
** Input parameters:
**    symPathAndName:
**        string containing "path" and symbol name to look up
**
** Output parameters: identical to SymGetSymbolByName
**
** Error: identical to SymGetSymbolByName
*/
/*--------------------------------------------------------------------------*/
RETCODE EXPORT
SymHLGetSymbolByName(LPSTR          symPathAndName,
                     DESCRIPTOR     *addrRange,
                     SYM_DESCRIPTOR *outputSymbol);


/*************************
 ** CHANGE NOTIFICATION **
 *************************/


