📄 cstrnchk.c
字号:
if ((type != INSTANCE_ADDRESS) && (type != INSTANCE_NAME))
{ return(TRUE); }
/*=============================================*/
/* If an instance name is specified, determine */
/* whether the instance exists. */
/*=============================================*/
if (type == INSTANCE_ADDRESS)
{ ins = (INSTANCE_TYPE *) vPtr; }
else
{ ins = FindInstanceBySymbol(theEnv,(SYMBOL_HN *) vPtr); }
if (ins == NULL)
{ return(FALSE); }
/*======================================================*/
/* Search through the class list to see if the instance */
/* belongs to one of the allowed classes in the list. */
/*======================================================*/
insClass = (DEFCLASS *) EnvGetInstanceClass(theEnv,ins);
for (tmpPtr = constraints->classList;
tmpPtr != NULL;
tmpPtr = tmpPtr->nextArg)
{
cmpClass = (DEFCLASS *) EnvFindDefclass(theEnv,ValueToString(tmpPtr->value));
if (cmpClass == NULL) continue;
if (cmpClass == insClass) return(TRUE);
if (EnvSubclassP(theEnv,insClass,cmpClass)) return(TRUE);
}
/*=========================================================*/
/* If a parent class wasn't found in the list, then return */
/* FALSE because the constraint has been violated. */
/*=========================================================*/
return(FALSE);
#else
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(theEnv)
#pragma unused(type)
#pragma unused(vPtr)
#pragma unused(constraints)
#endif
return(TRUE);
#endif
}
/*************************************************************/
/* CheckRangeConstraint: Determines if a primitive data type */
/* satisfies the range constraint of a constraint record. */
/*************************************************************/
static intBool CheckRangeConstraint(
void *theEnv,
int type,
void *vPtr,
CONSTRAINT_RECORD *constraints)
{
struct expr *minList, *maxList;
/*===================================*/
/* If the constraint record is NULL, */
/* there are no range restrictions. */
/*===================================*/
if (constraints == NULL) return(TRUE);
/*============================================*/
/* If the value being checked isn't a number, */
/* then the range restrictions don't apply. */
/*============================================*/
if ((type != INTEGER) && (type != FLOAT)) return(TRUE);
/*=====================================================*/
/* Check each of the range restrictions to see if the */
/* number falls within at least one of the allowed */
/* ranges. If it falls within one of the ranges, then */
/* return TRUE since the constraint is satisifed. */
/*=====================================================*/
minList = constraints->minValue;
maxList = constraints->maxValue;
while (minList != NULL)
{
if (CompareNumbers(theEnv,type,vPtr,minList->type,minList->value) == LESS_THAN)
{
minList = minList->nextArg;
maxList = maxList->nextArg;
}
else if (CompareNumbers(theEnv,type,vPtr,maxList->type,maxList->value) == GREATER_THAN)
{
minList = minList->nextArg;
maxList = maxList->nextArg;
}
else
{ return(TRUE); }
}
/*===========================================*/
/* Return FALSE since the number didn't fall */
/* within one of the allowed numeric ranges. */
/*===========================================*/
return(FALSE);
}
/************************************************/
/* ConstraintViolationErrorMessage: Generalized */
/* error message for constraint violations. */
/************************************************/
globle void ConstraintViolationErrorMessage(
void *theEnv,
char *theWhat,
char *thePlace,
int command,
int thePattern,
struct symbolHashNode *theSlot,
int theField,
int violationType,
CONSTRAINT_RECORD *theConstraint,
int printPrelude)
{
/*======================================================*/
/* Don't print anything other than the tail explanation */
/* of the error unless asked to do so. */
/*======================================================*/
if (printPrelude)
{
/*===================================*/
/* Print the name of the thing which */
/* caused the constraint violation. */
/*===================================*/
if (violationType == FUNCTION_RETURN_TYPE_VIOLATION)
{
PrintErrorID(theEnv,"CSTRNCHK",1,TRUE);
EnvPrintRouter(theEnv,WERROR,"The function return value ");
}
else if (theWhat != NULL)
{
PrintErrorID(theEnv,"CSTRNCHK",1,TRUE);
EnvPrintRouter(theEnv,WERROR,theWhat);
EnvPrintRouter(theEnv,WERROR," ");
}
/*=======================================*/
/* Print the location of the thing which */
/* caused the constraint violation. */
/*=======================================*/
if (thePlace != NULL)
{
EnvPrintRouter(theEnv,WERROR,"found in ");
if (command) EnvPrintRouter(theEnv,WERROR,"the ");
EnvPrintRouter(theEnv,WERROR,thePlace);
if (command) EnvPrintRouter(theEnv,WERROR," command");
}
/*================================================*/
/* If the violation occured in the LHS of a rule, */
/* indicate which pattern was at fault. */
/*================================================*/
if (thePattern > 0)
{
EnvPrintRouter(theEnv,WERROR,"found in CE #");
PrintLongInteger(theEnv,WERROR,(long int) thePattern);
}
}
/*===============================================================*/
/* Indicate the type of constraint violation (type, range, etc). */
/*===============================================================*/
if ((violationType == TYPE_VIOLATION) ||
(violationType == FUNCTION_RETURN_TYPE_VIOLATION))
{ EnvPrintRouter(theEnv,WERROR,"\ndoes not match the allowed types"); }
else if (violationType == RANGE_VIOLATION)
{
EnvPrintRouter(theEnv,WERROR,"\ndoes not fall in the allowed range ");
PrintRange(theEnv,WERROR,theConstraint);
}
else if (violationType == ALLOWED_VALUES_VIOLATION)
{ EnvPrintRouter(theEnv,WERROR,"\ndoes not match the allowed values"); }
else if (violationType == CARDINALITY_VIOLATION)
{ EnvPrintRouter(theEnv,WERROR,"\ndoes not satisfy the cardinality restrictions"); }
else if (violationType == ALLOWED_CLASSES_VIOLATION)
{ EnvPrintRouter(theEnv,WERROR,"\ndoes not match the allowed classes"); }
/*==============================================*/
/* Print either the slot name or field position */
/* where the constraint violation occured. */
/*==============================================*/
if (theSlot != NULL)
{
EnvPrintRouter(theEnv,WERROR," for slot ");
EnvPrintRouter(theEnv,WERROR,ValueToString(theSlot));
}
else if (theField > 0)
{
EnvPrintRouter(theEnv,WERROR," for field #");
PrintLongInteger(theEnv,WERROR,(long) theField);
}
EnvPrintRouter(theEnv,WERROR,".\n");
}
/********************************************************************/
/* PrintRange: Prints the range restriction of a constraint record. */
/* For example, 8 to +00 (eight to positive infinity). */
/********************************************************************/
static void PrintRange(
void *theEnv,
char *logicalName,
CONSTRAINT_RECORD *theConstraint)
{
if (theConstraint->minValue->value == SymbolData(theEnv)->NegativeInfinity)
{ EnvPrintRouter(theEnv,logicalName,ValueToString(SymbolData(theEnv)->NegativeInfinity)); }
else PrintExpression(theEnv,logicalName,theConstraint->minValue);
EnvPrintRouter(theEnv,logicalName," to ");
if (theConstraint->maxValue->value == SymbolData(theEnv)->PositiveInfinity)
{ EnvPrintRouter(theEnv,logicalName,ValueToString(SymbolData(theEnv)->PositiveInfinity)); }
else PrintExpression(theEnv,logicalName,theConstraint->maxValue);
}
/*************************************************************/
/* ConstraintCheckDataObject: Given a value stored in a data */
/* object structure and a constraint record, determines if */
/* the data object satisfies the constraint record. */
/*************************************************************/
globle int ConstraintCheckDataObject(
void *theEnv,
DATA_OBJECT *theData,
CONSTRAINT_RECORD *theConstraints)
{
long i; /* 6.04 Bug Fix */
int rv;
struct field *theMultifield;
if (theConstraints == NULL) return(NO_VIOLATION);
if (theData->type == MULTIFIELD)
{
if (CheckCardinalityConstraint(theEnv,(theData->end - theData->begin) + 1,
theConstraints) == FALSE)
{ return(CARDINALITY_VIOLATION); }
theMultifield = ((struct multifield *) theData->value)->theFields;
for (i = theData->begin; i <= theData->end; i++)
{
if ((rv = ConstraintCheckValue(theEnv,theMultifield[i].type,
theMultifield[i].value,
theConstraints)) != NO_VIOLATION)
{ return(rv); }
}
return(NO_VIOLATION);
}
if (CheckCardinalityConstraint(theEnv,1L,theConstraints) == FALSE)
{ return(CARDINALITY_VIOLATION); }
return(ConstraintCheckValue(theEnv,theData->type,theData->value,theConstraints));
}
/****************************************************************/
/* ConstraintCheckValue: Given a value and a constraint record, */
/* determines if the value satisfies the constraint record. */
/****************************************************************/
globle int ConstraintCheckValue(
void *theEnv,
int theType,
void *theValue,
CONSTRAINT_RECORD *theConstraints)
{
if (CheckTypeConstraint(theType,theConstraints) == FALSE)
{ return(TYPE_VIOLATION); }
else if (CheckAllowedValuesConstraint(theType,theValue,theConstraints) == FALSE)
{ return(ALLOWED_VALUES_VIOLATION); }
else if (CheckAllowedClassesConstraint(theEnv,theType,theValue,theConstraints) == FALSE)
{ return(ALLOWED_CLASSES_VIOLATION); }
else if (CheckRangeConstraint(theEnv,theType,theValue,theConstraints) == FALSE)
{ return(RANGE_VIOLATION); }
else if (theType == FCALL)
{
if (CheckFunctionReturnType((int) ValueFunctionType(theValue),theConstraints) == FALSE)
{ return(FUNCTION_RETURN_TYPE_VIOLATION); }
}
return(NO_VIOLATION);
}
/********************************************************************/
/* ConstraintCheckExpressionChain: Checks an expression and nextArg */
/* links for constraint conflicts (argList is not followed). */
/********************************************************************/
globle int ConstraintCheckExpressionChain(
void *theEnv,
struct expr *theExpression,
CONSTRAINT_RECORD *theConstraints)
{
struct expr *theExp;
int min = 0, max = 0, vCode;
/*===========================================================*/
/* Determine the minimum and maximum number of value which */
/* can be derived from the expression chain (max of -1 means */
/* positive infinity). */
/*===========================================================*/
for (theExp = theExpression ; theExp != NULL ; theExp = theExp->nextArg)
{
if (ConstantType(theExp->type)) min++;
else if (theExp->type == FCALL)
{
if ((ExpressionFunctionType(theExp) != 'm') &&
(ExpressionFunctionType(theExp) != 'u')) min++;
else max = -1;
}
else max = -1;
}
/*====================================*/
/* Check for a cardinality violation. */
/*====================================*/
if (max == 0) max = min;
if (CheckRangeAgainstCardinalityConstraint(theEnv,min,max,theConstraints) == FALSE)
{ return(CARDINALITY_VIOLATION); }
/*========================================*/
/* Check for other constraint violations. */
/*========================================*/
for (theExp = theExpression ; theExp != NULL ; theExp = theExp->nextArg)
{
vCode = ConstraintCheckValue(theEnv,theExp->type,theExp->value,theConstraints);
if (vCode != NO_VIOLATION)
return(vCode);
}
return(NO_VIOLATION);
}
#if (! RUN_TIME) && (! BLOAD_ONLY)
/***************************************************/
/* ConstraintCheckExpression: Checks an expression */
/* for constraint conflicts. Returns TRUE if */
/* conflicts are found, otherwise FALSE. */
/***************************************************/
globle int ConstraintCheckExpression(
void *theEnv,
struct expr *theExpression,
CONSTRAINT_RECORD *theConstraints)
{
int rv = NO_VIOLATION;
if (theConstraints == NULL) return(rv);
while (theExpression != NULL)
{
rv = ConstraintCheckValue(theEnv,theExpression->type,
theExpression->value,
theConstraints);
if (rv != NO_VIOLATION) return(rv);
rv = ConstraintCheckExpression(theEnv,theExpression->argList,theConstraints);
if (rv != NO_VIOLATION) return(rv);
theExpression = theExpression->nextArg;
}
return(rv);
}
#endif /* (! RUN_TIME) && (! BLOAD_ONLY) */
#if (! RUN_TIME)
/*****************************************************/
/* UnmatchableConstraint: Determines if a constraint */
/* record can still be satisfied by some value. */
/*****************************************************/
globle intBool UnmatchableConstraint(
CONSTRAINT_RECORD *theConstraint)
{
if (theConstraint == NULL) return(FALSE);
if ((! theConstraint->anyAllowed) &&
(! theConstraint->symbolsAllowed) &&
(! theConstraint->stringsAllowed) &&
(! theConstraint->floatsAllowed) &&
(! theConstraint->integersAllowed) &&
(! theConstraint->instanceNamesAllowed) &&
(! theConstraint->instanceAddressesAllowed) &&
(! theConstraint->multifieldsAllowed) &&
(! theConstraint->externalAddressesAllowed) &&
(! theConstraint->voidAllowed) &&
(! theConstraint->factAddressesAllowed))
{ return(TRUE); }
return(FALSE);
}
#endif /* (! RUN_TIME) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -