?? sclproc.c
字號(hào):
ST_INT type_id;
MVL_VAR_ASSOC *var_assoc;
OBJECT_NAME object_name;
ST_VOID *data; /* buffer to store logical node data. Allocated here.*/
MVL_TYPE_CTRL *type_ctrl;
ST_RET retcode;
ST_CHAR type_name[MAX_IDENT_LEN+2]; /* one extra byte for NULL, another to catch if limit exceeded*/
retcode = SD_FAILURE; /* assume failure */
/* Generate type_name. */
/*if (scl_ln->rcbHead )*/
if (scl_ln->rcbHead || scl_ln->lcbHead || scl_ln->gcbHead || scl_ln->sgcbHead || scl_ln->svcbHead)
{ /* If LN contains control blocks, use custom type. */
unique_type_name (scl_ld, scl_ln, type_name, sizeof (type_name));
}
else
strcpy (type_name, scl_ln->lnType); /* no RCBs. Use LNType "id".*/
/* Get typeid from type name */
type_id = mvl_typename_to_typeid (type_name);
if (type_id < 0)
SXLOG_ERR2 ("Cannot find type='%s' for logical node='%s'", scl_ln->lnType, scl_ln->varName);
else
{
/* CRITICAL: alloc buffer to store "data". All data for this LN stored here.*/
/* This data buffer constitutes the "Data Cache" described in Design Doc. */
/* NOTE: type_ctrl->data_size==type_ctrl->rt_ctrl->rt_first->offset_to_last*/
type_ctrl = mvl_type_ctrl_find (type_id);
data = chk_calloc (1, type_ctrl->data_size);
/* Construct object name from LD & LN info. */
object_name.object_tag = DOM_SPEC; /* ALWAYS Domain specific */
object_name.domain_id = scl_ld->domName;
object_name.obj_name.vmd_spec = scl_ln->varName;
/* Create the MMS variable (Logical Node). */
var_assoc = mvl_var_add (&object_name,
NULL, /* MVL_NET_INFO * */
type_id,
data,
NULL, /* MVL_VAR_PROC * */
SD_TRUE); /* ALWAYS copy name to var_assoc */
if (var_assoc == NULL)
SXLOG_ERR2 ("Cannot create LN='%s' in LD='%s'", scl_ln->varName, scl_ld->domName);
else
{
var_assoc->flags = MVL_VAR_FLAG_UCA; /* CRITICAL: must make it a UCA variable*/
/* NOTE: var_assoc->use_static_data flag is automatically set */
/* by mvl_var_add because data is never NULL. */
scl_ln->mvl_var_assoc = var_assoc; /* save var_assoc for later*/
retcode = SD_SUCCESS;
}
}
return (retcode);
}
/************************************************************************/
/* scl2_dataset_create */
/* Create one DataSet (SCL_DATASET) for this Logical Node (SCL_LN). */
/* A DataSet maps to a MMS NamedVariableList (NVL). */
/* The MMS NVL name follows the form "LogicalNodeName$DataSetName". */
/* RETURNS: SD_SUCCESS or error code */
/************************************************************************/
static ST_RET scl2_dataset_create (
SCL_LD *scl_ld,
SCL_LN *scl_ln,
SCL_DATASET *scl_dataset)
{
OBJECT_NAME nvl_obj;
MVL_NVLIST_CTRL *nvlist_ctrl;
OBJECT_NAME *var_obj; /* array of var names */
SCL_FCDA *scl_fcda;
ST_RET ret;
/* allow extra char in var_name so strncat can go beyond limit. If it does, return error.*/
ST_CHAR *var_name_buf; /* one buf allocated to hold all var names */
ST_CHAR *var_name; /* ptr to current name being constructed */
ST_CHAR *dot_ptr; /* ptr to '.' within var_name */
ST_CHAR nvl_name [MAX_IDENT_LEN+1]; /* one extra byte for NULL */
ST_INT num_var = 0;
ret = SD_SUCCESS; /* assume success */
/* Construct NVL object name from LD, LN, and DataSet info. */
if (strlen (scl_ln->prefix) + strlen (scl_ln->lnClass) + strlen (scl_ln->inst)
+ strlen (scl_dataset->name) + 1 > MAX_IDENT_LEN)
{
SXLOG_ERR1 ("Constructed NVL name would be too long for dataset '%s'.", scl_dataset->name);
return (SD_FAILURE);
}
sprintf (nvl_name, "%s%s%s$%s", scl_ln->prefix, scl_ln->lnClass, scl_ln->inst, scl_dataset->name);
nvl_obj.object_tag = DOM_SPEC; /* ALWAYS Domain specific */
nvl_obj.domain_id = scl_ld->domName;
nvl_obj.obj_name.vmd_spec = nvl_name; /* use constructed NVL name */
/* Go through list once just to count number of variables. */
for (scl_fcda = (SCL_FCDA *) list_find_last ((DBL_LNK *) scl_dataset->fcdaHead);
scl_fcda != NULL;
scl_fcda = (SCL_FCDA *) list_find_prev ((DBL_LNK *) scl_dataset->fcdaHead, (DBL_LNK *) scl_fcda))
{
num_var++;
}
/* Allocate var_obj array. */
var_obj = chk_calloc (num_var, sizeof (OBJECT_NAME));
/* NOTE: this is a bit tricky. OBJECT_NAME struct contains only a ptr
* to name, no storage. Need to allocate storage for names. Here we
* allocate one big buffer for all names. In the loop below,
* we use part of this buffer for each name.
*/
var_name_buf = chk_calloc (num_var, MAX_IDENT_LEN+2); /* Note +2 for NULL plus extra char*/
/* Go through list again to fill in var_obj array. */
num_var = 0;
for (scl_fcda = (SCL_FCDA *) list_find_last ((DBL_LNK *) scl_dataset->fcdaHead);
scl_fcda != NULL;
scl_fcda = (SCL_FCDA *) list_find_prev ((DBL_LNK *) scl_dataset->fcdaHead, (DBL_LNK *) scl_fcda))
{
/* Set "var_name" pointing to proper section of big buffer. */
var_name = var_name_buf + num_var*(MAX_IDENT_LEN+2);
/* Fill in "var_name". */
strncpy (var_name, scl_fcda->prefix, MAX_IDENT_LEN+1);
strncat (var_name, scl_fcda->lnClass, MAX_IDENT_LEN+1-strlen(var_name));
strncat (var_name, scl_fcda->lnInst, MAX_IDENT_LEN+1-strlen(var_name));
strncat (var_name, "$", MAX_IDENT_LEN+1-strlen(var_name));
strncat (var_name, scl_fcda->fc, MAX_IDENT_LEN+1-strlen(var_name));
if (strlen (scl_fcda->doName))
{
strncat (var_name, "$", MAX_IDENT_LEN+1-strlen(var_name));
strncat (var_name, scl_fcda->doName, MAX_IDENT_LEN+1-strlen(var_name));
}
if (strlen (scl_fcda->daName))
{
strncat (var_name, "$", MAX_IDENT_LEN+1-strlen(var_name));
strncat (var_name, scl_fcda->daName, MAX_IDENT_LEN+1-strlen(var_name));
}
/* doName or daName may contain '.'. Each '.' must be replaced with '$'.*/
dot_ptr = var_name;
while ((dot_ptr = strchr (dot_ptr, '.')) != NULL)
*dot_ptr++ = '$';
if (strlen (var_name) > MAX_IDENT_LEN)
{
SXLOG_ERR1 ("Variable name generated from FCDA info too long '%s'", var_name);
ret = SD_FAILURE;
break; /* stop looping */
}
/* var_name generated, now fill in this "var_obj". */
var_obj[num_var].object_tag = DOM_SPEC; /* ALWAYS Domain specific */
var_obj[num_var].domain_id = scl_fcda->domName;
var_obj[num_var].obj_name.vmd_spec = var_name;
num_var++;
}
if (ret == SD_SUCCESS)
{
nvlist_ctrl = mvl_nvl_add (&nvl_obj, NULL, num_var, var_obj, SD_TRUE);
if (nvlist_ctrl)
ret = SD_SUCCESS;
else
ret = SD_FAILURE;
}
/* NOTE: can free these now because mvl_nvl_add copied this info.*/
chk_free (var_obj);
chk_free (var_name_buf);
return (ret);
}
/************************************************************************/
/* scl2_dataset_create_all */
/* Create all DataSets (SCL_DATASET) for this Logical Node (SCL_LN). */
/* RETURNS: SD_SUCCESS or error code */
/************************************************************************/
static ST_RET scl2_dataset_create_all (
SCL_LD *scl_ld,
SCL_LN *scl_ln)
{
SCL_DATASET *scl_dataset;
ST_RET ret;
ret = SD_SUCCESS; /* assume success */
/* NOTE: linked list is in reverse order from data in SCL file, */
/* so get off list in reverse order. */
for (scl_dataset = (SCL_DATASET *) list_find_last ((DBL_LNK *) scl_ln->datasetHead);
scl_dataset != NULL;
scl_dataset = (SCL_DATASET *) list_find_prev ((DBL_LNK *) scl_ln->datasetHead, (DBL_LNK *) scl_dataset))
{
ret = scl2_dataset_create (scl_ld, scl_ln, scl_dataset);
if (ret)
{
SXLOG_ERR3 ("scl2_dataset_create FAILED for '%s' (LD=%s LN=%s)",
scl_dataset->name, scl_ld->domName, scl_ln->varName);
break; /* if one fails, stop processing */
}
else
{
SXLOG_FLOW3 ("scl2_dataset_create DONE for '%s' (LD=%s LN=%s)",
scl_dataset->name, scl_ld->domName, scl_ln->varName);
}
}
return (ret);
}
/************************************************************************/
/* scl2_rcb_create */
/* RETURNS: SD_SUCCESS or error code */
/************************************************************************/
static ST_RET scl2_rcb_create (
SCL_INFO *scl_info,
SCL_LD *scl_ld,
SCL_LN *scl_ln,
SCL_RCB *scl_rcb,
SCL_RCB_COUNTERS *scl_rcb_counters,
ST_UINT reportScanRate) /* report scan rate (millisec) */
{
ST_RET ret;
MVLU_RPT_CTRL *rpt_ctrl;
ST_CHAR basrcb_var_name [MAX_IDENT_LEN + 1];
ST_CHAR basrcb_type_name [MAX_IDENT_LEN + 1]; /* for setting leaf functions*/
ST_CHAR leaf_name [MAX_IDENT_LEN + 1];
MVL_VAR_ASSOC *base_va;
ST_INT rcb_type;
ST_INT buftim_action;
OBJECT_NAME base_var_oname;
OBJECT_NAME nvl_oname;
MVL_NVLIST_CTRL *nvl;
SCL_DATASET *scl_dataset;
ST_INT set_flags; /* flags for mvlu_set_leaf_param_name */
ST_CHAR nvl_name [MAX_IDENT_LEN+1];
/* Initialize basrcb_type_name. Add $BR.. or $RP.. later. */
unique_type_name (scl_ld, scl_ln, basrcb_type_name, sizeof (basrcb_type_name));
scl_dataset = scl_find_dataset (scl_ln, scl_rcb->datSet);
if (scl_dataset == NULL)
{
SXLOG_ERR1 ("scl2_rcb_create: datSet='%s' not found", scl_rcb->datSet);
return (SD_FAILURE);
}
if (scl_rcb->buffered)
rcb_type = RCB_TYPE_IEC_BRCB;
else
rcb_type = RCB_TYPE_IEC_URCB;
/* Generate basrcb_var_name from SCL info. The code below should generate a unique
* basrcb_var_name for every RCB in this LN.
*/
strcpy (basrcb_var_name, scl_ln->varName); /* never too long */
if (scl_rcb->buffered)
{
strncat_safe (basrcb_var_name, "$BR$", MAX_IDENT_LEN-strlen(basrcb_var_name));
strncat_safe (basrcb_type_name, "$BR$", MAX_IDENT_LEN-strlen(basrcb_type_name));
}
else
{
strncat_safe (basrcb_var_name, "$RP$", MAX_IDENT_LEN-strlen(basrcb_var_name));
strncat_safe (basrcb_type_name, "$RP$", MAX_IDENT_LEN-strlen(basrcb_type_name));
}
/* Add RCB name (read from SCL file). */
strncat_safe (basrcb_var_name, scl_rcb->name, MAX_IDENT_LEN-strlen(basrcb_var_name));
strncat_safe (basrcb_type_name, scl_rcb->name, MAX_IDENT_LEN-strlen(basrcb_type_name));
/* Make sure there's room for longest suffix */
if (strlen (basrcb_var_name) > (MAX_IDENT_LEN-sizeof("$TimeOfEntry")))
{
SXLOG_ERR1 ("BasRCB variable name '%s' too long", basrcb_var_name);
return (SD_FAILURE);
}
if (strlen (basrcb_type_name) > (MAX_IDENT_LEN-sizeof("$TimeOfEntry")))
{
SXLOG_ERR1 ("BasRCB type name '%s' too long", basrcb_type_name);
return (SD_FAILURE);
}
/* Find the "base_va". Needed as arg to mvlu_create_rpt_ctrl. */
base_var_oname.object_tag = DOM_SPEC;
base_var_oname.domain_id = scl_ld->domName;
base_var_oname.obj_name.item_id = scl_ln->varName;
base_va = mvl_find_va (&base_var_oname);
if (base_va == NULL)
{
SXLOG_ERR1 ("Cannot find base variable='%s' for RCB", scl_ln->varName);
return (SD_FAILURE);
}
/* Construct NVL object name from LD, LN, and DataSet info. */
if (strlen (scl_ln->prefix) + strlen (scl_ln->lnClass) + strlen (scl_ln->inst)
+ strlen (scl_rcb->datSet) + 1 > MAX_IDENT_LEN)
{
SXLOG_ERR1 ("Constructed NVL name would be too long for dataset '%s'.", scl_rcb->datSet);
return (SD_FAILURE);
}
sprintf (nvl_name, "%s%s%s$%s", scl_ln->prefix, scl_ln->lnClass, scl_ln->inst, scl_rcb->datSet);
nvl_oname.object_tag = DOM_SPEC;
nvl_oname.domain_id = scl_ld->domName; /* domain name */
nvl_oname.obj_name.item_id = nvl_name; /* use constructed NVL name */
nvl = mvl_find_nvl (&nvl_oname);
if (nvl == NULL)
{
SXLOG_ERR3 ("Cannot find NVL '%s' in domain '%s' to create RCB '%s'",
nvl_oname.obj_name.item_id,
nvl_oname.domain_id,
basrcb_var_name);
return (SD_FAILURE);
}
/* DEBUG: nothing in SCL to set buftim_action. Is there another way to get this info? */
buftim_action = MVLU_RPT_BUFTIM_SEND_NOW;
/* Set all leaf functions required to implement RCB.
* NOTE: these leaf functions replace the default leaf functions
* set by "u_set_all_leaf_functions" when the datatype was created.
*/
/* Use same flags for all leafs */
set_flags = MVLU_SET_RD_FUN | MVLU_SET_WR_FUN | MVLU_SET_REF;
/* Start with good return value & OR all returns together. If ANY call
* to mvlu_set_leaf_param_name fails, this function will fail.
*/
ret = SD_SUCCESS;
/* CRITICAL: len of basrcb_type_name chked above, so none of these "sprintf"s
* will cause leaf_name to be exceeded.
*/
sprintf (leaf_name, "%s$RptID", basrcb_type_name);
ret |= mvlu_set_leaf_param_name (set_flags,
leaf_name,
"mvlu_rptid_rd_ind_fun",
"mvlu_rptid_wr_ind_fun",
"");
sprintf (leaf_name, "%s$RptEna", basrcb_type_name);
ret |= mvlu_set_leaf_param_name (set_flags,
leaf_name,
"mvlu_rptena_rd_ind_fun",
"mvlu_rptena_wr_ind_fun",
"");
if (!scl_rcb->buffered) /* "Resv" only for Unbuffered */
{
sprintf (leaf_n
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -