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

📄 sclproc.c

📁 scl解析文件,欢迎大家学习共享,解析算法值得学习
💻 C
📖 第 1 页 / 共 5 页
字号:
  return (retcode);	/* NOTE: may have returned sooner on some errors*/
  }	/* end tdladd_go_or_gs	*/

/************************************************************************/
/*			tdladd_ms_or_us					*/
/* RETURNS:	SD_SUCCESS or error code				*/
/* Add the TDL for special FC=MS or FC=US at the current pointer	*/
/* (tdl_ctxt->tdlptr).							*/
/* Increase (tdl_ctxt->tdlptr) by the number of bytes added.		*/
/* Decrease (tdl_ctxt->len_avail) by the number of bytes added.		*/
/************************************************************************/
ST_CHAR *mscb_tdl = "{\
(SvEna)Bool,\
(MsvID)Vstring65,\
(DatSet)Vstring65,\
(ConfRev)Ulong,\
(SmpRate)Ushort,\
(OptFlds)BVstring3,\
(DstAddress){\
  (Addr)Ostring6,\
  (PRIORITY)Ubyte,\
  (VID)Ushort,\
  (APPID)Ushort,\
},\
},\n";	/* TDL for MsvCB (Sampled Value Control Block)	*/

ST_CHAR *uscb_tdl = "{\
(SvEna)Bool,\
(Resv)Bool,\
(UsvID)Vstring65,\
(DatSet)Vstring65,\
(ConfRev)Ulong,\
(SmpRate)Ushort,\
(OptFlds)BVstring3,\
},\n";	/* TDL for UsvCB (Sampled Value Control Block)	*/


static ST_RET tdladd_ms_or_us (
	TDLADD_CTXT *tdl_ctxt,
	SCL_INFO *scl_info,
	SCL_LNTYPE *scl_lntype,
	SCL_LN *scl_ln,
	ST_BOOLEAN multicast)	/* SD_TRUE to add GOOSE (FC=GO)		*/
				/* SD_FALSE to add GSSE (FC=GS)		*/
				/* CRITICAL: no other values allowed	*/
  {
SCL_SVCB *scl_svcb;
SCL_DATASET *scl_dataset;
ST_RET retcode = SD_SUCCESS;
ST_INT count = 0;

  for (scl_svcb = (SCL_SVCB *) list_find_last ((DBL_LNK *) scl_ln->svcbHead);
       scl_svcb != NULL;
       scl_svcb = (SCL_SVCB *) list_find_prev ((DBL_LNK *) scl_ln->svcbHead, (DBL_LNK *) scl_svcb))
  {
    /* If RCB doesn't match the kind we're looking for, ignore it.	*/
    if (scl_svcb->multicast != multicast)
      continue;
      /*Find dataset now.	*/
      scl_dataset = scl_find_dataset (scl_ln, scl_svcb->datSet);
      if (scl_dataset == NULL)
        {
        SXLOG_ERR1 ("tdladd_vs_or_us: datSet='%s' not found", scl_svcb->datSet);
        return (SD_FAILURE);
        }

    if (scl_svcb->multicast)
      {
      if (count==0)
        retcode = tdladd_string (tdl_ctxt, "(MS){\n(");	/* first one needs (GO)	*/
      else
        retcode = tdladd_string (tdl_ctxt, "(");
      }
    else
      {
      if (count==0)
        retcode = tdladd_string (tdl_ctxt, "(US){\n(");	/* first one needs (GS)	*/
      else
        retcode = tdladd_string (tdl_ctxt, "(");
      }

    if (retcode)		/* if error, stop	*/
      return (retcode);

    /* Add svcb name as component name.*/  
    if (tdladd_string (tdl_ctxt, scl_svcb->name)!=SD_SUCCESS)
      return (SD_FAILURE);	/* error (already logged)	*/

    if (tdladd_string (tdl_ctxt, ")")!=SD_SUCCESS)	/* add end of comp name	*/
      return (SD_FAILURE);	/* error (already logged)	*/

    /* NOTE: if NOT the type we're looking for, never get here (see 'continue' above)*/
    if (scl_svcb->multicast)	/* looking for MSV & this is MSV	*/
      retcode = tdladd_string (tdl_ctxt, mscb_tdl);
    else			/* looking for USV & this is USV	*/
      retcode = tdladd_string (tdl_ctxt, uscb_tdl);

    if (retcode)		/* if error, stop	*/
      return (retcode);	

    count++;	/* increment count of svcb	*/
    }	/* end loop	*/

  /* If any found, add ending text.	*/
  if (count>0)
    retcode = tdladd_string (tdl_ctxt, "},\n");

  return (retcode);	/* NOTE: may have returned sooner on some errors*/
  }	/* end tdladd_ms_or_us	*/

