view ccd/cdc_com.c @ 8:b36540edb046

L1/cfile/l1_*.c: initial import from tcs211-l1-reconst
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 05:45:03 +0000
parents 75a11d740a02
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  
|  Modul   : cdc_com.c
+----------------------------------------------------------------------------- 
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  Condat Conder Decoder
|             Definitions of common functions for encoding and decoding of
|             GSM, GPRS or UMTS air interface messages
+----------------------------------------------------------------------------- 
*/ 

#ifdef _MSDOS
#include <dos.h>
#include <conio.h>
#endif

/*
 * standard definitions like UCHAR, ERROR etc.
 */
#include "typedefs.h"
#include "header.h"
#include <string.h>
#include <stdlib.h>

/*
 * Prototypes of ccd (USE_DRIVER EQ undef) for prototypes only
 * look at ccdapi.h
 */
#undef USE_DRIVER
#include "ccdapi.h"

/*
 * Types and functions for bit access and manipulation
 */
#include "ccd_globs.h"
#include "bitfun.h"

/*
 * Declaration of coder/decoder-tables
 */
#include "ccdtable.h"
#include "ccddata.h"

/*
 * Prototypes and constants in the common part of ccd
 */
#include "ccd.h"
#include "ccd_codingtypes.h"

/*
 * Need memory allocation functions for dynamic arrays (pointers)
 */
#ifdef DYNAMIC_ARRAYS
#include "vsi.h"
#endif

#ifndef RUN_FLASH
const UBYTE padding_bits[8]      =    {0, 0, 1, 0, 1, 0, 1, 1};
const UBYTE padding_bits_prev[8] =    {1, 0, 0, 1, 0, 1, 0, 1};
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/* Attention for RUN_...: static data (used in cdc_skipElem) */
static UBYTE  dummy[256];
#endif /* !RUN_FLASH */

typedef struct unknownTag
{
 U8  errCode;
 U8  tag;
 U16 bitpos;
 struct unknownTag *next;
}T_UNKNOWN_TAG;


#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_init_ctx_table  |
+--------------------------------------------------------------------+

  PURPOSE : init the iei_ctx table. This must be done before decoding
            a message.

*/

static void cdc_init_ctx_table (T_CCD_Globs *globs)
{
  int i;

#ifdef DEBUG_CCD
  TRACE_CCD (globs, "CONTEXT table init");
#endif

  for (i=0; i<MAX_RECURSIONS_PER_MSG; i++)
  {
    globs->iei_ctx[i].valid = FALSE;
  }
  globs->numEOCPending = 0;
}
#endif /* !RUN_FLASH */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CCD                 |
| STATE   : code                       ROUTINE : cdc_BCD_decode      |
+--------------------------------------------------------------------+

  PURPOSE : Decoding of an bitstream containing a BCD string
            with k digits. If the first digit in the bitstream
            is DIGIT_2, the digits are ordered
            in the Bitstream as follow:

            MSBit     LSBit
            8 7 6 5 4 3 2 1
            DIGIT_2 DIGIT_1    Octett n
            DIGIT_4 DIGIT_3    Octett n+1
            : : : : : : : :
            DIGIT_Z DIGIT_X    Octett n+m

            if the number of the digits is odd, the last
            Octett contains the bit pattern 1111 in the
            most significant nibble.

            : : : : : : : :
            1 1 1 1 DIGIT_X    Octett n+m

  NOTE:     If the first digit in the bitstream is DIGIT_1,
            the digits are ordered in a different way:

            MSBit     LSBit
            8 7 6 5 4 3 2 1
            DIGIT_1 XXXXXXX    Octett n
            DIGIT_3 DIGIT_2    Octett n+1
            DIGIT_5 DIGIT_4    Octett n+2
            : : : : : : : :
            DIGIT_Z DIGIT_X    Octett n+m

            In this case, if the number of the digits
            is even, the last octett contains the bit
            pattern 1111 in the most significant nibble.

            : : : : : : : :
            1 1 1 1 DIGIT_X    Octett n+m

            The amount of digits may be constant or variable.

  NOTE:     A special case (type BCD_NOFILL) is the encoding and
            decoding of a BCD string starting with DIGIT_2 but
            without setting/checking the most significant nibble
            of Octet n+m. This nibble belongs to the next IE 
            (usual coded by type BCD_MNC). 
            Type BCD_NOFILL is coded by startDigit EQ 2.  
*/

void cdc_BCD_decode (const ULONG e_ref, UBYTE startDigit, T_CCD_Globs *globs)
{
  BOOL    is_variable;
  UBYTE  *digits;
  UBYTE  *addr_c_xxx;
  ULONG   i, max_rep, nibbles_to_read, repeat;
  ULONG   cix_ref, num_prolog_steps, prolog_step_ref;
  int     k;

#ifdef DEBUG_CCD
  #ifndef CCD_SYMBOLS
  TRACE_CCD (globs, "cdc_BCD_decode()");
	#else
	TRACE_CCD (globs, "cdc_BCD_decode() %s", ccddata_get_alias((USHORT) e_ref, 1));
	#endif
#endif

  cix_ref = melem[e_ref].calcIdxRef;
  num_prolog_steps = calcidx[cix_ref].numPrologSteps;
  prolog_step_ref  = calcidx[cix_ref].prologStepRef;

  /*
   * if this element is conditional, check the condition
   */
  if (calcidx[cix_ref].numCondCalcs NEQ 0
  AND ! ccd_conditionOK (e_ref, globs))
    return;

  /*
   * if this element have a defined Prolog
   * we have to process it before decoding the bitstream
   */
  if (num_prolog_steps)
  {
    ccd_performOperations (num_prolog_steps, prolog_step_ref, globs);
  }
  
  /*
   * if this element is repeatable, and the number of
   * repeats depends on another element, calculate the repeater
   */

  if (melem[e_ref].repType NEQ ' ')
  {
   is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs);
  }
  else
  {
    repeat = 1;
    is_variable = FALSE;
  }
  
  /*
   * setup the offset into the C-structure for this element
   */
  globs->pstructOffs = melem[e_ref].structOffs;

  if (melem[e_ref].optional)
  {
    /*
     * for optional elements set the valid-flag
     */
    globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE;
  }


  if (is_variable)
  {
    /*
     * for variable sized elements store the min-value
     * as counter into the C-Structure (c_xxx).
     */
    addr_c_xxx = (UBYTE *) (globs->pstruct + globs->pstructOffs++);
    if (max_rep > 255)
      globs->pstructOffs++;
  }
  else
    addr_c_xxx = NULL;

  digits = (UBYTE *) (globs->pstruct + globs->pstructOffs);


  if (startDigit EQ 1)
  {
    /*
     * read the BCD digits out of the bitstream.
     * The read order is 1,X,3,2,5,4 ...
     */
    /*
     * if the first digit is digit_1 read it and skip
     * the next 4 bits, because they do not belong to
     * the BCD stream.
     */
    digits[0] = bf_decodeByteNumber (4, globs);
    bf_incBitpos (4, globs);
    /*
     * make a correction on the repeatvalue
     */
    if (melem[e_ref].repType NEQ ' ')
    {
      is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs);
    }

    k = 2;

    for (i=0; i<repeat; i++)
    {
      digits[k] = bf_decodeByteNumber (4, globs);
  #ifdef DEBUG_CCD
      TRACE_CCD (globs, "BCD digit (%X) read", (USHORT) digits[k]);
  #endif
      k = ((k&1) EQ 0) ? (k-1) : (k+3);
    }
  }
  else
  {
    /*
     * read the BCD digits out of the bitstream.
     * The read order is 2,1,4,3,6,5 ...
     */
    k = 1;

    nibbles_to_read = repeat;

    if (repeat & 1)
      nibbles_to_read++;

    for (i=0; i<nibbles_to_read; i++)
    {
      digits[k] = bf_decodeByteNumber (4, globs);
  #ifdef DEBUG_CCD
      TRACE_CCD (globs, "BCD digit (%X) read", (USHORT) digits[k]);
  #endif
      k = ((k&1) EQ 1) ? (k-1) : (k+3);
    }
  }

  /*
   * check the 1111 pattern and the even odd criteria
   */

  if (startDigit EQ 1)
  {
    if ((repeat & 1) EQ 0) 
    {
      /* even number of digits */
      if (digits[repeat] NEQ 0xf)
        repeat++;
    }
  }
  else
  {
    if ((repeat & 1) EQ 1) 
    {
      /* odd number of digits */
      if (digits[repeat] NEQ 0xf AND startDigit EQ 0)
      {
        /*
         * if there is no 1111 pattern generate an error
         */
        ccd_setError (globs, ERR_PATTERN_MISMATCH,
                      CONTINUE,
                      (USHORT) (globs->bitpos-8), (USHORT) -1);
      }
    }

    else
    {
      /* even number of digits - the last may be 0xf */
      if (digits[repeat-1] EQ 0xf)
        repeat--;   /* 0x0f dosn't belong to the coded digit string */
    }
  }

  if (addr_c_xxx NEQ NULL)
  {
    /*
     * store the number of digits into the 
     * c_xxx variable if there is one.
     */
     if (max_rep > 65535)
     {
       ULONG *addr_c_xxx_u32;
       addr_c_xxx_u32 = (ULONG *)addr_c_xxx;
       *addr_c_xxx_u32 = repeat;
     }
     else if (max_rep > 255)
     {
       USHORT *addr_c_xxx_u16;
       addr_c_xxx_u16 = (USHORT *)addr_c_xxx;
       *addr_c_xxx_u16 = (USHORT) repeat;
     }
     else
       *addr_c_xxx = (UBYTE) repeat;
  }
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CCD                 |
| STATE   : code                       ROUTINE : cdc_BCD_encode      |
+--------------------------------------------------------------------+

  PURPOSE : encoding a Bytearray, that contain a BCD Number, into
            bitstream.
            The digits coded in the following order
            into the Bitstream:

            MSBit     LSBit   
            7 8 6 5 4 3 2 1
            DIGIT_2 DIGIT_1    Octett n
            DIGIT_4 DIGIT_3    Octett n+1
            : : : : : : : :
            DIGIT_Z DIGIT_X    Octett n+m
            
            if the number of the digits are odd, the bit pattern 1111
            will be coded in the most significant nibble of
            the last Octett.
            
            : : : : : : : :
            1 1 1 1 DIGIT_X    Octett n+m

            The amount of digits may be constant or variable.
*/
void cdc_BCD_encode (const ULONG e_ref, UBYTE startDigit, T_CCD_Globs *globs)
{
  ULONG           repeat;
  int             k;
  register UBYTE *digits;
  BOOL            fullBitsNeeded=FALSE;
  ULONG           cix_ref, num_prolog_steps, prolog_step_ref;

#ifdef DEBUG_CCD
  #ifndef CCD_SYMBOLS
  TRACE_CCD (globs, "cdc_BCD_encode()");
	#else
	TRACE_CCD (globs, "cdc_BCD_encode() %s", ccddata_get_alias((USHORT) e_ref, 1));
	#endif
#endif

  cix_ref = melem[e_ref].calcIdxRef;  
  num_prolog_steps = calcidx[cix_ref].numPrologSteps;
  prolog_step_ref  = calcidx[cix_ref].prologStepRef;

  /*
   * if this element is conditional, check the condition
   */
  if (calcidx[cix_ref].numCondCalcs NEQ 0
  AND ! ccd_conditionOK (e_ref, globs))
    return;

  /*
   * if this element have a defined Prolog
   * we have to process it before decoding the bitstream
   */
  if (num_prolog_steps)
  {
    ccd_performOperations (num_prolog_steps, prolog_step_ref, globs);
  }
  
  /*
   * setup the offset into the C-structure for this element
   */
  globs->pstructOffs = melem[e_ref].structOffs;

  if (melem[e_ref].optional)
  {
    /*
     * for optional elements check the valid-flag
     */
    if (globs->pstruct[globs->pstructOffs++] == FALSE)
      return;
#ifdef DEBUG_CCD
    else if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
    {
      TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d",
                 e_ref);
    }
#endif
  }

  /* 
   * if this element is repeatable, and the number of
   * repeats depends on another element, calculate the repeater
   */
  if (melem[e_ref].repType EQ 'v' OR melem[e_ref].repType EQ 'i')
  {
    /*
     * for variable sized elements read the amount
     * of repeats out of the C-Structure (c_xxx).
     * If the number of repeats given by the C-Structure 
     * exceeds the allowed value (maxRepeat) CCD gives a warning!
     */
    if (melem[e_ref].maxRepeat > 255)
    {
      ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++));
      repeat = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat);
      if (repeat < count) 
         ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
                          e_ref, globs->pstruct + globs->pstructOffs);
    }
    else
    {
      repeat = (ULONG)MINIMUM (globs->pstruct[globs->pstructOffs], 
                                melem[e_ref].maxRepeat);
      if ( repeat < (ULONG) (globs->pstruct[globs->pstructOffs]) )
         ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
                          (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
    }
    globs->pstructOffs++;
  }
  else
    if (melem[e_ref].repType EQ 'c')
      repeat = (ULONG) melem[e_ref].maxRepeat;
    else
      repeat = 1; 

  /* There seems to exist cases where address contains no digits. */
  if (repeat EQ 0)
    return;

  /* 
   * setup the read pointer to the byte array that contain
   * the BCD number.
   */
  digits = (UBYTE *) (globs->pstruct + globs->pstructOffs);

  if (startDigit EQ 1)
  {
    /*
     * write the BCD digits into the bitstream.
     * The write order is 1,X,3,2,5,4 ...
     */
    if ((repeat & 1) EQ 0)
    {
      /*
       * for even digits store the 1111 pattern at last digit
       */
      fullBitsNeeded = TRUE;
    }
    /*
     * if the first digit is digit_1 write it and skip
     * the next 4 bits, because they does not belong to
     * the BCD stream.
     */
    bf_codeByteNumber (4, digits[0], globs);

  #ifdef DEBUG_CCD
    TRACE_CCD (globs, "BCD digit (%X) written", (USHORT) digits[0]);
    TRACE_CCD (globs, "skipping 4 bits");
  #endif

    bf_incBitpos (4, globs);
    k = 2;

    while (--repeat>1)
    {
      bf_codeByteNumber (4, digits[k], globs);
  #ifdef DEBUG_CCD
      TRACE_CCD (globs, "BCD digit (%X) written", (USHORT) digits[k]);
  #endif
      k = ((k&1) EQ 0) ? (k-1) : (k+3);
    }
    if (repeat)
    {
    if (fullBitsNeeded)
    {
      bf_codeByteNumber (4, 0xf, globs);
      k = ((k&1) EQ 0) ? (k-1) : (k+3);
      }
      bf_codeByteNumber (4, digits[k], globs);
   }
    
  }
  else
  {
    /*
     * store the BCD digits into the bitstream.
     * The write order is 2,1,4,3,6,5 ...
     */
    if (repeat & 1)
    {
      /*
       * for odd digits store the 1111 pattern at last digit
       * in case of type BCD_NOFILL use 0 instead
       */
        fullBitsNeeded = TRUE;
    }

    k = 1;

    while ( repeat-- > 1)
    {
      bf_codeByteNumber (4, digits[k], globs);
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "BCD digit (%X) written", (USHORT) digits[k]);
#endif
      k = ((k&1) EQ 1) ? (k-1) : (k+3);
    }
    if (fullBitsNeeded)
    {
      bf_codeByteNumber (4, (UBYTE)((startDigit NEQ 2) ? 0xf : 0), globs);
      k = ((k&1) EQ 1) ? (k-1) : (k+3);
    }
    bf_codeByteNumber (4, digits[k], globs);
  }
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_FLASH
/* Attention for RUN_...: static function */
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_init_table      |
+--------------------------------------------------------------------+

  PURPOSE : init the iei_table for each new msg that is to be decoded.
            The c_ref references a composition (msg). The function
            initialises the table entrys only for the used iei for
            this message.

*/

static void cdc_init_table (const ULONG c_ref, T_CCD_Globs *globs)

{
  ULONG  look_up;
  ULONG  num_elems;
  ULONG  ie_table_idx;
  ULONG  rlevel = globs->ccd_recurs_level;

  if (globs->iei_ctx[rlevel].valid AND rlevel < (ULONG) globs->last_level)
  {
    int i;
    /*
     * this iei context has been initialized before, so
     * no action for this. All deeper levels must be set
     * to invalid;
     */
    for (i=globs->last_level; i<MAX_RECURSIONS_PER_MSG; i++)
       globs->iei_ctx[i].valid = FALSE;
 
#ifdef DEBUG_CCD
    TRACE_CCD (globs, "TAG table init for old level %d", rlevel);
#endif
  }
  else
  {
    /*
     * this iei context has not been initialized before, so
     * initialize the iei_table for this.
     */
#ifdef DEBUG_CCD
  TRACE_CCD (globs, "TAG table init for new level %d", rlevel);
#endif
    look_up   = (ULONG) mcomp[c_ref].componentRef;
    num_elems = (ULONG) mcomp[c_ref].numOfComponents;

    /*
     * store the startposition of the corresponding melem table and
     * the number of elements in the IEtable
     */
    globs->iei_ctx[rlevel].melemStart   = (USHORT) look_up;
    globs->iei_ctx[rlevel].ieTableLen   = (USHORT) num_elems;
    globs->iei_ctx[rlevel].EOCPending   = FALSE;
    globs->iei_ctx[rlevel].countSkipped = 0;

    /* 
     * for each element with an iei (ident) setup the 
     * the iei_table-entry.
     */
    ie_table_idx = 0;

    /*
     * if the number of IE in this message is greater than 
     * the allocated IEItable, generate an error.
     */
    if (num_elems > MAX_IE_PER_MSG)
      ccd_setError (globs, ERR_INTERNAL_ERROR, BREAK, (USHORT) -1);

    while (num_elems--)
    {
      if (melem[look_up].ident NEQ 0xffff)
      {  
        globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident = (UBYTE) melem[look_up].ident;
        
        /*
         * GSM1TV elements have only a 4 bit Tag (T). For this 
         * elements we have to shift the ident into the upper nibble
         * and set the lower nibble to zero. For GSM2T elements and
         * GSM1TV elements set the MSBit (Bit7). 
         */
        if (melem[look_up].codingType EQ CCDTYPE_GSM1_TV)
        {
          /*
           * shift into the upper nibble, clear the lower nibble
           * and set the MSBit.
           */
          globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident <<= 4;
          globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident |= 0x80;
          globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident &= 0xf0;
        }
        else
        {
          if (melem[look_up].codingType EQ CCDTYPE_GSM2_T)
          {
            /*
             * Set the MSBit.
             */
            globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident |= 0x80;
          }
        }
        globs->iei_ctx[rlevel].iei_table[ie_table_idx].act_amount = 0;
        globs->iei_ctx[rlevel].iei_table[ie_table_idx].exhausted = FALSE;

        switch (melem[look_up].codingType)
        {      
          case CCDTYPE_GSM1_TV:

          case CCDTYPE_GSM2_T:

          case CCDTYPE_GSM3_TV:

          case CCDTYPE_GSM4_TLV:

          case CCDTYPE_GSM5_TV:

          case CCDTYPE_GSM5_TLV:

          case CCDTYPE_GSM1_ASN:

          case CCDTYPE_GSM6_TLV:

            globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid = TRUE;
            break;

          default:
            globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid = FALSE;
            break;
        }
      }
      else
        globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid = FALSE;

#ifdef DEBUG_CCD
    TRACE_CCD (globs, "iei_table[%d] v=%d ident=%x level=%d",
                ie_table_idx,
                globs->iei_ctx[rlevel].iei_table[ie_table_idx].valid,
                globs->iei_ctx[rlevel].iei_table[ie_table_idx].ident,
                rlevel);
#endif

      look_up++;
      ie_table_idx++;
    }
    globs->iei_ctx[rlevel].valid = TRUE;
  }
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/* Attention for RUN_...: static function */
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_search_table    |
+--------------------------------------------------------------------+

  PURPOSE : search on the iei_table for the given TAG (T).
            if the TAG can be found (and - in case of CCDTYPE_GSM1_ASN - 
            if the information element isn't exhausted), the table 
            index was returned as a difference between the found index
            and the aktIndex, -127 otherwise.
  
*/

static int cdc_search_table 
            ( 
              int   akt_index,
              ULONG t,
              BOOL  limited,
              BOOL  *nonTaggedFound,
              T_CCD_Globs *globs
            )
{
  int   tab_idx;
  ULONG iei;
  int   ret = -127;
  ULONG rec_level = globs->ccd_recurs_level;
  
  /*
   * search from the akt position to the end of the table.
   * This is faster, because in correct messages the found Tag
   * is at a later position in the table. 
   */
  tab_idx = akt_index;
  
  *nonTaggedFound = FALSE;

  while (tab_idx < (int) globs->iei_ctx[rec_level].ieTableLen)
  {
#ifdef DEBUG_CCD
    TRACE_CCD (globs, "looking for Tag(%x) iei_table[%d] v=%d ident=%x level=%d",
                t, tab_idx,
                globs->iei_ctx[rec_level].iei_table[tab_idx].valid,
                globs->iei_ctx[rec_level].iei_table[tab_idx].ident,
                rec_level);
#endif

    if (globs->iei_ctx[rec_level].iei_table[tab_idx].valid)
    {
      if (limited)
      {
        iei= (ULONG)(globs->iei_ctx[rec_level].iei_table[tab_idx].ident & 0x7f);
      }
      else
      {
        iei= (ULONG)(globs->iei_ctx[rec_level].iei_table[tab_idx].ident);
      }
      if ( iei EQ t )
      {
        if ( globs->iei_ctx[rec_level].iei_table[tab_idx].exhausted EQ FALSE )
        {
          return (tab_idx-akt_index);
        }
        else if ( (globs->iei_ctx[rec_level].melemStart + akt_index) 
            EQ  (int) globs->iei_ctx[rec_level].melemLast)
        {
         /*
          * allows multiple appearance of the repeated element is coded as 
          * TLV0 TLV1 TLV2 ....
          */
          return (tab_idx-akt_index);
        }
        else 
        {
          ret = (tab_idx-akt_index);
        }
      }
    }
    else
      *nonTaggedFound = TRUE;        
    tab_idx++;
  }

  tab_idx = 0;

  while (tab_idx < akt_index)
  {
#ifdef DEBUG_CCD
    TRACE_CCD (globs, "looking for Tag(%x) iei_table[%d] v=%d ident=%x level=%d",
                t, tab_idx,
                globs->iei_ctx[rec_level].iei_table[tab_idx].valid,
                globs->iei_ctx[rec_level].iei_table[tab_idx].ident,
                rec_level);
#endif
    if (limited)
    {
      iei= (ULONG)(globs->iei_ctx[rec_level].iei_table[tab_idx].ident & 0x7f);
    }
    else
    {
      iei= (ULONG) globs->iei_ctx[rec_level].iei_table[tab_idx].ident;
    }
    if (globs->iei_ctx[rec_level].iei_table[tab_idx].valid
    AND (iei EQ t) )
    {
      if ( globs->iei_ctx[rec_level].iei_table[tab_idx].exhausted EQ FALSE )
      {
        return (tab_idx-akt_index);
      }
      else 
      {
        ret = (tab_idx-akt_index);
      }
    }
    tab_idx++;
  }
 
  if (ret != -127)
  {
    globs->SequenceError = TRUE;
  }
    
  return ret;
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/* Attention for RUN_...: static function */
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_decode_L        |
+--------------------------------------------------------------------+

  PURPOSE : Decode the length element of TLV and LV values
*/

static ULONG cdc_decode_L (const ULONG  e_ref, const ULONG len_l, T_CCD_Globs *globs)
{
  ULONG l;
  
  switch (melem[e_ref].codingType)
  {
    case CCDTYPE_GSM1_ASN:
      l = (ULONG) bf_decodeByteNumber (8, globs);
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "decoding 8 bits, l = (%x)", l);
#endif
      if (l EQ 0x80)
        l = 0xFFFF;
      else if (l EQ 0x81)
      {
        l = (ULONG) bf_decodeByteNumber (8, globs);
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "decoding 8 bits after 0x81, l = (%x)", l);
#endif
      }
      else if (l EQ 0x82)
      {
        l = bf_decodeShortNumber (16, globs);
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "decoding 16 bits after 0x82, l = (%x)", l);
#endif
      }
      break;
  
    case CCDTYPE_GSM5_TLV:
      l = (ULONG) bf_decodeByteNumber (8, globs);

      if (l EQ 0x81)
      {
        l = (ULONG) bf_decodeByteNumber (8, globs);
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "decoding 8 bits after 0x81, l = (%x)", l);
      }
      else
      {
        TRACE_CCD (globs, "decoding 8 bits, l = (%x)", l);
#endif
      }
      break;

   case CCDTYPE_GSM6_TLV:
      l = bf_decodeShortNumber (16, globs);
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "decoding 16 bits, l = (%x)", l);
#endif
      break;  

    default:
      l = (ULONG) bf_decodeByteNumber (len_l, globs);
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "decoding %d bits, l = (%x)", len_l, l);
#endif
      break;
  }

  /*
   * Write the value of l at the end of UPN Stack.
   * this could be read by an IE of the coding type NO_CODE.
   */  
  globs->KeepReg[0] = l ; 
  return l;
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/* Attention for RUN_...: static function */
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_tagged_LV_decode|
+--------------------------------------------------------------------+

  PURPOSE : If the parameter lenL is set to a positive value,
            this function decodes the L-component.
            After this it decodes the element referenced
            by eRef out of the bitstream into the C-Structure
            (globs->pstruct) at position globs->pstructOffs.
            If a repeat value is defined for this element,
            this function decodes only one appeareance
            of the element because it is a tagged 
            element. In this case the decoded element is stored in
            an array wich is indexed by eIndex;
*/

static BOOL cdc_tagged_LV_decode (const ULONG e_ref,
                                  ULONG e_index,
                                  const ULONG len_l,
                                  T_CCD_Globs *globs)
{
  ULONG  amount, l;
  USHORT act_maxBP, tmp_maxBP; 
  BOOL   endOfComposition = FALSE;
  BOOL   asn1=FALSE;
  U32    offset=0;
#ifdef DYNAMIC_ARRAYS
  U8    *old_pstruct = NULL;
#endif
      
  if (melem[e_ref].codingType EQ CCDTYPE_GSM1_ASN)
    asn1 = TRUE;
 
  if (melem[e_ref].elemType NEQ 'S')
  {
    /*
     * set the offset into the C-structure for this element. 
     */
    if (melem[e_ref].optional)
    {
      globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE;
    }

    if (melem[e_ref].repType EQ 'i')
    {
      /*
       * The number of appearance of all repeatable IEs may
       * differ in a message. So we have to store the number
       * in a c_xxx counter into the C-Structure.
       */
      if (melem[e_ref].maxRepeat > 65535)
        *(ULONG  *) (globs->pstruct + globs->pstructOffs++) = e_index;
      else if (melem[e_ref].maxRepeat > 255)
        *(USHORT *) (globs->pstruct + globs->pstructOffs++) = (USHORT) e_index;
      else
        globs->pstruct[globs->pstructOffs] = (UBYTE) e_index;

      globs->pstructOffs++;

      /*
       * Recalculate the struct offset for repeatable IEs.
       * New pointer types 'R' and 'F' are equivalent to 'V'.
       */
#ifdef DYNAMIC_ARRAYS
      offset = (e_index-1) * ((melem[e_ref].elemType EQ 'V'
                              OR melem[e_ref].elemType EQ 'R'
                              OR melem[e_ref].elemType EQ 'F'
                              ) ? mvar[melem[e_ref].elemRef].cSize
			     : mcomp[melem[e_ref].elemRef].cSize
                             );
#else
      offset = (e_index-1) * ((melem[e_ref].elemType EQ 'V')
				      ? mvar[melem[e_ref].elemRef].cSize
				      : mcomp[melem[e_ref].elemRef].cSize
				      );
#endif
    }
  }
  /*
   * If len_l > 0 read the l-Component out of the bistream.
   */
  if (len_l)
  {
    if( len_l <= (ULONG) (globs->maxBitpos - globs->bitpos) )
    {
      act_maxBP = globs->maxBitpos;
      l = cdc_decode_L (e_ref, len_l, globs);

      if (l EQ 0xFFFF)
      {
        /*
         * For ASN1-BER encoding we must look for the special
         * length 0x80 because it indicates the indefinite
         * length. This needs a special handling with later EOC tags.
         *
         */
        globs->iei_ctx[globs->ccd_recurs_level].EOCPending = TRUE;
        globs->numEOCPending++;

  #ifdef DEBUG_CCD
        TRACE_CCD (globs, "implicit ASN1 length - EOC is pending");
  #endif
      }
      else
      {
        /*
         * Calculate the max bitpos for this element
         */
        tmp_maxBP = (USHORT) (globs->bitpos + (l*8));
        if (globs->buflen < tmp_maxBP)
        {
          ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
        }
        else if (globs->maxBitpos < tmp_maxBP)
        {
          ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
        }
        globs->maxBitpos = (USHORT)MINIMUM (globs->buflen, tmp_maxBP);
        tmp_maxBP = globs->maxBitpos;
      }
    }
    else 
    {
      ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
    }
  }
#ifdef DYNAMIC_ARRAYS
  /*
   * Check for pointer types; allocate memory if necessary.
   */
  if ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR
      (melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F')) 
  {
    U32     cSize;
    U8      *addr;

    /*
     * Find size to allocate;
     * - Read from mcomp or mvar according to type
     */
    cSize = (ULONG)((melem[e_ref].elemType EQ 'V' OR
		      melem[e_ref].elemType EQ 'R')
                     ? mvar[melem[e_ref].elemRef].cSize
                     : mcomp[melem[e_ref].elemRef].cSize
		     );

    /*
     * Allocate additional memory
     */
    addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS);

    /* If no memory, log error and return immediately */
    if (addr EQ NULL) {
      ccd_setError (globs, ERR_NO_MEM,
                    BREAK,
                    (USHORT) -1);
      return endOfComposition;
    }
    else
      memset (addr, 0, (size_t)(cSize));

    /*
     * Memory allocated;
     * 1. Save old "globs->pstruct" variables
     * 2. Store pointer to freshly allocated memory area in structure
     * 3. Initialize pstruct to point to the freshly allocated memory area.
     * 4. Initialize pstructOffs to 0 to start decoding at offset 0
     *    in the new memory area.
     */
    old_pstruct        = globs->pstruct;
    *(U8 **)(globs->pstruct + globs->pstructOffs) = addr;
    globs->pstruct     = addr;
    globs->pstructOffs = 0;
  }
  else
  {
    globs->pstructOffs += offset;
  }
#else /* DYNAMIC_ARRAYS */
  globs->pstructOffs += offset;
#endif /* DYNAMIC_ARRAYS */


  /*
   * Decode the value. Keep caution with BER encoding of ASN1 integers.
   * All other types can be decoded by a generic function.
   */
  if (asn1 AND melem[e_ref].elemType EQ 'V'
      AND
      melem[e_ref].repType EQ ' '
      AND
      l NEQ 0xFFFF
     )
  {
#ifdef DEBUG_CCD
#ifdef CCD_SYMBOLS
    TRACE_CCD (globs, "BER decoding of ASN.1 integer %s",
               ccddata_get_alias((USHORT) e_ref, 1));
#else
    TRACE_CCD (globs, "BER decoding of ASN.1 integer; e_ref = %d", melem[e_ref].elemRef);
#endif
#endif

    if (mvar[melem[e_ref].elemRef].cType EQ 'X')
      bf_readBitChunk (l*8, globs);
    else
      bf_readBits (l*8, globs);
  }
  else
  {
    amount = 1;
    if (len_l)
    {
      if (l > 0)
      {
        cdc_decodeElemvalue (e_ref, &amount, globs);
      }
      else
      {
        amount = 0;
      }
    }
    else
    {
      if (melem[e_ref].codingType != CCDTYPE_GSM2_T)
        cdc_decodeElemvalue (e_ref, &amount, globs);
    }
  }
#ifdef DYNAMIC_ARRAYS
  /*
   * Restore globs->pstruct for possible use below
   */
  if (old_pstruct NEQ NULL)
    globs->pstruct     = old_pstruct;
#endif

  if (asn1 AND globs->numEOCPending AND !bf_endOfBitstream(globs))
  {
    UBYTE T = bf_decodeByteNumber (8, globs);
#ifdef DEBUG_CCD
    TRACE_CCD (globs, "looking for EOC decoding 8 bits T = (%x)", T);
#endif

    if (T EQ 0)
    {
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "First EOC octet found");
#endif

      if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) 
      {
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "End of ASN1 TLV");
#endif
        /*
         * Skip the second EOC octet.
         */
        bf_incBitpos (8, globs);
        globs->iei_ctx[globs->ccd_recurs_level].EOCPending = FALSE;
        globs->numEOCPending--;
      }
      else
      {
        /*
         * The read first EOC octet belongs to an ASN1 TLV of a 
         * higher recursion level. Let it be read and evalauted later 
         * again for that IE.
         */
        bf_setBitpos (globs->bitpos-8, globs);
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "End of higer level ASN1 TLV");
        TRACE_CCD (globs, "Decrementing bitpos by 8 to %d", globs->bitpos);
