1154 lines
37 KiB
C
1154 lines
37 KiB
C
/************************************************************************/
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
|
/************************************************************************/
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
|
/* 1986 - 2001, All Rights Reserved. */
|
|
/* */
|
|
/* PROPRIETARY AND CONFIDENTIAL */
|
|
/* */
|
|
/* MODULE NAME : ms_tdef.c */
|
|
/* PRODUCT(S) : MMS-EASE */
|
|
/* */
|
|
/* MODULE DESCRIPTION : */
|
|
/* This module contains some MMS-EASE virtual machine support */
|
|
/* functions that help the user with MMS variable access and */
|
|
/* type specifications. */
|
|
/* */
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
|
/* */
|
|
/* MODIFICATION LOG : */
|
|
/* Date Who Rev Comments */
|
|
/* -------- --- ------ ------------------------------------------- */
|
|
/* 06/22/07 JRB 26 Log max on buffer overrun. */
|
|
/* 01/17/06 NAV 25 ms_runtime_to_tdl: fix tdl_buf overwrite */
|
|
/* 07/12/04 JRB 24 For RT_UTF8_STRING, chg "t18" to "t16" in */
|
|
/* "tdlTypes" to match latest 61850-8-1. */
|
|
/* 05/03/04 JRB 23 ms_mk_asn1_type: return err if struct empty, */
|
|
/* ignore extra commas, use ASN1_ENC_* macros, */
|
|
/* & log the ASN.1 produced. */
|
|
/* type_subst: remove whitespace in dest string.*/
|
|
/* 10/13/03 JRB 22 ms_runtime_to_tdl: Chg assert to err return. */
|
|
/* 07/14/03 JRB 21 Use strlen(comp_name), was assuming maxlen=32*/
|
|
/* 04/22/03 JRB 20 Allow fixed len UTF8 only if local fmt=UTF16.*/
|
|
/* 04/02/03 JRB 19 Add UTF8string support (see RT_UTF8_STRING). */
|
|
/* Use "RT_*" defines in "switch (type)". */
|
|
/* DRASTICALLY simplify ms_runtime_to_tdl. */
|
|
/* add_tdl_separator: add args (& fix spelling):*/
|
|
/* - allows 3 global vars to be eliminated. */
|
|
/* - allows semaphore to be eliminated. */
|
|
/* 12/15/02 JRB 18 Add ms_tdl_to_runtime function. */
|
|
/* 11/11/02 JRB 17 Replace ms_asn1_to.. w/ ms_runtime_create. */
|
|
/* 03/04/02 JRB 16 Add more SD_CONST. Add str_util.h. */
|
|
/* 12/20/01 JRB 15 Converted to use ASN1R (re-entrant ASN1) */
|
|
/* 11/13/01 EJV 14 Added support for new MMS type UtcTime: */
|
|
/* tdlTypes[]: added new type "Utctime" [17] */
|
|
/* ms_mk_asn1_type: added case for type 17. */
|
|
/* anticipated[]: added type 17 and moved other.*/
|
|
/* ms_runtime_to_tdl: added RT_UTC_TIME case. */
|
|
/* 03/08/01 JRB 13 Chk return val from ms_comp_name_find. */
|
|
/* 08/24/00 JRB 12 Use ms_comp_name_find, so code works for */
|
|
/* MMS_LITE (i.e. USE_RT_TYPE_2 or USE_RT_TYPE_3*/
|
|
/* defined). */
|
|
/* 07/28/00 JRB 11 Use new defines in #ifdef. */
|
|
/* 09/13/99 MDE 10 Added SD_CONST modifiers */
|
|
/* 09/21/98 MDE 09 Minor lint cleanup */
|
|
/* 08/21/98 MDE 08 Eliminated warning in ms_asn1_to_tdl. */
|
|
/* 06/03/98 MDE 07 Now check 'ms_asn1_to_runtime' return code */
|
|
/* 03/11/98 MDE 06 Removed NEST_RT_TYPES */
|
|
/* 02/10/98 MDE 05 Runtime type changes for LITE */
|
|
/* 10/30/97 MDE 04 Calculate size of RT table before alloc */
|
|
/* 09/16/97 MDE 03 Now don't require @VMD for referenced type */
|
|
/* 06/19/97 MDE 02 Added 64 bit integer support, cleanup */
|
|
/* 06/09/97 MDE 01 Changed Runtime Type, and it's use */
|
|
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
|
|
/* history. */
|
|
/************************************************************************/
|
|
|
|
#include "glbtypes.h"
|
|
#include "sysincs.h"
|
|
#include "glbsem.h"
|
|
#include "mmsdefs.h"
|
|
#include "asn1defs.h"
|
|
#include "mem_chk.h"
|
|
#include "str_util.h" /* for strnicmp */
|
|
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
/* 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
|
|
|
|
|
|
/************************************************************************/
|
|
/* TDL DEFINES */
|
|
/* Defined constants giving the primitive syntax for the keywords: */
|
|
/* Bool, Byte, Short, Long, Ubyte, Ushort, Ulong, Float, Double, */
|
|
/* Vstring, Fstring, Ostring, Bstring, Gtime, Btime4, Btime8, respec- */
|
|
/* tively. */
|
|
/* These are used in 'ms_mk_asn1_type' for substitutions */
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
|
|
static ST_INT type_subst (ST_CHAR *dest_str, ST_CHAR *src_str, ST_INT src_len);
|
|
static ST_RET wr_object_name (ASN1_ENC_CTXT *aCtx, ST_CHAR *objname);
|
|
static ST_UCHAR *err_rtn (ST_RET error, ST_CHAR *tspec);
|
|
|
|
#ifdef MMS_LITE
|
|
ST_INT m_rt_type_limit = 50; /* max number of runtime blocks per def */
|
|
#endif
|
|
|
|
/* These checks catch if a define change breaks the code using "tdlTypes"*/
|
|
/* The way "tdlTypes" is used, does not work if any of the RT_* defines change.*/
|
|
/* It would be better to modify the code to always use the RT_* defines,*/
|
|
/* but that is not so easy now. */
|
|
#if (RT_BOOL != 3)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_BIT_STRING != 4)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_INTEGER != 5)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_UNSIGNED != 6)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_FLOATING_POINT != 7)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_OCTET_STRING != 9)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_VISIBLE_STRING != 10)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_GENERAL_TIME != 11)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_BINARY_TIME != 12)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_BCD != 13)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_BOOLEANARRAY != 14)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_UTC_TIME != 17)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
#if (RT_UTF8_STRING != 16)
|
|
#error define does't match expected. tdlTypes array won't work.
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
|
|
typedef struct
|
|
{
|
|
ST_CHAR *abbrev;
|
|
ST_CHAR *subType;
|
|
} TDL_TYPES;
|
|
|
|
/* tdlTypes array
|
|
* CRITICAL: the number after the "t" in the 2nd string of each struct
|
|
* MUST match the ASN.1 tag for that type. The tags are defined in "mms_vvar.h"
|
|
* and they have a prefix of "RT_".
|
|
* For example, the ASN.1 tag for Boolean is 3, so "mms_vvar.h" has the define:
|
|
* #define RT_BOOL 3
|
|
* and the string in this array for Boolean is:
|
|
* "t3"
|
|
*/
|
|
|
|
TDL_TYPES tdlTypes[] =
|
|
{
|
|
{ "Bool", "t3" },
|
|
{ "Byte", "t5+8" },
|
|
{ "Short", "t5+16" },
|
|
{ "Long", "t5+32" },
|
|
#ifdef INT64_SUPPORT
|
|
{ "Int64", "t5+64" },
|
|
#endif
|
|
{ "Ubyte", "t6+8" },
|
|
{ "Ushort", "t6+16" },
|
|
{ "Ulong", "t6+32" },
|
|
#ifdef INT64_SUPPORT
|
|
{ "Uint64", "t6+64" },
|
|
#endif
|
|
{ "Float", "t7+2071" },
|
|
{ "Double", "t7+2868" },
|
|
{ "Vstring", "t10-" },
|
|
{ "Fstring", "t10+" },
|
|
{ "Ostring", "t9+" },
|
|
{ "OVstring", "t9-" },
|
|
{ "Bstring", "t4+" },
|
|
{ "BVstring", "t4-" },
|
|
{ "Gtime", "t11" },
|
|
{ "Btime4", "t12+0" },
|
|
{ "Btime6", "t12+1" },
|
|
{ "Bcd", "t13+" },
|
|
{ "Utctime", "t17" },
|
|
{ "UTF8Vstring", "t16-" },
|
|
#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF16)
|
|
{ "UTF8string", "t16+" },
|
|
#endif
|
|
};
|
|
ST_INT numTdlTypes = (sizeof (tdlTypes)/sizeof(TDL_TYPES));
|
|
|
|
/************************************************************************/
|
|
/* ms_mk_asn1_type */
|
|
/* Function to convert a character string type specification to an */
|
|
/* ASN.1 string, as required by the ms_add_named_type function. It */
|
|
/* is assumed that the function strt_asn1 has been called elsewhere */
|
|
/* in the user's program. The input 'tspec' character string must */
|
|
/* conform to the following syntax for specifying a type: */
|
|
/* */
|
|
/* Let N be a number, i.e. a sequence of digits. Let */
|
|
/* IDENTIFIER be a character string which is a valid MMS */
|
|
/* identifier. And let OBJECT_NAME be a character string */
|
|
/* which represents a valid MMS object name of the form: */
|
|
/* string1:IDENTIFIER, where string1 is "+" for a VMD- */
|
|
/* specific object, "-" for an AA-specific object, or a */
|
|
/* valid IDENTIFIER naming a domain for a domain-specific */
|
|
/* object. Then we have the following Bacchus-Nauer rules */
|
|
/* for specifying the syntax: */
|
|
/* */
|
|
/* Type ::= <OBJECT_NAME> | tN+N | tN-N | tN | [N:Type] */
|
|
/* | [pN:Type] | {Component_list} | {p:Component_list} */
|
|
/* Component_list ::= Component | Component_list,Component */
|
|
/* Component ::= Type | (IDENTIFIER)Type */
|
|
/* */
|
|
/* The above syntax may contain white space (blanks, tabs and new- */
|
|
/* lines) to make it more readable. (Hence, a character string */
|
|
/* constant input for 'tspec' may extend over several lines.) */
|
|
/* However, the symbols appearing in the definition above (called */
|
|
/* terminal symbols), such as '<', '>', 't', '+', ,'-', '[', ':', ']', */
|
|
/* '{', '}', '(', ')', 'p' and ',', must be used exactly as specified. */
|
|
/* The meaning of the above syntax is given below: */
|
|
/* */
|
|
/* <OBJECT_NAME> - Name of a type object that has already been */
|
|
/* declared to MMS-EASE using ms_add_named_type */
|
|
/* or ms_add_std_types. */
|
|
/* tN+N, tN-N, tN - Primitive type, where the first N indicates */
|
|
/* the basic type, and the second N is the */
|
|
/* length of the type (normally in bits, but */
|
|
/* for octet-strings and visible-strings, it */
|
|
/* represents the number of bytes, and floats */
|
|
/* are a special case - see note below). The */
|
|
/* basic types are explained below. If the type */
|
|
/* length (+N or -N) is left off, it defaults */
|
|
/* to zero. Note that char strings may have */
|
|
/* negative type lengths, indicating variable- */
|
|
/* length (i.e., can be <= N), but all other */
|
|
/* types must have nonnegative type lengths. */
|
|
/* [N:Type] - Array of N elements of the specified type. */
|
|
/* {Component_list} - Structure consisting of one or more compo- */
|
|
/* nents, separated by commas, with or without */
|
|
/* component names. */
|
|
/* (IDENTIFIER)Type - A component of a structure identified by a */
|
|
/* component name, in order that it may be */
|
|
/* referenced in a subsequent alternate access. */
|
|
/* p - Used in arrays or structures to indicate */
|
|
/* that it is 'packed', i.e. compressed in some */
|
|
/* implementation-specific way. */
|
|
/* */
|
|
/* The basic types are numbers (first N following the 't' of a primi- */
|
|
/* tive type) with the following meanings: */
|
|
/* */
|
|
/* 3 - Boolean, type length = 0 (or absent). Ex: "t3". */
|
|
/* 4 - Bit-string, type length >= 0. Ex: "t4+27" for a 27-bit */
|
|
/* bit-string. */
|
|
/* 5 - Integer, type length = 16 or 32 for most computers. Ex: */
|
|
/* "t5+16" for a 2-byte integer, "t5+32" for a 4-byte int. */
|
|
/* 6 - Unsigned, type length = 16 or 32 for most computers. Ex: */
|
|
/* "t6+16" for a 2-byte unsigned integer. */
|
|
/* 7 - Floating point, type length = 2071 for single precision */
|
|
/* or 2868 for double precision on most computers. See */
|
|
/* the note below. */
|
|
/* 9 - Octet-string, type length >= 0. Ex: "t9+19" for a 19- */
|
|
/* byte octet-string. */
|
|
/* 10 - Visible-string, any type length. Ex: "t10+30" specifies */
|
|
/* a fixed-length string of exactly 30 characters, whereas */
|
|
/* "t10-12" specifies a variable-length string of at most */
|
|
/* 12 characters. */
|
|
/* 11 - Generalized-time, type length = 0 (or absent). Ex: "t11". */
|
|
/* 12 - Binary-time, type length = 0 or 1 (SD_FALSE or SD_TRUE). Ex: */
|
|
/* "t12+1" for a 6-byte binary-time time of day, including */
|
|
/* date. */
|
|
/* 13 - BCD, type length >= 0 AND <= 8 */
|
|
/* computers). Ex: "t13+8" for a 8-nibble BCD integer. */
|
|
/* 17 - UTC Time is struct of 3 unsigned integers encoded as */
|
|
/* 8 bytes octet string (ssssqmmm), where */
|
|
/* ssss seconds since Jan 1, 1970, 4 bytes padded with */
|
|
/* leading 0's */
|
|
/* q quality flags, 1 byte */
|
|
/* mmm microseconds in a second, 3 bytes in range */
|
|
/* [0,999999], padded with 0's. */
|
|
/* Note: this is new type added to the spec in 2001/2002. */
|
|
/* 16 - UTF8string, any type length. Ex: "t16+30" specifies */
|
|
/* a fixed-length string of exactly 30 characters, whereas */
|
|
/* "t16-12" specifies a variable-length string of at most */
|
|
/* 12 characters. */
|
|
/* */
|
|
/* NOTE: Floating point is a special case in that its length is */
|
|
/* a combination of two numbers: fractional width (say 52 bits) */
|
|
/* and exponent width (say 11 bits). The length of the floating */
|
|
/* point type is computed according to the following algorithm: */
|
|
/* N = e*256 + f, */
|
|
/* where f = fractional width and e = exponent width. For stan- */
|
|
/* dard IEEE floating point format, N = 2071 for single-precision */
|
|
/* and N = 2868 for double-precision. Hence, most users will use */
|
|
/* the following notation for floating point types: */
|
|
/* "t7+2071" for single prec. and "t7+2868" for double prec. */
|
|
/* WARNING: This function will not accept type specifications for */
|
|
/* floating point exponents with a width greater than 127 bits or */
|
|
/* mantissas with a width greater than 255 bits. */
|
|
/* */
|
|
/* The other input arguments of this function are the length of a */
|
|
/* buffer to hold the ASN.1 string, and a pointer to that buffer. */
|
|
/* The 'asn1_len' argument is modified to equal the actual length of */
|
|
/* the ASN.1 string produced. */
|
|
/* */
|
|
/* If there is no error in this function, the return value is a */
|
|
/* pointer to where the ASN.1 string starts in the buffer. (The */
|
|
/* ASN.1 string always ends at the end of the buffer, but it begins */
|
|
/* anywhere within the buffer.) If an error does occur in this */
|
|
/* function, a NULL pointer is returned, and the global variable */
|
|
/* 'mms_op_err' gives further detail as to the nature of the problem */
|
|
/* that has caused this function to fail. */
|
|
/************************************************************************/
|
|
|
|
#define TYPE_NAME 0
|
|
#define BEG_STRUCT 2
|
|
#define PACKED 0
|
|
#define COMPONENT_NAME 0
|
|
#define BEG_COMP_TYPE 1
|
|
|
|
|
|
ST_UCHAR *ms_mk_asn1_type (ST_INT *asn1_len, ST_UCHAR *asn1, ST_CHAR *type_spec)
|
|
{
|
|
ST_CHAR *tspec;
|
|
ST_INT type;
|
|
ST_BOOLEAN literal;
|
|
ST_BOOLEAN number;
|
|
ST_INT type_len;
|
|
ST_BOOLEAN name;
|
|
ST_BOOLEAN m_packed;
|
|
ST_INT i;
|
|
ST_LONG num_elts;
|
|
ST_UCHAR acc_float_size;
|
|
ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_ENC_CTXT *aCtx = &localEncCtx;
|
|
|
|
|
|
/* Initialize everything first. */
|
|
|
|
S_LOCK_COMMON_RESOURCES ();
|
|
num_elts = 0L;
|
|
number = SD_FALSE;
|
|
name = SD_FALSE;
|
|
literal = SD_FALSE;
|
|
m_packed = SD_FALSE;
|
|
type_len = 0;
|
|
i = strlen (type_spec);
|
|
tspec = (ST_CHAR *) chk_malloc (2*i);
|
|
asn1r_strt_asn1_bld (aCtx, asn1,*asn1_len);
|
|
|
|
/* Replace abbreviations in the type definition string with the */
|
|
/* appropriate syntax and reset new length of type spec string. */
|
|
if ((i = type_subst (tspec,type_spec,i)) < 1)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_LEN0,tspec));
|
|
}
|
|
/* Loop through the 'tspec' string, from the back to the front. */
|
|
|
|
while (i > 0)
|
|
{
|
|
switch (tspec[--i])
|
|
{
|
|
case '>' :
|
|
if (number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_GT,tspec));
|
|
}
|
|
literal = SD_TRUE;
|
|
tspec[i] = '\0';
|
|
asn1r_strt_constr (aCtx);
|
|
break;
|
|
|
|
case '<' :
|
|
if (number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_LT,tspec));
|
|
}
|
|
literal = SD_FALSE;
|
|
if (wr_object_name (aCtx, &tspec[i+1]))
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_OBJNAME,tspec));
|
|
}
|
|
asn1r_fin_constr (aCtx, TYPE_NAME, CTX, 0);
|
|
break;
|
|
|
|
case '}' :
|
|
if (number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_RBRACE,tspec));
|
|
}
|
|
asn1r_strt_constr (aCtx); /* Start structure type.*/
|
|
asn1r_strt_constr (aCtx); /* Start component part.*/
|
|
asn1r_strt_constr (aCtx); /* Start last component.*/
|
|
asn1r_strt_constr (aCtx); /* Start component's */
|
|
break; /* explicit type spec. */
|
|
|
|
case '{' :
|
|
if (number)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_LBRACE,tspec));
|
|
}
|
|
if (tspec[i+1]=='}') /* Empty struct */
|
|
{
|
|
MLOG_ERR2 ("ms_mk_asn1_type: empty struct defined starting at offset %d TDL=%s", i, &tspec[i]);
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_LBRACE,tspec));
|
|
}
|
|
if (!name)
|
|
asn1r_fin_constr (aCtx, BEG_COMP_TYPE, CTX, 0);
|
|
asn1r_fin_constr (aCtx, SEQ_CODE, UNI, 0);
|
|
name = SD_FALSE;
|
|
asn1r_fin_constr (aCtx, 1, CTX, 0);
|
|
if (m_packed)
|
|
{
|
|
asn1r_wr_i16 (aCtx, 1);
|
|
asn1r_fin_prim (aCtx, PACKED,CTX);
|
|
}
|
|
asn1r_fin_constr (aCtx, BEG_STRUCT, CTX, 0);
|
|
m_packed = SD_FALSE;
|
|
break;
|
|
|
|
case ',' :
|
|
if (number)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_COMMA,tspec));
|
|
}
|
|
if (tspec[i+1]=='}' || tspec[i+1]==',') /* Ignore extra commas */
|
|
{
|
|
MLOG_ENC0 ("ms_mk_asn1_type: ',' followed by ',' or '}' in TDL string ignored.");
|
|
}
|
|
else
|
|
{
|
|
if (!name)
|
|
asn1r_fin_constr (aCtx, BEG_COMP_TYPE, CTX, 0);
|
|
asn1r_fin_constr (aCtx, SEQ_CODE, UNI, 0);
|
|
name = SD_FALSE;
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_strt_constr (aCtx);
|
|
}
|
|
break;
|
|
|
|
case ')' :
|
|
if (number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_RPAREN,tspec));
|
|
}
|
|
asn1r_fin_constr (aCtx, BEG_COMP_TYPE, CTX, 0);
|
|
name = SD_TRUE;
|
|
literal = SD_TRUE;
|
|
tspec[i] = '\0';
|
|
break;
|
|
|
|
case '(' :
|
|
if (number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_LPAREN,tspec));
|
|
}
|
|
literal = SD_FALSE;
|
|
asn1r_wr_vstr (aCtx, &tspec[i+1]);
|
|
asn1r_fin_prim (aCtx, COMPONENT_NAME, CTX);
|
|
break;
|
|
|
|
case 'p' :
|
|
if (literal)
|
|
break;
|
|
if (m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_P,tspec));
|
|
}
|
|
m_packed = SD_TRUE;
|
|
break;
|
|
|
|
case '+' :
|
|
if (literal)
|
|
break;
|
|
if (!number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_PLUS,tspec));
|
|
}
|
|
type_len = atoi (&tspec[i+1]);
|
|
tspec[i] = '\0';
|
|
number = SD_FALSE;
|
|
break;
|
|
|
|
case '-' :
|
|
if (literal)
|
|
break;
|
|
if (!number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_MINUS,tspec));
|
|
}
|
|
type_len = -atoi (&tspec[i+1]);
|
|
tspec[i] = '\0';
|
|
number = SD_FALSE;
|
|
break;
|
|
|
|
case 't' :
|
|
if (literal)
|
|
break;
|
|
if (!number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_T,tspec));
|
|
}
|
|
type = atoi (&tspec[i+1]);
|
|
switch (type)
|
|
{
|
|
case RT_BOOL :
|
|
case RT_GENERAL_TIME :
|
|
case RT_UTC_TIME :
|
|
if (type_len)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_BADLEN3,tspec));
|
|
}
|
|
asn1r_fin_prim (aCtx, (ST_UINT16) type,CTX);
|
|
break;
|
|
|
|
case RT_BIT_STRING :
|
|
case RT_OCTET_STRING :
|
|
case RT_VISIBLE_STRING :
|
|
case RT_UTF8_STRING:
|
|
asn1r_wr_i32 (aCtx, (ST_INT32) type_len);
|
|
asn1r_fin_prim (aCtx, (ST_UINT16) type,CTX);
|
|
break;
|
|
|
|
case RT_INTEGER :
|
|
case RT_UNSIGNED :
|
|
case RT_BINARY_TIME :
|
|
if (type_len > 127)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_BADLEN5,tspec));
|
|
}
|
|
asn1r_wr_u8 (aCtx, (ST_UCHAR) type_len);
|
|
asn1r_fin_prim (aCtx, (ST_UINT16) type, CTX);
|
|
break;
|
|
|
|
case RT_BCD :
|
|
if (type_len > 8 || type_len <= 0)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_BADLEN5,tspec));
|
|
}
|
|
asn1r_wr_u8 (aCtx, (ST_UCHAR) type_len);
|
|
asn1r_fin_prim (aCtx, (ST_UINT16) type, CTX);
|
|
break;
|
|
|
|
case RT_FLOATING_POINT :
|
|
if (type_len < 256)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_BADLEN7,tspec));
|
|
}
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_wr_u8 (aCtx, (ST_UCHAR) ((type_len>>8) & 0xFF)); /* write exp */
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
|
|
/* For IS MMS, first octet is exponent + sign + mantissa */
|
|
/* For DIS MMS, first octet is mantissa */
|
|
|
|
if (!m_use_dis_float)
|
|
{
|
|
acc_float_size =(ST_UCHAR) ((type_len>>8) & 0xFF); /* exp */
|
|
acc_float_size += (ST_UCHAR)(type_len & 0xFF); /* fract*/
|
|
++acc_float_size; /* sign */
|
|
asn1r_wr_u8 (aCtx, acc_float_size);
|
|
}
|
|
else
|
|
asn1r_wr_u8 (aCtx, (ST_UCHAR)(type_len & 0xFF)); /* write fract */
|
|
|
|
asn1r_fin_prim (aCtx, INT_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, (ST_UINT16) type, CTX, 0);
|
|
break;
|
|
|
|
default :
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_BADTYPE,tspec));
|
|
}
|
|
type_len = 0;
|
|
number = SD_FALSE;
|
|
break;
|
|
|
|
case ':' :
|
|
if (literal)
|
|
break;
|
|
if (number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_COLON,tspec));
|
|
}
|
|
tspec [i] = '\0';
|
|
num_elts = -1L;
|
|
break;
|
|
|
|
case ']' :
|
|
if (number || m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_RBRACKET,tspec));
|
|
}
|
|
asn1r_strt_constr (aCtx);
|
|
asn1r_strt_constr (aCtx);
|
|
tspec [i] = '\0';
|
|
break;
|
|
|
|
case '[' :
|
|
if (!number || !num_elts)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_LBRACKET,tspec));
|
|
}
|
|
asn1r_fin_constr (aCtx, 2,CTX,0);
|
|
if (m_packed)
|
|
num_elts = atol (strchr(&tspec[i+1],'p') + 1);
|
|
else
|
|
num_elts = atol (&tspec[i+1]);
|
|
if (num_elts < 1L)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_NUM_ELTS,tspec));
|
|
}
|
|
asn1r_wr_i32 (aCtx, num_elts);
|
|
asn1r_fin_prim (aCtx, 1, CTX);
|
|
if (m_packed)
|
|
{
|
|
asn1r_wr_i16 (aCtx, 1);
|
|
asn1r_fin_prim (aCtx, PACKED,CTX);
|
|
}
|
|
asn1r_fin_constr (aCtx, 1, CTX, 0);
|
|
num_elts = 0L;
|
|
number = SD_FALSE;
|
|
m_packed = SD_FALSE;
|
|
break;
|
|
|
|
case ' ' :
|
|
case '\t' :
|
|
case '\n' :
|
|
break;
|
|
|
|
default :
|
|
if (literal)
|
|
break;
|
|
if (tspec[i] >= '0' && tspec[i] <= '9')
|
|
{
|
|
if (m_packed)
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_DIGIT,tspec));
|
|
}
|
|
number = SD_TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (err_rtn (MVE_TYPEDEF_SYM_OTHER,tspec));
|
|
}
|
|
}
|
|
} /* end of while loop */
|
|
|
|
|
|
chk_free (tspec);
|
|
if (aCtx->asn1r_encode_overrun)
|
|
{
|
|
mms_op_err = ME_ASN1_ENCODE_OVERRUN;
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (NULL);
|
|
}
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
MLOG_ENC1 ("ASN.1 type def encoded from TDL=%s", type_spec);
|
|
MLOG_ENCH (ASN1_ENC_LEN(aCtx), ASN1_ENC_PTR(aCtx));
|
|
*asn1_len = ASN1_ENC_LEN(aCtx);
|
|
return (ASN1_ENC_PTR(aCtx));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* type_subst */
|
|
/* Function to pre-processes type definition strings. It substitutes */
|
|
/* primitive syntax for certain abbreviations defined in the 'abbrev' */
|
|
/* array. The syntax of the resulting string is able to be parsed */
|
|
/* simply by ms_mk_asn1_type. This function returns the length of the */
|
|
/* destination string. */
|
|
/************************************************************************/
|
|
|
|
static ST_INT type_subst (ST_CHAR *dest_str, ST_CHAR *src_str, ST_INT src_len)
|
|
{
|
|
ST_BOOLEAN literal1, literal2; /* booleans indicating we're in a type */
|
|
/* name or component name literal string*/
|
|
ST_INT i, j, k, n; /* indexes and counters */
|
|
ST_BOOLEAN found; /* boolean indicating a string starting */
|
|
/* with a capital letter matches an */
|
|
/* abbreviation and is to be replaced */
|
|
|
|
literal1 = literal2 = SD_FALSE;
|
|
i = j = 0;
|
|
|
|
while (i < src_len) /* step through the source string */
|
|
{
|
|
if (literal1)
|
|
{
|
|
if (src_str[i] == '>') /* Keep track of when a type name */
|
|
literal1 = SD_FALSE; /* (delimited by '<' and '>') is */
|
|
} /* beginning and ending. Abbreviations */
|
|
else if (literal2) /* are not substituted inside type */
|
|
{ /* names. Ditto for component names */
|
|
if (src_str[i] == ')') /* (delimited by '(' and ')'). */
|
|
literal2 = SD_FALSE;
|
|
}
|
|
else if (src_str[i] == '<')
|
|
literal1 = SD_TRUE;
|
|
else if (src_str[i] == '(')
|
|
literal2 = SD_TRUE;
|
|
else if (src_str[i] >= 'A' && src_str[i] <= 'z')
|
|
{
|
|
found = SD_FALSE;
|
|
for (n = 0; n < numTdlTypes; n++)
|
|
{
|
|
if (strnicmp (tdlTypes[n].abbrev, &src_str[i], strlen (tdlTypes[n].abbrev)))
|
|
continue;
|
|
else
|
|
{
|
|
found = SD_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (found)
|
|
{
|
|
k = strlen (tdlTypes[n].subType);
|
|
memcpy (&dest_str[j],tdlTypes[n].subType,k);
|
|
j += k;
|
|
i += strlen (tdlTypes[n].abbrev);
|
|
continue;
|
|
}
|
|
}
|
|
if (!isspace(src_str[i])) /* do not copy whitespace chars */
|
|
dest_str[j++] = src_str[i];
|
|
i++; /* ALWAYS increment src index */
|
|
}
|
|
dest_str[j] = '\0';
|
|
return (j);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
/* wr_object_name */
|
|
/* Function to write an object name string to the ASN.1 stream */
|
|
/* according to the ObjectName production in the MMS protocol */
|
|
/* specification. The input string takes the form: */
|
|
/* string1:IDENTIFIER, where string1 is "@VMD" for a VMD-specific */
|
|
/* object, "@AA" for an AA-specific object, or a valid IDENTIFIER */
|
|
/* naming a domain for a domain-specific object. IDENTIFIER is the */
|
|
/* actual name of the object within the domain, VMD, or association- */
|
|
/* specific environment. Returns 0 if successful, nonzero otherwise. */
|
|
/************************************************************************/
|
|
|
|
static ST_RET wr_object_name (ASN1_ENC_CTXT *aCtx, ST_CHAR *objname)
|
|
{
|
|
ST_CHAR *ptr;
|
|
|
|
if ((ptr = strchr (objname,':')) == NULL) /* check for colon */
|
|
{
|
|
asn1r_wr_vstr (aCtx, objname); /* Default is VMD specific */
|
|
asn1r_fin_prim (aCtx, 0,CTX);
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
*ptr = '\0'; /* replace colon with null char */
|
|
ptr++; /* "ptr" pts to string after ':'*/
|
|
if (!strcmp (objname,"@VMD"))
|
|
{
|
|
asn1r_wr_vstr (aCtx, ptr);
|
|
asn1r_fin_prim (aCtx, 0,CTX);
|
|
}
|
|
else if (!strcmp (objname,"@AA"))
|
|
{
|
|
asn1r_wr_vstr (aCtx, ptr);
|
|
asn1r_fin_prim (aCtx, 2,CTX);
|
|
}
|
|
else
|
|
{
|
|
asn1r_strt_constr (aCtx); /* Domain-specific when string */
|
|
asn1r_wr_vstr (aCtx, ptr); /* before ':' is anything else */
|
|
asn1r_fin_prim (aCtx, VISTR_CODE,UNI);
|
|
asn1r_wr_vstr (aCtx, objname);
|
|
asn1r_fin_prim (aCtx, VISTR_CODE,UNI);
|
|
asn1r_fin_constr (aCtx, 1,CTX,0);
|
|
}
|
|
return (SD_SUCCESS);
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* err_rtn */
|
|
/* Function to be called when there is an error in ms_mk_asn1_type. */
|
|
/************************************************************************/
|
|
|
|
static ST_UCHAR *err_rtn (ST_RET error, ST_CHAR *tspec)
|
|
{
|
|
mms_op_err = error;
|
|
chk_free (tspec);
|
|
return (NULL);
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* ms_asn1_to_tdl */
|
|
/************************************************************************/
|
|
|
|
ST_CHAR *ms_asn1_to_tdl (ST_UCHAR *asn1_ptr, ST_INT asn1_len, ST_INT max_tdl_len)
|
|
{
|
|
ST_CHAR *tdl_buf;
|
|
ST_INT tdl_len;
|
|
RUNTIME_CTRL *rt_ctrl;
|
|
|
|
S_LOCK_COMMON_RESOURCES ();
|
|
|
|
/* Create temporary runtime type table. */
|
|
/* Last arg allows biggest array "theoretically" possible to allocate.*/
|
|
rt_ctrl = ms_runtime_create (asn1_ptr, asn1_len,
|
|
(UINT_MAX/sizeof(RUNTIME_TYPE))-100);
|
|
if (!rt_ctrl) /* if ASN.1 decode failed */
|
|
{
|
|
mms_op_err = MVE_ASN1_TO_RT;
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (NULL); /* quit */
|
|
}
|
|
|
|
tdl_buf = (ST_CHAR *) chk_calloc (1, max_tdl_len);
|
|
tdl_len = ms_runtime_to_tdl (rt_ctrl->rt_first, rt_ctrl->rt_num, tdl_buf, max_tdl_len);
|
|
|
|
if (tdl_len == 0)
|
|
{
|
|
mms_op_err = MVE_ASN1_TO_RT;
|
|
chk_free (tdl_buf);
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (NULL);
|
|
}
|
|
|
|
tdl_buf = (ST_CHAR *) chk_realloc (tdl_buf, tdl_len);
|
|
ms_runtime_destroy (rt_ctrl); /* destroy temp rt type */
|
|
|
|
S_UNLOCK_COMMON_RESOURCES ();
|
|
return (tdl_buf);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ms_runtime_to_tdl */
|
|
/************************************************************************/
|
|
static ST_INT add_tdl_separator (ST_CHAR *tdl_buf, ST_INT index,
|
|
ST_BOOLEAN member_found,
|
|
ST_BOOLEAN named_component_found);
|
|
|
|
ST_INT ms_runtime_to_tdl (SD_CONST RUNTIME_TYPE *rt, ST_INT rt_num,
|
|
ST_CHAR *tdl_buf, ST_INT max_tdl_len)
|
|
{
|
|
ST_INT i;
|
|
ST_INT total_size;
|
|
SD_CONST RUNTIME_TYPE * rt_ptr;
|
|
#define SIZE_OF_TEMP_BUF 30
|
|
ST_CHAR temp_buf[SIZE_OF_TEMP_BUF];
|
|
ST_INT temp_size; /* len of string in temp_buf */
|
|
ST_BOOLEAN overrun_detected;
|
|
SD_CONST ST_CHAR * comp_name; /* component name */
|
|
ST_INT comp_name_len; /* len of component name*/
|
|
|
|
struct struct_tracking {
|
|
ST_BOOLEAN member_found;
|
|
};
|
|
struct struct_tracking nest_level[ASN1_MAX_LEVEL];
|
|
ST_BOOLEAN named_component_found;
|
|
|
|
ST_INT cur_nest_level;
|
|
|
|
for (i = 0; i < ASN1_MAX_LEVEL; i++)
|
|
{
|
|
nest_level[i].member_found = SD_FALSE;
|
|
}
|
|
|
|
i=0;
|
|
overrun_detected = SD_FALSE;
|
|
rt_ptr = rt;
|
|
total_size = 0;
|
|
cur_nest_level = 0;
|
|
while ((i < rt_num) && (overrun_detected == SD_FALSE))
|
|
{
|
|
named_component_found = SD_FALSE; /* assume comp name not found */
|
|
comp_name = ms_comp_name_find (rt_ptr);
|
|
if (comp_name != NULL && comp_name[0] != 0)
|
|
{
|
|
comp_name_len = strlen (comp_name);
|
|
|
|
/* Make sure there's room for comp_name + separator + '(' + ')'. */
|
|
if ((total_size + comp_name_len + 3) < max_tdl_len)
|
|
{
|
|
/* CRITICAL: named_component_found is not yet set for this call.*/
|
|
total_size += add_tdl_separator (tdl_buf, total_size,
|
|
nest_level[cur_nest_level].member_found,
|
|
named_component_found);
|
|
strcpy (&tdl_buf[total_size], "(");
|
|
total_size += 1;
|
|
strcpy (&tdl_buf[total_size],comp_name);
|
|
total_size += comp_name_len;
|
|
strcpy (&tdl_buf[total_size], ")");
|
|
total_size += 1;
|
|
}
|
|
else
|
|
{
|
|
overrun_detected = SD_TRUE;
|
|
}
|
|
named_component_found = SD_TRUE;
|
|
}
|
|
|
|
if (rt_ptr->el_tag == RT_ARR_END || rt_ptr->el_tag == RT_STR_END)
|
|
nest_level[cur_nest_level].member_found = SD_FALSE;
|
|
else
|
|
{
|
|
if (total_size + 1 < max_tdl_len)
|
|
{
|
|
total_size += add_tdl_separator (tdl_buf, total_size,
|
|
nest_level[cur_nest_level].member_found,
|
|
named_component_found);
|
|
}
|
|
else
|
|
overrun_detected = SD_TRUE;
|
|
nest_level[cur_nest_level].member_found = SD_TRUE;
|
|
}
|
|
|
|
temp_buf[0] = '\0'; /* start with NULL string */
|
|
switch (rt_ptr->el_tag)
|
|
{
|
|
case RT_ARR_START :
|
|
sprintf (temp_buf, "[%d:", (ST_INT)rt_ptr->u.arr.num_elmnts);
|
|
cur_nest_level++;
|
|
break;
|
|
|
|
case RT_STR_START :
|
|
strcpy (temp_buf, "{");
|
|
cur_nest_level++;
|
|
break;
|
|
|
|
case RT_BOOL :
|
|
strcpy (temp_buf, "Bool");
|
|
break;
|
|
|
|
case RT_BIT_STRING :
|
|
if (rt_ptr->u.p.el_len < 0)
|
|
sprintf (temp_buf, "BVstring%d", abs (rt_ptr->u.p.el_len));
|
|
else
|
|
sprintf (temp_buf, "Bstring%d", rt_ptr->u.p.el_len);
|
|
break;
|
|
|
|
case RT_INTEGER :
|
|
switch (rt_ptr->u.p.el_len)
|
|
{
|
|
case 1:
|
|
strcpy (temp_buf, "Byte");
|
|
break;
|
|
case 2:
|
|
strcpy (temp_buf, "Short");
|
|
break;
|
|
case 4:
|
|
strcpy (temp_buf, "Long");
|
|
break;
|
|
#ifdef INT64_SUPPORT
|
|
case 8:
|
|
strcpy (temp_buf, "Int64");
|
|
break;
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case RT_UNSIGNED :
|
|
switch (rt_ptr->u.p.el_len)
|
|
{
|
|
case 1:
|
|
strcpy (temp_buf, "Ubyte");
|
|
break;
|
|
case 2:
|
|
strcpy (temp_buf, "Ushort");
|
|
break;
|
|
case 4:
|
|
strcpy (temp_buf, "Ulong");
|
|
break;
|
|
#ifdef INT64_SUPPORT
|
|
case 8:
|
|
strcpy (temp_buf, "Uint64");
|
|
break;
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case RT_FLOATING_POINT :
|
|
switch (rt_ptr->u.p.el_len)
|
|
{
|
|
case 4:
|
|
strcpy (temp_buf, "Float");
|
|
break;
|
|
case 8:
|
|
strcpy (temp_buf, "Double");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case RT_OCTET_STRING :
|
|
if (rt_ptr->u.p.el_len < 0)
|
|
sprintf (temp_buf, "OVstring%d", abs (rt_ptr->u.p.el_len));
|
|
else
|
|
sprintf (temp_buf, "Ostring%d", rt_ptr->u.p.el_len);
|
|
break;
|
|
|
|
case RT_VISIBLE_STRING :
|
|
if (rt_ptr->u.p.el_len < 0)
|
|
sprintf (temp_buf, "Vstring%d", abs (rt_ptr->u.p.el_len));
|
|
else
|
|
sprintf (temp_buf, "Fstring%d", rt_ptr->u.p.el_len);
|
|
break;
|
|
|
|
case RT_GENERAL_TIME :
|
|
strcpy (temp_buf, "Gtime");
|
|
break;
|
|
|
|
case RT_BINARY_TIME :
|
|
sprintf (temp_buf, "Btime%d", rt_ptr->u.p.el_len);
|
|
break;
|
|
|
|
case RT_BCD :
|
|
sprintf (temp_buf, "Bcd%d", (ST_INT)rt_ptr->u.p.el_len);
|
|
break;
|
|
|
|
case RT_BOOLEANARRAY :
|
|
break;
|
|
|
|
case RT_UTC_TIME:
|
|
strcpy (temp_buf, "Utctime");
|
|
break;
|
|
|
|
case RT_UTF8_STRING:
|
|
if (rt_ptr->u.p.el_len < 0)
|
|
sprintf (temp_buf, "UTF8Vstring%d", (ST_INT) abs (rt_ptr->u.p.el_len));
|
|
else
|
|
sprintf (temp_buf, "UTF8string%d", (ST_INT) (rt_ptr->u.p.el_len));
|
|
break;
|
|
|
|
case RT_STR_END :
|
|
strcpy (temp_buf, "}");
|
|
cur_nest_level--;
|
|
break;
|
|
|
|
case RT_ARR_END :
|
|
strcpy (temp_buf, "]");
|
|
cur_nest_level--;
|
|
break;
|
|
}
|
|
|
|
|
|
temp_size = strlen (temp_buf);
|
|
if (temp_size == 0)
|
|
{ /* If buffer empty, rt_ptr contains unrecognized type*/
|
|
/* DEBUG: this should NEVER happen. Chk for memory corruption. */
|
|
MLOG_ERR1 ("RUNTIME_TYPE contains illegal el_tag = %d", rt_ptr->el_tag);
|
|
return (0); /* error */
|
|
}
|
|
if (total_size + temp_size < max_tdl_len)
|
|
{
|
|
strcpy (&tdl_buf[total_size], temp_buf);
|
|
total_size += temp_size;
|
|
}
|
|
else
|
|
overrun_detected = SD_TRUE;
|
|
|
|
rt_ptr++; /* point to next runtime element*/
|
|
i++;
|
|
} /* end main loop*/
|
|
|
|
if (overrun_detected == SD_TRUE)
|
|
{
|
|
MLOG_NERR1 ("ms_runtime_to_tdl: tdl buffer overrun (max=%d)", max_tdl_len);
|
|
total_size = 0;
|
|
}
|
|
else
|
|
{
|
|
tdl_buf[total_size] = 0; /* ensure a Null terminator */
|
|
total_size++; /* account for a Null terminator*/
|
|
}
|
|
|
|
return (total_size);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* add_tdl_separator */
|
|
/************************************************************************/
|
|
|
|
static ST_INT add_tdl_separator (ST_CHAR *tdl_buf, ST_INT index,
|
|
ST_BOOLEAN member_found,
|
|
ST_BOOLEAN named_component_found)
|
|
{
|
|
if ((member_found == SD_TRUE) &&
|
|
(named_component_found == SD_FALSE))
|
|
{
|
|
strcpy (&tdl_buf[index], ",");
|
|
return (1);
|
|
}
|
|
else
|
|
{
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ms_tdl_to_runtime */
|
|
/* This function converts TDL to ASN.1 and then ASN.1 to RUNTIME_TYPE. */
|
|
/* NOTE: this function allocates array of RUNTIME_TYPE structs by */
|
|
/* calling "ms_runtime_create". The array must be freed by */
|
|
/* calling "ms_runtime_destroy" (DO NOT use M_FREE or chk_free). */
|
|
/************************************************************************/
|
|
RUNTIME_CTRL *ms_tdl_to_runtime (ST_CHAR *tdl, /* TDL string */
|
|
ST_UCHAR *asn1_buf, /* ASN.1 buffer */
|
|
ST_INT asn1_buf_len) /* buffer len */
|
|
{
|
|
ST_UCHAR *asn1_start; /* ptr to ASN.1 encoded type */
|
|
RUNTIME_CTRL *rt_ctrl = NULL; /* assume failure */
|
|
|
|
/* NOTE: ms_mk_.. overwrites asn1_buf_len with len of ASN.1 encoding */
|
|
asn1_start = ms_mk_asn1_type (&asn1_buf_len, asn1_buf, tdl);
|
|
if (asn1_start) /* successful */
|
|
rt_ctrl = ms_runtime_create (asn1_start, asn1_buf_len,
|
|
(UINT_MAX/sizeof(RUNTIME_TYPE))-100);
|
|
return (rt_ctrl);
|
|
}
|