2508 lines
84 KiB
C
2508 lines
84 KiB
C
|
|
/************************************************************************/
|
|||
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
|||
|
|
/* 2004-2006, All Rights Reserved */
|
|||
|
|
/* */
|
|||
|
|
/* MODULE NAME : sclparse.c */
|
|||
|
|
/* PRODUCT(S) : */
|
|||
|
|
/* */
|
|||
|
|
/* MODULE DESCRIPTION : This routine parses XML files conforming to the */
|
|||
|
|
/* SCL object model. */
|
|||
|
|
/* */
|
|||
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
|||
|
|
/* */
|
|||
|
|
/* MODIFICATION LOG : */
|
|||
|
|
/* Date Who Rev Comments */
|
|||
|
|
/* -------- --- ------ ------------------------------------------- */
|
|||
|
|
/* 05/06/08 JRB 23 Chk ReportControl indexed attr (must be true)*/
|
|||
|
|
/* 04/23/08 JRB 22 Parse & save "SettingControl" info (SGCB). */
|
|||
|
|
/* Save dchg, qchg, dupd values in SCL_DA struct*/
|
|||
|
|
/* 01/18/08 JRB 21 Allow max LN prefix+inst=11. IEC 61850 max=7.*/
|
|||
|
|
/* Must also reduce max suffix in mvlu_rt.c to */
|
|||
|
|
/* avoid overflow. */
|
|||
|
|
/* 01/18/08 JRB 20 Chg datSet in GSEControl & LogControl to */
|
|||
|
|
/* optional to match Schema (see tControl def). */
|
|||
|
|
/* 07/10/07 JRB 19 Check length of lnClass, prefix, & inst. */
|
|||
|
|
/* 06/12/07 JRB 18 Save VLANID in SCL_GSE & SCL_SMV. */
|
|||
|
|
/* 09/08/06 JRB 17 Fix dstlen type in convert_mac. */
|
|||
|
|
/* 07/26/06 LWP/JRB 16 Parse & save GOOSE & SMV addressing info from*/
|
|||
|
|
/* "Communication" section. */
|
|||
|
|
/* 04/19/06 JRB 15 Make datSet in ReportControl "optional". */
|
|||
|
|
/* 04/19/06 JRB 14 Parse & save "RptEnabled" info. */
|
|||
|
|
/* 04/04/06 JRB 13 Parse & save "SampledValueControl" info. */
|
|||
|
|
/* 03/25/06 JRB 12 Change order of operations: call create/add */
|
|||
|
|
/* functions first, then copy data directly to */
|
|||
|
|
/* SCL structs (eliminates intermediate copy). */
|
|||
|
|
/* Repl scl_get_attr (could overflow caller buf)*/
|
|||
|
|
/* with scl_get_attr_ptr & scl_get_attr_copy. */
|
|||
|
|
/* Replace CONTROL_BLOCK with SCL_RCB & SCL_LCB,*/
|
|||
|
|
/* Fix _DA_SEFun setting of dchg, qchg, & dupd. */
|
|||
|
|
/* Fix sx_get_string calls to prevent overflow. */
|
|||
|
|
/* Fix "*_Val_*" functions. */
|
|||
|
|
/* Chg desc to ptr (allocated during parse). */
|
|||
|
|
/* 07/25/05 JRB 11 Make nameStructure optional, default=IEDName.*/
|
|||
|
|
/* 06/24/05 JRB 10 Call sx_parseExx_mt (faster). */
|
|||
|
|
/* Chg "ord" from unsigned to signed value. */
|
|||
|
|
/* 05/17/05 DWL 09 Use sx_push instead of SX_PUSH, and force */
|
|||
|
|
/* user code to call sx_pop. Eliminated some */
|
|||
|
|
/* unnecessary debug logging. */
|
|||
|
|
/* 05/17/05 JRB 08 Avoid allocating struct in scl_parse. */
|
|||
|
|
/* 02/15/05 JRB 07 Save iedName in scl_info. */
|
|||
|
|
/* Parse Header & save in scl_info. */
|
|||
|
|
/* Fix some log messages. */
|
|||
|
|
/* 12/07/04 JRB 06 Del unneeded memsets after callocs. */
|
|||
|
|
/* 08/23/04 JRB 05 Ret err if iedName or accessPoint.. not found*/
|
|||
|
|
/* 08/06/04 JRB 04 Del "sclparse.h", use "scl.h". */
|
|||
|
|
/* 07/23/04 JRB 03 Del unused static functions. */
|
|||
|
|
/* 07/15/04 DWL 02 Added LogControl & GSEControl elements */
|
|||
|
|
/* Handle LN and LN0 differently. */
|
|||
|
|
/* 06/10/04 DWL 01 Created */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
#include "glbtypes.h"
|
|||
|
|
#include "sysincs.h"
|
|||
|
|
#include "mem_chk.h"
|
|||
|
|
#include "sx_defs.h"
|
|||
|
|
#include "sx_log.h"
|
|||
|
|
#include "str_util.h"
|
|||
|
|
#include "slog.h"
|
|||
|
|
#include "scl.h" /* SCL file processing structs & functions */
|
|||
|
|
#include "mvl_uca.h"
|
|||
|
|
#include "smpval.h"
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* For debug version, use a static pointer to avoid duplication of */
|
|||
|
|
/* __FILE__ strings. */
|
|||
|
|
|
|||
|
|
#ifdef DEBUG_SISCO
|
|||
|
|
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
#define SCL_ATTR_OPTIONAL 0 /* attribute is optional */
|
|||
|
|
#define SCL_ATTR_REQUIRED 1 /* attribute is required */
|
|||
|
|
|
|||
|
|
typedef struct scl_dec_ctrl
|
|||
|
|
{
|
|||
|
|
ST_CHAR *iedName;
|
|||
|
|
ST_CHAR *accessPointName;
|
|||
|
|
ST_BOOLEAN accessPointFound; /* SD_TRUE if IED and AccessPoint found */
|
|||
|
|
ST_BOOLEAN iedNameMatched;
|
|||
|
|
ST_BOOLEAN accessPointMatched;
|
|||
|
|
SCL_INFO *sclInfo;
|
|||
|
|
SCL_GSE *scl_gse; /* Used for "GSE" in "Communication" section */
|
|||
|
|
SCL_SMV *scl_smv; /* Used for "SMV" in "Communication" section */
|
|||
|
|
SCL_LD *scl_ld; /* Used for "LDevice" */
|
|||
|
|
SCL_LN *scl_ln; /* Used for "LN" (Logical Node) */
|
|||
|
|
SCL_RCB *scl_rcb; /* alloc to store ReportControl info */
|
|||
|
|
SCL_LCB *scl_lcb; /* alloc to store LogControl info */
|
|||
|
|
ST_UINT8 TrgOps[1]; /* Used for ReportControl or LogControl. */
|
|||
|
|
/* Copied to SCL_RCB or SCL_LCB. */
|
|||
|
|
SCL_SVCB *scl_svcb; /* Used for "SampledValueControl". */
|
|||
|
|
SCL_ENUMVAL *scl_enumval; /* Used for "EnumVal". */
|
|||
|
|
SCL_DAI *scl_dai; /* Used for "DAI". */
|
|||
|
|
SCL_DA *scl_da; /* Used for "DA". */
|
|||
|
|
SCL_BDA *scl_bda; /* Used for "BDA". */
|
|||
|
|
ST_CHAR flattened[MAX_FLAT_LEN + 1]; /* Created by concatenating values*/
|
|||
|
|
/* from DOI, SDI, and DAI elements*/
|
|||
|
|
} SCL_DEC_CTRL;
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SCL_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _Header_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
|
|||
|
|
static ST_VOID _Communication_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SubNetwork_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _ConnectedAP_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _GSE_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _GSE_Address_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _GSE_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SMV_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SMV_Address_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SMV_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
/*renxiaobao GSE <20><><EFBFBD><EFBFBD>*/
|
|||
|
|
static ST_VOID _GSE_MinTime_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _GSE_MaxTime_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
|
|||
|
|
static ST_VOID _IED_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _AccessPoint_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _Server_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _LDevice_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _LN_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DataSet_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _FCDA_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _ReportControl_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _LogControl_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _GSEControl_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SettingControl_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _TrgOps_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _OptFlds_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _RptEnabled_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DOI_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SDI_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DAI_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DAI_Val_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DataTypeTemplates_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _LNodeType_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DO_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DOType_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DA_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SDO_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DAType_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _DA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _BDA_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _BDA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _EnumType_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _EnumVal_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_RET _scl_unknown_el_start (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag);
|
|||
|
|
static ST_RET _scl_unknown_el_end (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag);
|
|||
|
|
static ST_VOID _SampledValueControl_SEFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SampledValueControl_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SampledValueControl_EFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
static ST_VOID _SmvOpts_SFun (SX_DEC_CTRL *sxDecCtrl);
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* Only the elements we need to extract are listed here. */
|
|||
|
|
/* The rest are handled by "unknown" element handler. */
|
|||
|
|
SX_ELEMENT sclStartElements[] =
|
|||
|
|
{
|
|||
|
|
{"SCL", SX_ELF_CSTARTEND, _SCL_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT SCLElements[] =
|
|||
|
|
{
|
|||
|
|
{"Header", SX_ELF_CSTART|SX_ELF_OPT, _Header_SFun, NULL, 0},
|
|||
|
|
{"Communication", SX_ELF_CSTARTEND|SX_ELF_OPT, _Communication_SEFun, NULL, 0},
|
|||
|
|
{"IED", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _IED_SEFun, NULL, 0},
|
|||
|
|
{"DataTypeTemplates", SX_ELF_CSTARTEND|SX_ELF_OPT, _DataTypeTemplates_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* Tables for mapping "Communication" elements. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
SX_ELEMENT CommunicationElements[] =
|
|||
|
|
{
|
|||
|
|
{"SubNetwork", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SubNetwork_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT SubNetworkElements[] =
|
|||
|
|
{
|
|||
|
|
/* NOTE: "bitRate" and "Text" elements ignored. */
|
|||
|
|
{"ConnectedAP", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _ConnectedAP_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT ConnectedAPElements[] =
|
|||
|
|
{
|
|||
|
|
/* DEBUG: add "Address". Ignore "PhyConn". */
|
|||
|
|
{"GSE", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_SEFun, NULL, 0},
|
|||
|
|
{"SMV", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SMV_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT GSEElements[] =
|
|||
|
|
{
|
|||
|
|
{"Address", SX_ELF_CSTARTEND|SX_ELF_OPT, _GSE_Address_SEFun, NULL, 0},
|
|||
|
|
/*renxiaobao GSE <20><><EFBFBD><EFBFBD>*/
|
|||
|
|
{"MinTime", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_MinTime_SEFun, NULL, 0},
|
|||
|
|
{"MaxTime", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_MaxTime_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
SX_ELEMENT GSEAddressElements[] =
|
|||
|
|
{
|
|||
|
|
{"P", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _GSE_Address_P_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT SMVElements[] =
|
|||
|
|
{
|
|||
|
|
{"Address", SX_ELF_CSTARTEND|SX_ELF_OPT, _SMV_Address_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT SMVAddressElements[] =
|
|||
|
|
{
|
|||
|
|
{"P", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SMV_Address_P_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* Tables for mapping "IED" elements. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
SX_ELEMENT IEDElements[] =
|
|||
|
|
{
|
|||
|
|
{"AccessPoint", SX_ELF_CSTARTEND|SX_ELF_RPT, _AccessPoint_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT AccessPointElements[] =
|
|||
|
|
{
|
|||
|
|
{"Server", SX_ELF_CSTARTEND, _Server_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT ServerElements[] =
|
|||
|
|
{
|
|||
|
|
{"LDevice", SX_ELF_CSTARTEND|SX_ELF_RPT, _LDevice_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT LDeviceElements[] =
|
|||
|
|
{
|
|||
|
|
{"LN0", SX_ELF_CSTARTEND, _LN_SEFun, NULL, 0},
|
|||
|
|
{"LN", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _LN_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT LN0Elements[] =
|
|||
|
|
{
|
|||
|
|
{"DataSet", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DataSet_SEFun, NULL, 0},
|
|||
|
|
{"ReportControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _ReportControl_SEFun, NULL, 0},
|
|||
|
|
{"DOI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DOI_SEFun, NULL, 0},
|
|||
|
|
{"SampledValueControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SampledValueControl_SEFun, NULL, 0},
|
|||
|
|
{"LogControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _LogControl_SEFun, NULL, 0},
|
|||
|
|
{"SettingControl", SX_ELF_CSTART|SX_ELF_OPTRPT, _SettingControl_SFun, NULL, 0},
|
|||
|
|
{"GSEControl", SX_ELF_CSTART|SX_ELF_OPTRPT, _GSEControl_SFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT LNElements[] =
|
|||
|
|
{
|
|||
|
|
{"DataSet", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DataSet_SEFun, NULL, 0},
|
|||
|
|
{"ReportControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _ReportControl_SEFun, NULL, 0},
|
|||
|
|
{"DOI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DOI_SEFun, NULL, 0},
|
|||
|
|
{"SampledValueControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SampledValueControl_SEFun, NULL, 0},
|
|||
|
|
{"LogControl", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _LogControl_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT DataSetElements[] =
|
|||
|
|
{
|
|||
|
|
{"FCDA", SX_ELF_CSTART|SX_ELF_RPT, _FCDA_SFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT ReportControlElements[] =
|
|||
|
|
{
|
|||
|
|
{"TrgOps", SX_ELF_CSTART|SX_ELF_OPT, _TrgOps_SFun, NULL, 0},
|
|||
|
|
{"OptFields", SX_ELF_CSTART, _OptFlds_SFun, NULL, 0},
|
|||
|
|
{"RptEnabled", SX_ELF_CSTART|SX_ELF_OPT, _RptEnabled_SFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT LogControlElements[] =
|
|||
|
|
{
|
|||
|
|
{"TrgOps", SX_ELF_CSTART|SX_ELF_OPT, _TrgOps_SFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT SampledValueControlElements[] =
|
|||
|
|
{
|
|||
|
|
{"SmvOpts", SX_ELF_CSTART, _SmvOpts_SFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT DOIElements[] =
|
|||
|
|
{
|
|||
|
|
{"SDI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SDI_SEFun, NULL, 0},
|
|||
|
|
{"DAI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DAI_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/* SDI can be nested under itself indefinitely */
|
|||
|
|
SX_ELEMENT SDIElements[] =
|
|||
|
|
{
|
|||
|
|
{"SDI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _SDI_SEFun, NULL, 0},
|
|||
|
|
{"DAI", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DAI_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT DAIElements[] =
|
|||
|
|
{
|
|||
|
|
{"Val", SX_ELF_CSTARTEND|SX_ELF_OPT, _DAI_Val_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* Tables for mapping "DataTypeTemplates" elements. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
SX_ELEMENT DataTypeTemplatesElements[] =
|
|||
|
|
{
|
|||
|
|
{"LNodeType", SX_ELF_CSTARTEND|SX_ELF_RPT, _LNodeType_SEFun, NULL, 0},
|
|||
|
|
{"DOType", SX_ELF_CSTARTEND|SX_ELF_RPT, _DOType_SEFun, NULL, 0},
|
|||
|
|
{"DAType", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DAType_SEFun, NULL, 0},
|
|||
|
|
{"EnumType", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _EnumType_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT LNodeTypeElements[] =
|
|||
|
|
{
|
|||
|
|
{"DO", SX_ELF_CSTART|SX_ELF_RPT, _DO_SFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT DOTypeElements[] =
|
|||
|
|
{
|
|||
|
|
{"DA", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DA_SEFun, NULL, 0},
|
|||
|
|
{"SDO", SX_ELF_CSTART|SX_ELF_OPTRPT, _SDO_SFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT DAElements[] =
|
|||
|
|
{
|
|||
|
|
{"Val", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _DA_Val_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT DATypeElements[] =
|
|||
|
|
{
|
|||
|
|
{"BDA", SX_ELF_CSTARTEND|SX_ELF_RPT, _BDA_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT BDAElements[] =
|
|||
|
|
{
|
|||
|
|
{"Val", SX_ELF_CSTARTEND|SX_ELF_OPTRPT, _BDA_Val_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
SX_ELEMENT EnumTypeElements[] =
|
|||
|
|
{
|
|||
|
|
{"EnumVal", SX_ELF_CSTARTEND|SX_ELF_RPT, _EnumVal_SEFun, NULL, 0}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* convert_mac */
|
|||
|
|
/* Converts MAC string read from SCL file (like 01-02-03-04-05-06) */
|
|||
|
|
/* to 6 byte hex MAC address. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
#define MAX_MAC_STRING_LEN 60
|
|||
|
|
static ST_RET convert_mac (ST_UCHAR *dst, ST_CHAR *src)
|
|||
|
|
{
|
|||
|
|
ST_RET retcode;
|
|||
|
|
ST_CHAR tmpbuf [MAX_MAC_STRING_LEN+1];
|
|||
|
|
ST_CHAR *tmpptr;
|
|||
|
|
ST_UINT dstlen;
|
|||
|
|
|
|||
|
|
/* Input string may include extra blanks, so allow for fairly long string.*/
|
|||
|
|
if (strlen (src) > MAX_MAC_STRING_LEN)
|
|||
|
|
retcode = SD_FAILURE;
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* Just replace each '-' with ' '. Then use ascii_to_hex_str to convert.*/
|
|||
|
|
tmpptr = tmpbuf;
|
|||
|
|
/* Copy until NULL terminator but ignore '-' and spaces. */
|
|||
|
|
for ( ; *src; src++)
|
|||
|
|
{
|
|||
|
|
if (*src != '-' && (!isspace(*src)))
|
|||
|
|
*tmpptr++ = *src;
|
|||
|
|
}
|
|||
|
|
*tmpptr = '\0'; /* NULL terminate temp buffer */
|
|||
|
|
retcode = ascii_to_hex_str (dst, &dstlen, 6, tmpbuf);
|
|||
|
|
if (retcode == SD_SUCCESS && dstlen != 6)
|
|||
|
|
retcode = SD_FAILURE;
|
|||
|
|
}
|
|||
|
|
return (retcode);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* log_notfound_attr */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID log_notfound_attr (ST_CHAR *attrName)
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR1 ("SCL PARSE: Required attribute '%s' not found.",
|
|||
|
|
attrName);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* log_attr_str */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID log_attr_str (ST_CHAR *name, ST_CHAR *value)
|
|||
|
|
{
|
|||
|
|
SXLOG_DEC2 ("SCL PARSE: Found attribute '%s', value is '%s'", name, value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* log_attr_int */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID log_attr_int (ST_CHAR *name, ST_INT value)
|
|||
|
|
{
|
|||
|
|
SXLOG_DEC2 ("SCL PARSE: Found attribute '%s', value is '%d'", name, value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* log_attr_uint */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID log_attr_uint (ST_CHAR *name, ST_UINT value)
|
|||
|
|
{
|
|||
|
|
SXLOG_DEC2 ("SCL PARSE: Found attribute '%s', value is '%u'", name, value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* log_returned_failure */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID log_returned_failure (ST_CHAR *funcName, ST_LONG ret)
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR2 ("SCL PARSE: %s returned failure, err=%ld", funcName, ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* scl_stop_parsing */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID scl_stop_parsing (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *offender,
|
|||
|
|
ST_RET errCode)
|
|||
|
|
{
|
|||
|
|
sxDecCtrl->errCode = errCode;
|
|||
|
|
sxDecCtrl->termFlag = SD_TRUE;
|
|||
|
|
if (errCode == SX_REQUIRED_TAG_NOT_FOUND)
|
|||
|
|
{
|
|||
|
|
log_notfound_attr (offender);
|
|||
|
|
}
|
|||
|
|
else /* SX_USER_ERROR */
|
|||
|
|
{
|
|||
|
|
log_returned_failure (offender, errCode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* scl_get_attr_ptr */
|
|||
|
|
/* Get a pointer to an attr string stored in SX_DEC_CTRL. */
|
|||
|
|
/* If attr found, SD_SUCCESS returned & "*value" points to string. */
|
|||
|
|
/* NOTE: The pointer returned in "*value" might not be valid later */
|
|||
|
|
/* when parsing continues. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_RET scl_get_attr_ptr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name,
|
|||
|
|
ST_CHAR **value, ST_BOOLEAN required)
|
|||
|
|
{
|
|||
|
|
ST_RET ret;
|
|||
|
|
|
|||
|
|
ret = sx_get_attr_ptr (sxDecCtrl, value, name);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
*value = NULL; /* make sure ptr is NULL on error (better than garbage)*/
|
|||
|
|
if (required)
|
|||
|
|
scl_stop_parsing (sxDecCtrl, name, SX_REQUIRED_TAG_NOT_FOUND);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
log_attr_str (name, *value);
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* scl_get_attr_copy */
|
|||
|
|
/* Get a pointer to an attr string stored in SX_DEC_CTRL. */
|
|||
|
|
/* If strlen <= maxValueLen, copy string, else return error. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_RET scl_get_attr_copy (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name,
|
|||
|
|
ST_CHAR *value, ST_UINT maxValueLen, ST_BOOLEAN required)
|
|||
|
|
{
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_CHAR *pValue;
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, name, &pValue, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (strlen (pValue) <= maxValueLen)
|
|||
|
|
strcpy (value, pValue); /* copy string to caller's buffer */
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR3 ("Attribute Value='%s' exceeds max len '%d' for attribute '%s'", pValue, maxValueLen, name);
|
|||
|
|
scl_stop_parsing (sxDecCtrl, name, SX_USER_ERROR);
|
|||
|
|
ret = SD_FAILURE;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* scl_get_int_attr */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_RET scl_get_int_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name,
|
|||
|
|
ST_INT *value, ST_BOOLEAN required)
|
|||
|
|
{
|
|||
|
|
ST_RET ret;
|
|||
|
|
|
|||
|
|
ret = sx_get_int_attr (sxDecCtrl, name, value);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (required)
|
|||
|
|
scl_stop_parsing (sxDecCtrl, name, SX_REQUIRED_TAG_NOT_FOUND);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
log_attr_int (name, *value);
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* scl_get_uint_attr */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_RET scl_get_uint_attr (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *name,
|
|||
|
|
ST_UINT *value, ST_BOOLEAN required)
|
|||
|
|
{
|
|||
|
|
ST_RET ret;
|
|||
|
|
|
|||
|
|
ret = sx_get_uint_attr (sxDecCtrl, name, value);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (required)
|
|||
|
|
scl_stop_parsing (sxDecCtrl, name, SX_REQUIRED_TAG_NOT_FOUND);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
log_attr_uint (name, *value);
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* construct_flattened */
|
|||
|
|
/* Construct a flattened variable name from DOI, SDI, DAI names. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET construct_flattened (ST_CHAR *flattened, size_t maxlen, ST_CHAR *name, ST_CHAR *ix)
|
|||
|
|
{
|
|||
|
|
size_t ixlen;
|
|||
|
|
ST_RET retCode;
|
|||
|
|
|
|||
|
|
/* Calc space needed for optional [ix] */
|
|||
|
|
if (ix)
|
|||
|
|
ixlen = strlen(ix)+2; /* string plus brackets */
|
|||
|
|
else
|
|||
|
|
ixlen = 0;
|
|||
|
|
/* Make sure there is room for [ix] and "$" */
|
|||
|
|
if (strlen (flattened) + strlen(name) + ixlen + 1 <= maxlen)
|
|||
|
|
{
|
|||
|
|
/* If flattened is now empty, just copy name, else add "$" then name.*/
|
|||
|
|
if (strlen(flattened) == 0)
|
|||
|
|
strcpy (flattened, name);
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
strcat (flattened, "$");
|
|||
|
|
strcat (flattened, name);
|
|||
|
|
}
|
|||
|
|
if (ix)
|
|||
|
|
{ /* Add 'ix' to flattened if necessary. */
|
|||
|
|
strcat (flattened, "[");
|
|||
|
|
strcat (flattened, ix);
|
|||
|
|
strcat (flattened, "]");
|
|||
|
|
}
|
|||
|
|
retCode = SD_SUCCESS;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{ /* flattened is big, so this error should never occur with normal SCL.*/
|
|||
|
|
SXLOG_ERR2 ("ERROR: not enough space to add name '%s' to flattened name '%s'", name, flattened);
|
|||
|
|
retCode = SD_FAILURE;
|
|||
|
|
}
|
|||
|
|
return (retCode);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* scl_parse */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
ST_RET scl_parse (ST_CHAR *xmlFileName, ST_CHAR *iedName,
|
|||
|
|
ST_CHAR *accessPointName, SCL_INFO *sclInfo)
|
|||
|
|
{
|
|||
|
|
ST_RET ret;
|
|||
|
|
SCL_DEC_CTRL sclDecCtrl = {0}; /* start with clean struct. */
|
|||
|
|
|
|||
|
|
memset (sclInfo, 0, sizeof (SCL_INFO)); /* CRITICAL: start with clean struct*/
|
|||
|
|
|
|||
|
|
/* Save iedName in sclInfo for later use. */
|
|||
|
|
strncpy_safe (sclInfo->iedName, iedName, MAX_IDENT_LEN);
|
|||
|
|
|
|||
|
|
sclDecCtrl.iedName = iedName;
|
|||
|
|
sclDecCtrl.accessPointName = accessPointName;
|
|||
|
|
sclDecCtrl.accessPointFound = SD_FALSE;
|
|||
|
|
sclDecCtrl.sclInfo = sclInfo;
|
|||
|
|
|
|||
|
|
ret = sx_parseExx_mt (xmlFileName,
|
|||
|
|
sizeof (sclStartElements)/sizeof(SX_ELEMENT), sclStartElements,
|
|||
|
|
&sclDecCtrl, _scl_unknown_el_start, _scl_unknown_el_end);
|
|||
|
|
|
|||
|
|
/* NOTE: sx_parseEx_mt doesn't log error if file open fails, so log here*/
|
|||
|
|
/* It may not log some other errors, so log any other error here too. */
|
|||
|
|
if (ret == SX_FILE_NOT_FOUND)
|
|||
|
|
SXLOG_ERR1 ("XML File (%s) Open Error",xmlFileName);
|
|||
|
|
else if (ret != SD_SUCCESS)
|
|||
|
|
SXLOG_ERR2 ("Error 0x%X parsing SCL file (%s)", ret, xmlFileName);
|
|||
|
|
|
|||
|
|
/* If parsing successful, check if requested AccessPoint was found. */
|
|||
|
|
if (ret == SD_SUCCESS && sclDecCtrl.accessPointFound == SD_FALSE)
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR3 ("IED='%s' or AccessPoint='%s' not found in input file (%s)",
|
|||
|
|
iedName, accessPointName, xmlFileName);
|
|||
|
|
ret = SX_REQUIRED_TAG_NOT_FOUND; /* new error code could be clearer*/
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* SCL_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _SCL_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
sx_push (sxDecCtrl, sizeof(SCLElements)/sizeof(SX_ELEMENT), SCLElements, SD_FALSE);
|
|||
|
|
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
while (sxDecCtrl->itemStackLevel > 0)
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _Header_SFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _Header_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *nameStructure;
|
|||
|
|
ST_RET ret;
|
|||
|
|
SCL_INFO *sclInfo;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
sclInfo = sclDecCtrl->sclInfo;
|
|||
|
|
|
|||
|
|
/* Get required attributes */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "id", sclInfo->Header.id,
|
|||
|
|
(sizeof(sclInfo->Header.id)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return; /* At least one required attr not found. Stop now. */
|
|||
|
|
|
|||
|
|
/* Handle optional "nameStructure". */
|
|||
|
|
if (scl_get_attr_ptr (sxDecCtrl, "nameStructure", &nameStructure, SCL_ATTR_OPTIONAL) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (strcmp (nameStructure, "IEDName") != 0)
|
|||
|
|
SXLOG_ERR1 ("Header attribute nameStructure='%s' not allowed. Assuming nameStructure='IEDName' (i.e. 'Product Naming')", nameStructure);
|
|||
|
|
}
|
|||
|
|
/* Always assume nameStructure="IEDName" (i.e. "Product Naming") */
|
|||
|
|
sclInfo->Header.nameStructure = SCL_NAMESTRUCTURE_IEDNAME;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _Communication_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _Communication_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sx_push (sxDecCtrl, sizeof(CommunicationElements)/sizeof(SX_ELEMENT),
|
|||
|
|
CommunicationElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SubNetwork_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SubNetwork_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_SUBNET *scl_subnet;
|
|||
|
|
scl_subnet = scl_subnet_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_subnet == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_subnet_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* Get required attributes. */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_subnet->name, (sizeof(scl_subnet->name)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
if (ret)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "SubNetwork", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* Get optional attributes. */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_subnet->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "type", scl_subnet->type, (sizeof(scl_subnet->type)-1), SCL_ATTR_OPTIONAL);
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(SubNetworkElements)/sizeof(SX_ELEMENT),
|
|||
|
|
SubNetworkElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _ConnectedAP_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _ConnectedAP_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_CAP *scl_cap;
|
|||
|
|
scl_cap = scl_cap_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_cap == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_cap_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* Get required attributes */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "iedName", scl_cap->iedName, (sizeof(scl_cap->iedName)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "apName", scl_cap->apName, (sizeof(scl_cap->apName)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
if (ret)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "ConnectedAP", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* Get optional attributes. */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_cap->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(ConnectedAPElements)/sizeof(SX_ELEMENT),
|
|||
|
|
ConnectedAPElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _GSE_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _GSE_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* NOTE: save ptr in sclDecCtrl->scl_gse to use later in parsing. */
|
|||
|
|
sclDecCtrl->scl_gse = scl_gse_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (sclDecCtrl->scl_gse == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_gse_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "ldInst", sclDecCtrl->scl_gse->ldInst, (sizeof(sclDecCtrl->scl_gse->ldInst)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "cbName", sclDecCtrl->scl_gse->cbName, (sizeof(sclDecCtrl->scl_gse->cbName)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
if (ret)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "GSE", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_push (sxDecCtrl, sizeof(GSEElements)/sizeof(SX_ELEMENT),
|
|||
|
|
GSEElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _GSE_Address_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _GSE_Address_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sx_push (sxDecCtrl, sizeof(GSEAddressElements)/sizeof(SX_ELEMENT),
|
|||
|
|
GSEAddressElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _GSE_Address_P_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _GSE_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_CHAR *str;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
ST_CHAR *strOut;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_END)
|
|||
|
|
{
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "type", &str, required);
|
|||
|
|
if (!strcmpi(str,"MAC-Address"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (convert_mac (sclDecCtrl->scl_gse->MAC,strOut))
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR1 ("Illegal MAC Address '%s'", strOut);
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_GSE_Address_P_SEFun", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (!strcmpi(str,"APPID"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_gse->APPID = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
else if (!strcmpi(str,"VLAN-PRIORITY"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_gse->VLANPRI = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
else if (!strcmpi(str,"VLAN-ID"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_gse->VLANID = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*renxiaobao GSE <20><><EFBFBD><EFBFBD>*/
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _GSE_MinTime_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _GSE_MinTime_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_CHAR *str;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
ST_CHAR *strOut;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_END)
|
|||
|
|
{
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "unit", &str, required);
|
|||
|
|
/*if (!strcmpi(str,"s"))*/
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_gse->MinTime = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
static ST_VOID _GSE_MaxTime_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_CHAR *str;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
ST_CHAR *strOut;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_END)
|
|||
|
|
{
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "unit", &str, required);
|
|||
|
|
/*if (!strcmpi(str,"s"))*/
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_gse->MaxTime = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SMV_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SMV_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* NOTE: save ptr in sclDecCtrl->scl_smv to use later in parsing. */
|
|||
|
|
sclDecCtrl->scl_smv = scl_smv_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (sclDecCtrl->scl_smv == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_smv_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "ldInst", sclDecCtrl->scl_smv->ldInst, (sizeof(sclDecCtrl->scl_smv->ldInst)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "cbName", sclDecCtrl->scl_smv->cbName, (sizeof(sclDecCtrl->scl_smv->cbName)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
if (ret)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "SMV", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_push (sxDecCtrl, sizeof(SMVElements)/sizeof(SX_ELEMENT),
|
|||
|
|
SMVElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SMV_Address_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SMV_Address_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sx_push (sxDecCtrl, sizeof(SMVAddressElements)/sizeof(SX_ELEMENT),
|
|||
|
|
SMVAddressElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SMV_Address_P_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SMV_Address_P_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_CHAR *str;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
ST_CHAR *strOut;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_END)
|
|||
|
|
{
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "type", &str, required);
|
|||
|
|
if (!strcmpi(str,"MAC-Address"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (convert_mac (sclDecCtrl->scl_smv->MAC,strOut))
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR1 ("Illegal MAC Address '%s'", strOut);
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_SMV_Address_P_SEFun", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (!strcmpi(str,"APPID"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_smv->APPID = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
else if (!strcmpi(str,"VLAN-PRIORITY"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_smv->VLANPRI = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
else if (!strcmpi(str,"VLAN-ID"))
|
|||
|
|
{
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &strOut, &strLen);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_smv->VLANID = atoi(strOut);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* IED_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
char icd_ied_type[65];
|
|||
|
|
static ST_VOID _IED_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "name", &str, required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (strcmp(str, sclDecCtrl->iedName) == 0)
|
|||
|
|
{
|
|||
|
|
icd_ied_type[0] = 0;
|
|||
|
|
scl_get_attr_copy (sxDecCtrl, "type", &icd_ied_type[0], 64, 0); /*renxiaobao add 20151218*/
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: IED 'name' match found: %s", str);
|
|||
|
|
sclDecCtrl->iedNameMatched = SD_TRUE;
|
|||
|
|
sx_push (sxDecCtrl, sizeof(IEDElements)/sizeof(SX_ELEMENT), IEDElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: IED 'name' found (%s), not a match", str);
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (sclDecCtrl->iedNameMatched == SD_TRUE)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl->iedNameMatched = SD_FALSE;
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _AccessPoint_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _AccessPoint_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "name", &str, required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (strcmp(str, sclDecCtrl->accessPointName) == 0)
|
|||
|
|
{
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: AccessPoint 'name' match found: %s", str);
|
|||
|
|
sclDecCtrl->accessPointFound = SD_TRUE; /*NOTE: only get here if IED also found*/
|
|||
|
|
sclDecCtrl->accessPointMatched = SD_TRUE;
|
|||
|
|
sx_push (sxDecCtrl, sizeof(AccessPointElements)/sizeof(SX_ELEMENT), AccessPointElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: AccessPoint 'name' found (%s), not a match", str);
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
if (sclDecCtrl->accessPointMatched == SD_TRUE)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl->accessPointMatched = SD_FALSE;
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _Server_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _Server_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sx_push (sxDecCtrl, sizeof(ServerElements)/sizeof(SX_ELEMENT), ServerElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _LDevice_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _LDevice_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_INFO *scl_info;
|
|||
|
|
SCL_LD *scl_ld;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_ld = sclDecCtrl->scl_ld = scl_ld_create (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_ld == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_ld_create", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_ld->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "inst", scl_ld->inst, (sizeof(scl_ld->inst)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return; /* At least one required attr not found. Stop now. */
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(LDeviceElements)/sizeof(SX_ELEMENT), LDeviceElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{ /* reason == SX_ELEMENT_END */
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
scl_info = sclDecCtrl->sclInfo;
|
|||
|
|
scl_ld = sclDecCtrl->scl_ld;
|
|||
|
|
/* Construct MMS Domain name from scl info. */
|
|||
|
|
/* ASSUME nameStructure="IEDName" (domain name = IED name + LDevice inst)*/
|
|||
|
|
/* nameStructure="FuncName" is OBSOLETE. */
|
|||
|
|
if (strlen(scl_info->iedName) + strlen(scl_ld->inst) <= MAX_IDENT_LEN)
|
|||
|
|
{
|
|||
|
|
strcpy (scl_ld->domName, scl_info->iedName); /* construct domain name*/
|
|||
|
|
strcat (scl_ld->domName, scl_ld->inst);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR0 ("Cannot create LD: constructed domain name too long");
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_LDevice_SEFun", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _LN_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _LN_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret,ret1;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_LN *scl_ln;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_ln = sclDecCtrl->scl_ln = scl_ln_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_ln == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_ln_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_ln->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "prefix", scl_ln->prefix, (sizeof(scl_ln->prefix)-1), required);
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "lnType", scl_ln->lnType, (sizeof(scl_ln->lnType)-1), required);
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* ret |= scl_get_attr_copy (sxDecCtrl, "inst", scl_ln->inst, (sizeof(scl_ln->inst)-1), required); renxiaobao remove*/
|
|||
|
|
/* scl_ln->inst ="";*/
|
|||
|
|
/* ret |= */
|
|||
|
|
scl_get_attr_copy (sxDecCtrl, "inst", scl_ln->inst, (sizeof(scl_ln->inst)-1), SD_FALSE);
|
|||
|
|
|
|||
|
|
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "lnClass", scl_ln->lnClass, (sizeof(scl_ln->lnClass)-1), required);
|
|||
|
|
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return;
|
|||
|
|
|
|||
|
|
if (stricmp(sxDecCtrl->sxDecElInfo.tag, "LN0") == 0 &&
|
|||
|
|
stricmp(scl_ln->lnClass, "LLN0") != 0)
|
|||
|
|
{
|
|||
|
|
sxDecCtrl->errCode = SX_USER_ERROR;
|
|||
|
|
sxDecCtrl->termFlag = SD_TRUE;
|
|||
|
|
SXLOG_ERR0 ("SCL PARSE: Attribute 'lnClass' of element 'LN0' has a value other then 'LLN0' (schema violation).");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
if (stricmp(sxDecCtrl->sxDecElInfo.tag, "LN0") == 0)
|
|||
|
|
sx_push (sxDecCtrl, sizeof(LN0Elements)/sizeof(SX_ELEMENT), LN0Elements, SD_FALSE);
|
|||
|
|
else
|
|||
|
|
sx_push (sxDecCtrl, sizeof(LNElements)/sizeof(SX_ELEMENT), LNElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{ /* reason == SX_ELEMENT_END */
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
scl_ln = sclDecCtrl->scl_ln;
|
|||
|
|
/* Construct MMS Variable name from scl info. */
|
|||
|
|
if (strlen (scl_ln->lnClass) != 4)
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR1 ("Illegal lnClass='%s'. Must be exactly 4 char",
|
|||
|
|
scl_ln->lnClass);
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_LN_SEFun", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
else if (strlen (scl_ln->prefix) + strlen (scl_ln->inst) > 11)
|
|||
|
|
{
|
|||
|
|
/* NOTE: standard only allows max=7, but we want to be more forgiving.*/
|
|||
|
|
SXLOG_ERR3 ("Illegal definition for lnClass='%s': prefix (%s) plus inst (%s) > 11 char.",
|
|||
|
|
scl_ln->lnClass, scl_ln->prefix, scl_ln->inst);
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_LN_SEFun", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
strcpy (scl_ln->varName, scl_ln->prefix);
|
|||
|
|
strcat (scl_ln->varName, scl_ln->lnClass);
|
|||
|
|
strcat (scl_ln->varName, scl_ln->inst);
|
|||
|
|
}
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DataSet_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DataSet_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_DATASET *scl_dataset;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_dataset = scl_dataset_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_dataset == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_dataset_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_dataset->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_dataset->name, (sizeof(scl_dataset->name)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return;
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(DataSetElements)/sizeof(SX_ELEMENT), DataSetElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _FCDA_SFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _FCDA_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_INFO *scl_info;
|
|||
|
|
SCL_FCDA *scl_fcda;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
scl_info = sclDecCtrl->sclInfo;
|
|||
|
|
|
|||
|
|
scl_fcda = scl_fcda_add (scl_info);
|
|||
|
|
if (scl_fcda == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_fcda_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "ldInst", scl_fcda->ldInst, (sizeof(scl_fcda->ldInst)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "prefix", scl_fcda->prefix, (sizeof(scl_fcda->prefix)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "lnInst", scl_fcda->lnInst, (sizeof(scl_fcda->lnInst)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "lnClass", scl_fcda->lnClass, (sizeof(scl_fcda->lnClass)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "doName", scl_fcda->doName, (sizeof(scl_fcda->doName)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "daName", scl_fcda->daName, (sizeof(scl_fcda->daName)-1), required);
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "fc", scl_fcda->fc, (sizeof(scl_fcda->fc)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return;
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
/* Construct domain name from SCL info */
|
|||
|
|
/* ASSUME nameStructure="IEDName" (domain name = IED name + LDevice inst)*/
|
|||
|
|
/* nameStructure="FuncName" is OBSOLETE. */
|
|||
|
|
if (strlen(scl_info->iedName) + strlen(scl_fcda->ldInst) <= MAX_IDENT_LEN)
|
|||
|
|
{
|
|||
|
|
strcpy (scl_fcda->domName, scl_info->iedName);
|
|||
|
|
strcat (scl_fcda->domName, scl_fcda->ldInst);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR0 ("Cannot add FCDA: constructed domain name too long");
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_FCDA_SFun", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _ReportControl_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _ReportControl_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* Alloc struct, save ptr in sclDecCtrl, & set local ptr to it. */
|
|||
|
|
SCL_RCB *scl_rcb = sclDecCtrl->scl_rcb = scl_rcb_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_rcb == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_rcb_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_rcb->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_rcb->datSet, (sizeof(scl_rcb->datSet)-1), required);
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "intgPd", &scl_rcb->intgPd, required);
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "bufTime", &scl_rcb->bufTime, required);
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "buffered", &str, required);
|
|||
|
|
|
|||
|
|
scl_rcb->buffered = SD_FALSE; /* default */
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
scl_rcb->buffered = SD_TRUE;
|
|||
|
|
}
|
|||
|
|
/* NOTE: we only accept default value of indexed="true". */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "indexed", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "false") == 0)
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR0 ("ReportControl attribute indexed='false' not supported");
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_rcb_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_rcb->name, (sizeof(scl_rcb->name)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "rptID", scl_rcb->rptID, (sizeof(scl_rcb->rptID)-1), required);
|
|||
|
|
ret |= scl_get_uint_attr (sxDecCtrl, "confRev", &scl_rcb->confRev, required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return;
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(ReportControlElements)/sizeof(SX_ELEMENT), ReportControlElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
/* CRITICAL: Copy TrgOps to scl_rcb. */
|
|||
|
|
sclDecCtrl->scl_rcb->TrgOps[0] = sclDecCtrl->TrgOps[0];
|
|||
|
|
/* If "RptEnabled max" not configured, set default value*/
|
|||
|
|
if (sclDecCtrl->scl_rcb->maxClient == 0)
|
|||
|
|
sclDecCtrl->scl_rcb->maxClient = 1; /* default */
|
|||
|
|
/* NOTE: scl_rcb is all filled in now */
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _LogControl_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _LogControl_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* Alloc struct, save ptr in sclDecCtrl, & set local ptr to it. */
|
|||
|
|
SCL_LCB *scl_lcb = sclDecCtrl->scl_lcb = scl_lcb_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_lcb == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_lcb_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_lcb->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "intgPd", &scl_lcb->intgPd, required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_lcb->datSet, (sizeof(scl_lcb->datSet)-1), required);
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "logEna", &str, required);
|
|||
|
|
scl_lcb->logEna = SD_FALSE; /* default */
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
scl_lcb->logEna = SD_TRUE;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "reasonCode", &str, required);
|
|||
|
|
scl_lcb->reasonCode = SD_FALSE; /* default */
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
scl_lcb->reasonCode = SD_TRUE;
|
|||
|
|
}
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_lcb->name, (sizeof(scl_lcb->name)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "logName", scl_lcb->logName, (sizeof(scl_lcb->logName)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return;
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(LogControlElements)/sizeof(SX_ELEMENT), LogControlElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
/* CRITICAL: Copy TrgOps to scl_lcb. */
|
|||
|
|
sclDecCtrl->scl_lcb->TrgOps[0] = sclDecCtrl->TrgOps[0];
|
|||
|
|
/* NOTE: scl_lcb is all filled in now */
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _GSEControl_SFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _GSEControl_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
ST_CHAR *type; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
SCL_GCB *scl_gcb;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_gcb = scl_gcb_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_gcb == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_gcb_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_gcb->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "confRev", &scl_gcb->confRev, required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_gcb->datSet, (sizeof(scl_gcb->datSet)-1), required);
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "type", &type, required);
|
|||
|
|
if (ret == SD_SUCCESS && strcmp(type, "GSSE") == 0)
|
|||
|
|
scl_gcb->isGoose = SD_FALSE;
|
|||
|
|
else
|
|||
|
|
scl_gcb->isGoose = SD_TRUE;
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_gcb->name, (sizeof(scl_gcb->name)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "appID", scl_gcb->appID, (sizeof(scl_gcb->appID)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return;
|
|||
|
|
/* end required attributes */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SettingControl_SFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _SettingControl_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required;
|
|||
|
|
SCL_SGCB *scl_sgcb;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_sgcb = scl_sgcb_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_sgcb == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_sgcb_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
required = SD_FALSE;
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_sgcb->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "actSG", &scl_sgcb->actSG, required);
|
|||
|
|
if (ret)
|
|||
|
|
scl_sgcb->actSG = 1; /* default value */
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "numOfSGs", &scl_sgcb->numOfSGs, required);
|
|||
|
|
/* end required attributes */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _TrgOps_SFun */
|
|||
|
|
/* Save all TrgOps bits in sclDecCtrl->TrgOps. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _TrgOps_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
sclDecCtrl->TrgOps[0] = 0; /* Start with all bits=0 */
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "dchg", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_DATA_CHANGE);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "qchg", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_QUALITY_CHANGE);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "dupd", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_DATA_UPDATE);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "period", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(sclDecCtrl->TrgOps, TRGOPS_BITNUM_INTEGRITY);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/* end optional attributes */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _OptFlds_SFun */
|
|||
|
|
/* Save all OptFlds bits in sclDecCtrl->scl_rcb->OptFlds. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _OptFlds_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
SCL_RCB *scl_rcb;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
scl_rcb = sclDecCtrl->scl_rcb;
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "seqNum", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_SQNUM);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "timeStamp", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_TIMESTAMP);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "dataSet", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_DATSETNAME);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "reasonCode", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_REASON);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "dataRef", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_DATAREF);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "bufOvfl", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_BUFOVFL);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "entryID", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_ENTRYID);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "configRef", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_rcb->OptFlds, OPTFLD_BITNUM_CONFREV);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/* end optional attributes */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _RptEnabled_SFun */
|
|||
|
|
/* Save RptEnabled info in sclDecCtrl->scl_rcb. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _RptEnabled_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
SCL_RCB *scl_rcb;
|
|||
|
|
|
|||
|
|
assert (sxDecCtrl->reason == SX_ELEMENT_START);
|
|||
|
|
scl_rcb = sclDecCtrl->scl_rcb;
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "max", &scl_rcb->maxClient, SCL_ATTR_OPTIONAL);
|
|||
|
|
/* If configured, check for legal value. */
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (scl_rcb->maxClient <= 0 || scl_rcb->maxClient > 99)
|
|||
|
|
{
|
|||
|
|
SXLOG_ERR1 ("RptEnabled max=%d is not valid. Must be value between 1 and 99", scl_rcb->maxClient);
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "RptEnabled", SX_USER_ERROR);
|
|||
|
|
scl_rcb->maxClient = 1; /* set to default just in case user ignores error*/
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DOI_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DOI_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *ix;
|
|||
|
|
ST_CHAR *name;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "ix", &ix, required);
|
|||
|
|
if (ret)
|
|||
|
|
ix = NULL;
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "name", &name, required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
/* Start creation of flattened name */
|
|||
|
|
sclDecCtrl->flattened[0] = '\0'; /* CRITICAL: start with empty flatname*/
|
|||
|
|
if (construct_flattened (sclDecCtrl->flattened, sizeof(sclDecCtrl->flattened), name, ix)
|
|||
|
|
!= SD_SUCCESS)
|
|||
|
|
{ /* error already logged. */
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_DOI_SEFun", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: Created flattened variable: '%s'", sclDecCtrl->flattened);
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(DOIElements)/sizeof(SX_ELEMENT), DOIElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SDI_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _SDI_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *ix;
|
|||
|
|
ST_CHAR *name;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_CHAR *p;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "ix", &ix, required);
|
|||
|
|
if (ret)
|
|||
|
|
ix = NULL;
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "name", &name, required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
/* Continue creation of flattened name */
|
|||
|
|
if (construct_flattened (sclDecCtrl->flattened, sizeof(sclDecCtrl->flattened), name, ix)
|
|||
|
|
!= SD_SUCCESS)
|
|||
|
|
{ /* error already logged. */
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_SDI_SEFun", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: Appended to flattened variable: '%s'", sclDecCtrl->flattened);
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(SDIElements)/sizeof(SX_ELEMENT), SDIElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
/* Remove the last item from the flattened string */
|
|||
|
|
p = strrchr(sclDecCtrl->flattened, '$');
|
|||
|
|
if (p != NULL)
|
|||
|
|
*p = 0;
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: Removed last item from flattened variable: '%s'", sclDecCtrl->flattened);
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DAI_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DAI_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *ix;
|
|||
|
|
ST_CHAR *name;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_CHAR *p;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_DAI *scl_dai;
|
|||
|
|
if ((scl_dai = sclDecCtrl->scl_dai = scl_dai_add (sclDecCtrl->sclInfo)) == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_enumtype_create", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "ix", &ix, required);
|
|||
|
|
if (ret)
|
|||
|
|
ix = NULL;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "sAddr", scl_dai->sAddr, (sizeof(scl_dai->sAddr)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "valKind", scl_dai->valKind, (sizeof(scl_dai->valKind)-1), required);
|
|||
|
|
if (ret)
|
|||
|
|
strcpy (scl_dai->valKind, "Set"); /* default */
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "name", &name, required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
/* Continue creation of flattened name */
|
|||
|
|
if (construct_flattened (sclDecCtrl->flattened, sizeof(sclDecCtrl->flattened), name, ix)
|
|||
|
|
!= SD_SUCCESS)
|
|||
|
|
{ /* error already logged. */
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_DAI_SEFun", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: Appended to flattened variable: '%s'", sclDecCtrl->flattened);
|
|||
|
|
strcpy (scl_dai->flattened, sclDecCtrl->flattened);
|
|||
|
|
sx_push (sxDecCtrl, sizeof(DAIElements)/sizeof(SX_ELEMENT), DAIElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
/* Remove the last item from the flattened string */
|
|||
|
|
p = strrchr(sclDecCtrl->flattened, '$');
|
|||
|
|
if (p != NULL)
|
|||
|
|
*p = 0;
|
|||
|
|
SXLOG_CDEC1 ("SCL PARSE: Removed last item from flattened variable: '%s'", sclDecCtrl->flattened);
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DAI_Val_SEFun */
|
|||
|
|
/* Sets "sGroup" and "Val" in sclDecCtrl->scl_dai. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DAI_Val_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
/* start optional attributes (don't care about return) */
|
|||
|
|
scl_get_uint_attr (sxDecCtrl, "sGroup", &sclDecCtrl->scl_dai->sGroup, SCL_ATTR_OPTIONAL);
|
|||
|
|
/* end optional attributes */
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
ST_CHAR *Val;
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &Val, &strLen);
|
|||
|
|
if (ret==SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_dai->Val = chk_strdup (Val); /* alloc & store Val*/
|
|||
|
|
else
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "DAI Val", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DataTypeTemplates_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DataTypeTemplates_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
sx_push (sxDecCtrl, sizeof(DataTypeTemplatesElements)/sizeof(SX_ELEMENT), DataTypeTemplatesElements, SD_FALSE);
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _LNodeType_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _LNodeType_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_LNTYPE *scl_lntype;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_lntype = scl_lntype_create (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_lntype == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_lntype_create", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "id", scl_lntype->id, (sizeof(scl_lntype->id)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "lnClass", scl_lntype->lnClass, (sizeof(scl_lntype->lnClass)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(LNodeTypeElements)/sizeof(SX_ELEMENT), LNodeTypeElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DO_SFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DO_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_DO *scl_do;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_do = scl_lntype_add_do (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_do == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_lntype_add_do", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_do->name, (sizeof(scl_do->name)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "type", scl_do->type, (sizeof(scl_do->type)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DOType_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DOType_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_DOTYPE *scl_dotype;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_dotype = scl_dotype_create (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_dotype == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_dotype_create", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "id", scl_dotype->id, (sizeof(scl_dotype->id)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "cdc", scl_dotype->cdc, (sizeof(scl_dotype->cdc)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(DOTypeElements)/sizeof(SX_ELEMENT), DOTypeElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DA_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DA_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* use for dchg, qchg, dupd */
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_DA *scl_da;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_da = sclDecCtrl->scl_da = scl_dotype_add_da (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_da == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_dotype_add_da", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_da->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "sAddr", scl_da->sAddr, (sizeof(scl_da->sAddr)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "valKind", scl_da->valKind, (sizeof(scl_da->valKind)-1), required);
|
|||
|
|
if (ret)
|
|||
|
|
strcpy (scl_da->valKind, "Set"); /* default */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "type", scl_da->type, (sizeof(scl_da->type)-1), required);
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "count", &scl_da->count, required);
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "dchg", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
scl_da->dchg = SD_TRUE;
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "qchg", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
scl_da->qchg = SD_TRUE;
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "dupd", &str, required);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
scl_da->dupd = SD_TRUE;
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_da->name, (sizeof(scl_da->name)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "bType", scl_da->bType, (sizeof(scl_da->bType)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "fc", scl_da->fc, (sizeof(scl_da->fc)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
sx_push (sxDecCtrl, sizeof(DAElements)/sizeof(SX_ELEMENT), DAElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SDO_SFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _SDO_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_DA *scl_da;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_da = scl_dotype_add_sdo (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_da == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_dotype_add_sdo", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_da->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_da->name, (sizeof(scl_da->name)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "type", scl_da->type, (sizeof(scl_da->type)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DA_Val_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
/* start optional attributes (don't care about return) */
|
|||
|
|
scl_get_uint_attr (sxDecCtrl, "sGroup", &sclDecCtrl->scl_da->sGroup, SCL_ATTR_OPTIONAL);
|
|||
|
|
/* end optional attributes */
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
ST_CHAR *Val;
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &Val, &strLen);
|
|||
|
|
if (ret==SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_da->Val = chk_strdup (Val); /* alloc & store Val*/
|
|||
|
|
else
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "DA Val", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _DAType_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _DAType_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_DATYPE *scl_datype;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_datype = scl_datype_create (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_datype == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_datype_create", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "id", scl_datype->id, (sizeof(scl_datype->id)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(DATypeElements)/sizeof(SX_ELEMENT), DATypeElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _BDA_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _BDA_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_BDA *scl_bda;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
scl_bda = sclDecCtrl->scl_bda = scl_datype_add_bda (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_bda == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_datype_add_bda", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, required);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_bda->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "sAddr", scl_bda->sAddr, (sizeof(scl_bda->sAddr)-1), required);
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "valKind", scl_bda->valKind, (sizeof(scl_bda->valKind)-1), required);
|
|||
|
|
if (ret)
|
|||
|
|
strcpy (scl_bda->valKind, "Set"); /* default */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "type", scl_bda->type, (sizeof(scl_bda->type)-1), required);
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "count", &scl_bda->count, required);
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_bda->name, (sizeof(scl_bda->name)-1), required);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "bType", scl_bda->bType, (sizeof(scl_bda->bType)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
sx_push (sxDecCtrl, sizeof(BDAElements)/sizeof(SX_ELEMENT), BDAElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _BDA_Val_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _BDA_Val_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
/* start optional attributes (don't care about return) */
|
|||
|
|
scl_get_uint_attr (sxDecCtrl, "sGroup", &sclDecCtrl->scl_bda->sGroup, SCL_ATTR_OPTIONAL);
|
|||
|
|
/* end optional attributes */
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
ST_CHAR *Val;
|
|||
|
|
ret = sx_get_string_ptr (sxDecCtrl, &Val, &strLen);
|
|||
|
|
if (ret==SD_SUCCESS)
|
|||
|
|
sclDecCtrl->scl_bda->Val = chk_strdup (Val); /* alloc & store Val*/
|
|||
|
|
else
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "BDA Val", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _EnumType_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _EnumType_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_ENUMTYPE *scl_enumtype;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if ((scl_enumtype = scl_enumtype_create (sclDecCtrl->sclInfo)) == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_enumtype_create", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "id", scl_enumtype->id, (sizeof(scl_enumtype->id)-1), required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(EnumTypeElements)/sizeof(SX_ELEMENT), EnumTypeElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _EnumVal_SEFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_VOID _EnumVal_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_RET ret;
|
|||
|
|
ST_INT strLen;
|
|||
|
|
ST_BOOLEAN required = SD_FALSE;
|
|||
|
|
SCL_ENUMVAL *scl_enumval;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
{
|
|||
|
|
if ((scl_enumval = sclDecCtrl->scl_enumval = scl_enumtype_add_enumval (sclDecCtrl->sclInfo)) == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_enumtype_add_enumval", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
required = SD_TRUE;
|
|||
|
|
ret = scl_get_int_attr (sxDecCtrl, "ord", &scl_enumval->ord, required);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
/* end required attributes */
|
|||
|
|
}
|
|||
|
|
else /* reason = SX_ELEMENT_END */
|
|||
|
|
{
|
|||
|
|
scl_enumval = sclDecCtrl->scl_enumval;
|
|||
|
|
/* CRITICAL: Init strLen = max len. After sx_get_string, strLen = actual len*/
|
|||
|
|
strLen = sizeof(scl_enumval->EnumVal)-1;
|
|||
|
|
ret = sx_get_string (sxDecCtrl, scl_enumval->EnumVal, &strLen);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "_EnumVal_SEFun", SX_USER_ERROR);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _scl_unknown_el_start */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_RET _scl_unknown_el_start (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)
|
|||
|
|
{
|
|||
|
|
SXLOG_DEC1 ("SCL PARSE: Unneeded or unknown element '%s'", tag);
|
|||
|
|
return (SD_SUCCESS);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _scl_unknown_el_end */
|
|||
|
|
/************************************************************************/
|
|||
|
|
|
|||
|
|
static ST_RET _scl_unknown_el_end (SX_DEC_CTRL *sxDecCtrl, ST_CHAR *tag)
|
|||
|
|
{
|
|||
|
|
return (SD_SUCCESS);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SampledValueControl_SEFun */
|
|||
|
|
/* DEBUG: if parser called separate start and end functions, the lower */
|
|||
|
|
/* functs could be called directly & this funct would not be needed. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SampledValueControl_SEFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
if (sxDecCtrl->reason == SX_ELEMENT_START)
|
|||
|
|
_SampledValueControl_SFun (sxDecCtrl);
|
|||
|
|
else
|
|||
|
|
_SampledValueControl_EFun (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SampledValueControl_SFun */
|
|||
|
|
/* Handle Start tag */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SampledValueControl_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
SCL_SVCB *scl_svcb;
|
|||
|
|
ST_CHAR *desc;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
|
|||
|
|
/* Alloc struct, save in sclDecCtrl, & set local ptr to it. */
|
|||
|
|
scl_svcb = sclDecCtrl->scl_svcb = scl_svcb_add (sclDecCtrl->sclInfo);
|
|||
|
|
if (scl_svcb == NULL)
|
|||
|
|
{
|
|||
|
|
scl_stop_parsing (sxDecCtrl, "scl_svcb_add", SX_USER_ERROR);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* start required attributes */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "name", scl_svcb->name, (sizeof(scl_svcb->name)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
ret |= scl_get_attr_copy (sxDecCtrl, "smvID", scl_svcb->smvID, (sizeof(scl_svcb->smvID)-1), SCL_ATTR_REQUIRED);
|
|||
|
|
ret |= scl_get_uint_attr (sxDecCtrl, "smpRate", &scl_svcb->smpRate, SCL_ATTR_REQUIRED);
|
|||
|
|
ret |= scl_get_uint_attr (sxDecCtrl, "nofASDU", &scl_svcb->nofASDU, SCL_ATTR_REQUIRED);
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
return; /* At least one required attr not found. Stop now. */
|
|||
|
|
/* end required attributes */
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "desc", &desc, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
scl_svcb->desc = chk_strdup (desc); /* Alloc & copy desc string */
|
|||
|
|
ret = scl_get_attr_copy (sxDecCtrl, "datSet", scl_svcb->datSet, (sizeof(scl_svcb->datSet)-1), SCL_ATTR_OPTIONAL);
|
|||
|
|
ret = scl_get_uint_attr (sxDecCtrl, "confRev", &scl_svcb->confRev, SCL_ATTR_OPTIONAL);
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "multicast", &str, SCL_ATTR_OPTIONAL); /* chk "str" below*/
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "false") == 0)
|
|||
|
|
scl_svcb->multicast = SD_FALSE;
|
|||
|
|
else
|
|||
|
|
scl_svcb->multicast = SD_TRUE; /* default value */
|
|||
|
|
/* end optional attributes */
|
|||
|
|
|
|||
|
|
sx_push (sxDecCtrl, sizeof(SampledValueControlElements)/sizeof(SX_ELEMENT), SampledValueControlElements, SD_FALSE);
|
|||
|
|
}
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SampledValueControl_EFun */
|
|||
|
|
/* Handle End tag */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SampledValueControl_EFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
sx_pop (sxDecCtrl);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* _SmvOpts_SFun */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_VOID _SmvOpts_SFun (SX_DEC_CTRL *sxDecCtrl)
|
|||
|
|
{
|
|||
|
|
SCL_DEC_CTRL *sclDecCtrl;
|
|||
|
|
ST_CHAR *str; /* ptr set by scl_get_attr_ptr */
|
|||
|
|
ST_RET ret;
|
|||
|
|
SCL_SVCB *scl_svcb;
|
|||
|
|
|
|||
|
|
sclDecCtrl = (SCL_DEC_CTRL *) sxDecCtrl->usr;
|
|||
|
|
scl_svcb = sclDecCtrl->scl_svcb;
|
|||
|
|
|
|||
|
|
/* start optional attributes */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "sampleRate", &str, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_svcb->OptFlds, SVOPT_BITNUM_SMPRATE);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "refreshTime", &str, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_svcb->OptFlds, SVOPT_BITNUM_REFRTM);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "sampleSynchronized", &str, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
{
|
|||
|
|
BSTR_BIT_SET_ON(scl_svcb->OptFlds, SVOPT_BITNUM_SMPSYNCH);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "security", &str, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
scl_svcb->securityPres = SD_TRUE; /* scl_svcb calloced so init val is FALSE*/
|
|||
|
|
|
|||
|
|
/* NOTE: SCL calls this "dataRef", but 7-2 & 9-2 call it "DatSet". */
|
|||
|
|
ret = scl_get_attr_ptr (sxDecCtrl, "dataRef", &str, SCL_ATTR_OPTIONAL);
|
|||
|
|
if (ret == SD_SUCCESS && stricmp(str, "true") == 0)
|
|||
|
|
scl_svcb->dataRefPres = SD_TRUE; /* scl_svcb calloced so init val is FALSE*/
|
|||
|
|
/* end optional attributes */
|
|||
|
|
}
|