#endif
        endOfComposition = TRUE;
      }
    }
    else
    {
      if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending)
      {
        /*
         * EOC element is pending but not found.
         */
        ccd_setError (globs, ERR_EOC_TAG_MISSING,
                      BREAK,
                      (USHORT) T,
                      globs->bitpos-8,
                      (USHORT) -1);

        bf_setBitpos (globs->bitpos-8, globs);
      }
      else
      {
        /*
         * normal TAG leave it in the bitstream
         */
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "Normal TAG - Decrementing bitpos by 8 to %d", globs->bitpos);
#endif
        bf_setBitpos (globs->bitpos-8, globs);
      }
    }
  }

  if (len_l)
  {
    if (!asn1)
    {
      if (globs->bitpos > tmp_maxBP)
      {
        ccd_recordFault (globs, ERR_ELEM_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
      }
      else
      {
        /*
         * set the bitpos to the end of the LV or TLV element
         */
        bf_setBitpos (tmp_maxBP, globs);
      }
    }
    /*
     * set the maxBitpos to the next octet boundary if the 
     * last non-spare IE does not end at an octet boundary.
     * This is necessary for avoiding an early end of decoding.
     */
/*  
    globs->maxBitpos = globs->buflen;
*/
    globs->maxBitpos = act_maxBP;
  }

  return endOfComposition;
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/* Attention for RUN_...: static function */
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_normal_LV_decode|
+--------------------------------------------------------------------+

  PURPOSE : If the parameter lenL is set, this function
            decodes the L-component. After this it decodes
            the element referenced by eRef from the
            bitstream into the C-Structure (globs->pstruct)
            at position globs->pstructOffs. 
            If a repeat value is defined for this element
            this function decodes the V-component multiple and stores
            the values into an array.
*/

static BOOL cdc_normal_LV_decode (const ULONG  e_ref,
                                  const ULONG  len_l,
                                  T_CCD_Globs *globs)
{
  ULONG  l, repeat, amount, max_rep;
  USHORT act_maxBP, tmp_maxBP; 
  BOOL   is_variable;
  BOOL   endOfComposition = FALSE;
  BOOL   asn1;
  BOOL   length_in_bits;
#ifdef DYNAMIC_ARRAYS
  U8    *old_pstruct = NULL;
#endif  

  switch (melem[e_ref].codingType)
  {
    case CCDTYPE_GSM1_ASN:
      asn1 = TRUE;
      length_in_bits = FALSE;
      break;

    case CCDTYPE_GSM7_LV:
      asn1 = FALSE;
      length_in_bits = TRUE;
      break;

    default:
      asn1 = FALSE;
      length_in_bits = FALSE;
      break;
  }

  /* 
   * if this element is repeatable, and the number of
   * repeats depends on another element, calculate the repeater
   */
  if (melem[e_ref].repType NEQ ' ')
  {
    is_variable = ccd_calculateRep (e_ref, &repeat, &max_rep, globs);
  }
  else
  {
    repeat = 1;
    is_variable = FALSE;
  }

  if (melem[e_ref].elemType NEQ 'S')
  {
    /*
     * Element is not a SPARE.
     * Setup the offset into the C-structure for this element
     */
    if (melem[e_ref].optional)
    {
      globs->pstruct[globs->pstructOffs++] = (UBYTE) TRUE;
    }

    if (is_variable)
    {
      /*
       * for variable sized elements store the min-value
       * as counter into the C-Structure (c_xxx).
       */
      if (max_rep > 65535)
        *(ULONG *) (globs->pstruct + globs->pstructOffs++) = repeat;
      else if (max_rep > 255)
        *(USHORT *) (globs->pstruct + globs->pstructOffs++) = (USHORT) repeat;
      else
        globs->pstruct[globs->pstructOffs] = (UBYTE) repeat;

      globs->pstructOffs++;
    }
  }

  /*
   * if len_l > 0 read the l-Component out of the bistream.
   */
  if (len_l)
  {
    if( len_l <= (ULONG)(globs->maxBitpos - globs->bitpos) )
    {
      act_maxBP = globs->maxBitpos;

      l = cdc_decode_L (e_ref, len_l, globs);

      if (l EQ 0xFFFF)
      {
        /*
         * for ASN1 element coding we must look for the special
         * length 0x80 because it indicates the indefinite
         * length. This needs a special handling with later EOC tags.
         */
        globs->iei_ctx[globs->ccd_recurs_level].EOCPending = TRUE;

        globs->numEOCPending++;

  #ifdef DEBUG_CCD
        TRACE_CCD (globs, "implicit ASN1 length - EOC is pending");
  #endif
      }
      else
      {
        /*
         * calculate the max bitpos for this element
         */
        if (!length_in_bits)
          l *= 8;

        tmp_maxBP = (USHORT) (globs->bitpos + l);

        if (globs->buflen < tmp_maxBP)
        {
          ccd_recordFault (globs, ERR_MSG_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
        }
        else if (globs->maxBitpos < tmp_maxBP)
        {
          ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
        }
        globs->maxBitpos = (USHORT)MINIMUM (globs->buflen, tmp_maxBP); 
        tmp_maxBP = globs->maxBitpos;
       
        /*
         * for bitfields which appear in TLV or LV elements
         * we must calculate the length (repeat) from the l values
         */
         if (melem[e_ref].repType EQ 'b')
           repeat = l;
      }
    }
    else
    {
      ccd_recordFault (globs, ERR_ELEM_LEN, BREAK, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
    }
  }
#ifdef DYNAMIC_ARRAYS
  /*
   * MVJ: Dynamic array addition.
   * Check for pointer types; allocate memory if necessary.
   */
  if ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR
      (melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F')) {
    ULONG    cSize, rep;
    U8      *addr;

    /*
     * Find size to allocate;
     * - Read from mcomp or mvar according to type
     * - Unbounded (0-terminated) ASN1-types are allocated with MAX repeat
     */
    if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) {
      rep = (ULONG) melem[e_ref].maxRepeat;
    } else {
      rep = repeat;
    }
    cSize = (ULONG)((melem[e_ref].elemType EQ 'V' OR
		      melem[e_ref].elemType EQ 'R')
                     ? mvar[melem[e_ref].elemRef].cSize
                     : mcomp[melem[e_ref].elemRef].cSize
		     ) * rep;

    /*
     * Allocate additional memory
     */
    addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS);

    /* If no memory, log error and return immediately */
    if (addr EQ NULL) {
      ccd_setError (globs, ERR_NO_MEM,
                    BREAK,
                    (USHORT) -1);
      return endOfComposition;
    }
    else
      memset (addr, 0, (size_t)cSize);

    /*
     * Memory allocated;
     * 1. Save old "globs->pstruct" variables
     * 2. Store pointer to freshly allocated memory area in structure
     * 3. Initialize pstruct to point to the freshly allocated memory area.
     * 4. Initialize pstructOffs to 0 to start decoding at offset 0
     *    in the new memory area.
     */
    old_pstruct        = globs->pstruct;
    *(U8 **)(globs->pstruct + globs->pstructOffs) = addr;
    globs->pstruct     = addr;
    globs->pstructOffs = 0;
  }
#endif

  /*
   * Decode the value. Keep caution with BER encoding of ASN1 integers.
   * All other types can be decoded by a generic function.
   */
  if (asn1 AND melem[e_ref].elemType EQ 'V' 
      AND 
      melem[e_ref].repType EQ ' ' 
      AND 
      l NEQ 0xFFFF
     )
  {
#ifdef DEBUG_CCD
#ifdef CCD_SYMBOLS
    TRACE_CCD (globs, "BER decoding of ASN.1 integer %s",
               ccddata_get_alias((USHORT) e_ref, 1));
#else
    TRACE_CCD (globs, "BER decoding of ASN.1 integer; e_ref = %d", melem[e_ref].elemRef);
#endif
#endif
    amount = l;
    if (mvar[melem[e_ref].elemRef].cType EQ 'X')
      bf_readBitChunk (l, globs);
    else
      bf_readBits (l, globs);
  }
  else
  {
    amount = repeat;
    if (len_l)
    {
      if (l > 0)
      {
        cdc_decodeElemvalue (e_ref, &amount, globs);
      }
      else
      {
        amount = 0;
      }
    }
    else
    {
      if (melem[e_ref].codingType != CCDTYPE_GSM2_T)
        cdc_decodeElemvalue (e_ref, &amount, globs);
    }
  }

#ifdef DYNAMIC_ARRAYS
  /*
   * Restore globs->pstruct for possible use below
   */
  if (old_pstruct NEQ NULL) {
    globs->pstruct     = old_pstruct;
  }
#endif

  if (amount NEQ repeat AND is_variable)
  {
    /*
     * If the number of decoded elements is not equal to the given
     * repeat value, because the bitstream or the IE ended,
     * store the new c_xxx value.
     */
    globs->pstructOffs = melem[e_ref].structOffs;

    if (melem[e_ref].optional)
      globs->pstructOffs++;

    globs->pstruct[globs->pstructOffs] = (UBYTE) amount;

    if (melem[e_ref].repType NEQ 'i')
    {
      /*
       * if this element is not of the repeat style 'interval'
       * ([X..Y] where X and Y are constants) we have to generate
       * an ccd error because some outstanding repeats are missing.
       */
      ccd_setError (globs, ERR_MAND_ELEM_MISS,
                    CONTINUE,
                    (USHORT) -1);
    }
  }

  if (asn1 AND globs->numEOCPending AND !bf_endOfBitstream(globs))
  {
    UBYTE T = bf_decodeByteNumber (8, globs);
#ifdef DEBUG_CCD
    TRACE_CCD (globs, "looking for EOC decoding 8 bits T = (%x)", T);
#endif

    if (T EQ 0)
    {
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "First EOC octet found");
#endif

      if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending) 
      {
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "End of ASN1 TLV");
#endif
        /*
         * Skip the second EOC octet.
         */
        bf_incBitpos (8, globs);
        globs->iei_ctx[globs->ccd_recurs_level].EOCPending = FALSE;
        globs->numEOCPending--;
      }
      else
      {
        /*
         * The read first EOC octet belongs to an ASN1 TLV of a 
         * higher recursion level. Let it be read and evalauted later 
         * again for that IE.
         */
        bf_setBitpos (globs->bitpos-8, globs);
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "End of higer level ASN1 TLV");
        TRACE_CCD (globs, "Decrementing bitpos by 8 to %d", globs->bitpos);
#endif
        endOfComposition = TRUE;
      }
    }
    else
    {
      if (globs->iei_ctx[globs->ccd_recurs_level].EOCPending)
      {
        /*
         * EOC element is pending but not found.
         */
        ccd_setError (globs, ERR_EOC_TAG_MISSING,
                      BREAK,
                      (USHORT) T,
                      globs->bitpos-8,
                      (USHORT) -1);

        bf_setBitpos (globs->bitpos-8, globs);
      }
      else
      {
        /*
         * normal TAG leave it in the bitstream
         */
#ifdef DEBUG_CCD
        TRACE_CCD (globs, "Normal TAG - Decrementing bitpos by 8 to %d", globs->bitpos);
#endif
        bf_setBitpos (globs->bitpos-8, globs);
      }
    }
  }

  if (len_l)
  {
    if (!asn1)
    {
      if (globs->bitpos > tmp_maxBP)
      {
        ccd_recordFault (globs, ERR_ELEM_LEN, CONTINUE, (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
      }
      else
      {
        /*
         * set the bitpos to the end of the LV or TLV element
         */
         bf_setBitpos (tmp_maxBP, globs);
      }
    }

    /*
     * set the maxBitpos to the next octet boundary if the 
     * last non-spare IE does not end at an octet boundary.
     * This is necessary for avoiding an early end of decoding.
     */
/*
    globs->maxBitpos = globs->buflen;
*/
    globs->maxBitpos = act_maxBP;
  }

  return endOfComposition;
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/* Attention for RUN_...: static function */
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_skipElem        |
+--------------------------------------------------------------------+

  PURPOSE : Skip an element referenced by eRef. This function
            perform a decoding of this element, but not into
            the target C-Structure. A dummy C-Structure is used
            instead.
            The complete decoding is necesary, because there is
            no information about the length of this element.
            B.t.w. for mandatory elements with fixed length, we can
            calculate the length, for optional elements or for
            variable sized arrays or bitbuffers it is impossible
            without decoding the entire element.
*/

static void cdc_skipElem (const ULONG e_ref, const ULONG len_l, T_CCD_Globs *globs)
{
  UBYTE  *ActStructAddr;
  U32    ActStructOffs;

#ifdef DEBUG_CCD
  TRACE_CCD (globs, "skipping element %d",
             melem[e_ref].elemRef);
#endif

  ActStructAddr = globs->pstruct; 
  ActStructOffs = globs->pstructOffs; 

  globs->pstruct     = dummy; 
  globs->pstructOffs = 0;
  
  cdc_tagged_LV_decode (e_ref, 1, len_l, globs);

  globs->pstruct     = ActStructAddr; 
  globs->pstructOffs = ActStructOffs; 
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_tlv_decode      |
+--------------------------------------------------------------------+

  PURPOSE : Decoding of the T-components of T TV and TLV typed
            information elements. The len determines the
            length of the T component. This function returns the
            index (reference) of the rigth element. If the
            iei is not known in this composition (msg or submsg)
            an error handling is done and NO_REF is returned. 

*/

SHORT cdc_tlv_decode (const ULONG c_ref,
                      const ULONG e_ref,
                      const T_TLV_SORT  *tlv_inf,
                            T_CCD_Globs *globs)
{
  ULONG  repeat, max_rep;
  ULONG  ie_amount, l, len_l, len_t, t;
  BOOL   is_variable, nonTagged, limitSearch=FALSE;
  UBYTE  CR=FALSE;
  SHORT  IdxOffset = 0;
  int    ieTableIdx;
  BOOL   asn1, non_std_tag;
  SHORT  ret;
  ULONG  cix_ref, num_prolog_steps, prolog_step_ref;
  /* .../src/linux/include/asm/current.h defines a macro 'current' */
  T_UNKNOWN_TAG *first, *currentTag;


  /*
   * Set the flag for the type of extension which is to expect
   * at the end of the message.
   */
  globs->SeekTLVExt = TRUE;

  /* Set ref number for calcidx table. */
  cix_ref = melem[e_ref].calcIdxRef;
  num_prolog_steps = calcidx[cix_ref].numPrologSteps;
  prolog_step_ref  = calcidx[cix_ref].prologStepRef;

  /*
   * if this element is conditional, check the condition
   */
  if (calcidx[cix_ref].numCondCalcs NEQ 0
  AND ! ccd_conditionOK (e_ref, globs))
    return 1;

  len_t = 8; 
  switch (melem[e_ref].codingType)
  {
    case CCDTYPE_GSM1_ASN:
      asn1        = TRUE;
      non_std_tag = FALSE;
      len_l        = 8;
      break;

    case CCDTYPE_GSM5_TV:
    case CCDTYPE_GSM5_TLV:
      non_std_tag = TRUE;
      asn1        = FALSE;
      len_l        = 8;
      break;

    case CCDTYPE_GSM6_TLV:
      non_std_tag = FALSE;
      asn1        = FALSE;
      len_l        = 16;
      break;

    case CCDTYPE_GSM7_LV:
      non_std_tag = FALSE;
      asn1        = FALSE;
      len_l        = 7;
      break;

    default:
      asn1        = FALSE;
      non_std_tag = FALSE;
      len_l        = 8;
      break;
  }

  /*
   * if this element have a defined Prolog
   * we have to process it before decoding the bitstream
   */
  if (num_prolog_steps)
  {
    ccd_performOperations (num_prolog_steps, prolog_step_ref, globs);
  }
  
  if (tlv_inf->gotTag)
  {
    /* 
     * tagged element
     */
    len_t = 8;
    /*
     * initialize the iei_table for each new message
     */
    if (globs->ccd_recurs_level NEQ globs->last_level)
    {
      cdc_init_table (c_ref, globs);
      globs->TagPending    = FALSE;
      globs->SequenceError = FALSE;
      globs->last_level    = globs->ccd_recurs_level;
    }

    /*
     * calculate the index into the ieTable for this element
     */
    ieTableIdx = (int)(e_ref - globs->iei_ctx[globs->ccd_recurs_level].melemStart);

    if (globs->TagPending)
    {
      /*
       * if we previously read a t value and does not processed it
       * get this pending tag.
       */
      t = (ULONG) globs->PendingTag;
      globs->TagPending = FALSE;
    }
    else
    {
      /*
       * read the information element identifier out of the bitstream.
       * If the first bit (MSBit) of the t-component is set, it is
       * a Tag of a TYPE1 or TYPE2 element.
       */
      
      t = (ULONG) bf_decodeByteNumber (8, globs);



      if (!asn1 AND !non_std_tag AND (t & 0x80) EQ 0x80 AND (t & 0xA0) NEQ 0xA0)
      {
        ULONG Tag4 = t & 0xf0;        
        /*
         * MSBit is set. We have to check if the Tag value can
         * be found as a 4 bit or 8 bit value in the IEI-table.
         */
        if (cdc_search_table (ieTableIdx, Tag4, limitSearch, &nonTagged, globs) NEQ -127) 
        {
          /*
           * Tag found as a 4 bit value. Decrement the readpointer
           * of the bitstream by 4, because we have read out 4 bits
           * to much.
           */
          bf_setBitpos (globs->bitpos-4, globs);
          t = Tag4;
          len_t =4;
#ifdef DEBUG_CCD
          TRACE_CCD (globs, "4 bit Tag decrementing bitpos by 4 to %d", globs->bitpos);
#endif
        }
      }
    }

#ifdef DEBUG_CCD
    TRACE_CCD (globs, "reading t = 0x%X", t);
#endif

    if (melem[e_ref].codingType EQ CCDTYPE_GSM5_TLV)
    {
      limitSearch = TRUE;  
      CR = (UBYTE) (((t & 0x80) EQ 0x80) ? TRUE : FALSE);
      t &= 0x7f;
    }


    if (asn1 AND t EQ 0x00)
    {
      /*
       * This is for ASN1 element coding the special
       * End Of Component Tag (EOC). The following length must be zero.
       */
      bf_setBitpos (globs->bitpos-8, globs);

#ifdef DEBUG_CCD
      TRACE_CCD (globs, "ASN1 End of Component found belongs to higher TLV");
      TRACE_CCD (globs, "leaving this level and decrementing bitpos by 8 to %d", globs->bitpos);
#endif

      return END_OF_COMPOSITION; /* skip the remaining elements in this level */
    } /* asn1 and EOC */
    else
    {
      if ((IdxOffset = (SHORT) cdc_search_table (ieTableIdx, t, limitSearch, &nonTagged, globs)) == -127)
      {
        /*
         * t (iei) not defined in this composition (msg or submsg)
         */
        if (asn1)
        {
          if (melem[mcomp[c_ref].componentRef + mcomp[c_ref].numOfComponents -1].codingType == CCDTYPE_GSM5_V)
          {
            /* Restore the old bitposition (before the 'TAG') and return
             * IdxOffset to jump to last element of the composition.
             * The coding type of this elements is CCDTYPE_GSM5_V
             */
            bf_setBitpos (globs->bitpos-8, globs);
            IdxOffset = (SHORT)(mcomp[c_ref].numOfComponents - ieTableIdx - 1);
            return (IdxOffset);
          }

          /*
           * for recursive ASN.1 structs it is possible that the foreign
           * tag belongs to a upper level composition of element.
           *
           * 
           * Restore the old bitposition (before the TAG) and return
           * END_OF_COMPOSITION to leave this composition level
           */
          bf_setBitpos (globs->bitpos-8, globs);
#ifdef DEBUG_CCD
          TRACE_CCD (globs, "Unknown Tag. It may belong to upper ASN.1 comp -> dec. bitpos by 8 to %d", globs->bitpos);
#endif

          return END_OF_COMPOSITION; /* skip the remaining elements in this level */
        }
        else if (nonTagged)
        {
          U16 actBitpos;
          actBitpos = globs->bitpos-8;

          if (melem[mcomp[c_ref].componentRef + mcomp[c_ref].numOfComponents -1].codingType == CCDTYPE_GSM5_V &&
              melem[e_ref].codingType EQ CCDTYPE_GSM5_TLV)
          {
#if defined (CCD_TEST)
            currentTag = (T_UNKNOWN_TAG *) malloc(sizeof(T_UNKNOWN_TAG));
#else
            currentTag = (T_UNKNOWN_TAG *) D_ALLOC(sizeof(T_UNKNOWN_TAG));
#endif
            first = currentTag;
            currentTag->bitpos = globs->bitpos-8;
            currentTag->errCode = ERR_NO_MORE_ERROR;
            currentTag->next = NULL;

            /* unknown GSM Type TLV -> skip 'l' bytes */
            /* at least 8 bits must remain for following expeceted tagged element */
            while (globs->maxBitpos - 8 - globs->bitpos >= 8)
            {
              currentTag->bitpos = globs->bitpos-8;
              currentTag->tag    = (UBYTE) t;

              /* 
               * Expecting a CCDTYPE_GSM5_TLV type we get an unknown tag with MSB set.
               * Store bitpos and t for the application (SAT) for the handling of 
               * comprehension required elements.
               */

              if (CR)
              { // save (ERR_COMPREH_REQUIRED; globs->bitpos-len_t) 
                currentTag->errCode =  ERR_COMPREH_REQUIRED;
              }
              else 
              { // save (ERR_IE_NOT_EXPECTED; globs->bitpos-len_t) 
                currentTag->errCode =  ERR_IE_NOT_EXPECTED;
              }

              l = (ULONG) bf_decodeByteNumber (8, globs);
              bf_incBitpos ((l << 3) , globs);
              
              t = (ULONG) bf_decodeByteNumber (8, globs);

              limitSearch = TRUE;  
              CR = (UBYTE) (((t & 0x80) EQ 0x80) ? TRUE : FALSE);
              t &= 0x7f;

              if (cdc_search_table (ieTableIdx, t, limitSearch, &nonTagged, globs) != -127)
              {
                bf_setBitpos (globs->bitpos-8, globs);
                // set all ccd Errors
                do 
                {
                  currentTag = first;
                  ccd_setError (globs, currentTag->errCode,
                                CONTINUE,
                                (USHORT) currentTag->tag,
                                currentTag->bitpos,
                                (USHORT) -1);
                  first = currentTag->next;
#if defined (CCD_TEST)
                  free(currentTag);
#else                
                  D_FREE(currentTag);
#endif               
                }
                while (first != NULL );

                return 0;
              }
              else
              {                
#if defined (CCD_TEST)
                currentTag->next = (T_UNKNOWN_TAG *) malloc(sizeof(T_UNKNOWN_TAG));
#else                
                currentTag->next = (T_UNKNOWN_TAG *) D_ALLOC(sizeof(T_UNKNOWN_TAG));
#endif               
                currentTag = currentTag->next;
                currentTag->next = NULL;
              }
            }

            do
            {
              currentTag = first;
              first = currentTag->next;
#if defined (CCD_TEST)
              free(currentTag);
#else                
              D_FREE(currentTag);
#endif               
            }
            while (first != NULL );
          }

            /*
             * a non tagged element is possible in the message. If the tag 
             * can not be found, the tag may be the beginning of the non  tagged
             * element. E.g. rest octetts in sysinfo 4
             * 
             * Restore the old bitposition (before the TAG) and return 1 to 
             * go to the next element.
             */
          
          bf_setBitpos (actBitpos, globs);
#ifdef DEBUG_CCD
          TRACE_CCD (globs, "Unknown Tag but mand. IE possible -> dec. bitpos by 8 to %d", globs->bitpos);
#endif

          return 1;
        }


        /*
         * Otherwise look if it is a type 1,2 or 4 Element
         */
        if ((t & 0x80) EQ 0x80)
        {
          /* MSBit set -> GSM Type 1 or Type2 -> skip 1 byte */
          /* position already incremented by decoding the TAG value */
        }
        /* Just another reason for getting IdxOffset equal to 0. */
        else if (globs->ccd_recurs_level >= MAX_RECURSIONS_PER_MSG)
        {
          ccd_setError (globs, ERR_INTERNAL_ERROR, BREAK, (USHORT) -1);
        }
        else
        {
          /* 
           * Expecting a CCDTYPE_GSM5_TLV type we get an unknown tag with MSB set.
           * Store bitpos and t for the application (SAT) for the handling of 
           * comprehension required elements.
           */
          if (CR)
          {
            ccd_setError (globs, ERR_COMPREH_REQUIRED,
                          CONTINUE,
                          (USHORT) t,
                          (USHORT) globs->bitpos-len_t,
                          (USHORT) -1);
          }
          /* 
           * Expecting other types than CCDTYPE_GSM5_TLV we get an unknown tag with
           * comprehension required bits (5, 6, 7 and 8 of IEI according to GSM0407)
           * are set to zero.
           * Store bitpos and t for the application for the handling of comprehension
           * required elements.
           */
          else if ((t & 0x70) EQ 0 AND
                    melem[e_ref].codingType NEQ CCDTYPE_GSM5_TLV)
          {
            ccd_setError (globs, ERR_COMPREH_REQUIRED,
                          CONTINUE,
                          (USHORT) t,
                          (USHORT) globs->bitpos-len_t,
                          (USHORT) -1);
          }
          /* 
           * We get an unknown tag and any sort of comprehension required flag is set.
           * Store bitpos and t for the application
           */
          else 
          {
            ccd_setError (globs, ERR_IE_NOT_EXPECTED,
                          CONTINUE,
                          (USHORT) t,
                          (USHORT) globs->bitpos-len_t,
                          (USHORT) -1);
          }
          
          /* MSBit cleared -> GSM Type TLV -> skip 'l' bytes */
          if (globs->maxBitpos - globs->bitpos >= 8)
          {
            l = (ULONG) bf_decodeByteNumber (8, globs);
            bf_incBitpos ((l << 3) , globs);
          }
          else
          {
            ccd_recordFault (globs,
                             ERR_ELEM_LEN,
                             BREAK,
                             (USHORT) e_ref,
                             globs->pstruct + globs->pstructOffs);
          }
        }

        /*
         * return 0 -> that means try it again with this actual element
         * referenced by e_ref
         */
        return 0;
      } /* tag not found */
      else
      {
        T_IEI_TABLE *iei_tbl = &globs->iei_ctx[globs->ccd_recurs_level].iei_table[ieTableIdx];
        /*
         * element definition for this iei found
         */
        if (IdxOffset NEQ 0)
        {
          /*
           * found index differs from the actual index
           */
          globs->TagPending    = TRUE;
          globs->PendingTag    = (UBYTE) t;

          if (!asn1 AND IdxOffset < 0)
          {
            /*
             * found an element in wrong sequence
             * (for ASN1 elements the sequence order is not relevant)
             */
            ccd_setError (globs, ERR_IE_SEQUENCE,
                          (UBYTE) ((asn1) ? BREAK : CONTINUE),
                          (USHORT) t,
                          (USHORT) globs->bitpos-len_t,
                          (USHORT) -1);

            globs->SequenceError = TRUE;
          }
          if (globs->SequenceError)
          {
            globs->RefBeforeError = (USHORT) e_ref;
          }
          if (asn1) 
          {
            globs->iei_ctx[globs->ccd_recurs_level].countSkipped += IdxOffset;
          }
          /*
           * skip to the found element
           */
          return (IdxOffset);
        }
        else
        {
          globs->iei_ctx[globs->ccd_recurs_level].melemLast = (USHORT) e_ref;

          if (iei_tbl->act_amount == 0)
          {
            /*
             * first apearance of this iei
             * calculate the upper and lower boundaries and the
             * facility of multiple appearance of this tagged element
             * in the bitstream.
             */

            /*
             * The element is repeatable. There are three kinds of 
             * repeat definitions valid for standard elements:
             *  [5]    - The element is repeated 5 times.
             *  [0..5] - The element is repeated 0 to 5 times.
             *  [a..5] - The element is repeated "the value of a" times.
             *
             * For tagged elements the following processing is defined:
             *
             *  [5]    - The t-Component is decoded
             *           (maybe the l-Component too (if defined one).
             *           After this the V-component of the element
             *           is decoded 5 times.
             *
             *  [0..5] - The t- and maybe the l-Component are decoded.
             *           After this one V-Component is decoded and it
             *           is stored as an array entry into
             *           the target C-Structure. In this case the
             *           parameter ieIndex gives the index into
             *           this array, where the element has to
             *           be written into.
             *
             *  [a..5] - The t- and maybe the l-Component are decoded.            
             *           After this one V-Component is decoded
             *           "a" times and is stored into the C-Structure
             *           as an array.
             *           
             */
            switch (melem[e_ref+IdxOffset].repType)
            {
              case 'i':
                /* 
                 * multiapearance of this element. The V-component is 
                 * repeated once
                 */
                is_variable = ccd_calculateRep (e_ref+IdxOffset,
                                  &repeat,
                                  &max_rep,
                                  globs);

                iei_tbl->max_amount = (UBYTE) max_rep;
                iei_tbl->multiple   = TRUE;
                break;

              case 'v':
              case 'b':
              default:
                /* 
                 * if this element is repeatable, and the number of
                 * repeats depends on another element, the valid amount
                 * of this element is 1 and the V-component will be
                 * repeated.
                 */
                iei_tbl->max_amount = 1;
                iei_tbl->multiple   = FALSE;
                break;
            }
            iei_tbl->act_amount = 1;
          }

          if (iei_tbl->act_amount <= iei_tbl->max_amount)
          {
            /*
             * process only the max_amount appearances of each element.
             * All additional IEs are ignored.
             */
            ie_amount = (ULONG)(iei_tbl->act_amount)++;
          }
          else
          {
            if (asn1)
            {
              /* For ASN1 elements the sequence order is not relevant.
               * It is possible that the tag belongs to an upper level 
               * composition of elements. 
               * Restore the old bitposition (before the TAG) and return
               * END_OF_COMPOSITION to leave this composition level
               */
              bf_setBitpos (globs->bitpos-8, globs);
#ifdef DEBUG_CCD
          TRACE_CCD (globs, "Tag may belong to upper ASN.1 comp -> dec. bitpos by 8 to %d", globs->bitpos);
#endif

              return END_OF_COMPOSITION; /* skip the remaining elements in this level */
            }
            else
            {
              ie_amount = 0;
              ccd_setError (globs, ERR_MAX_IE_EXCEED,
                            CONTINUE,
                            (USHORT) t,
                            (USHORT) globs->bitpos-len_t,
                            (USHORT) -1);
            }
          }

          /*
           * The t-component matches with the defined identifier for
           * the actual element definition (e_ref).
           */

          if (globs->SequenceError)
          {
            globs->SequenceError = FALSE;

            if (asn1)
            {
              /* For ASN1 elements the sequence order is not relevant.
               * It is possible that the tag belongs to an upper level 
               * composition of elements. 
               * Restore the old bitposition (before the TAG) and return
               * END_OF_COMPOSITION to leave this composition level
               */
              bf_setBitpos (globs->bitpos-8, globs);
#ifdef DEBUG_CCD
          TRACE_CCD (globs, "Tag may belong to upper ASN.1 comp -> dec. bitpos by 8 to %d", globs->bitpos);
#endif

              return END_OF_COMPOSITION; /* skip the remaining elements in this level */
            }
            else
            {
              /* found an element in wrong sequence */
              
              cdc_skipElem (e_ref, (tlv_inf->gotLen ? len_l:0), globs);
              return (SHORT)(globs->RefBeforeError - e_ref);
            }
          }

          /* 
           * if this element is conditional, check the condition
           */
          if (calcidx[cix_ref].numCondCalcs NEQ 0
            AND ! ccd_conditionOK (e_ref, globs))
          {
            /*
             * if the condition for this element is not valid
             * but this element appears in the message, generate 
             * an error and skip the element
             */
            ccd_setError (globs, ERR_IE_NOT_EXPECTED,
                          CONTINUE,
                          (USHORT) t,
                          (USHORT) globs->bitpos-len_t,
                          (USHORT) -1);

            cdc_skipElem (e_ref, (tlv_inf->gotLen ? len_l:0), globs);

            return 0;
          }

          /*
           * check for a valid index
           */
          if (ie_amount EQ 0)
          {
            /*
             * The max number of repeats are reached
             * In this case we must skip this element.
             */
            cdc_skipElem (e_ref, (tlv_inf->gotLen ? len_l:0), globs);

            return 0;
          }

     
          if (iei_tbl->multiple)
          {
            if (melem[e_ref].elemType NEQ 'S')
            {
              /*
               * Element is not a SPARE 
               * Setup the offset into the C-structure for this element
               */
              globs->pstructOffs = melem[e_ref].structOffs;
            }
            ret = cdc_tagged_LV_decode (e_ref, ie_amount,
                                       (tlv_inf->gotLen ? len_l:0), globs);
          }
          else
          {
            if (melem[e_ref].elemType NEQ 'S')
            { /*
               * Element is not a SPARE 
               * Setup the offset into the C-structure for this element
               */
              globs->pstructOffs = melem[e_ref].structOffs;
            }
            ret = cdc_normal_LV_decode (e_ref, 
                                       (tlv_inf->gotLen ? len_l:0), globs);
          }
          globs->SeekTLVExt = TRUE;
          iei_tbl->exhausted  = TRUE;

          if (ret)
            return END_OF_COMPOSITION;

          /*
           * if more then one IE of this type are allowed, a ret of 0
           * indicates the calling function (ccd_decodeComposition())
           * to leave the pointer to the actual element definition on
           * this element. If the value of ret is greater then 0 the
           * calling function will increment the pointer by the value
           * of ret.
           * cdc_T_decode() has found the expected element definition.
           * Go to the next definition or stay at this definition,
           * if the occurance of this element is more than one. 
           */
          if (iei_tbl->act_amount > iei_tbl->max_amount)
          {
            iei_tbl->act_amount = 0;
          }
          if (iei_tbl->max_amount > 1)
          {
            return (0);
          }
          else 
          {
            if (globs->iei_ctx[globs->ccd_recurs_level].countSkipped)
            {
              ret = (-1) * (globs->iei_ctx[globs->ccd_recurs_level].countSkipped);
              (globs->iei_ctx[globs->ccd_recurs_level].countSkipped) = 0;
              return (ret);
            }
            else 
            {
              return (1);
            }
          }
        } /* IdxOffset == 0 */
      } /* tag found */
    }  /* no asn1, no EOC */
  } /* got tag */
  else
  {
    /* 
     * element has no t-component, process the l- and V-components
     */
    if (melem[e_ref].elemType NEQ 'S')
    { /*
       * Element is not a SPARE 
       * Setup the offset into the C-structure for this element
       */
      globs->pstructOffs = melem[e_ref].structOffs;
    }
    ret = cdc_normal_LV_decode (e_ref, len_l, globs) ? END_OF_COMPOSITION : 1;
    globs->SeekTLVExt = TRUE;
    return ret;
  }
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_tlv_encode      |
+--------------------------------------------------------------------+

  PURPOSE : if T_len > 0 this function encodes the T-Component of
            this element. If L_len > 0 it encodes the number
            of bytes uses for this element. After all the function
            encodes the V-component referenced by eRef from the
            C-Structure (globs->pstruct) at position globs->pstructOffs
            into the bitstream.

*/

void cdc_tlv_encode  (const ULONG  e_ref,
                            UBYTE  lenT,
                            UBYTE  lenL,
                            T_CCD_Globs *globs)
{
  ULONG  posL=0, t_repeat, v_repeat, repeat;
  ULONG  cSize, startOffset=0;
  BOOL   multAppear;
  U8     *old_pstruct = NULL;
  ULONG  i;
  ULONG  cix_ref, num_prolog_steps, prolog_step_ref;

  cix_ref = melem[e_ref].calcIdxRef;
  num_prolog_steps = calcidx[cix_ref].numPrologSteps;
  prolog_step_ref  = calcidx[cix_ref].prologStepRef;

  /*
   * If this element is conditional, check the condition.
   */
  if (calcidx[cix_ref].numCondCalcs NEQ 0
  AND ! ccd_conditionOK (e_ref, globs))
    return;

  /*
   * If this element have a defined Prolog,
   * we have to process it before decoding the bit stream.
   */
  if (num_prolog_steps)
  {
    ccd_performOperations (num_prolog_steps, prolog_step_ref, globs);
  }
  
  if (melem[e_ref].elemType NEQ 'S')
  {
    /*
     * Element is not a SPARE.
     * Setup the offset into the C-structure for this element.
     * In case of pointer types, the pstructOffs must be
     * the offset into the memory area pointed to. CCDGEN must
     * ensure this holds true.
     */
    globs->pstructOffs = melem[e_ref].structOffs;

    if ( ! cdc_isPresent(e_ref, globs) )
      return;

    if (melem[e_ref].repType EQ 'v' OR melem[e_ref].repType EQ 'i')
    {
      /*
       * for variable sized elements read the amount
       * of repeats out of the C-Structure (c_xxx).
       * If the number of repeats given by the C-Structure 
       * exceeds the allowed value (maxRepeat) CCD gives a warning!
       */
      if (melem[e_ref].maxRepeat > 255)
      {
        ULONG count = (ULONG) (* (USHORT *)(globs->pstruct + globs->pstructOffs++));
        repeat = MINIMUM (count, (ULONG) melem[e_ref].maxRepeat);
        if (repeat < count) 
          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, 
                           (USHORT) e_ref, globs->pstruct + globs->pstructOffs);
      }
      else
      {
        repeat     = (ULONG) MINIMUM (globs->pstruct[globs->pstructOffs],
                                      melem[e_ref].maxRepeat);
        if ( repeat < (ULONG) (globs->pstruct[globs->pstructOffs]) )
          ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, (USHORT) e_ref, 
                           globs->pstruct + globs->pstructOffs);
      }
                         
      globs->pstructOffs++;

      multAppear = (melem[e_ref].repType EQ 'i');
    }
    else
    {
      /*
       * Field of constant length: repType EQ 'c'  
       * or bit-field allocated with 
       * given maximum length: repType EQ 'b' (often cType='X')
       */
      repeat = (ULONG)((melem[e_ref].repType EQ 'c' 
                         OR melem[e_ref].repType EQ 'b')
                        ? melem[e_ref].maxRepeat 
                        : 1 );
      multAppear = FALSE;
    }

    /*
     * Perform pointer dereference for pointer types.
     * Also, check optionality for these types.
     */
#ifdef DYNAMIC_ARRAYS
    if ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR
	(melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F')) 
    {
      U8 *deref_pstruct;

      /* Get pointer value */
      deref_pstruct = *(U8 **)(globs->pstruct + globs->pstructOffs);

      /*
       * Strictly speaking the 'D' to 'F' types should not need this
       * check (should have returned after the optionality check above),
       * but it will catch stray NULL pointers (or uninitialized
       * valid flags)
      */
      if (ccd_check_pointer(deref_pstruct) != ccdOK)
      {
        ccd_recordFault (globs, ERR_INVALID_PTR, BREAK, (USHORT) e_ref, 
                         &globs->pstruct[globs->pstructOffs]);
        return;
      }

      /*
       * Pointer not NULL;
       * 1. Save old globs->pstruct and assign pointer to globs->pstruct
       *    as new base.
       * 2. Set pstructOffs to 0 (zero) as the next offset will start
       *    in the new memory area.
       */
      old_pstruct        = globs->pstruct;
      globs->pstruct     = deref_pstruct;
      globs->pstructOffs = 0;
    }
#endif

    /*
     * 20010621 MVJ: Dynamic array addition.
     * Types 'R' and 'F' point to base types (just as type 'V') and
     * read sizes from the same table.
     */
    cSize = (ULONG)((melem[e_ref].elemType EQ 'V'
#ifdef DYNAMIC_ARRAYS
                      OR melem[e_ref].elemType EQ 'R'
                      OR melem[e_ref].elemType EQ 'F'
#endif
                     ) ? mvar[melem[e_ref].elemRef].cSize
                     : mcomp[melem[e_ref].elemRef].cSize
                     );

    startOffset = globs->pstructOffs;
  }
  else
  {
    repeat = (ULONG)((melem[e_ref].repType EQ 'c') 
                      ? melem[e_ref].maxRepeat
                      : 1);

    multAppear = FALSE;

    cSize = 0;
  }

  if (multAppear AND lenT)
  {
    /*
     * multiple appearance of the repeated element is coded as 
     * TLV0 TLV1 TLV2 ....
     */
    t_repeat = repeat;
    v_repeat = 1;
  }
  else
  {
    t_repeat = 1;
    v_repeat = repeat;
  }

  /*
   * single appearance of the repeated element is coded as 
   * TLV0V1V2V3 ....
   */

  for (i=0; i < t_repeat; i++)
  {
    if (lenT)
    {
      /*
       * encode the T-component
       */
      bf_codeByteNumber (lenT, (UBYTE) melem[e_ref].ident, globs);
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "encoding %d bits T-value (%x)", lenT, melem[e_ref].ident);
#endif
    }

    /*
     * if lenL > 0 remember the position of the L-component, because
     * we know it after encoding the entire element. for GSM5TLV elements
     * it could be necessary to use 2 bytes for the length information.
     */
    if (lenL)
    {
      posL = (ULONG) globs->bitpos;
      bf_incBitpos (lenL, globs);
#ifdef DEBUG_CCD
      TRACE_CCD (globs, "skipping %d bits for L-value at byte %d.%d", lenL, globs->bytepos, globs->byteoffs);
#endif
    }

    if (cSize)
    {
      /*
       * calculate the offset if it is not a spare
       */
      globs->pstructOffs = (ULONG)(startOffset + (i * cSize));
    }

    /*
     * Encode the value. Keep caution with BER encoding of ASN1 integers.
     * All other types can be encoded by a generic function.
     */
    if (melem[e_ref].codingType EQ CCDTYPE_GSM1_ASN
        AND 
        melem[e_ref].elemType EQ 'V'
        AND melem[e_ref].repType EQ ' '
       )
    {
#ifdef DEBUG_CCD
#ifdef CCD_SYMBOLS
      TRACE_CCD (globs, "BER encoding of ASN.1 integer %s",
               ccddata_get_alias((USHORT) e_ref, 1));
#else
      TRACE_CCD (globs, "BER encoding of ASN.1 integer; e_ref= %d", melem[e_ref].elemRef);
#endif
#endif

      switch (mvar[melem[e_ref].elemRef].cType)
      {
        case 'B': bf_writeBits (8, globs);
          break;
        case 'S':
        {
          if (*(U16 *) (globs->pstruct+globs->pstructOffs) <= (U16)0xFF)
            bf_writeBits (8, globs);
          else
            bf_writeBits (16, globs);
        }
          break;
        case 'L': 
        {          
          U32 tmpVal= *(U32 *) (globs->pstruct+globs->pstructOffs);
        
          if ( tmpVal <= (U32)0xFF)
            bf_writeBits (8, globs);
          else if ( tmpVal <= (U32)0xFFFF)
            bf_writeBits (16, globs);
          else if ( tmpVal <= (U32)0xFFFFFF)
            bf_writeBits (24, globs);
          else
            bf_writeBits (32, globs);
        }
          break;
        case 'X': 
        {   
          U16 ValLen= *(U16 *) (globs->pstruct+globs->pstructOffs);
          
          if ( mvar[melem[e_ref].elemRef].bSize >= ValLen)
            bf_writeBitChunk (ValLen, globs);
          else
          {
#ifdef DEBUG_CCD
            TRACE_CCD (globs, "value length (%d) exceeds defined bSize!", ValLen);
#endif
          }

        }
          break;
      }
    }
    else
    {
      cdc_encodeElemvalue (e_ref, v_repeat, globs);
    }

    /*
     * calculate the bitlen if it is an TLV element and write the
     * L-value.
     */

    if (lenL)
    {
      switch (melem[e_ref].codingType)
      {
        case CCDTYPE_GSM5_TLV:
        {
          USHORT L = (((USHORT)((globs->bitpos - posL)-lenL)+7) >> 3);


#ifdef DEBUG_CCD
          TRACE_CCD (globs, "recoding the 8 bit L-value (%d)", L);
#endif

          if (L > 127)
          {
            /*
             * if the length is > 127 we code the first byte to
             * 0x81, shift the whole stuff rightwise by 8 and 
             * encode the length in the next byte (16 bits for L)
             */
            bf_rShift8Bit ((USHORT) (posL+8), (USHORT) (L<<3), globs);
            bf_incBitpos (8, globs);
            bf_recodeByteNumber ((USHORT) posL, lenL, (UBYTE) 0x81, globs);
            bf_recodeByteNumber ((USHORT) (posL+8), lenL, (UBYTE) L, globs);
            /*
             * set the bitpos to a 8 bit aligned position
             * corresponding the L value
             */
            bf_setBitpos (posL+(L*8)+16, globs);
          }
          else
          {
            bf_recodeByteNumber ((USHORT) posL, lenL, (UBYTE) L, globs);
            /*
             * set the bitpos to a 8 bit aligned position
             * corresponding the L value
             */
            bf_setBitpos (posL+(L*8)+8, globs);
          }
          break;
        }

        case CCDTYPE_GSM6_TLV:
        {
          USHORT L = ((USHORT)(((globs->bitpos - posL)-lenL)+7) >> 3);

#ifdef DEBUG_CCD
          TRACE_CCD (globs, "recoding the 16 bit L-value (%d)", L);
#endif
          bf_recodeShortNumber ((USHORT)posL, lenL, L, globs);
          /*
           * set the bitpos to a 8 bit aligned position
           * corresponding the L value
           */
          bf_setBitpos (posL+(L*8)+16, globs);
          break;
        }

        case CCDTYPE_GSM7_LV:
        {
          USHORT L = (USHORT) ((globs->bitpos - posL)-lenL);

#ifdef DEBUG_CCD
          TRACE_CCD (globs, "recoding the 7 bit L-value (bitlength) (%d)", L);
#endif
          bf_recodeShortNumber ((USHORT)posL, lenL, L, globs);

          bf_setBitpos (posL+L+7, globs);
          break;
        }

        default:
        {
          USHORT L = ((USHORT)(((globs->bitpos - posL)-lenL)+7) >> 3);

#ifdef DEBUG_CCD
          TRACE_CCD (globs, "recoding the 8 bit L-value (%d)", L);
#endif
          bf_recodeByteNumber ((USHORT)posL, lenL, (UBYTE) L, globs);
          /*
           * Set the bitpos to a 8 bit aligned position
           * corresponding the L value
           */
          bf_setBitpos (posL+(L*8)+8, globs);
          break;
        }
      }
    }
  }

  /*
   * Restore globs->pstruct if overwritten by pointer dereference.
   */
  if (old_pstruct)
    globs->pstruct = old_pstruct;
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)                 MODULE  : CDC_COM             |
| STATE   : code                       ROUTINE : cdc_GSM_start       |
+--------------------------------------------------------------------+

  PURPOSE : Initialize the GSM specific codec part for each msg. 

*/

void cdc_GSM_start (T_CCD_Globs *globs)
{
  globs->Swap1V_inProgress = FALSE;
  globs->last_level       = 255;
  cdc_init_ctx_table (globs);
}
#endif /* !RUN_FLASH */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : cdc_isPresent          |
+--------------------------------------------------------------------+

  PURPOSE : For optional elements check the valid-flag in the C-struct.
            Spare elements in PER do not have a corresponding valid flag.
            In case of Dynamic Arrays:
            Postpone optional check for non-code transparent pointer
            types ('P', 'Q', 'R').
            For these types, the optional flag is the pointer itself.
            These types cannot be checked yet, as the pointer may be
            preceeded by a counter octet, a union tag id octet etc.
*/
U16 cdc_isPresent (const ULONG e_ref, T_CCD_Globs *globs)
{
  if (melem[e_ref].optional)
  {
#ifdef DYNAMIC_ARRAYS
    if (melem[e_ref].elemType < 'P' OR melem[e_ref].elemType > 'R')
    {
      if(globs->pstruct[globs->pstructOffs++] == FALSE)
        return FALSE;
#ifdef DEBUG_CCD
      else if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
      {
        TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d",
                   e_ref);
      }
#endif
    }
    else
    { /*If elemType is P, Q or R - check the pointer value*/
      if(*(void**) &globs->pstruct[globs->pstructOffs] == NULL)
        return FALSE;
    }
#else
    if (globs->pstruct[globs->pstructOffs++] == FALSE)
      return FALSE;
#ifdef DEBUG_CCD
    else if (globs->pstruct [melem[e_ref].structOffs] != TRUE)
    {
      TRACE_CCD (globs, "Ambiguous value for valid flag!\n...assumed 1 for ccdID=%d",
                 e_ref);
    }
#endif
#endif
  }
  return TRUE;
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : is_pointer_type        |
+--------------------------------------------------------------------+

  PURPOSE : Return TRUE for pointer elements.

*/
BOOL is_pointer_type (const ULONG e_ref)
{
  return ((melem[e_ref].elemType >= 'P' AND melem[e_ref].elemType <= 'R') OR
	  (melem[e_ref].elemType >= 'D' AND melem[e_ref].elemType <= 'F'));
}
#endif /* !RUN_FLASH */

#ifndef RUN_FLASH
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : is_variable_type       |
+--------------------------------------------------------------------+

  PURPOSE : Return TRUE for elements with variable character.

*/
BOOL is_variable_type (const ULONG e_ref)
{
  return ((melem[e_ref].elemType == 'F') || ( melem[e_ref].elemType == 'R') ||
	  (melem[e_ref].elemType == 'V'));
}
#endif /* !RUN_FLASH */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : PER_CommonBegin        |
+--------------------------------------------------------------------+

  PURPOSE : Common settings done by most of the encoding or decoding 
            functions for UNALIGNED PER (UMTS).
            It handles position of pointer to the C-structure, 
            valid flag for optional elements and length determinant 
            for array of elements.
*/
SHORT PER_CommonBegin (const ULONG e_ref, ULONG *max_rep, T_CCD_Globs *globs)
{
  /*
   * Set the offset in the C-structure on the value for this element
   */
  globs->pstructOffs = melem[e_ref].structOffs;

  /* For optional elements we have already set the valid flag in the
   * C-structure while processing ASN1_SEQ.
   */
  if ( ! cdc_isPresent(e_ref, globs) )
    return (SHORT)ccdError;
   
  switch (melem[e_ref].repType)
  {
    case ' ':
      /*
       * Element is not an array.
       */
      *max_rep = 1;
      break;
    case 'c':
    case 'C':
      /*
       * Read the size for an array of fixed length.
       */
      *max_rep = (ULONG) melem[e_ref].maxRepeat; 
      break;                
    case 'j':
    case 'J':
    {
      /*
       * Read the size for an array of variable length.
       * Read the value of the last encoded element. It is the length
       * indicator.
       * Hint 1: globs->pstruct[melem[e_ref-1].structOffs is 0, since
       *   fields of variable length are projected on a COMP made of an
       *   ASN1_INTEGER for the lenght indicator and the field elements
       *   (sequences, integers, octets or bits). 
       * Hint 2: The current version of UMTS does not use length
       *   indicators larger than 64K. Hence the use of USHORT for repeat.
       */
      switch (mvar[melem[e_ref-1].elemRef].cType)
      {
      case 'B':  *max_rep = (ULONG)  globs->pstruct[melem[e_ref-1].structOffs];
      	         break;
      case 'S':  *max_rep = (ULONG) *(USHORT *) (globs->pstruct+melem[e_ref-1].structOffs);
	               break;
      default:   *max_rep = 0;
	               break;
      }
      break;
    }
    default:
      ccd_recordFault (globs, ERR_DEFECT_CCDDATA, BREAK, (USHORT) e_ref,
                     globs->pstruct + globs->pstructOffs);
      break;
  }

  /*
   * There is nothing to be encoded. 
   */
  if (*max_rep EQ 0)
  {
    return (SHORT)ccdError;
  }
  /* 
   * Check the validity of the lenght information.
   */
  else if (melem[e_ref].maxRepeat AND *max_rep > melem[e_ref].maxRepeat)
  {
    ccd_recordFault (globs, ERR_MAX_REPEAT, CONTINUE, (USHORT) e_ref,
                     globs->pstruct + globs->pstructOffs);
  }

  return (SHORT)ccdOK;
}
#endif /* !RUN_INT_RAM */


#ifdef DYNAMIC_ARRAYS
#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : PER_allocmem           |
+--------------------------------------------------------------------+

  PURPOSE : Allocate memory for pointer types (dynamic array addition)
            Returns address of freshly allocated memory
            or ccdError in case no memory is available.
*/
U8 *PER_allocmem(const ULONG e_ref, ULONG repeat, T_CCD_Globs *globs)
{
  /*
   * Check for pointer types; allocate memory if necessary.
   */
  if ( is_pointer_type(e_ref) ) {
    ULONG   cSize;
    U8     *addr;

    /*
     * Find size to allocate.
     * Read from mcomp or mvar according to type.
     */
    cSize = (ULONG)((melem[e_ref].elemType EQ 'V' OR
		     melem[e_ref].elemType EQ 'R'
		     OR melem[e_ref].elemType EQ 'F')
		    ? mvar[melem[e_ref].elemRef].cSize
		    : mcomp[melem[e_ref].elemRef].cSize
		    );

#ifdef DEBUG_CCD
    TRACE_CCD (globs, "PER_allocmem(): alloc%5d x%5d bytes (type '%c'); "
	       "elem%5d ('%s')",
	       repeat, cSize, melem[e_ref].elemType, e_ref,
#ifdef CCD_SYMBOLS
	       mcomp[melem[e_ref].elemRef].name
#else
	       ""
#endif
	       );
#endif
    /*
     * Allocate additional memory - append to existing mem chain
     */

    cSize *= repeat;
    addr = (U8 *)DP_ALLOC( cSize, globs->alloc_head, DP_NO_FRAME_GUESS);

    /* If no memory, log error and return immediately */
    if (addr EQ NULL) {
      ccd_setError (globs, ERR_NO_MEM,
                    BREAK,
                    (USHORT) -1);
      return (U8 *)ccdError;
    }
    else
      memset (addr, 0, (size_t)cSize);
    return addr;
  }
  return (U8 *)ccdError;
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : PER_allocmem_and_update|
+--------------------------------------------------------------------+

  PURPOSE : Allocate memory for pointer types (dynamic array addition)
            Updates global variables after allocation
            (globs->pstruct and globs->pstructOffs).
            Assumes that these global variables are saved by the
            calling function.
            Returns ccdOK or ccdError in case no memory is available.
*/
USHORT PER_allocmem_and_update(const ULONG e_ref, ULONG repeat, T_CCD_Globs *globs)
{
  U8    *addr;

  /* Allocate memory */
  addr = PER_allocmem(e_ref, repeat, globs);

  /* No memory ? */
  if ( addr != (U8 *)ccdError ) {
    /*
     * Memory allocated;
     * 1. Store pointer to freshly allocated memory area in structure
     * 2. Initialize pstruct to point to the freshly allocated memory area.
     * 3. Initialize pstructOffs to 0 to start decoding at offset 0
     *    in the new memory area.
     * Assumes that globs->pstruct is saved in the calling function.
     */
    *(U8 **)(globs->pstruct + globs->pstructOffs) = addr;
    globs->pstruct     = addr;
    globs->pstructOffs = 0;
    return ccdOK;
  } else {
    /* No memory - Return error */
    return ccdError;
  }
}
#endif /* !RUN_INT_RAM */
#endif

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code       ROUTINE : Read_NormallySmallNonNegativeWholeNr|
+--------------------------------------------------------------------+

  PURPOSE : Read a normally small non-negative whole number as defined
            by ASN.1 PER. Function is used to read elements such as:
			a) bit-map field of SEQUENCE extensions,
			b) index of CHOICE extension or
			c) extension value of extensible INTEGER or ENUMERATED.
