Files
microser/mmslib/mmsl/mms_tdef.c

3266 lines
107 KiB
C
Raw Normal View History

2026-06-15 15:48:16 +08:00
/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1986 - 2006, All Rights Reserved. */
/* */
/* PROPRIETARY AND CONFIDENTIAL */
/* */
/* MODULE NAME : mms_tdef.c */
/* PRODUCT(S) : MMSEASE */
/* */
/* MODULE DESCRIPTION : */
/* Function to decode ASN.1 type definitions into Runtime typedefs */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* ms_runtime_create */
/* ms_runtime_destroy */
/* ms_is_rt_prim */
/* ms_rt_el_tag_text */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 08/06/07 JRB 59 Chg ms_rt_bld_* to avoid realloc (reduces */
/* max memory usage and fragmentation). */
/* 04/17/07 JRB 58 ms_get_blocked_length: set also prim_count. */
/* 02/02/07 JRB 57 Fix log message in ms_rt_bld_chk_state. */
/* 10/30/06 JRB 56 Add ms_rt_bld_* functions. */
/* 03/22/06 EJV 55 Chg RT_GENERAL_TIME to use time_t len & algn.*/
/* 01/30/06 GLB 54 Integrated porting changes for VMS */
/* 08/01/05 JRB 53 Avoid risky cast to remove const. */
/* 04/07/05 MDE 52 Changed ERR log to NERR */
/* 03/10/05 JRB 51 Add ms_rt_el_tag_text funct. */
/* 02/23/05 JRB 50 ms_is_rt_prim: add SD_CONST to arg. */
/* 02/21/05 JRB 49 Del m_struct_* for Lite, created by FOUNDRY. */
/* Del asserts checking m_struct_*. */
/* 01/27/05 JRB 48 Move m_lite_data.. extern to mms_vvar.h. */
/* Init m_data_algn_tbl=NULL if FOUNDRY. */
/* Add ; to one more MLOG* call. */
/* 11/02/04 JRB 47 For MMS_LITE, use m_lite_data_algn_tbl */
/* generated by Foundry for target platform. */
/* 11/01/04 JRB 46 Add ; on MLOG* calls to work with new macros.*/
/* 06/29/04 JRB 45 str_done: chk for empty structure. */
/* 12/09/03 JRB 44 Add LYNX support. */
/* 11/07/03 JRB 43 Fix misleading log message when decode done. */
/* 10/13/03 EJV 42 Removed defined(__VAX). */
/* 06/05/03 JRB 41 type_name_cstr_done: copy component names */
/* for USE_RT_TYPE_2. */
/* 04/28/03 JRB 40 Eliminate compiler warnings. */
/* 04/28/03 JRB 39 Add UTF8string support (see RT_UTF8_STRING). */
/* 03/13/03 JRB 38 u_ml_get_rt_type: chg from "func ptr" to func.*/
/* 02/20/03 JRB 37 get_str_comp_name ret err if name index */
/* can't be found for USE_RT_TYPE_3. */
/* type_name_cstr_done save & restore comp name */
/* for USE_RT_TYPE_2/USE_RT_TYPE_3. */
/* 02/20/03 JRB 36 Del PSOS code. */
/* 01/20/03 CRM 35 Added "defined(linux)" code. */
/* 01/03/03 JRB 34 Move arr_loop* globals to locals in ms_get.. */
/* 12/31/02 MDE 33 Eliminate use of m_calc_rt_size global. */
/* 12/26/02 JRB 32 Add ms_asn1_to_runtime_x for backward compat.*/
/* 12/16/02 JRB 31 Add ms_is_rt_prim funct. */
/* 11/11/02 JRB 30 Chg ms_runtime_create/destroy args. */
/* Make ms_asn1_to_runtime static, must call */
/* ms_runtime_create instead. */
/* Use DEC_INFO struct to avoid global vars. */
/* Pass aCtx to ms_asn1_to_runtime & pass */
/* DEC_INFO in aCtx->usr_info[0]. */
/* 04/16/02 MDE 29 Now set name index for named struct elements */
/* 03/04/02 JRB 28 Add more "SD_CONST RUNTIME_TYPE *". */
/* 12/20/01 JRB 27 Converted to use ASN1R (re-entrant ASN1) */
/* 11/14/01 EJV 26 Added support for new MMS type UtcTime: */
/* Added fun get_utc_time_el; */
/* set_type_tags: added code for tag 17; */
/* _ms_m_get_rt_info: added case for RT_UTC_TIME*/
/* _ms_log_runtime: added case for RT_UTC_TIME; */
/* 10/18/01 JRB 25 Eliminate warning. */
/* 08/29/00 JRB 24 Del ms_comp_name_find function. Use macro. */
/* 07/28/00 JRB 23 Simplify RT_TYPE ifdefs. */
/* Fix SD_CONST usage & lint warnings. */
/* Make ms_type_nam* static. Only used here. */
/* 07/13/00 JRB 22 Add ms_runtime_create, ms_runtime_destroy, */
/* ms_comp_name_find. */
/* 06/29/00 JRB 21 Make ms_asn1_to_runtime work for MMS LITE. */
/* Must def USE_RT_TYPE_2 to save comp names. */
/* 09/13/99 MDE 20 Added SD_CONST modifiers */
/* 04/14/99 MDE 19 Removed unnecessary include files */
/* 02/23/99 JRB 18 MMS_LITE: "m_data_algn.. = m_def_data_algn.."*/
/* Don't need packed for backward compatibility.*/
/* 09/10/98 MDE 17 Changes to work better with MMS-LITE */
/* 08/21/98 EJV 16 __hpux STRSTRT_ALGN set from 3 to 0, and */
/* 07/23/98 RKR 15 OPEN_VMS STRSTRT_ALGN set from 3 to 0 */
/* 06/26/98 EJV 14 m_def_data_algn_tbl only for __alpha DECUNIX.*/
/* 06/03/98 MDE 13 Corrected structure end alignment handling */
/* 03/23/98 MDE 12 Tweaks to structure alignment */
/* 03/12/98 MDE 11 Worked on structure alignment */
/* 02/10/98 MDE 10 Runtime type changes for LITE */
/* 11/04/97 DSF 09 Fixed alignment table for WIN32 */
/* 10/30/97 MDE 08 Minor logging change */
/* 09/29/97 MDE 07 Minor logging change */
/* 08/27/97 MDE 06 Fixed problem with log runtime w/numrt = 0 */
/* 08/15/97 MDE 05 BTOD handling changes */
/* 08/04/97 MDE 04 Minor cleanup */
/* 06/19/97 MDE 03 Added 64 bit integer support */
/* 06/09/97 MDE 02 Fixed MMS-LITE compile problems, other minor */
/* 04/08/97 MDE 01 Fixed 'RT Table too small prob w/named types */
/* 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 "mms_pvar.h"
#include "mms_vvar.h"
#include "asn1defs.h"
#if defined(MMS_LITE)
#include "mvl_defs.h"
#endif
/************************************************************************/
/************************************************************************/
/* 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
/************************************************************************/
#ifdef MMS_LITE
ST_VOID (*u_rt_type_process) (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt);
#endif
static ST_VOID _ms_log_runtime (ST_INT indent, SD_CONST RUNTIME_TYPE *rt,
ST_INT num_rt);
static ST_VOID _do_padding (RUNTIME_TYPE *padDest,
ST_INT *curr_offset,
ST_INT algn);
static ST_VOID _get_struct_start_align (SD_CONST RUNTIME_TYPE *rt,
ST_INT *algn_out,
ST_INT *ellen_out);
static ST_VOID _get_struct_end_align (SD_CONST RUNTIME_TYPE *rt,
ST_INT *algn_out,
ST_INT *ellen_out);
static ST_VOID _get_arr_start_align (SD_CONST RUNTIME_TYPE *rt,
ST_INT *algn_out,
ST_INT *ellen_out);
/************************************************************************/
static ST_VOID str_comp_seq_start (ASN1_DEC_CTXT *aCtx); /* CTX 1 CSTR - seq of comp */
static ST_VOID get_num_arr_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID array_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID arr_el_cstr_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_arr_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID float_cstr_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_float_exp (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_float_fract (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_str_packed (ASN1_DEC_CTXT *aCtx); /* CTX 0 BOOL - packed */
static ST_VOID get_arr_packed (ASN1_DEC_CTXT *aCtx);
static ST_VOID type_name_cstr_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID type_name_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_named_type (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_array_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_struct_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_bool_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_bitstr_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_int_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_uint_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_float_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_octstr_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_vstr_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_gtime_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_btime_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_bcd_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_utc_time_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_utf8_el (ASN1_DEC_CTXT *aCtx);
static ST_VOID set_type_tags (ASN1_DEC_CTXT *aCtx);
static ST_VOID td_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID td_err (ASN1_DEC_CTXT *aCtx, ST_RET err);
/************************************************************************/
/************************************************************************/
/* Variables and definitions used in this module */
static RUNTIME_TYPE *rt_ptr; /* current runtime element */
static ST_INT rt_count; /* total elements in runtime table */
/* (also index) */
static ST_INT rt_limit; /* max # runtime elements */
/* defines used during decode for various types of errors */
#define PDU_ERR 2
#define LENGTH_ERR 3
#define UNSUPPORTED 4
#define UNKNOWN_TYPENAME 5
#define RUNTIME_LIMIT 6
static ST_INT arr_index[ASN1_MAX_LEVEL]; /* index to array element start */
static RUNTIME_TYPE *struct_tracking[ASN1_MAX_LEVEL];
static OBJECT_NAME type_name; /* temp storage */
/************************************************************************/
/* ms_asn1_to_runtime */
/************************************************************************/
static ST_INT _ms_asn1_to_runtime (ASN1_DEC_CTXT *aCtx,
ST_UCHAR *asn1ptr, ST_UINT asn1len,
RUNTIME_TYPE *rt_table, ST_INT rt_len)
{
MMSDEC_INFO dummy_rslt;
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
S_LOCK_COMMON_RESOURCES ();
_mmsdec_rslt = &dummy_rslt; /* give _ms_get_mms_objname a place to point */
/* to */
rt_ptr = rt_table; /* initialize the element pointer */
decInfo->rt_start = rt_table;/* initialize the element pointer */
rt_limit = rt_len; /* save the limit */
rt_count = 0; /* set element count = 0 */
#if defined(USE_RT_TYPE_2)
decInfo->comp_name_used = 0;
decInfo->comp_name_ptr = decInfo->comp_name_buf;
#endif
aCtx->asn1r_decode_method = ASN1_TAG_METHOD;
aCtx->asn1r_decode_done_fun = td_done; /* set up done function */
aCtx->asn1r_err_fun = td_err; /* set up error detected fun */
set_type_tags (aCtx); /* setup the legal tags */
asn1r_decode_asn1 (aCtx, asn1ptr,asn1len); /* do message decode and */
/* If decode was OK and we are producing a real RT table, need to set */
/* the data element sizes. */
if (rt_count && !decInfo->calc_only)
{
ms_rt_size_calc (rt_table,rt_count);
/* Also log the runtime type, if selected */
if (mms_debug_sel & MMS_LOG_RT)
ms_log_runtime (rt_table, rt_count);
}
S_UNLOCK_COMMON_RESOURCES ();
return (rt_count); /* return # elements used */
}
/************************************************************************/
/* set_type_tags */
/* setup tags for main TypeSpecfication decode */
/************************************************************************/
static ST_VOID set_type_tags (ASN1_DEC_CTXT *aCtx)
{
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,get_named_type);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_array_el);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_struct_el);
ASN1R_TAG_ADD (aCtx, CTX,3,get_bool_el);
ASN1R_TAG_ADD (aCtx, CTX,4,get_bitstr_el);
ASN1R_TAG_ADD (aCtx, CTX,5,get_int_el);
ASN1R_TAG_ADD (aCtx, CTX,6,get_uint_el);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,7,get_float_el);
ASN1R_TAG_ADD (aCtx, CTX,9,get_octstr_el);
ASN1R_TAG_ADD (aCtx, CTX,10,get_vstr_el);
ASN1R_TAG_ADD (aCtx, CTX,11,get_gtime_el);
ASN1R_TAG_ADD (aCtx, CTX,12,get_btime_el);
ASN1R_TAG_ADD (aCtx, CTX,13,get_bcd_el);
ASN1R_TAG_ADD (aCtx, CTX,17,get_utc_time_el);
ASN1R_TAG_ADD (aCtx, CTX,RT_UTF8_STRING,get_utf8_el);
}
/************************************************************************/
/* rt_ptr_inc */
/* move the rt_ptr to next element and inc count. Checks vs limit. */
/************************************************************************/
static ST_VOID rt_ptr_inc (ASN1_DEC_CTXT *aCtx)
{
if (++rt_count >= rt_limit) /* move the runtime pointer */
{
MLOG_CDEC0 ("decode_done");
aCtx->asn1r_decode_done = SD_TRUE;
}
else
rt_ptr++; /* point to next runtime element */
}
/************************************************************************/
/************************************************************************/
/* TypeSpecification element get start functions */
/************************************************************************/
/************************************************************************/
/* get_named_type */
/* named type element, check if in database, copy if so. */
/************************************************************************/
static ST_VOID get_named_type (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_named_type");
/* execute 'type_name_done' when type name has been extracted */
_ms_get_mms_objname (aCtx, &type_name,type_name_done);
}
/************************************************************************/
/* type_name_done */
/* The type_name objectName has been read, and is now in 'type_name' */
/* That means that the type_name constructor now can be complete. */
/************************************************************************/
static ST_VOID type_name_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("type_name_done");
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = type_name_cstr_done;
}
/************************************************************************/
/* get_array_el */
/* array element, setup to get array parameters. */
/************************************************************************/
static ST_VOID get_array_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
MLOG_CDEC0 ("get_array_el");
if (!decInfo->calc_only)
rt_ptr->el_tag = RT_ARR_START; /* write the tag */
arr_index[aCtx->asn1r_msg_level] = rt_count; /* save index to this element */
ASN1R_TAG_ADD (aCtx, CTX,0,get_arr_packed);/* set up to get next items */
ASN1R_TAG_ADD (aCtx, CTX,1,get_num_arr_el);
}
/************************************************************************/
/* get_struct_el */
/* structure element, setup to get struct parameters. */
/************************************************************************/
static ST_VOID get_struct_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
MLOG_CDEC0 ("get_struct_el");
if (++rt_count >= rt_limit)
{
MLOG_NERR0 ("ASN.1 to RT Error : RT Table too small");
asn1r_set_dec_err (aCtx, RUNTIME_LIMIT);
}
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_STR_START; /* write the tag */
struct_tracking[aCtx->asn1r_msg_level] = rt_ptr;
rt_ptr++; /* point to next runtime element*/
}
}
ASN1R_TAG_ADD (aCtx, CTX,0,get_str_packed);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,str_comp_seq_start);
}
/************************************************************************/
/* Simple type get functions */
/************************************************************************/
/************************************************************************/
/* get_bool_el */
/* boolean element encountered. */
/************************************************************************/
static ST_VOID get_bool_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
MLOG_CDEC0 ("get_bool_el");
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_BOOL; /* set data type tag */
rt_ptr->u.p.el_len = 1; /* set max data length */
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
/************************************************************************/
/* get_bitstr_el */
/* bitstring element encountered. */
/************************************************************************/
static ST_VOID get_bitstr_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_INT32 size;
MLOG_CDEC0 ("get_bitstr_el");
if (asn1r_get_i32 (aCtx, &size))
asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_BIT_STRING; /* set data type tag */
rt_ptr->u.p.el_len = (ST_INT) size; /* save size */
if (rt_ptr->u.p.el_len != (ST_INT) size) /* make sure OK cast */
{
MLOG_NERR0 ("Bitstring size too big");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */
}
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
}
/************************************************************************/
/* get_int_el */
/* integer element encountered. */
/************************************************************************/
static ST_VOID get_int_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_UCHAR size;
MLOG_CDEC0 ("get_int_el");
if (asn1r_get_u8 (aCtx, &size) || size %8) /* read integer */
asn1r_set_dec_err (aCtx, LENGTH_ERR); /* if too long or not byte size */
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_INTEGER; /* set data type tag */
rt_ptr->u.p.el_len = 1; /* set max data length */
rt_ptr->u.p.el_len = (ST_INT) size/8; /* looks OK so far */
if ((rt_ptr->u.p.el_len != sizeof (ST_CHAR) &&
rt_ptr->u.p.el_len != sizeof (ST_INT16) &&
rt_ptr->u.p.el_len != sizeof (ST_INT) && /*** decunix use 1,2,4,8 bytes ***/
#ifdef INT64_SUPPORT
rt_ptr->u.p.el_len != sizeof (ST_INT64) &&
#endif
rt_ptr->u.p.el_len != sizeof (ST_INT32)) ||
size % 8)
{
MLOG_NERR0 ("Integer length not supported");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* not standard size int */
}
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
}
/************************************************************************/
/* get_uint_el */
/* unsigned element encountered. */
/************************************************************************/
static ST_VOID get_uint_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_UCHAR size;
MLOG_CDEC0 ("get_uint_el");
if (asn1r_get_u8 (aCtx, &size) || size %8) /* read integer */
asn1r_set_dec_err (aCtx, LENGTH_ERR); /* if too long or not byte size */
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_UNSIGNED; /* set data type tag */
rt_ptr->u.p.el_len = (ST_INT) size/8; /* looks OK so far */
if ((rt_ptr->u.p.el_len != sizeof (ST_CHAR) &&
rt_ptr->u.p.el_len != sizeof (ST_INT16) &&
rt_ptr->u.p.el_len != sizeof (ST_INT) && /*** decunix use 1,2,4,8 bytes ***/
#ifdef INT64_SUPPORT
rt_ptr->u.p.el_len != sizeof (ST_INT64) &&
#endif
rt_ptr->u.p.el_len != sizeof (ST_INT32)) ||
size % 8)
{
MLOG_NERR0 ("Integer length not supported");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* not standard size int */
}
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
}
/************************************************************************/
/************************************************************************/
/* get_float_el */
/* float element encountered. */
/************************************************************************/
static ST_UCHAR float_f;
static ST_UCHAR float_e;
static ST_VOID get_float_el (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_float_el");
ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_float_fract);
}
/************************************************************************/
/* get_float_fract */
/* float element fractional positions (unsigned 8) encountered */
/************************************************************************/
static ST_VOID get_float_fract (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_float_fract");
if (asn1r_get_u8 (aCtx, &float_f))
asn1r_set_dec_err (aCtx, UNSUPPORTED);
else
ASN1R_TAG_ADD (aCtx, UNI,INT_CODE,get_float_exp);
}
/************************************************************************/
/* get_float_exp */
/* float element fractional positions (unsigned 8) encountered */
/************************************************************************/
static ST_VOID get_float_exp (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
MLOG_CDEC0 ("get_float_exp");
if (asn1r_get_u8 (aCtx, &float_e))
asn1r_set_dec_err (aCtx, UNSUPPORTED);
else
{ /* IEEE 754 Single */
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_FLOATING_POINT; /* set data type tag */
/* Since DIS & IS differ on the values used to represent floating point */
/* types, allow either. */
if ((float_f == SNGL_FRACT || float_f == SNGL_WHOLE) &&
float_e == SNGL_EXP)
rt_ptr->u.p.el_len = 4; /* single precision */
else
{ /* IEEE 754 Double */
if ((float_f == DOUBL_FRACT || float_f == DOUBL_WHOLE) &&
float_e == DOUBL_EXP)
rt_ptr->u.p.el_len = 8; /* double precision */
else
{
MLOG_NERR0 ("Float format not supported");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* not standard size int */
}
}
}
}
/* Float element constructor can now be done */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = float_cstr_done;
}
/************************************************************************/
/* float_cstr_done */
/* float element cstr done function, allow type decode to continue */
/************************************************************************/
static ST_VOID float_cstr_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("float_cstr_done");
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
/************************************************************************/
/* get_octstr_el */
/* octet string element encountered. */
/************************************************************************/
static ST_VOID get_octstr_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_INT32 size;
MLOG_CDEC0 ("get_octstr_el");
if (asn1r_get_i32 (aCtx, &size))
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_OCTET_STRING; /* set data type tag */
rt_ptr->u.p.el_len = (ST_INT) size; /* save precision */
if (rt_ptr->u.p.el_len != (ST_INT) size) /* make sure OK cast */
{
MLOG_NERR0 ("Octet string too big");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */
}
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
}
/************************************************************************/
/* get_vstr_el */
/* visible string element encountered. */
/************************************************************************/
static ST_VOID get_vstr_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_INT32 size;
MLOG_CDEC0 ("get_vstr_el");
if (asn1r_get_i32 (aCtx, &size))
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_VISIBLE_STRING; /* set data type tag */
rt_ptr->u.p.el_len = (ST_INT) size; /* save precision */
if (rt_ptr->u.p.el_len != (ST_INT) size) /* make sure OK cast */
{
MLOG_NERR0 ("Vis string too big");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */
}
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
}
/************************************************************************/
/* get_gtime_el */
/* generalized time element encountered. */
/************************************************************************/
static ST_VOID get_gtime_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
MLOG_CDEC0 ("get_gtime_el");
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_GENERAL_TIME; /* set data type tag */
rt_ptr->u.p.el_len = sizeof(time_t);/* gen time precision */
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
/************************************************************************/
/* get_btime_el */
/* binary time element encountered. */
/************************************************************************/
static ST_VOID get_btime_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_BOOLEAN dateFlag;
MLOG_CDEC0 ("get_btime_el");
if (asn1r_get_bool (aCtx, &dateFlag)) /* get the 4/6 flag */
asn1r_set_dec_err (aCtx, PDU_ERR);
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_BINARY_TIME; /* set data type tag */
if (dateFlag) /* if date included */
rt_ptr->u.p.el_len = 6; /* expect 6 bytes */
else /* no date */
rt_ptr->u.p.el_len = 4; /* expect 4 bytes */
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
}
/************************************************************************/
/* get_bcd_el */
/* bcd element encountered. */
/************************************************************************/
static ST_VOID get_bcd_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_UCHAR size;
MLOG_CDEC0 ("get_bcd_el");
if (asn1r_get_u8 (aCtx, &size)) /* get the precision */
asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */
else /* find # bytes */
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_BCD; /* set data type tag */
rt_ptr->u.p.el_len = (ST_INT) size;/* save precision */
if (size > 8)
{
MLOG_NERR0 ("BCD size too big");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE */
}
}
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
/************************************************************************/
/* get_utc_time_el */
/* UTC Time element encountered. */
/************************************************************************/
static ST_VOID get_utc_time_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
MLOG_CDEC0 ("get_utc_time_el");
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_UTC_TIME; /* set data type tag */
rt_ptr->u.p.el_len = 8; /* expect 8 bytes */
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
/************************************************************************/
/* get_utf8_el */
/* Unicode UTF8string element encountered. */
/************************************************************************/
static ST_VOID get_utf8_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_INT32 size;
MLOG_CDEC0 ("get_utf8_el");
if (asn1r_get_i32 (aCtx, &size))
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE*/
else
{
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_UTF8_STRING; /* set data type tag */
rt_ptr->u.p.el_len = (ST_RTINT) size; /* save size */
if (rt_ptr->u.p.el_len != size)
{ /* lost precision in cast*/
MLOG_NERR0 ("Unicode UTF8 string too long");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long for MMS-EASE*/
}
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
}
/************************************************************************/
/************************************************************************/
/* STRUCTURE COMPONENT DECODE */
/************************************************************************/
/* function declarations used in structure parsing */
static ST_VOID get_str_comp_seq (ASN1_DEC_CTXT *aCtx); /* UNI seq - comp */
static ST_VOID get_str_comp_name (ASN1_DEC_CTXT *aCtx); /* CTX 0 comp ID */
static ST_VOID get_str_comp_type (ASN1_DEC_CTXT *aCtx); /* CTX 1 CSTR - typedef */
static ST_VOID str_comp_type_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID str_comp_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID str_comp_seq_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID str_done (ASN1_DEC_CTXT *aCtx); /* main struct cstr done */
/************************************************************************/
/* get_str_packed */
/************************************************************************/
static ST_VOID get_str_packed (ASN1_DEC_CTXT *aCtx)
{
#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3)
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
#endif
ST_UCHAR m_packed;
MLOG_CDEC0 ("get_str_packed");
if (asn1r_get_u8 (aCtx, &m_packed)) /* get the boolean value */
asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */
else
{
#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3)
if (!decInfo->calc_only)
rt_ptr->u.str.packd = m_packed;
#endif
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,str_comp_seq_start);
}
}
/************************************************************************/
/* str_comp_seq_start */
/* This is a 'seq' component , of the main struct 'seq of' */
/* Next is an optional 'packed' or the components sequence */
/************************************************************************/
static ST_VOID str_comp_seq_start (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("str_comp_seq_start");
ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,get_str_comp_seq);
}
/************************************************************************/
/* get_str_comp_seq */
/* This is a 'seq' component , of the main struct 'seq of' */
/* Next is an optional 'packed' or the components sequence */
/************************************************************************/
static ST_VOID get_str_comp_seq (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_str_comp_seq");
ASN1R_TAG_ADD (aCtx, CTX,0,get_str_comp_name);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_str_comp_type);
}
/************************************************************************/
/* get_str_comp_name */
/* structure component name here */
/* NOTE: USE_RT_TYPE_2 must be defined or this function will not save */
/* component names (needs rt_ptr->comp_name_ptr). */
/************************************************************************/
#if defined(USE_RT_TYPE_3)
static ST_INT _mvl_rt_name_to_index (ST_CHAR *name)
{
ST_INT i;
for (i = 0; i < numMvlRtNames; ++i)
{
if (!strcmp (mvlRtNames[i], name))
return (i);
}
return (-1);
}
#endif
static ST_VOID get_str_comp_name (ASN1_DEC_CTXT *aCtx)
{
ST_CHAR name[MAX_IDENT_LEN+1]; /* for component name element */
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
#if defined(USE_RT_TYPE_2)
ST_INT name_len;
#endif
MLOG_CDEC0 ("get_str_comp_name");
if (asn1r_get_identifier (aCtx, name)) /* read the identifier */
asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */
else
{
#ifdef USE_RT_TYPE_2
name_len = strlen (name) + 1; /* make space for NULL */
decInfo->comp_name_used += name_len;/* compute total len BEFORE copy*/
if (!decInfo->calc_only)
{
if (decInfo->comp_name_ptr &&
decInfo->comp_name_used <= decInfo->comp_name_size) /* enough space?*/
{
strcpy (decInfo->comp_name_ptr, name);
rt_ptr->comp_name_ptr = decInfo->comp_name_ptr; /* Store name ptr*/
decInfo->comp_name_ptr += name_len;
}
else
{ /* Buffer too small. Should never happen. */
MLOG_ERR0 ("ASN.1 to RT Error : Component name buffer overflow.");
asn1r_set_dec_err (aCtx, RUNTIME_LIMIT);
return;
}
}
#elif defined(USE_RT_TYPE_3)
if (!decInfo->calc_only)
{
rt_ptr->name_index = _mvl_rt_name_to_index (name);
if (rt_ptr->name_index < 0)
{
MLOG_NERR1 ("ASN.1 to RT Error : Component name '%s'cannot be converted to index", name);
asn1r_set_dec_err (aCtx, UNKNOWN_TYPENAME);
return;
}
}
#else /* Default */
if (!decInfo->calc_only)
strcpy (rt_ptr->name, name);
#endif /* Default */
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_str_comp_type); /* need to get type next */
}
}
/************************************************************************/
/* get_str_comp_type */
/* structure component, is a type definition */
/* This constructor contains the type_definition element */
/************************************************************************/
static ST_VOID get_str_comp_type (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_str_comp_type");
set_type_tags (aCtx); /* set up to get the type spec. */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_comp_type_done;
}
/************************************************************************/
/* str_comp_type_done */
/* structure component typedef constructor complete */
/* This just means that is is OK for this component to be done. */
/************************************************************************/
static ST_VOID str_comp_type_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("str_comp_type_done");
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_comp_done;
}
/************************************************************************/
/* str_comp_done */
/* structure component constructor complete */
/* set up to get the next */
/************************************************************************/
static ST_VOID str_comp_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("str_comp_done");
/* setup to get next struct component */
ASN1R_TAG_ADD (aCtx, UNI|CONSTR,SEQ_CODE,get_str_comp_seq);
/* since a struct comp has been read, OK for this seq to be done */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_comp_seq_done;
}
/************************************************************************/
/* str_comp_seq_done */
/* structure component seq complete */
/* set up to get the next seq, or could be done with this seq */
/************************************************************************/
static ST_VOID str_comp_seq_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("str_comp_seq_done");
/* since a struct comp has been read, OK for this seq to be done */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = str_done; /* ok for this struct to be done */
}
/************************************************************************/
/* str_done */
/* structure complete */
/* set up to get the next element */
/************************************************************************/
static ST_VOID str_done (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
RUNTIME_TYPE *start_rt_blk;
ST_INT num_rt;
MLOG_CDEC0 ("str_done");
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_STR_END; /* write the tag */
/* calculate where the corresponding STR_START elment is */
start_rt_blk = struct_tracking[aCtx->asn1r_msg_level+1];
/* Set num_rt, for use in AA processing */
num_rt = (rt_ptr - start_rt_blk - 1);
/* If everything else working correctly, this error should never occur. */
if (num_rt <= 0)
{
MLOG_ERR0 ("ASN.1 to RT Error : Structure empty.");
asn1r_set_dec_err (aCtx, LENGTH_ERR);
}
start_rt_blk->u.str.num_rt_blks = num_rt;
rt_ptr->u.str.num_rt_blks = num_rt;
#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3)
/* copy the packed flag from the start block to the end block */
rt_ptr->u.str.packd = start_rt_blk->u.str.packd;
#endif
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
/************************************************************************/
/************************************************************************/
/* ARRAY COMPONENT DECODE */
/************************************************************************/
/* get_arr_packed */
/* packed flag received here, just ignore for now */
/************************************************************************/
static ST_VOID get_arr_packed (ASN1_DEC_CTXT *aCtx)
{
#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3)
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
#endif
ST_UCHAR m_packed;
MLOG_CDEC0 ("get_arr_packed");
if (asn1r_get_u8 (aCtx, &m_packed)) /* get the boolean value */
asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */
else
{
#if !defined(USE_RT_TYPE_2) && !defined(USE_RT_TYPE_3)
if (!decInfo->calc_only)
rt_ptr->u.arr.packd = m_packed;
#endif
ASN1R_TAG_ADD (aCtx, CTX,1,get_num_arr_el); /* next must be number of elmnts*/
}
}
/************************************************************************/
/* get_num_arr_el */
/* number of array elements */
/************************************************************************/
static ST_VOID get_num_arr_el (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
ST_UINT32 num;
MLOG_CDEC0 ("get_num_arr_el");
if (asn1r_get_u32 (aCtx, &num)) /* get the number of elements */
asn1r_set_dec_err (aCtx, PDU_ERR); /* too long */
else
{
if (!decInfo->calc_only)
{
rt_ptr->u.arr.num_elmnts = (ST_INT) num;
if (rt_ptr->u.arr.num_elmnts != (ST_INT) num) /* verify cast */
{
MLOG_NERR0 ("Array size too big");
asn1r_set_dec_err (aCtx, UNSUPPORTED); /* too long */
}
}
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_arr_el); /* need to get type next */
if (++rt_count >= rt_limit) /* check runtime table limit */
{
MLOG_NERR0 ("ASN.1 to RT Error : RT Table too small");
asn1r_set_dec_err (aCtx, RUNTIME_LIMIT);
}
else
rt_ptr++; /* move rt ptr to next element */
}
}
/************************************************************************/
/* get_arr_el */
/* structure component, is a type definition */
/* This constructor contains the type_definition element */
/************************************************************************/
static ST_VOID get_arr_el (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_arr_el");
set_type_tags (aCtx); /* set up to get the type spec. */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = arr_el_cstr_done;
}
/************************************************************************/
/* arr_el_cstr_done */
/* array element constructor complete */
/* This means that the array sequence is complete */
/************************************************************************/
static ST_VOID arr_el_cstr_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("arr_el_cstr_done");
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = array_done; /* set done function for array */
}
/************************************************************************/
/* array_done */
/* array constructor complete */
/* calculate the # rt blocks is each element, update start/end of array */
/************************************************************************/
static ST_VOID array_done (ASN1_DEC_CTXT *aCtx)
{
ST_INT num_rt;
RUNTIME_TYPE *start_rt_blk;
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
MLOG_CDEC0 ("array_done");
if (!decInfo->calc_only)
{
rt_ptr->el_tag = RT_ARR_END; /* write the tag */
/* calculate and write rt count for end, start blocks */
start_rt_blk = decInfo->rt_start + arr_index[aCtx->asn1r_msg_level+1];
num_rt = rt_count - arr_index[aCtx->asn1r_msg_level+1] -1; /* rt_count not inc'd yet*/
rt_ptr->u.arr.num_rt_blks = num_rt;
start_rt_blk->u.arr.num_rt_blks = num_rt;
/* copy the element count from the start block to the end block */
rt_ptr->u.arr.num_elmnts = start_rt_blk->u.arr.num_elmnts;
}
rt_ptr_inc (aCtx); /* move rt ptr, inc count */
}
/************************************************************************/
/************************************************************************/
/* NAMED TYPE */
/************************************************************************/
/* type_name_cstr_done */
/* type_name constructor complete */
/* need to find in local database, copy the runtime elements */
/************************************************************************/
static ST_VOID type_name_cstr_done (ASN1_DEC_CTXT *aCtx)
{
ASN1_TO_RT_DEC_INFO *decInfo = (ASN1_TO_RT_DEC_INFO *) aCtx->usr_info[0];
RUNTIME_TYPE *sub_rt_head; /* ptr to first rt in sub-type */
ST_INT sub_rt_num; /* num of rt in sub-type */
#if !defined(MMS_LITE)
NAMED_TYPE *tptr;
#endif
#if defined (USE_RT_TYPE_2)
ST_CHAR *name_ptr_save;
ST_INT j;
ST_INT comp_name_len;
#elif defined(USE_RT_TYPE_3)
ST_RTINT name_index_save;
#else
ST_CHAR name_save[MAX_IDENT_LEN+1];
#endif
MLOG_CDEC0 ("type_name_cstr_done");
#if !defined(MMS_LITE)
tptr = ms_find_named_type_obj (&type_name,0);
if (!tptr)
{
MLOG_NERR1 ("Named type %s not found", type_name.obj_name.vmd_spec);
asn1r_set_dec_err (aCtx, UNKNOWN_TYPENAME);
return;
}
sub_rt_num = tptr->rt_num;
sub_rt_head = tptr->rt_head;
#else
/* This function finds previously defined types. The default function */
/* should be in the library, but user may replace it with customized funct.*/
if (u_ml_get_rt_type (aCtx, &type_name, &sub_rt_head, &sub_rt_num) != SD_SUCCESS)
{
MLOG_NERR1 ("Named type %s not found", type_name.obj_name.vmd_spec);
asn1r_set_dec_err (aCtx, UNKNOWN_TYPENAME);
return;
}
#endif
/* OK, we have a pointer to the referenced runtime type and the number */
/* of elements. We can either insert the referenced table into the */
/* new one, OR we can just add a reference. */
if ((rt_count += sub_rt_num) > rt_limit)
{
MLOG_NERR0 ("ASN.1 to RT Error : RT Table too small");
asn1r_set_dec_err (aCtx, RUNTIME_LIMIT);
return;
}
if (decInfo->calc_only)
{
#if defined(USE_RT_TYPE_2) /* make room to copy comp names from sub-type*/
for (j = 0; j < sub_rt_num; ++j)
{
if (sub_rt_head[j].comp_name_ptr)
decInfo->comp_name_used += (strlen (sub_rt_head[j].comp_name_ptr) + 1);
}
#endif
}
else
{
#if defined(USE_RT_TYPE_2)
name_ptr_save = rt_ptr->comp_name_ptr;
#elif defined(USE_RT_TYPE_3)
name_index_save = rt_ptr->name_index;
#else
strcpy (name_save, rt_ptr->name);
#endif
/* Copy array of RUNTIME_TYPE structs. */
memcpy ((ST_CHAR *)rt_ptr,(ST_CHAR *)sub_rt_head, sizeof(RUNTIME_TYPE)*sub_rt_num);
#if defined(USE_RT_TYPE_2)
/* Copy component names from sub-type into new type. */
/* Must update comp_name_ptr in each rt. */
for (j = 0; j < sub_rt_num; ++j)
{
if (sub_rt_head[j].comp_name_ptr)
{
/* check for buffer space BEFORE strcpy. */
comp_name_len = (strlen(sub_rt_head[j].comp_name_ptr) + 1);
decInfo->comp_name_used += comp_name_len;
if (decInfo->comp_name_used <= decInfo->comp_name_size) /* enough space?*/
{
strcpy (decInfo->comp_name_ptr, sub_rt_head[j].comp_name_ptr);
rt_ptr[j].comp_name_ptr = decInfo->comp_name_ptr;
decInfo->comp_name_ptr += comp_name_len;
}
else
{ /* Buffer too small. Should never happen. */
MLOG_ERR0 ("ASN.1 to RT Error : Component name buffer overflow.");
asn1r_set_dec_err (aCtx, RUNTIME_LIMIT);
return;
}
}
}
rt_ptr->comp_name_ptr = name_ptr_save;
#elif defined(USE_RT_TYPE_3)
rt_ptr->name_index = name_index_save;
#else
strcpy (rt_ptr->name, name_save);
#endif
rt_ptr += sub_rt_num; /* chg global rt_ptr to point after inserted sub-type*/
}
}
/************************************************************************/
/************************************************************************/
/* DECODE DONE FUNCTIONS */
/************************************************************************/
/* td_done */
/************************************************************************/
static ST_VOID td_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("td_done");
}
/************************************************************************/
/* td_err */
/************************************************************************/
static ST_VOID td_err (ASN1_DEC_CTXT *aCtx, ST_RET err)
{
MLOG_CDEC0 ("td_err");
rt_count = 0; /* error, set count = 0 */
mms_op_err = aCtx->asn1r_pdu_dec_err; /* save error code */
}
/************************************************************************/
/* DATA ALIGNMENT TABLE DEFINITIONS */
/************************************************************************/
/* This is the 'packed' data alignment table, which is used to emulate */
/* the alignment used by previous versions of the data conversion */
/* functions. */
SD_CONST ST_INT m_packed_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0000, /* INT16_ALGN 05 */
0x0000, /* INT32_ALGN 06 */
0x0000, /* INT64_ALGN 07 */
0x0000, /* FLOAT_ALGN 08 */
0x0000, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0000, /* BCD2_ALGN 13 */
0x0000, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
/* CRITICAL: this global variable "m_data_algn_tbl" must be set before */
/* any types are created. */
#ifdef MMS_LITE
#if defined(FOUNDRY)
/* For some strange reason on "linux", the linker tries to get this */
/* module again from the library (causing duplicates) if */
/* m_data_algn_tbl is not initialized here. */
SD_CONST ST_INT *m_data_algn_tbl=NULL; /* Foundry sets it as needed */
#else
/* Use m_lite_data_algn_tbl generated by Foundry for target platform. */
/* This assures that Foundry types & dynamic types have same alignment. */
SD_CONST ST_INT *m_data_algn_tbl = m_lite_data_algn_tbl;
#endif
#else /* !MMS_LITE */
/* Should use "m_def_data_algn_tbl" for all systems, but must */
/* default to "m_packed_data_algn_tbl" for backward compatiblity with */
/* very old MMS-EASE products. */
#if !defined(NO_GLB_VAR_INIT)
SD_CONST ST_INT *m_data_algn_tbl = m_packed_data_algn_tbl;
#endif
#endif /* !MMS_LITE */
/* Here is where we create the 'default' alignment tables. These should */
/* allow natural access to components. */
/* This data alignment table provides word alignment per the following */
/* simple rule : */
/* Align on the smaller of the size of the data type OR 2 bytes. */
/* To do this we set the low bit for every type that is greater than */
/* or equal to 2 bytes in size. */
#if !defined(MMS_LITE) /* m_def_data_algn_tbl NOT used for MMS_LITE */
#if defined(MSDOS)
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0001, /* INT32_ALGN 06 */
0x0001, /* INT64_ALGN 07 */
0x0001, /* FLOAT_ALGN 08 */
0x0001, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0001, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
/* This data alignment table provides word alignment per the following */
/* simple rule : */
/* Align on the smaller of the size of the data type OR 4 bytes. */
/* To do this we set the low bit for every type that is equal to 2 */
/* bytes in size, and the low two bits for every type that is greater */
/* than or equal to 4 bytes in size. */
#if 0
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0003, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0000, /* BCD2_ALGN 13 */
0x0001, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#ifdef _AIX
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0003, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#if defined (__hpux)
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0007, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#ifdef __OS2__
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0003, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#ifdef sun
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0007, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#if (defined(__ALPHA) && defined(__VMS))
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0007, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#if defined(__alpha) && !defined(__VMS)
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0007, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#ifdef _WIN32
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0007, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0007, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#ifdef VXWORKS
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0001, /* INT32_ALGN 06 */
0x0001, /* INT64_ALGN 07 */
0x0001, /* FLOAT_ALGN 08 */
0x0001, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0001, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif
#if defined (__QNX__) /* packed */
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0000, /* INT16_ALGN 05 */
0x0000, /* INT32_ALGN 06 */
0x0000, /* INT64_ALGN 07 */
0x0000, /* FLOAT_ALGN 08 */
0x0000, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0000, /* BCD2_ALGN 13 */
0x0000, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif /* __QNX__ */
#if defined(linux)
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0003, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0003, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif /* linux */
#if defined (__LYNX)
#define M_STRSTART_MODE M_STRSTART_MODE_LARGEST
#define M_STREND_MODE M_STREND_MODE_LARGEST
SD_CONST ST_INT m_def_data_algn_tbl[NUM_ALGN_TYPES] =
{
0x0000, /* ARRSTRT_ALGN 00 */
0x0000, /* ARREND_ALGN 01 */
0x0000, /* STRSTRT_ALGN 02 */
0x0000, /* STREND_ALGN 03 */
0x0000, /* INT8_ALGN 04 */
0x0001, /* INT16_ALGN 05 */
0x0003, /* INT32_ALGN 06 */
0x0003, /* INT64_ALGN 07 */
0x0003, /* FLOAT_ALGN 08 */
0x0003, /* DOUBLE_ALGN 09 */
0x0000, /* OCT_ALGN 10 */
0x0000, /* BOOL_ALGN 11 */
0x0000, /* BCD1_ALGN 12 */
0x0001, /* BCD2_ALGN 13 */
0x0003, /* BCD4_ALGN 14 */
0x0000, /* BIT_ALGN 15 */
0x0000 /* VIS_ALGN 16 */
};
#endif /* __LYNX */
#endif /* !defined(MMS_LITE) */
/************************************************************************/
/************************************************************************/
/* ms_rt_size_calc */
/************************************************************************/
/* */
/* ****** PRIMITIVE elements alignment is well known. */
/* Element above == primitive : Add padding to element above. */
/* { */
/* prim yy << pad */
/* prim xx */
/* } */
/* Element above == struct end : Add padding to struct end above. */
/* { */
/* struct yy */
/* { */
/* ... */
/* } << pad */
/* prim xx */
/* } */
/* Element above == arr end : Add padding to array end above. */
/* { */
/* arr yy[zz]; */
/* arr_end << pad */
/* prim xx */
/* } */
/* */
/* ****** STRUCTURE START elements alignment is derived from elements */
/* Element above == primitive : Add padding to element above. */
/* { */
/* prim yy */
/* struct << pad */
/* { */
/* ... */
/* } xx */
/* } */
/* Element above == struct end : Add padding to struct end above. */
/* { */
/* struct yy */
/* { */
/* ... */
/* } */
/* struct << pad */
/* { */
/* ... */
/* } xx */
/* } */
/* Element above == arr end : Add padding to array end above. */
/* { */
/* arr yy[zz]; */
/* struct << pad */
/* { */
/* ... */
/* } xx */
/* } */
/* */
/* ****** ARRAY START elements alignment is derived from element */
/* Element above == primitive : Add padding to element above. */
/* { */
/* prim yy << pad */
/* arr xx[zz]; */
/* } */
/* Element above == struct end : Add padding to struct end above. */
/* { */
/* struct yy */
/* { */
/* ... */
/* } << pad */
/* arr xx[zz]; */
/* } */
/* Element above == arr end : Add padding to array end above. */
/* { */
/* arr yy[zz]; */
/* arr_end << pad */
/* arr xx[zz]; */
/* } */
/* */
/* STRUCTURE SIZE PADDING - struct end */
/* struct */
/* { */
/* xx */
/* yy << Pad for structure size */
/* } */
/* */
/* ARRAYS OF STRUCTURES - array of structure end */
/* struct ss */
/* { */
/* xx */
/* yy */
/* } << Pad to accomadate ss and xx alignment requirements */
/* [xx]; */
/* */
/* */
#if !defined(MMS_LITE)
/* NOTE: For MMS_LITE, these variables are created by Foundry and placed*/
/* in the Foundry output 'c' file. */
ST_INT m_struct_start_algn_mode = M_STRSTART_MODE;
ST_INT m_struct_end_algn_mode = M_STREND_MODE;
#endif
ST_VOID ms_rt_size_calc (RUNTIME_TYPE *rt_head, ST_INT rt_num)
{
ST_INT ellen;
RUNTIME_TYPE *arr1_rt;
RUNTIME_TYPE *rt;
RUNTIME_TYPE *rt_end;
RUNTIME_TYPE *rt_pad_dest;
ST_INT curr_offset;
ST_INT algn;
ST_INT arr_level;
ST_INT arr_start_offset[ASN1_MAX_LEVEL];
ST_INT arr_element_size;
S_LOCK_COMMON_RESOURCES ();
rt = rt_head; /* set runtime ptr */
rt_end = rt_head + rt_num; /* end block */
arr_level = 0;
curr_offset = 0; /* Offset from start of data */
rt_pad_dest = NULL;
while (rt < rt_end)
{
if (rt->el_tag == RT_ARR_END)
{
/* Special handling for an array of structures */
/* We need to check if the structure end needs to be padded */
arr1_rt = rt - rt->u.arr.num_rt_blks;
if (arr1_rt->el_tag == RT_STR_START)
{
_get_struct_start_align (arr1_rt, &algn, &ellen);
_do_padding (rt_pad_dest, &curr_offset, algn);
}
/* Now we need to multiply the size of this array element by the */
/* number of elements in the array */
--arr_level;
arr_element_size = curr_offset - arr_start_offset[arr_level];
curr_offset += (arr_element_size * (rt->u.arr.num_elmnts-1));
}
/* Get the current RT element's alignment requirements and do any */
/* required padding on the element above us. */
_ms_m_get_rt_info (rt, &algn, &ellen);
_do_padding (rt_pad_dest, &curr_offset, algn);
/* If we are starting an array, we must remember the start offset */
if (rt->el_tag == RT_ARR_START)
{
arr_start_offset[arr_level] = curr_offset;
++arr_level;
}
/* Set the current element's nominal memory requirements */
rt->el_size = ellen;
/* Set the offset for the next element */
curr_offset += ellen;
/* Usually we pad the element directly above us ... */
rt_pad_dest = rt;
rt++;
}
/* We are all done with adjusting padding for our type. */
/* Get the offset past the last element, for encoding */
rt_head->offset_to_last = ms_get_blocked_length (rt_head,rt_num);
/* Let the user have a shot at the runtime type if they want to */
if (u_rt_type_process)
(*u_rt_type_process) (rt_head, rt_num);
S_UNLOCK_COMMON_RESOURCES ();
}
/************************************************************************/
/* _ms_m_get_rt_info */
/************************************************************************/
/* WARNING: Recursive routine */
ST_RET _ms_m_get_rt_info (SD_CONST RUNTIME_TYPE *rt, ST_INT *algn_out,
ST_INT *ellen_out)
{
ST_INT algn_index = NUM_ALGN_TYPES; /* init to ILLEGAL value */
ST_INT ellen;
switch (rt->el_tag)
{
case RT_STR_START : /* structure starting */
_get_struct_start_align (rt, algn_out, ellen_out);
return (SD_SUCCESS);
break;
case RT_STR_END : /* structure done */
_get_struct_end_align (rt, algn_out, ellen_out);
return (SD_SUCCESS);
break;
case RT_ARR_START : /* array starting */
_get_arr_start_align (rt, algn_out, ellen_out);
return (SD_SUCCESS);
break;
case RT_ARR_END : /* array done */
ellen = 0;
algn_index = ARREND_ALGN;
break;
case RT_GENERAL_TIME : /* generalized time */
ellen = sizeof(time_t);
algn_index = GENERAL_TIME_ALGN;
break;
case RT_BINARY_TIME : /* binary time is one or 2 ST_INT32 */
if (rt->u.p.el_len == 6)
ellen = 2 * sizeof(ST_INT32);
else
ellen = sizeof(ST_INT32);
algn_index = INT32_ALGN;
break;
case RT_UTC_TIME : /* UTC Time is 3 ST_UINT32 in struct */
ellen = sizeof (MMS_UTC_TIME); /* 3 * sizeof(ST_UINT32); */
algn_index = INT32_ALGN;
break;
case RT_INTEGER : /* integer */
case RT_UNSIGNED : /* integer */
ellen = rt->u.p.el_len; /* # bytes used */
switch (ellen)
{
case 1 :
algn_index = INT8_ALGN;
break;
case 2 :
algn_index = INT16_ALGN;
break;
case 4 :
algn_index = INT32_ALGN;
break;
#ifdef INT64_SUPPORT
case 8 :
algn_index = INT64_ALGN;
break;
#endif
}
break;
case RT_FLOATING_POINT : /* float */
ellen = rt->u.p.el_len; /* # bytes used */
if (ellen == 4)
algn_index = FLOAT_ALGN;
else
algn_index = DOUBLE_ALGN;
break;
case RT_OCTET_STRING : /* octet string */
ellen = abs (rt->u.p.el_len); /* max # bytes used */
if (rt->u.p.el_len < 0) /* if variable, allow for size */
{
algn_index = INT16_ALGN;
ellen += sizeof (ST_INT16);
}
else
algn_index = OCT_ALGN;
break;
case RT_BOOL : /* boolean */
ellen = rt->u.p.el_len; /* # bytes used */
algn_index = BOOL_ALGN;
break;
case RT_BCD : /* bcd */
if (rt->u.p.el_len <= 2)
{
ellen = 1;
algn_index = BCD1_ALGN;
}
else if (rt->u.p.el_len <= 4)
{
ellen = 2;
algn_index = BCD2_ALGN;
}
else
{
ellen = 4;
algn_index = BCD4_ALGN;
}
break;
case RT_BIT_STRING : /* bit string */
ellen = abs (rt->u.p.el_len)/8; /* # bytes used */
if (rt->u.p.el_len % 8) /* if not a multiple of 8 */
ellen++; /* add one to take spare bits */
if (rt->u.p.el_len < 0) /* if variable, allow for size */
{
algn_index = INT16_ALGN;
ellen += sizeof (ST_INT16);
}
else
algn_index = BIT_ALGN;
break;
case RT_VISIBLE_STRING : /* visible string */
ellen = abs (rt->u.p.el_len) + 1; /* # bytes used */
algn_index = VIS_ALGN;
break;
case RT_UTF8_STRING : /* Unicode UTF8 string */
#if (UNICODE_LOCAL_FORMAT==UNICODE_UTF8)
ellen = abs(rt->u.p.el_len)*4 + 1;/* # bytes (4 bytes per char + NULL)*/
algn_index = VIS_ALGN; /* Same alignment as visible string*/
#else /* assume UNICODE_UTF16 */
ellen = abs(rt->u.p.el_len)*2 + 2;/* # bytes (2 bytes per char + 2 byte NULL)*/
algn_index = INT16_ALGN;
#endif
break;
default : /* should not be any other tag */
MLOG_NERR0 ("Bad el_tag in RT");
return (SD_FAILURE);
break;
}
if (algn_index == NUM_ALGN_TYPES) /* ILLEGAL value */
{
MLOG_ERR0 ("algn_index never set"); /* THIS SHOULD NEVER HAPPEN */
return (SD_FAILURE);
}
*algn_out = m_data_algn_tbl[algn_index];
*ellen_out = ellen;
return (SD_SUCCESS);
}
/************************************************************************/
/* _get_struct_start_align */
/************************************************************************/
/* WARNING: Recursive routine */
static ST_VOID _get_struct_start_align (SD_CONST RUNTIME_TYPE *rt,
ST_INT *algn_out,
ST_INT *ellen_out)
{
ST_INT i;
ST_INT curr_algn;
ST_INT algn;
ST_INT ellen;
ST_INT num_rt;
algn = m_data_algn_tbl[STRSTRT_ALGN];
num_rt = rt->u.str.num_rt_blks;
++rt; /* Point to first structure member */
if (m_struct_start_algn_mode == M_STRSTART_MODE_LARGEST)
{
for (i = 0; i < num_rt; ++i, ++rt)
{
_ms_m_get_rt_info (rt, &curr_algn, &ellen);
if (curr_algn > algn)
algn = curr_algn;
}
}
else if (m_struct_start_algn_mode == M_STRSTART_MODE_FIRST)
_ms_m_get_rt_info (rt, &algn, &ellen);
*algn_out = algn;
*ellen_out = 0;
}
/************************************************************************/
/* _get_struct_end_align */
/************************************************************************/
/* WARNING: Recursive routine */
static ST_VOID _get_struct_end_align (SD_CONST RUNTIME_TYPE *rt,
ST_INT *algn_out,
ST_INT *ellen_out)
{
ST_INT i;
ST_INT algn;
ST_INT curr_algn;
ST_INT ellen;
ST_INT num_rt;
num_rt = rt->u.str.num_rt_blks;
rt -= rt->u.str.num_rt_blks;
algn = m_data_algn_tbl[STREND_ALGN];
if (m_struct_end_algn_mode == M_STREND_MODE_LARGEST)
{
for (i = 0; i < num_rt; ++i, ++rt)
{
_ms_m_get_rt_info (rt, &curr_algn, &ellen);
if (curr_algn > algn)
algn = curr_algn;
}
}
*algn_out = algn;
*ellen_out = 0;
}
/************************************************************************/
/* _get_arr_start_align */
/************************************************************************/
/* WARNING: Recursive routine */
static ST_VOID _get_arr_start_align (SD_CONST RUNTIME_TYPE *rt,
ST_INT *algn_out,
ST_INT *ellen_out)
{
ST_INT i;
ST_INT algn;
ST_INT ellen;
ST_INT num_rt;
algn = m_data_algn_tbl[ARRSTRT_ALGN];
num_rt = rt->u.arr.num_rt_blks;
++rt;
for (i = 0; i < num_rt; ++i, ++rt)
{
if (rt->el_tag != RT_ARR_START)
{
_ms_m_get_rt_info (rt, &algn, &ellen);
break;
}
}
*algn_out = algn;
*ellen_out = 0;
}
/************************************************************************/
/* _do_padding */
/************************************************************************/
static ST_VOID _do_padding (RUNTIME_TYPE *padDest,
ST_INT *curr_offset,
ST_INT algn)
{
ST_INT pad;
/*Increment the offset until no bits are set that shouldn't be */
pad = 0;
while ((*curr_offset) & algn)
{
(*curr_offset)++;
pad++;
}
/* If pad bytes are needed, add to the end struct element */
if (pad)
{
if (!padDest)
{
MLOG_ERR0 ("Alignment table error");
}
else
padDest->el_size += pad;
}
}
/************************************************************************/
/************************************************************************/
/************************************************************************/
/* ms_get_blocked_len */
/* Function to return the size of buffer required for blocked data for */
/* the data type selected. This is used when type definitions come over */
/* the wire, and in general, when a type is created. */
/************************************************************************/
#ifndef MMS_LITE
ST_INT ms_get_blocked_len (NAMED_TYPE *tptr)
{
return (ms_get_blocked_length (tptr->rt_head,tptr->rt_num));
}
#endif
/************************************************************************/
/* ms_get_blocked_length */
/* If MMS_LITE, this function also sets rt_head->mvluTypeInfo.prim_count*/
/************************************************************************/
ST_INT ms_get_blocked_length (SD_CONST RUNTIME_TYPE *rt_head, ST_INT rt_num)
{
ST_INT total_size;
SD_CONST RUNTIME_TYPE *rt; /* current runtime element */
SD_CONST RUNTIME_TYPE *rt_end;
ST_INT arr_loop_buf[ASN1_MAX_LEVEL];
ST_INT arr_loop_level;
ST_INT *arr_loops;
ST_RTINT prim_count;
S_LOCK_COMMON_RESOURCES ();
arr_loop_level = 0;
arr_loops = arr_loop_buf;
rt = rt_head; /* set runtime ptr */
rt_end = rt_head + rt_num; /* end block */
total_size = 0;
prim_count = 0; /* initialize */
while (rt < rt_end)
{
if (rt->el_tag == RT_ARR_START) /* Set up array looping */
{
++arr_loop_level;
arr_loops[arr_loop_level] = rt->u.arr.num_elmnts;
}
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;
}
--arr_loop_level;
}
total_size += rt->el_size;
if (ms_is_rt_prim (rt))
prim_count++;
rt++; /* point to next runtime element*/
}
#if defined(MMS_LITE)
rt_head->mvluTypeInfo.prim_count = prim_count;
#endif
S_UNLOCK_COMMON_RESOURCES ();
return (total_size);
}
/************************************************************************/
/* ms_log_runtime */
/************************************************************************/
/* list the elements in a runtime type def table */
#define MAX_INDENT 5
ST_VOID ms_log_runtime (SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt)
{
_ms_log_runtime (0, rt, num_rt);
}
static ST_VOID _ms_log_runtime (ST_INT indent, SD_CONST RUNTIME_TYPE *rt, ST_INT num_rt)
{
#if defined(DEBUG_SISCO)
ST_INT i;
const ST_CHAR *comp_name;
ST_CHAR *sp[MAX_INDENT] =
{
" ",
" ",
" ",
" ",
" ",
};
ST_CHAR *sp2[MAX_INDENT] =
{
" ",
" ",
" ",
" ",
"",
};
S_LOCK_COMMON_RESOURCES ();
if (num_rt == 0)
{
MLOG_ALWAYS0 ("Runtime Type : 0 elements");
}
else if (indent == 0)
{
MLOG_ALWAYS2 ("Runtime Type : %d elements, Offset past last : %d",
num_rt, rt->offset_to_last);
}
for (i = 0; i < num_rt; ++i, rt++)
{
comp_name = ms_comp_name_find (rt);
if (strlen (comp_name))
{
MLOG_CALWAYS3 ("%sNamed comp %s: %s",
sp[indent],
sp2[indent],
comp_name);
}
switch (rt->el_tag)
{
case RT_ARR_START :
MLOG_CALWAYS5 ("%sArray start %s: size %02d, %02d elmnts, %02d rt",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.arr.num_elmnts,
rt->u.arr.num_rt_blks);
if (++indent >= MAX_INDENT)
indent--;
break;
case RT_ARR_END :
if (--indent < 0)
indent++;
MLOG_CALWAYS5 ("%sArray end %s: size %02d, %02d elmnts, %02d rt",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.arr.num_elmnts,
rt->u.arr.num_rt_blks);
break;
case RT_STR_START :
MLOG_CALWAYS4 ("%sStruct start%s: size %02d, %02d rt",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.str.num_rt_blks);
if (++indent >= MAX_INDENT)
indent--;
break;
case RT_STR_END :
if (--indent < 0)
indent++;
MLOG_CALWAYS3 ("%sStruct end %s: size %02d",
sp[indent],
sp2[indent],
rt->el_size);
break;
case RT_BOOL :
MLOG_CALWAYS4 ("%sBoolean %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_BIT_STRING :
MLOG_CALWAYS4 ("%sBitstring %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_INTEGER :
MLOG_CALWAYS4 ("%sInteger %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_UNSIGNED :
MLOG_CALWAYS4 ("%sUnsigned %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_FLOATING_POINT :
MLOG_CALWAYS4 ("%sFloat %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_OCTET_STRING :
MLOG_CALWAYS4 ("%sOctet Str %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_VISIBLE_STRING :
MLOG_CALWAYS4 ("%sVisible Str %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_GENERAL_TIME :
MLOG_CALWAYS4 ("%sGen Time %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_BINARY_TIME :
MLOG_CALWAYS4 ("%sBin Time %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_BCD :
MLOG_CALWAYS4 ("%sBCD %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_UTC_TIME :
MLOG_CALWAYS4 ("%sUTC Time %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
case RT_UTF8_STRING :
MLOG_CALWAYS4 ("%sUTF8string %s: size %02d, precision %02d",
sp[indent],
sp2[indent],
rt->el_size,
rt->u.p.el_len);
break;
default : /* should not be any other tag */
MLOG_CALWAYS1 (" **** UNKNOWN ELEMENT %02d ",i);
break;
}
}
S_UNLOCK_COMMON_RESOURCES ();
#endif
}
/************************************************************************/
/* ms_runtime_create */
/* This function parses an ASN.1 type definition, and creates a Runtime */
/* Type Table from it. It allocates memory for the table and fills it in.*/
/* The table should be destroyed by calling "ms_runtime_destroy". */
/************************************************************************/
RUNTIME_CTRL *ms_runtime_create (ST_UCHAR *asn1_data,
ST_UINT asn1_len,
ST_INT max_num_rt)
{
RUNTIME_CTRL *rt_ctrl = NULL; /* assume failure */
ST_INT num_rt; /* num entries in RUNTIME_TYPE array */
ASN1_DEC_CTXT aCtx; /* Main decode struct */
ASN1_TO_RT_DEC_INFO decInfo; /* temporary storage for extra decode info. */
ST_UCHAR *asn1_tmp; /* temporary copy of asn1_data. */
assert (m_data_algn_tbl != NULL); /* ptr MUST be set before now. */
/* First decode only to compute "num_rt" (RUNTIME_TYPE array NOT alloc'd)*/
memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/
aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context. */
/* set global variables to parse the type for size */
decInfo.calc_only = SD_TRUE; /* flag to calculate num rt blocks*/
/* If USE_COMPACT_MMS_STRUCTS defined & ObjectNames included in ASN.1,*/
/* (maybe other cases) the ASN1 buffer gets corrupted by decode. */
/* Copy to tmp buffer & use tmp buffer on 1st decode. */
asn1_tmp = (ST_UCHAR *) chk_calloc (1, asn1_len);
memcpy (asn1_tmp, asn1_data, asn1_len);
num_rt = _ms_asn1_to_runtime (&aCtx, asn1_tmp, asn1_len, NULL, max_num_rt);
chk_free (asn1_tmp); /* done with temporary copy */
/* Second decode to alloc & init array of RUNTIME_TYPE structs. */
if (num_rt)
{
memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/
aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context.*/
/* Allocate RUNTIME_CTRL struct plus array of RUNTIME_TYPE structs. */
rt_ctrl = (RUNTIME_CTRL *) chk_calloc (1, sizeof (RUNTIME_CTRL) + num_rt * sizeof (RUNTIME_TYPE));
rt_ctrl->rt_first = (RUNTIME_TYPE *)(rt_ctrl + 1);
/* parse the type encoding a second time to get an RT TYPE */
decInfo.calc_only = SD_FALSE;
#if defined(USE_RT_TYPE_2)
decInfo.comp_name_size = decInfo.comp_name_used; /* Save running count.*/
if (decInfo.comp_name_size)
decInfo.comp_name_buf = (ST_CHAR *) chk_calloc (1, decInfo.comp_name_size);
else
decInfo.comp_name_buf = NULL; /* There is no buffer. */
#endif /* USE_RT_TYPE_2 */
rt_ctrl->rt_num = _ms_asn1_to_runtime (&aCtx, asn1_data, asn1_len, rt_ctrl->rt_first, num_rt);
if (rt_ctrl->rt_num == 0)
{ /* 2nd decode failed. Should almost NEVER happen. Cleanup. */
#if defined(USE_RT_TYPE_2)
if (decInfo.comp_name_buf)
chk_free (decInfo.comp_name_buf);
#endif
chk_free (rt_ctrl);
rt_ctrl = NULL;
}
}
/* rt_first & rt_num should now be set in rt_ctrl */
return (rt_ctrl);
}
/************************************************************************/
/* ms_runtime_destroy */
/* This function frees up all the memory for a Runtime Type Table */
/* created by "ms_runtime_create". */
/* It should not be called until all references to the Rumtime Type */
/* (i.e. Variable associations, etc.) have been destroyed. */
/************************************************************************/
ST_VOID ms_runtime_destroy (RUNTIME_CTRL *rt_ctrl)
{
#if defined(USE_RT_TYPE_2)
RUNTIME_TYPE *rt_table = rt_ctrl->rt_first;
ST_INT j;
/* Component names only saved if USE_RT_TYPE_2 defined. Must free them.*/
/* Find the first non-NULL comp_name_ptr. This should be the pointer */
/* to the buffer allocated for "component names". Free the buffer. */
for (j=0; j < rt_ctrl->rt_num; j++)
{
if (rt_table[j].comp_name_ptr != 0)
{
chk_free (rt_table[j].comp_name_ptr); /* Free the buffer of names*/
break;
}
}
#endif /* USE_RT_TYPE_2 */
/* Free the table. */
chk_free (rt_ctrl);
}
/************************************************************************/
/* ms_is_rt_prim */
/************************************************************************/
ST_BOOLEAN ms_is_rt_prim (SD_CONST RUNTIME_TYPE *rt)
{
switch (rt->el_tag)
{
case RT_BOOL :
case RT_BIT_STRING :
case RT_INTEGER :
case RT_UNSIGNED :
case RT_FLOATING_POINT :
case RT_OCTET_STRING :
case RT_VISIBLE_STRING :
case RT_GENERAL_TIME :
case RT_BINARY_TIME :
case RT_BCD :
case RT_BOOLEANARRAY :
case RT_UTC_TIME :
case RT_UTF8_STRING :
return (SD_TRUE);
break;
}
return (SD_FALSE);
}
/************************************************************************/
/* ms_rt_el_tag_text */
/* Gets "el_tag" from RUNTIME_TYPE struct and converts is to text. */
/************************************************************************/
ST_CHAR *ms_rt_el_tag_text (SD_CONST RUNTIME_TYPE *rt_type)
{
ST_CHAR *el_tag_text;
switch (rt_type->el_tag)
{
case RT_ARR_START: el_tag_text="RT_ARR_START"; break;
case RT_STR_START: el_tag_text="RT_STR_START"; break;
case RT_BOOL: el_tag_text="RT_BOOL"; break;
case RT_BIT_STRING: el_tag_text="RT_BIT_STRING"; break;
case RT_INTEGER: el_tag_text="RT_INTEGER"; break;
case RT_UNSIGNED: el_tag_text="RT_UNSIGNED"; break;
case RT_FLOATING_POINT: el_tag_text="RT_FLOATING_POINT"; break;
case RT_OCTET_STRING: el_tag_text="RT_OCTET_STRING"; break;
case RT_VISIBLE_STRING: el_tag_text="RT_VISIBLE_STRING"; break;
case RT_GENERAL_TIME: el_tag_text="RT_GENERAL_TIME"; break;
case RT_BINARY_TIME: el_tag_text="RT_BINARY_TIME"; break;
case RT_BCD: el_tag_text="RT_BCD"; break;
case RT_BOOLEANARRAY: el_tag_text="RT_BOOLEANARRAY"; break;
case RT_UTC_TIME: el_tag_text="RT_UTC_TIME"; break;
case RT_UTF8_STRING: el_tag_text="RT_UTF8_STRING"; break;
case RT_STR_END: el_tag_text="RT_STR_END"; break;
case RT_ARR_END: el_tag_text="RT_ARR_END"; break;
default: el_tag_text="RT_UNSUPPORTED"; break; /* should never happen*/
}
return (el_tag_text);
}
/************************************************************************/
/* ms_asn1_to_runtime_x */
/* For backward compatibility only. Does NOT work with USE_RT_TYPE_2. */
/* New programs should use ms_runtime_create. */
/************************************************************************/
#if !defined(MMS_LITE)
ST_INT ms_asn1_to_runtime_x (ST_UCHAR *asn1_data, ST_UINT asn1_len,
RUNTIME_TYPE *rt_table, ST_INT rt_len,
ST_BOOLEAN calc_only)
{
ST_INT rt_num; /* num entries in RUNTIME_TYPE array */
ASN1_DEC_CTXT aCtx; /* Main decode struct */
ASN1_TO_RT_DEC_INFO decInfo; /* temporary storage for extra decode info. */
memset (&aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean.*/
aCtx.usr_info[0] = &decInfo; /* save ptr to decInfo in context.*/
decInfo.calc_only = calc_only;
rt_num = _ms_asn1_to_runtime (&aCtx, asn1_data, asn1_len, rt_table, rt_len);
/* rt_first & rt_num should now be set in rt_ctrl */
return (rt_num);
}
#endif /* !MMS_LITE */
#if defined(USE_RT_TYPE_2)
/* Currently, the ms_rt_bld*" functions work only if USE_RT_TYPE_2 */
/* defined. Fix to work with other options, or eliminate them. */
/************************************************************************/
/* ms_rt_bld_set_name */
/* Copy the comp_name into the buffer and set the comp_name_ptr in the */
/* current RUNTIME_TYPE pointing to it. */
/************************************************************************/
static ST_VOID ms_rt_bld_set_name (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name)
{
if (comp_name)
{
ctxt->rt_type->comp_name_ptr = ctxt->comp_name_buf + (ctxt->rt_ctrl->rt_num * (MAX_IDENT_LEN + 1));
strcpy (ctxt->rt_type->comp_name_ptr, comp_name);
}
}
/************************************************************************/
/* ms_rt_bld_compress */
/* NOTE: don't need to save pointer to component name buffer allocated */
/* here. This buf is freed in "ms_runtime_destroy" by using the */
/* "comp_name_ptr" of the first RUNTIME_TYPE. */
/************************************************************************/
static ST_VOID ms_rt_bld_compress (RUNTIME_BUILD_CTXT *ctxt)
{
RUNTIME_CTRL *rt_ctrl = ctxt->rt_ctrl;
RUNTIME_TYPE *rt_type;
ST_CHAR *compressed_buf;/* allocated buf to store all component names. */
ST_CHAR *cur_ptr; /* ptr to current position in buffer. */
ST_INT j;
size_t total_len;
/* Compute total len of all component names (including 1 byte NULL terminator).*/
for (j = 0, rt_type = rt_ctrl->rt_first, total_len = 0; j< rt_ctrl->rt_num; j++, rt_type++)
{
if (rt_type->comp_name_ptr)
total_len += (strlen(rt_type->comp_name_ptr) + 1);
}
/* Allocate new buffer. Copy all component names to new buffer */
/* and update each component name pointer. */
compressed_buf = chk_malloc (total_len);
for (j = 0, rt_type = rt_ctrl->rt_first, cur_ptr = compressed_buf;
j< rt_ctrl->rt_num;
j++, rt_type++)
{
if (rt_type->comp_name_ptr)
{
strcpy (cur_ptr, rt_type->comp_name_ptr);
rt_type->comp_name_ptr = cur_ptr;
cur_ptr += (strlen(rt_type->comp_name_ptr) + 1);
}
}
assert (cur_ptr == compressed_buf + total_len); /* make sure we counted right*/
/* Done with old buffer, so free it, and set pointer back to NULL. */
chk_free (ctxt->comp_name_buf);
ctxt->comp_name_buf = NULL;
}
/************************************************************************/
/* ms_rt_bld_start */
/* Start building a type. */
/* If max_rt_num == 0: */
/* Start computing the number of RUNTIME_TYPE elements */
/* by setting "do_count=SD_TRUE" (used by all lower ms_rt_bld* functs).*/
/* Call ms_rt_bld_get_count when build is done to get the count. */
/* DO NOT need to call ..bld_finish or ..bld_cancel when build is done.*/
/* If max_rt_num != 0: */
/* Alloc that number of RUNTIME_TYPE elements and prepare to fill them in.*/
/* MUST call ..bld_finish or ..bld_cancel to clean up when build is done.*/
/************************************************************************/
ST_VOID ms_rt_bld_start (RUNTIME_BUILD_CTXT *rt_ctxt, ST_INT max_rt_num)
{
RUNTIME_CTRL *rt_ctrl;
if (max_rt_num==0)
{ /* set up to compute number of RUNTIME_TYPE */
/* NOTE: this memset effectively sets these paramters as we want: */
/* rt_ctxt->curr_count = 0 (lower functions increment it). */
/* rt_ctxt->rt_ctrl = NULL (must not write to it). */
memset (rt_ctxt, 0, sizeof (RUNTIME_BUILD_CTXT)); /* start clean */
rt_ctxt->do_count = SD_TRUE;
return;
}
/* Allocate RUNTIME_CTRL struct plus array of RUNTIME_TYPE structs. */
rt_ctrl = (RUNTIME_CTRL *) chk_calloc (1, sizeof (RUNTIME_CTRL) + max_rt_num * sizeof (RUNTIME_TYPE));
rt_ctrl->rt_first = (RUNTIME_TYPE *)(rt_ctrl + 1);
/* NOTE: rt_ctrl->rt_num = 0 now. Incremented as types added. */
/* Initialize the runtime build context structure. */
/* NOTE: this memset effectively sets these paramters as we want: */
/* rt_ctxt->nest_level = 0; */
/* rt_ctxt->errcode = SD_SUCCESS; */
/* rt_ctxt->do_count = SD_FALSE; */
memset (rt_ctxt, 0, sizeof (RUNTIME_BUILD_CTXT)); /* start clean */
rt_ctxt->rt_ctrl = rt_ctrl;
rt_ctxt->rt_type = rt_ctrl->rt_first; /* point to first. This ptr */
/* incremented as types added */
rt_ctxt->max_rt_type = rt_ctrl->rt_first + max_rt_num;
/* Allocate buffer to store component names. Compress it later using */
/* ms_rt_bld_compress. */
rt_ctxt->comp_name_buf = chk_calloc (max_rt_num , (MAX_IDENT_LEN+1));
memset (rt_ctxt->nest_start_ptr, 0, sizeof (rt_ctxt->nest_start_ptr));
}
/************************************************************************/
/************************************************************************/
ST_VOID ms_rt_bld_cancel (RUNTIME_BUILD_CTXT *rt_ctxt)
{
if (rt_ctxt->do_count)
return; /* no cleanup necessary */
if (rt_ctxt->comp_name_buf)
{
chk_free (rt_ctxt->comp_name_buf);
rt_ctxt->comp_name_buf = NULL;
}
chk_free (rt_ctxt->rt_ctrl);
}
/************************************************************************/
/************************************************************************/
ST_VOID ms_rt_bld_finish (RUNTIME_BUILD_CTXT *rt_ctxt)
{
if (rt_ctxt->do_count)
return; /* no cleanup necessary */
/* This assert verifies rt_num & rt_type incremented/decremented correctly.*/
assert (&rt_ctxt->rt_ctrl->rt_first[rt_ctxt->rt_ctrl->rt_num] == rt_ctxt->rt_type);
ms_rt_bld_compress (rt_ctxt);
/* CRITICAL: this funct sets "el_size" in every RUNTIME_TYPE.*/
ms_rt_size_calc (rt_ctxt->rt_ctrl->rt_first, rt_ctxt->rt_ctrl->rt_num);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_remove_last (RUNTIME_BUILD_CTXT *ctxt)
{
RUNTIME_TYPE *rt_type;
if (ctxt->do_count)
{
assert (ctxt->curr_count > 0); /* this should never be called otherwise*/
ctxt->curr_count--;
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if (ctxt->rt_ctrl->rt_num > 0)
{
ctxt->rt_ctrl->rt_num--;
ctxt->rt_type--; /* always decrement this & rt_num at same time*/
rt_type = ctxt->rt_type;
/* If removing STR_START or ARR_START must adjust nest level*/
if (rt_type->el_tag==RT_STR_START || rt_type->el_tag== RT_ARR_START)
ctxt->nest_level--;
memset (rt_type, 0, sizeof (RUNTIME_TYPE)); /* clean struct */
return (SD_SUCCESS);
}
else
return (SD_FAILURE); /* already empty. Nothing to remove.*/
}
/************************************************************************/
/* Check if state is valid to add another type. */
/* CRITICAL: DO NOT use when (ctxt->do_count==SD_TRUE). */
/************************************************************************/
ST_RET ms_rt_bld_chk_state (RUNTIME_BUILD_CTXT *ctxt)
{
if (ctxt->errcode)
return (ctxt->errcode); /* err already set. Just return it. */
if (ctxt->rt_type >= ctxt->max_rt_type)
{
/* NOTE: if this error occurs, try calling ms_rt_bld_start with larger num*/
/* NOTE: we want to log the "max_rt_num" passed to "ms_rt_bld_start"*/
/* but we didn't save it, so use pointer arithmetic to compute it.*/
MLOG_ERR1 ("Error building type. Exceeds max number of elements '%d'",
ctxt->max_rt_type - ctxt->rt_ctrl->rt_first);
ctxt->errcode = SD_FAILURE; /* set flag so all subsequent calls fail too.*/
return (SD_FAILURE);
}
return (SD_SUCCESS);
}
/************************************************************************/
/* Get current count. */
/* CRITICAL: maximum count may be slightly more than current count */
/* because RT_STR_START or RT_ARR_START may be temporarily added, then */
/* removed later if they are empty (see ms_rt_bld_remove_last). */
/************************************************************************/
ST_INT ms_rt_bld_get_count (RUNTIME_BUILD_CTXT *ctxt)
{
if (ctxt->do_count)
return (ctxt->curr_count);
else
return (ctxt->rt_ctrl->rt_num); /* usually same as curr_count, */
/* but may be different on error*/
}
/************************************************************************/
/* Get maximum count. */
/* CRITICAL: maximum count may be slightly more than current count */
/* because RT_STR_START or RT_ARR_START may be temporarily added, then */
/* removed later if they are empty (see ms_rt_bld_remove_last). */
/************************************************************************/
ST_INT ms_rt_bld_get_max_count (RUNTIME_BUILD_CTXT *ctxt)
{
assert (ctxt->do_count!=SD_FALSE); /* only valid if do_count is TRUE.*/
return (ctxt->max_count);
}
/************************************************************************/
/* Increment the count and adjust the max count, if necessary. */
/************************************************************************/
static ST_VOID inc_count (RUNTIME_BUILD_CTXT *ctxt)
{
ctxt->curr_count++;
if (ctxt->curr_count > ctxt->max_count)
ctxt->max_count = ctxt->curr_count; /* update max */
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_str_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_STR_START;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
assert (ctxt->nest_level < ASN1_MAX_LEVEL);
ctxt->nest_start_ptr[ctxt->nest_level++] = rt_type;
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_str_end (RUNTIME_BUILD_CTXT *ctxt)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_INT num_rt;
RUNTIME_TYPE *rt_start;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
if (--ctxt->nest_level < 0)
{
MLOG_ERR0 ("STR_END does not have corresponding STR_START");
ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/
return (ctxt->errcode);
}
rt_start = ctxt->nest_start_ptr[ctxt->nest_level];
if (rt_start->el_tag != RT_STR_START)
{
MLOG_ERR0 ("STR_END does not have corresponding STR_START");
ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/
return (ctxt->errcode);
}
num_rt = (rt_type - rt_start - 1);
rt_start->u.str.num_rt_blks = num_rt;
rt_type->u.str.num_rt_blks = num_rt;
rt_type->el_tag = RT_STR_END;
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_arr_start (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT array_count)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_ARR_START;
ms_rt_bld_set_name (ctxt, comp_name);
rt_type->u.arr.num_elmnts = array_count;
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
ctxt->nest_start_ptr[ctxt->nest_level++] = rt_type;
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_arr_end (RUNTIME_BUILD_CTXT *ctxt)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_INT num_rt;
RUNTIME_TYPE *rt_start;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
if (--ctxt->nest_level < 0)
{
MLOG_ERR0 ("ARR_END does not have corresponding ARR_START");
ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/
return (ctxt->errcode);
}
rt_start = ctxt->nest_start_ptr[ctxt->nest_level];
if (rt_start->el_tag != RT_ARR_START)
{
MLOG_ERR0 ("ARR_END does not have corresponding ARR_START");
ctxt->errcode = SD_FAILURE; /* DEBUG: use different errcode?*/
return (ctxt->errcode);
}
num_rt = (rt_type - rt_start - 1);
rt_type->u.arr.num_rt_blks = num_rt;
rt_start->u.arr.num_rt_blks = num_rt;
/* copy the element count from the start block to the end block */
rt_type->u.arr.num_elmnts = rt_start->u.arr.num_elmnts;
rt_type->el_tag = RT_ARR_END;
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_bool (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_BOOL;
rt_type->u.p.el_len = 1;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_int (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_INTEGER;
rt_type->u.p.el_len = el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_uint (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_UNSIGNED;
rt_type->u.p.el_len = el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_float (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_FLOATING_POINT;
rt_type->u.p.el_len = el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_bstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_BIT_STRING;
rt_type->u.p.el_len = el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_bvstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_BIT_STRING;
rt_type->u.p.el_len = -el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_VISIBLE_STRING;
rt_type->u.p.el_len = -el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_utctime (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_UTC_TIME;
rt_type->u.p.el_len = 8;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_btime6 (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_BINARY_TIME;
rt_type->u.p.el_len = 6;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_ostring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_OCTET_STRING;
rt_type->u.p.el_len = el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_ovstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_OCTET_STRING;
rt_type->u.p.el_len = -el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET ms_rt_bld_add_utf8vstring (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, ST_INT el_len)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
rt_type->el_tag = RT_UTF8_STRING;
rt_type->u.p.el_len = -el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
/************************************************************************/
/* Use info from caller's RUNTIME_TYPE struct. */
/************************************************************************/
ST_RET ms_rt_bld_add_special (RUNTIME_BUILD_CTXT *ctxt, ST_CHAR *comp_name, RUNTIME_TYPE *special)
{
RUNTIME_TYPE *rt_type = ctxt->rt_type;
ST_RET ret;
if (ctxt->do_count)
{
inc_count (ctxt);
return (SD_SUCCESS); /* just counting, nothing else to do */
}
if ((ret = ms_rt_bld_chk_state (ctxt)) != SD_SUCCESS)
return (ret);
/* NOTE: only need el_tag & el_len */
rt_type->el_tag = special->el_tag;
rt_type->u.p.el_len = special->u.p.el_len;
ms_rt_bld_set_name (ctxt, comp_name);
ctxt->rt_ctrl->rt_num++;
ctxt->rt_type++; /* always increment this & rt_num at same time*/
return (SD_SUCCESS);
}
#endif /* defined(USE_RT_TYPE_2) */