自主协议库编译通过
This commit is contained in:
422
mmslib/mvlu/mvlu_rt.c
Normal file
422
mmslib/mvlu/mvlu_rt.c
Normal file
@@ -0,0 +1,422 @@
|
||||
/************************************************************************/
|
||||
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||||
/************************************************************************/
|
||||
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||||
/* 1997-2001, All Rights Reserved */
|
||||
/* */
|
||||
/* MODULE NAME : mvlu_rt.c */
|
||||
/* PRODUCT(S) : */
|
||||
/* */
|
||||
/* MODULE DESCRIPTION : */
|
||||
/* */
|
||||
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||||
/* main */
|
||||
/* */
|
||||
/* MODIFICATION LOG : */
|
||||
/* Date Who Rev Comments */
|
||||
/* -------- --- ------ ------------------------------------------- */
|
||||
/* 01/18/08 JRB 11 We allow up to 15 char LNName (sclparse.c), */
|
||||
/* so max flatname must be MAX_IDENT_LEN-15. */
|
||||
/* 07/20/07 JRB 10 Flatnames must be shorter to add LNName later*/
|
||||
/* 11/22/06 JRB 09 Free bufs if _mvlu_build_uca_name_tbl fails. */
|
||||
/* 01/30/06 GLB 09 Integrated porting changes for VMS */
|
||||
/* 03/11/04 GLB 08 Added "#ifdef DEBUG_SISCO" for "thisFileName" */
|
||||
/* 09/18/03 JRB 07 Allow array of structures. */
|
||||
/* DON'T allow array of arrays (return error). */
|
||||
/* 05/02/03 JRB 06 switch(rt->el_tag): Use default for most cases*/
|
||||
/* 04/29/03 JRB 05 Chg several functions to return ST_RET. */
|
||||
/* 04/24/03 JRB 04 Use MAX_IDENT_LEN define. */
|
||||
/* 03/13/03 JRB 03 mvlu_proc_rt_type: Chg to use RUNTIME_CTRL. */
|
||||
/* MVLU_UCA_NAME_CTRL: Chg ucaName member from */
|
||||
/* ptr to array (saves allocs). */
|
||||
/* 12/11/02 JRB 02 Use new mvl_uca.h */
|
||||
/* 11/14/02 MDE 01 New module, extracted fo_uca.c */
|
||||
/************************************************************************/
|
||||
|
||||
#include "glbtypes.h"
|
||||
#include "sysincs.h"
|
||||
#include "gen_list.h"
|
||||
|
||||
#include "mmsdefs.h"
|
||||
#include "mms_pvar.h"
|
||||
#include "mms_vvar.h"
|
||||
#include "mem_chk.h"
|
||||
#include "mvl_uca.h"
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef DEBUG_SISCO
|
||||
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* STATIC VARIABLES */
|
||||
|
||||
#define MAX_PREFIX_LEN 200
|
||||
#define MAX_NEST_LEVEL 50
|
||||
static ST_CHAR *namePrefix[MAX_NEST_LEVEL];
|
||||
static ST_INT nestLevel;
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* STATIC FUNCTIONS */
|
||||
|
||||
static ST_RET _mvlu_set_rt_sort_num (ST_CHAR *typeName,
|
||||
RUNTIME_TYPE *rt, ST_INT numRt,
|
||||
MVLU_UCA_NAME_CTRL **ucaNamesOut);
|
||||
static ST_VOID _mvlu_set_rt_size (RUNTIME_TYPE *rt) ;
|
||||
static ST_VOID _mvlu_set_rt_offset (RUNTIME_TYPE *rt, ST_INT numRt);
|
||||
static ST_RET _mvlu_build_uca_name_tbl (RUNTIME_TYPE *rt, ST_INT rt_num,
|
||||
MVLU_UCA_NAME_CTRL *mvluFoundryInfo);
|
||||
static ST_RET _mvlu_save_rt_uca_name (ST_INT nestLevel, RUNTIME_TYPE *rt,
|
||||
MVLU_UCA_NAME_CTRL *mvluFoundryInfo);
|
||||
static ST_VOID _mvlu_sort_uca_names (MVLU_UCA_NAME_CTRL *ucaNames,
|
||||
RUNTIME_TYPE *rt, ST_INT numRt);
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* mvlu_proc_rt_type */
|
||||
/************************************************************************/
|
||||
|
||||
ST_RET mvlu_proc_rt_type (ST_CHAR *typeName, RUNTIME_CTRL *rt_ctrl,
|
||||
MVLU_UCA_NAME_CTRL **ucaNamesOut)
|
||||
{
|
||||
RUNTIME_TYPE *rt;
|
||||
ST_INT i;
|
||||
ST_RET ret;
|
||||
|
||||
/* Set the sortedNum for each RT element */
|
||||
ret = _mvlu_set_rt_sort_num (typeName, rt_ctrl->rt_first, rt_ctrl->rt_num, ucaNamesOut);
|
||||
if (ret)
|
||||
return(ret); /* don't bother continuing */
|
||||
|
||||
/* Find the offset of the data for each RT within the type */
|
||||
_mvlu_set_rt_offset (rt_ctrl->rt_first, rt_ctrl->rt_num);
|
||||
|
||||
/* Find the size of each RT within the type */
|
||||
rt = rt_ctrl->rt_first;
|
||||
for (i = 0; i < rt_ctrl->rt_num; ++i, ++rt)
|
||||
_mvlu_set_rt_size (rt);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* _mvlu_set_rt_size */
|
||||
/************************************************************************/
|
||||
/* This function would not be needed except that the UCA structure */
|
||||
/* handling needs to know the size of each subelement too ... */
|
||||
|
||||
static ST_VOID _mvlu_set_rt_size (RUNTIME_TYPE *rt)
|
||||
{
|
||||
ST_INT numUcaRt;
|
||||
ST_INT blockedLen;
|
||||
|
||||
if (rt->el_tag == RT_ARR_END || rt->el_tag == RT_STR_END)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (rt->el_tag == RT_STR_START)
|
||||
numUcaRt = rt->u.str.num_rt_blks+2;
|
||||
else if (rt->el_tag == RT_ARR_START)
|
||||
numUcaRt = rt->u.arr.num_rt_blks+2;
|
||||
else
|
||||
numUcaRt = 1;
|
||||
|
||||
/* Now we can find the size of this element and it's associates */
|
||||
blockedLen = ms_get_blocked_length (rt, numUcaRt);
|
||||
rt->offset_to_last = blockedLen;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* _mvlu_set_rt_offset */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_VOID _mvlu_set_rt_offset (RUNTIME_TYPE *rt, ST_INT numRt)
|
||||
{
|
||||
ST_INT data_offset;
|
||||
SD_CONST RUNTIME_TYPE *rt_end;
|
||||
ST_INT arr_loops[ASN1_MAX_LEVEL];
|
||||
ST_BOOLEAN arr_el_set[ASN1_MAX_LEVEL];
|
||||
ST_INT arr_loop_level;
|
||||
|
||||
arr_loop_level = 0;
|
||||
rt_end = rt + numRt; /* end block */
|
||||
data_offset = 0;
|
||||
|
||||
/* Traverse the RT type as though we were doing a ASN.1 to LOCAL */
|
||||
while (rt < rt_end)
|
||||
{
|
||||
if (rt->el_tag == RT_ARR_END) /* treat case of array ending */
|
||||
{
|
||||
if (--arr_loops[arr_loop_level] > 0)/* if need to do next ar elmnt*/
|
||||
{
|
||||
rt -= rt->u.arr.num_rt_blks; /* mv rt to start of arr */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
--arr_loop_level;
|
||||
}
|
||||
if (arr_loop_level == 0 || arr_el_set[arr_loop_level] == SD_FALSE)
|
||||
{
|
||||
rt->mvluTypeInfo.offSet = data_offset; /* Set the offset */
|
||||
/* renxiaobao <20><><EFBFBD><EFBFBD>*/
|
||||
/*arr_el_set[arr_loop_level] = SD_TRUE;*/
|
||||
}
|
||||
|
||||
data_offset += rt->el_size; /* Offset for next */
|
||||
|
||||
if (rt->el_tag == RT_ARR_START) /* Set up array looping */
|
||||
{
|
||||
++arr_loop_level;
|
||||
arr_loops[arr_loop_level] = rt->u.arr.num_elmnts;
|
||||
arr_el_set[arr_loop_level] = SD_FALSE;
|
||||
}
|
||||
rt++; /* point to next runtime element */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* _mvlu_set_rt_sort_num */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_RET _mvlu_set_rt_sort_num (ST_CHAR *typeName,
|
||||
RUNTIME_TYPE *rt, ST_INT numRt,
|
||||
MVLU_UCA_NAME_CTRL **ucaNamesOut)
|
||||
{
|
||||
MVLU_UCA_NAME_CTRL *ucaNames;
|
||||
ST_INT i;
|
||||
|
||||
ucaNames = (MVLU_UCA_NAME_CTRL *) chk_calloc (numRt, sizeof (MVLU_UCA_NAME_CTRL));
|
||||
nestLevel = 0;
|
||||
|
||||
/* Derive the UCA names within this type */
|
||||
namePrefix[0] = (ST_CHAR *) chk_calloc (1, MAX_PREFIX_LEN);
|
||||
if (typeName != NULL)
|
||||
strcpy (namePrefix[0], typeName);
|
||||
|
||||
if (_mvlu_build_uca_name_tbl (rt, numRt, ucaNames))
|
||||
{
|
||||
chk_free(ucaNames);
|
||||
chk_free(namePrefix[0]);
|
||||
return (SD_FAILURE); /* don't bother continuing */
|
||||
}
|
||||
|
||||
/* Now sort the UCA names within the type */
|
||||
_mvlu_sort_uca_names (ucaNames, rt, numRt);
|
||||
|
||||
for (i = 0; i < MAX_NEST_LEVEL; ++i)
|
||||
{
|
||||
if (namePrefix[i] != NULL)
|
||||
{
|
||||
chk_free (namePrefix[i]);
|
||||
namePrefix[i] = NULL;
|
||||
}
|
||||
}
|
||||
if (ucaNamesOut == NULL)
|
||||
chk_free (ucaNames);
|
||||
else
|
||||
*ucaNamesOut = ucaNames;
|
||||
return (SD_SUCCESS);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* _mvlu_build_uca_name_tbl */
|
||||
/* Start with retCode=SD_SUCCESS. If any call to _mvlu_save_rt_uca_name */
|
||||
/* fails, set retCode=SD_FAILURE. Do not return immediately because we */
|
||||
/* want to log as many problems as possible first. */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_RET _mvlu_build_uca_name_tbl (RUNTIME_TYPE *rt, ST_INT rt_num,
|
||||
MVLU_UCA_NAME_CTRL *ucaNames)
|
||||
{
|
||||
ST_INT i;
|
||||
ST_RET retCode=SD_SUCCESS;
|
||||
|
||||
nestLevel = 0;
|
||||
for (i = 0; i < rt_num; ++i, ++rt)
|
||||
{
|
||||
ucaNames[i].rtIndex = i;
|
||||
ucaNames[i].rt = rt;
|
||||
switch (rt->el_tag)
|
||||
{
|
||||
case RT_STR_START :
|
||||
if (ms_comp_name_pres(rt))
|
||||
{
|
||||
if (_mvlu_save_rt_uca_name (nestLevel, rt, &ucaNames[i]))
|
||||
retCode = SD_FAILURE; /*continue but eventually return this*/
|
||||
|
||||
++nestLevel;
|
||||
if (namePrefix[nestLevel] == NULL)
|
||||
namePrefix[nestLevel] = (ST_CHAR *) chk_calloc (1, MAX_PREFIX_LEN);
|
||||
|
||||
strcpy (namePrefix[nestLevel], namePrefix[nestLevel-1]);
|
||||
strcat (namePrefix[nestLevel], "$");
|
||||
strcat (namePrefix[nestLevel], ms_comp_name_find(rt));
|
||||
}
|
||||
break;
|
||||
|
||||
case RT_STR_END :
|
||||
--nestLevel;
|
||||
break;
|
||||
|
||||
case RT_ARR_START :
|
||||
if (_mvlu_save_rt_uca_name (nestLevel, rt, &ucaNames[i]))
|
||||
retCode = SD_FAILURE; /*continue but eventually return this*/
|
||||
|
||||
/* We let the array element inherit our name so we will generate */
|
||||
/* rd/wr ind handler functions and references for the contained */
|
||||
/* primitive elements */
|
||||
/* This causes duplicate names (name of array same as name of */
|
||||
/* object IN array). That's OK because names of anything inside */
|
||||
/* array are dropped when sorted (see _mvlu_sort_uca_names). */
|
||||
/* The "sorted" array of names is used in GetNameList response. */
|
||||
|
||||
if (ms_is_rt_prim (rt+1) || (rt+1)->el_tag==RT_STR_START)
|
||||
{
|
||||
|
||||
#if defined(USE_RT_TYPE_2)
|
||||
(rt+1)->comp_name_ptr = rt->comp_name_ptr;
|
||||
#elif defined(USE_RT_TYPE_3)
|
||||
(rt+1)->name_index = rt->name_index;
|
||||
#else
|
||||
strcpy ((rt+1)->name, rt->name);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
SLOGALWAYS1 ("Warning: Arrays of arrays not supported for UCA (%s)",
|
||||
ucaNames[i].ucaName);
|
||||
retCode = SD_FAILURE; /*continue but eventually return this*/
|
||||
}
|
||||
break;
|
||||
|
||||
case RT_ARR_END :
|
||||
break;
|
||||
|
||||
default :
|
||||
if (_mvlu_save_rt_uca_name (nestLevel, rt, &ucaNames[i]))
|
||||
retCode = SD_FAILURE; /*continue but eventually return this*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (retCode);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* _mvlu_save_rt_uca_name */
|
||||
/* Start with retCode=SD_SUCCESS. If anything fails, set retCode=SD_FAILURE.*/
|
||||
/************************************************************************/
|
||||
static ST_RET _mvlu_save_rt_uca_name (ST_INT nestLevel,
|
||||
RUNTIME_TYPE *rt,
|
||||
MVLU_UCA_NAME_CTRL *nameDest)
|
||||
{
|
||||
ST_CHAR nameBuf[256];
|
||||
ST_RET retCode = SD_SUCCESS;
|
||||
|
||||
nameDest->ucaName [0] = '\0'; /* start with empty string */
|
||||
nameDest->rt = rt;
|
||||
if (ms_comp_name_pres(rt))
|
||||
{
|
||||
sprintf (nameBuf, "%s$%s", namePrefix[nestLevel], ms_comp_name_find(rt));
|
||||
/* Make sure there is room left for longest allowed Logical Node Name*/
|
||||
/* (11 characters according to IEC 61850-7-2 but we allow 15). */
|
||||
/* NOTE: this allows 5 or 6 more char than 61850-7-2 specifies, so */
|
||||
/* it is more forgiving, but it prevents illegal MMS names. */
|
||||
if (strlen (nameBuf) > (MAX_IDENT_LEN-15))
|
||||
{
|
||||
SLOGALWAYS2 ("Error: Flattened IEC 61850 variable name '%s' > %d characters. Illegal.",
|
||||
nameBuf, (MAX_IDENT_LEN-15));
|
||||
SLOGCALWAYS0 ("Must allow space for LNName up to 15 characters");
|
||||
retCode = SD_FAILURE;
|
||||
}
|
||||
else
|
||||
strcpy (nameDest->ucaName, nameBuf);
|
||||
}
|
||||
return (retCode);
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/************************************************************************/
|
||||
/* SORTING UCA NAMES WITHIN A TYPE */
|
||||
/************************************************************************/
|
||||
/* elementCompare */
|
||||
/************************************************************************/
|
||||
/* This function is sorting the namelist table */
|
||||
|
||||
static ST_INT elementCompare (const MVLU_UCA_NAME_CTRL *a,
|
||||
const MVLU_UCA_NAME_CTRL *b)
|
||||
{
|
||||
return (strcmp (a->ucaName, b->ucaName));
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* _mvlu_sort_uca_names */
|
||||
/************************************************************************/
|
||||
|
||||
static ST_VOID _mvlu_sort_uca_names (MVLU_UCA_NAME_CTRL *ucaNames,
|
||||
RUNTIME_TYPE *rt, ST_INT numRt)
|
||||
{
|
||||
ST_INT i;
|
||||
ST_INT numNames;
|
||||
MVLU_UCA_NAME_CTRL *sortedNames; /* compressed/sorted array of names*/
|
||||
|
||||
sortedNames = (MVLU_UCA_NAME_CTRL *) M_MALLOC (MSMEM_GEN, numRt*sizeof(MVLU_UCA_NAME_CTRL));
|
||||
|
||||
/* Compress the name table */
|
||||
numNames = 0;
|
||||
for (i = 0; i < numRt; ++i, ++rt)
|
||||
{
|
||||
if (ucaNames[i].ucaName[0] != '\0')
|
||||
{
|
||||
sortedNames[numNames] = ucaNames[i];
|
||||
++numNames;
|
||||
/* CRITICAL:
|
||||
* The "ucaNames" array contains names for objects inside arrays.
|
||||
* They must be kept in the original array, because they are needed
|
||||
* for generating leaf function names.
|
||||
* However, they are NOT legal variable names, so they are NOT
|
||||
* copied to the SORTED array (used for GetNameList response).
|
||||
* This is done by skipping over the runtime type for the array.
|
||||
*/
|
||||
if (rt->el_tag==RT_ARR_START)
|
||||
{
|
||||
rt += (rt->u.arr.num_rt_blks + 1);
|
||||
i += (rt->u.arr.num_rt_blks + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, we now have a raw table of names, go ahead and sort them */
|
||||
qsort (sortedNames, numNames, sizeof (MVLU_UCA_NAME_CTRL),
|
||||
(int (*)(const void *,const void *)) elementCompare);
|
||||
|
||||
#if 0 /* DEBUG: enable this code to debug sorting algorithm */
|
||||
if (numNames)
|
||||
{
|
||||
ST_INT j;
|
||||
SLOGALWAYS0 ("Array of UCA variable names (Uncompressed/Unsorted)");
|
||||
for (j = 0; j<numRt; j++)
|
||||
SLOGCALWAYS1 ("%s", ucaNames[j].ucaName);
|
||||
|
||||
SLOGALWAYS0 ("Array of UCA variable names (Compressed/Sorted)");
|
||||
for (j = 0; j<numNames; j++)
|
||||
SLOGCALWAYS1 ("%s", sortedNames[j].ucaName);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now assign sort numbers to the RT elements */
|
||||
for (i = 0; i < numNames; ++i)
|
||||
{
|
||||
sortedNames[i].rt->mvluTypeInfo.sortedNum = i+1;
|
||||
}
|
||||
M_FREE (MSMEM_GEN, sortedNames);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user