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

1163 lines
35 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
#include "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, &notval2, 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;
}