#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "setup.h"
#include "argacces.h"
#include "constant.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "multifld.h"
#include "prntutil.h"
#include "router.h"
#include "sysdep.h"
#include "utility.h"
#include "symbol.h"
#define FALSE_STRING "FALSE"
#define TRUE_STRING "TRUE"
#define POSITIVE_INFINITY_STRING "+oo"
#define NEGATIVE_INFINITY_STRING "-oo"
#define AVERAGE_STRING_SIZE 10
#define AVERAGE_BITMAP_SIZE sizeof(long)
#define NUMBER_OF_LONGS_FOR_HASH 25
static void RemoveHashNode(Environment *,GENERIC_HN *,GENERIC_HN **,int,int);
static void AddEphemeralHashNode(Environment *,GENERIC_HN *,struct ephemeron **,
int,int,bool);
static void RemoveEphemeralHashNodes(Environment *,struct ephemeron **,
GENERIC_HN **,
int,int,int);
static const char *StringWithinString(const char *,const char *);
static size_t CommonPrefixLength(const char *,const char *);
static void DeallocateSymbolData(Environment *);
void InitializeAtomTables(
Environment *theEnv,
CLIPSLexeme **symbolTable,
CLIPSFloat **floatTable,
CLIPSInteger **integerTable,
CLIPSBitMap **bitmapTable,
CLIPSExternalAddress **externalAddressTable)
{
#if MAC_XCD
#pragma unused(symbolTable)
#pragma unused(floatTable)
#pragma unused(integerTable)
#pragma unused(bitmapTable)
#pragma unused(externalAddressTable)
#endif
unsigned long i;
AllocateEnvironmentData(theEnv,SYMBOL_DATA,sizeof(struct symbolData),DeallocateSymbolData);
#if ! RUN_TIME
SymbolData(theEnv)->SymbolTable = (CLIPSLexeme **)
gm2(theEnv,sizeof (CLIPSLexeme *) * SYMBOL_HASH_SIZE);
SymbolData(theEnv)->FloatTable = (CLIPSFloat **)
gm2(theEnv,sizeof (CLIPSFloat *) * FLOAT_HASH_SIZE);
SymbolData(theEnv)->IntegerTable = (CLIPSInteger **)
gm2(theEnv,sizeof (CLIPSInteger *) * INTEGER_HASH_SIZE);
SymbolData(theEnv)->BitMapTable = (CLIPSBitMap **)
gm2(theEnv,sizeof (CLIPSBitMap *) * BITMAP_HASH_SIZE);
SymbolData(theEnv)->ExternalAddressTable = (CLIPSExternalAddress **)
gm2(theEnv,sizeof (CLIPSExternalAddress *) * EXTERNAL_ADDRESS_HASH_SIZE);
for (i = 0; i < SYMBOL_HASH_SIZE; i++) SymbolData(theEnv)->SymbolTable[i] = NULL;
for (i = 0; i < FLOAT_HASH_SIZE; i++) SymbolData(theEnv)->FloatTable[i] = NULL;
for (i = 0; i < INTEGER_HASH_SIZE; i++) SymbolData(theEnv)->IntegerTable[i] = NULL;
for (i = 0; i < BITMAP_HASH_SIZE; i++) SymbolData(theEnv)->BitMapTable[i] = NULL;
for (i = 0; i < EXTERNAL_ADDRESS_HASH_SIZE; i++) SymbolData(theEnv)->ExternalAddressTable[i] = NULL;
theEnv->TrueSymbol = AddSymbol(theEnv,TRUE_STRING,SYMBOL_TYPE);
IncrementLexemeCount(TrueSymbol(theEnv));
theEnv->FalseSymbol = AddSymbol(theEnv,FALSE_STRING,SYMBOL_TYPE);
IncrementLexemeCount(FalseSymbol(theEnv));
SymbolData(theEnv)->PositiveInfinity = AddSymbol(theEnv,POSITIVE_INFINITY_STRING,SYMBOL_TYPE);
IncrementLexemeCount(SymbolData(theEnv)->PositiveInfinity);
SymbolData(theEnv)->NegativeInfinity = AddSymbol(theEnv,NEGATIVE_INFINITY_STRING,SYMBOL_TYPE);
IncrementLexemeCount(SymbolData(theEnv)->NegativeInfinity);
SymbolData(theEnv)->Zero = CreateInteger(theEnv,0LL);
IncrementIntegerCount(SymbolData(theEnv)->Zero);
#else
SetSymbolTable(theEnv,symbolTable);
SetFloatTable(theEnv,floatTable);
SetIntegerTable(theEnv,integerTable);
SetBitMapTable(theEnv,bitmapTable);
SymbolData(theEnv)->ExternalAddressTable = (CLIPSExternalAddress **)
gm2(theEnv,sizeof (CLIPSExternalAddress *) * EXTERNAL_ADDRESS_HASH_SIZE);
for (i = 0; i < EXTERNAL_ADDRESS_HASH_SIZE; i++) SymbolData(theEnv)->ExternalAddressTable[i] = NULL;
theEnv->TrueSymbol = FindSymbolHN(theEnv,TRUE_STRING,SYMBOL_BIT);
theEnv->FalseSymbol = FindSymbolHN(theEnv,FALSE_STRING,SYMBOL_BIT);
#endif
theEnv->VoidConstant = get_struct(theEnv,clipsVoid);
theEnv->VoidConstant->header.type = VOID_TYPE;
}
static void DeallocateSymbolData(
Environment *theEnv)
{
int i;
CLIPSLexeme *shPtr, *nextSHPtr;
CLIPSInteger *ihPtr, *nextIHPtr;
CLIPSFloat *fhPtr, *nextFHPtr;
CLIPSBitMap *bmhPtr, *nextBMHPtr;
CLIPSExternalAddress *eahPtr, *nextEAHPtr;
if ((SymbolData(theEnv)->SymbolTable == NULL) ||
(SymbolData(theEnv)->FloatTable == NULL) ||
(SymbolData(theEnv)->IntegerTable == NULL) ||
(SymbolData(theEnv)->BitMapTable == NULL) ||
(SymbolData(theEnv)->ExternalAddressTable == NULL))
{ return; }
genfree(theEnv,theEnv->VoidConstant,sizeof(TypeHeader));
for (i = 0; i < SYMBOL_HASH_SIZE; i++)
{
shPtr = SymbolData(theEnv)->SymbolTable[i];
while (shPtr != NULL)
{
nextSHPtr = shPtr->next;
if (! shPtr->permanent)
{
rm(theEnv,(void *) shPtr->contents,strlen(shPtr->contents)+1);
rtn_struct(theEnv,clipsLexeme,shPtr);
}
shPtr = nextSHPtr;
}
}
for (i = 0; i < FLOAT_HASH_SIZE; i++)
{
fhPtr = SymbolData(theEnv)->FloatTable[i];
while (fhPtr != NULL)
{
nextFHPtr = fhPtr->next;
if (! fhPtr->permanent)
{ rtn_struct(theEnv,clipsFloat,fhPtr); }
fhPtr = nextFHPtr;
}
}
for (i = 0; i < INTEGER_HASH_SIZE; i++)
{
ihPtr = SymbolData(theEnv)->IntegerTable[i];
while (ihPtr != NULL)
{
nextIHPtr = ihPtr->next;
if (! ihPtr->permanent)
{ rtn_struct(theEnv,clipsInteger,ihPtr); }
ihPtr = nextIHPtr;
}
}
for (i = 0; i < BITMAP_HASH_SIZE; i++)
{
bmhPtr = SymbolData(theEnv)->BitMapTable[i];
while (bmhPtr != NULL)
{
nextBMHPtr = bmhPtr->next;
if (! bmhPtr->permanent)
{
rm(theEnv,(void *) bmhPtr->contents,bmhPtr->size);
rtn_struct(theEnv,clipsBitMap,bmhPtr);
}
bmhPtr = nextBMHPtr;
}
}
for (i = 0; i < EXTERNAL_ADDRESS_HASH_SIZE; i++)
{
eahPtr = SymbolData(theEnv)->ExternalAddressTable[i];
while (eahPtr != NULL)
{
nextEAHPtr = eahPtr->next;
if (! eahPtr->permanent)
{
rtn_struct(theEnv,clipsExternalAddress,eahPtr);
}
eahPtr = nextEAHPtr;
}
}
#if ! RUN_TIME
rm(theEnv,SymbolData(theEnv)->SymbolTable,sizeof (CLIPSLexeme *) * SYMBOL_HASH_SIZE);
genfree(theEnv,SymbolData(theEnv)->FloatTable,sizeof (CLIPSFloat *) * FLOAT_HASH_SIZE);
genfree(theEnv,SymbolData(theEnv)->IntegerTable,sizeof (CLIPSInteger *) * INTEGER_HASH_SIZE);
genfree(theEnv,SymbolData(theEnv)->BitMapTable,sizeof (CLIPSBitMap *) * BITMAP_HASH_SIZE);
#endif
genfree(theEnv,SymbolData(theEnv)->ExternalAddressTable,sizeof (CLIPSExternalAddress *) * EXTERNAL_ADDRESS_HASH_SIZE);
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE || BLOAD_INSTANCES || BSAVE_INSTANCES
if (SymbolData(theEnv)->SymbolArray != NULL)
rm(theEnv,SymbolData(theEnv)->SymbolArray,sizeof(CLIPSLexeme *) * SymbolData(theEnv)->NumberOfSymbols);
if (SymbolData(theEnv)->FloatArray != NULL)
rm(theEnv,SymbolData(theEnv)->FloatArray,sizeof(CLIPSFloat *) * SymbolData(theEnv)->NumberOfFloats);
if (SymbolData(theEnv)->IntegerArray != NULL)
rm(theEnv,SymbolData(theEnv)->IntegerArray,sizeof(CLIPSInteger *) * SymbolData(theEnv)->NumberOfIntegers);
if (SymbolData(theEnv)->BitMapArray != NULL)
rm(theEnv,SymbolData(theEnv)->BitMapArray,sizeof(CLIPSBitMap *) * SymbolData(theEnv)->NumberOfBitMaps);
#endif
}
CLIPSLexeme *CreateBoolean(
Environment *theEnv,
bool theValue)
{
if (theValue)
{ return TrueSymbol(theEnv); }
else
{ return FalseSymbol(theEnv); }
}
CLIPSLexeme *CreateSymbol(
Environment *theEnv,
const char *str)
{
return AddSymbol(theEnv,str,SYMBOL_TYPE);
}
CLIPSLexeme *CreateString(
Environment *theEnv,
const char *str)
{
return AddSymbol(theEnv,str,STRING_TYPE);
}
CLIPSLexeme *CreateInstanceName(
Environment *theEnv,
const char *str)
{
return AddSymbol(theEnv,str,INSTANCE_NAME_TYPE);
}
CLIPSLexeme *AddSymbol(
Environment *theEnv,
const char *str,
unsigned short theType)
{
size_t tally;
size_t length;
CLIPSLexeme *past = NULL, *peek;
char *buffer;
if (str == NULL)
{
SystemError(theEnv,"SYMBOL",1);
ExitRouter(theEnv,EXIT_FAILURE);
}
tally = HashSymbol(str,SYMBOL_HASH_SIZE);
peek = SymbolData(theEnv)->SymbolTable[tally];
while (peek != NULL)
{
if ((peek->header.type == theType) &&
(strcmp(str,peek->contents) == 0))
{ return peek; }
past = peek;
peek = peek->next;
}
peek = get_struct(theEnv,clipsLexeme);
if (past == NULL) SymbolData(theEnv)->SymbolTable[tally] = peek;
else past->next = peek;
length = strlen(str) + 1;
buffer = (char *) gm2(theEnv,length);
genstrcpy(buffer,str);
peek->contents = buffer;
peek->next = NULL;
peek->bucket = (unsigned int) tally;
peek->count = 0;
peek->permanent = false;
peek->header.type = theType;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) peek,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralSymbolList,
sizeof(CLIPSLexeme),AVERAGE_STRING_SIZE,true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
return peek;
}
CLIPSLexeme *FindSymbolHN(
Environment *theEnv,
const char *str,
unsigned short expectedType)
{
size_t tally;
CLIPSLexeme *peek;
tally = HashSymbol(str,SYMBOL_HASH_SIZE);
for (peek = SymbolData(theEnv)->SymbolTable[tally];
peek != NULL;
peek = peek->next)
{
if (((1 << peek->header.type) & expectedType) &&
(strcmp(str,peek->contents) == 0))
{ return peek; }
}
return NULL;
}
CLIPSFloat *CreateFloat(
Environment *theEnv,
double number)
{
size_t tally;
CLIPSFloat *past = NULL, *peek;
tally = HashFloat(number,FLOAT_HASH_SIZE);
peek = SymbolData(theEnv)->FloatTable[tally];
while (peek != NULL)
{
if (number == peek->contents)
{ return peek; }
past = peek;
peek = peek->next;
}
peek = get_struct(theEnv,clipsFloat);
if (past == NULL) SymbolData(theEnv)->FloatTable[tally] = peek;
else past->next = peek;
peek->contents = number;
peek->next = NULL;
peek->bucket = (unsigned int) tally;
peek->count = 0;
peek->permanent = false;
peek->header.type = FLOAT_TYPE;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) peek,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralFloatList,
sizeof(CLIPSFloat),0,true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
return peek;
}
CLIPSInteger *CreateInteger(
Environment *theEnv,
long long number)
{
size_t tally;
CLIPSInteger *past = NULL, *peek;
tally = HashInteger(number,INTEGER_HASH_SIZE);
peek = SymbolData(theEnv)->IntegerTable[tally];
while (peek != NULL)
{
if (number == peek->contents)
{ return peek; }
past = peek;
peek = peek->next;
}
peek = get_struct(theEnv,clipsInteger);
if (past == NULL) SymbolData(theEnv)->IntegerTable[tally] = peek;
else past->next = peek;
peek->contents = number;
peek->next = NULL;
peek->bucket = (unsigned int) tally;
peek->count = 0;
peek->permanent = false;
peek->header.type = INTEGER_TYPE;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) peek,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralIntegerList,
sizeof(CLIPSInteger),0,true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
return peek;
}
CLIPSInteger *FindLongHN(
Environment *theEnv,
long long theLong)
{
size_t tally;
CLIPSInteger *peek;
tally = HashInteger(theLong,INTEGER_HASH_SIZE);
for (peek = SymbolData(theEnv)->IntegerTable[tally];
peek != NULL;
peek = peek->next)
{ if (peek->contents == theLong) return(peek); }
return NULL;
}
void *AddBitMap(
Environment *theEnv,
void *vTheBitMap,
unsigned short size)
{
char *theBitMap = (char *) vTheBitMap;
size_t tally;
unsigned short i;
CLIPSBitMap *past = NULL, *peek;
char *buffer;
if (theBitMap == NULL)
{
SystemError(theEnv,"SYMBOL",2);
ExitRouter(theEnv,EXIT_FAILURE);
}
tally = HashBitMap(theBitMap,BITMAP_HASH_SIZE,size);
peek = SymbolData(theEnv)->BitMapTable[tally];
while (peek != NULL)
{
if (peek->size == size)
{
for (i = 0; i < size ; i++)
{ if (peek->contents[i] != theBitMap[i]) break; }
if (i == size) return((void *) peek);
}
past = peek;
peek = peek->next;
}
peek = get_struct(theEnv,clipsBitMap);
if (past == NULL) SymbolData(theEnv)->BitMapTable[tally] = peek;
else past->next = peek;
buffer = (char *) gm2(theEnv,size);
for (i = 0; i < size ; i++) buffer[i] = theBitMap[i];
peek->contents = buffer;
peek->next = NULL;
peek->bucket = (unsigned int) tally;
peek->count = 0;
peek->permanent = false;
peek->size = size;
peek->header.type = BITMAP_TYPE;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) peek,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralBitMapList,
sizeof(CLIPSBitMap),sizeof(long),true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
return((void *) peek);
}
CLIPSExternalAddress *CreateCExternalAddress(
Environment *theEnv,
void *theExternalAddress)
{
return CreateExternalAddress(theEnv,theExternalAddress,C_POINTER_EXTERNAL_ADDRESS);
}
CLIPSExternalAddress *CreateExternalAddress(
Environment *theEnv,
void *theExternalAddress,
unsigned short theType)
{
size_t tally;
CLIPSExternalAddress *past = NULL, *peek;
tally = HashExternalAddress(theExternalAddress,EXTERNAL_ADDRESS_HASH_SIZE);
peek = SymbolData(theEnv)->ExternalAddressTable[tally];
while (peek != NULL)
{
if ((peek->type == theType) &&
(peek->contents == theExternalAddress))
{ return peek; }
past = peek;
peek = peek->next;
}
peek = get_struct(theEnv,clipsExternalAddress);
if (past == NULL) SymbolData(theEnv)->ExternalAddressTable[tally] = peek;
else past->next = peek;
peek->contents = theExternalAddress;
peek->type = theType;
peek->next = NULL;
peek->bucket = (unsigned int) tally;
peek->count = 0;
peek->permanent = false;
peek->header.type = EXTERNAL_ADDRESS_TYPE;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) peek,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralExternalAddressList,
sizeof(CLIPSExternalAddress),sizeof(long),true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
return peek;
}
size_t HashSymbol(
const char *word,
size_t range)
{
size_t i;
size_t tally = 0;
for (i = 0; word[i]; i++)
{ tally = tally * 127 + (size_t) word[i]; }
if (range == 0)
{ return tally; }
return tally % range;
}
size_t HashFloat(
double number,
size_t range)
{
size_t tally = 0;
char *word;
size_t i;
word = (char *) &number;
for (i = 0; i < sizeof(double); i++)
{ tally = tally * 127 + (size_t) word[i]; }
if (range == 0)
{ return tally; }
return tally % range;
}
size_t HashInteger(
long long number,
size_t range)
{
size_t tally;
#if WIN_MVC
if (number < 0)
{ number = - number; }
tally = (((size_t) number) % range);
#else
tally = (((size_t) llabs(number)) % range);
#endif
if (range == 0)
{ return tally; }
return tally;
}
size_t HashExternalAddress(
void *theExternalAddress,
size_t range)
{
size_t tally;
union
{
void *vv;
unsigned uv;
} fis;
fis.uv = 0;
fis.vv = theExternalAddress;
tally = (fis.uv / 256);
if (range == 0)
{ return tally; }
return(tally % range);
}
size_t HashBitMap(
const char *word,
size_t range,
unsigned length)
{
unsigned k,j,i;
size_t tally;
unsigned longLength;
unsigned long count = 0L,tmpLong;
char *tmpPtr;
tmpPtr = (char *) &tmpLong;
longLength = length / sizeof(unsigned long);
for (i = 0 , j = 0 ; i < longLength; i++)
{
for (k = 0 ; k < sizeof(unsigned long) ; k++ , j++)
tmpPtr[k] = word[j];
count += tmpLong;
}
for (; j < length; j++) count += (size_t) word[j];
if (range == 0)
{ return count; }
tally = (count % range);
return tally;
}
void RetainLexeme(
Environment *theEnv,
CLIPSLexeme *theValue)
{
theValue->count++;
}
void ReleaseLexeme(
Environment *theEnv,
CLIPSLexeme *theValue)
{
if (theValue->count < 0)
{
SystemError(theEnv,"SYMBOL",3);
ExitRouter(theEnv,EXIT_FAILURE);
}
if (theValue->count == 0)
{
SystemError(theEnv,"SYMBOL",4);
ExitRouter(theEnv,EXIT_FAILURE);
}
theValue->count--;
if (theValue->count != 0) return;
if (theValue->markedEphemeral == false)
{
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralSymbolList,
sizeof(CLIPSLexeme),AVERAGE_STRING_SIZE,true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
}
return;
}
void RetainFloat(
Environment *theEnv,
CLIPSFloat *theValue)
{
theValue->count++;
}
void ReleaseFloat(
Environment *theEnv,
CLIPSFloat *theValue)
{
if (theValue->count <= 0)
{
SystemError(theEnv,"SYMBOL",5);
ExitRouter(theEnv,EXIT_FAILURE);
}
theValue->count--;
if (theValue->count != 0) return;
if (theValue->markedEphemeral == false)
{
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralFloatList,
sizeof(CLIPSFloat),0,true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
}
return;
}
void RetainInteger(
Environment *theEnv,
CLIPSInteger *theValue)
{
theValue->count++;
}
void ReleaseInteger(
Environment *theEnv,
CLIPSInteger *theValue)
{
if (theValue->count <= 0)
{
SystemError(theEnv,"SYMBOL",6);
ExitRouter(theEnv,EXIT_FAILURE);
}
theValue->count--;
if (theValue->count != 0) return;
if (theValue->markedEphemeral == false)
{
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralIntegerList,
sizeof(CLIPSInteger),0,true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
}
return;
}
void IncrementBitMapReferenceCount(
Environment *theEnv,
CLIPSBitMap *theValue)
{
theValue->count++;
}
void DecrementBitMapReferenceCount(
Environment *theEnv,
CLIPSBitMap *theValue)
{
if (theValue->count < 0)
{
SystemError(theEnv,"SYMBOL",7);
ExitRouter(theEnv,EXIT_FAILURE);
}
if (theValue->count == 0)
{
SystemError(theEnv,"SYMBOL",8);
ExitRouter(theEnv,EXIT_FAILURE);
}
theValue->count--;
if (theValue->count != 0) return;
if (theValue->markedEphemeral == false)
{
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralBitMapList,
sizeof(CLIPSBitMap),sizeof(long),true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
}
return;
}
void RetainExternalAddress(
Environment *theEnv,
CLIPSExternalAddress *theValue)
{
theValue->count++;
}
void ReleaseExternalAddress(
Environment *theEnv,
CLIPSExternalAddress *theValue)
{
if (theValue->count < 0)
{
SystemError(theEnv,"SYMBOL",9);
ExitRouter(theEnv,EXIT_FAILURE);
}
if (theValue->count == 0)
{
SystemError(theEnv,"SYMBOL",10);
ExitRouter(theEnv,EXIT_FAILURE);
}
theValue->count--;
if (theValue->count != 0) return;
if (theValue->markedEphemeral == false)
{
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralExternalAddressList,
sizeof(CLIPSExternalAddress),sizeof(long),true);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
}
return;
}
static void RemoveHashNode(
Environment *theEnv,
GENERIC_HN *theValue,
GENERIC_HN **theTable,
int size,
int type)
{
GENERIC_HN *previousNode, *currentNode;
CLIPSExternalAddress *theAddress;
previousNode = NULL;
currentNode = theTable[theValue->bucket];
while (currentNode != theValue)
{
previousNode = currentNode;
currentNode = currentNode->next;
if (currentNode == NULL)
{
SystemError(theEnv,"SYMBOL",11);
ExitRouter(theEnv,EXIT_FAILURE);
}
}
if (previousNode == NULL)
{ theTable[theValue->bucket] = theValue->next; }
else
{ previousNode->next = currentNode->next; }
if (type == SYMBOL_TYPE)
{
rm(theEnv,(void *) ((CLIPSLexeme *) theValue)->contents,
strlen(((CLIPSLexeme *) theValue)->contents) + 1);
}
else if (type == BITMAPARRAY)
{
rm(theEnv,(void *) ((CLIPSBitMap *) theValue)->contents,
((CLIPSBitMap *) theValue)->size);
}
else if (type == EXTERNAL_ADDRESS_TYPE)
{
theAddress = (CLIPSExternalAddress *) theValue;
if ((EvaluationData(theEnv)->ExternalAddressTypes[theAddress->type] != NULL) &&
(EvaluationData(theEnv)->ExternalAddressTypes[theAddress->type]->discardFunction != NULL))
{ (*EvaluationData(theEnv)->ExternalAddressTypes[theAddress->type]->discardFunction)(theEnv,theAddress->contents); }
}
rtn_sized_struct(theEnv,size,theValue);
}
static void AddEphemeralHashNode(
Environment *theEnv,
GENERIC_HN *theHashNode,
struct ephemeron **theEphemeralList,
int hashNodeSize,
int averageContentsSize,
bool checkCount)
{
struct ephemeron *temp;
if (checkCount && (theHashNode->count != 0))
{
SystemError(theEnv,"SYMBOL",12);
ExitRouter(theEnv,EXIT_FAILURE);
}
theHashNode->markedEphemeral = true;
temp = get_struct(theEnv,ephemeron);
temp->associatedValue = theHashNode;
temp->next = *theEphemeralList;
*theEphemeralList = temp;
}
void RemoveEphemeralAtoms(
Environment *theEnv)
{
struct garbageFrame *theGarbageFrame;
theGarbageFrame = UtilityData(theEnv)->CurrentGarbageFrame;
if (! theGarbageFrame->dirty) return;
RemoveEphemeralHashNodes(theEnv,&theGarbageFrame->ephemeralSymbolList,(GENERIC_HN **) SymbolData(theEnv)->SymbolTable,
sizeof(CLIPSLexeme),SYMBOL_TYPE,AVERAGE_STRING_SIZE);
RemoveEphemeralHashNodes(theEnv,&theGarbageFrame->ephemeralFloatList,(GENERIC_HN **) SymbolData(theEnv)->FloatTable,
sizeof(CLIPSFloat),FLOAT_TYPE,0);
RemoveEphemeralHashNodes(theEnv,&theGarbageFrame->ephemeralIntegerList,(GENERIC_HN **) SymbolData(theEnv)->IntegerTable,
sizeof(CLIPSInteger),INTEGER_TYPE,0);
RemoveEphemeralHashNodes(theEnv,&theGarbageFrame->ephemeralBitMapList,(GENERIC_HN **) SymbolData(theEnv)->BitMapTable,
sizeof(CLIPSBitMap),BITMAPARRAY,AVERAGE_BITMAP_SIZE);
RemoveEphemeralHashNodes(theEnv,&theGarbageFrame->ephemeralExternalAddressList,(GENERIC_HN **) SymbolData(theEnv)->ExternalAddressTable,
sizeof(CLIPSExternalAddress),EXTERNAL_ADDRESS_TYPE,0);
}
void EphemerateValue(
Environment *theEnv,
void *theValue)
{
CLIPSLexeme *theSymbol;
CLIPSFloat *theFloat;
CLIPSInteger *theInteger;
CLIPSExternalAddress *theExternalAddress;
switch (((TypeHeader *) theValue)->type)
{
case SYMBOL_TYPE:
case STRING_TYPE:
#if OBJECT_SYSTEM
case INSTANCE_NAME_TYPE:
#endif
theSymbol = (CLIPSLexeme *) theValue;
if (theSymbol->markedEphemeral) return;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,
&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralSymbolList,
sizeof(CLIPSLexeme),AVERAGE_STRING_SIZE,false);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
break;
case FLOAT_TYPE:
theFloat = (CLIPSFloat *) theValue;
if (theFloat->markedEphemeral) return;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,
&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralFloatList,
sizeof(CLIPSFloat),0,false);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
break;
case INTEGER_TYPE:
theInteger = (CLIPSInteger *) theValue;
if (theInteger->markedEphemeral) return;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,
&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralIntegerList,
sizeof(CLIPSInteger),0,false);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
break;
case EXTERNAL_ADDRESS_TYPE:
theExternalAddress = (CLIPSExternalAddress *) theValue;
if (theExternalAddress->markedEphemeral) return;
AddEphemeralHashNode(theEnv,(GENERIC_HN *) theValue,
&UtilityData(theEnv)->CurrentGarbageFrame->ephemeralExternalAddressList,
sizeof(CLIPSExternalAddress),sizeof(long),false);
UtilityData(theEnv)->CurrentGarbageFrame->dirty = true;
break;
case MULTIFIELD_TYPE:
EphemerateMultifield(theEnv,(Multifield *) theValue);
break;
}
}
static void RemoveEphemeralHashNodes(
Environment *theEnv,
struct ephemeron **theEphemeralList,
GENERIC_HN **theTable,
int hashNodeSize,
int hashNodeType,
int averageContentsSize)
{
struct ephemeron *edPtr, *lastPtr = NULL, *nextPtr;
edPtr = *theEphemeralList;
while (edPtr != NULL)
{
nextPtr = edPtr->next;
if (edPtr->associatedValue->count == 0)
{
RemoveHashNode(theEnv,edPtr->associatedValue,theTable,hashNodeSize,hashNodeType);
rtn_struct(theEnv,ephemeron,edPtr);
if (lastPtr == NULL) *theEphemeralList = nextPtr;
else lastPtr->next = nextPtr;
}
else if (edPtr->associatedValue->count > 0)
{
edPtr->associatedValue->markedEphemeral = false;
rtn_struct(theEnv,ephemeron,edPtr);
if (lastPtr == NULL) *theEphemeralList = nextPtr;
else lastPtr->next = nextPtr;
}
else
{ lastPtr = edPtr; }
edPtr = nextPtr;
}
}
CLIPSLexeme **GetSymbolTable(
Environment *theEnv)
{
return(SymbolData(theEnv)->SymbolTable);
}
void SetSymbolTable(
Environment *theEnv,
CLIPSLexeme **value)
{
SymbolData(theEnv)->SymbolTable = value;
}
CLIPSFloat **GetFloatTable(
Environment *theEnv)
{
return(SymbolData(theEnv)->FloatTable);
}
void SetFloatTable(
Environment *theEnv,
CLIPSFloat **value)
{
SymbolData(theEnv)->FloatTable = value;
}
CLIPSInteger **GetIntegerTable(
Environment *theEnv)
{
return(SymbolData(theEnv)->IntegerTable);
}
void SetIntegerTable(
Environment *theEnv,
CLIPSInteger **value)
{
SymbolData(theEnv)->IntegerTable = value;
}
CLIPSBitMap **GetBitMapTable(
Environment *theEnv)
{
return(SymbolData(theEnv)->BitMapTable);
}
void SetBitMapTable(
Environment *theEnv,
CLIPSBitMap **value)
{
SymbolData(theEnv)->BitMapTable = value;
}
CLIPSExternalAddress **GetExternalAddressTable(
Environment *theEnv)
{
return(SymbolData(theEnv)->ExternalAddressTable);
}
void SetExternalAddressTable(
Environment *theEnv,
CLIPSExternalAddress **value)
{
SymbolData(theEnv)->ExternalAddressTable = value;
}
void RefreshSpecialSymbols(
Environment *theEnv)
{
SymbolData(theEnv)->PositiveInfinity = FindSymbolHN(theEnv,POSITIVE_INFINITY_STRING,SYMBOL_BIT);
SymbolData(theEnv)->NegativeInfinity = FindSymbolHN(theEnv,NEGATIVE_INFINITY_STRING,SYMBOL_BIT);
SymbolData(theEnv)->Zero = FindLongHN(theEnv,0L);
}
struct symbolMatch *FindSymbolMatches(
Environment *theEnv,
const char *searchString,
unsigned *numberOfMatches,
size_t *commonPrefixLength)
{
struct symbolMatch *reply = NULL, *temp;
CLIPSLexeme *hashPtr = NULL;
size_t searchLength;
searchLength = strlen(searchString);
*numberOfMatches = 0;
while ((hashPtr = GetNextSymbolMatch(theEnv,searchString,searchLength,hashPtr,
false,commonPrefixLength)) != NULL)
{
*numberOfMatches = *numberOfMatches + 1;
temp = get_struct(theEnv,symbolMatch);
temp->match = hashPtr;
temp->next = reply;
reply = temp;
}
return(reply);
}
void ReturnSymbolMatches(
Environment *theEnv,
struct symbolMatch *listOfMatches)
{
struct symbolMatch *temp;
while (listOfMatches != NULL)
{
temp = listOfMatches->next;
rtn_struct(theEnv,symbolMatch,listOfMatches);
listOfMatches = temp;
}
}
void ClearBitString(
void *vTheBitMap,
size_t length)
{
char *theBitMap = (char *) vTheBitMap;
size_t i;
for (i = 0; i < length; i++) theBitMap[i] = '\0';
}
bool BitStringHasBitsSet(
void *vTheBitMap,
unsigned length)
{
char *theBitMap = (char *) vTheBitMap;
unsigned i;
for (i = 0; i < length; i++)
{ if (theBitMap[i] != '\0') return true; }
return false;
}
CLIPSLexeme *GetNextSymbolMatch(
Environment *theEnv,
const char *searchString,
size_t searchLength,
CLIPSLexeme *prevSymbol,
bool anywhere,
size_t *commonPrefixLength)
{
unsigned long i;
CLIPSLexeme *hashPtr;
bool flag = true;
size_t prefixLength;
if (anywhere && (commonPrefixLength != NULL))
*commonPrefixLength = 0;
if (prevSymbol == NULL)
{
i = 0;
hashPtr = SymbolData(theEnv)->SymbolTable[0];
}
else
{
i = prevSymbol->bucket;
hashPtr = prevSymbol->next;
}
while (flag)
{
for (; hashPtr != NULL; hashPtr = hashPtr->next)
{
if ((hashPtr->contents[0] == '(') ||
(hashPtr->markedEphemeral))
{ continue; }
if (! anywhere)
{
if (prevSymbol != NULL)
prefixLength = CommonPrefixLength(prevSymbol->contents,hashPtr->contents);
else
prefixLength = CommonPrefixLength(searchString,hashPtr->contents);
if (prefixLength >= searchLength)
{
if (commonPrefixLength != NULL)
{
if (prevSymbol == NULL)
*commonPrefixLength = strlen(hashPtr->contents);
else if (prefixLength < *commonPrefixLength)
*commonPrefixLength = prefixLength;
}
return(hashPtr);
}
}
else
{
if (StringWithinString(hashPtr->contents,searchString) != NULL)
{ return(hashPtr); }
}
}
if (++i >= SYMBOL_HASH_SIZE) flag = false;
else hashPtr = SymbolData(theEnv)->SymbolTable[i];
}
return NULL;
}
static const char *StringWithinString(
const char *cs,
const char *ct)
{
unsigned i,j,k;
for (i = 0 ; cs[i] != '\0' ; i++)
{
for (j = i , k = 0 ; ct[k] != '\0' && cs[j] == ct[k] ; j++, k++) ;
if ((ct[k] == '\0') && (k != 0))
return(cs + i);
}
return NULL;
}
static size_t CommonPrefixLength(
const char *cs,
const char *ct)
{
unsigned i;
for (i = 0 ; (cs[i] != '\0') && (ct[i] != '\0') ; i++)
if (cs[i] != ct[i])
break;
return(i);
}
#if BLOAD_AND_BSAVE || CONSTRUCT_COMPILER || BSAVE_INSTANCES
void SetAtomicValueIndices(
Environment *theEnv,
bool setAll)
{
unsigned int count;
unsigned int i;
CLIPSLexeme *symbolPtr, **symbolArray;
CLIPSFloat *floatPtr, **floatArray;
CLIPSInteger *integerPtr, **integerArray;
CLIPSBitMap *bitMapPtr, **bitMapArray;
count = 0;
symbolArray = GetSymbolTable(theEnv);
for (i = 0; i < SYMBOL_HASH_SIZE; i++)
{
for (symbolPtr = symbolArray[i];
symbolPtr != NULL;
symbolPtr = symbolPtr->next)
{
if ((symbolPtr->neededSymbol == true) || setAll)
{ symbolPtr->bucket = count++; }
}
}
count = 0;
floatArray = GetFloatTable(theEnv);
for (i = 0; i < FLOAT_HASH_SIZE; i++)
{
for (floatPtr = floatArray[i];
floatPtr != NULL;
floatPtr = floatPtr->next)
{
if ((floatPtr->neededFloat == true) || setAll)
{ floatPtr->bucket = count++; }
}
}
count = 0;
integerArray = GetIntegerTable(theEnv);
for (i = 0; i < INTEGER_HASH_SIZE; i++)
{
for (integerPtr = integerArray[i];
integerPtr != NULL;
integerPtr = integerPtr->next)
{
if ((integerPtr->neededInteger == true) || setAll)
{ integerPtr->bucket = count++; }
}
}
count = 0;
bitMapArray = GetBitMapTable(theEnv);
for (i = 0; i < BITMAP_HASH_SIZE; i++)
{
for (bitMapPtr = bitMapArray[i];
bitMapPtr != NULL;
bitMapPtr = bitMapPtr->next)
{
if ((bitMapPtr->neededBitMap == true) || setAll)
{ bitMapPtr->bucket = count++; }
}
}
}
void RestoreAtomicValueBuckets(
Environment *theEnv)
{
unsigned int i;
CLIPSLexeme *symbolPtr, **symbolArray;
CLIPSFloat *floatPtr, **floatArray;
CLIPSInteger *integerPtr, **integerArray;
CLIPSBitMap *bitMapPtr, **bitMapArray;
symbolArray = GetSymbolTable(theEnv);
for (i = 0; i < SYMBOL_HASH_SIZE; i++)
{
for (symbolPtr = symbolArray[i];
symbolPtr != NULL;
symbolPtr = symbolPtr->next)
{ symbolPtr->bucket = i; }
}
floatArray = GetFloatTable(theEnv);
for (i = 0; i < FLOAT_HASH_SIZE; i++)
{
for (floatPtr = floatArray[i];
floatPtr != NULL;
floatPtr = floatPtr->next)
{ floatPtr->bucket = i; }
}
integerArray = GetIntegerTable(theEnv);
for (i = 0; i < INTEGER_HASH_SIZE; i++)
{
for (integerPtr = integerArray[i];
integerPtr != NULL;
integerPtr = integerPtr->next)
{ integerPtr->bucket = i; }
}
bitMapArray = GetBitMapTable(theEnv);
for (i = 0; i < BITMAP_HASH_SIZE; i++)
{
for (bitMapPtr = bitMapArray[i];
bitMapPtr != NULL;
bitMapPtr = bitMapPtr->next)
{ bitMapPtr->bucket = i; }
}
}
#endif