/************************************************************************/ /* 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) */