?? cstrnops.c
字號(hào):
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.24 07/01/05 */ /* */ /* CONSTRAINT OPERATIONS MODULE */ /*******************************************************//*************************************************************//* Purpose: Provides functions for performing operations on *//* constraint records including computing the intersection *//* and union of constraint records. *//* *//* Principal Programmer(s): *//* Gary D. Riley *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//* 6.24: Added allowed-classes slot facet. *//* *//*************************************************************/#define _CSTRNOPS_SOURCE_#include "setup.h"#include <stdio.h>#define _STDIO_INCLUDED_#include <stdlib.h>#if (! RUN_TIME)#include "constant.h"#include "envrnmnt.h"#include "memalloc.h"#include "router.h"#include "extnfunc.h"#include "scanner.h"#include "multifld.h"#include "constrnt.h"#include "cstrnchk.h"#include "cstrnutl.h"#include "cstrnops.h"/***************************************//* LOCAL INTERNAL FUNCTION DEFINITIONS *//***************************************/ static void IntersectNumericExpressions(void *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *,int); static void IntersectAllowedValueExpressions(void *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *); static void IntersectAllowedClassExpressions(void *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *); static int FindItemInExpression(int,void *,int,struct expr *); static void UpdateRestrictionFlags(CONSTRAINT_RECORD *);#if (! BLOAD_ONLY) static void UnionRangeMinMaxValueWithList(void *, struct expr *, struct expr *, struct expr **, struct expr **); static void UnionNumericExpressions(void *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *,int); static struct expr *AddToUnionList(void *, struct expr *,struct expr *, CONSTRAINT_RECORD *); static void UnionAllowedValueExpressions(void *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *); static void UnionAllowedClassExpressions(void *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *, CONSTRAINT_RECORD *); static int RestrictionOnType(int,CONSTRAINT_RECORD *);#endif/**************************************************************//* IntersectConstraints: Creates a new constraint record that *//* is the intersection of two other constraint records. *//**************************************************************/globle struct constraintRecord *IntersectConstraints( 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)) { rv = GetConstraintRecord(theEnv); rv->multifieldsAllowed = TRUE; return(rv); } /*=================================================*/ /* If one of the constraint records is NULL, then */ /* the intersection is the other constraint record */ /* (a NULL value means no constraints). */ /*=================================================*/ if (c1 == NULL) return(CopyConstraintRecord(theEnv,c2)); if (c2 == NULL) return(CopyConstraintRecord(theEnv,c1)); /*=================================*/ /* Create a new constraint record. */ /*=================================*/ rv = GetConstraintRecord(theEnv); /*==============================*/ /* Intersect the allowed types. */ /*==============================*/ if ((c1->multifieldsAllowed != c2->multifieldsAllowed) && (c1->singlefieldsAllowed != c2->singlefieldsAllowed)) { rv->anyAllowed = FALSE; return(rv); } if (c1->multifieldsAllowed && c2->multifieldsAllowed) { rv->multifieldsAllowed = TRUE; } else { rv->multifieldsAllowed = FALSE; } if (c1->singlefieldsAllowed && c2->singlefieldsAllowed) { rv->singlefieldsAllowed = TRUE; } else { rv->singlefieldsAllowed = FALSE; } if (c1->anyAllowed && c2->anyAllowed) rv->anyAllowed = TRUE; else { if (c1->anyAllowed) { c1Changed = TRUE; SetAnyAllowedFlags(c1,FALSE); } else if (c2->anyAllowed) { c2Changed = TRUE; SetAnyAllowedFlags(c2,FALSE); } 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->multifieldsAllowed = (c1->multifieldsAllowed && c2->multifieldsAllowed); rv->factAddressesAllowed = (c1->factAddressesAllowed && c2->factAddressesAllowed); if (c1Changed) SetAnyAllowedFlags(c1,TRUE); if (c2Changed) SetAnyAllowedFlags(c2,TRUE); } /*=====================================*/ /* Intersect the allowed-values flags. */ /*=====================================*/ if (c1->anyRestriction || c2->anyRestriction) rv->anyRestriction = TRUE; else { 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); } /*==================================================*/ /* Intersect the allowed values list, allowed class */ /* list, min and max values, and the range values. */ /*==================================================*/ IntersectAllowedValueExpressions(theEnv,c1,c2,rv); IntersectAllowedClassExpressions(theEnv,c1,c2,rv); IntersectNumericExpressions(theEnv,c1,c2,rv,TRUE); IntersectNumericExpressions(theEnv,c1,c2,rv,FALSE); /*==========================================*/ /* Update the allowed-values flags based on */ /* the previous intersection for allowed, */ /* min and max, and range values. */ /*==========================================*/ UpdateRestrictionFlags(rv); /*============================================*/ /* If multifields are allowed, then intersect */ /* the constraint record for them. */ /*============================================*/ if (rv->multifieldsAllowed) { rv->multifield = IntersectConstraints(theEnv,c1->multifield,c2->multifield); if (UnmatchableConstraint(rv->multifield)) { rv->multifieldsAllowed = FALSE; } } /*========================*/ /* Return the intersected */ /* constraint record. */ /*========================*/ return(rv); }/*************************************************//* IntersectAllowedValueExpressions: Creates the *//* intersection of two allowed-values lists. *//*************************************************/static void IntersectAllowedValueExpressions( void *theEnv, CONSTRAINT_RECORD *constraint1, CONSTRAINT_RECORD *constraint2, CONSTRAINT_RECORD *newConstraint) { struct expr *theList1, *theList2; struct expr *theHead = NULL, *tmpExpr; /*===========================================*/ /* Loop through each value in allowed-values */ /* list of the first constraint record. Add */ /* each value to a list if it satisfies the */ /* restrictions for both constraint records. */ /*===========================================*/ for (theList1 = constraint1->restrictionList; theList1 != NULL; theList1 = theList1->nextArg) { if (CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint1) && CheckAllowedValuesConstraint(theList1->type,theList1->value,constraint2)) { tmpExpr = GenConstant(theEnv,theList1->type,theList1->value); tmpExpr->nextArg = theHead; theHead = tmpExpr; } } /*===========================================*/ /* Loop through each value in allowed-values */ /* list of the second constraint record. Add */ /* each value to a list if it satisfies the */ /* restrictions for both constraint records. */ /*===========================================*/ for (theList2 = constraint2->restrictionList; theList2 != NULL; theList2 = theList2->nextArg) { if (FindItemInExpression(theList2->type,theList2->value,TRUE,theHead)) { /* The value is already in the list--Do nothing */ } else if (CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint1) && CheckAllowedValuesConstraint(theList2->type,theList2->value,constraint2)) { tmpExpr = GenConstant(theEnv,theList2->type,theList2->value); tmpExpr->nextArg = theHead; theHead = tmpExpr; } } /*================================================*/ /* Set the allowed values list for the constraint */ /* record to the intersected values of the two */ /* other constraint records. */ /*================================================*/ newConstraint->restrictionList = theHead; } /*************************************************//* IntersectAllowedClassExpressions: Creates the *//* intersection of two allowed-classes lists. *//*************************************************/static void IntersectAllowedClassExpressions( void *theEnv, CONSTRAINT_RECORD *constraint1, CONSTRAINT_RECORD *constraint2, CONSTRAINT_RECORD *newConstraint) { struct expr *theList1, *theList2; struct expr *theHead = NULL, *tmpExpr; /*============================================*/ /* Loop through each value in allowed-classes */ /* list of the first constraint record. Add */ /* each value to a list if it satisfies the */ /* restrictions for both constraint records. */ /*============================================*/ for (theList1 = constraint1->classList; theList1 != NULL; theList1 = theList1->nextArg) { if (CheckAllowedClassesConstraint(theEnv,theList1->type,theList1->value,constraint1) && CheckAllowedClassesConstraint(theEnv,theList1->type,theList1->value,constraint2)) { tmpExpr = GenConstant(theEnv,theList1->type,theList1->value); tmpExpr->nextArg = theHead; theHead = tmpExpr; } } /*============================================*/ /* Loop through each value in allowed-classes */ /* list of the second constraint record. Add */ /* each value to a list if it satisfies the */ /* restrictions for both constraint records. */ /*============================================*/ for (theList2 = constraint2->classList; theList2 != NULL; theList2 = theList2->nextArg) { if (FindItemInExpression(theList2->type,theList2->value,TRUE,theHead)) { /* The value is already in the list--Do nothing */ } else if (CheckAllowedClassesConstraint(theEnv,theList2->type,theList2->value,constraint1) && CheckAllowedClassesConstraint(theEnv,theList2->type,theList2->value,constraint2)) { tmpExpr = GenConstant(theEnv,theList2->type,theList2->value); tmpExpr->nextArg = theHead; theHead = tmpExpr; } } /*=================================================*/ /* Set the allowed classes list for the constraint */ /* record to the intersected values of the two */ /* other constraint records. */ /*=================================================*/ newConstraint->classList = theHead; } /*********************************************************//* IntersectNumericExpressions: Creates the intersection *//* of two range or two min/max-fields constraints. *//*********************************************************/static void IntersectNumericExpressions( void *theEnv, CONSTRAINT_RECORD *constraint1, CONSTRAINT_RECORD *constraint2, CONSTRAINT_RECORD *newConstraint, int range) { struct expr *tmpmin1, *tmpmax1, *tmpmin2, *tmpmax2, *theMin, *theMax; struct expr *theMinList, *theMaxList, *lastMin = NULL, *lastMax = NULL; int cmaxmax, cminmin, cmaxmin, cminmax; /*==========================================*/ /* Initialize the new range/min/max values */ /* for the intersection of the constraints. */ /*==========================================*/ theMinList = NULL; theMaxList = NULL; /*=================================*/ /* Determine the min/max values of */ /* the first constraint record. */ /*=================================*/ if (range) { tmpmin1 = constraint1->minValue; tmpmax1 = constraint1->maxValue;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -