windows-nt/Source/XPSP1/NT/ds/security/asn1/asn1c/examine.c

1828 lines
48 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
#include "error.h"
#include "util.h"
typedef enum {
eNull, eSingle, eMultiple, eString
} RepresentationGroup_e;
void BuildTypeFlags(AssignmentList_t ass, Type_t *type);
Type_t *RebuildTypeWithoutSelectionType(AssignmentList_t ass, Type_t *type);
/* name the sub types of a type */
/* returns 1 if any naming has been performed */
int
NameSubType(AssignmentList_t *ass, char *identifier, Type_t *type, ModuleIdentifier_t *module)
{
char name[256], *n;
char *p;
Component_t *components;
Type_t *subtype;
int ret = 0;
/* build the prefix for the subtypes */
strcpy(name, identifier);
strcat(name, "_");
p = name + strlen(name);
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
/* check all components */
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
/* do not name unstructured types */
if (!IsStructuredType(components->U.NOD.NamedType->Type))
break;
/* name the type of the component and use a type */
/* reference instead */
strcpy(p, components->U.NOD.NamedType->Identifier);
n = Identifier2C(name);
subtype = NewType(eType_Reference);
subtype->U.Reference.Identifier = n;
subtype->U.Reference.Module = module;
AssignType(ass, subtype, components->U.NOD.NamedType->Type);
components->U.NOD.NamedType->Type = subtype;
if (components->Type == eComponent_Default)
components->U.NOD.Value->Type = subtype;
ret = 1;
break;
}
}
break;
case eType_SequenceOf:
case eType_SetOf:
/* already named? */
if (type->U.SS.Type->Type == eType_Reference)
break;
/* name the type of the elements and use a type reference instead */
strcpy(p, type->Type == eType_SequenceOf ? "Seq" : "Set");
n = Identifier2C(name);
subtype = NewType(eType_Reference);
subtype->U.Reference.Identifier = n;
subtype->U.Reference.Module = module;
AssignType(ass, subtype, type->U.SS.Type);
type->U.SS.Type = subtype;
ret = 1;
break;
case eType_Selection:
/* do not name unstructured types */
if (!IsStructuredType(type->U.Selection.Type))
break;
/* name the type of the selected type and use a type reference */
/* instead */
strcpy(p, "Sel");
n = Identifier2C(name);
subtype = NewType(eType_Reference);
subtype->U.Reference.Identifier = n;
subtype->U.Reference.Module = module;
AssignType(ass, subtype, type->U.Selection.Type);
type->U.Selection.Type = subtype;
ret = 1;
break;
}
/* return 1 if any naming has been performed */
return ret;
}
/* name the default value of a type */
/* return 1 if any naming has been performed */
int
NameValueOfType(AssignmentList_t *ass, char *identifier, Type_t *type, ModuleIdentifier_t *module)
{
char name[256], *n;
char *p;
Component_t *components;
Value_t *subvalue;
int ret = 0;
/* build the prefix for the subtypes */
strcpy(name, identifier);
strcat(name, "_");
p = name + strlen(name);
switch (type->Type) {
case eType_Sequence:
case eType_Set:
/* check all components */
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Default:
/* already named? */
if (!components->U.NOD.Value->Type)
break;
/* name the value of the default component and use a value */
/* reference instead */
strcpy(p, components->U.NOD.NamedType->Identifier);
strcat(p, "_default");
n = Identifier2C(name);
subvalue = NewValue(NULL, NULL);
subvalue->U.Reference.Identifier = n;
subvalue->U.Reference.Module = module;
AssignValue(ass, subvalue, components->U.NOD.Value);
components->U.NOD.Value = subvalue;
ret = 1;
break;
}
}
break;
}
/* return 1 if any naming has been performed */
return ret;
}
/* name the types of typefields of the settings of an object */
/* return 1 if any naming has been performed */
int
NameSettings(AssignmentList_t *ass, char *identifier, SettingList_t se, ModuleIdentifier_t *module)
{
int ret = 0;
char name[256], *n;
char *p;
Type_t *subtype;
/* build the prefix for the subtypes */
strcpy(name, identifier);
strcat(name, "_");
p = name + strlen(name);
/* check all settings */
for (; se; se = se->Next) {
strcpy(p, se->Identifier + 1);
switch (se->Type) {
case eSetting_Type:
/* name field type if not already named */
if (se->U.Type.Type->Type != eType_Reference) {
n = Identifier2C(name);
subtype = NewType(eType_Reference);
subtype->U.Reference.Identifier = n;
subtype->U.Reference.Module = module;
ret = AssignType(ass, subtype, se->U.Type.Type);
}
/* mark field type for generation */
se->U.Type.Type->Flags |= eTypeFlags_GenAll;
break;
}
}
/* return 1 if any naming has been performed */
return ret;
}
/* name the default types of typefields of the field specs of an object class */
/* return 1 if any naming has been performed */
int
NameDefaultTypes(AssignmentList_t *ass, char *identifier, ObjectClass_t *oc, SettingList_t se, ModuleIdentifier_t *module)
{
int ret = 0;
char name[256], *n;
char *p;
Type_t *subtype;
FieldSpec_t *fs;
/* build the prefix for the subtypes */
strcpy(name, identifier);
strcat(name, "_");
p = name + strlen(name);
oc = GetObjectClass(*ass, oc);
/* check all field specs */
for (fs = oc->U.ObjectClass.FieldSpec; fs; fs = fs->Next) {
strcpy(p, fs->Identifier + 1);
switch (fs->Type) {
case eFieldSpec_Type:
/* check if typefield has a default type */
if (fs->U.Type.Optionality->Type != eOptionality_Default_Type ||
FindSetting(se, fs->Identifier))
break;
/* name field type if not already named */
if (fs->U.Type.Optionality->U.Type->Type != eType_Reference) {
n = Identifier2C(name);
subtype = NewType(eType_Reference);
subtype->U.Reference.Identifier = n;
subtype->U.Reference.Module = module;
ret = AssignType(ass, subtype, fs->U.Type.Optionality->U.Type);
}
/* mark field type for generation */
fs->U.Type.Optionality->U.Type->Flags |= eTypeFlags_GenAll;
break;
}
}
/* return 1 if any naming has been performed */
return ret;
}
/* name the types of type fields of an object and the default types of */
/* typefields of the field specs of an object class */
/* return 1 if any naming has been performed */
int
NameSettingsOfObject(AssignmentList_t *ass, char *identifier, Object_t *object, ModuleIdentifier_t *module)
{
int ret = 0;
switch (object->Type) {
case eObject_Object:
ret = NameSettings(ass, identifier, object->U.Object.Settings,
module);
ret |= NameDefaultTypes(ass, identifier, object->U.Object.ObjectClass,
object->U.Object.Settings, module);
break;
}
/* return 1 if any naming has been performed */
return ret;
}
/* name the identification value of embedded pdv/character string types */
void
NameIdentificationValueOfType(AssignmentList_t *ass, char *identifier, Type_t *type, ModuleIdentifier_t *module)
{
char name[256], *n;
char *p;
Component_t *components;
NamedValue_t *namedValues;
Value_t *subvalue;
/* build the prefix for the subtypes */
strcpy(name, identifier);
strcat(name, "_");
p = name + strlen(name);
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
/* check all components */
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
strcpy(p, components->U.NOD.NamedType->Identifier);
NameIdentificationValueOfType(ass, name,
components->U.NOD.NamedType->Type, module);
break;
}
}
break;
case eType_SequenceOf:
case eType_SetOf:
/* check the subtype */
strcpy(p, type->Type == eType_SequenceOf ? "Seq" : "Set");
NameIdentificationValueOfType(ass, name, type->U.SS.Type, module);
break;
case eType_EmbeddedPdv:
case eType_CharacterString:
/* check if type has a fixed identification syntaxes constraint */
namedValues = GetFixedIdentification(*ass, type->Constraints);
if (namedValues && !strcmp(namedValues->Identifier, "syntaxes")) {
/* name the identification and use a value reference instead */
for (namedValues = namedValues->Value->U.SSC.NamedValues;
namedValues; namedValues = namedValues->Next) {
strcpy(p, "identification_syntaxes_");
strcat(p, namedValues->Identifier);
n = Identifier2C(name);
subvalue = NewValue(NULL, NULL);
subvalue->U.Reference.Identifier = n;
subvalue->U.Reference.Module = module;
AssignValue(ass, subvalue, namedValues->Value);
}
}
break;
}
}
/* name the type of a value */
/* returns 1 if any naming has been performed */
int
NameTypeOfValue(AssignmentList_t *ass, char *identifier, Value_t *value, ModuleIdentifier_t *module)
{
Type_t *type;
char name[256], *n;
Type_t *subtype;
int ret = 0;
type = value->Type;
/* do not name types of value references or unstructured types */
if (type && IsStructuredType(type)) {
/* build the prefix for the subtype */
strcpy(name, identifier);
strcat(name, "_");
strcat(name, "Type");
n = Identifier2C(name);
/* name the type and use a type reference instead */
subtype = NewType(eType_Reference);
subtype->U.Reference.Identifier = n;
subtype->U.Reference.Module = module;
AssignType(ass, subtype, type);
value->Type = subtype;
ret = 1;
}
return ret;
}
/* replace any components of by the components of the referenced type */
ComponentList_t
RebuildComponentsWithoutComponentsOf(AssignmentList_t ass, ComponentList_t components)
{
Component_t *newcomponents, *subcomponents, **pcomponents;
Type_t *subtype;
int ext;
ext = 0;
pcomponents = &newcomponents;
for (; components; components = components->Next) {
switch (components->Type) {
case eComponent_ComponentsOf:
/* components of should not be used in an extension */
if (ext)
error(E_COMPONENTS_OF_in_extension, NULL);
/* get the components of the referenced type */
subtype = GetType(ass, components->U.ComponentsOf.Type);
switch (subtype->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_External:
case eType_EmbeddedPdv:
case eType_CharacterString:
case eType_Real:
case eType_InstanceOf:
subcomponents = subtype->U.SSC.Components;
break;
default:
error(E_applied_COMPONENTS_OF_to_bad_type, NULL);
}
/* get the real components of the referenced type */
/*XXX self-referencing components of types will idle forever */
*pcomponents = RebuildComponentsWithoutComponentsOf(ass,
subcomponents);
/* find end of components of referenced type */
while (*pcomponents) {
if ((*pcomponents)->Type == eComponent_ExtensionMarker)
error(E_COMPONENTS_OF_extended_type, NULL);
pcomponents = &(*pcomponents)->Next;
}
break;
case eComponent_ExtensionMarker:
/* copy extension marker */
ext = 1;
*pcomponents = DupComponent(components);
pcomponents = &(*pcomponents)->Next;
break;
default:
/* copy other components */
*pcomponents = DupComponent(components);
pcomponents = &(*pcomponents)->Next;
break;
}
}
/* terminate and return component list */
*pcomponents = NULL;
return newcomponents;
}
/* replace any components of by the components of the referenced type */
Type_t *
RebuildTypeWithoutComponentsOf(AssignmentList_t ass, Type_t *type)
{
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
type->U.SSC.Components =
RebuildComponentsWithoutComponentsOf(ass, type->U.SSC.Components);
break;
}
return type;
}
/* replace any selection type by the component of the selected type */
ComponentList_t
RebuildComponentsWithoutSelectionType(AssignmentList_t ass, ComponentList_t components)
{
Component_t *c;
for (c = components; c; c = c->Next) {
switch (c->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
c->U.NOD.NamedType->Type = RebuildTypeWithoutSelectionType(
ass, c->U.NOD.NamedType->Type);
break;
}
}
return components;
}
/* replace any selection type by the component of the selected type */
Type_t *RebuildTypeWithoutSelectionType(AssignmentList_t ass, Type_t *type)
{
Type_t *subtype;
Component_t *components;
switch (type->Type) {
case eType_Selection:
subtype = GetType(ass, type->U.Selection.Type);
switch (subtype->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_External:
case eType_EmbeddedPdv:
case eType_CharacterString:
case eType_Real:
case eType_InstanceOf:
/* get the components of the referenced type */
components = FindComponent(ass, subtype->U.SSC.Components,
type->U.Selection.Identifier);
if (!components)
error(E_bad_component_in_selectiontype, NULL);
/* get the real type of the referenced type */
/*XXX self-referencing selection types will idle forever */
type = RebuildTypeWithoutSelectionType(ass,
components->U.NOD.NamedType->Type);
break;
default:
error(E_selection_of_bad_type, NULL);
}
break;
case eType_Sequence:
case eType_Set:
case eType_Choice:
type->U.SSC.Components =
RebuildComponentsWithoutSelectionType(ass, type->U.SSC.Components);
break;
case eType_SequenceOf:
case eType_SetOf:
type->U.SS.Type = RebuildTypeWithoutSelectionType(ass, type->U.SS.Type);
break;
}
return type;
}
/* mark a type for autotagging */
void
MarkTypeForAutotagging(AssignmentList_t ass, Type_t *type)
{
Component_t *components;
int ext;
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
ext = 0;
/* set flags for autotagging */
type->U.SSC.Autotag[0] = 1;
type->U.SSC.Autotag[1] = 1;
/* reset flags for autotagging if a tag has been used */
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
if (GetTag(ass, components->U.NOD.NamedType->Type))
type->U.SSC.Autotag[ext] = 0;
break;
case eComponent_ExtensionMarker:
ext = 1;
break;
case eComponent_ComponentsOf:
break;
}
}
break;
}
}
/* autotag a marked type */
void
AutotagType(AssignmentList_t ass, Type_t *type)
{
Component_t *components;
Type_t *subtype;
int ext;
int tag;
Tag_t *tags;
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
ext = 0;
/* tag number to use */
tag = 0;
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
subtype = components->U.NOD.NamedType->Type;
tags = subtype->Tags;
/* check if type needs autotagging */
if (!tags &&
type->TagDefault == eTagType_Automatic &&
type->U.SSC.Autotag[ext]) {
/* create a tagged version of the type */
components->U.NOD.NamedType->Type = subtype =
DupType(subtype);
/* use explicit tag for choice components types and */
/* for open type and dummy reference, implicit tag */
/* otherwise */
if (subtype->Type == eType_Choice ||
subtype->Type == eType_Open
/*XXX || DummyReference*/) {
subtype->Tags = NewTag(eTagType_Explicit);
} else {
subtype->Tags = NewTag(eTagType_Implicit);
}
subtype->Tags->Tag = NewValue(NULL, Builtin_Type_Integer);
intx_setuint32(&subtype->Tags->Tag->U.Integer.Value,
tag++);
}
break;
case eComponent_ExtensionMarker:
ext = 1;
break;
}
}
break;
}
}
/* mark constraints extendable */
void
AutoextendConstraints(Constraint_t *constraints)
{
if (!constraints)
return;
if (constraints->Type == eExtension_Unextended)
constraints->Type = eExtension_Extendable;
}
/* autoextend a type if desired */
void
AutoextendType(AssignmentList_t ass, Type_t *type)
{
Component_t *c, **cc;
Type_t *subtype;
int ext;
/* already done? */
if (type->Flags & eTypeFlags_Done)
return;
type->Flags |= eTypeFlags_Done;
/* auto extending wanted? */
if (type->ExtensionDefault != eExtensionType_Automatic)
return;
/* check all sub types */
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
/* extend a sequence/set/choice type */
ext = 0;
for (cc = &type->U.SSC.Components, c = *cc; c;
c = c->Next, cc = &(*cc)->Next) {
*cc = DupComponent(c);
switch (c->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
subtype = c->U.NOD.NamedType->Type;
AutoextendType(ass, subtype);
break;
case eComponent_ExtensionMarker:
ext = 1;
break;
}
}
if (!ext) {
*cc = NewComponent(eComponent_ExtensionMarker);
cc = &(*cc)->Next;
}
*cc = NULL;
break;
case eType_SequenceOf:
case eType_SetOf:
subtype = type->U.SS.Type;
AutoextendType(ass, subtype);
break;
}
/* mark type as extendable */
AutoextendConstraints(type->Constraints);
}
/* set the tag type of unspecified tags to explicit or implicit, */
/* create list of all tags (including the type's universal tag and the */
/* tags of the referenced type if applicable), */
/* and create list of first tags (esp. for choice types) */
void
BuildTags(AssignmentList_t ass, Type_t *type, TagType_e eParentDefTagType)
{
Tag_t *t, *t2, **tt;
Component_t *components;
Type_t *reftype;
Type_e te;
uint32_t i;
/* already done? */
if (type->Flags & eTypeFlags_Done)
return;
type->Flags |= eTypeFlags_Done;
// update default tag type
if (type->TagDefault == eTagType_Unknown &&
(eParentDefTagType == eTagType_Explicit || eParentDefTagType == eTagType_Implicit))
{
type->TagDefault = eParentDefTagType;
}
/* set tag type of unspecified tags to explicit or implicit */
/* use explicit tags when: */
/* - TagDefault indicates explicit tags, */
/* - Type is choice/open type/dummy reference and no other explicit tag */
/* will follow */
te = GetTypeType(ass, type);
if (type->Tags)
{
for (tt = &type->Tags, t = type->Tags; t; tt = &(*tt)->Next, t = t->Next)
{
*tt = DupTag(t);
if ((*tt)->Type == eTagType_Unknown)
{
for (t2 = t->Next; t2; t2 = t2->Next)
{
if (t2->Type != eTagType_Implicit)
break;
}
if (type->TagDefault == eTagType_Explicit ||
(!t2 && (te == eType_Choice || te == eType_Open /*XXX || DummyReference*/)))
{
(*tt)->Type = eTagType_Explicit;
}
else
{
(*tt)->Type = eTagType_Implicit;
}
}
}
}
/* copy given tags to AllTags list */
for (tt = &type->AllTags, t = type->Tags;
t;
tt = &(*tt)->Next, t = t->Next)
{
*tt = DupTag(t);
}
/* build tags of subtypes and copy tags of reference type */
switch (type->Type)
{
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
for (components = type->U.SSC.Components;
components;
components = components->Next)
{
switch (components->Type)
{
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
BuildTags(ass, components->U.NOD.NamedType->Type, type->TagDefault);
break;
}
}
break;
case eType_SequenceOf:
case eType_SetOf:
BuildTags(ass, type->U.SS.Type, eTagType_Unknown);
break;
case eType_Reference:
reftype = GetReferencedType(ass, type);
BuildTags(ass, reftype, type->TagDefault);
for (t = reftype->AllTags; t; tt = &(*tt)->Next, t = t->Next)
{
*tt = DupTag(t);
}
break;
}
/* add the type's universal tag to the AllTags list if the type is */
/* not an internal type */
if (!(type->Type & 0x8000))
{
*tt = NewTag(eTagType_Implicit);
(*tt)->Class = eTagClass_Universal;
(*tt)->Tag = NewValue(NULL, Builtin_Type_Integer);
intx_setuint32(&(*tt)->Tag->U.Integer.Value, type->Type & 0x1f);
}
/* build list of FirstTags containing the possible tag values of the type */
tt = &type->FirstTags;
if (type->AllTags)
{
/* if type has any tags, only the first tag is needed */
*tt = DupTag(type->AllTags);
tt = &(*tt)->Next;
}
else
{
/* otherwise we have to examine the type */
switch (type->Type)
{
case eType_Choice:
/* get the first tags of all components of a choice as FirstTags */
for (components = type->U.SSC.Components;
components;
components = components->Next)
{
switch (components->Type)
{
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
for (t = components->U.NOD.NamedType->Type->FirstTags;
t;
t = t->Next)
{
*tt = DupTag(t);
tt = &(*tt)->Next;
}
break;
}
}
break;
case eType_Open:
/* create a list of all tags for open type */
for (i = 1; i < 0x20; i++)
{
*tt = NewTag(eTagType_Unknown);
(*tt)->Class = eTagClass_Unknown;
(*tt)->Tag = NewValue(NULL, Builtin_Type_Integer);
intx_setuint32(&(*tt)->Tag->U.Integer.Value, i);
tt = &(*tt)->Next;
}
break;
case eType_Reference:
/* get the tags of the referenced type */
for (t = reftype->FirstTags; t; t = t->Next)
{
*tt = DupTag(t);
tt = &(*tt)->Next;
}
break;
}
}
*tt = NULL;
}
/* get the smallest tag of a tag list */
Tag_t *
FindSmallestTag(AssignmentList_t ass, TagList_t tags)
{
Tag_t *mintag, *t;
mintag = tags;
for (t = tags->Next; t; t = t->Next) {
if (mintag->Class > t->Class ||
mintag->Class == t->Class && intx_cmp(
&GetValue(ass, mintag->Tag)->U.Integer.Value,
&GetValue(ass, t->Tag)->U.Integer.Value) > 0)
mintag = t;
}
return mintag;
}
/* compare two tags by tag class and tag value */
int
CmpTags(const void *p1, const void *p2, void *ctx)
{
Tag_t *tags1 = (Tag_t *)p1;
Tag_t *tags2 = (Tag_t *)p2;
Assignment_t *ass = (Assignment_t *)ctx;
if (tags1->Class != tags2->Class)
return tags1->Class - tags2->Class;
return intx2uint32(&GetValue(ass, tags1->Tag)->U.Integer.Value) -
intx2uint32(&GetValue(ass, tags2->Tag)->U.Integer.Value);
}
/* compare two components by their smallest tag */
int
CmpComponentsBySmallestTag(const void *p1, const void *p2, void *ctx)
{
Component_t *c1 = (Component_t *)p1;
Component_t *c2 = (Component_t *)p2;
Assignment_t *ass = (Assignment_t *)ctx;
Tag_t *tags1, *tags2;
tags1 = FindSmallestTag(ass, c1->U.NOD.NamedType->Type->FirstTags);
tags2 = FindSmallestTag(ass, c2->U.NOD.NamedType->Type->FirstTags);
if (tags1->Class != tags2->Class)
return tags1->Class - tags2->Class;
return intx2uint32(&tags1->Tag->U.Integer.Value) -
intx2uint32(&tags2->Tag->U.Integer.Value);
}
/* sort the components of a set or choice by their smallest tag */
void
SortTypeTags(AssignmentList_t ass, Type_t *type)
{
Component_t **pcomponents, *extensions;
switch (type->Type) {
case eType_Set:
case eType_Choice:
/* remove extensions */
for (pcomponents = &type->U.SSC.Components; *pcomponents;
pcomponents = &(*pcomponents)->Next) {
if ((*pcomponents)->Type == eComponent_ExtensionMarker)
break;
}
extensions = *pcomponents;
*pcomponents = NULL;
/* sort extension root */
qsortSL((void **)&type->U.SSC.Components, offsetof(Component_t, Next),
CmpComponentsBySmallestTag, ass);
/* sort extensions */
if (extensions && extensions->Next)
qsortSL((void **)&extensions->Next, offsetof(Component_t, Next),
CmpComponentsBySmallestTag, ass);
/* merge extension root and extensions */
for (pcomponents = &type->U.SSC.Components; *pcomponents;
pcomponents = &(*pcomponents)->Next) {}
*pcomponents = extensions;
break;
}
}
/* check if two lists of tags have common tags */
void
CheckCommonTags(AssignmentList_t ass, TagList_t tags1, TagList_t tags2)
{
Tag_t *t1, *t2;
int ret;
qsortSL((void **)&tags1, offsetof(Tag_t, Next), CmpTags, ass);
qsortSL((void **)&tags2, offsetof(Tag_t, Next), CmpTags, ass);
for (t1 = tags1, t2 = tags2; t1 && t2; ) {
ret = CmpTags((const void *)t1, (const void *)t2, (void *)ass);
if (ret == 0) {
error(E_duplicate_tag, NULL);
} else if (ret < 0) {
t1 = t1->Next;
} else {
t2 = t2->Next;
}
}
}
/* check if a list of tags and the first tags of components have common tags */
void
CheckTagsInComponents(AssignmentList_t ass, TagList_t tags, ComponentList_t components, int untilnormal)
{
for (; components; components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
CheckCommonTags(ass, tags,
components->U.NOD.NamedType->Type->FirstTags);
if (untilnormal && components->Type == eComponent_Normal)
return;
break;
}
}
}
/* check for common tags */
void
CheckTags(AssignmentList_t ass, Type_t *type)
{
Component_t *c;
Type_t *subtype;
Tag_t *tag;
switch (type->Type) {
case eType_Sequence:
/* check for common tags in a sequence: */
/* the first tags of an optional/default component and the first */
/* tags of the following components (up to and including the next */
/* non-optional/non-default component) must not have common first */
/* tags */
for (c = type->U.Sequence.Components; c; c = c->Next) {
switch (c->Type) {
case eComponent_Optional:
case eComponent_Default:
subtype = c->U.NOD.NamedType->Type;
tag = subtype->FirstTags;
CheckTagsInComponents(ass, tag, c->Next, 1);
break;
}
}
break;
case eType_Set:
case eType_Choice:
/* check for common tags in a set/choice: */
/* the first tags of all components must be destinct */
for (c = type->U.Sequence.Components; c; c = c->Next) {
switch (c->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
subtype = c->U.NOD.NamedType->Type;
tag = subtype->FirstTags;
CheckTagsInComponents(ass, tag, c->Next, 0);
break;
}
}
break;
}
}
/* build the list of PER-visible constraints */
void BuildConstraints(AssignmentList_t ass, Type_t *type)
{
Type_t *reftype;
Constraint_t *cons, *c1, *c2;
Component_t *components;
/* already done? */
if (type->Flags & eTypeFlags_Done)
return;
type->Flags |= eTypeFlags_Done;
switch (type->Type) {
case eType_Reference:
/* create an intersection of the constraints of the reference type */
/* and the constraints of the referenced type */
reftype = GetReferencedType(ass, type);
BuildConstraints(ass, reftype);
c1 = reftype->Constraints;
c2 = type->Constraints;
if (c1) {
if (c2) {
IntersectConstraints(&cons, c1, c2);
} else {
cons = c1;
}
} else {
cons = c2;
}
type->Constraints = cons;
/* get the PER-visible constraints */
GetPERConstraints(ass, cons, &type->PERConstraints);
break;
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
/* build the constraints of any component */
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
reftype = components->U.NOD.NamedType->Type;
BuildConstraints(ass, reftype);
break;
}
}
/* get the PER-visible constraints */
GetPERConstraints(ass, type->Constraints, &type->PERConstraints);
break;
case eType_SequenceOf:
case eType_SetOf:
/* build the constraints of the subtype */
reftype = type->U.SS.Type;
BuildConstraints(ass, reftype);
/* get the PER-visible constraints */
GetPERConstraints(ass, type->Constraints, &type->PERConstraints);
break;
default:
/* get the PER-visible constraints */
GetPERConstraints(ass, type->Constraints, &type->PERConstraints);
break;
}
}
/* build type flags from the directives */
void BuildDirectives(AssignmentList_t ass, Type_t *type, int isComponent)
{
int pointer = 0;
TypeRules_e rule = 0;
RepresentationGroup_e grp;
int32_t noctets;
uint32_t zero;
Directive_t *d;
Component_t *components;
Type_t *reftype;
/* already done? */
if (type->Flags & eTypeFlags_Done)
return;
type->Flags |= eTypeFlags_Done;
/* get directive group which may be applied to the type */
switch (type->Type)
{
case eType_Boolean:
case eType_Integer:
case eType_ObjectIdentifier:
case eType_ObjectDescriptor:
case eType_External:
case eType_Real:
case eType_Enumerated:
case eType_EmbeddedPdv:
case eType_Sequence:
case eType_Set:
case eType_InstanceOf:
case eType_UTCTime:
case eType_GeneralizedTime:
case eType_Choice:
case eType_BitString:
case eType_OctetString:
grp = eSingle;
break;
case eType_Reference:
grp = eSingle;
break;
case eType_CharacterString:
case eType_NumericString:
case eType_PrintableString:
case eType_TeletexString:
case eType_T61String:
case eType_VideotexString:
case eType_IA5String:
case eType_GraphicString:
case eType_VisibleString:
case eType_ISO646String:
case eType_GeneralString:
case eType_UniversalString:
case eType_BMPString:
case eType_RestrictedString:
case eType_UTF8String:
grp = eString;
/*XXX rule = zero ? eTypeRules_ZeroTerminated : eTypeRules_FixedArray;
for upperconstrained size */
// lonchanc: it was eTypeRules_LengthPointer
if (type->PrivateDirectives.fLenPtr)
{
rule = eTypeRules_LengthPointer;
}
else
if (type->PrivateDirectives.fArray)
{
rule = eTypeRules_FixedArray;
}
else
{
GetStringType(ass, type, &noctets, &zero);
rule = zero ? eTypeRules_ZeroTerminated : eTypeRules_LengthPointer;
}
break;
case eType_Null:
grp = eNull;
break;
case eType_SequenceOf:
case eType_SetOf:
grp = eMultiple;
// lonchanc: it was eTypeRules_LengthPointer
if (type->PrivateDirectives.fSLinked)
{
rule = eTypeRules_SinglyLinkedList;
}
else
if (type->PrivateDirectives.fLenPtr)
{
rule = eTypeRules_LengthPointer;
}
else
if (type->PrivateDirectives.fArray)
{
rule = eTypeRules_FixedArray;
}
else
if (type->PrivateDirectives.fPointer)
{
rule = eTypeRules_PointerToElement | eTypeRules_FixedArray;
}
else
if (type->PrivateDirectives.fDLinked)
{
rule = eTypeRules_DoublyLinkedList;
}
else
{
if (eExtension_Unconstrained == type->PERConstraints.Size.Type)
{
rule = g_eDefTypeRuleSS_NonSized;
}
else
{
rule = g_eDefTypeRuleSS_Sized;
}
}
break;
case eType_Selection:
MyAbort();
/*NOTREACHED*/
case eType_Undefined:
MyAbort();
/*NOTREACHED*/
}
/* parse list of directives */
for (d = type->Directives; d; d = d->Next) {
switch (d->Type) {
case eDirective_LengthPointer:
if (grp != eString)
error(E_bad_directive, NULL);
rule = eTypeRules_LengthPointer;
break;
case eDirective_ZeroTerminated:
if (grp != eString)
error(E_bad_directive, NULL);
rule = eTypeRules_ZeroTerminated;
break;
case eDirective_Pointer:
if (!isComponent)
error(E_bad_directive, NULL);
pointer = eTypeRules_Pointer;
break;
case eDirective_NoPointer:
if (!isComponent)
error(E_bad_directive, NULL);
pointer = 0;
break;
}
}
/* parse list of size directives of sequence of/set of */
if (type->Type == eType_SequenceOf || type->Type == eType_SetOf) {
for (d = type->U.SS.Directives; d; d = d->Next) {
switch (d->Type) {
case eDirective_FixedArray:
rule = eTypeRules_FixedArray;
break;
case eDirective_DoublyLinkedList:
rule = eTypeRules_DoublyLinkedList;
break;
case eDirective_SinglyLinkedList:
rule = eTypeRules_SinglyLinkedList;
break;
case eDirective_LengthPointer:
rule = eTypeRules_LengthPointer;
break;
}
}
}
/* lists are always pointered, no additional pointer needed */
if (rule & (eTypeRules_SinglyLinkedList | eTypeRules_DoublyLinkedList))
pointer = 0;
/* set type flags according to directive rule and pointer flag */
type->Rules = rule | pointer;
/* build directives of subtypes */
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
components = type->U.SSC.Components;
for (; components; components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
reftype = components->U.NOD.NamedType->Type;
BuildDirectives(ass, reftype, 1);
break;
case eComponent_ExtensionMarker:
break;
}
}
break;
case eType_SequenceOf:
case eType_SetOf:
reftype = type->U.SS.Type;
BuildDirectives(ass, reftype, 0);
break;
}
}
/* build type flags and counters for components */
/* will set eTypeFlags_Null if type has only null components */
/* will set eTypeFlags_Simple if type has only simple components */
/* will count optional/default components in the extension root (optionals) */
/* will count components in the extension root (alternatives) */
/* will count components in the extension (extensions) */
void
BuildComponentsTypeFlags(AssignmentList_t ass, ComponentList_t components, TypeFlags_e *flags, uint32_t *alternatives, uint32_t *optionals, uint32_t *extensions)
{
int extended = 0;
TypeFlags_e f = eTypeFlags_Null | eTypeFlags_Simple;
while (components) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
BuildTypeFlags(ass, components->U.NOD.NamedType->Type);
if (!(components->U.NOD.NamedType->Type->Flags & eTypeFlags_Null))
f &= ~eTypeFlags_Null;
if ((components->U.NOD.NamedType->Type->Rules &
eTypeRules_Pointer) ||
!(components->U.NOD.NamedType->Type->Flags & eTypeFlags_Simple))
f &= ~eTypeFlags_Simple;
if (extended) {
if (extensions)
(*extensions)++;
} else {
if (alternatives)
(*alternatives)++;
if (optionals && components->Type != eComponent_Normal)
(*optionals)++;
}
break;
case eComponent_ExtensionMarker:
f |= eTypeFlags_ExtensionMarker;
extended = 1;
break;
}
components = components->Next;
}
*flags |= f;
}
/* build type flags and count components of sequence/set/choice types */
void
BuildTypeFlags(AssignmentList_t ass, Type_t *type)
{
Assignment_t *a;
Type_t *subtype;
char *itype;
int32_t sign;
/* already done? */
if (type->Flags & eTypeFlags_Done)
return;
type->Flags |= eTypeFlags_Done;
switch (type->Type) {
case eType_Null:
/* null is null and simple */
type->Flags |= eTypeFlags_Null | eTypeFlags_Simple;
break;
case eType_Boolean:
case eType_Enumerated:
/* boolean and enumerated are simple if no pointer is used */
if (!(type->Rules & eTypeRules_Pointer))
type->Flags |= eTypeFlags_Simple;
break;
case eType_Integer:
/* integer is simple if no pointer is used and no intx_t is used */
itype = GetIntegerType(ass, type, &sign);
if (strcmp(itype, "ASN1intx_t") && !(type->Rules & eTypeRules_Pointer))
type->Flags |= eTypeFlags_Simple;
break;
case eType_Real:
/* real is simple if no pointer is used and no real_t is used */
itype = GetRealType(type);
if (strcmp(itype, "ASN1real_t") && !(type->Rules & eTypeRules_Pointer))
type->Flags |= eTypeFlags_Simple;
break;
case eType_Sequence:
case eType_Set:
/* build type flags and counters for the components */
BuildComponentsTypeFlags(ass, type->U.SSC.Components, &type->Flags,
NULL, &type->U.SSC.Optionals, &type->U.Sequence.Extensions);
/* an extended type or a type containing optionals is not null */
if ((type->Flags & eTypeFlags_ExtensionMarker) || type->U.SSC.Optionals)
type->Flags &= ~eTypeFlags_Null;
break;
case eType_SequenceOf:
case eType_SetOf:
/* never null nor simple */
BuildTypeFlags(ass, type->U.SS.Type);
break;
case eType_Choice:
/* build type flags and counters for the components */
BuildComponentsTypeFlags(ass, type->U.Choice.Components, &type->Flags,
&type->U.Choice.Alternatives, NULL, &type->U.Choice.Extensions);
/* a choice of nulls with more than one alternative or extensions */
/* is not null because an offset has to be encoded */
/* set the nullchoice flag instead */
if ((type->Flags & eTypeFlags_Null) &&
((type->Flags & eTypeFlags_ExtensionMarker) ||
type->U.Choice.Alternatives > 1)) {
type->Flags &= ~eTypeFlags_Null;
type->Flags |= eTypeFlags_NullChoice;
}
break;
case eType_Reference:
/* get the flags of the referenced type */
a = FindAssignment(ass, eAssignment_Type,
type->U.Reference.Identifier, type->U.Reference.Module);
a = GetAssignment(ass, a);
subtype = a->U.Type.Type;
BuildTypeFlags(ass, subtype);
type->Flags = subtype->Flags;
break;
}
}
/* Mark non-structured types (or all types if wanted) for generation */
void MarkTypeForGeneration(AssignmentList_t ass, Type_t *type, TypeFlags_e needed)
{
Assignment_t *a;
Component_t *components;
/* already done? */
if (type->Flags & eTypeFlags_Done) {
type->Flags |= needed;
return;
}
type->Flags |= eTypeFlags_Done | needed;
if (!IsStructuredType(GetType(ass, type)) && !ForceAllTypes) {
/* generate type only */
type->Flags |= eTypeFlags_GenType;
} else {
if (type->Flags & eTypeFlags_Simple) {
/* generate encoding/decoding/compare */
type->Flags |= eTypeFlags_GenSimple;
} else {
/* generate encoding/decoding/free/compare */
type->Flags |= eTypeFlags_GenAll;
}
}
/* mark subtypes for generation */
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
MarkTypeForGeneration(ass, components->U.NOD.NamedType->Type,
needed);
break;
}
}
break;
case eType_SequenceOf:
case eType_SetOf:
MarkTypeForGeneration(ass, type->U.SS.Type,
needed | eTypeFlags_GenCompare);
break;
case eType_Reference:
a = FindAssignment(ass, eAssignment_Type,
type->U.Reference.Identifier, type->U.Reference.Module);
a = GetAssignment(ass, a);
MarkTypeForGeneration(ass, a->U.Type.Type, needed);
break;
}
}
/* mark a value for generation */
void
MarkValueForGeneration(AssignmentList_t ass, Value_t *value)
{
/* already done? */
if (value->Flags & eValueFlags_Done)
return;
value->Flags |= eValueFlags_GenAll | eValueFlags_Done;
/* mark type of value for generation */
if (value->Type)
MarkTypeForGeneration(ass, value->Type, 0);
}
/* mark assignments for generation */
void
MarkForGeneration(AssignmentList_t ass, ModuleIdentifier_t *mainmodule, Assignment_t *a)
{
/* builtin elements need not to be generated */
if (!CmpModuleIdentifier(ass, a->Module, Builtin_Module) ||
!CmpModuleIdentifier(ass, a->Module, Builtin_Character_Module))
return;
/* non-main module elements will require long names and are only */
/* generated if they are referenced by elements of the main module */
if (CmpModuleIdentifier(ass, a->Module, mainmodule)) {
a->Flags |= eAssignmentFlags_LongName;
return;
}
/* mark type/value for generation */
switch (a->Type) {
case eAssignment_Type:
MarkTypeForGeneration(ass, a->U.Type.Type, 0);
break;
case eAssignment_Value:
MarkValueForGeneration(ass, a->U.Value.Value);
break;
}
}
/* clear done flags of types */
void
ClearTypeDone(Type_t *type)
{
Component_t *components;
type->Flags &= ~eTypeFlags_Done;
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
for (components = type->U.SSC.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
case eComponent_Optional:
case eComponent_Default:
ClearTypeDone(components->U.NOD.NamedType->Type);
break;
}
}
break;
case eType_SequenceOf:
case eType_SetOf:
ClearTypeDone(type->U.SS.Type);
break;
}
}
/* clear done flags of values */
void
ClearValueDone(Value_t *value)
{
value->Flags &= ~eValueFlags_Done;
if (value->Type)
ClearTypeDone(value->Type);
}
/* clear done flags of assignments */
void
ClearDone(AssignmentList_t ass)
{
for (; ass; ass = ass->Next) {
switch (ass->Type) {
case eAssignment_Type:
ClearTypeDone(ass->U.Type.Type);
break;
case eAssignment_Value:
ClearValueDone(ass->U.Value.Value);
break;
}
}
}
/* examination of assignments */
void Examination(AssignmentList_t *ass, ModuleIdentifier_t *mainmodule)
{
Assignment_t *a, *nexta, **aa;
Type_t *subtype;
Value_t *subvalue;
ObjectClass_t *subobjclass;
Object_t *subobject;
ObjectSet_t *subobjset;
int redo;
/* drop results of previous passes */
for (aa = ass; *aa;) {
if ((*aa)->Type == eAssignment_NextPass)
*aa = NULL;
else
aa = &(*aa)->Next;
}
/* reverse order of assignments to get the original order */
for (a = *ass, *ass = NULL; a; a = nexta) {
nexta = a->Next;
a->Next = *ass;
*ass = a;
}
/* replace references from IMPORT by corresponding type-/value-/...-refs */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Reference) {
a->Type = GetAssignmentType(*ass, a);
switch (a->Type) {
case eAssignment_Type:
subtype = NewType(eType_Reference);
subtype->U.Reference.Identifier = a->U.Reference.Identifier;
subtype->U.Reference.Module = a->U.Reference.Module;
a->U.Type.Type = subtype;
break;
case eAssignment_Value:
subvalue = NewValue(NULL, NULL);
subvalue->U.Reference.Identifier = a->U.Reference.Identifier;
subvalue->U.Reference.Module = a->U.Reference.Module;
a->U.Value.Value = subvalue;
break;
case eAssignment_ObjectClass:
subobjclass = NewObjectClass(eObjectClass_Reference);
subobjclass->U.Reference.Identifier = a->U.Reference.Identifier;
subobjclass->U.Reference.Module = a->U.Reference.Module;
a->U.ObjectClass.ObjectClass = subobjclass;
break;
case eAssignment_Object:
subobject = NewObject(eObject_Reference);
subobject->U.Reference.Identifier = a->U.Reference.Identifier;
subobject->U.Reference.Module = a->U.Reference.Module;
a->U.Object.Object = subobject;
break;
case eAssignment_ObjectSet:
subobjset = NewObjectSet(eObjectSet_Reference);
subobjset->U.Reference.Identifier = a->U.Reference.Identifier;
subobjset->U.Reference.Module = a->U.Reference.Module;
a->U.ObjectSet.ObjectSet = subobjset;
break;
default:
MyAbort();
}
}
}
/* name types in types, values in types, types of values, types of objects*/
do {
redo = 0;
for (a = *ass; a; a = a->Next) {
switch (a->Type) {
case eAssignment_Type:
redo |= NameSubType(ass, Identifier2C(a->Identifier),
a->U.Type.Type, a->Module);
redo |= NameValueOfType(ass, Identifier2C(a->Identifier),
a->U.Type.Type, a->Module);
break;
case eAssignment_Value:
redo |= NameTypeOfValue(ass, Identifier2C(a->Identifier),
a->U.Value.Value, a->Module);
break;
case eAssignment_Object:
redo |= NameSettingsOfObject(ass,
Identifier2C(a->Identifier),
a->U.Object.Object, a->Module);
break;
}
}
} while (redo);
/* name identification of embedded pdv/character strings */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
NameIdentificationValueOfType(ass, Identifier2C(a->Identifier),
a->U.Type.Type, a->Module);
}
/* mark types that will be automatically tagged */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
MarkTypeForAutotagging(*ass, a->U.Type.Type);
}
/* replace components of by corresponding components */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
a->U.Type.Type = RebuildTypeWithoutComponentsOf(*ass,
a->U.Type.Type);
}
/* replace selection types by corresponding component types */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
a->U.Type.Type = RebuildTypeWithoutSelectionType(*ass,
a->U.Type.Type);
}
/* perform automatic tagging */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
AutotagType(*ass, a->U.Type.Type);
}
/* perform automatic extension */
ClearDone(*ass);
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
AutoextendType(*ass, a->U.Type.Type);
}
/* build tags of Sequence/Set/Choice/InstanceOf */
ClearDone(*ass);
for (a = *ass; a; a = a->Next)
{
if (a->Type == eAssignment_Type)
{
switch (a->U.Type.Type->Type)
{
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
BuildTags(*ass, a->U.Type.Type, a->eDefTagType);
break;
}
}
}
/* build tags of other types */
ClearDone(*ass);
for (a = *ass; a; a = a->Next)
{
if (a->Type == eAssignment_Type)
{
switch (a->U.Type.Type->Type)
{
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_InstanceOf:
break;
default:
BuildTags(*ass, a->U.Type.Type, a->eDefTagType);
break;
}
}
}
/* sort set and choice types by tag */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
SortTypeTags(*ass, a->U.Type.Type);
}
/* check for duplicate tags */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
CheckTags(*ass, a->U.Type.Type);
}
/* derive constraints of referenced types to referencing types */
ClearDone(*ass);
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
BuildConstraints(*ass, a->U.Type.Type);
}
/* derive constraints of referenced types to referencing types of values */
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Value)
BuildConstraints(*ass, GetValue(*ass, a->U.Value.Value)->Type);
}
/* examine directives of types */
ClearDone(*ass);
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
BuildDirectives(*ass, a->U.Type.Type, 0);
}
/* examine types to be empty/simple/choice of nulls */
ClearDone(*ass);
for (a = *ass; a; a = a->Next) {
if (a->Type == eAssignment_Type)
BuildTypeFlags(*ass, a->U.Type.Type);
}
/* mark types and values that shall be generated */
ClearDone(*ass);
for (a = *ass; a; a = a->Next) {
MarkForGeneration(*ass, mainmodule, a);
}
/* sort assignments so that no forward references will be needed */
SortAssignedTypes(ass);
}