⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sclproc.c

📁 scl解析文件,欢迎大家学习共享,解析算法值得学习
💻 C
📖 第 1 页 / 共 5 页
字号:
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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -