📄 cstrnops.c
字号:
}
else
{
tmpmin1 = constraint1->minFields;
tmpmax1 = constraint1->maxFields;
}
/*===========================================*/
/* Loop through each of range/min/max values */
/* from the first constraint record. */
/*===========================================*/
for (;
tmpmin1 != NULL;
tmpmin1 = tmpmin1->nextArg, tmpmax1 = tmpmax1->nextArg)
{
/*============================================*/
/* Get the appropriate values from the second */
/* constraint record for comparison. */
/*============================================*/
if (range)
{
tmpmin2 = constraint2->minValue;
tmpmax2 = constraint2->maxValue;
}
else
{
tmpmin2 = constraint2->minFields;
tmpmax2 = constraint2->maxFields;
}
/*================================================*/
/* Loop through each of range/min/max values from */
/* the second constraint record comparing it to */
/* the values from the first constraint record. */
/*================================================*/
for (;
tmpmin2 != NULL;
tmpmin2 = tmpmin2->nextArg, tmpmax2 = tmpmax2->nextArg)
{
/*==============================================*/
/* Determine the relationship between the four */
/* combinations of min/max values (>, <, or =). */
/*==============================================*/
cmaxmax = CompareNumbers(theEnv,tmpmax1->type,tmpmax1->value,
tmpmax2->type,tmpmax2->value);
cminmin = CompareNumbers(theEnv,tmpmin1->type,tmpmin1->value,
tmpmin2->type,tmpmin2->value);
cmaxmin = CompareNumbers(theEnv,tmpmax1->type,tmpmax1->value,
tmpmin2->type,tmpmin2->value);
cminmax = CompareNumbers(theEnv,tmpmin1->type,tmpmin1->value,
tmpmax2->type,tmpmax2->value);
/*============================================*/
/* If the range/min/max values don't overlap, */
/* then proceed to the next pair of numbers */
/* to see if they overlap. */
/*============================================*/
if ((cmaxmin == LESS_THAN) || (cminmax == GREATER_THAN))
{ continue; }
/*=======================================*/
/* Compute the new minimum value for the */
/* intersected range/min/max values. */
/*=======================================*/
if (cminmin == GREATER_THAN)
{ theMin = GenConstant(theEnv,tmpmin1->type,tmpmin1->value); }
else
{ theMin = GenConstant(theEnv,tmpmin2->type,tmpmin2->value); }
/*=======================================*/
/* Compute the new maximum value for the */
/* intersected range/min/max values. */
/*=======================================*/
if (cmaxmax == LESS_THAN)
{ theMax = GenConstant(theEnv,tmpmax1->type,tmpmax1->value); }
else
{ theMax = GenConstant(theEnv,tmpmax2->type,tmpmax2->value); }
/*==================================*/
/* Add the new range/min/max values */
/* to the intersection list. */
/*==================================*/
if (lastMin == NULL)
{
theMinList = theMin;
theMaxList = theMax;
}
else
{
lastMin->nextArg = theMin;
lastMax->nextArg = theMax;
}
lastMin = theMin;
lastMax = theMax;
}
}
/*============================================================*/
/* If the intersection produced a pair of valid range/min/max */
/* values, then replace the previous values of the constraint */
/* record to the new intersected values. */
/*============================================================*/
if (theMinList != NULL)
{
if (range)
{
ReturnExpression(theEnv,newConstraint->minValue);
ReturnExpression(theEnv,newConstraint->maxValue);
newConstraint->minValue = theMinList;
newConstraint->maxValue = theMaxList;
}
else
{
ReturnExpression(theEnv,newConstraint->minFields);
ReturnExpression(theEnv,newConstraint->maxFields);
newConstraint->minFields = theMinList;
newConstraint->maxFields = theMaxList;
}
}
/*===============================================================*/
/* Otherwise, the intersection produced no valid range/min/max */
/* values. For the range attribute, this means that no numbers */
/* can satisfy the constraint. For the min/max fields attribute, */
/* it means that no value can satisfy the constraint. */
/*===============================================================*/
else
{
if (range)
{
if (newConstraint->anyAllowed) SetAnyAllowedFlags(newConstraint,FALSE);
newConstraint->integersAllowed = FALSE;
newConstraint->floatsAllowed = FALSE;
}
else
{
SetAnyAllowedFlags(newConstraint,TRUE);
newConstraint->singlefieldsAllowed = FALSE;
newConstraint->multifieldsAllowed = FALSE;
newConstraint->anyAllowed = FALSE;
}
}
}
/************************************************************/
/* UpdateRestrictionFlags: Updates the types allowed flags */
/* based on the allowed values in a constraint record. */
/* Intended to be called after the allowed values list */
/* has been changed (for example after intersecting the */
/* allowed-values list there may no be any values of a */
/* particular type left even though the type is allowed). */
/************************************************************/
static void UpdateRestrictionFlags(
CONSTRAINT_RECORD *rv)
{
if ((rv->anyRestriction) && (rv->restrictionList == NULL))
{
SetAnyAllowedFlags(rv,TRUE);
rv->anyAllowed = FALSE;
}
if ((rv->symbolRestriction) && (rv->symbolsAllowed))
{ rv->symbolsAllowed = FindItemInExpression(SYMBOL,NULL,FALSE,rv->restrictionList); }
if ((rv->stringRestriction) && (rv->stringsAllowed))
{ rv->stringsAllowed = FindItemInExpression(STRING,NULL,FALSE,rv->restrictionList); }
if ((rv->floatRestriction) && (rv->floatsAllowed))
{ rv->floatsAllowed = FindItemInExpression(FLOAT,NULL,FALSE,rv->restrictionList); }
if ((rv->integerRestriction) && (rv->integersAllowed))
{ rv->integersAllowed = FindItemInExpression(INTEGER,NULL,FALSE,rv->restrictionList); }
if ((rv->instanceNameRestriction) && (rv->instanceNamesAllowed))
{ rv->instanceNamesAllowed = FindItemInExpression(INSTANCE_NAME,NULL,FALSE,rv->restrictionList); }
}
/*************************************************************/
/* FindItemInExpression: Determines if a particular constant */
/* (such as 27) or a class of constants (such as integers) */
/* can be found in a list of constants. Returns TRUE if */
/* such a constant can be found, otherwise FALSE. */
/*************************************************************/
static int FindItemInExpression(
int theType,
void *theValue,
int useValue,
struct expr *theList)
{
while (theList != NULL)
{
if (theList->type == theType)
{
if (! useValue) return(TRUE);
else if (theList->value == theValue) return(TRUE);
}
theList = theList->nextArg;
}
return(FALSE);
}
#if (! BLOAD_ONLY)
/**************************************************/
/* RestrictionOnType: Determines if a restriction */
/* is present for a specific type. Returns TRUE */
/* if there is, otherwise FALSE. */
/**************************************************/
static int RestrictionOnType(
int theType,
CONSTRAINT_RECORD *theConstraint)
{
if (theConstraint == NULL) return(FALSE);
if ((theConstraint->anyRestriction) ||
(theConstraint->symbolRestriction && (theType == SYMBOL)) ||
(theConstraint->stringRestriction && (theType == STRING)) ||
(theConstraint->floatRestriction && (theType == FLOAT)) ||
(theConstraint->integerRestriction && (theType == INTEGER)) ||
(theConstraint->classRestriction && ((theType == INSTANCE_ADDRESS) ||
(theType == INSTANCE_NAME))) ||
(theConstraint->instanceNameRestriction && (theType == INSTANCE_NAME)))
{ return(TRUE); }
return(FALSE);
}
/**********************************************************/
/* UnionConstraints: Creates a new constraint record that */
/* is the union of two other constraint records. */
/**********************************************************/
globle struct constraintRecord *UnionConstraints(
void *theEnv,
CONSTRAINT_RECORD *c1,
CONSTRAINT_RECORD *c2)
{
struct constraintRecord *rv;
int c1Changed = FALSE, c2Changed = FALSE;
/*=================================================*/
/* If both constraint records are NULL,then create */
/* a constraint record that allows any value. */
/*=================================================*/
if ((c1 == NULL) && (c2 == NULL)) return(GetConstraintRecord(theEnv));
/*=====================================================*/
/* If one of the constraint records is NULL, then the */
/* union is the other constraint record. Note that */
/* this is different from the way that intersections */
/* were handled (a NULL constraint record implied that */
/* any value was legal which in turn would imply that */
/* the union would allow any value as well). */
/*=====================================================*/
if (c1 == NULL) return(CopyConstraintRecord(theEnv,c2));
if (c2 == NULL) return(CopyConstraintRecord(theEnv,c1));
/*=================================*/
/* Create a new constraint record. */
/*=================================*/
rv = GetConstraintRecord(theEnv);
/*==========================*/
/* Union the allowed types. */
/*==========================*/
if (c1->multifieldsAllowed || c2->multifieldsAllowed)
{ rv->multifieldsAllowed = TRUE; }
if (c1->singlefieldsAllowed || c2->singlefieldsAllowed)
{ rv->singlefieldsAllowed = TRUE; }
if (c1->anyAllowed || c2->anyAllowed) rv->anyAllowed = TRUE;
else
{
rv->anyAllowed = FALSE;
rv->symbolsAllowed = (c1->symbolsAllowed || c2->symbolsAllowed);
rv->stringsAllowed = (c1->stringsAllowed || c2->stringsAllowed);
rv->floatsAllowed = (c1->floatsAllowed || c2->floatsAllowed);
rv->integersAllowed = (c1->integersAllowed || c2->integersAllowed);
rv->instanceNamesAllowed = (c1->instanceNamesAllowed || c2->instanceNamesAllowed);
rv->instanceAddressesAllowed = (c1->instanceAddressesAllowed || c2->instanceAddressesAllowed);
rv->externalAddressesAllowed = (c1->externalAddressesAllowed || c2->externalAddressesAllowed);
rv->voidAllowed = (c1->voidAllowed || c2->voidAllowed);
rv->factAddressesAllowed = (c1->factAddressesAllowed || c2->factAddressesAllowed);
}
/*=================================*/
/* Union the allowed-values flags. */
/*=================================*/
if (c1->anyRestriction && c2->anyRestriction) rv->anyRestriction = TRUE;
else
{
if (c1->anyRestriction)
{
c1Changed = TRUE;
SetAnyRestrictionFlags(c1,FALSE);
}
else if (c2->anyRestriction)
{
c2Changed = TRUE;
SetAnyRestrictionFlags(c2,FALSE);
}
rv->anyRestriction = FALSE;
rv->symbolRestriction = (c1->symbolRestriction && c2->symbolRestriction);
rv->stringRestriction = (c1->stringRestriction && c2->stringRestriction);
rv->floatRestriction = (c1->floatRestriction && c2->floatRestriction);
rv->integerRestriction = (c1->integerRestriction && c2->integerRestriction);
rv->classRestriction = (c1->classRestriction && c2->classRestriction);
rv->instanceNameRestriction = (c1->instanceNameRestriction && c2->instanceNameRestriction);
if (c1Changed) SetAnyRestrictionFlags(c1,FALSE);
else if (c2Changed) SetAnyRestrictionFlags(c2,FALSE);
}
/*========================================*/
/* Union the allowed values list, the min */
/* and max values, and the range values. */
/*========================================*/
UnionAllowedValueExpressions(theEnv,c1,c2,rv);
UnionAllowedClassExpressions(theEnv,c1,c2,rv);
UnionNumericExpressions(theEnv,c1,c2,rv,TRUE);
UnionNumericExpressions(theEnv,c1,c2,rv,FALSE);
/*========================================*/
/* If multifields are allowed, then union */
/* the constraint record for them. */
/*========================================*/
if (rv->multifieldsAllowed)
{ rv->multifield = UnionConstraints(theEnv,c1->multifield,c2->multifield); }
/*====================*/
/* Return the unioned */
/* constraint record. */
/*====================*/
return(rv);
}
/**************************************************/
/* UnionNumericExpressions: Creates the union of */
/* two range or two min/max-fields constraints. */
/**************************************************/
static void UnionNumericExpressions(
void *theEnv,
CONSTRAINT_RECORD *constraint1,
CONSTRAINT_RECORD *constraint2,
CONSTRAINT_RECORD *newConstraint,
int range)
{
struct expr *tmpmin, *tmpmax;
struct expr *theMinList, *theMaxList;
/*=========================================*/
/* Initialize the new range/min/max values */
/* for the union of the constraints. */
/*=========================================*/
theMinList = NULL;
theMaxList = NULL;
/*=================================*/
/* Determine the min/max values of */
/* the first constraint record. */
/*=================================*/
if (range)
{
tmpmin = constraint1->minValue;
tmpmax = constraint1->maxValue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -