/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */ /* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */ #include "precomp.h" #include "util.h" #include "error.h" static void GetAllPERFromConstraints(AssignmentList_t ass, Constraint_t *constraints, Extension_e *evalue, ValueConstraintList_t *valueConstraints, ValueConstraintList_t *evalueConstraints, Extension_e *esize, ValueConstraintList_t *sizeConstraints, ValueConstraintList_t *esizeConstraints, Extension_e *epermittedAlphabet, ValueConstraintList_t *permittedAlphabetConstraints, ValueConstraintList_t *epermittedAlphabetConstraints, int inPermAlpha); static void GetAllPERFromElementSetSpecs(AssignmentList_t ass, ElementSetSpec_t *element, Extension_e *evalue, ValueConstraintList_t *valueConstraints, ValueConstraintList_t *evalueConstraints, Extension_e *esize, ValueConstraintList_t *sizeConstraints, ValueConstraintList_t *esizeConstraints, Extension_e *epermittedAlphabet, ValueConstraintList_t *permittedAlphabetConstraints, ValueConstraintList_t *epermittedAlphabetConstraints, int inPermAlpha); static void GetAllPERFromSubtypeElements(AssignmentList_t ass, SubtypeElement_t *element, Extension_e *evalue, ValueConstraintList_t *valueConstraints, ValueConstraintList_t *evalueConstraints, Extension_e *esize, ValueConstraintList_t *sizeConstraints, ValueConstraintList_t *esizeConstraints, Extension_e *epermittedAlphabet, ValueConstraintList_t *permittedAlphabetConstraints, ValueConstraintList_t *epermittedAlphabetConstraints, int inPermAlpha); static void IntersectValueConstraints(AssignmentList_t ass, ValueConstraintList_t *result, ValueConstraintList_t val1, ValueConstraintList_t val2); static void UniteValueConstraints(ValueConstraintList_t *result, ValueConstraintList_t val1, ValueConstraintList_t val2); static void ExcludeValueConstraints(AssignmentList_t ass, ValueConstraintList_t *result, ValueConstraintList_t val1, ValueConstraintList_t val2); static void NegateValueConstraints(AssignmentList_t ass, ValueConstraintList_t *result, ValueConstraintList_t val); static void IntersectPERConstraints(AssignmentList_t ass, Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1, Extension_e type2, ValueConstraintList_t val2, ValueConstraintList_t eval2); static void UnitePERConstraints(Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1, Extension_e type2, ValueConstraintList_t val2, ValueConstraintList_t eval2); static void NegatePERConstraints(AssignmentList_t ass, Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1); static void ExcludePERConstraints(AssignmentList_t ass, Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1, Extension_e type2, ValueConstraintList_t val2, ValueConstraintList_t eval2); static void ReduceValueConstraints(AssignmentList_t ass, ValueConstraintList_t *valueConstraints); #if 0 ValueConstraint_t *EmptyValueConstraint(); ValueConstraint_t *EmptySizeConstraint(); ValueConstraint_t *EmptyPermittedAlphabetConstraint(); #endif static NamedValue_t *GetFixedIdentificationFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elements); static NamedValue_t *GetFixedAbstractAndTransfer(AssignmentList_t ass, Constraint_t *constraints); static NamedValue_t *GetFixedAbstractAndTransferFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elements); static NamedValue_t *GetFixedSyntaxes(AssignmentList_t ass, Constraint_t *constraints); static NamedValue_t *GetFixedSyntaxesFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elements); /* extract per-visible constraints from a type constraint */ void GetPERConstraints(AssignmentList_t ass, Constraint_t *constraints, PERConstraints_t *per) { GetAllPERFromConstraints(ass, constraints, &per->Value.Type, &per->Value.Root, &per->Value.Additional, &per->Size.Type, &per->Size.Root, &per->Size.Additional, &per->PermittedAlphabet.Type, &per->PermittedAlphabet.Root, &per->PermittedAlphabet.Additional, 0); if (per->Value.Type > eExtension_Unconstrained) ReduceValueConstraints(ass, &per->Value.Root); if (per->Value.Type == eExtension_Extended) ReduceValueConstraints(ass, &per->Value.Additional); if (per->Size.Type > eExtension_Unconstrained) ReduceValueConstraints(ass, &per->Size.Root); if (per->Size.Type == eExtension_Extended) ReduceValueConstraints(ass, &per->Size.Additional); if (per->PermittedAlphabet.Type > eExtension_Unconstrained) ReduceValueConstraints(ass, &per->PermittedAlphabet.Root); /* permitted alphabet extensions are not PER-visible */ if (per->PermittedAlphabet.Type > eExtension_Unextended) per->PermittedAlphabet.Type = eExtension_Unextended; /* we do not support complex value sets for the size */ if (per->Size.Type == eExtension_Extended && per->Size.Root->Next) error(E_constraint_too_complex, NULL); } /* extract per-visible constraints from a type constraint */ static void GetAllPERFromConstraints(AssignmentList_t ass, Constraint_t *constraints, Extension_e *evalue, ValueConstraintList_t *valueConstraints, ValueConstraintList_t *evalueConstraints, Extension_e *esize, ValueConstraintList_t *sizeConstraints, ValueConstraintList_t *esizeConstraints, Extension_e *epermAlpha, ValueConstraintList_t *permAlphaConstraints, ValueConstraintList_t *epermAlphaConstraints, int inPermAlpha) { ValueConstraint_t *vc, *sc, *pc; /* initialize */ if (evalue) *evalue = eExtension_Unconstrained; if (valueConstraints) *valueConstraints = NULL; if (evalueConstraints) *evalueConstraints = NULL; if (esize) *esize = eExtension_Unconstrained; if (sizeConstraints) *sizeConstraints = NULL; if (esizeConstraints) *esizeConstraints = NULL; if (epermAlpha) *epermAlpha = eExtension_Unconstrained; if (permAlphaConstraints) *permAlphaConstraints = NULL; if (epermAlphaConstraints) *epermAlphaConstraints = NULL; vc = sc = pc = NULL; /* examine constraint */ if (constraints) { switch (constraints->Type) { case eExtension_Unextended: /* get constraints of the extension root */ GetAllPERFromElementSetSpecs(ass, constraints->Root, evalue, valueConstraints, evalueConstraints, esize, sizeConstraints, esizeConstraints, epermAlpha, permAlphaConstraints, epermAlphaConstraints, inPermAlpha); break; case eExtension_Extendable: /* get constraints of the extension root */ GetAllPERFromElementSetSpecs(ass, constraints->Root, evalue, valueConstraints, evalueConstraints, esize, sizeConstraints, esizeConstraints, epermAlpha, permAlphaConstraints, epermAlphaConstraints, inPermAlpha); /* mark as extendable */ if (valueConstraints && *valueConstraints && *evalue < eExtension_Extendable) *evalue = eExtension_Extendable; if (sizeConstraints && *sizeConstraints && *esize < eExtension_Extendable) *esize = eExtension_Extendable; if (permAlphaConstraints && *permAlphaConstraints && *epermAlpha < eExtension_Extendable) *epermAlpha = eExtension_Extendable; break; case eExtension_Extended: /* get constraints of the extension root and of the extension */ /* addition and mark them as extended */ GetAllPERFromElementSetSpecs(ass, constraints->Root, evalue, valueConstraints, evalueConstraints, esize, sizeConstraints, esizeConstraints, epermAlpha, permAlphaConstraints, epermAlphaConstraints, inPermAlpha); GetAllPERFromElementSetSpecs(ass, constraints->Additional, NULL, &vc, NULL, NULL, &sc, NULL, NULL, &pc, NULL, inPermAlpha); /* extension additions given twice? */ if ((vc && evalueConstraints && *evalueConstraints) || (sc && esizeConstraints && *esizeConstraints) || (pc && epermAlphaConstraints && *epermAlphaConstraints)) error(E_constraint_too_complex, NULL); /* mark as extended */ if (vc) { *evalueConstraints = vc; *evalue = eExtension_Extended; } if (sc) { *esizeConstraints = sc; *esize = eExtension_Extended; } if (pc) { *epermAlphaConstraints = pc; *epermAlpha = eExtension_Extended; } break; default: MyAbort(); } } } /* get per-visible constraints from an element set spec */ static void GetAllPERFromElementSetSpecs(AssignmentList_t ass, ElementSetSpec_t *element, Extension_e *evalue, ValueConstraintList_t *valueConstraints, ValueConstraintList_t *evalueConstraints, Extension_e *esize, ValueConstraintList_t *sizeConstraints, ValueConstraintList_t *esizeConstraints, Extension_e *epermAlpha, ValueConstraintList_t *permAlphaConstraints, ValueConstraintList_t *epermAlphaConstraints, int inPermAlpha) { ValueConstraint_t *vc1, *vc2, *evc1, *evc2; ValueConstraint_t *sc1, *sc2, *esc1, *esc2; ValueConstraint_t *pc1, *pc2, *epc1, *epc2; Extension_e ev1, ev2, es1, es2, ep1, ep2; /* initialize */ ev1 = ev2 = es1 = es2 = ep1 = ep2 = eExtension_Unconstrained; vc1 = vc2 = evc1 = evc2 = NULL; sc1 = sc2 = esc1 = esc2 = NULL; pc1 = pc2 = epc1 = epc2 = NULL; /* examine element set spec */ switch (element->Type) { case eElementSetSpec_Intersection: /* intersection: get the constraints of the sub-element set specs */ /* and intersect them */ GetAllPERFromElementSetSpecs(ass, element->U.Intersection.Elements1, &ev1, &vc1, &evc1, &es1, &sc1, &esc1, &ep1, &pc1, &epc1, inPermAlpha); GetAllPERFromElementSetSpecs(ass, element->U.Intersection.Elements2, &ev2, &vc2, &evc2, &es2, &sc2, &esc2, &ep2, &pc2, &epc2, inPermAlpha); IntersectPERConstraints(ass, evalue, valueConstraints, evalueConstraints, ev1, vc1, evc1, ev2, vc2, evc2); IntersectPERConstraints(ass, esize, sizeConstraints, esizeConstraints, es1, sc1, esc1, es2, sc2, esc2); IntersectPERConstraints(ass, epermAlpha, permAlphaConstraints, epermAlphaConstraints, ep1, pc1, epc1, ep2, pc2, epc2); break; case eElementSetSpec_Union: /* union: get the constraints of the sub-element set specs */ /* and unite them */ GetAllPERFromElementSetSpecs(ass, element->U.Union.Elements1, &ev1, &vc1, &evc1, &es1, &sc1, &esc1, &ep1, &pc1, &epc1, inPermAlpha); GetAllPERFromElementSetSpecs(ass, element->U.Union.Elements2, &ev2, &vc2, &evc2, &es2, &sc2, &esc2, &ep2, &pc2, &epc2, inPermAlpha); UnitePERConstraints(evalue, valueConstraints, evalueConstraints, ev1, vc1, evc1, ev2, vc2, evc2); UnitePERConstraints(esize, sizeConstraints, esizeConstraints, es1, sc1, esc1, es2, sc2, esc2); UnitePERConstraints(epermAlpha, permAlphaConstraints, epermAlphaConstraints, ep1, pc1, epc1, ep2, pc2, epc2); break; case eElementSetSpec_AllExcept: /* all-except: get the constraints of the sub-element set specs */ /* and negate them */ GetAllPERFromElementSetSpecs(ass, element->U.AllExcept.Elements, &ev1, &vc1, &evc1, &es1, &sc1, &esc1, &ep1, &pc1, &epc1, inPermAlpha); NegatePERConstraints(ass, evalue, valueConstraints, evalueConstraints, ev1, vc1, evc1); NegatePERConstraints(ass, esize, sizeConstraints, esizeConstraints, es1, sc1, esc1); NegatePERConstraints(ass, epermAlpha, permAlphaConstraints, epermAlphaConstraints, ep1, pc1, epc1); break; case eElementSetSpec_Exclusion: /* exclusion: get the constraints of the sub-element set specs */ /* and substract them */ GetAllPERFromElementSetSpecs(ass, element->U.Exclusion.Elements1, &ev1, &vc1, &evc1, &es1, &sc1, &esc1, &ep1, &pc1, &epc1, inPermAlpha); GetAllPERFromElementSetSpecs(ass, element->U.Exclusion.Elements2, &ev2, &vc2, &evc2, &es2, &sc2, &esc2, &ep2, &pc2, &epc2, inPermAlpha); ExcludePERConstraints(ass, evalue, valueConstraints, evalueConstraints, ev1, vc1, evc1, ev2, vc2, evc2); ExcludePERConstraints(ass, esize, sizeConstraints, esizeConstraints, es1, sc1, esc1, es2, sc2, esc2); ExcludePERConstraints(ass, epermAlpha, permAlphaConstraints, epermAlphaConstraints, ep1, pc1, epc1, ep2, pc2, epc2); break; case eElementSetSpec_SubtypeElement: /* subtype element: get the constraints of the subtype element */ GetAllPERFromSubtypeElements(ass, element->U.SubtypeElement.SubtypeElement, evalue, valueConstraints, evalueConstraints, esize, sizeConstraints, esizeConstraints, epermAlpha, permAlphaConstraints, epermAlphaConstraints, inPermAlpha); break; default: MyAbort(); /*NOTREACHED*/ } } /* get per-visible constraints from a subtype element */ static void GetAllPERFromSubtypeElements(AssignmentList_t ass, SubtypeElement_t *element, Extension_e *evalue, ValueConstraintList_t *valueConstraints, ValueConstraintList_t *evalueConstraints, Extension_e *esize, ValueConstraintList_t *sizeConstraints, ValueConstraintList_t *esizeConstraints, Extension_e *epermAlpha, ValueConstraintList_t *permAlphaConstraints, ValueConstraintList_t *epermAlphaConstraints, int inPermAlpha) { unsigned i; Value_t *v; ValueConstraint_t **p; ValueConstraint_t *vc, *evc; ValueConstraint_t *sc, *esc; Extension_e ev, es; /* examine the subtype element */ switch (element->Type) { case eSubtypeElement_ValueRange: /* value range: create a value constraint containing the bounds */ if (evalue) *evalue = eExtension_Unextended; if (!valueConstraints) error(E_constraint_too_complex, NULL); *valueConstraints = NewValueConstraint(); (*valueConstraints)->Lower = element->U.ValueRange.Lower; (*valueConstraints)->Upper = element->U.ValueRange.Upper; break; case eSubtypeElement_SingleValue: /* single value: create a value constraint containing the element */ if (evalue) *evalue = eExtension_Unextended; if (!valueConstraints) error(E_constraint_too_complex, NULL); v = GetValue(ass, element->U.SingleValue.Value); switch (GetTypeType(ass, v->Type)) { case eType_Integer: *valueConstraints = NewValueConstraint(); (*valueConstraints)->Lower.Flags = (*valueConstraints)->Upper.Flags = 0; (*valueConstraints)->Lower.Value = (*valueConstraints)->Upper.Value = v; break; 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: if (inPermAlpha) { /* single value of a string is used for permitted alphabet */ /* the characters of the string shall be interpreted as a */ /* union of the characters */ p = valueConstraints; for (i = 0; i < v->U.RestrictedString.Value.length; i++) { *p = NewValueConstraint(); (*p)->Lower.Flags = (*p)->Upper.Flags = 0; (*p)->Lower.Value = (*p)->Upper.Value = NewValue(ass, GetType(ass, v->Type)); (*p)->Lower.Value->U.RestrictedString.Value.length = 1; (*p)->Lower.Value->U.RestrictedString.Value.value = (char32_t *)malloc(sizeof(char32_t)); (*p)->Lower.Value->U.RestrictedString.Value.value[0] = v->U.RestrictedString.Value.value[i]; p = &(*p)->Next; } *p = 0; } break; default: /* value element of other types may be ignored for per */ break; } break; case eSubtypeElement_Size: /* size: get the size constraint */ if (!sizeConstraints || inPermAlpha) error(E_constraint_too_complex, NULL); GetAllPERFromConstraints(ass, element->U.Size.Constraints, esize, sizeConstraints, esizeConstraints, NULL, NULL, NULL, NULL, NULL, NULL, inPermAlpha); break; case eSubtypeElement_PermittedAlphabet: /* permitted alphabet: get the permitted alphabet constraint */ if (!permAlphaConstraints || inPermAlpha) error(E_constraint_too_complex, NULL); GetAllPERFromConstraints(ass, element->U.PermittedAlphabet.Constraints, epermAlpha, permAlphaConstraints, epermAlphaConstraints, NULL, NULL, NULL, NULL, NULL, NULL, 1); break; case eSubtypeElement_ContainedSubtype: /* contained subtype: */ if (inPermAlpha) { /* get the permitted alphabet of the referenced type */ GetAllPERFromConstraints(ass, GetType(ass, element->U.ContainedSubtype.Type)->Constraints, &ev, &vc, &evc, &es, &sc, &esc, evalue, valueConstraints, evalueConstraints, inPermAlpha); /* drop extensions for contained subtype constraints */ if (evalue && *evalue > eExtension_Unextended) { *evalue = eExtension_Unextended; if (evalueConstraints) *evalueConstraints = NULL; } } else { /* get the constraints of the referenced type */ GetAllPERFromConstraints(ass, GetType(ass, element->U.ContainedSubtype.Type)->Constraints, evalue, valueConstraints, evalueConstraints, esize, sizeConstraints, esizeConstraints, epermAlpha, permAlphaConstraints, epermAlphaConstraints, inPermAlpha); /* drop extensions for contained subtype constraints */ if (evalue && *evalue > eExtension_Unextended) { *evalue = eExtension_Unextended; if (evalueConstraints) *evalueConstraints = NULL; } if (esize && *esize > eExtension_Unextended) { *esize = eExtension_Unextended; if (esizeConstraints) *esizeConstraints = NULL; } if (epermAlpha && *epermAlpha > eExtension_Unextended) { *epermAlpha = eExtension_Unextended; if (epermAlphaConstraints) *epermAlphaConstraints = NULL; } } break; case eSubtypeElement_Type: case eSubtypeElement_SingleType: case eSubtypeElement_FullSpecification: case eSubtypeElement_PartialSpecification: /* not PER-visible constraints */ break; case eSubtypeElement_ElementSetSpec: /* get the constraints of the element set spec */ GetAllPERFromElementSetSpecs(ass, element->U.ElementSetSpec.ElementSetSpec, evalue, valueConstraints, evalueConstraints, esize, sizeConstraints, esizeConstraints, epermAlpha, permAlphaConstraints, epermAlphaConstraints, inPermAlpha); break; default: MyAbort(); } } /* intersect two value constraints */ static void IntersectValueConstraints(AssignmentList_t ass, ValueConstraintList_t *result, ValueConstraintList_t val1, ValueConstraintList_t val2) { ValueConstraint_t *v1, *v2; EndPoint_t lo, up; /*XXX may be optimized for better results */ /* unite intersection of each pair of value ranges */ for (v1 = val1; v1; v1 = v1->Next) { for (v2 = val2; v2; v2 = v2->Next) { /* get bigger lower bound */ if (CmpLowerEndPoint(ass, &v1->Lower, &v2->Lower) >= 0) lo = v1->Lower; else lo = v2->Lower; /* get smaller upper bound */ if (CmpUpperEndPoint(ass, &v1->Upper, &v2->Upper) <= 0) up = v1->Upper; else up = v2->Upper; /* add intersection if it is not empty */ if ((lo.Flags & eEndPoint_Min) || (up.Flags & eEndPoint_Max) || CmpLowerUpperEndPoint(ass, &lo, &up) <= 0) { *result = NewValueConstraint(); (*result)->Lower = lo; (*result)->Upper = up; result = &(*result)->Next; } } } *result = NULL; } /* unite two value constraints */ static void UniteValueConstraints(ValueConstraintList_t *result, ValueConstraintList_t val1, ValueConstraintList_t val2) { /*XXX may be optimized for better results */ for (; val1; val1 = val1->Next) { *result = NewValueConstraint(); (*result)->Lower = val1->Lower; (*result)->Upper = val1->Upper; result = &(*result)->Next; } for (; val2; val2 = val2->Next) { *result = NewValueConstraint(); (*result)->Lower = val2->Lower; (*result)->Upper = val2->Upper; result = &(*result)->Next; } *result = NULL; } /* negate a value constraint */ static void NegateValueConstraints(AssignmentList_t ass, ValueConstraintList_t *result, ValueConstraintList_t val) { ValueConstraint_t *vc, *lvc, *uvc; EndPoint_t *lower, *upper; *result = NewValueConstraint(); (*result)->Lower.Flags = eEndPoint_Min; (*result)->Upper.Flags = eEndPoint_Max; for (; val; val = val->Next) { lower = &val->Lower; upper = &val->Upper; if (!(upper->Flags & eEndPoint_Max)) { uvc = NewValueConstraint(); uvc->Lower.Flags = (upper->Flags & eEndPoint_Open) ^ eEndPoint_Open; uvc->Lower.Value = upper->Value; uvc->Upper.Flags = eEndPoint_Max; } else { uvc = NULL; } if (!(lower->Flags & eEndPoint_Min)) { lvc = NewValueConstraint(); lvc->Lower.Flags = eEndPoint_Min; lvc->Upper.Flags = (lower->Flags & eEndPoint_Open) ^ eEndPoint_Open; lvc->Upper.Value = lower->Value; } else { lvc = NULL; } if (!lvc && !uvc) { *result = NULL; return; } if (lvc) { vc = lvc; if (uvc) vc->Next = uvc; } else { vc = uvc; } IntersectValueConstraints(ass, result, *result, vc); } } /* substract two value constraints */ static void ExcludeValueConstraints(AssignmentList_t ass, ValueConstraintList_t *result, ValueConstraintList_t val1, ValueConstraintList_t val2) { ValueConstraint_t *notval2; NegateValueConstraints(ass, ¬val2, val2); IntersectValueConstraints(ass, result, val1, notval2); } /* intersect two constraints */ static void IntersectPERConstraints(AssignmentList_t ass, Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1, Extension_e type2, ValueConstraintList_t val2, ValueConstraintList_t eval2) { if (type1 == eExtension_Unconstrained) { if (rtype) *rtype = type2; if (result) *result = val2; if (eresult) *eresult = eval2; } else if (type2 == eExtension_Unconstrained) { if (rtype) *rtype = type1; if (result) *result = val1; if (eresult) *eresult = eval1; } else { if (rtype) *rtype = type1 < type2 ? type1 : type2; if (result) IntersectValueConstraints(ass, result, val1, val2); if (rtype && *rtype == eExtension_Extended && eresult) IntersectValueConstraints(ass, eresult, eval1, eval2); } } /* unite two constraints */ static void UnitePERConstraints(Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1, Extension_e type2, ValueConstraintList_t val2, ValueConstraintList_t eval2) { if (type1 == eExtension_Unconstrained) { if (rtype) *rtype = type2; if (result) *result = val2; if (eresult) *eresult = eval2; } else if (type2 == eExtension_Unconstrained) { if (rtype) *rtype = type1; if (result) *result = val1; if (eresult) *eresult = eval1; } else { if (rtype) *rtype = type1 > type2 ? type1 : type2; if (result) UniteValueConstraints(result, val1, val2); if (rtype && *rtype == eExtension_Extended && eresult) UniteValueConstraints(eresult, eval1 ? eval1 : val1, eval2 ? eval2 : val2); } } /* negate a constraint */ static void NegatePERConstraints(AssignmentList_t ass, Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1) { if (rtype) *rtype = type1; if (result) NegateValueConstraints(ass, result, val1); if (rtype && *rtype == eExtension_Extended && eresult) NegateValueConstraints(ass, eresult, eval1); } /* substract two constraints */ static void ExcludePERConstraints(AssignmentList_t ass, Extension_e *rtype, ValueConstraintList_t *result, ValueConstraintList_t *eresult, Extension_e type1, ValueConstraintList_t val1, ValueConstraintList_t eval1, Extension_e type2, ValueConstraintList_t val2, ValueConstraintList_t eval2) { if (type1 == eExtension_Unconstrained) { if (rtype) *rtype = type2; if (result) *result = val2; if (eresult) *eresult = eval2; } else if (type2 == eExtension_Unconstrained) { if (rtype) *rtype = type1; if (result) *result = val1; if (eresult) *eresult = eval1; } else { if (rtype) *rtype = type1 < type2 ? type1 : type2; if (result) ExcludeValueConstraints(ass, result, val1, val2); if (rtype && *rtype == eExtension_Extended && eresult) ExcludeValueConstraints(ass, eresult, eval1, eval2); } } /* compare two value constraints */ static int CmpValueConstraints(const void *v1, const void *v2, void *ctx) { ValueConstraint_t *vc1 = (ValueConstraint_t *)v1; ValueConstraint_t *vc2 = (ValueConstraint_t *)v2; Assignment_t *ass = (Assignment_t *)ctx; int r; r = CmpLowerEndPoint(ass, &vc1->Lower, &vc2->Lower); if (r) return r; return CmpUpperEndPoint(ass, &vc1->Upper, &vc2->Upper); } /* reduce a value constraint by concatenation of value ranges (if possible) */ void ReduceValueConstraints(AssignmentList_t ass, ValueConstraintList_t *valueConstraints) { ValueConstraint_t *p; EndPoint_t lower, upper, lower2, upper2; int flg; if (!*valueConstraints) return; qsortSL((void **)valueConstraints, offsetof(ValueConstraint_t, Next), CmpValueConstraints, ass); flg = 0; for (p = *valueConstraints; p; p = p->Next) { if (flg) { lower2 = p->Lower; upper2 = p->Upper; if (CheckEndPointsJoin(ass, &upper, &lower2)) { upper = upper2; continue; } *valueConstraints = NewValueConstraint(); /*LINTED*/ (*valueConstraints)->Lower = lower; (*valueConstraints)->Upper = upper; valueConstraints = &(*valueConstraints)->Next; } lower = p->Lower; upper = p->Upper; flg = 1; } *valueConstraints = NewValueConstraint(); (*valueConstraints)->Lower = lower; (*valueConstraints)->Upper = upper; (*valueConstraints)->Next = NULL; } /* count the values of a value constraint */ int CountValues(AssignmentList_t ass, ValueConstraintList_t v, intx_t *n) { intx_t ix; intx_setuint32(n, 0); for (; v; v = v->Next) { if ((v->Lower.Flags & eEndPoint_Min) || (v->Upper.Flags & eEndPoint_Max)) return 0; if (!SubstractValues(ass, &ix, v->Lower.Value, v->Upper.Value)) return 0; intx_add(n, n, &ix); intx_inc(n); } return 1; } /* check if the value constraint of a value is empty */ int HasNoValueConstraint(ValueConstraintList_t v) { EndPoint_t *p1, *p2; if (!v) return 1; if (!v->Next) { p1 = &v->Lower; p2 = &v->Upper; if ((p1->Flags & eEndPoint_Min) && (p2->Flags & eEndPoint_Max)) { return 1; } } return 0; } /* check if the value constraint of a size is empty */ int HasNoSizeConstraint(AssignmentList_t ass, ValueConstraintList_t v) { EndPoint_t *p1, *p2; if (!v) return 1; if (!v->Next) { p1 = &v->Lower; p2 = &v->Upper; if (!(p1->Flags & eEndPoint_Min) && !intx_cmp(&GetValue(ass, p1->Value)->U.Integer.Value, &intx_0) && (p2->Flags & eEndPoint_Max)) { return 1; } } return 0; } /* check if the value constraint of a permitted alphabet is empty */ int HasNoPermittedAlphabetConstraint(AssignmentList_t ass, ValueConstraintList_t v) { EndPoint_t *p1, *p2; if (!v) return 1; if (!v->Next) { p1 = &v->Lower; p2 = &v->Upper; if (!(p1->Flags & eEndPoint_Min) && GetValue(ass, p1->Value)->U.RestrictedString.Value.length == 1 && GetValue(ass, p1->Value)->U.RestrictedString.Value.value[0] == 0 && !(p2->Flags & eEndPoint_Max) && GetValue(ass, p2->Value)->U.RestrictedString.Value.length == 1 && GetValue(ass, p2->Value)->U.RestrictedString.Value.value[0] == 0xffffffff) { return 1; } } return 0; } /* get the fixed identification */ /* this is needed for embedded pdv/character string types who are encoded */ /* in an "optimized" manner if the identification is fixed */ NamedValue_t * GetFixedIdentification(AssignmentList_t ass, Constraint_t *constraints) { if (!constraints) return NULL; return GetFixedIdentificationFromElementSetSpec(ass, constraints->Root); } /* get the fixed identification from an element set spec */ static NamedValue_t * GetFixedIdentificationFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elements) { NamedConstraint_t *named; NamedValue_t *nv1, *nv2; SubtypeElement_t *se; if (!elements) return NULL; switch (elements->Type) { case eElementSetSpec_AllExcept: return NULL; case eElementSetSpec_Union: nv1 = GetFixedIdentificationFromElementSetSpec(ass, elements->U.Union.Elements1); nv2 = GetFixedIdentificationFromElementSetSpec(ass, elements->U.Union.Elements2); return nv1 && nv2 ? nv1 : NULL; /*XXX conflicts ignored */ case eElementSetSpec_Intersection: nv1 = GetFixedIdentificationFromElementSetSpec(ass, elements->U.Union.Elements1); nv2 = GetFixedIdentificationFromElementSetSpec(ass, elements->U.Union.Elements2); return nv1 ? nv1 : nv2; /*XXX conflicts ignored */ case eElementSetSpec_Exclusion: nv1 = GetFixedIdentificationFromElementSetSpec(ass, elements->U.Exclusion.Elements1); nv2 = GetFixedIdentificationFromElementSetSpec(ass, elements->U.Exclusion.Elements2); return nv1 && !nv2 ? nv1 : NULL; /*XXX conflicts ignored */ case eElementSetSpec_SubtypeElement: se = elements->U.SubtypeElement.SubtypeElement; switch (se->Type) { case eSubtypeElement_FullSpecification: case eSubtypeElement_PartialSpecification: for (named = se->U.FP.NamedConstraints; named; named = named->Next) { if (!strcmp(named->Identifier, "identification")) return GetFixedSyntaxes(ass, named->Constraint); } break; } return NULL; default: MyAbort(); /*NOTREACHED*/ } return NULL; } /* get the fixed syntaxes from a constraint */ static NamedValue_t * GetFixedSyntaxes(AssignmentList_t ass, Constraint_t *constraints) { if (!constraints) return NULL; return GetFixedSyntaxesFromElementSetSpec(ass, constraints->Root); } /* get the fixed syntaxes from an element set spec */ static NamedValue_t * GetFixedSyntaxesFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elements) { int present, absent, bit; Constraint_t *presentconstraints[6]; NamedConstraint_t *named; NamedValue_t *nv1, *nv2; SubtypeElement_t *se; if (!elements) return NULL; switch (elements->Type) { case eElementSetSpec_AllExcept: return NULL; case eElementSetSpec_Union: nv1 = GetFixedSyntaxesFromElementSetSpec(ass, elements->U.Union.Elements1); nv2 = GetFixedSyntaxesFromElementSetSpec(ass, elements->U.Union.Elements2); return nv1 && nv2 ? nv1 : NULL; /*XXX conflicts ignored */ case eElementSetSpec_Intersection: nv1 = GetFixedSyntaxesFromElementSetSpec(ass, elements->U.Intersection.Elements1); nv2 = GetFixedSyntaxesFromElementSetSpec(ass, elements->U.Intersection.Elements2); return nv1 ? nv1 : nv2; /*XXX conflicts ignored */ case eElementSetSpec_Exclusion: nv1 = GetFixedSyntaxesFromElementSetSpec(ass, elements->U.Exclusion.Elements1); nv2 = GetFixedSyntaxesFromElementSetSpec(ass, elements->U.Exclusion.Elements2); return nv1 && !nv2 ? nv1 : NULL; /*XXX conflicts ignored */ case eElementSetSpec_SubtypeElement: se = elements->U.SubtypeElement.SubtypeElement; switch (se->Type) { case eSubtypeElement_FullSpecification: case eSubtypeElement_PartialSpecification: present = absent = 0; for (named = se->U.FP.NamedConstraints; named; named = named->Next) { if (!strcmp(named->Identifier, "syntaxes")) { bit = 0; } else if (!strcmp(named->Identifier, "syntax")) { bit = 1; } else if (!strcmp(named->Identifier, "presentation-context-id")) { bit = 2; } else if (!strcmp(named->Identifier, "context-negotiation")) { bit = 3; } else if (!strcmp(named->Identifier, "transfer-syntax")) { bit = 4; } else if (!strcmp(named->Identifier, "fixed")) { bit = 5; } switch (named->Presence) { case ePresence_Normal: if (se->Type == eSubtypeElement_PartialSpecification) break; /*FALLTHROUGH*/ case ePresence_Present: present |= (1 << bit); presentconstraints[bit] = named->Constraint; break; case ePresence_Absent: absent |= (1 << bit); break; case ePresence_Optional: break; } } if (se->Type == eSubtypeElement_FullSpecification) absent |= (0x3f & ~present); if (present == 0x20 && absent == 0x1f) return NewNamedValue("fixed", Builtin_Value_Null); if (present == 0x01 && absent == 0x3e) return GetFixedAbstractAndTransfer(ass, presentconstraints[0]); return NULL; } return NULL; default: MyAbort(); /*NOTREACHED*/ } return NULL; } /* get the fixed abstract and transfer from a constraint */ static NamedValue_t * GetFixedAbstractAndTransfer(AssignmentList_t ass, Constraint_t *constraints) { if (!constraints) return NULL; return GetFixedAbstractAndTransferFromElementSetSpec(ass, constraints->Root); } /* get the fixed abstract and transfer from an element set spec */ static NamedValue_t * GetFixedAbstractAndTransferFromElementSetSpec(AssignmentList_t ass, ElementSetSpec_t *elements) { NamedValue_t *nv1, *nv2; SubtypeElement_t *se; if (!elements) return NULL; switch (elements->Type) { case eElementSetSpec_AllExcept: return NULL; case eElementSetSpec_Union: nv1 = GetFixedAbstractAndTransferFromElementSetSpec(ass, elements->U.Union.Elements1); nv2 = GetFixedAbstractAndTransferFromElementSetSpec(ass, elements->U.Union.Elements2); return nv1 && nv2 ? nv1 : NULL; /*XXX conflicts ignored */ case eElementSetSpec_Intersection: nv1 = GetFixedAbstractAndTransferFromElementSetSpec(ass, elements->U.Intersection.Elements1); nv2 = GetFixedAbstractAndTransferFromElementSetSpec(ass, elements->U.Intersection.Elements2); return nv1 ? nv1 : nv2; /*XXX conflicts ignored */ case eElementSetSpec_Exclusion: nv1 = GetFixedAbstractAndTransferFromElementSetSpec(ass, elements->U.Exclusion.Elements1); nv2 = GetFixedAbstractAndTransferFromElementSetSpec(ass, elements->U.Exclusion.Elements2); return nv1 && !nv2 ? nv1 : NULL; /*XXX conflicts ignored */ case eElementSetSpec_SubtypeElement: se = elements->U.SubtypeElement.SubtypeElement; switch (se->Type) { case eSubtypeElement_SingleValue: return NewNamedValue("syntaxes", se->U.SingleValue.Value); } return NULL; default: MyAbort(); /*NOTREACHED*/ } return NULL; }