1828 lines
48 KiB
C
1828 lines
48 KiB
C
|
/* 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);
|
||
|
}
|