windows-nt/Source/XPSP1/NT/ds/security/asn1/asn1c/util.c
2020-09-26 16:20:57 +08:00

1779 lines
49 KiB
C

/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
extern int g_fLongNameForImported;
/* get the type by resolving references */
Type_t *
GetType(AssignmentList_t ass, Type_t *type)
{
if (!type)
return NULL;
if (IsReferenceType(type))
return GetType(ass, GetReferencedType(ass, type));
return type;
}
/* get the type's type by resolving references */
Type_e
GetTypeType(AssignmentList_t ass, Type_t *type)
{
type = GetType(ass, type);
return type ? type->Type : eType_Undefined;
}
/* get the type rules */
TypeRules_e
GetTypeRules(AssignmentList_t ass, Type_t *type)
{
if (!IsReferenceType(type))
return type->Rules;
return type->Rules | GetTypeRules(ass, GetReferencedType(ass, type));
}
/* get the value by resolving references */
Value_t *
GetValue(AssignmentList_t ass, Value_t *value)
{
Assignment_t *a;
if (!value)
return NULL;
if (!value->Type) {
a = GetAssignment(ass, FindAssignment(ass, eAssignment_Value,
value->U.Reference.Identifier, value->U.Reference.Module));
if (!a)
return NULL;
return GetValue(ass, a->U.Value.Value);
}
return value;
}
/* get the object class by resolving references */
ObjectClass_t *
GetObjectClass(AssignmentList_t ass, ObjectClass_t *oc)
{
Assignment_t *a;
FieldSpec_t *fs;
ObjectClass_t *oc2;
if (!oc)
return NULL;
switch (oc->Type) {
case eObjectClass_Reference:
a = GetAssignment(ass, FindAssignment(ass, eAssignment_ObjectClass,
oc->U.Reference.Identifier, oc->U.Reference.Module));
if (!a)
return NULL;
return GetObjectClass(ass, a->U.ObjectClass.ObjectClass);
case eObjectClass_FieldReference:
oc2 = GetObjectClass(ass, oc->U.FieldReference.ObjectClass);
if (!oc2)
return NULL;
fs = GetFieldSpec(ass, FindFieldSpec(oc2->U.ObjectClass.FieldSpec,
oc->U.FieldReference.Identifier));
if (!fs)
return NULL;
if (fs->Type == eFieldSpec_Object)
return GetObjectClass(ass, fs->U.Object.ObjectClass);
else if (fs->Type == eFieldSpec_ObjectSet)
return GetObjectClass(ass, fs->U.ObjectSet.ObjectClass);
else
return NULL;
}
return oc;
}
/* get the object by resolving references */
Object_t *
GetObject(AssignmentList_t ass, Object_t *o)
{
Assignment_t *a;
if (!o)
return NULL;
if (o->Type == eObject_Reference) {
a = GetAssignment(ass, FindAssignment(ass, eAssignment_Object,
o->U.Reference.Identifier, o->U.Reference.Module));
if (!a)
return NULL;
return GetObject(ass, a->U.Object.Object);
}
return o;
}
/* get the object set by resolving references */
ObjectSet_t *
GetObjectSet(AssignmentList_t ass, ObjectSet_t *os)
{
Assignment_t *a;
if (!os)
return NULL;
if (os->Type == eObjectSet_Reference) {
a = GetAssignment(ass, FindAssignment(ass, eAssignment_ObjectSet,
os->U.Reference.Identifier, os->U.Reference.Module));
if (!a)
return NULL;
return GetObjectSet(ass, a->U.ObjectSet.ObjectSet);
}
return os;
}
/* get the field spec */
FieldSpec_t *
GetFieldSpec(AssignmentList_t ass, FieldSpec_t *fs)
{
return fs;
}
/* get the field spec type */
FieldSpecs_e
GetFieldSpecType(AssignmentList_t ass, FieldSpec_t *fs)
{
return fs ? fs->Type : eFieldSpec_Undefined;
}
/* convert an identifier into C syntax */
char *
Identifier2C(char *identifier)
{
char buffer[256];
char *p = buffer;
while (*identifier) {
if (isalnum(*identifier))
*p++ = *identifier;
else
*p++ = '_';
identifier++;
}
*p = 0;
return strdup(buffer);
}
/* convert an identifier into C syntax */
char *
PIdentifier2C(char *identifier)
{
char buffer[256];
char *p = buffer;
*p++ = 'P';
while (*identifier) {
if (isalnum(*identifier))
*p++ = *identifier;
else
*p++ = '_';
identifier++;
}
*p = 0;
return strdup(buffer);
}
/* get the integer type and the sign of an integer with the given bounds */
static char *
GetIType(intx_t *lb, intx_t *ub, int32_t *sign)
{
enum {
eint8 = 1,
euint8 = 2,
eint16 = 4,
euint16 = 8,
eint32 = 16,
euint32 = 32,
eint64 = 64,
euint64 = 128,
eintx = 256,
euintx = 512
} type;
type = (eint8 | euint8 | eint16 | euint16 | eint32 | euint32 | eintx | euintx);
if (Has64Bits)
type |= eint64 | euint64;
if (!intxisuint8(lb) || !intxisuint8(ub))
type &= ~euint8;
if (!intxisuint16(lb) || !intxisuint16(ub))
type &= ~euint16;
if (!intxisuint32(lb) || !intxisuint32(ub))
type &= ~euint32;
if (!intxisuint64(lb) || !intxisuint64(ub))
type &= ~euint64;
if (!intxisint8(lb) || !intxisint8(ub))
type &= ~eint8;
if (!intxisint16(lb) || !intxisint16(ub))
type &= ~eint16;
if (!intxisint32(lb) || !intxisint32(ub))
type &= ~eint32;
if (!intxisint64(lb) || !intxisint64(ub))
type &= ~eint64;
if (lb->value[0] >= 0x7f || ub->value[0] >= 0x7f)
type &= ~euintx;
if (type & euint8) {
*sign = 1;
return "ASN1uint16_t"; // lonchanc: for av; original is "ASN1uint8_t";
}
if (type & eint8) {
*sign = -1;
return "ASN1int8_t";
}
if (type & euint16) {
*sign = 1;
return "ASN1uint16_t";
}
if (type & eint16) {
*sign = -1;
return "ASN1int16_t";
}
if (type & euint32) {
*sign = 1;
return "ASN1uint32_t";
}
if (type & eint32) {
*sign = -1;
return "ASN1int32_t";
}
if (type & euint64) {
*sign = 1;
return "ASN1uint64_t";
}
if (type & eint64) {
*sign = -1;
return "ASN1int64_t";
}
if (type & euintx) {
*sign = 1;
return "ASN1intx_t";
}
if (type & eintx) {
*sign = -1;
return "ASN1intx_t";
}
MyAbort();
/*NOTREACHED*/
return NULL;
}
/* adjust the lower and upper bound according to the value constraints in */
/* the constraints list */
void GetMinMax(AssignmentList_t ass, ValueConstraintList_t constraints,
EndPoint_t *lower, EndPoint_t *upper)
{
ValueConstraint_t *vc;
EndPoint_t lo, up;
for (vc = constraints; vc; vc = vc->Next) {
lo = vc->Lower;
up = vc->Upper;
if (CmpLowerEndPoint(ass, lower, &lo) > 0)
*lower = lo;
if (CmpUpperEndPoint(ass, upper, &up) < 0)
*upper = up;
}
}
/* get the integer type and the sign of an integer with the given bounds */
char *GetIntType(AssignmentList_t ass, EndPoint_t *lower, EndPoint_t *upper, int32_t *sign)
{
char *inttype;
if (!(lower->Flags & eEndPoint_Min) &&
!(upper->Flags & eEndPoint_Max)) {
inttype = GetIType(&GetValue(ass, lower->Value)->U.Integer.Value,
&GetValue(ass, upper->Value)->U.Integer.Value, sign);
} else {
if (!(lower->Flags & eEndPoint_Min) &&
intx_cmp(&GetValue(ass, lower->Value)->U.Integer.Value, &intx_0) >= 0) {
inttype = UIntegerRestriction;
*sign = 1;
} else {
inttype = IntegerRestriction;
*sign = -1;
}
if (!strncmp(inttype, "ASN1uint", 8))
*sign = 1;
else if (!strncmp(inttype, "ASN1int", 7))
*sign = -1;
}
return inttype;
}
/* get the integer type and the sign of an integer type */
char *GetIntegerType(AssignmentList_t ass, Type_t *type, int32_t *sign)
{
EndPoint_t lower, upper;
if (type->PrivateDirectives.fIntx)
{
return "ASN1intx_t";
}
lower.Flags = eEndPoint_Max;
upper.Flags = eEndPoint_Min;
GetMinMax(ass, type->PERConstraints.Value.Root, &lower, &upper);
if (type->PERConstraints.Value.Type == eExtension_Extended)
GetMinMax(ass, type->PERConstraints.Value.Additional,
&lower, &upper);
if (lower.Flags & eEndPoint_Max)
lower.Flags = eEndPoint_Min;
if (upper.Flags & eEndPoint_Min)
upper.Flags = eEndPoint_Max;
return GetIntType(ass, &lower, &upper, sign);
}
/* get the real type */
/*ARGSUSED*/
char *GetRealType(Type_t *type)
{
return RealRestriction;
}
/* get the boolean type */
char *GetBooleanType()
{
return "ASN1bool_t";
}
/* get the enumerated type */
char *GetEnumeratedType(AssignmentList_t ass, Type_t *type, int32_t *sign)
{
#if 1 // added by Microsoft
return "ASN1enum_t";
#else
EndPoint_t lower, upper, ep;
NamedNumber_t *namedNumbers;
lower.Flags = eEndPoint_Max;
upper.Flags = eEndPoint_Min;
ep.Flags = 0;
for (namedNumbers = type->U.Enumerated.NamedNumbers; namedNumbers;
namedNumbers = namedNumbers->Next) {
switch (namedNumbers->Type) {
case eNamedNumber_Normal:
ep.Value = namedNumbers->U.Normal.Value;
if (CmpLowerEndPoint(ass, &lower, &ep) > 0)
lower = ep;
if (CmpUpperEndPoint(ass, &upper, &ep) < 0)
upper = ep;
break;
case eNamedNumber_ExtensionMarker:
break;
}
}
if (lower.Flags & eEndPoint_Max)
lower.Flags = eEndPoint_Min;
if (upper.Flags & eEndPoint_Min)
upper.Flags = eEndPoint_Max;
return GetIntType(ass, &lower, &upper, sign);
#endif
}
/* get the type of an choice selector */
char *GetChoiceType(Type_t *type)
{
#if 1 // added by Microsoft
return "ASN1choice_t";
#else
uint32_t nchoice;
Component_t *components;
nchoice = 0;
for (components = type->U.Choice.Components; components;
components = components->Next) {
switch (components->Type) {
case eComponent_Normal:
nchoice++;
break;
case eComponent_ExtensionMarker:
nchoice++; /* one reserved value for unknown extensions */
break;
default:
MyAbort();
}
}
if (nchoice < 0x100)
return "ASN1uint8_t";
if (nchoice < 0x10000)
return "ASN1uint16_t";
return "ASN1uint32_t";
#endif
}
/* get the type of a string */
char *GetStringType(AssignmentList_t ass, Type_t *type, int32_t *noctets, uint32_t *zero)
{
EndPoint_t lower, upper;
uint32_t up;
type = GetType(ass, type);
*zero = type->PrivateDirectives.fLenPtr ? 0 : 1; // null terminator
/* get the upper bound and zero flag of the type */
switch (type->Type) {
case eType_NumericString:
up = 0x39;
break;
case eType_PrintableString:
up = 0x7a;
break;
case eType_ISO646String:
case eType_VisibleString:
up = 0x7e;
break;
case eType_IA5String:
up = 0x7f;
// *zero = 0;
break;
case eType_UTF8String:
up = 0xffff;
break;
case eType_BMPString:
up = 0xffff;
*zero = 0; // must be unbounded
break;
case eType_UniversalString:
up = 0xffffffff;
*zero = 0; // must be unbounded
break;
case eType_GeneralString:
case eType_GraphicString:
up = 0xff;
break;
case eType_TeletexString:
up = 0xff;
break;
case eType_T61String:
up = 0xff;
break;
case eType_VideotexString:
up = 0xff;
break;
default:
MyAbort();
/*NOTREACHED*/
}
lower.Flags = eEndPoint_Max;
upper.Flags = 0;
upper.Value = NewValue(NULL, NewType(eType_RestrictedString));
upper.Value->U.RestrictedString.Value.length = 1;
upper.Value->U.RestrictedString.Value.value = &up;
/* apply permitted alphabet constraints */
if (type->PERConstraints.PermittedAlphabet.Type !=
eExtension_Unconstrained) {
GetMinMax(ass, type->PERConstraints.PermittedAlphabet.Root,
&lower, &upper);
if (type->PERConstraints.PermittedAlphabet.Type == eExtension_Extended)
GetMinMax(ass, type->PERConstraints.PermittedAlphabet.Additional,
&lower, &upper);
}
/* set zero flag if the resulting type rejects the 0-character */
if (!(lower.Flags & eEndPoint_Max) &&
*GetValue(ass, lower.Value)->U.RestrictedString.Value.value > 0)
*zero = 1;
/* get the number of octets needed for a character */
*noctets = uint32_uoctets(
*GetValue(ass, upper.Value)->U.RestrictedString.Value.value);
/* if the type is marked as zero-terminated or length/value, use the */
/* appropriate type */
if (GetTypeRules(ass, type) & eTypeRules_ZeroTerminated)
*zero = 1;
else if (GetTypeRules(ass, type) & (eTypeRules_LengthPointer|eTypeRules_FixedArray))
*zero = 0;
/* return the correct type */
if (*zero) {
if (*noctets == 1)
{
#ifdef ENABLE_CHAR_STR_SIZE
if (g_eEncodingRule == eEncoding_Packed &&
type->PERTypeInfo.Root.LConstraint == ePERSTIConstraint_Constrained)
{
return "ASN1char_t";
}
else
{
return "ASN1ztcharstring_t";
}
#else
return "ASN1ztcharstring_t";
#endif
}
if (*noctets == 2)
return "ASN1ztchar16string_t";
*noctets = 4;
return "ASN1ztchar32string_t";
} else {
if (*noctets == 1)
return "ASN1charstring_t";
if (*noctets == 2)
return "ASN1char16string_t";
*noctets = 4;
return "ASN1char32string_t";
}
}
/* check if a type is a restricted string type */
int IsRestrictedString(Type_e type)
{
return
type == eType_NumericString ||
type == eType_PrintableString ||
type == eType_TeletexString ||
type == eType_T61String ||
type == eType_VideotexString ||
type == eType_IA5String ||
type == eType_GraphicString ||
type == eType_VisibleString ||
type == eType_ISO646String ||
type == eType_GeneralString ||
type == eType_UniversalString ||
type == eType_BMPString ||
type == eType_RestrictedString;
}
/* create a reference to a value */
char *Reference(char *p)
{
char *q;
if (*p == '*')
return p + 1;
q = (char *)malloc(strlen(p) + 2);
*q = '&';
strcpy(q + 1, p);
return q;
}
/* create a dereference to a value */
char *Dereference(char *p)
{
char *q;
if (*p == '&')
return p + 1;
q = (char *)malloc(strlen(p) + 2);
*q = '*';
strcpy(q + 1, p);
return q;
}
/* get the name of a type */
char *GetTypeName(AssignmentList_t ass, Type_t *t)
{
Assignment_t *a;
int32_t noctets;
uint32_t zero;
int32_t sign;
char buf[256];
char *p;
switch (t->Type) {
case eType_Boolean:
return GetBooleanType();
case eType_Integer:
return GetIntegerType(ass, t, &sign);
case eType_BitString:
return "ASN1bitstring_t";
case eType_OctetString:
return "ASN1octetstring_t";
case eType_UTF8String:
return "ASN1wstring_t";
case eType_Null:
MyAbort();
/*NOTREACHED*/
case eType_ObjectIdentifier:
if (t->PrivateDirectives.fOidPacked)
{
return "ASN1encodedOID_t";
}
return t->PrivateDirectives.fOidArray ? "ASN1objectidentifier2_t" : "ASN1objectidentifier_t";
case eType_Real:
return GetRealType(t);
case eType_Enumerated:
return GetEnumeratedType(ass, t, &sign);
case eType_EmbeddedPdv:
return "ASN1embeddedpdv_t";
case eType_Sequence:
case eType_SequenceOf:
case eType_Set:
case eType_SetOf:
case eType_Choice:
case eType_InstanceOf:
MyAbort();
/*NOTREACHED*/
case eType_NumericString:
case eType_PrintableString:
case eType_VisibleString:
case eType_ISO646String:
case eType_GraphicString:
case eType_GeneralString:
case eType_IA5String:
case eType_UniversalString:
case eType_BMPString:
case eType_TeletexString:
case eType_T61String:
case eType_VideotexString:
return GetStringType(ass, t, &noctets, &zero);
case eType_UTCTime:
return "ASN1utctime_t";
case eType_GeneralizedTime:
return "ASN1generalizedtime_t";
case eType_ObjectDescriptor:
return "ASN1objectdescriptor_t";
case eType_External:
return "ASN1external_t";
case eType_CharacterString:
return "ASN1characterstring_t";
/*NOTREACHED*/
case eType_Selection:
MyAbort();
/*NOTREACHED*/
case eType_Reference:
a = FindAssignment(ass, eAssignment_Type,
t->U.Reference.Identifier, t->U.Reference.Module);
return GetName(a);
case eType_FieldReference:
p = GetObjectClassName(ass, t->U.FieldReference.ObjectClass);
sprintf(buf, "%s_%s", p, t->U.FieldReference.Identifier);
return Identifier2C(buf);
case eType_RestrictedString:
MyAbort();
/*NOTREACHED*/
case eType_Open:
return "ASN1open_t";
case eType_Undefined:
MyAbort();
/*NOTREACHED*/
}
/*NOTREACHED*/
return NULL;
}
/* get the name of a type */
char *PGetTypeName(AssignmentList_t ass, Type_t *t)
{
Assignment_t *a;
if (t->Type == eType_Reference)
{
a = FindAssignment(ass, eAssignment_Type,
t->U.Reference.Identifier, t->U.Reference.Module);
return IsPSetOfType(ass, a) ? PGetName(ass, a) : GetName(a);
}
return GetTypeName(ass, t);
}
/* get the name of a value */
char *GetValueName(AssignmentList_t ass, Value_t *value)
{
Assignment_t *a;
if (value->Type)
MyAbort();
a = FindAssignment(ass, eAssignment_Value,
value->U.Reference.Identifier, value->U.Reference.Module);
return GetName(a);
}
/* get the name of an object class */
char *GetObjectClassName(AssignmentList_t ass, ObjectClass_t *oc)
{
Assignment_t *a;
switch (oc->Type) {
case eObjectClass_Reference:
a = FindAssignment(ass, eAssignment_ObjectClass,
oc->U.Reference.Identifier, oc->U.Reference.Module);
return GetName(a);
default:
MyAbort();
/*NOTREACHED*/
}
return NULL;
}
/* check if a type is of structured type */
int IsStructuredType(Type_t *type)
{
switch (type->Type) {
case eType_Sequence:
case eType_SequenceOf:
case eType_Set:
case eType_SetOf:
case eType_Choice:
case eType_InstanceOf:
return 1;
default:
return 0;
}
}
/* check if a type is of sequence type */
int IsSequenceType(Type_t *type)
{
switch (type->Type) {
case eType_Sequence:
case eType_Set:
case eType_Choice:
case eType_Real:
case eType_External:
case eType_EmbeddedPdv:
case eType_CharacterString:
case eType_InstanceOf:
return 1;
default:
return 0;
}
}
/* check if a type is a reference type */
int IsReferenceType(Type_t *type)
{
switch (type->Type) {
case eType_Reference:
case eType_FieldReference:
return 1;
default:
return 0;
}
}
/* get the tag of a type */
Tag_t *GetTag(AssignmentList_t ass, Type_t *type)
{
Type_t *type2;
for (;;) {
if (type->Tags || !IsReferenceType(type))
return type->Tags;
type2 = GetReferencedType(ass, type);
/*XXX self-referencing types will idle forever */
if (type == type2)
{
ASSERT(0);
return NULL;
}
type = type2;
}
/*NOTREACHED*/
}
/* get the number of octets of a C type */
int32_t GetOctets(char *inttype)
{
if (!strcmp(inttype, "ASN1uint8_t"))
return sizeof(ASN1uint8_t);
if (!strcmp(inttype, "ASN1uint16_t"))
return sizeof(ASN1uint16_t);
if (!strcmp(inttype, "ASN1uint32_t"))
return sizeof(ASN1uint32_t);
if (!strcmp(inttype, "ASN1uint64_t"))
return 8;
if (!strcmp(inttype, "ASN1int8_t"))
return sizeof(ASN1int8_t);
if (!strcmp(inttype, "ASN1int16_t"))
return sizeof(ASN1int16_t);
if (!strcmp(inttype, "ASN1int32_t"))
return sizeof(ASN1int32_t);
if (!strcmp(inttype, "ASN1int64_t"))
return 8;
if (!strcmp(inttype, "ASN1intx_t"))
return 0;
if (!strcmp(inttype, "ASN1bool_t"))
return sizeof(ASN1bool_t);
if (!strcmp(inttype, "ASN1char_t"))
return sizeof(ASN1char_t);
if (!strcmp(inttype, "ASN1char16_t"))
return sizeof(ASN1char16_t);
if (!strcmp(inttype, "ASN1char32_t"))
return sizeof(ASN1char32_t);
if (!strcmp(inttype, "double"))
return 8;
if (!strcmp(inttype, "ASN1real_t"))
return 0;
// added by Microsoft
if (!strcmp(inttype, "ASN1enum_t"))
return sizeof(ASN1enum_t);
if (!strcmp(inttype, "ASN1choice_t"))
return sizeof(ASN1choice_t);
MyAbort();
/*NOTREACHED*/
return 0;
}
/* compare two values; return 0 if equal */
int CmpValue(AssignmentList_t ass, Value_t *v1, Value_t *v2)
{
uint32_t i;
int32_t d;
Type_e t1, t2;
v1 = GetValue(ass, v1);
v2 = GetValue(ass, v2);
t1 = GetTypeType(ass, v1->Type);
t2 = GetTypeType(ass, v2->Type);
if (t1 == eType_Integer && t2 == eType_Integer) {
return intx_cmp(&v1->U.Integer.Value, &v2->U.Integer.Value);
}
if (t1 == eType_ObjectIdentifier && t2 == eType_ObjectIdentifier) {
d = v1->U.ObjectIdentifier.Value.length -
v2->U.ObjectIdentifier.Value.length;
if (d)
return d;
for (i = 0; i < v1->U.ObjectIdentifier.Value.length; i++) {
d = v1->U.ObjectIdentifier.Value.value[i] -
v2->U.ObjectIdentifier.Value.value[i];
if (d)
return d;
}
return 0;
}
if (IsRestrictedString(t1) && IsRestrictedString(t2)) {
if (v1->U.RestrictedString.Value.length != 1 ||
v2->U.RestrictedString.Value.length != 1)
MyAbort();
if (*v1->U.RestrictedString.Value.value <
*v2->U.RestrictedString.Value.value)
return -1;
if (*v1->U.RestrictedString.Value.value >
*v2->U.RestrictedString.Value.value)
return 1;
return 0;
}
MyAbort();
/*NOTREACHED*/
return 1; // not equal
}
/* substract two values (integer/character) */
int SubstractValues(AssignmentList_t ass, intx_t *diff, Value_t *v1, Value_t *v2)
{
v1 = GetValue(ass, v1);
v2 = GetValue(ass, v2);
switch (GetTypeType(ass, v1->Type)) {
case eType_Integer:
intx_sub(diff, &v1->U.Integer.Value, &v2->U.Integer.Value);
return 1;
default:
if (IsRestrictedString(GetTypeType(ass, v1->Type))) {
if (v1->U.RestrictedString.Value.length != 1 ||
v2->U.RestrictedString.Value.length != 1)
return 0;
intx_setuint32(diff, v2->U.RestrictedString.Value.value[0] -
v1->U.RestrictedString.Value.value[0]);
return 1;
}
break;
}
MyAbort();
/*NOTREACHED*/
return 0;
}
/* get the lower endpoint; adjust endpoint if the endpoint is "open" */
/* (means "not including the value") */
EndPoint_t *GetLowerEndPoint(AssignmentList_t ass, EndPoint_t *e)
{
EndPoint_t *newe;
Type_t *type;
if ((e->Flags & eEndPoint_Min) || !(e->Flags & eEndPoint_Open))
return e;
type = GetType(ass, GetValue(ass, e->Value)->Type);
switch (type->Type) {
case eType_Integer:
newe = NewEndPoint();
newe->Value = NewValue(ass, type);
intx_add(&newe->Value->U.Integer.Value, &e->Value->U.Integer.Value,
&intx_1);
return newe;
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:
newe = NewEndPoint();
newe->Value = NewValue(ass, type);
newe->Value->U.RestrictedString.Value.length = 1;
newe->Value->U.RestrictedString.Value.value =
(char32_t *)malloc(sizeof(char32_t));
*newe->Value->U.RestrictedString.Value.value =
*e->Value->U.RestrictedString.Value.value + 1;
return newe;
default:
return e;
}
}
/* get the upper endpoint; adjust endpoint if the endpoint is "open" */
/* (means "not including the value") */
EndPoint_t *GetUpperEndPoint(AssignmentList_t ass, EndPoint_t *e)
{
EndPoint_t *newe;
Type_t *type;
if ((e->Flags & eEndPoint_Max) || !(e->Flags & eEndPoint_Open))
return e;
type = GetType(ass, GetValue(ass, e->Value)->Type);
switch (type->Type) {
case eType_Integer:
newe = NewEndPoint();
newe->Value = NewValue(ass, type);
intx_sub(&newe->Value->U.Integer.Value, &e->Value->U.Integer.Value,
&intx_1);
return newe;
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:
newe = NewEndPoint();
newe->Value = NewValue(ass, type);
newe->Value->U.RestrictedString.Value.length = 1;
newe->Value->U.RestrictedString.Value.value =
(char32_t *)malloc(sizeof(char32_t));
*newe->Value->U.RestrictedString.Value.value =
*e->Value->U.RestrictedString.Value.value - 1;
return newe;
default:
return e;
}
}
/* compare two lower endpoints */
int CmpLowerEndPoint(AssignmentList_t ass, EndPoint_t *e1, EndPoint_t *e2)
{
int ret;
e1 = GetLowerEndPoint(ass, e1);
e2 = GetLowerEndPoint(ass, e2);
if (e1->Flags & eEndPoint_Min) {
if (e2->Flags & eEndPoint_Min)
return 0;
return -1;
} else if (e2->Flags & eEndPoint_Min) {
return 1;
} else if (e1->Flags & eEndPoint_Max) {
if (e2->Flags & eEndPoint_Max)
return 0;
return 1;
} else if (e2->Flags & eEndPoint_Max) {
return -1;
} else {
ret = CmpValue(ass, e1->Value, e2->Value);
if (ret != 0)
return ret;
if (e1->Flags & eEndPoint_Open) {
if (e2->Flags & eEndPoint_Open)
return 0;
else
return 1;
} else {
if (e2->Flags & eEndPoint_Open)
return -1;
else
return 0;
}
}
}
/* compare two upper endpoints */
int CmpUpperEndPoint(AssignmentList_t ass, EndPoint_t *e1, EndPoint_t *e2)
{
int ret;
e1 = GetUpperEndPoint(ass, e1);
e2 = GetUpperEndPoint(ass, e2);
if (e1->Flags & eEndPoint_Min) {
if (e2->Flags & eEndPoint_Min)
return 0;
return -1;
} else if (e2->Flags & eEndPoint_Min) {
return 1;
} else if (e1->Flags & eEndPoint_Max) {
if (e2->Flags & eEndPoint_Max)
return 0;
return 1;
} else if (e2->Flags & eEndPoint_Max) {
return -1;
} else {
ret = CmpValue(ass, e1->Value, e2->Value);
if (ret != 0)
return ret;
if (e1->Flags & eEndPoint_Open) {
if (e2->Flags & eEndPoint_Open)
return 0;
else
return -1;
} else {
if (e2->Flags & eEndPoint_Open)
return 1;
else
return 0;
}
}
}
/* compare a lower and an upper endpoints */
int CmpLowerUpperEndPoint(AssignmentList_t ass, EndPoint_t *e1, EndPoint_t *e2)
{
int ret;
e1 = GetLowerEndPoint(ass, e1);
e2 = GetUpperEndPoint(ass, e2);
if (e1->Flags & eEndPoint_Min) {
if (e2->Flags & eEndPoint_Min)
return 0;
return -1;
} else if (e2->Flags & eEndPoint_Min) {
return 1;
} else if (e1->Flags & eEndPoint_Max) {
if (e2->Flags & eEndPoint_Max)
return 0;
return 1;
} else if (e2->Flags & eEndPoint_Max) {
return -1;
} else {
ret = CmpValue(ass, e1->Value, e2->Value);
if (ret != 0)
return ret;
if ((e1->Flags & eEndPoint_Open) || (e2->Flags & eEndPoint_Open))
return 1;
else
return 0;
}
}
/* check whether two EndPoint_t's join together */
int CheckEndPointsJoin(AssignmentList_t ass, EndPoint_t *e1, EndPoint_t *e2)
{
intx_t ix;
Value_t *v1, *v2;
/* check if endpoints overlap */
if (CmpLowerUpperEndPoint(ass, e2, e1) <= 0)
return 1;
e1 = GetUpperEndPoint(ass, e1);
e2 = GetLowerEndPoint(ass, e2);
v1 = GetValue(ass, e1->Value);
v2 = GetValue(ass, e2->Value);
switch (GetTypeType(ass, v1->Type)) {
case eType_Integer:
/* check for subsequent integers */
intx_dup(&ix, &v1->U.Integer.Value);
intx_inc(&ix);
return intx_cmp(&ix, &v2->U.Integer.Value) >= 0;
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:
/* reject multiple characters */
if (v1->U.RestrictedString.Value.length != 1 ||
v2->U.RestrictedString.Value.length != 1)
MyAbort();
/* beware of wrap around */
if (v1->U.RestrictedString.Value.value[0] == 0xffffffff &&
v2->U.RestrictedString.Value.value[0] == 0)
return 0;
/* check for subsequent characters */
return v2->U.RestrictedString.Value.value[0] -
v1->U.RestrictedString.Value.value[0] == 1;
}
MyAbort();
/*NOTREACHED*/
return 0;
}
/* compare two module identifiers; return 0 if equal */
int CmpModuleIdentifier(AssignmentList_t ass, ModuleIdentifier_t *mod1, ModuleIdentifier_t *mod2)
{
if (mod1->ObjectIdentifier && mod2->ObjectIdentifier)
return CmpValue(ass, mod1->ObjectIdentifier, mod2->ObjectIdentifier);
if (mod1->Identifier && mod2->Identifier)
return strcmp(mod1->Identifier, mod2->Identifier);
return 0;
}
/* get the name of an assignment */
char *GetNameEx(AssignmentList_t ass, AssignmentList_t a, int fPSetOf)
{
char *p;
char *ide;
char *mod;
if (a->Type == eAssignment_Type &&
a->U.Type.Type && a->U.Type.Type->PrivateDirectives.pszTypeName)
{
if (fPSetOf && IsPSetOfType(ass, a))
{
ide = PIdentifier2C(a->U.Type.Type->PrivateDirectives.pszTypeName);
}
else
{
ide = Identifier2C(a->U.Type.Type->PrivateDirectives.pszTypeName);
}
}
else
{
if (fPSetOf && IsPSetOfType(ass, a))
{
ide = PIdentifier2C(a->Identifier);
}
else
{
ide = Identifier2C(a->Identifier);
}
}
// LONCHANC: disable the following code per MikeV.
if (g_fLongNameForImported)
{
if (!(a->Flags & eAssignmentFlags_LongName))
return ide;
mod = Identifier2C(a->Module->Identifier);
p = (char *)malloc(strlen(mod) + strlen(ide) + 2);
sprintf(p, "%s_%s", mod, ide);
return p;
}
else
{
return ide;
}
}
/* get the name of an assignment */
char *GetName(AssignmentList_t a)
{
return GetNameEx(NULL, a, 0);
}
char *PGetName(AssignmentList_t ass, AssignmentList_t a)
{
return GetNameEx(ass, a, 1);
}
/* convert a 32 bit string into a generalized time */
int String2GeneralizedTime(generalizedtime_t *time, char32string_t *string)
{
char str[64];
unsigned i;
if (string->length > 63 || string->length < 10)
return 0;
for (i = 0; i < string->length; i++)
str[i] = (char)string->value[i];
str[i] = 0;
return string2generalizedtime(time, str);
}
/* convert a 32 bit string into an utc time */
int String2UTCTime(utctime_t *time, char32string_t *string)
{
char str[64];
unsigned i;
if (string->length > 63 || string->length < 10)
return 0;
for (i = 0; i < string->length; i++)
str[i] = (char)string->value[i];
str[i] = 0;
return string2utctime(time, str);
}
/* build an intersection of two constraints */
void IntersectConstraints(Constraint_t **ret, Constraint_t *c1, Constraint_t *c2)
{
ElementSetSpec_t *e;
if (!c2) {
*ret = c1;
return;
}
if (!c1) {
*ret = c2;
return;
}
*ret = NewConstraint();
if (!c1->Root) {
(*ret)->Root = c2->Root;
} else if (!c2->Root) {
(*ret)->Root = c1->Root;
} else {
(*ret)->Root = e = NewElementSetSpec(eElementSetSpec_Intersection);
e->U.Intersection.Elements1 = c1->Root;
e->U.Intersection.Elements2 = c2->Root;
}
if (c1->Type > c2->Type)
(*ret)->Type = c1->Type;
else
(*ret)->Type = c2->Type;
if ((*ret)->Type == eExtension_Extended) {
if (c1->Type != eExtension_Extended || !c1->Additional) {
(*ret)->Additional = c2->Additional;
} else if (c2->Type != eExtension_Extended || !c2->Additional) {
(*ret)->Additional = c1->Additional;
} else {
(*ret)->Additional = e =
NewElementSetSpec(eElementSetSpec_Intersection);
e->U.Intersection.Elements1 = c1->Additional;
e->U.Intersection.Elements2 = c2->Additional;
}
}
}
/* find a field spec by name of an object class */
FieldSpec_t *GetObjectClassField(AssignmentList_t ass, ObjectClass_t *oc, char *field)
{
oc = GetObjectClass(ass, oc);
if (!oc)
return NULL;
return GetFieldSpec(ass, FindFieldSpec(oc->U.ObjectClass.FieldSpec, field));
}
/* find a field spec by name list of an object class */
FieldSpec_t *GetFieldSpecFromObjectClass(AssignmentList_t ass, ObjectClass_t *oc, StringList_t sl)
{
FieldSpec_t *fs;
for (; sl; sl = sl->Next) {
fs = GetObjectClassField(ass, oc, sl->String);
if (!fs)
return NULL;
if (!sl->Next)
return fs;
if (fs->Type == eFieldSpec_Object)
oc = fs->U.Object.ObjectClass;
else if (fs->Type == eFieldSpec_ObjectSet)
oc = fs->U.ObjectSet.ObjectClass;
else
return NULL;
}
return NULL;
}
/* get the default setting of a field spec */
static Setting_t *GetDefaultSetting(FieldSpec_t *fs)
{
Setting_t *ret = NULL;
Optionality_t *op;
switch (fs->Type) {
case eFieldSpec_Type:
op = fs->U.Type.Optionality;
if (op && op->Type == eOptionality_Default_Type) {
ret = NewSetting(eSetting_Type);
ret->Identifier = fs->Identifier;
ret->U.Type.Type = op->U.Type;
}
break;
case eFieldSpec_FixedTypeValue:
op = fs->U.FixedTypeValue.Optionality;
if (op && op->Type == eOptionality_Default_Value) {
ret = NewSetting(eSetting_Value);
ret->Identifier = fs->Identifier;
ret->U.Value.Value = op->U.Value;
}
break;
case eFieldSpec_VariableTypeValue:
op = fs->U.VariableTypeValue.Optionality;
if (op && op->Type == eOptionality_Default_Value) {
ret = NewSetting(eSetting_Value);
ret->Identifier = fs->Identifier;
ret->U.Value.Value = op->U.Value;
}
break;
case eFieldSpec_FixedTypeValueSet:
op = fs->U.FixedTypeValueSet.Optionality;
if (op && op->Type == eOptionality_Default_ValueSet) {
ret = NewSetting(eSetting_ValueSet);
ret->Identifier = fs->Identifier;
ret->U.ValueSet.ValueSet = op->U.ValueSet;
}
break;
case eFieldSpec_VariableTypeValueSet:
op = fs->U.VariableTypeValueSet.Optionality;
if (op && op->Type == eOptionality_Default_ValueSet) {
ret = NewSetting(eSetting_ValueSet);
ret->Identifier = fs->Identifier;
ret->U.ValueSet.ValueSet = op->U.ValueSet;
}
break;
case eFieldSpec_Object:
op = fs->U.Object.Optionality;
if (op && op->Type == eOptionality_Default_Object) {
ret = NewSetting(eSetting_Object);
ret->Identifier = fs->Identifier;
ret->U.Object.Object = op->U.Object;
}
break;
case eFieldSpec_ObjectSet:
op = fs->U.Object.Optionality;
if (op && op->Type == eOptionality_Default_ObjectSet) {
ret = NewSetting(eSetting_ObjectSet);
ret->Identifier = fs->Identifier;
ret->U.ObjectSet.ObjectSet = op->U.ObjectSet;
}
break;
default:
return NULL;
}
return ret;
}
Setting_t *GetSettingFromSettings(AssignmentList_t ass, SettingList_t se, StringList_t sl)
{
Object_t *o;
for (; sl; sl = sl->Next) {
for (; se; se = se->Next) {
if (!strcmp(se->Identifier, sl->String))
break;
}
if (!se)
return NULL;
if (!sl->Next)
return se;
if (se->Type != eSetting_Object)
return NULL;
o = GetObject(ass, se->U.Object.Object);
if (!o)
return NULL;
se = o->U.Object.Settings;
}
return NULL;
}
Setting_t *GetSettingFromObject(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
FieldSpec_t *fs;
Setting_t *se;
ObjectClass_t *oc;
for (; sl; sl = sl->Next) {
o = GetObject(ass, o);
if (!o)
return NULL;
oc = GetObjectClass(ass, o->U.Object.ObjectClass);
if (!oc)
return NULL;
fs = GetFieldSpec(ass,
FindFieldSpec(oc->U.ObjectClass.FieldSpec, sl->String));
if (!fs)
return NULL;
se = FindSetting(o->U.Object.Settings, sl->String);
if (!se) {
se = GetDefaultSetting(fs);
if (!se)
return NULL;
}
if (!sl->Next)
return se;
if (fs->Type == eFieldSpec_Object && se->Type == eSetting_Object) {
o = se->U.Object.Object;
} else {
return NULL;
}
}
return NULL;
}
ObjectClass_t *GetObjectClassFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elems)
{
ObjectSetElement_t *ose;
Object_t *o;
ObjectSet_t *os;
switch (elems->Type) {
case eElementSetSpec_AllExcept:
return GetObjectClassFromElementSetSpec(ass,
elems->U.AllExcept.Elements);
case eElementSetSpec_Union:
case eElementSetSpec_Intersection:
case eElementSetSpec_Exclusion:
return GetObjectClassFromElementSetSpec(ass,
elems->U.UIE.Elements1);
case eElementSetSpec_SubtypeElement:
MyAbort();
/*NOTREACHED*/
case eElementSetSpec_ObjectSetElement:
ose = elems->U.ObjectSetElement.ObjectSetElement;
switch (ose->Type) {
case eObjectSetElement_Object:
o = ose->U.Object.Object;
o = GetObject(ass, o);
if (!o)
return NULL;
return o->U.Object.ObjectClass;
case eObjectSetElement_ObjectSet:
os = ose->U.ObjectSet.ObjectSet;
os = GetObjectSet(ass, os);
if (!os)
return NULL;
return os->U.ObjectSet.ObjectClass;
case eObjectSetElement_ElementSetSpec:
return GetObjectClassFromElementSetSpec(ass,
ose->U.ElementSetSpec.ElementSetSpec);
}
/*NOTREACHED*/
}
/*NOTREACHED*/
return NULL;
}
#if 0
Type_t *GetTypeFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elems)
{
Type_t *ret;
SubtypeElement_t *sub;
Value_t *value;
switch (elems->Type) {
case eElementSetSpec_AllExcept:
return GetTypeFromElementSetSpec(ass,
elems->U.AllExcept.Elements);
case eElementSetSpec_Union:
case eElementSetSpec_Intersection:
case eElementSetSpec_Exclusion:
ret = GetTypeFromElementSetSpec(ass, elems->U.UIE.Elements1);
if (ret)
return ret;
return GetTypeFromElementSetSpec(ass, elems->U.UIE.Elements2);
case eElementSetSpec_SubtypeElement:
sub = elems->U.SubtypeElement.SubtypeElement;
switch (sub->Type) {
case eSubtypeElement_Size:
case eSubtypeElement_PermittedAlphabet:
case eSubtypeElement_SingleType:
case eSubtypeElement_FullSpecification:
case eSubtypeElement_PartialSpecification:
return NULL;
case eSubtypeElement_Type:
return Builtin_Type_Open;
case eSubtypeElement_ContainedSubtype:
return sub->U.ContainedSubtype.Type;
case eSubtypeElement_SingleValue:
value = GetValue(ass, sub->U.SingleValue.Value);
return value->Type;
case eSubtypeElement_ValueRange:
if (!(sub->U.ValueRange.Lower.Flags & eEndPoint_Min)) {
value = GetValue(ass, sub->U.ValueRange.Lower.Value);
return value->Type;
}
if (!(sub->U.ValueRange.Upper.Flags & eEndPoint_Max)) {
value = GetValue(ass, sub->U.ValueRange.Upper.Value);
return value->Type;
}
return NULL;
case eSubtypeElement_ElementSetSpec:
return GetTypeFromElementSetSpec(ass,
sub->U.ElementSetSpec.ElementSetSpec);
}
/*NOTREACHED*/
case eElementSetSpec_ObjectSetElement:
MyAbort();
/*NOTREACHED*/
}
/*NOTREACHED*/
}
#endif
Type_t *GetTypeOfValueSet(AssignmentList_t ass, ValueSet_t *vs)
{
Type_t *ret;
Constraint_t *c;
if (!vs)
return NULL;
ret = DupType(vs->Type);
c = NewConstraint();
c->Type = eExtension_Unextended;
c->Root = vs->Elements;
IntersectConstraints(&ret->Constraints, vs->Type->Constraints, c);
return ret;
}
Value_t *GetValueFromObject(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
Setting_t *se;
se = GetSettingFromObject(ass, o, sl);
if (!se)
return NULL;
if (se->Type != eSetting_Value)
return NULL; /* error */
return se->U.Value.Value;
}
ValueSet_t *GetValueSetFromObject(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
Setting_t *se;
se = GetSettingFromObject(ass, o, sl);
if (!se)
return NULL;
if (se->Type != eSetting_ValueSet)
return NULL; /* error */
return se->U.ValueSet.ValueSet;
}
Type_t *GetTypeFromObject(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
Setting_t *se;
se = GetSettingFromObject(ass, o, sl);
if (!se)
return NULL;
if (se->Type != eSetting_Type)
return NULL; /* error */
return se->U.Type.Type;
}
Object_t *GetObjectFromObject(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
Setting_t *se;
se = GetSettingFromObject(ass, o, sl);
if (!se)
return NULL;
if (se->Type != eSetting_Object)
return NULL; /* error */
return se->U.Object.Object;
}
ObjectSet_t *GetObjectSetFromObject(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
Setting_t *se;
se = GetSettingFromObject(ass, o, sl);
if (!se)
return NULL;
if (se->Type != eSetting_ObjectSet)
return NULL; /* error */
return se->U.ObjectSet.ObjectSet;
}
ElementSetSpec_t *ConvertElementSetSpecToElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elems, StringList_t sl, ElementSetSpec_t *(*fn)(AssignmentList_t ass, Object_t *o, StringList_t sl))
{
ElementSetSpec_t *ret, *e1, *e2;
ObjectSetElement_t *ose;
ret = NULL;
switch (elems->Type) {
case eElementSetSpec_AllExcept:
e1 = ConvertElementSetSpecToElementSetSpec(
ass, elems->U.AllExcept.Elements, sl, fn);
if (e1) {
ret = NewElementSetSpec(elems->Type);
ret->U.AllExcept.Elements = e1;
}
break;
case eElementSetSpec_Union:
case eElementSetSpec_Intersection:
case eElementSetSpec_Exclusion:
e1 = ConvertElementSetSpecToElementSetSpec(
ass, elems->U.UIE.Elements1, sl, fn);
e2 = ConvertElementSetSpecToElementSetSpec(
ass, elems->U.UIE.Elements2, sl, fn);
if (e1 && e2) {
ret = NewElementSetSpec(elems->Type);
ret->U.UIE.Elements1 = ConvertElementSetSpecToElementSetSpec(
ass, elems->U.UIE.Elements1, sl, fn);
ret->U.UIE.Elements2 = ConvertElementSetSpecToElementSetSpec(
ass, elems->U.UIE.Elements2, sl, fn);
} else if (e1) {
ret = e1;
} else if (e2) {
if (elems->Type == eElementSetSpec_Exclusion) {
ret = NewElementSetSpec(eElementSetSpec_AllExcept);
ret->U.AllExcept.Elements = e2;
} else {
ret = e2;
}
}
break;
case eElementSetSpec_ObjectSetElement:
ose = elems->U.ObjectSetElement.ObjectSetElement;
switch (ose->Type) {
case eObjectSetElement_Object:
ret = fn(ass, ose->U.Object.Object, sl);
break;
case eObjectSetElement_ObjectSet:
ret = ConvertObjectSetToElementSetSpec(ass,
ose->U.ObjectSet.ObjectSet, sl, fn);
break;
case eObjectSetElement_ElementSetSpec:
ret = ConvertElementSetSpecToElementSetSpec(ass,
ose->U.ElementSetSpec.ElementSetSpec, sl, fn);
break;
}
break;
case eElementSetSpec_SubtypeElement:
MyAbort();
/*NOTREACHED*/
}
return ret;
}
ElementSetSpec_t *ConvertObjectSetToElementSetSpec(AssignmentList_t ass, ObjectSet_t *os, StringList_t sl, ElementSetSpec_t *(*fn)(AssignmentList_t ass, Object_t *o, StringList_t sl))
{
os = GetObjectSet(ass, os);
if (!os)
return NULL;
return ConvertElementSetSpecToElementSetSpec(ass,
os->U.ObjectSet.Elements, sl, fn);
}
static ElementSetSpec_t *CbGetValueSetFromObjectSet(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
ElementSetSpec_t *ret;
Setting_t *se;
SubtypeElement_t *sub;
se = GetSettingFromObject(ass, o, sl);
if (!se)
return NULL;
if (se->Type == eSetting_Value) {
sub = NewSubtypeElement(eSubtypeElement_SingleValue);
sub->U.SingleValue.Value = se->U.Value.Value;
ret = NewElementSetSpec(eElementSetSpec_SubtypeElement);
ret->U.SubtypeElement.SubtypeElement = sub;
return ret;
} else if (se->Type == eSetting_ValueSet) {
return se->U.ValueSet.ValueSet->Elements;
} else {
return NULL; /* error */
}
}
ValueSet_t *GetValueSetFromObjectSet(AssignmentList_t ass, ObjectSet_t *os, StringList_t sl)
{
ElementSetSpec_t *elems;
ValueSet_t *ret;
ObjectClass_t *oc;
FieldSpec_t *fs;
Type_t *type;
os = GetObjectSet(ass, os);
if (!os)
return NULL;
oc = os->U.ObjectSet.ObjectClass;
fs = GetFieldSpecFromObjectClass(ass, oc, sl);
if (!fs)
return NULL;
if (fs->Type == eFieldSpec_FixedTypeValue)
type = fs->U.FixedTypeValue.Type;
else if (fs->Type == eFieldSpec_FixedTypeValueSet)
type = fs->U.FixedTypeValueSet.Type;
else
return NULL;
elems = ConvertObjectSetToElementSetSpec(ass, os, sl,
CbGetValueSetFromObjectSet);
if (!elems)
return NULL;
ret = NewValueSet();
ret->Elements = elems;
ret->Type = type;
return ret;
}
static ElementSetSpec_t *CbGetObjectSetFromObjectSet(AssignmentList_t ass, Object_t *o, StringList_t sl)
{
ElementSetSpec_t *ret;
Setting_t *se;
ObjectSetElement_t *sub;
se = GetSettingFromObject(ass, o, sl);
if (!se)
return NULL;
if (se->Type == eSetting_Object) {
sub = NewObjectSetElement(eObjectSetElement_Object);
sub->U.Object.Object = se->U.Object.Object;
ret = NewElementSetSpec(eElementSetSpec_ObjectSetElement);
ret->U.ObjectSetElement.ObjectSetElement = sub;
return ret;
} else if (se->Type == eSetting_ObjectSet) {
return se->U.ObjectSet.ObjectSet->U.ObjectSet.Elements;
} else {
return NULL; /* error */
}
}
ObjectSet_t *GetObjectSetFromObjectSet(AssignmentList_t ass, ObjectSet_t *os, StringList_t sl)
{
ElementSetSpec_t *elems;
ObjectSet_t *ret;
elems = ConvertObjectSetToElementSetSpec(ass, os, sl,
CbGetObjectSetFromObjectSet);
if (!elems)
return NULL;
ret = NewObjectSet(eObjectSet_ObjectSet);
ret->U.ObjectSet.Elements = elems;
ret->U.ObjectSet.ObjectClass = GetObjectClassFromElementSetSpec(ass, elems);
return ret;
}
// The following is added by Microsoft
int IsPSetOfType(AssignmentList_t ass, Assignment_t *a)
{
Type_t *t2 = a->U.Type.Type;
#if 0
if (t2->Type == eType_Reference)
{
t2 = GetType(ass, t2);
}
#endif
return ((eType_SequenceOf == t2->Type || eType_SetOf == t2->Type)
&&
(t2->Rules & (eTypeRules_LinkedListMask | eTypeRules_PointerToElement))
// (t2->PrivateDirectives.fSLinked)
);
}
void MyAbort(void)
{
ASSERT(0);
abort();
}
void MyExit(int val)
{
ASSERT(0);
exit(val);
}