/* 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); }