Windows-Server-2003/sdktools/asn1/asn1c/ber.c

788 lines
21 KiB
C
Raw Permalink Normal View History

2024-08-04 01:28:15 +02:00
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
void ExamineBERType(AssignmentList_t ass, Type_t *type, char *ideref);
void ExamineBERType_Boolean(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_Integer(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_Enumerated(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_Real(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_BitString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_OctetString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_UTF8String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_Null(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_EmbeddedPdv(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_External(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_ObjectIdentifier(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_BMPString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_GeneralString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_GraphicString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_IA5String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_ISO646String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_NumericString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_PrintableString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_TeletexString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_T61String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_UniversalString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_VideotexString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_VisibleString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_UnrestrictedString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_GeneralizedTime(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_UTCTime(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_ObjectDescriptor(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_Open(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_SequenceSet(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_SequenceSetOf(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_Choice(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_InstanceOf(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
void ExamineBERType_Reference(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info);
/* examine all types and extract informations needed for BER encoding */
void
ExamineBER(AssignmentList_t ass)
{
Assignment_t *a;
/* examine all assignments */
for (a = ass; a; a = a->Next) {
/* examine types */
switch (a->Type) {
case eAssignment_Type:
ExamineBERType(ass, a->U.Type.Type, GetName(a));
break;
}
}
}
/* extract some type informations needed for BER encoding */
void
ExamineBERType(AssignmentList_t ass, Type_t *type, char *ideref)
{
BERTypeInfo_t *info;
info = &type->BERTypeInfo;
info->pPrivateDirectives = &type->PrivateDirectives;
/* get tags to en-/decode */
if (IsReferenceType(type) && IsStructuredType(GetType(ass, type))) {
info->Tags = type->Tags;
} else {
info->Tags = type->AllTags;
}
/* get the type to be examined */
if (IsReferenceType(type) && !IsStructuredType(GetType(ass, type)))
type = GetType(ass, type);
/* initialize the BER informations */
info->Identifier = ideref;
info->Rules = type->Rules;
info->Flags = type->Flags;
info->NOctets = 0;
info->SubIdentifier = NULL;
info->SubType = NULL;
info->Data = eBERSTIData_Null;
/* BER informations are type specific ... */
switch (type->Type) {
case eType_Boolean:
ExamineBERType_Boolean(ass, type, info);
break;
case eType_Integer:
ExamineBERType_Integer(ass, type, info);
break;
case eType_Enumerated:
ExamineBERType_Enumerated(ass, type, info);
break;
case eType_Real:
ExamineBERType_Real(ass, type, info);
break;
case eType_BitString:
ExamineBERType_BitString(ass, type, info);
break;
case eType_OctetString:
ExamineBERType_OctetString(ass, type, info);
break;
case eType_UTF8String:
ExamineBERType_UTF8String(ass, type, info);
break;
case eType_Null:
ExamineBERType_Null(ass, type, info);
break;
case eType_EmbeddedPdv:
ExamineBERType_EmbeddedPdv(ass, type, info);
break;
case eType_External:
ExamineBERType_External(ass, type, info);
break;
case eType_ObjectIdentifier:
ExamineBERType_ObjectIdentifier(ass, type, info);
break;
case eType_BMPString:
ExamineBERType_BMPString(ass, type, info);
break;
case eType_GeneralString:
ExamineBERType_GeneralString(ass, type, info);
break;
case eType_GraphicString:
ExamineBERType_GraphicString(ass, type, info);
break;
case eType_IA5String:
ExamineBERType_IA5String(ass, type, info);
break;
case eType_ISO646String:
ExamineBERType_ISO646String(ass, type, info);
break;
case eType_NumericString:
ExamineBERType_NumericString(ass, type, info);
break;
case eType_PrintableString:
ExamineBERType_PrintableString(ass, type, info);
break;
case eType_TeletexString:
ExamineBERType_TeletexString(ass, type, info);
break;
case eType_T61String:
ExamineBERType_T61String(ass, type, info);
break;
case eType_UniversalString:
ExamineBERType_UniversalString(ass, type, info);
break;
case eType_VideotexString:
ExamineBERType_VideotexString(ass, type, info);
break;
case eType_VisibleString:
ExamineBERType_VisibleString(ass, type, info);
break;
case eType_CharacterString:
ExamineBERType_UnrestrictedString(ass, type, info);
break;
case eType_GeneralizedTime:
ExamineBERType_GeneralizedTime(ass, type, info);
break;
case eType_UTCTime:
ExamineBERType_UTCTime(ass, type, info);
break;
case eType_ObjectDescriptor:
ExamineBERType_ObjectDescriptor(ass, type, info);
break;
case eType_Open:
ExamineBERType_Open(ass, type, info);
break;
case eType_Sequence:
case eType_Set:
ExamineBERType_SequenceSet(ass, type, info);
break;
case eType_SequenceOf:
case eType_SetOf:
ExamineBERType_SequenceSetOf(ass, type, info);
break;
case eType_Choice:
ExamineBERType_Choice(ass, type, info);
break;
case eType_InstanceOf:
ExamineBERType_InstanceOf(ass, type, info);
break;
case eType_RestrictedString:
MyAbort(); /* may never happen */
/*NOTREACHED*/
case eType_Selection:
MyAbort(); /* may never happen */
/*NOTREACHED*/
case eType_Undefined:
MyAbort(); /* may never happen */
/*NOTREACHED*/
case eType_Reference:
ExamineBERType_Reference(ass, type, info);
break;
case eType_FieldReference:
MyAbort(); /* may never happen */
/*NOTREACHED*/
}
}
/*
* Description of the fields of BERTypeInfo_t:
* info.
* Identifier complete name of the type
* Rules encoding directive rules
* Flags encoding flags
* NOctets size of string characters/integer type
* Data data type of value
* SubIdentifier complete name of the subtype
* SubType the subtype itself
* Tags tag list of the type
*
* NOTES:
* The encoding is mostly controlled by following arguments:
* - Data, the type: one of:
* eBERSTIData_Null, eBERSTIData_Boolean,
* eBERSTIData_Integer, eBERSTIData_Unsigned,
* eBERSTIData_Real, eBERSTIData_BitString, eBERSTIData_RZBBitString,
* eBERSTIData_OctetString, eBERSTIData_SequenceOf, eBERSTIData_SetOf,
* eBERSTIData_Sequence, eBERSTIData_Set, eBERSTIData_Choice,
* eBERSTIData_ObjectIdentifier, eBERSTIData_ObjectIdEncoded, eBERSTIData_String,
* eBERSTIData_ZeroString, eBERSTIData_Reference, eBERSTIData_External,
* eBERSTIData_EmbeddedPdv, eBERSTIData_UnrestrictedString
*
* Following arguments contain variable/function names in the generated
* code:
* - Identifier, the name of the current type
* - SubIdentifier, the name of the subtype
*
* Following values require additional arguments:
* - Data == eBERSTIData_Reference
* -> SubIdentifier, the name of the subtype
* -> SubType, the subtype itself
* - Data == eBERSTIData_*String
* -> NOctets, the size of the string characters
* - Data == eBERSTIData_Integer || Data == eBERSTIData_Unsigned ||
* Data == eBERSTIData_Boolean || Data == eBERSTIData_Choice
* -> NOctets, the size of the integer type
* - Data == eBERSTIData_SequenceOf || Data == eBERSTIData_SetOf
* -> SubIdentifier, the name of the subtype
* -> SubType, the subtype itself
* -> Rule, the encoding directive rules
*/
/*
* BOOLEAN:
*
* Data == eBERSTIData_Boolean
*
* Additional arguments:
*
* - Data == eBERSTIData_Integer || dat == eBERSTIData_Unsigned ||
* Data == eBERSTIData_Boolean || dat == eBERSTIData_Choice
* -> NOctets, the size of the integer type
*/
void
ExamineBERType_Boolean(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = eBERSTIData_Boolean;
info->NOctets = GetOctets(GetBooleanType());
}
/*
* INTEGER:
*
* Data == eBERSTIData_Integer ||
* Data == eBERSTIData_Unsigned
*
* Additional arguments:
*
* - Data == eBERSTIData_Integer || dat == eBERSTIData_Unsigned ||
* Data == eBERSTIData_Boolean || dat == eBERSTIData_Choice
* -> NOctets, the size of the integer type
*/
void
ExamineBERType_Integer(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
int32_t sign;
/* calculate NOctets and Data depending on the used C-Type */
info->NOctets = GetOctets(GetIntegerType(ass, type, &sign));
info->Data = sign > 0 ? eBERSTIData_Unsigned : eBERSTIData_Integer;
}
/*
* ENUMERATED:
*
* Data == eBERSTIData_Integer ||
* Data == eBERSTIData_Unsigned
*
* Additional arguments:
*
* - Data == eBERSTIData_Integer || dat == eBERSTIData_Unsigned ||
* Data == eBERSTIData_Boolean || dat == eBERSTIData_Choice
* -> NOctets, the size of the integer type
*/
void
ExamineBERType_Enumerated(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
int32_t sign;
/* calculate NOctets and Data depending on the used C-Type */
info->NOctets = GetOctets(GetEnumeratedType(ass, type, &sign));
info->Data = sign > 0 ? eBERSTIData_Unsigned : eBERSTIData_Integer;
}
/*
* REAL:
*
* Data == eBERSTIData_Real
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_Real(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->NOctets = GetOctets(GetRealType(type));
info->Data = eBERSTIData_Real;
}
/*
* BIT STRING:
*
* Data == eBERSTIData_BitString ||
* Data == eBERSTIData_RZBBitString
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_BitString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
/* set Data to RZBBitString/BitString */
if (type->U.BitString.NamedNumbers)
info->Data = eBERSTIData_RZBBitString;
else
info->Data = eBERSTIData_BitString;
}
/*
* OCTET STRING:
*
* Data == eBERSTIData_OctetString
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_OctetString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
/* set Data to OctetString */
info->Data = eBERSTIData_OctetString;
}
void
ExamineBERType_UTF8String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
/* set Data to UTF8String */
info->Data = eBERSTIData_UTF8String;
}
/*
* NULL:
*
* Data == eBERSTIData_Null
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_Null(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = eBERSTIData_Null;
}
/*
* EMBEDDED PDV:
*
* Data == eBERSTIData_EmbeddedPdv
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_EmbeddedPdv(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = eBERSTIData_EmbeddedPdv;
}
/*
* EXTERNAL:
*
* Data == eBERSTIData_External
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_External(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = eBERSTIData_External;
}
/*
* OBJECT IDENTIFIER:
*
* Data == eBERSTIData_ObjectIdEncoded || eBERSTIData_ObjectIdentifier
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_ObjectIdentifier(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = type->PrivateDirectives.fOidPacked ? eBERSTIData_ObjectIdEncoded : eBERSTIData_ObjectIdentifier;
}
/*
* *String:
*
* Data == eBERSTIData_String ||
* Data == eBERSTIData_ZeroString
*
* Additional arguments:
*
* - Data == eBERSTIData_*String
* -> NOctets, the size of the string characters
*/
void
ExamineBERType_BMPString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_GeneralString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_GraphicString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_IA5String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_ISO646String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_NumericString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_PrintableString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_TeletexString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t noctets, zero;
GetStringType(ass, type, &noctets, &zero); // to make hack directives become effective
info->Data = eBERSTIData_MultibyteString;
info->NOctets = 1;
}
void
ExamineBERType_T61String(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t noctets, zero;
GetStringType(ass, type, &noctets, &zero); // to make hack directives become effective
info->Data = eBERSTIData_MultibyteString;
info->NOctets = 1;
}
void
ExamineBERType_UniversalString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
void
ExamineBERType_VideotexString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t noctets, zero;
GetStringType(ass, type, &noctets, &zero); // to make hack directives become effective
info->Data = eBERSTIData_MultibyteString;
info->NOctets = 1;
}
void
ExamineBERType_VisibleString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
uint32_t zero;
GetStringType(ass, type, &info->NOctets, &zero);
info->Data = zero ? eBERSTIData_ZeroString : eBERSTIData_String;
}
/*
* CHARACTER STRING:
*
* Data == eBERSTIData_UnrestrictedString
*
* Additional arguments:
*
* - Data == eBERSTIData_EmbeddedPdv ||
* Data == eBERSTIData_UnrestrictedString
* -> Identification, the identification of the type if the type
* is constraint to fixed identification or syntaxes identification
* with single value
*/
void
ExamineBERType_UnrestrictedString(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = eBERSTIData_UnrestrictedString;
}
/*
* GeneralizedTime:
*
* Data == eBERSTIData_GeneralizedTime
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_GeneralizedTime(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = eBERSTIData_GeneralizedTime;
}
/*
* UTCTime:
*
* Data == eBERSTIData_UTCTime
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_UTCTime(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->Data = eBERSTIData_UTCTime;
}
/*
* ObjectDescriptor:
*
* Data == eBERSTIData_ZeroString
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_ObjectDescriptor(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->NOctets = 1;
info->Data = eBERSTIData_ZeroString;
}
/*
* OpenType:
*
* Data == eBERSTIData_Open
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_Open(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
info->NOctets = 1;
info->Data = eBERSTIData_Open;
}
/*
* SEQUENCE/SET:
*
* Data == eBERSTIData_Sequence ||
* Data == eBERSTIData_Set
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_SequenceSet(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
Component_t *comp;
NamedType_t *namedType;
char idebuf[256];
info->Data = (type->Type == eType_Sequence) ?
eBERSTIData_Sequence : eBERSTIData_Set;
/* examine types of components */
for (comp = type->U.SSC.Components; comp; comp = comp->Next) {
switch (comp->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
namedType = comp->U.NOD.NamedType;
sprintf(idebuf, "%s_%s", info->Identifier, namedType->Identifier);
ExamineBERType(ass, namedType->Type, strdup(idebuf));
break;
}
}
}
/*
* SEQUENCE OF/SET OF:
*
* Data == eBERSTIData_SequenceOf ||
* Data == eBERSTIData_SetOf
*
* Additional arguments:
*
* - Data == eBERSTIData_SequenceOf || dat == eBERSTIData_SetOf
* -> SubIdentifier, the name of the subtype
* -> SubType, the subtype itself
* -> Rule, the encoding directive rules
*/
void
ExamineBERType_SequenceSetOf(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
char idebuf[256];
/* set data type and Alignment */
info->Data = (type->Type == eType_SequenceOf ?
eBERSTIData_SequenceOf : eBERSTIData_SetOf);
/* set SubType, SubIdentifier */
info->SubType = type->U.SS.Type;
info->SubIdentifier = GetTypeName(ass, info->SubType);
/* examine subtype */
sprintf(idebuf, "%s_%s", info->Identifier,
type->Type == eType_SequenceOf ? "Sequence" : "Set");
ExamineBERType(ass, type->U.SS.Type, strdup(idebuf));
}
/*
* CHOICE:
*
* Data == eBERSTIData_Choice
*
* Additional arguments:
*
* - Data == eBERSTIData_Integer || dat == eBERSTIData_Unsigned ||
* Data == eBERSTIData_Boolean || dat == eBERSTIData_Choice
* -> NOctets, the size of the integer type
*/
void
ExamineBERType_Choice(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
Component_t *comp;
NamedType_t *namedType;
char idebuf[256];
info->NOctets = GetOctets(GetChoiceType(type));
info->Data = eBERSTIData_Choice;
/* examine types of alternatives */
for (comp = type->U.SSC.Components; comp; comp = comp->Next) {
switch (comp->Type) {
case eComponent_Normal:
namedType = comp->U.NOD.NamedType;
sprintf(idebuf, "%s_%s", info->Identifier, namedType->Identifier);
ExamineBERType(ass, namedType->Type, strdup(idebuf));
break;
}
}
}
/*
* INSTANCE OF:
*
* Data == eBERSTIData_Sequence
*
* Additional arguments:
*
* none
*/
void
ExamineBERType_InstanceOf(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
Component_t *comp;
NamedType_t *namedType;
char idebuf[256];
info->Data = eBERSTIData_Sequence;
/* examine types of components */
for (comp = type->U.SSC.Components; comp; comp = comp->Next) {
switch (comp->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
namedType = comp->U.NOD.NamedType;
sprintf(idebuf, "%s_%s", info->Identifier, namedType->Identifier);
ExamineBERType(ass, namedType->Type, strdup(idebuf));
break;
}
}
}
/*
* Reference:
*
* Data == eBERSTIData_Reference
*
* Additional arguments:
*
* - Data == eBERSTIData_Reference
* -> SubIdentifier, the name of the subtype
* -> SubType, the subtype itself
*/
void
ExamineBERType_Reference(AssignmentList_t ass, Type_t *type, BERTypeInfo_t *info)
{
Assignment_t *a;
info->Data = eBERSTIData_Reference;
a = GetAssignment(ass, FindAssignment(ass, eAssignment_Type,
type->U.Reference.Identifier, type->U.Reference.Module));
info->SubIdentifier = GetName(a);
info->SubType = a->U.Type.Type;
}