#include "sysdep.h"
#include "HTUtils.h"
#include "HTString.h"
#include "CSParse.h"
#include "CSMR.h"
#include "CSMRSt.h"

#define GetCSMachRead(A) ((A)->target.pCSMachRead)
#define SETNEXTSTATE(target, subState) \
  pCSParse->pTargetObject = target; \
  pCSParse->currentSubState = subState;


struct CSMachRead_s {
    CSMachReadData_t * pCSMachReadData;

    MachRead_category_t * pCurrentMachRead_category;
    MachRead_enum_t * pCurrentMachRead_enum;
    BOOL inDefault;

    MachReadTargetCallback_t * pMachReadTargetCallback;
    MRErrorHandler_t * pMRErrorHandler;
};

PRIVATE TargetObject_t MachRead_targetObject;
PRIVATE TargetObject_t Version_targetObject;
PRIVATE TargetObject_t System_targetObject;
PRIVATE TargetObject_t Service_targetObject;
PRIVATE TargetObject_t Icon_targetObject;
PRIVATE TargetObject_t Name_targetObject;
PRIVATE TargetObject_t Description_targetObject;
PRIVATE TargetObject_t Default_targetObject;
PRIVATE TargetObject_t Min_targetObject;
PRIVATE TargetObject_t Max_targetObject;
PRIVATE TargetObject_t Multi_targetObject;
PRIVATE TargetObject_t Unord_targetObject;
PRIVATE TargetObject_t Integer_targetObject;
PRIVATE TargetObject_t Labeled_targetObject;
PRIVATE TargetObject_t Category_targetObject;
PRIVATE TargetObject_t Transmit_as_targetObject;
PRIVATE TargetObject_t Enum_targetObject;
PRIVATE TargetObject_t Value_targetObject;
PRIVATE Prep_t postValueState;
PRIVATE Prep_t Category_next;
PRIVATE Prep_t Multi_setTrue;
PRIVATE Prep_t Unord_setTrue;
PRIVATE Prep_t Integer_setTrue;
PRIVATE Prep_t Labeled_setTrue;
PRIVATE Check_t Version_get;
PRIVATE Check_t System_get;
PRIVATE Check_t Service_get;
PRIVATE Check_t Icon_get;
PRIVATE Check_t Name_get;
PRIVATE Check_t Description_get;
PRIVATE Check_t Min_get;
PRIVATE Check_t Max_get;
PRIVATE Check_t Multi_get;
PRIVATE Check_t Unord_get;
PRIVATE Check_t Integer_get;
PRIVATE Check_t Labeled_get;
PRIVATE Check_t Transmit_as_get;
PRIVATE Check_t Value_get;
PRIVATE Open_t MachRead_open;
PRIVATE Open_t Category_open;
PRIVATE Open_t Default_open;
PRIVATE Open_t Enum_open;
PRIVATE Close_t MachRead_close;
PRIVATE Close_t Category_close;
PRIVATE Close_t Default_close;
PRIVATE Close_t Enum_close;
PRIVATE Destroy_t MachRead_destroy;
PRIVATE Destroy_t Category_destroy;
PRIVATE Destroy_t Default_destroy;
PRIVATE Destroy_t Enum_destroy;

PRIVATE TargetChangeCallback_t targetChangeCallback;
PRIVATE ParseErrorHandler_t parseErrorHandler;

/* CSParse_doc states */
/* M A C H I N E   R E A D A B L E   P A R S E R   S T A T E S */
/* This contains all the states in the BNF for PICS service descriptions.
 * See User/Parsing.html for details.
 */
PRIVATE StateToken_t MachRead_stateTokens[] = { 
    /* A: 1st we need a version
       B: then a system
       C: and a service
       D: an open paren
       E: could be icondef - category
       F: back from category so open or close paren
       G: open paren so it is a category */
     {           "enter", SubState_N,    Punct_ALL, 0,             0, 0, 0, &MachRead_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"need version set", SubState_A, Punct_LPAREN, 0,             0, 0, 0, &Version_targetObject, SubState_N, 0, 0},
     { "need system set", SubState_B, Punct_LPAREN, 0,             0, 0, 0, &System_targetObject, SubState_N, 0, 0},
     {"need service set", SubState_C, Punct_LPAREN, 0,             0, 0, 0, &Service_targetObject, SubState_N, 0, 0},
     {"need options set", SubState_D, Punct_LPAREN, 0,             0, 0, 0, &MachRead_targetObject, SubState_E, 0, 0},
     {            "icon", SubState_E,  Punct_WHITE, 0,        "icon", 0, 0, &Icon_targetObject, SubState_N, 0, 0},
     {            "name", SubState_E,  Punct_WHITE, 0,        "name", 0, 0, &Name_targetObject, SubState_N, 0, 0},
     {     "description", SubState_E,  Punct_WHITE, 0, "description", 0, 0, &Description_targetObject, SubState_N, 0, 0},
     {         "default", SubState_E, Punct_LPAREN, 0,     "default", 0, 0, &Default_targetObject, SubState_N, 0, 0},
     {        "category", SubState_E, Punct_LPAREN, 0,    "category", 0, 0, &Category_targetObject, SubState_N, 0, 0},
     {   "open category", SubState_F, Punct_LPAREN, 0,             0, 0, 0, &MachRead_targetObject, SubState_G, 0, 0},
     {             "end", SubState_F, Punct_RPAREN, 0,             0, 0, 0, &MachRead_targetObject, SubState_N, Command_CLOSE, 0},
     {        "category", SubState_G, Punct_LPAREN, 0,    "category", 0, 0, &Category_targetObject, SubState_N, 0, 0}
    };
