#include <stdio.h>
#include <stdlib.h>
#include "setup.h"
#include "argacces.h"
#include "constant.h"
#include "envrnmnt.h"
#include "extnfunc.h"
#include "memalloc.h"
#include "multifld.h"
#include "router.h"
#include "scanner.h"
#include "constrnt.h"
#if (! RUN_TIME) && (! BLOAD_ONLY)
static void InstallConstraintRecord(Environment *,CONSTRAINT_RECORD *);
static bool ConstraintCompare(struct constraintRecord *,struct constraintRecord *);
#endif
static void ReturnConstraintRecord(Environment *,CONSTRAINT_RECORD *);
static void DeinstallConstraintRecord(Environment *,CONSTRAINT_RECORD *);
static void DeallocateConstraintData(Environment *);
void InitializeConstraints(
Environment *theEnv)
{
#if (! RUN_TIME) && (! BLOAD_ONLY)
int i;
#endif
AllocateEnvironmentData(theEnv,CONSTRAINT_DATA,sizeof(struct constraintData),DeallocateConstraintData);
#if (! RUN_TIME) && (! BLOAD_ONLY)
ConstraintData(theEnv)->ConstraintHashtable = (struct constraintRecord **)
gm2(theEnv,sizeof (struct constraintRecord *) *
SIZE_CONSTRAINT_HASH);
if (ConstraintData(theEnv)->ConstraintHashtable == NULL) ExitRouter(theEnv,EXIT_FAILURE);
for (i = 0; i < SIZE_CONSTRAINT_HASH; i++) ConstraintData(theEnv)->ConstraintHashtable[i] = NULL;
#endif
#if (! RUN_TIME)
AddUDF(theEnv,"get-dynamic-constraint-checking","b",0,0,NULL,GDCCommand,"GDCCommand",NULL);
AddUDF(theEnv,"set-dynamic-constraint-checking","b",1,1,NULL,SDCCommand,"SDCCommand",NULL);
#endif
}
static void DeallocateConstraintData(
Environment *theEnv)
{
#if ! RUN_TIME
struct constraintRecord *tmpPtr, *nextPtr;
int i;
for (i = 0; i < SIZE_CONSTRAINT_HASH; i++)
{
tmpPtr = ConstraintData(theEnv)->ConstraintHashtable[i];
while (tmpPtr != NULL)
{
nextPtr = tmpPtr->next;
ReturnConstraintRecord(theEnv,tmpPtr);
tmpPtr = nextPtr;
}
}
rm(theEnv,ConstraintData(theEnv)->ConstraintHashtable,
sizeof(struct constraintRecord *) * SIZE_CONSTRAINT_HASH);
#else
#if MAC_XCD
#pragma unused(theEnv)
#endif
#endif
#if (BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE) && (! RUN_TIME)
if (ConstraintData(theEnv)->NumberOfConstraints != 0)
{
genfree(theEnv,ConstraintData(theEnv)->ConstraintArray,
(sizeof(CONSTRAINT_RECORD) * ConstraintData(theEnv)->NumberOfConstraints));
}
#endif
}
static void ReturnConstraintRecord(
Environment *theEnv,
CONSTRAINT_RECORD *constraints)
{
if (constraints == NULL) return;
if (! constraints->installed)
{
ReturnExpression(theEnv,constraints->classList);
ReturnExpression(theEnv,constraints->restrictionList);
ReturnExpression(theEnv,constraints->maxValue);
ReturnExpression(theEnv,constraints->minValue);
ReturnExpression(theEnv,constraints->minFields);
ReturnExpression(theEnv,constraints->maxFields);
}
ReturnConstraintRecord(theEnv,constraints->multifield);
rtn_struct(theEnv,constraintRecord,constraints);
}
static void DeinstallConstraintRecord(
Environment *theEnv,
CONSTRAINT_RECORD *constraints)
{
if (constraints->installed)
{
RemoveHashedExpression(theEnv,constraints->classList);
RemoveHashedExpression(theEnv,constraints->restrictionList);
RemoveHashedExpression(theEnv,constraints->maxValue);
RemoveHashedExpression(theEnv,constraints->minValue);
RemoveHashedExpression(theEnv,constraints->minFields);
RemoveHashedExpression(theEnv,constraints->maxFields);
}
else
{
ExpressionDeinstall(theEnv,constraints->classList);
ExpressionDeinstall(theEnv,constraints->restrictionList);
ExpressionDeinstall(theEnv,constraints->maxValue);
ExpressionDeinstall(theEnv,constraints->minValue);
ExpressionDeinstall(theEnv,constraints->minFields);
ExpressionDeinstall(theEnv,constraints->maxFields);
}
if (constraints->multifield != NULL)
{ DeinstallConstraintRecord(theEnv,constraints->multifield); }
}
void RemoveConstraint(
Environment *theEnv,
struct constraintRecord *theConstraint)
{
struct constraintRecord *tmpPtr, *prevPtr = NULL;
if (theConstraint == NULL) return;
if (! theConstraint->installed)
{
ReturnConstraintRecord(theEnv,theConstraint);
return;
}
tmpPtr = ConstraintData(theEnv)->ConstraintHashtable[theConstraint->bucket];
while (tmpPtr != NULL)
{
if (tmpPtr == theConstraint)
{
theConstraint->count--;
if (theConstraint->count == 0)
{
if (prevPtr == NULL)
{ ConstraintData(theEnv)->ConstraintHashtable[theConstraint->bucket] = theConstraint->next; }
else
{ prevPtr->next = theConstraint->next; }
DeinstallConstraintRecord(theEnv,theConstraint);
ReturnConstraintRecord(theEnv,theConstraint);
}
return;
}
prevPtr = tmpPtr;
tmpPtr = tmpPtr->next;
}
return;
}
#if (! RUN_TIME) && (! BLOAD_ONLY)
unsigned long HashConstraint(
struct constraintRecord *theConstraint)
{
unsigned short i = 0;
unsigned long count = 0;
unsigned long hashValue;
struct expr *tmpPtr;
count +=
(theConstraint->anyAllowed * 17) +
(theConstraint->symbolsAllowed * 5) +
(theConstraint->stringsAllowed * 23) +
(theConstraint->floatsAllowed * 19) +
(theConstraint->integersAllowed * 29) +
(theConstraint->instanceNamesAllowed * 31) +
(theConstraint->instanceAddressesAllowed * 17);
count +=
(theConstraint->externalAddressesAllowed * 29) +
(theConstraint->voidAllowed * 29) +
(theConstraint->multifieldsAllowed * 29) +
(theConstraint->factAddressesAllowed * 79) +
(theConstraint->anyRestriction * 59) +
(theConstraint->symbolRestriction * 61);
count +=
(theConstraint->stringRestriction * 3) +
(theConstraint->floatRestriction * 37) +
(theConstraint->integerRestriction * 9) +
(theConstraint->classRestriction * 11) +
(theConstraint->instanceNameRestriction * 7);
for (tmpPtr = theConstraint->classList; tmpPtr != NULL; tmpPtr = tmpPtr->nextArg)
{ count += GetAtomicHashValue(tmpPtr->type,tmpPtr->value,i++); }
for (tmpPtr = theConstraint->restrictionList; tmpPtr != NULL; tmpPtr = tmpPtr->nextArg)
{ count += GetAtomicHashValue(tmpPtr->type,tmpPtr->value,i++); }
for (tmpPtr = theConstraint->minValue; tmpPtr != NULL; tmpPtr = tmpPtr->nextArg)
{ count += GetAtomicHashValue(tmpPtr->type,tmpPtr->value,i++); }
for (tmpPtr = theConstraint->maxValue; tmpPtr != NULL; tmpPtr = tmpPtr->nextArg)
{ count += GetAtomicHashValue(tmpPtr->type,tmpPtr->value,i++); }
for (tmpPtr = theConstraint->minFields; tmpPtr != NULL; tmpPtr = tmpPtr->nextArg)
{ count += GetAtomicHashValue(tmpPtr->type,tmpPtr->value,i++); }
for (tmpPtr = theConstraint->maxFields; tmpPtr != NULL; tmpPtr = tmpPtr->nextArg)
{ count += GetAtomicHashValue(tmpPtr->type,tmpPtr->value,i++); }
if (theConstraint->multifield != NULL)
{ count += HashConstraint(theConstraint->multifield); }
hashValue = count % SIZE_CONSTRAINT_HASH;
return hashValue;
}
static bool ConstraintCompare(
struct constraintRecord *constraint1,
struct constraintRecord *constraint2)
{
struct expr *tmpPtr1, *tmpPtr2;
if ((constraint1->anyAllowed != constraint2->anyAllowed) ||
(constraint1->symbolsAllowed != constraint2->symbolsAllowed) ||
(constraint1->stringsAllowed != constraint2->stringsAllowed) ||
(constraint1->floatsAllowed != constraint2->floatsAllowed) ||
(constraint1->integersAllowed != constraint2->integersAllowed) ||
(constraint1->instanceNamesAllowed != constraint2->instanceNamesAllowed) ||
(constraint1->instanceAddressesAllowed != constraint2->instanceAddressesAllowed) ||
(constraint1->externalAddressesAllowed != constraint2->externalAddressesAllowed) ||
(constraint1->voidAllowed != constraint2->voidAllowed) ||
(constraint1->multifieldsAllowed != constraint2->multifieldsAllowed) ||
(constraint1->singlefieldsAllowed != constraint2->singlefieldsAllowed) ||
(constraint1->factAddressesAllowed != constraint2->factAddressesAllowed) ||
(constraint1->anyRestriction != constraint2->anyRestriction) ||
(constraint1->symbolRestriction != constraint2->symbolRestriction) ||
(constraint1->stringRestriction != constraint2->stringRestriction) ||
(constraint1->floatRestriction != constraint2->floatRestriction) ||
(constraint1->integerRestriction != constraint2->integerRestriction) ||
(constraint1->classRestriction != constraint2->classRestriction) ||
(constraint1->instanceNameRestriction != constraint2->instanceNameRestriction))
{ return false; }
for (tmpPtr1 = constraint1->classList, tmpPtr2 = constraint2->classList;
(tmpPtr1 != NULL) && (tmpPtr2 != NULL);
tmpPtr1 = tmpPtr1->nextArg, tmpPtr2 = tmpPtr2->nextArg)
{
if ((tmpPtr1->type != tmpPtr2->type) || (tmpPtr1->value != tmpPtr2->value))
{ return false; }
}
if (tmpPtr1 != tmpPtr2) return false;
for (tmpPtr1 = constraint1->restrictionList, tmpPtr2 = constraint2->restrictionList;
(tmpPtr1 != NULL) && (tmpPtr2 != NULL);
tmpPtr1 = tmpPtr1->nextArg, tmpPtr2 = tmpPtr2->nextArg)
{
if ((tmpPtr1->type != tmpPtr2->type) || (tmpPtr1->value != tmpPtr2->value))
{ return false; }
}
if (tmpPtr1 != tmpPtr2) return false;
for (tmpPtr1 = constraint1->minValue, tmpPtr2 = constraint2->minValue;
(tmpPtr1 != NULL) && (tmpPtr2 != NULL);
tmpPtr1 = tmpPtr1->nextArg, tmpPtr2 = tmpPtr2->nextArg)
{
if ((tmpPtr1->type != tmpPtr2->type) || (tmpPtr1->value != tmpPtr2->value))
{ return false; }
}
if (tmpPtr1 != tmpPtr2) return false;
for (tmpPtr1 = constraint1->maxValue, tmpPtr2 = constraint2->maxValue;
(tmpPtr1 != NULL) && (tmpPtr2 != NULL);
tmpPtr1 = tmpPtr1->nextArg, tmpPtr2 = tmpPtr2->nextArg)
{
if ((tmpPtr1->type != tmpPtr2->type) || (tmpPtr1->value != tmpPtr2->value))
{ return false; }
}
if (tmpPtr1 != tmpPtr2) return false;
for (tmpPtr1 = constraint1->minFields, tmpPtr2 = constraint2->minFields;
(tmpPtr1 != NULL) && (tmpPtr2 != NULL);
tmpPtr1 = tmpPtr1->nextArg, tmpPtr2 = tmpPtr2->nextArg)
{
if ((tmpPtr1->type != tmpPtr2->type) || (tmpPtr1->value != tmpPtr2->value))
{ return false; }
}
if (tmpPtr1 != tmpPtr2) return false;
for (tmpPtr1 = constraint1->maxFields, tmpPtr2 = constraint2->maxFields;
(tmpPtr1 != NULL) && (tmpPtr2 != NULL);
tmpPtr1 = tmpPtr1->nextArg, tmpPtr2 = tmpPtr2->nextArg)
{
if ((tmpPtr1->type != tmpPtr2->type) || (tmpPtr1->value != tmpPtr2->value))
{ return false; }
}
if (tmpPtr1 != tmpPtr2) return false;
if (((constraint1->multifield == NULL) && (constraint2->multifield != NULL)) ||
((constraint1->multifield != NULL) && (constraint2->multifield == NULL)))
{ return false; }
else if (constraint1->multifield == constraint2->multifield)
{ return true; }
return(ConstraintCompare(constraint1->multifield,constraint2->multifield));
}
struct constraintRecord *AddConstraint(
Environment *theEnv,
struct constraintRecord *theConstraint)
{
struct constraintRecord *tmpPtr;
unsigned long hashValue;
if (theConstraint == NULL) return NULL;
hashValue = HashConstraint(theConstraint);
for (tmpPtr = ConstraintData(theEnv)->ConstraintHashtable[hashValue];
tmpPtr != NULL;
tmpPtr = tmpPtr->next)
{
if (ConstraintCompare(theConstraint,tmpPtr))
{
tmpPtr->count++;
ReturnConstraintRecord(theEnv,theConstraint);
return tmpPtr;
}
}
InstallConstraintRecord(theEnv,theConstraint);
theConstraint->count = 1;
theConstraint->bucket = (unsigned int) hashValue;
theConstraint->installed = true;
theConstraint->next = ConstraintData(theEnv)->ConstraintHashtable[hashValue];
ConstraintData(theEnv)->ConstraintHashtable[hashValue] = theConstraint;
return theConstraint;
}
static void InstallConstraintRecord(
Environment *theEnv,
CONSTRAINT_RECORD *constraints)
{
struct expr *tempExpr;
tempExpr = AddHashedExpression(theEnv,constraints->classList);
ReturnExpression(theEnv,constraints->classList);
constraints->classList = tempExpr;
tempExpr = AddHashedExpression(theEnv,constraints->restrictionList);
ReturnExpression(theEnv,constraints->restrictionList);
constraints->restrictionList = tempExpr;
tempExpr = AddHashedExpression(theEnv,constraints->maxValue);
ReturnExpression(theEnv,constraints->maxValue);
constraints->maxValue = tempExpr;
tempExpr = AddHashedExpression(theEnv,constraints->minValue);
ReturnExpression(theEnv,constraints->minValue);
constraints->minValue = tempExpr;
tempExpr = AddHashedExpression(theEnv,constraints->minFields);
ReturnExpression(theEnv,constraints->minFields);
constraints->minFields = tempExpr;
tempExpr = AddHashedExpression(theEnv,constraints->maxFields);
ReturnExpression(theEnv,constraints->maxFields);
constraints->maxFields = tempExpr;
if (constraints->multifield != NULL)
{ InstallConstraintRecord(theEnv,constraints->multifield); }
}
#endif
void SDCCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
UDFValue theArg;
returnValue->lexemeValue = CreateBoolean(theEnv,GetDynamicConstraintChecking(theEnv));
if (! UDFFirstArgument(context,ANY_TYPE_BITS,&theArg))
{ return; }
SetDynamicConstraintChecking(theEnv,theArg.value != FalseSymbol(theEnv));
}
void GDCCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
returnValue->lexemeValue = CreateBoolean(theEnv,GetDynamicConstraintChecking(theEnv));
}
bool SetDynamicConstraintChecking(
Environment *theEnv,
bool value)
{
bool ov;
ov = ConstraintData(theEnv)->DynamicConstraintChecking;
ConstraintData(theEnv)->DynamicConstraintChecking = value;
return(ov);
}
bool GetDynamicConstraintChecking(
Environment *theEnv)
{
return(ConstraintData(theEnv)->DynamicConstraintChecking);
}