📄 symbol.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/05/06 */
/* */
/* SYMBOL MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Manages the atomic data value hash tables for */
/* storing symbols, integers, floats, and bit maps. */
/* Contains routines for adding entries, examining the */
/* hash tables, and performing garbage collection to */
/* remove entries no longer in use. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* Brian L. Donnell */
/* */
/* Revision History: */
/* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 */
/* */
/* 6.24: CLIPS crashing on AMD64 processor in the */
/* function used to generate a hash value for */
/* integers. DR0871 */
/* */
/* Support for run-time programs directly passing */
/* the hash tables for initialization. */
/* */
/* Corrected code generating compilation */
/* warnings. */
/* */
/*************************************************************/
#define _SYMBOL_SOURCE_
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <stdlib.h>
#include <string.h>
#include "setup.h"
#include "constant.h"
#include "envrnmnt.h"
#include "memalloc.h"
#include "router.h"
#include "utility.h"
#include "argacces.h"
#include "symbol.h"
/***************/
/* DEFINITIONS */
/***************/
#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
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static void RemoveHashNode(void *,GENERIC_HN *,GENERIC_HN **,int,int);
static void AddEphemeralHashNode(void *,GENERIC_HN *,struct ephemeron **,
int,int);
static void RemoveEphemeralHashNodes(void *,struct ephemeron **,
GENERIC_HN **,
int,int,int);
static char *StringWithinString(char *,char *);
static unsigned CommonPrefixLength(char *,char *);
static void DeallocateSymbolData(void *);
/*******************************************************/
/* InitializeAtomTables: Initializes the SymbolTable, */
/* IntegerTable, and FloatTable. It also initializes */
/* the TrueSymbol and FalseSymbol. */
/*******************************************************/
#if IBM_TBC && (! RUN_TIME)
#pragma argsused
#endif
globle void InitializeAtomTables(
void *theEnv,
struct symbolHashNode **symbolTable,
struct floatHashNode **floatTable,
struct integerHashNode **integerTable,
struct bitMapHashNode **bitmapTable)
{
#if ! RUN_TIME
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(symbolTable)
#pragma unused(floatTable)
#pragma unused(integerTable)
#pragma unused(bitmapTable)
#endif
unsigned long i;
#endif
AllocateEnvironmentData(theEnv,SYMBOL_DATA,sizeof(struct symbolData),DeallocateSymbolData);
#if ! RUN_TIME
/*=========================*/
/* Create the hash tables. */
/*=========================*/
SymbolData(theEnv)->SymbolTable = (SYMBOL_HN **)
gm3(theEnv,sizeof (SYMBOL_HN *) * SYMBOL_HASH_SIZE);
SymbolData(theEnv)->FloatTable = (FLOAT_HN **)
gm2(theEnv,(int) sizeof (FLOAT_HN *) * FLOAT_HASH_SIZE);
SymbolData(theEnv)->IntegerTable = (INTEGER_HN **)
gm2(theEnv,(int) sizeof (INTEGER_HN *) * INTEGER_HASH_SIZE);
SymbolData(theEnv)->BitMapTable = (BITMAP_HN **)
gm2(theEnv,(int) sizeof (BITMAP_HN *) * BITMAP_HASH_SIZE);
/*===================================================*/
/* Initialize all of the hash table entries to NULL. */
/*===================================================*/
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;
/*========================*/
/* Predefine some values. */
/*========================*/
SymbolData(theEnv)->TrueSymbolHN = EnvAddSymbol(theEnv,TRUE_STRING);
IncrementSymbolCount(SymbolData(theEnv)->TrueSymbolHN);
SymbolData(theEnv)->FalseSymbolHN = EnvAddSymbol(theEnv,FALSE_STRING);
IncrementSymbolCount(SymbolData(theEnv)->FalseSymbolHN);
SymbolData(theEnv)->PositiveInfinity = EnvAddSymbol(theEnv,POSITIVE_INFINITY_STRING);
IncrementSymbolCount(SymbolData(theEnv)->PositiveInfinity);
SymbolData(theEnv)->NegativeInfinity = EnvAddSymbol(theEnv,NEGATIVE_INFINITY_STRING);
IncrementSymbolCount(SymbolData(theEnv)->NegativeInfinity);
SymbolData(theEnv)->Zero = EnvAddLong(theEnv,0L);
IncrementIntegerCount(SymbolData(theEnv)->Zero);
#else
SetSymbolTable(theEnv,symbolTable);
SetFloatTable(theEnv,floatTable);
SetIntegerTable(theEnv,integerTable);
SetBitMapTable(theEnv,bitmapTable);
#endif
}
/*************************************************/
/* DeallocateSymbolData: Deallocates environment */
/* data for symbols. */
/*************************************************/
static void DeallocateSymbolData(
void *theEnv)
{
int i;
SYMBOL_HN *shPtr, *nextSHPtr;
INTEGER_HN *ihPtr, *nextIHPtr;
FLOAT_HN *fhPtr, *nextFHPtr;
BITMAP_HN *bmhPtr, *nextBMHPtr;
struct ephemeron *edPtr, *nextEDPtr;
if ((SymbolData(theEnv)->SymbolTable == NULL) ||
(SymbolData(theEnv)->FloatTable == NULL) ||
(SymbolData(theEnv)->IntegerTable == NULL) ||
(SymbolData(theEnv)->BitMapTable == NULL))
{ return; }
for (i = 0; i < SYMBOL_HASH_SIZE; i++)
{
shPtr = SymbolData(theEnv)->SymbolTable[i];
while (shPtr != NULL)
{
nextSHPtr = shPtr->next;
if (! shPtr->permanent)
{
rm(theEnv,shPtr->contents,strlen(shPtr->contents)+1);
rtn_struct(theEnv,symbolHashNode,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,floatHashNode,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,integerHashNode,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,bmhPtr->contents,bmhPtr->size);
rtn_struct(theEnv,bitMapHashNode,bmhPtr);
}
bmhPtr = nextBMHPtr;
}
}
/*=========================================*/
/* Remove the ephemeral symbol structures. */
/*=========================================*/
edPtr = SymbolData(theEnv)->EphemeralSymbolList;
while (edPtr != NULL)
{
nextEDPtr = edPtr->next;
rtn_struct(theEnv,ephemeron,edPtr);
edPtr = nextEDPtr;
}
edPtr = SymbolData(theEnv)->EphemeralFloatList;
while (edPtr != NULL)
{
nextEDPtr = edPtr->next;
rtn_struct(theEnv,ephemeron,edPtr);
edPtr = nextEDPtr;
}
edPtr = SymbolData(theEnv)->EphemeralIntegerList;
while (edPtr != NULL)
{
nextEDPtr = edPtr->next;
rtn_struct(theEnv,ephemeron,edPtr);
edPtr = nextEDPtr;
}
edPtr = SymbolData(theEnv)->EphemeralBitMapList;
while (edPtr != NULL)
{
nextEDPtr = edPtr->next;
rtn_struct(theEnv,ephemeron,edPtr);
edPtr = nextEDPtr;
}
/*================================*/
/* Remove the symbol hash tables. */
/*================================*/
#if ! RUN_TIME
rm3(theEnv,SymbolData(theEnv)->SymbolTable,sizeof (SYMBOL_HN *) * SYMBOL_HASH_SIZE);
genfree(theEnv,SymbolData(theEnv)->FloatTable,(int) sizeof (FLOAT_HN *) * FLOAT_HASH_SIZE);
genfree(theEnv,SymbolData(theEnv)->IntegerTable,(int) sizeof (INTEGER_HN *) * INTEGER_HASH_SIZE);
genfree(theEnv,SymbolData(theEnv)->BitMapTable,(int) sizeof (BITMAP_HN *) * BITMAP_HASH_SIZE);
#endif
/*==============================*/
/* Remove binary symbol tables. */
/*==============================*/
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE || BLOAD_INSTANCES || BSAVE_INSTANCES
if (SymbolData(theEnv)->SymbolArray != NULL)
rm3(theEnv,(void *) SymbolData(theEnv)->SymbolArray,(long) sizeof(SYMBOL_HN *) * SymbolData(theEnv)->NumberOfSymbols);
if (SymbolData(theEnv)->FloatArray != NULL)
rm3(theEnv,(void *) SymbolData(theEnv)->FloatArray,(long) sizeof(FLOAT_HN *) * SymbolData(theEnv)->NumberOfFloats);
if (SymbolData(theEnv)->IntegerArray != NULL)
rm3(theEnv,(void *) SymbolData(theEnv)->IntegerArray,(long) sizeof(INTEGER_HN *) * SymbolData(theEnv)->NumberOfIntegers);
if (SymbolData(theEnv)->BitMapArray != NULL)
rm3(theEnv,(void *) SymbolData(theEnv)->BitMapArray,(long) sizeof(BITMAP_HN *) * SymbolData(theEnv)->NumberOfBitMaps);
#endif
}
/*********************************************************************/
/* EnvAddSymbol: Searches for the string in the symbol table. If the */
/* string is already in the symbol table, then the address of the */
/* string's location in the symbol table is returned. Otherwise, */
/* the string is added to the symbol table and then the address */
/* of the string's location in the symbol table is returned. */
/*********************************************************************/
globle void *EnvAddSymbol(
void *theEnv,
char *str)
{
unsigned long tally;
size_t length;
SYMBOL_HN *past = NULL, *peek;
/*====================================*/
/* Get the hash value for the string. */
/*====================================*/
if (str == NULL)
{
SystemError(theEnv,"SYMBOL",1);
EnvExitRouter(theEnv,EXIT_FAILURE);
}
tally = HashSymbol(str,SYMBOL_HASH_SIZE);
peek = SymbolData(theEnv)->SymbolTable[tally];
/*==================================================*/
/* Search for the string in the list of entries for */
/* this symbol table location. If the string is */
/* found, then return the address of the string. */
/*==================================================*/
while (peek != NULL)
{
if (strcmp(str,peek->contents) == 0)
{ return((void *) peek); }
past = peek;
peek = peek->next;
}
/*==================================================*/
/* Add the string at the end of the list of entries */
/* for this symbol table location. */
/*==================================================*/
peek = get_struct(theEnv,symbolHashNode);
if (past == NULL) SymbolData(theEnv)->SymbolTable[tally] = peek;
else past->next = peek;
length = strlen(str) + 1;
peek->contents = (char *) gm2(theEnv,length);
peek->next = NULL;
peek->bucket = tally;
peek->count = 0;
peek->permanent = FALSE;
strcpy(peek->contents,str);
/*================================================*/
/* Add the string to the list of ephemeral items. */
/*================================================*/
AddEphemeralHashNode(theEnv,(GENERIC_HN *) peek,&SymbolData(theEnv)->EphemeralSymbolList,
sizeof(SYMBOL_HN),AVERAGE_STRING_SIZE);
peek->depth = EvaluationData(theEnv)->CurrentEvaluationDepth;
/*===================================*/
/* Return the address of the symbol. */
/*===================================*/
return((void *) peek);
}
/*****************************************************************/
/* FindSymbolHN: Searches for the string in the symbol table and */
/* returns a pointer to it if found, otherwise returns NULL. */
/*****************************************************************/
globle SYMBOL_HN *FindSymbolHN(
void *theEnv,
char *str)
{
unsigned long tally;
SYMBOL_HN *peek;
tally = HashSymbol(str,SYMBOL_HASH_SIZE);
for (peek = SymbolData(theEnv)->SymbolTable[tally];
peek != NULL;
peek = peek->next)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -