#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "setup.h"
#include "argacces.h"
#include "commline.h"
#include "constant.h"
#include "envrnmnt.h"
#include "factmngr.h"
#include "memalloc.h"
#include "modulutl.h"
#include "router.h"
#include "prcdrfun.h"
#include "multifld.h"
#include "prntutil.h"
#include "exprnpsr.h"
#include "utility.h"
#include "proflfun.h"
#include "sysdep.h"
#if DEFFUNCTION_CONSTRUCT
#include "dffnxfun.h"
#endif
#if DEFGENERIC_CONSTRUCT
#include "genrccom.h"
#endif
#if OBJECT_SYSTEM
#include "object.h"
#include "inscom.h"
#endif
#include "evaluatn.h"
static void DeallocateEvaluationData(Environment *);
static void PrintCAddress(Environment *,const char *,void *);
static void NewCAddress(UDFContext *,UDFValue *);
void InitializeEvaluationData(
Environment *theEnv)
{
struct externalAddressType cPointer = { "C", PrintCAddress, PrintCAddress, NULL, NewCAddress, NULL };
AllocateEnvironmentData(theEnv,EVALUATION_DATA,sizeof(struct evaluationData),DeallocateEvaluationData);
InstallExternalAddressType(theEnv,&cPointer);
}
static void DeallocateEvaluationData(
Environment *theEnv)
{
int i;
for (i = 0; i < EvaluationData(theEnv)->numberOfAddressTypes; i++)
{ rtn_struct(theEnv,externalAddressType,EvaluationData(theEnv)->ExternalAddressTypes[i]); }
}
bool EvaluateExpression(
Environment *theEnv,
struct expr *problem,
UDFValue *returnValue)
{
struct expr *oldArgument;
struct functionDefinition *fptr;
UDFContext theUDFContext;
#if PROFILING_FUNCTIONS
struct profileFrameInfo profileFrame;
#endif
returnValue->voidValue = VoidConstant(theEnv);
returnValue->begin = 0;
returnValue->range = SIZE_MAX;
if (problem == NULL)
{
returnValue->value = FalseSymbol(theEnv);
return(EvaluationData(theEnv)->EvaluationError);
}
switch (problem->type)
{
case STRING_TYPE:
case SYMBOL_TYPE:
case FLOAT_TYPE:
case INTEGER_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
case INSTANCE_ADDRESS_TYPE:
#endif
case FACT_ADDRESS_TYPE:
case EXTERNAL_ADDRESS_TYPE:
returnValue->value = problem->value;
break;
case FCALL:
{
fptr = problem->functionValue;
#if PROFILING_FUNCTIONS
StartProfile(theEnv,&profileFrame,
&fptr->usrData,
ProfileFunctionData(theEnv)->ProfileUserFunctions);
#endif
oldArgument = EvaluationData(theEnv)->CurrentExpression;
EvaluationData(theEnv)->CurrentExpression = problem;
theUDFContext.environment = theEnv;
theUDFContext.context = fptr->context;
theUDFContext.theFunction = fptr;
theUDFContext.lastArg = problem->argList;
theUDFContext.lastPosition = 1;
theUDFContext.returnValue = returnValue;
fptr->functionPointer(theEnv,&theUDFContext,returnValue);
if ((returnValue->header->type == MULTIFIELD_TYPE) &&
(returnValue->range == SIZE_MAX))
{ returnValue->range = returnValue->multifieldValue->length; }
#if PROFILING_FUNCTIONS
EndProfile(theEnv,&profileFrame);
#endif
EvaluationData(theEnv)->CurrentExpression = oldArgument;
break;
}
case MULTIFIELD_TYPE:
returnValue->value = ((UDFValue *) (problem->value))->value;
returnValue->begin = ((UDFValue *) (problem->value))->begin;
returnValue->range = ((UDFValue *) (problem->value))->range;
break;
case MF_VARIABLE:
case SF_VARIABLE:
if (GetBoundVariable(theEnv,returnValue,problem->lexemeValue) == false)
{
PrintErrorID(theEnv,"EVALUATN",1,false);
WriteString(theEnv,STDERR,"Variable ");
if (problem->type == MF_VARIABLE)
{ WriteString(theEnv,STDERR,"$?"); }
else
{ WriteString(theEnv,STDERR,"?"); }
WriteString(theEnv,STDERR,problem->lexemeValue->contents);
WriteString(theEnv,STDERR," is unbound.\n");
returnValue->value = FalseSymbol(theEnv);
SetEvaluationError(theEnv,true);
}
break;
default:
if (EvaluationData(theEnv)->PrimitivesArray[problem->type] == NULL)
{
SystemError(theEnv,"EVALUATN",3);
ExitRouter(theEnv,EXIT_FAILURE);
}
if (EvaluationData(theEnv)->PrimitivesArray[problem->type]->copyToEvaluate)
{
returnValue->value = problem->value;
break;
}
if (EvaluationData(theEnv)->PrimitivesArray[problem->type]->evaluateFunction == NULL)
{
SystemError(theEnv,"EVALUATN",4);
ExitRouter(theEnv,EXIT_FAILURE);
}
oldArgument = EvaluationData(theEnv)->CurrentExpression;
EvaluationData(theEnv)->CurrentExpression = problem;
#if PROFILING_FUNCTIONS
StartProfile(theEnv,&profileFrame,
&EvaluationData(theEnv)->PrimitivesArray[problem->type]->usrData,
ProfileFunctionData(theEnv)->ProfileUserFunctions);
#endif
(*EvaluationData(theEnv)->PrimitivesArray[problem->type]->evaluateFunction)(theEnv,problem->value,returnValue);
#if PROFILING_FUNCTIONS
EndProfile(theEnv,&profileFrame);
#endif
EvaluationData(theEnv)->CurrentExpression = oldArgument;
break;
}
return EvaluationData(theEnv)->EvaluationError;
}
void InstallPrimitive(
Environment *theEnv,
struct entityRecord *thePrimitive,
int whichPosition)
{
if (EvaluationData(theEnv)->PrimitivesArray[whichPosition] != NULL)
{
SystemError(theEnv,"EVALUATN",5);
ExitRouter(theEnv,EXIT_FAILURE);
}
EvaluationData(theEnv)->PrimitivesArray[whichPosition] = thePrimitive;
}
int InstallExternalAddressType(
Environment *theEnv,
struct externalAddressType *theAddressType)
{
struct externalAddressType *copyEAT;
int rv = EvaluationData(theEnv)->numberOfAddressTypes;
if (EvaluationData(theEnv)->numberOfAddressTypes == MAXIMUM_EXTERNAL_ADDRESS_TYPES)
{
SystemError(theEnv,"EVALUATN",6);
ExitRouter(theEnv,EXIT_FAILURE);
}
copyEAT = (struct externalAddressType *) genalloc(theEnv,sizeof(struct externalAddressType));
memcpy(copyEAT,theAddressType,sizeof(struct externalAddressType));
EvaluationData(theEnv)->ExternalAddressTypes[EvaluationData(theEnv)->numberOfAddressTypes++] = copyEAT;
return rv;
}
void ResetErrorFlags(
Environment *theEnv)
{
EvaluationData(theEnv)->EvaluationError = false;
EvaluationData(theEnv)->HaltExecution = false;
}
void SetEvaluationError(
Environment *theEnv,
bool value)
{
EvaluationData(theEnv)->EvaluationError = value;
if (value == true)
{ EvaluationData(theEnv)->HaltExecution = true; }
}
bool GetEvaluationError(
Environment *theEnv)
{
return(EvaluationData(theEnv)->EvaluationError);
}
void SetHaltExecution(
Environment *theEnv,
bool value)
{
EvaluationData(theEnv)->HaltExecution = value;
}
bool GetHaltExecution(
Environment *theEnv)
{
return(EvaluationData(theEnv)->HaltExecution);
}
void ReturnValues(
Environment *theEnv,
UDFValue *garbagePtr,
bool decrementSupplementalInfo)
{
UDFValue *nextPtr;
while (garbagePtr != NULL)
{
nextPtr = garbagePtr->next;
ReleaseUDFV(theEnv,garbagePtr);
if ((garbagePtr->supplementalInfo != NULL) && decrementSupplementalInfo)
{ ReleaseLexeme(theEnv,(CLIPSLexeme *) garbagePtr->supplementalInfo); }
rtn_struct(theEnv,udfValue,garbagePtr);
garbagePtr = nextPtr;
}
}
void WriteCLIPSValue(
Environment *theEnv,
const char *fileid,
CLIPSValue *argPtr)
{
switch(argPtr->header->type)
{
case VOID_TYPE:
case SYMBOL_TYPE:
case STRING_TYPE:
case INTEGER_TYPE:
case FLOAT_TYPE:
case EXTERNAL_ADDRESS_TYPE:
case FACT_ADDRESS_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
case INSTANCE_ADDRESS_TYPE:
#endif
PrintAtom(theEnv,fileid,argPtr->header->type,argPtr->value);
break;
case MULTIFIELD_TYPE:
PrintMultifieldDriver(theEnv,fileid,argPtr->multifieldValue,
0,argPtr->multifieldValue->length,true);
break;
default:
WriteString(theEnv,fileid,"<UnknownPrintType");
WriteInteger(theEnv,fileid,argPtr->header->type);
WriteString(theEnv,fileid,">");
SetHaltExecution(theEnv,true);
SetEvaluationError(theEnv,true);
break;
}
}
void WriteUDFValue(
Environment *theEnv,
const char *fileid,
UDFValue *argPtr)
{
switch(argPtr->header->type)
{
case VOID_TYPE:
case SYMBOL_TYPE:
case STRING_TYPE:
case INTEGER_TYPE:
case FLOAT_TYPE:
case EXTERNAL_ADDRESS_TYPE:
case FACT_ADDRESS_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
case INSTANCE_ADDRESS_TYPE:
#endif
PrintAtom(theEnv,fileid,argPtr->header->type,argPtr->value);
break;
case MULTIFIELD_TYPE:
PrintMultifieldDriver(theEnv,fileid,argPtr->multifieldValue,
argPtr->begin,argPtr->range,true);
break;
default:
WriteString(theEnv,fileid,"<UnknownPrintType");
WriteInteger(theEnv,fileid,argPtr->header->type);
WriteString(theEnv,fileid,">");
SetHaltExecution(theEnv,true);
SetEvaluationError(theEnv,true);
break;
}
}
void SetMultifieldErrorValue(
Environment *theEnv,
UDFValue *returnValue)
{
returnValue->value = CreateMultifield(theEnv,0L);
returnValue->begin = 0;
returnValue->range = 0;
}
void RetainUDFV(
Environment *theEnv,
UDFValue *vPtr)
{
if (vPtr->header->type == MULTIFIELD_TYPE)
{ IncrementCLIPSValueMultifieldReferenceCount(theEnv,vPtr->multifieldValue); }
else
{ Retain(theEnv,vPtr->header); }
}
void ReleaseUDFV(
Environment *theEnv,
UDFValue *vPtr)
{
if (vPtr->header->type == MULTIFIELD_TYPE)
{ DecrementCLIPSValueMultifieldReferenceCount(theEnv,vPtr->multifieldValue); }
else
{ Release(theEnv,vPtr->header); }
}
void RetainCV(
Environment *theEnv,
CLIPSValue *vPtr)
{
if (vPtr->header->type == MULTIFIELD_TYPE)
{ IncrementCLIPSValueMultifieldReferenceCount(theEnv,vPtr->multifieldValue); }
else
{ Retain(theEnv,vPtr->header); }
}
void ReleaseCV(
Environment *theEnv,
CLIPSValue *vPtr)
{
if (vPtr->header->type == MULTIFIELD_TYPE)
{ DecrementCLIPSValueMultifieldReferenceCount(theEnv,vPtr->multifieldValue); }
else
{ Release(theEnv,vPtr->header); }
}
void Retain(
Environment *theEnv,
TypeHeader *th)
{
switch (th->type)
{
case SYMBOL_TYPE:
case STRING_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
#endif
IncrementLexemeCount(th);
break;
case FLOAT_TYPE:
IncrementFloatCount(th);
break;
case INTEGER_TYPE:
IncrementIntegerCount(th);
break;
case EXTERNAL_ADDRESS_TYPE:
IncrementExternalAddressCount(th);
break;
case MULTIFIELD_TYPE:
RetainMultifield(theEnv,(Multifield *) th);
break;
#if OBJECT_SYSTEM
case INSTANCE_ADDRESS_TYPE:
RetainInstance((Instance *) th);
break;
#endif
#if DEFTEMPLATE_CONSTRUCT
case FACT_ADDRESS_TYPE:
RetainFact((Fact *) th);
break;
#endif
case VOID_TYPE:
break;
default:
SystemError(theEnv,"EVALUATN",7);
ExitRouter(theEnv,EXIT_FAILURE);
break;
}
}
void Release(
Environment *theEnv,
TypeHeader *th)
{
switch (th->type)
{
case SYMBOL_TYPE:
case STRING_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
#endif
ReleaseLexeme(theEnv,(CLIPSLexeme *) th);
break;
case FLOAT_TYPE:
ReleaseFloat(theEnv,(CLIPSFloat *) th);
break;
case INTEGER_TYPE:
ReleaseInteger(theEnv,(CLIPSInteger *) th);
break;
case EXTERNAL_ADDRESS_TYPE:
ReleaseExternalAddress(theEnv,(CLIPSExternalAddress *) th);
break;
case MULTIFIELD_TYPE:
ReleaseMultifield(theEnv,(Multifield *) th);
break;
#if OBJECT_SYSTEM
case INSTANCE_ADDRESS_TYPE:
ReleaseInstance((Instance *) th);
break;
#endif
#if DEFTEMPLATE_CONSTRUCT
case FACT_ADDRESS_TYPE:
ReleaseFact((Fact *) th);
break;
#endif
case VOID_TYPE:
break;
default:
SystemError(theEnv,"EVALUATN",8);
ExitRouter(theEnv,EXIT_FAILURE);
break;
}
}
void AtomInstall(
Environment *theEnv,
unsigned short type,
void *vPtr)
{
switch (type)
{
case SYMBOL_TYPE:
case STRING_TYPE:
#if DEFGLOBAL_CONSTRUCT
case GBL_VARIABLE:
#endif
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
#endif
IncrementLexemeCount(vPtr);
break;
case FLOAT_TYPE:
IncrementFloatCount(vPtr);
break;
case INTEGER_TYPE:
IncrementIntegerCount(vPtr);
break;
case EXTERNAL_ADDRESS_TYPE:
IncrementExternalAddressCount(vPtr);
break;
case MULTIFIELD_TYPE:
RetainMultifield(theEnv,(Multifield *) vPtr);
break;
case VOID_TYPE:
break;
default:
if (EvaluationData(theEnv)->PrimitivesArray[type] == NULL) break;
if (EvaluationData(theEnv)->PrimitivesArray[type]->bitMap) IncrementBitMapCount(vPtr);
else if (EvaluationData(theEnv)->PrimitivesArray[type]->incrementBusyCount)
{ (*EvaluationData(theEnv)->PrimitivesArray[type]->incrementBusyCount)(theEnv,vPtr); }
break;
}
}
void AtomDeinstall(
Environment *theEnv,
unsigned short type,
void *vPtr)
{
switch (type)
{
case SYMBOL_TYPE:
case STRING_TYPE:
#if DEFGLOBAL_CONSTRUCT
case GBL_VARIABLE:
#endif
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
#endif
ReleaseLexeme(theEnv,(CLIPSLexeme *) vPtr);
break;
case FLOAT_TYPE:
ReleaseFloat(theEnv,(CLIPSFloat *) vPtr);
break;
case INTEGER_TYPE:
ReleaseInteger(theEnv,(CLIPSInteger *) vPtr);
break;
case EXTERNAL_ADDRESS_TYPE:
ReleaseExternalAddress(theEnv,(CLIPSExternalAddress *) vPtr);
break;
case MULTIFIELD_TYPE:
ReleaseMultifield(theEnv,(Multifield *) vPtr);
break;
case VOID_TYPE:
break;
default:
if (EvaluationData(theEnv)->PrimitivesArray[type] == NULL) break;
if (EvaluationData(theEnv)->PrimitivesArray[type]->bitMap) DecrementBitMapReferenceCount(theEnv,(CLIPSBitMap *) vPtr);
else if (EvaluationData(theEnv)->PrimitivesArray[type]->decrementBusyCount)
{ (*EvaluationData(theEnv)->PrimitivesArray[type]->decrementBusyCount)(theEnv,vPtr); }
}
}
void CopyDataObject(
Environment *theEnv,
UDFValue *dst,
UDFValue *src,
int garbageMultifield)
{
if (src->header->type != MULTIFIELD_TYPE)
{
dst->value = src->value;
}
else
{
DuplicateMultifield(theEnv,dst,src);
if (garbageMultifield)
{ AddToMultifieldList(theEnv,dst->multifieldValue); }
}
}
void TransferDataObjectValues(
UDFValue *dst,
UDFValue *src)
{
dst->value = src->value;
dst->begin = src->begin;
dst->range = src->range;
dst->supplementalInfo = src->supplementalInfo;
dst->next = src->next;
}
struct expr *ConvertValueToExpression(
Environment *theEnv,
UDFValue *theValue)
{
size_t i;
struct expr *head = NULL, *last = NULL, *newItem;
if (theValue->header->type != MULTIFIELD_TYPE)
{ return(GenConstant(theEnv,theValue->header->type,theValue->value)); }
for (i = theValue->begin; i < (theValue->begin + theValue->range); i++)
{
newItem = GenConstant(theEnv,theValue->multifieldValue->contents[i].header->type,
theValue->multifieldValue->contents[i].value);
if (last == NULL) head = newItem;
else last->nextArg = newItem;
last = newItem;
}
if (head == NULL)
return(GenConstant(theEnv,FCALL,FindFunction(theEnv,"create$")));
return(head);
}
unsigned long GetAtomicHashValue(
unsigned short type,
void *value,
unsigned short position)
{
unsigned long tvalue;
union
{
double fv;
void *vv;
unsigned long liv;
} fis;
switch (type)
{
case FLOAT_TYPE:
fis.liv = 0;
fis.fv = ((CLIPSFloat *) value)->contents;
tvalue = fis.liv;
break;
case INTEGER_TYPE:
tvalue = (unsigned long) ((CLIPSInteger *) value)->contents;
break;
case EXTERNAL_ADDRESS_TYPE:
fis.liv = 0;
fis.vv = ((CLIPSExternalAddress *) value)->contents;
tvalue = fis.liv;
break;
case FACT_ADDRESS_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_ADDRESS_TYPE:
#endif
fis.liv = 0;
fis.vv = value;
tvalue = fis.liv;
break;
case STRING_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
#endif
case SYMBOL_TYPE:
tvalue = ((CLIPSLexeme *) value)->bucket;
break;
default:
tvalue = type;
}
return tvalue * (position + 29);
}
struct expr *FunctionReferenceExpression(
Environment *theEnv,
const char *name)
{
#if DEFGENERIC_CONSTRUCT
Defgeneric *gfunc;
#endif
#if DEFFUNCTION_CONSTRUCT
Deffunction *dptr;
#endif
struct functionDefinition *fptr;
#if DEFFUNCTION_CONSTRUCT
if ((dptr = LookupDeffunctionInScope(theEnv,name)) != NULL)
{ return(GenConstant(theEnv,PCALL,dptr)); }
#endif
#if DEFGENERIC_CONSTRUCT
if ((gfunc = LookupDefgenericInScope(theEnv,name)) != NULL)
{ return(GenConstant(theEnv,GCALL,gfunc)); }
#endif
if ((fptr = FindFunction(theEnv,name)) != NULL)
{ return(GenConstant(theEnv,FCALL,fptr)); }
return NULL;
}
bool GetFunctionReference(
Environment *theEnv,
const char *name,
Expression *theReference)
{
#if DEFGENERIC_CONSTRUCT
Defgeneric *gfunc;
#endif
#if DEFFUNCTION_CONSTRUCT
Deffunction *dptr;
#endif
struct functionDefinition *fptr;
bool moduleSpecified = false;
unsigned position;
CLIPSLexeme *moduleName = NULL, *constructName = NULL;
theReference->nextArg = NULL;
theReference->argList = NULL;
theReference->type = VOID_TYPE;
theReference->value = NULL;
if ((position = FindModuleSeparator(name)) != 0)
{
moduleName = ExtractModuleName(theEnv,position,name);
constructName = ExtractConstructName(theEnv,position,name,SYMBOL_TYPE);
moduleSpecified = true;
}
#if DEFGENERIC_CONSTRUCT
if (moduleSpecified)
{
if (ConstructExported(theEnv,"defgeneric",moduleName,constructName) ||
GetCurrentModule(theEnv) == FindDefmodule(theEnv,moduleName->contents))
{
if ((gfunc = FindDefgenericInModule(theEnv,name)) != NULL)
{
theReference->type = GCALL;
theReference->value = gfunc;
return true;
}
}
}
else
{
if ((gfunc = LookupDefgenericInScope(theEnv,name)) != NULL)
{
theReference->type = GCALL;
theReference->value = gfunc;
return true;
}
}
#endif
#if DEFFUNCTION_CONSTRUCT
if (moduleSpecified)
{
if (ConstructExported(theEnv,"deffunction",moduleName,constructName) ||
GetCurrentModule(theEnv) == FindDefmodule(theEnv,moduleName->contents))
{
if ((dptr = FindDeffunctionInModule(theEnv,name)) != NULL)
{
theReference->type = PCALL;
theReference->value = dptr;
return true;
}
}
}
else
{
if ((dptr = LookupDeffunctionInScope(theEnv,name)) != NULL)
{
theReference->type = PCALL;
theReference->value = dptr;
return true;
}
}
#endif
if ((fptr = FindFunction(theEnv,name)) != NULL)
{
theReference->type = FCALL;
theReference->value = fptr;
return true;
}
return false;
}
bool DOsEqual(
UDFValue *dobj1,
UDFValue *dobj2)
{
if (dobj1->header->type != dobj2->header->type)
{ return false; }
if (dobj1->header->type == MULTIFIELD_TYPE)
{
if (MultifieldDOsEqual(dobj1,dobj2) == false)
{ return false; }
}
else if (dobj1->value != dobj2->value)
{ return false; }
return true;
}
bool EvaluateAndStoreInDataObject(
Environment *theEnv,
bool mfp,
Expression *theExp,
UDFValue *val,
bool garbageSegment)
{
val->begin = 0;
val->range = 0;
if (theExp == NULL)
{
if (garbageSegment) val->value = CreateMultifield(theEnv,0L);
else val->value = CreateUnmanagedMultifield(theEnv,0L);
return true;
}
if ((mfp == false) && (theExp->nextArg == NULL))
EvaluateExpression(theEnv,theExp,val);
else
StoreInMultifield(theEnv,val,theExp,garbageSegment);
return(EvaluationData(theEnv)->EvaluationError ? false : true);
}
static void PrintCAddress(
Environment *theEnv,
const char *logicalName,
void *theValue)
{
char buffer[20];
WriteString(theEnv,logicalName,"<Pointer-C-");
gensprintf(buffer,"%p",((CLIPSExternalAddress *) theValue)->contents);
WriteString(theEnv,logicalName,buffer);
WriteString(theEnv,logicalName,">");
}
static void NewCAddress(
UDFContext *context,
UDFValue *rv)
{
unsigned int numberOfArguments;
Environment *theEnv = context->environment;
numberOfArguments = UDFArgumentCount(context);
if (numberOfArguments != 1)
{
PrintErrorID(theEnv,"NEW",1,false);
WriteString(theEnv,STDERR,"Function new expected no additional arguments for the C external language type.\n");
SetEvaluationError(theEnv,true);
return;
}
rv->value = CreateExternalAddress(theEnv,NULL,0);
}
FunctionCallBuilder *CreateFunctionCallBuilder(
Environment *theEnv,
size_t theSize)
{
FunctionCallBuilder *theFC;
if (theEnv == NULL) return NULL;
theFC = get_struct(theEnv,functionCallBuilder);
theFC->fcbEnv = theEnv;
theFC->bufferReset = theSize;
theFC->bufferMaximum = theSize;
theFC->length = 0;
if (theSize == 0)
{ theFC->contents = NULL; }
else
{ theFC->contents = (CLIPSValue *) gm2(theEnv,sizeof(CLIPSValue) * theSize); }
return theFC;
}
void FCBAppendUDFValue(
FunctionCallBuilder *theFCB,
UDFValue *theValue)
{
Environment *theEnv = theFCB->fcbEnv;
size_t i, neededSize, newSize;
CLIPSValue *newArray;
if (theValue->header->type == VOID_TYPE)
{ return; }
neededSize = theFCB->length + 1;
if (neededSize > theFCB->bufferMaximum)
{
newSize = neededSize * 2;
newArray = (CLIPSValue *) gm2(theEnv,sizeof(CLIPSValue) * newSize);
for (i = 0; i < theFCB->length; i++)
{ newArray[i] = theFCB->contents[i]; }
if (theFCB->bufferMaximum != 0)
{ rm(theFCB->fcbEnv,theFCB->contents,sizeof(CLIPSValue) * theFCB->bufferMaximum); }
theFCB->bufferMaximum = newSize;
theFCB->contents = newArray;
}
if (theValue->header->type == MULTIFIELD_TYPE)
{
CLIPSValue newValue;
UDFToCLIPSValue(theEnv,theValue,&newValue);
theFCB->contents[theFCB->length].value = newValue.value;
}
else
{ theFCB->contents[theFCB->length].value = theValue->value; }
Retain(theEnv,theFCB->contents[theFCB->length].header);
theFCB->length++;
}
void FCBAppend(
FunctionCallBuilder *theFCB,
CLIPSValue *theValue)
{
Environment *theEnv = theFCB->fcbEnv;
size_t i, neededSize, newSize;
CLIPSValue *newArray;
if (theValue->header->type == VOID_TYPE)
{ return; }
neededSize = theFCB->length + 1;
if (neededSize > theFCB->bufferMaximum)
{
newSize = neededSize * 2;
newArray = (CLIPSValue *) gm2(theEnv,sizeof(CLIPSValue) * newSize);
for (i = 0; i < theFCB->length; i++)
{ newArray[i] = theFCB->contents[i]; }
if (theFCB->bufferMaximum != 0)
{ rm(theFCB->fcbEnv,theFCB->contents,sizeof(CLIPSValue) * theFCB->bufferMaximum); }
theFCB->bufferMaximum = newSize;
theFCB->contents = newArray;
}
theFCB->contents[theFCB->length].value = theValue->value;
Retain(theEnv,theFCB->contents[theFCB->length].header);
theFCB->length++;
}
void FCBAppendCLIPSInteger(
FunctionCallBuilder *theFCB,
CLIPSInteger *pv)
{
CLIPSValue theValue;
theValue.integerValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendInteger(
FunctionCallBuilder *theFCB,
long long intValue)
{
CLIPSValue theValue;
CLIPSInteger *pv = CreateInteger(theFCB->fcbEnv,intValue);
theValue.integerValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendCLIPSFloat(
FunctionCallBuilder *theFCB,
CLIPSFloat *pv)
{
CLIPSValue theValue;
theValue.floatValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendFloat(
FunctionCallBuilder *theFCB,
double floatValue)
{
CLIPSValue theValue;
CLIPSFloat *pv = CreateFloat(theFCB->fcbEnv,floatValue);
theValue.floatValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendCLIPSLexeme(
FunctionCallBuilder *theFCB,
CLIPSLexeme *pv)
{
CLIPSValue theValue;
theValue.lexemeValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendSymbol(
FunctionCallBuilder *theFCB,
const char *strValue)
{
CLIPSValue theValue;
CLIPSLexeme *pv = CreateSymbol(theFCB->fcbEnv,strValue);
theValue.lexemeValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendString(
FunctionCallBuilder *theFCB,
const char *strValue)
{
CLIPSValue theValue;
CLIPSLexeme *pv = CreateString(theFCB->fcbEnv,strValue);
theValue.lexemeValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendInstanceName(
FunctionCallBuilder *theFCB,
const char *strValue)
{
CLIPSValue theValue;
CLIPSLexeme *pv = CreateInstanceName(theFCB->fcbEnv,strValue);
theValue.lexemeValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendCLIPSExternalAddress(
FunctionCallBuilder *theFCB,
CLIPSExternalAddress *pv)
{
CLIPSValue theValue;
theValue.externalAddressValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendFact(
FunctionCallBuilder *theFCB,
Fact *pv)
{
CLIPSValue theValue;
theValue.factValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendInstance(
FunctionCallBuilder *theFCB,
Instance *pv)
{
CLIPSValue theValue;
theValue.instanceValue = pv;
FCBAppend(theFCB,&theValue);
}
void FCBAppendMultifield(
FunctionCallBuilder *theFCB,
Multifield *pv)
{
CLIPSValue theValue;
theValue.multifieldValue = pv;
FCBAppend(theFCB,&theValue);
}
FunctionCallBuilderError FCBCall(
FunctionCallBuilder *theFCB,
const char *functionName,
CLIPSValue *returnValue)
{
Environment *theEnv;
Expression theReference, *lastAdd = NULL, *nextAdd, *multiAdd;
struct functionDefinition *theFunction = NULL;
size_t i, j;
UDFValue udfReturnValue;
GCBlock gcb;
if ((theFCB == NULL) || (functionName == NULL))
{ return FCBE_NULL_POINTER_ERROR; }
if (! GetFunctionReference(theFCB->fcbEnv,functionName,&theReference))
{ return FCBE_FUNCTION_NOT_FOUND_ERROR; }
if (theReference.type == FCALL)
{
theFunction = FindFunction(theFCB->fcbEnv,functionName);
if (theFunction->parser != NULL)
{ return FCBE_INVALID_FUNCTION_ERROR; }
}
theEnv = theFCB->fcbEnv;
for (i = 0; i < theFCB->length; i++)
{
if (theFCB->contents[i].header->type == MULTIFIELD_TYPE)
{
nextAdd = GenConstant(theEnv,FCALL,FindFunction(theEnv,"create$"));
if (lastAdd == NULL)
{ theReference.argList = nextAdd; }
else
{ lastAdd->nextArg = nextAdd; }
lastAdd = nextAdd;
multiAdd = NULL;
for (j = 0; j < theFCB->contents[i].multifieldValue->length; j++)
{
nextAdd = GenConstant(theEnv,theFCB->contents[i].multifieldValue->contents[j].header->type,
theFCB->contents[i].multifieldValue->contents[j].value);
if (multiAdd == NULL)
{ lastAdd->argList = nextAdd; }
else
{ multiAdd->nextArg = nextAdd; }
multiAdd = nextAdd;
}
}
else
{
nextAdd = GenConstant(theEnv,theFCB->contents[i].header->type,theFCB->contents[i].value);
if (lastAdd == NULL)
{ theReference.argList = nextAdd; }
else
{ lastAdd->nextArg = nextAdd; }
lastAdd = nextAdd;
}
}
ExpressionInstall(theEnv,&theReference);
#if DEFFUNCTION_CONSTRUCT
if (theReference.type == PCALL)
{
if (CheckDeffunctionCall(theEnv,(Deffunction *) theReference.value,CountArguments(theReference.argList)) == false)
{
ExpressionDeinstall(theEnv,&theReference);
ReturnExpression(theEnv,theReference.argList);
return FCBE_ARGUMENT_COUNT_ERROR;
}
}
#endif
#if ! RUN_TIME
if (theReference.type == FCALL)
{
FunctionArgumentsError theError;
if ((theError = CheckExpressionAgainstRestrictions(theEnv,&theReference,theFunction,functionName)) != FAE_NO_ERROR)
{
ExpressionDeinstall(theEnv,&theReference);
ReturnExpression(theEnv,theReference.argList);
if (theError == FAE_TYPE_ERROR) return FCBE_ARGUMENT_TYPE_ERROR;
else if (theError == FAE_COUNT_ERROR) return FCBE_ARGUMENT_COUNT_ERROR;
else
{
SystemError(theEnv,"EVALUATN",9);
ExitRouter(theEnv,EXIT_FAILURE);
}
}
}
#endif
GCBlockStart(theEnv,&gcb);
if (EvaluationData(theEnv)->CurrentExpression == NULL)
{ ResetErrorFlags(theEnv); }
EvaluateExpression(theEnv,&theReference,&udfReturnValue);
NormalizeMultifield(theEnv,&udfReturnValue);
ExpressionDeinstall(theEnv,&theReference);
ReturnExpression(theEnv,theReference.argList);
if (returnValue != NULL)
{ GCBlockEndUDF(theEnv,&gcb,&udfReturnValue); }
else
{ GCBlockEnd(theEnv,&gcb); }
if (EvaluationData(theEnv)->CurrentExpression == NULL)
{
if (returnValue != NULL)
{ CleanCurrentGarbageFrame(theEnv,&udfReturnValue); }
else
{ CleanCurrentGarbageFrame(theEnv,NULL); }
CallPeriodicTasks(theEnv);
}
if (returnValue != NULL)
{ returnValue->value = udfReturnValue.value; }
if (GetEvaluationError(theEnv)) return FCBE_PROCESSING_ERROR;
return FCBE_NO_ERROR;
}
void FCBReset(
FunctionCallBuilder *theFCB)
{
size_t i;
for (i = 0; i < theFCB->length; i++)
{ Release(theFCB->fcbEnv,theFCB->contents[i].header); }
if (theFCB->bufferReset != theFCB->bufferMaximum)
{
if (theFCB->bufferMaximum != 0)
{ rm(theFCB->fcbEnv,theFCB->contents,sizeof(CLIPSValue) * theFCB->bufferMaximum); }
if (theFCB->bufferReset == 0)
{ theFCB->contents = NULL; }
else
{ theFCB->contents = (CLIPSValue *) gm2(theFCB->fcbEnv,sizeof(CLIPSValue) * theFCB->bufferReset); }
theFCB->bufferMaximum = theFCB->bufferReset;
}
theFCB->length = 0;
}
void FCBDispose(
FunctionCallBuilder *theFCB)
{
Environment *theEnv = theFCB->fcbEnv;
size_t i;
for (i = 0; i < theFCB->length; i++)
{ Release(theFCB->fcbEnv,theFCB->contents[i].header); }
if (theFCB->bufferMaximum != 0)
{ rm(theFCB->fcbEnv,theFCB->contents,sizeof(CLIPSValue) * theFCB->bufferMaximum); }
rtn_struct(theEnv,multifieldBuilder,theFCB);
}