Files
microser/mmslib/util/sclparse.c
2026-06-15 15:48:16 +08:00

2508 lines
84 KiB
C
Raw Blame History

/************************************************************************/
/* 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 */
}