#include <stdio.h>
#include <string.h>
#include "setup.h"
#include "argacces.h"
#include "commline.h"
#include "constant.h"
#include "cstrcpsr.h"
#include "envrnmnt.h"
#include "exprnpsr.h"
#include "memalloc.h"
#include "miscfun.h"
#include "moduldef.h"
#include "modulutl.h"
#include "multifld.h"
#include "prcdrfun.h"
#include "prcdrpsr.h"
#include "prntutil.h"
#include "router.h"
#include "ruledef.h"
#include "scanner.h"
#include "sysdep.h"
#include "utility.h"
#include "watch.h"
#include "constrct.h"
static void DeallocateConstructData(Environment *);
void InitializeConstructData(
Environment *theEnv)
{
AllocateEnvironmentData(theEnv,CONSTRUCT_DATA,sizeof(struct constructData),DeallocateConstructData);
}
static void DeallocateConstructData(
Environment *theEnv)
{
Construct *tmpPtr, *nextPtr;
#if (! RUN_TIME) && (! BLOAD_ONLY)
DeallocateSaveCallList(theEnv,ConstructData(theEnv)->ListOfSaveFunctions);
#endif
DeallocateVoidCallList(theEnv,ConstructData(theEnv)->ListOfResetFunctions);
DeallocateVoidCallList(theEnv,ConstructData(theEnv)->ListOfClearFunctions);
DeallocateBoolCallList(theEnv,ConstructData(theEnv)->ListOfClearReadyFunctions);
#if (! RUN_TIME) && (! BLOAD_ONLY)
if (ConstructData(theEnv)->ErrorString != NULL)
{ genfree(theEnv,ConstructData(theEnv)->ErrorString,sizeof(ConstructData(theEnv)->ErrorString) + 1); }
if (ConstructData(theEnv)->WarningString != NULL)
{ genfree(theEnv,ConstructData(theEnv)->WarningString,sizeof(ConstructData(theEnv)->WarningString) + 1); }
ConstructData(theEnv)->ErrorString = NULL;
ConstructData(theEnv)->WarningString = NULL;
SetParsingFileName(theEnv,NULL);
SetWarningFileName(theEnv,NULL);
SetErrorFileName(theEnv,NULL);
#endif
tmpPtr = ConstructData(theEnv)->ListOfConstructs;
while (tmpPtr != NULL)
{
nextPtr = tmpPtr->next;
rtn_struct(theEnv,construct,tmpPtr);
tmpPtr = nextPtr;
}
}
#if (! RUN_TIME) && (! BLOAD_ONLY)
ParserErrorFunction *SetParserErrorCallback(
Environment *theEnv,
ParserErrorFunction *functionPtr,
void *context)
{
ParserErrorFunction *tmpPtr;
tmpPtr = ConstructData(theEnv)->ParserErrorCallback;
ConstructData(theEnv)->ParserErrorCallback = functionPtr;
ConstructData(theEnv)->ParserErrorContext = context;
return tmpPtr;
}
Construct *FindConstruct(
Environment *theEnv,
const char *name)
{
Construct *currentPtr;
for (currentPtr = ConstructData(theEnv)->ListOfConstructs;
currentPtr != NULL;
currentPtr = currentPtr->next)
{
if (strcmp(name,currentPtr->constructName) == 0)
{ return currentPtr; }
}
return NULL;
}
bool RemoveConstruct(
Environment *theEnv,
const char *name)
{
Construct *currentPtr, *lastPtr = NULL;
for (currentPtr = ConstructData(theEnv)->ListOfConstructs;
currentPtr != NULL;
currentPtr = currentPtr->next)
{
if (strcmp(name,currentPtr->constructName) == 0)
{
if (lastPtr == NULL)
{ ConstructData(theEnv)->ListOfConstructs = currentPtr->next; }
else
{ lastPtr->next = currentPtr->next; }
rtn_struct(theEnv,construct,currentPtr);
return true;
}
lastPtr = currentPtr;
}
return false;
}
bool Save(
Environment *theEnv,
const char *fileName)
{
struct saveCallFunctionItem *saveFunction;
FILE *filePtr;
Defmodule *defmodulePtr;
bool updated = false;
bool unvisited = true;
if (EvaluationData(theEnv)->CurrentExpression == NULL)
{ ResetErrorFlags(theEnv); }
if ((filePtr = GenOpen(theEnv,fileName,"w")) == NULL)
{ return false; }
SetFastSave(theEnv,filePtr);
MarkModulesAsUnvisited(theEnv);
while (unvisited)
{
unvisited = false;
updated = false;
for (defmodulePtr = GetNextDefmodule(theEnv,NULL);
defmodulePtr != NULL;
defmodulePtr = GetNextDefmodule(theEnv,defmodulePtr))
{
if (defmodulePtr->visitedFlag)
{ }
else if (AllImportedModulesVisited(theEnv,defmodulePtr))
{
for (saveFunction = ConstructData(theEnv)->ListOfSaveFunctions;
saveFunction != NULL;
saveFunction = saveFunction->next)
{ (*saveFunction->func)(theEnv,defmodulePtr,(char *) filePtr,saveFunction->context); }
updated = true;
defmodulePtr->visitedFlag = true;
}
else
{ unvisited = true; }
}
if (unvisited && (! updated))
{
SystemError(theEnv,"CONSTRCT",2);
break;
}
}
GenClose(theEnv,filePtr);
SetFastSave(theEnv,NULL);
return true;
}
bool RemoveSaveFunction(
Environment *theEnv,
const char *name)
{
bool found;
ConstructData(theEnv)->ListOfSaveFunctions =
RemoveSaveFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfSaveFunctions,&found);
if (found) return true;
return false;
}
void SetCompilationsWatch(
Environment *theEnv,
bool value)
{
ConstructData(theEnv)->WatchCompilations = value;
}
bool GetCompilationsWatch(
Environment *theEnv)
{
return ConstructData(theEnv)->WatchCompilations;
}
void SetPrintWhileLoading(
Environment *theEnv,
bool value)
{
ConstructData(theEnv)->PrintWhileLoading = value;
}
bool GetPrintWhileLoading(
Environment *theEnv)
{
return(ConstructData(theEnv)->PrintWhileLoading);
}
void SetLoadInProgress(
Environment *theEnv,
bool value)
{
ConstructData(theEnv)->LoadInProgress = value;
}
bool GetLoadInProgress(
Environment *theEnv)
{
return(ConstructData(theEnv)->LoadInProgress);
}
#endif
void InitializeConstructs(
Environment *theEnv)
{
#if (! RUN_TIME)
AddUDF(theEnv,"clear","v",0,0,NULL,ClearCommand,"ClearCommand",NULL);
AddUDF(theEnv,"reset","v",0,0,NULL,ResetCommand,"ResetCommand",NULL);
#if DEBUGGING_FUNCTIONS && (! BLOAD_ONLY)
AddWatchItem(theEnv,"compilations",0,&ConstructData(theEnv)->WatchCompilations,30,NULL,NULL);
#endif
#else
#if MAC_XCD
#pragma unused(theEnv)
#endif
#endif
}
void ClearCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
Clear(theEnv);
}
void ResetCommand(
Environment *theEnv,
UDFContext *context,
UDFValue *returnValue)
{
Reset(theEnv);
}
void Reset(
Environment *theEnv)
{
struct voidCallFunctionItem *resetPtr;
GCBlock gcb;
if (ConstructData(theEnv)->ResetInProgress) return;
ConstructData(theEnv)->ResetInProgress = true;
ConstructData(theEnv)->ResetReadyInProgress = true;
if (EvaluationData(theEnv)->CurrentExpression == NULL)
{ ResetErrorFlags(theEnv); }
SetErrorValue(theEnv,NULL);
GCBlockStart(theEnv,&gcb);
if ((ConstructData(theEnv)->BeforeResetCallback != NULL) ?
((*ConstructData(theEnv)->BeforeResetCallback)(theEnv) == false) : false)
{
ConstructData(theEnv)->ResetReadyInProgress = false;
ConstructData(theEnv)->ResetInProgress = false;
return;
}
ConstructData(theEnv)->ResetReadyInProgress = false;
for (resetPtr = ConstructData(theEnv)->ListOfResetFunctions;
(resetPtr != NULL) && (GetHaltExecution(theEnv) == false);
resetPtr = resetPtr->next)
{ (*resetPtr->func)(theEnv,resetPtr->context); }
SetCurrentModule(theEnv,FindDefmodule(theEnv,"MAIN"));
GCBlockEnd(theEnv,&gcb);
CallPeriodicTasks(theEnv);
ConstructData(theEnv)->ResetInProgress = false;
}
BeforeResetFunction *SetBeforeResetFunction(
Environment *theEnv,
BeforeResetFunction *theFunction)
{
BeforeResetFunction *tempFunction;
tempFunction = ConstructData(theEnv)->BeforeResetCallback;
ConstructData(theEnv)->BeforeResetCallback = theFunction;
return tempFunction;
}
bool AddResetFunction(
Environment *theEnv,
const char *name,
VoidCallFunction *functionPtr,
int priority,
void *context)
{
ConstructData(theEnv)->ListOfResetFunctions =
AddVoidFunctionToCallList(theEnv,name,priority,functionPtr,
ConstructData(theEnv)->ListOfResetFunctions,context);
return true;
}
bool RemoveResetFunction(
Environment *theEnv,
const char *name)
{
bool found;
ConstructData(theEnv)->ListOfResetFunctions =
RemoveVoidFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfResetFunctions,&found);
return found;
}
void IncrementClearReadyLocks(
Environment *theEnv)
{
ConstructData(theEnv)->ClearReadyLocks++;
}
void DecrementClearReadyLocks(
Environment *theEnv)
{
if (ConstructData(theEnv)->ClearReadyLocks > 0)
{ ConstructData(theEnv)->ClearReadyLocks--; }
}
bool Clear(
Environment *theEnv)
{
struct voidCallFunctionItem *theFunction;
GCBlock gcb;
if (EvaluationData(theEnv)->CurrentExpression == NULL)
{ ResetErrorFlags(theEnv); }
SetErrorValue(theEnv,NULL);
ConstructData(theEnv)->ClearReadyInProgress = true;
if ((ConstructData(theEnv)->ClearReadyLocks > 0) ||
(ConstructData(theEnv)->DanglingConstructs > 0) ||
(ClearReady(theEnv) == false))
{
PrintErrorID(theEnv,"CONSTRCT",1,false);
WriteString(theEnv,STDERR,"Some constructs are still in use. Clear cannot continue.\n");
ConstructData(theEnv)->ClearReadyInProgress = false;
return false;
}
ConstructData(theEnv)->ClearReadyInProgress = false;
GCBlockStart(theEnv,&gcb);
ConstructData(theEnv)->ClearInProgress = true;
for (theFunction = ConstructData(theEnv)->ListOfClearFunctions;
theFunction != NULL;
theFunction = theFunction->next)
{ (*theFunction->func)(theEnv,theFunction->context); }
GCBlockEnd(theEnv,&gcb);
CallPeriodicTasks(theEnv);
ConstructData(theEnv)->ClearInProgress = false;
#if DEFRULE_CONSTRUCT
if ((DefruleData(theEnv)->RightPrimeJoins != NULL) ||
(DefruleData(theEnv)->LeftPrimeJoins != NULL))
{ SystemError(theEnv,"CONSTRCT",1); }
#endif
Reset(theEnv);
return true;
}
bool ClearReady(
Environment *theEnv)
{
struct boolCallFunctionItem *theFunction;
for (theFunction = ConstructData(theEnv)->ListOfClearReadyFunctions;
theFunction != NULL;
theFunction = theFunction->next)
{
if ((*theFunction->func)(theEnv,theFunction->context) == false)
{ return false; }
}
return true;
}
bool AddClearReadyFunction(
Environment *theEnv,
const char *name,
BoolCallFunction *functionPtr,
int priority,
void *context)
{
ConstructData(theEnv)->ListOfClearReadyFunctions =
AddBoolFunctionToCallList(theEnv,name,priority,functionPtr,
ConstructData(theEnv)->ListOfClearReadyFunctions,context);
return true;
}
bool RemoveClearReadyFunction(
Environment *theEnv,
const char *name)
{
bool found;
ConstructData(theEnv)->ListOfClearReadyFunctions =
RemoveBoolFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfClearReadyFunctions,&found);
if (found) return true;
return false;
}
bool AddClearFunction(
Environment *theEnv,
const char *name,
VoidCallFunction *functionPtr,
int priority,
void *context)
{
ConstructData(theEnv)->ListOfClearFunctions =
AddVoidFunctionToCallList(theEnv,name,priority,functionPtr,
ConstructData(theEnv)->ListOfClearFunctions,context);
return true;
}
bool RemoveClearFunction(
Environment *theEnv,
const char *name)
{
bool found;
ConstructData(theEnv)->ListOfClearFunctions =
RemoveVoidFunctionFromCallList(theEnv,name,ConstructData(theEnv)->ListOfClearFunctions,&found);
if (found) return true;
return false;
}
bool ExecutingConstruct(
Environment *theEnv)
{
return ConstructData(theEnv)->Executing;
}
void SetExecutingConstruct(
Environment *theEnv,
bool value)
{
ConstructData(theEnv)->Executing = value;
}
void DeinstallConstructHeader(
Environment *theEnv,
ConstructHeader *theHeader)
{
ReleaseLexeme(theEnv,theHeader->name);
if (theHeader->ppForm != NULL)
{
rm(theEnv,(void *) theHeader->ppForm,
sizeof(char) * (strlen(theHeader->ppForm) + 1));
theHeader->ppForm = NULL;
}
if (theHeader->usrData != NULL)
{
ClearUserDataList(theEnv,theHeader->usrData);
theHeader->usrData = NULL;
}
}
void DestroyConstructHeader(
Environment *theEnv,
ConstructHeader *theHeader)
{
if (theHeader->ppForm != NULL)
{
rm(theEnv,(void *) theHeader->ppForm,
sizeof(char) * (strlen(theHeader->ppForm) + 1));
theHeader->ppForm = NULL;
}
if (theHeader->usrData != NULL)
{
ClearUserDataList(theEnv,theHeader->usrData);
theHeader->usrData = NULL;
}
}
Construct *AddConstruct(
Environment *theEnv,
const char *name,
const char *pluralName,
bool (*parseFunction)(Environment *,const char *),
FindConstructFunction *findFunction,
CLIPSLexeme *(*getConstructNameFunction)(ConstructHeader *),
const char *(*getPPFormFunction)(ConstructHeader *),
struct defmoduleItemHeader *(*getModuleItemFunction)(ConstructHeader *),
GetNextConstructFunction *getNextItemFunction,
void (*setNextItemFunction)(ConstructHeader *,ConstructHeader *),
IsConstructDeletableFunction *isConstructDeletableFunction,
DeleteConstructFunction *deleteFunction,
FreeConstructFunction *freeFunction)
{
Construct *newPtr;
newPtr = get_struct(theEnv,construct);
newPtr->constructName = name;
newPtr->pluralName = pluralName;
newPtr->parseFunction = parseFunction;
newPtr->findFunction = findFunction;
newPtr->getConstructNameFunction = getConstructNameFunction;
newPtr->getPPFormFunction = getPPFormFunction;
newPtr->getModuleItemFunction = getModuleItemFunction;
newPtr->getNextItemFunction = getNextItemFunction;
newPtr->setNextItemFunction = setNextItemFunction;
newPtr->isConstructDeletableFunction = isConstructDeletableFunction;
newPtr->deleteFunction = deleteFunction;
newPtr->freeFunction = freeFunction;
newPtr->next = ConstructData(theEnv)->ListOfConstructs;
ConstructData(theEnv)->ListOfConstructs = newPtr;
return(newPtr);
}
bool AddSaveFunction(
Environment *theEnv,
const char *name,
SaveCallFunction *functionPtr,
int priority,
void *context)
{
#if (! RUN_TIME) && (! BLOAD_ONLY)
ConstructData(theEnv)->ListOfSaveFunctions =
AddSaveFunctionToCallList(theEnv,name,priority,
functionPtr,
ConstructData(theEnv)->ListOfSaveFunctions,context);
#else
#if MAC_XCD
#pragma unused(theEnv)
#endif
#endif
return true;
}
SaveCallFunctionItem *AddSaveFunctionToCallList(
Environment *theEnv,
const char *name,
int priority,
SaveCallFunction *func,
struct saveCallFunctionItem *head,
void *context)
{
struct saveCallFunctionItem *newPtr, *currentPtr, *lastPtr = NULL;
char *nameCopy;
newPtr = get_struct(theEnv,saveCallFunctionItem);
nameCopy = (char *) genalloc(theEnv,strlen(name) + 1);
genstrcpy(nameCopy,name);
newPtr->name = nameCopy;
newPtr->func = func;
newPtr->priority = priority;
newPtr->context = context;
if (head == NULL)
{
newPtr->next = NULL;
return(newPtr);
}
currentPtr = head;
while ((currentPtr != NULL) ? (priority < currentPtr->priority) : false)
{
lastPtr = currentPtr;
currentPtr = currentPtr->next;
}
if (lastPtr == NULL)
{
newPtr->next = head;
head = newPtr;
}
else
{
newPtr->next = currentPtr;
lastPtr->next = newPtr;
}
return(head);
}
struct saveCallFunctionItem *RemoveSaveFunctionFromCallList(
Environment *theEnv,
const char *name,
struct saveCallFunctionItem *head,
bool *found)
{
struct saveCallFunctionItem *currentPtr, *lastPtr;
*found = false;
lastPtr = NULL;
currentPtr = head;
while (currentPtr != NULL)
{
if (strcmp(name,currentPtr->name) == 0)
{
*found = true;
if (lastPtr == NULL)
{ head = currentPtr->next; }
else
{ lastPtr->next = currentPtr->next; }
genfree(theEnv,(void *) currentPtr->name,strlen(currentPtr->name) + 1);
rtn_struct(theEnv,saveCallFunctionItem,currentPtr);
return head;
}
lastPtr = currentPtr;
currentPtr = currentPtr->next;
}
return head;
}
void DeallocateSaveCallList(
Environment *theEnv,
struct saveCallFunctionItem *theList)
{
struct saveCallFunctionItem *tmpPtr, *nextPtr;
tmpPtr = theList;
while (tmpPtr != NULL)
{
nextPtr = tmpPtr->next;
genfree(theEnv,(void *) tmpPtr->name,strlen(tmpPtr->name) + 1);
rtn_struct(theEnv,saveCallFunctionItem,tmpPtr);
tmpPtr = nextPtr;
}
}