*/
U32 Read_NormallySmallNonNegativeWholeNr (T_CCD_Globs *globs)
{
  U32 value_length=0;

  /* Read the first bit. If set to 0 it means the value is encoded
   * in the following five bits. Else read a normally small ...nr.
   */
  if (bf_readBit (globs) EQ 0)
  {
    return ((U32) bf_getBits (6, globs));
  }
  else 
  {
    /*
     * Do not handle the theoretical case that value length 
     * needs more than 63 bits.
     */
    bf_incBitpos (1, globs);

    /* 
     * Read the value length first. 
     * Then use the length to read the value.
     */
    value_length = (U32) bf_getBits (6, globs);
    return ((U32) bf_getBits (value_length, globs));
  }
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code      ROUTINE : Write_NormallySmallNonNegativeWholeNr|
+--------------------------------------------------------------------+

  PURPOSE : Write a normally small non-negative whole number as defined
            by ASN.1 PER. Function is used to encode elements such as:
			a) bit-map field of SEQUENCE extensions,
			b) index of CHOICE extension or
			c) extension value of extensible INTEGER or ENUMERATED.
*/
void Write_NormallySmallNonNegativeWholeNr (U32 Value, T_CCD_Globs *globs)
{
  /* For small numbers write 0 in the first bit. 
   * Then encode that number in the succeeding five bits.
   */
  if (Value < 64)
  {
  	bf_writeBit (0, globs);
	  bf_writeVal (Value, 6, globs);
  }
  /*
   * Encode the number under the assumption that its length is 
   * given by less than 63 bits. Hence encode also the length as a 
   * normally small...
   */
  else 
  {
	  /* Set flag bits:
	   * 1 means "length determinant encoded before the value itself"
	   * 0 means "length determinant encoded only in five bits"
	   */
	  bf_writeVal (2, 2, globs);
	  bf_writeVal (bitSize[Value], 5, globs);

	  /* Encode the number itself */
	  bf_writeVal (Value, bitSize[Value], globs);
  }

  return;
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : Read_OpenTpye_Length   |
+--------------------------------------------------------------------+

  PURPOSE : Read length of an ASN.1 open type.
            Open types are normally found in encoding of 
            parametrized information objects and extension types.
*/
U32 Read_OpenTpye_Length (T_CCD_Globs *globs)
{
  U32 Value;

  /* 
   * Flag bit is 0 for "Value < 128" which means
   * "encoding fits in the current octet"
   */
  if (bf_readBit (globs) EQ 0)
  {
	  Value = bf_getBits (7, globs);
  }
  /* 
   * Flag bits are 10 for 128 "< Value < 16K".
   * 1 means "encoding does not fit in the current octet".
   * 0 means "encoding needs only one further octet".
   */
  else if (bf_readBit (globs) EQ 0)
  {
  	Value = bf_getBits (14, globs);
  } 
  /* Currently no support for bigger values is required. */
  else 
  {
    /* force error detection */
    Value = 0;
  }

  return Value;
}
#endif /* !RUN_INT_RAM */

#ifndef RUN_INT_RAM
/*
+--------------------------------------------------------------------+
| PROJECT : CCD (6144)              MODULE  : CDC_COM                |
| STATE   : code                    ROUTINE : Write_OpenTpye_Length  |
+--------------------------------------------------------------------+

  PURPOSE : Write length of an ASN.1 open type.
            Open types are normally found in encoding of 
            parametrized information objects and extension types.
*/
void Write_OpenTpye_Length (U32 Value, T_CCD_Globs *globs)
{

  if (Value < 128)
  {
	  bf_writeVal (Value, 8, globs);
  }
  else if (Value < 0x8000)
  {
	  /* Set flag bits:
	   * 1 means "encoding does not fit in the current octet"
	   * 0 means "encoding needs only one further octet"
	   */
	  bf_writeVal (2, 2, globs);
	  bf_writeVal (Value, 14, globs);
  } 
  /* Currently no support for bigger values is required. */
  else 
  {}

  return;
}
#endif /* !RUN_INT_RAM */