/************************************************************************/
/*			scl2_datatype_create				*/
/* Create MMS Data type for one Logical Node Type (LNodeType)		*/
/* defined in SCL.							*/
/* This function needs a user buffer for constructing TDL strings.	*/
/* TDL is generated by calling "tdladd_*" functions. A ptr to a		*/
/* TDLADD_CTXT structure is passed to each "tdladd_*" function.		*/
/* The structure is used to keep track of the current ptr in the TDL	*/
/* buffer and the space remaining in the buffer.			*/
/* RETURNS:	SD_SUCCESS or error code				*/
/************************************************************************/
static ST_RET scl2_datatype_create (
	SCL_INFO *scl_info,	/* main struct where all SCL info stored*/
	SCL_LNTYPE *scl_lntype,	/* info for this LNType			*/
	ST_CHAR *tdlbuf,	/* buffer to use for constructing TDL	*/
				/* reused for each LNType in list	*/
	size_t tdlbuflen,	/* len of tdlbuf buffer in bytes	*/
	SCL_LD *scl_ld_special,	/* LD containing LN with "special stuff"*/
				/* (i.e. ReportControl, LogControl, etc)*/
				/* NULL if nothing special in LN.	*/
	SCL_LN *scl_ln_special)	/* LN with "special stuff"		*/
				/* NULL if nothing special in LN.	*/
  {
ST_RET retcode;
ST_INT type_id;
TDLADD_CTXT tdl_ctxt;
MVL_TYPE_CTRL *type_ctrl;
ST_CHAR type_name[MAX_IDENT_LEN+2];	/* one extra byte for NULL, another to catch if limit exceeded*/

  /* Generate type_name.	*/
  if (scl_ln_special)
    {	/* Create unique type name for this LN.	*/
    unique_type_name (scl_ld_special, scl_ln_special, type_name, sizeof(type_name));
    }
  else
    strcpy (type_name, scl_lntype->id);	/* no RCBs. Use LNType "id".*/

/* Go through all linked lists and create COMPLETE TDL.	*/
/* NOTE: order of FC specified in 61850-8-1 (section 6.1.3).	*/

  /* Initialize tdl_ctxt struct.	*/
  tdl_ctxt.tdlptr = tdlbuf;
  tdl_ctxt.len_avail = tdlbuflen;
  tdl_ctxt.errflag = SD_FALSE;

  /* NOTE: SCL only allows "ST" "MX" "CO" "SG" "SE" "SV" "CF" "DC" "EX".*/
  /*       "RP", "LG", "GO", "GS", "SP", and "BR" are special cases.			*/
  do
    {	/* "do-while" loop: only needed so we can break on first error.	*/
    /* if any tdladd_* call fails, break and return error.	*/
    if ((retcode = tdladd_string (&tdl_ctxt, "{\n")) != SD_SUCCESS)
      break;
    if ((retcode = tdladd_fc (&tdl_ctxt, "MX", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
    if ((retcode = tdladd_fc (&tdl_ctxt, "ST", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
    if ((retcode = tdladd_fc (&tdl_ctxt, "CO", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
    if ((retcode = tdladd_fc (&tdl_ctxt, "CF", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
    if ((retcode = tdladd_fc (&tdl_ctxt, "DC", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
    if (scl_ln_special)
      {
      /* FC=SP is special case. Call special function (last arg SD_TRUE).	*/ 
      if ((retcode = tdladd_sp (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS)
        break;
      }
    if ((retcode = tdladd_fc (&tdl_ctxt, "SG", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
  
    /* FC=RP is special case. Call special function.	*/
    if (scl_ln_special)
      {		/* special type for LN containing RCBs	*/
      if ((retcode = tdladd_rp_or_br (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS)
        break;
      }

    /* FC=LG is special case. Call special function.	*/
    if (scl_ln_special)
      {
      if ((retcode = tdladd_lg (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special)) != SD_SUCCESS)
        break;
      }

    /* FC=BR is special case. Call special function.	*/
    if (scl_ln_special)
      {		/* special type for LN containing RCBs	*/
      if ((retcode = tdladd_rp_or_br (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS)
        break;
      }

    if (scl_ln_special)
      {
      /* FC=GO is special case. Call special function (last arg SD_TRUE).	*/ 
      if ((retcode = tdladd_go_or_gs (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS)
        break;
      /* FC=GS is special case. Call special function (last arg SD_FALSE).	*/ 
      if ((retcode = tdladd_go_or_gs (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS)
        break;
      }

    if ((retcode = tdladd_fc (&tdl_ctxt, "SV", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
    if ((retcode = tdladd_fc (&tdl_ctxt, "SE", scl_info, scl_lntype)) != SD_SUCCESS)
      break;

    if (scl_ln_special)
      {
      /* FC=MS is special case. Call special function (last arg SD_TRUE).	*/ 
      if ((retcode = tdladd_ms_or_us (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_TRUE)) != SD_SUCCESS)
        break;
       }
    /* DEBUG: add something here for "SC" someday.*/

    if (scl_ln_special)
      {
      /* FC=US is special case. Call special function (last arg SD_TRUE).	*/ 
      if ((retcode = tdladd_ms_or_us (&tdl_ctxt, scl_info, scl_lntype, scl_ln_special, SD_FALSE)) != SD_SUCCESS)
        break;
       }

    if ((retcode = tdladd_fc (&tdl_ctxt, "EX", scl_info, scl_lntype)) != SD_SUCCESS)
      break;
    if ((retcode = tdladd_string (&tdl_ctxt, "}")) != SD_SUCCESS)
      break;
    } while (0);	/* end of "do-while" loop: only needed so we can break on first error.	*/

  assert (tdlbuf + strlen(tdlbuf) == tdl_ctxt.tdlptr);
  assert (strlen(tdlbuf) < tdlbuflen);	/* memory already corrupted	*/
  assert (strlen(tdlbuf) + tdl_ctxt.len_avail == tdlbuflen);

  /* If retcode==SD_SUCCESS, ALL "tdladd_fc" calls were successful, so create type here	*/
  if (retcode == SD_SUCCESS)
    {
    /* NOTE: if generated type_name is > MAX_IDENT_LEN, this will fail.	*/
    type_id = mvl_type_id_create_from_tdl (type_name, tdlbuf);
    if (type_id < 0)
      retcode = SD_FAILURE;
    else
      {
      type_ctrl = mvl_type_ctrl_find (type_id);

      /* CRITICAL: we want the same leaf function for every leaf, so	*/
      /* set leaf functions now in every RUNTIME_TYPE element.		*/
      /* NOTE: leaf functions never used for RT_STR_START, RT_ARR_START,*/
      /*       etc. but they're set anyway because it's easier to set all.*/
      /* NOTE: this function may be customized for each application.	*/
      /*       It should be placed in a "user" module.			*/

      retcode = u_set_all_leaf_functions (type_ctrl->rt_ctrl,scl_lntype->lnClass,scl_lntype->id);
      }
    }

  /* NOTE: these may not log entire TDL unless default "sl_max_msg_size" is increased.*/
  if (retcode)
    SXLOG_ERR3 ("scl2_datatype_create FAILED for type_name=%s\nTDL len=%u\nTDL=%s",
                 type_name, strlen(tdlbuf), tdlbuf);
  else
    SXLOG_FLOW3 ("scl2_datatype_create SUCCESSFUL for type_name=%s\nTDL len=%u\nTDL=%s",
                 type_name, strlen(tdlbuf), tdlbuf);

  /* Don't need to save or return type_id. Use "mvl_typename_to_typeid" later to find it.*/
  return (retcode);
  }


/************************************************************************/
/*			scl2_datatype_create_all			*/
/* Create MMS Data types for all Logical Node Types (LNodeType)		*/
/* defined in SCL.							*/
/* This function needs a user buffer for constructing TDL strings.	*/
/* RETURNS:	SD_SUCCESS or error code				*/
/************************************************************************/
ST_RET scl2_datatype_create_all (
	SCL_INFO *scl_info,	/* main struct where all SCL info stored*/
	ST_CHAR *tdlbuf,	/* buffer to use for constructing TDL	*/
				/* reused for each LNType in list	*/
	size_t tdlbuflen)	/* len of tdlbuf buffer in bytes	*/
  {
ST_RET retcode;
SCL_LNTYPE *scl_lntype;
SCL_LD *scl_ld;
SCL_LN *scl_ln;

  /* NOTE: linked list is in reverse order from data in SCL file,	*/
  /*     so get off list in reverse order.				*/
  for (scl_lntype = (SCL_LNTYPE *) list_find_last ((DBL_LNK *) scl_info->lnTypeHead);
       scl_lntype != NULL;
       scl_lntype = (SCL_LNTYPE *) list_find_prev ((DBL_LNK *) scl_info->lnTypeHead, (DBL_LNK *) scl_lntype))
    {
    retcode = scl2_datatype_create (scl_info, scl_lntype, tdlbuf, tdlbuflen, NULL, NULL);
    if (retcode)	/* error (already logged)	*/
      break;	/* if one fails, stop processing	*/
    /* Find all Logical Nodes that use this type. For each one that
     * contains "special stuff" (i.e. ReportControl, LogControl, GSEControl),
     * create a special type that includes the "special stuff".
     * Must check all Logical Nodes (scl_ln) in all Logical Devices (scl_ld).
     */ 
    for (scl_ld = (SCL_LD *) list_find_last ((DBL_LNK *) scl_info->ldHead);
         scl_ld != NULL;
         scl_ld = (SCL_LD *) list_find_prev ((DBL_LNK *) scl_info->ldHead, (DBL_LNK *) scl_ld))
      {
      for (scl_ln = (SCL_LN *) list_find_last ((DBL_LNK *) scl_ld->lnHead);
           scl_ln != NULL;
           scl_ln = (SCL_LN *) list_find_prev ((DBL_LNK *) scl_ld->lnHead, (DBL_LNK *) scl_ln))
        {
        /* If rcbHead!=NULL, this LN contains ReportControl.		*/
        /* If lcbHead!=NULL, this LN contains LogControl.		*/
        /* If gcbHead!=NULL, this LN contains GSEControl.		*/
        /* If sgcbHead!=NULL, this LN contains SGControl.		*/
        /* NOTE: do nothing if it fails. Detected later when rcb created.*/
        if ((scl_ln->rcbHead || scl_ln->lcbHead || scl_ln->gcbHead || scl_ln->sgcbHead || scl_ln->svcbHead) &&
            strcmp (scl_ln->lnType, scl_lntype->id) == 0)
          {
          /* Last 2 args point to LD & LN containing special info (rcb, gcb, etc.).*/
          scl2_datatype_create (scl_info, scl_lntype, tdlbuf, tdlbuflen, scl_ld, scl_ln);
          }
        }
      }
    }
  return (retcode);
  }

/************************************************************************/
/*			scl2_ln_create			*/
/* RETURNS:	SD_SUCCESS or error code				*/
/************************************************************************/
static ST_RET scl2_ln_create (
	SCL_INFO *scl_info,	/* main struct where all SCL info stored*/
	SCL_LD *scl_ld,
	SCL_LN *scl_ln)
  {

⌨️ 快捷键说明

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