PRIVATE TargetObject_t MachRead_targetObject = {"MachRead", &MachRead_open, &MachRead_close, &MachRead_destroy, MachRead_stateTokens, raysize(MachRead_stateTokens), CSMRTC_MACHREAD};

PRIVATE StateToken_t Version_stateTokens[] = { 
    /* A: fresh Version
       B: read value */
     {"enter", SubState_N,    Punct_ALL, 0,              0, 0, 0, &Version_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     { "text", SubState_A,  Punct_WHITE, 0, "PICS-version", 0, 0, &Version_targetObject, SubState_B, 0, 0},
     {"value", SubState_B, Punct_RPAREN, &Version_get,   0, 0, 0, &MachRead_targetObject, SubState_B, Command_CLOSE, 0}
    };
PRIVATE TargetObject_t Version_targetObject = {"Version", 0, 0, 0, Version_stateTokens, raysize(Version_stateTokens), CSMRTC_VERSION};

PRIVATE StateToken_t System_stateTokens[] = { 
    /* A: fresh System
       B: read value */
     {"enter", SubState_N,    Punct_ALL, 0,               0, 0, 0, &System_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     { "text", SubState_A,  Punct_WHITE, 0, "rating-system", 0, 0, &System_targetObject, SubState_B, 0, 0},
     {"value", SubState_B, Punct_RPAREN, &System_get,     0, 0, 0, &MachRead_targetObject, SubState_C, Command_CLOSE, 0}
    };
PRIVATE TargetObject_t System_targetObject = {"System", 0, 0, 0, System_stateTokens, raysize(System_stateTokens), CSMRTC_SYSTEM};

PRIVATE StateToken_t Service_stateTokens[] = { 
    /* A: fresh Service
       B: read value */
     {"enter", SubState_N,    Punct_ALL, 0,                0, 0, 0, &Service_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     { "text", SubState_A,  Punct_WHITE, 0, "rating-service", 0, 0, &Service_targetObject, SubState_B, 0, 0},
     {"value", SubState_B, Punct_RPAREN, &Service_get,     0, 0, 0, &MachRead_targetObject, SubState_D, Command_CLOSE, 0}
    };
PRIVATE TargetObject_t Service_targetObject = {"Service", 0, 0, 0, Service_stateTokens, raysize(Service_stateTokens), CSMRTC_SERVICE};

PRIVATE StateToken_t Icon_stateTokens[] = { 
    /* A: read value */
     {"enter", SubState_N,    Punct_ALL, 0,          0, 0, 0, &Icon_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"value", SubState_A, Punct_RPAREN, &Icon_get, 0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Icon_targetObject = {"Icon", 0, 0, 0, Icon_stateTokens, raysize(Icon_stateTokens), CSMRTC_ICON};

PRIVATE StateToken_t Name_stateTokens[] = { 
    /* A: read value */
     {"enter", SubState_N,    Punct_ALL, 0,          0, 0, 0, &Name_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"value", SubState_A, Punct_RPAREN, &Name_get, 0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Name_targetObject = {"Name", 0, 0, 0, Name_stateTokens, raysize(Name_stateTokens), CSMSRC_NAME};

PRIVATE StateToken_t Value_stateTokens[] = { 
    /* A: read value */
     {"enter", SubState_N,    Punct_ALL, 0,          0, 0, 0, &Value_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"value", SubState_A, Punct_RPAREN, &Value_get, 0, 0, 0,  &Enum_targetObject, SubState_G, Command_CLOSE, 0}
    };
PRIVATE TargetObject_t Value_targetObject = {"Name", 0, 0, 0, Value_stateTokens, raysize(Value_stateTokens), CSMSRC_VALUE};

PRIVATE StateToken_t Description_stateTokens[] = { 
    /* A: read value */
     {"enter", SubState_N,    Punct_ALL, 0,          0, 0, 0, &Description_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"value", SubState_A, Punct_RPAREN, &Description_get, 0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Description_targetObject = {"Description", 0, 0, 0, Description_stateTokens, raysize(Description_stateTokens), CSMSRC_DESC};

PRIVATE StateToken_t Default_stateTokens[] = { 
    /* A: need an open
	   B: need option */
     {  "enter", SubState_N, Punct_ALL, 0,          0, 0, 0, &Default_targetObject, SubState_B, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {   "open", SubState_A,             Punct_LPAREN, 0,            0, 0, 0, &Default_targetObject, SubState_B, 0, 0},
     {  "close", SubState_A,             Punct_RPAREN, 0,            0, 0, 0, &MachRead_targetObject, SubState_D, Command_CLOSE, 0},
     {    "min", SubState_B,              Punct_WHITE, 0,        "min", 0, 0, &Min_targetObject, SubState_N, 0, 0},
     {    "max", SubState_B,              Punct_WHITE, 0,        "max", 0, 0, &Max_targetObject, SubState_N, 0, 0},
     {  "multi", SubState_B, Punct_WHITE|Punct_RPAREN, 0, "multivalue", 0, 0, &Multi_targetObject, SubState_N, Command_CHAIN, 0},
     {  "unord", SubState_B, Punct_WHITE|Punct_RPAREN, 0,  "unordered", 0, 0, &Unord_targetObject, SubState_N, Command_CHAIN, 0},
     {"integer", SubState_B, Punct_WHITE|Punct_RPAREN, 0,    "integer", 0, 0, &Integer_targetObject, SubState_N, Command_CHAIN, 0},
     {"labeled", SubState_B, Punct_WHITE|Punct_RPAREN, 0, "label-only", 0, 0, &Labeled_targetObject, SubState_N, Command_CHAIN, 0},
    };
PRIVATE TargetObject_t Default_targetObject = {"Default", &Default_open, &Default_close, &Default_destroy, Default_stateTokens, raysize(Default_stateTokens), CSMRTC_DEF};

PRIVATE StateToken_t Min_stateTokens[] = { 
    /* A: read value */
     {"enter", SubState_N,    Punct_ALL,        0, 0, 0, 0, &Min_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"value", SubState_A, Punct_RPAREN, &Min_get, 0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Min_targetObject = {"Min", 0, 0, 0, Min_stateTokens, raysize(Min_stateTokens), CSMRTC_MIN};

PRIVATE StateToken_t Max_stateTokens[] = { 
    /* A: read value */
     {"enter", SubState_N,    Punct_ALL,        0, 0, 0, 0, &Max_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"value", SubState_A, Punct_RPAREN, &Max_get, 0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Max_targetObject = {"Max", 0, 0, 0, Max_stateTokens, raysize(Max_stateTokens), CSMRTC_MAX};

PRIVATE StateToken_t Multi_stateTokens[] = { 
    /* A: chained text with optional close paren
	   B: value */
     { "enter", SubState_N,    Punct_ALL, 0,            0, 0, 0, &Multi_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"binary", SubState_A,  Punct_WHITE, 0, "multivalue", 0, 0, &Multi_targetObject, SubState_B, 0, 0},
     { "unary", SubState_A, Punct_RPAREN, 0, "multivalue", 0, 0, 0, SubState_X, Command_CLOSE, &Multi_setTrue},
     { "value", SubState_B, Punct_RPAREN, &Multi_get,   0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Multi_targetObject = {"Multi", 0, 0, 0, Multi_stateTokens, raysize(Multi_stateTokens), CSMRTC_MULTI};

PRIVATE StateToken_t Unord_stateTokens[] = { 
    /* A: chained text with optional close paren
	   B: value */
     { "enter", SubState_N,    Punct_ALL, 0,           0, 0, 0, &Unord_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"binary", SubState_A,  Punct_WHITE, 0, "unordered", 0, 0, &Unord_targetObject, SubState_B, 0, 0},
     { "unary", SubState_A, Punct_RPAREN, 0, "unordered", 0, 0, 0, SubState_X, Command_CLOSE, &Unord_setTrue},
     { "value", SubState_B, Punct_RPAREN, &Unord_get,  0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Unord_targetObject = {"Unord", 0, 0, 0, Unord_stateTokens, raysize(Unord_stateTokens), CSMRTC_UNORD};

PRIVATE StateToken_t Integer_stateTokens[] = { 
    /* A: chained text with optional close paren
	   B: value */
     { "enter", SubState_N,    Punct_ALL,    0,       0, 0, 0, &Integer_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"binary", SubState_A,  Punct_WHITE,    0, "integer", 0, 0, &Integer_targetObject, SubState_B, 0, 0},
     { "unary", SubState_A, Punct_RPAREN,    0, "integer", 0, 0, 0, SubState_X, Command_CLOSE, &Integer_setTrue},
     { "value", SubState_B, Punct_RPAREN, &Integer_get, 0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Integer_targetObject = {"Integer", 0, 0, 0, Integer_stateTokens, raysize(Integer_stateTokens), CSMRTC_INT};

PRIVATE StateToken_t Labeled_stateTokens[] = { 
    /* A: chained text with optional close paren
	   B: value */
     { "enter", SubState_N,    Punct_ALL,    0,       0, 0, 0, &Labeled_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"binary", SubState_A,  Punct_WHITE, 0, "label-only", 0, 0, &Labeled_targetObject, SubState_B, 0, 0},
     { "unary", SubState_A, Punct_RPAREN, 0, "label-only", 0, 0, 0, SubState_X, Command_CLOSE, &Labeled_setTrue},
     { "value", SubState_B, Punct_RPAREN, &Labeled_get, 0, 0, 0, 0, SubState_X, Command_CLOSE, &postValueState}
    };
PRIVATE TargetObject_t Labeled_targetObject = {"Labeled", 0, 0, 0, Labeled_stateTokens, raysize(Labeled_stateTokens), CSMRTC_LABL};

PRIVATE StateToken_t Category_stateTokens[] = { 
    /* A: 1st we need a transmit-as
       B: an open paren
       C: could be icondef - enum, category
       D: back from enum so need open or close
       E: enum or category
       F: back from category so need open or close
       G: category */
     {           "enter", SubState_N,       Punct_ALL, 0,       0, 0, 0, &Transmit_as_targetObject, SubState_N, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {"need options set", SubState_B,    Punct_LPAREN, 0,             0, 0, 0, &Category_targetObject, SubState_C, 0, 0},
     {             "end", SubState_B,    Punct_RPAREN, 0,             0, 0, 0, 0, SubState_X, Command_CLOSE, &Category_next},
     {            "icon", SubState_C,     Punct_WHITE, 0,        "icon", 0, 0, &Icon_targetObject, SubState_N, 0, 0},
     {            "name", SubState_C,     Punct_WHITE, 0,        "name", 0, 0, &Name_targetObject, SubState_N, 0, 0},
     {     "description", SubState_C,     Punct_WHITE, 0, "description", 0, 0, &Description_targetObject, SubState_N, 0, 0},
     {             "min", SubState_C,     Punct_WHITE, 0,         "min", 0, 0, &Min_targetObject, SubState_N, 0, 0},
     {             "max", SubState_C,     Punct_WHITE, 0,         "max", 0, 0, &Max_targetObject, SubState_N, 0, 0},
     {  "multi", SubState_C, Punct_WHITE|Punct_RPAREN, 0,  "multivalue", 0, 0, &Multi_targetObject, SubState_N, Command_CHAIN, 0},
     {  "unord", SubState_C, Punct_WHITE|Punct_RPAREN, 0,   "unordered", 0, 0, &Unord_targetObject, SubState_N, Command_CHAIN, 0},
     {"integer", SubState_C, Punct_WHITE|Punct_RPAREN, 0,     "integer", 0, 0, &Integer_targetObject, SubState_N, Command_CHAIN, 0},
     {"labeled", SubState_C, Punct_WHITE|Punct_RPAREN, 0,  "label-only", 0, 0, &Labeled_targetObject, SubState_N, Command_CHAIN, 0},
     {            "enum", SubState_C,    Punct_LPAREN, 0,       "label", 0, 0, &Enum_targetObject, SubState_N, 0, 0},
     {        "category", SubState_C,    Punct_LPAREN, 0,    "category", 0, 0, &Category_targetObject, SubState_N, 0, 0},
     {"open enum or cat", SubState_D,    Punct_LPAREN, 0,             0, 0, 0, &Category_targetObject, SubState_E, 0, 0},
     {             "end", SubState_D,    Punct_RPAREN, 0,             0, 0, 0, 0, SubState_X, Command_CLOSE, &Category_next},
     {            "enum", SubState_E,    Punct_LPAREN, 0,       "label", 0, 0, &Enum_targetObject, SubState_N, 0, 0},
     {        "category", SubState_E,    Punct_LPAREN, 0,    "category", 0, 0, &Category_targetObject, SubState_N, 0, 0},
     {             "end", SubState_E,    Punct_RPAREN, 0,             0, 0, 0, 0, SubState_X, Command_CLOSE, &Category_next},
     {     "open or cat", SubState_F,    Punct_LPAREN, 0,             0, 0, 0, &Category_targetObject, SubState_G, 0, 0},
     {             "end", SubState_F,    Punct_RPAREN, 0,             0, 0, 0, 0, SubState_X, Command_CLOSE, &Category_next},
     {        "category", SubState_G,    Punct_LPAREN, 0,    "category", 0, 0, &Category_targetObject, SubState_N, 0, 0},

     {     "to MachRead", SubState_H,       Punct_ALL, 0,             0, 0, 0, &MachRead_targetObject, SubState_F, Command_CHAIN, 0}
    };
PRIVATE TargetObject_t Category_targetObject = {"Category", &Category_open, &Category_close, &Category_destroy, Category_stateTokens, raysize(Category_stateTokens), CSMRTC_CAT};

PRIVATE StateToken_t Transmit_as_stateTokens[] = { 
    /* A: fresh Service
       B: read value */
     {"enter", SubState_N,    Punct_ALL,    0,             0, 0, 0, &Transmit_as_targetObject, SubState_A, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     { "text", SubState_A,  Punct_WHITE,    0, "transmit-as", 0, 0, &Transmit_as_targetObject, SubState_B, 0, 0},
     {"value", SubState_B, Punct_RPAREN, &Transmit_as_get, 0, 0, 0, &Category_targetObject, SubState_B, Command_CLOSE, 0}
    };
PRIVATE TargetObject_t Transmit_as_targetObject = {"Transmit_as", 0, 0, 0, Transmit_as_stateTokens, raysize(Transmit_as_stateTokens), CSMRTC_TRANS};

PRIVATE StateToken_t Enum_stateTokens[] = { 
    /* A: 'label'(
	   B: 'name' -> C
	   C: (
	   D: 'description' -> E
	   D: 'value' -> G
	   E: (
	   F: 'value' -> G
	   G: ( - expect an icon
	   G: ) close
	   H: 'icon' -> I
	   I: close */
     {      "enter", SubState_N,    Punct_ALL, 0,             0, 0, 0, &Enum_targetObject, SubState_B, Command_MATCHANY|Command_OPEN|Command_CHAIN, 0},
     {       "name", SubState_B,  Punct_WHITE, 0,        "name", 0, 0, &Name_targetObject, SubState_N, 0, 0},
     {       "open", SubState_C, Punct_LPAREN, 0,             0, 0, 0, &Enum_targetObject, SubState_D, 0, 0},
     {"description", SubState_D,  Punct_WHITE, 0, "description", 0, 0, &Description_targetObject, SubState_N, 0, 0},
     {      "value", SubState_D,  Punct_WHITE, 0,       "value", 0, 0, &Value_targetObject, SubState_N, 0, 0},
     {       "open", SubState_E, Punct_LPAREN, 0,             0, 0, 0, &Enum_targetObject, SubState_F, 0, 0},
     {      "value", SubState_F,  Punct_WHITE, 0,       "value", 0, 0, &Value_targetObject, SubState_N, 0, 0},
     {       "open", SubState_G, Punct_LPAREN, 0,             0, 0, 0, &Enum_targetObject, SubState_H, 0, 0},
     {      "close", SubState_G, Punct_RPAREN, 0,             0, 0, 0, &Category_targetObject, SubState_B, Command_CLOSE, 0},
     {       "icon", SubState_H,  Punct_WHITE, 0,        "icon", 0, 0, &Icon_targetObject, SubState_N, 0, 0},
     {      "close", SubState_I, Punct_RPAREN, 0,             0, 0, 0, &Category_targetObject, SubState_B, Command_CLOSE, 0}
    };
PRIVATE TargetObject_t Enum_targetObject = {"Enum", &Enum_open, &Enum_close, &Enum_destroy, Enum_stateTokens, raysize(Enum_stateTokens), CSMRTC_ENUM};

/* CSParse_doc end */
/* S T A T E   A S S O C I A T I O N - associate a CSMachRead with the label list data 
   The label list data is kept around until all states referencing it are destroyed */
typedef struct {
    CSMachRead_t * pCSMachRead;
    CSMachReadData_t * pCSMachReadData;
    } CSMachReadAssoc_t;

PRIVATE HTList * CSMachReadAssocs = 0;

PRIVATE void CSMachReadAssoc_add(CSMachRead_t * pCSMachRead, CSMachReadData_t * pCSMachReadData)
{
    CSMachReadAssoc_t * pElement;
    if ((pElement = (CSMachReadAssoc_t *) HT_CALLOC(1, sizeof(CSMachReadAssoc_t))) == NULL)
        HT_OUTOFMEM("CSMachReadAssoc_t");
    pElement->pCSMachRead = pCSMachRead;
    pElement->pCSMachReadData = pCSMachReadData;
    if (!CSMachReadAssocs)
        CSMachReadAssocs = HTList_new();
    HTList_appendObject(CSMachReadAssocs, (void *)pElement);
}

PRIVATE CSMachReadAssoc_t * CSMachReadAssoc_findByData(CSMachReadData_t * pCSMachReadData)
{
    HTList * assocs = CSMachReadAssocs;
    CSMachReadAssoc_t * pElement;
    while ((pElement = (CSMachReadAssoc_t *) HTList_nextObject(assocs)))
        if (pElement->pCSMachReadData == pCSMachReadData)
            return pElement;
    return 0;
}

PRIVATE CSMachReadAssoc_t * CSMachReadAssoc_findByState(CSMachRead_t * pCSMachRead)
{
    HTList * assocs = CSMachReadAssocs;
    CSMachReadAssoc_t * pElement;
    while ((pElement = (CSMachReadAssoc_t *) HTList_nextObject(assocs)))
        if (pElement->pCSMachRead == pCSMachRead)
            return pElement;
    return 0;
}

PRIVATE void CSMachReadAssoc_removeByState(CSMachRead_t * pCSMachRead)
{
    CSMachReadAssoc_t * pElement = CSMachReadAssoc_findByState(pCSMachRead);
    if (!pElement)
        return;
    HTList_removeObject(CSMachReadAssocs, (void *)pElement);
    HT_FREE(pElement);
}

/* C O N S T R U C T O R S / D E S T R U C T O R S */
PRIVATE MachRead_enum_t * MachRead_enum_new(void)
{
	MachRead_enum_t * me;
	if ((me = (MachRead_enum_t *) HT_CALLOC(1, sizeof(MachRead_enum_t))) == NULL)
	    HT_OUTOFMEM("MachRead_enum_t");
    return me;
}

PUBLIC void MachRead_enum_free(MachRead_enum_t * me)
{
    SVal_clear(&me->name);
    SVal_clear(&me->description);
    FVal_clear(&me->value);
    SVal_clear(&me->icon);
}

PRIVATE MachRead_category_t * MachRead_category_new(void)
{
    MachRead_category_t * me;
    if ((me = (MachRead_category_t *) HT_CALLOC(1, sizeof(MachRead_category_t))) == NULL)
        HT_OUTOFMEM("MachRead_category_t");
    return me;
}

PUBLIC void MachRead_category_free(MachRead_category_t * me)
{
    MachRead_enum_t * pMachRead_enum;
    MachRead_category_t * pMachRead_category;
    while ((pMachRead_enum = (MachRead_enum_t *) HTList_removeLastObject(me->machRead_enums)))
        MachRead_enum_free(pMachRead_enum);
    while ((pMachRead_category = (MachRead_category_t *) HTList_removeLastObject(me->machRead_categories)))
        MachRead_category_free(pMachRead_category);
    HTList_delete(me->machRead_enums);
    HTList_delete(me->machRead_categories);
    SVal_clear(&me->transmit);
    SVal_clear(&me->icon);
    SVal_clear(&me->name);
    SVal_clear(&me->description);
    FVal_clear(&me->min);
    FVal_clear(&me->max);
    BVal_clear(&me->multi);
    BVal_clear(&me->unord);
    BVal_clear(&me->integer);
    BVal_clear(&me->labeled);
}

PUBLIC CSMachReadData_t * CSMachReadData_new(void)
{
    CSMachReadData_t * me;
    if ((me = (CSMachReadData_t *) HT_CALLOC(1, sizeof(CSMachReadData_t))) == NULL)
        HT_OUTOFMEM("CSMachReadData_t");
    me->machRead_categories = HTList_new();
    return me;
}

PUBLIC void CSMachReadData_free(CSMachReadData_t * me)
{
    MachRead_category_t * pMachRead_category;
    if (CSMachReadAssoc_findByData(me))
        return;
    while ((pMachRead_category = (MachRead_category_t *) HTList_removeLastObject(me->machRead_categories)))
        MachRead_category_free(pMachRead_category);
    FVal_clear(&me->version);
    SVal_clear(&me->system);
    SVal_clear(&me->service);
    SVal_clear(&me->icon);
    SVal_clear(&me->name);
    SVal_clear(&me->description);
    FVal_clear(&me->min);
    FVal_clear(&me->max);
    BVal_clear(&me->multi);
    BVal_clear(&me->unord);
    BVal_clear(&me->integer);
    BVal_clear(&me->labeled);
    HT_FREE(me);
}

PUBLIC CSMachRead_t * CSMachRead_new(CSMachReadData_t * pCSMachReadData, MachReadTargetCallback_t * pMachReadTargetCallback, 
								   MRErrorHandler_t * pMRErrorHandler)
{
    CSMachRead_t * me;
    if ((me = (CSMachRead_t *) HT_CALLOC(1, sizeof(CSMachRead_t))) == NULL)
        HT_OUTOFMEM("CSMachRead_t");
    me->pCSMachReadData = pCSMachReadData;
    me->pMachReadTargetCallback = pMachReadTargetCallback;
    me->pMRErrorHandler = pMRErrorHandler;
    CSMachReadAssoc_add(me, pCSMachReadData);
    return me;
}

PUBLIC CSMachRead_t * CSMachRead_copy(CSMachRead_t * old)
{
    CSMachRead_t * me;
    me = CSMachRead_new(old->pCSMachReadData, old->pMachReadTargetCallback, 
			old->pMRErrorHandler);
    memcpy(me, old, sizeof(CSMachRead_t));
    return me;
}

PUBLIC void CSMachRead_free(CSMachRead_t * me)
{
    CSMachReadData_t * pCSMachReadData = me->pCSMachReadData;
    CSMachReadAssoc_removeByState(me);
    HT_FREE(me);
    CSMachReadData_free(pCSMachReadData);
}

PUBLIC char * CSMachRead_getSystem(CSMachRead_t * me) {return SVal_value(&me->pCSMachReadData->system);}
PUBLIC char * CSMachRead_getService(CSMachRead_t * me) {return SVal_value(&me->pCSMachReadData->service);}
PUBLIC CSMachReadData_t * CSMachRead_getCSMachReadData(CSMachRead_t * me) {return me->pCSMachReadData;}
PUBLIC MachRead_category_t * CSMachRead_getMachReadCategory(CSMachRead_t * pCSMachRead) {return pCSMachRead->pCurrentMachRead_category;}
PUBLIC MachRead_enum_t * CSMachRead_getMachReadEnum(CSMachRead_t * pCSMachRead) {return pCSMachRead->pCurrentMachRead_enum;}

PUBLIC CSParse_t * CSParse_newMachRead(MachReadTargetCallback_t * pMachReadTargetCallback, 
				       MRErrorHandler_t * pMRErrorHandler)
{
    CSParse_t * me = CSParse_new();
    me->pParseContext->engineOf = &CSParse_targetParser;
    me->pParseContext->pTargetChangeCallback = &targetChangeCallback;
    me->pParseContext->pParseErrorHandler = &parseErrorHandler;
    me->target.pCSMachRead = CSMachRead_new(CSMachReadData_new(), pMachReadTargetCallback, pMRErrorHandler);
    me->pTargetObject = &MachRead_targetObject;
    me->currentSubState = SubState_N;
    return me;
}

PUBLIC CSMachRead_t * CSParse_getMachRead(CSParse_t * me)
{
    return (me->target.pCSMachRead);
}

PUBLIC BOOL CSParse_deleteMachRead(CSParse_t * pCSParse)
{
    CSMachRead_t * me = GetCSMachRead(pCSParse);
    CSMachReadData_free(CSMachRead_getCSMachReadData(me));
    CSMachRead_free(me);
    return YES;
}

/* P A R S I N G   H A N D L E R S */
PRIVATE StateRet_t targetChangeCallback(CSParse_t * pCSParse, TargetObject_t * pTargetObject, CSParseTC_t target, BOOL closed, void * pVoid)
{

    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pMachReadTargetCallback)
       	return (*pCSMachRead->pMachReadTargetCallback)(pCSMachRead, pCSParse, (CSMRTC_t)target, closed, pVoid);
    return StateRet_OK;
}

PRIVATE StateRet_t parseErrorHandler(CSParse_t * pCSParse, const char * token, char demark, StateRet_t errorCode)
{
	CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
	if (pCSMachRead->pMRErrorHandler)
		return (*pCSMachRead->pMRErrorHandler)(pCSMachRead, pCSParse, token, demark, errorCode);
  return errorCode;
}

/* CSParse_doc methods */
/* P A R S I N G   S T A T E   F U N C T I O N S */
PRIVATE StateRet_t postValueState(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);

    if (pCSMachRead->inDefault) {
        SETNEXTSTATE(&Default_targetObject, SubState_A);
	return StateRet_OK;
    }
    if (pCSMachRead->pCurrentMachRead_enum) {
	if (SVal_initialized(&pCSMachRead->pCurrentMachRead_enum->icon)) {
	    SETNEXTSTATE(&Enum_targetObject, SubState_I);
	    return StateRet_OK;
	}
	if (FVal_initialized(&pCSMachRead->pCurrentMachRead_enum->value)) {
	    SETNEXTSTATE(&Enum_targetObject, SubState_G);
	    return StateRet_OK;
	}
	if (SVal_initialized(&pCSMachRead->pCurrentMachRead_enum->description)) {
	    SETNEXTSTATE(&Enum_targetObject, SubState_E);
	    return StateRet_OK;
	}
        SETNEXTSTATE(&Enum_targetObject, SubState_C);
	return StateRet_OK;
      }
    if (pCSMachRead->pCurrentMachRead_category){
	SETNEXTSTATE(&Category_targetObject, SubState_B);
	return StateRet_OK;
    }
    SETNEXTSTATE(&MachRead_targetObject, SubState_D);
    return StateRet_OK;
}

PRIVATE StateRet_t Category_next(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category) {
        SETNEXTSTATE(&Category_targetObject, SubState_F);
	return StateRet_OK;
    }
    SETNEXTSTATE(&Category_targetObject, SubState_H);
    return StateRet_OK;
}

PRIVATE StateRet_t Multi_setTrue(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category) {
        BVal_set(&pCSMachRead->pCurrentMachRead_category->multi, YES);
    } else {
        BVal_set(&pCSMachRead->pCSMachReadData->multi, YES);
    }
    return postValueState(pCSParse, token, demark);
}

PRIVATE StateRet_t Unord_setTrue(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category) {
        BVal_set(&pCSMachRead->pCurrentMachRead_category->unord, YES);
    } else {
        BVal_set(&pCSMachRead->pCSMachReadData->unord, YES);
    }
    return postValueState(pCSParse, token, demark);
}

PRIVATE StateRet_t Integer_setTrue(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
	if (pCSMachRead->pCurrentMachRead_category) {
		BVal_set(&pCSMachRead->pCurrentMachRead_category->integer, YES);
	} else {
		BVal_set(&pCSMachRead->pCSMachReadData->integer, YES);
	}
	return postValueState(pCSParse, token, demark);
}

PRIVATE StateRet_t Labeled_setTrue(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
	if (pCSMachRead->pCurrentMachRead_category) {
		BVal_set(&pCSMachRead->pCurrentMachRead_category->labeled, YES);
	} else {
		BVal_set(&pCSMachRead->pCSMachReadData->labeled, YES);
	}
	return postValueState(pCSParse, token, demark);
}

PRIVATE StateRet_t Version_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
	if (!FVal_readVal(&pCSMachRead->pCSMachReadData->version, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t System_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
	if (!SVal_readVal(&pCSMachRead->pCSMachReadData->system, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Service_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
	if (!SVal_readVal(&pCSMachRead->pCSMachReadData->service, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Icon_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	SVal_t * pSVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_enum)
		pSVal = &pCSMachRead->pCurrentMachRead_enum->icon;
    else if (pCSMachRead->pCurrentMachRead_category)
		pSVal = &pCSMachRead->pCurrentMachRead_category->icon;
	else
		pSVal = &pCSMachRead->pCSMachReadData->icon;
	if (!SVal_readVal(pSVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Name_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	SVal_t * pSVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_enum)
		pSVal = &pCSMachRead->pCurrentMachRead_enum->name;
    else if (pCSMachRead->pCurrentMachRead_category)
		pSVal = &pCSMachRead->pCurrentMachRead_category->name;
	else
		pSVal = &pCSMachRead->pCSMachReadData->name;
	if (!SVal_readVal(pSVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Description_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	SVal_t * pSVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_enum)
		pSVal = &pCSMachRead->pCurrentMachRead_enum->description;
    else if (pCSMachRead->pCurrentMachRead_category)
		pSVal = &pCSMachRead->pCurrentMachRead_category->description;
	else
		pSVal = &pCSMachRead->pCSMachReadData->description;
	if (!SVal_readVal(pSVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Min_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	FVal_t * pFVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category)
		pFVal = &pCSMachRead->pCurrentMachRead_category->min;
	else
		pFVal = &pCSMachRead->pCSMachReadData->min;
	if (!FVal_readVal(pFVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Max_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	FVal_t * pFVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category)
		pFVal = &pCSMachRead->pCurrentMachRead_category->max;
	else
		pFVal = &pCSMachRead->pCSMachReadData->max;
	if (!FVal_readVal(pFVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Multi_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	BVal_t * pBVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category)
		pBVal = &pCSMachRead->pCurrentMachRead_category->multi;
	else
		pBVal = &pCSMachRead->pCSMachReadData->multi;
	if (!BVal_readVal(pBVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Unord_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	BVal_t * pBVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category)
		pBVal = &pCSMachRead->pCurrentMachRead_category->unord;
	else
		pBVal = &pCSMachRead->pCSMachReadData->unord;
	if (!BVal_readVal(pBVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}

PRIVATE StateRet_t Integer_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
	BVal_t * pBVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category)
		pBVal = &pCSMachRead->pCurrentMachRead_category->integer;
	else
		pBVal = &pCSMachRead->pCSMachReadData->integer;
	if (!BVal_readVal(pBVal, token))
		return StateRet_WARN_NO_MATCH;
	return StateRet_OK;
}


PRIVATE StateRet_t Labeled_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
    BVal_t * pBVal;
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (pCSMachRead->pCurrentMachRead_category)
        pBVal = &pCSMachRead->pCurrentMachRead_category->labeled;
    else
        pBVal = &pCSMachRead->pCSMachReadData->labeled;
    if (!BVal_readVal(pBVal, token))
        return StateRet_WARN_NO_MATCH;
    return StateRet_OK;
}

PRIVATE StateRet_t Transmit_as_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (!SVal_readVal(&pCSMachRead->pCurrentMachRead_category->transmit, token))
        return StateRet_WARN_NO_MATCH;
    return StateRet_OK;
}

PRIVATE StateRet_t Value_get(CSParse_t * pCSParse, StateToken_t * pStateToken, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    if (!FVal_readVal(&pCSMachRead->pCurrentMachRead_enum->value, token))
        return StateRet_WARN_NO_MATCH;
    return StateRet_OK;
}

PRIVATE StateRet_t MachRead_open(CSParse_t * pCSParse, char * token, char demark)
{
    return StateRet_OK;
}

PRIVATE StateRet_t Category_open(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    MachRead_category_t * me = MachRead_category_new();
    me->pParent = pCSMachRead->pCurrentMachRead_category;
    pCSMachRead->pCurrentMachRead_category = me;
    HTList_appendObject(pCSMachRead->pCSMachReadData->machRead_categories, (void *)me);
    return StateRet_OK;
}

PRIVATE StateRet_t Default_open(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    pCSMachRead->inDefault = YES;
    return StateRet_OK;
}

PRIVATE StateRet_t Enum_open(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    MachRead_enum_t * me = MachRead_enum_new();
    pCSMachRead->pCurrentMachRead_enum = me;
    if (!pCSMachRead->pCurrentMachRead_category->machRead_enums)
        pCSMachRead->pCurrentMachRead_category->machRead_enums = HTList_new();
    HTList_appendObject(pCSMachRead->pCurrentMachRead_category->machRead_enums, (void *)me);
    return StateRet_OK;
}

PRIVATE StateRet_t MachRead_close(CSParse_t * pCSParse, char * token, char demark)
{
	return StateRet_DONE;
}

PRIVATE StateRet_t Category_close(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    pCSMachRead->pCurrentMachRead_category = pCSMachRead->pCurrentMachRead_category->pParent;
    return StateRet_OK;
}

PRIVATE StateRet_t Default_close(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    pCSMachRead->inDefault = NO;
    return StateRet_OK;
}

PRIVATE StateRet_t Enum_close(CSParse_t * pCSParse, char * token, char demark)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    pCSMachRead->pCurrentMachRead_enum = 0;
    return StateRet_OK;
}

PRIVATE void MachRead_destroy(CSParse_t * pCSParse)
{
}

PRIVATE void Category_destroy(CSParse_t * pCSParse)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    HTList_removeObject(pCSMachRead->pCurrentMachRead_category->machRead_categories, (void *)pCSMachRead->pCurrentMachRead_category);
    MachRead_category_free(pCSMachRead->pCurrentMachRead_category);
    pCSMachRead->pCurrentMachRead_category = 0;
}

PRIVATE void Default_destroy(CSParse_t * pCSParse)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    pCSMachRead->inDefault = NO;
}

PRIVATE void Enum_destroy(CSParse_t * pCSParse)
{
    CSMachRead_t * pCSMachRead = GetCSMachRead(pCSParse);
    HTList_removeObject(pCSMachRead->pCurrentMachRead_category->machRead_enums, (void *)pCSMachRead->pCurrentMachRead_enum);
	if (!HTList_count(pCSMachRead->pCurrentMachRead_category->machRead_enums)) {
        HTList_delete(pCSMachRead->pCurrentMachRead_category->machRead_enums);
        pCSMachRead->pCurrentMachRead_category->machRead_enums = 0;
    }
    MachRead_enum_free(pCSMachRead->pCurrentMachRead_enum);
    pCSMachRead->pCurrentMachRead_enum = 0;
}

/* CSParse_doc end */
/* I T E R A T O R S - scan through the CSMachRead data structures for <identifier>
 */
PUBLIC CSError_t CSMachRead_iterateCategories(CSMachRead_t * pCSMachRead, CSMachRead_callback_t * pIteratorCB, State_Parms_t * pParms, const char * identifier, void * pVoid)
{
    HTList * machRead_categories;
    CSError_t ret = CSError_OK;
    int count = 0;
    if (!pIteratorCB ||
        !pCSMachRead ||
        !pCSMachRead->pCSMachReadData->machRead_categories)
        return CSError_BAD_PARAM;
    machRead_categories = pCSMachRead->pCSMachReadData->machRead_categories;
	while ((pCSMachRead->pCurrentMachRead_category = (MachRead_category_t *) HTList_nextObject(machRead_categories)) && ret == CSError_OK)
        if (!identifier || !strcasecomp(SVal_value(&pCSMachRead->pCurrentMachRead_category->transmit), identifier)) {
            ret = (*pIteratorCB)(pCSMachRead, pParms, identifier, pVoid) != CSError_OK;
            count++;
        }
    if (!count)
        return CSError_CATEGORY_MISSING;
    return ret;
}

PUBLIC CSError_t CSMachRead_iterateEnums(CSMachRead_t * pCSMachRead, CSMachRead_callback_t * pIteratorCB, State_Parms_t * pParms, const char * identifier, void * pVoid)
{
    HTList * machRead_enums;
    CSError_t ret = CSError_OK;
    int count = 0;
    if (!pIteratorCB ||
        !pCSMachRead ||
        !pCSMachRead->pCurrentMachRead_category ||
        !pCSMachRead->pCurrentMachRead_category->machRead_enums)
        return CSError_BAD_PARAM;
    machRead_enums = pCSMachRead->pCurrentMachRead_category->machRead_enums;
	while ((pCSMachRead->pCurrentMachRead_enum = (MachRead_enum_t *) HTList_nextObject(machRead_enums)) && ret == CSError_OK)
        if (!identifier || !strcasecomp(SVal_value(&pCSMachRead->pCurrentMachRead_enum->name), identifier)) {
            ret = (*pIteratorCB)(pCSMachRead, pParms, identifier, pVoid) != CSError_OK;
            count++;
        }
    if (!count)
        return CSError_ENUM_MISSING;
    return ret;
}

