📄 classfun.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 06/02/06 */
/* */
/* CLASS FUNCTIONS MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Internal class manipulation routines */
/* */
/* Principal Programmer(s): */
/* Brian L. Donnell */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* */
/* 6.24: Renamed BOOLEAN macro type to intBool. */
/* */
/* Corrected code to remove run-time program */
/* compiler warning. */
/* */
/*************************************************************/
/* =========================================
*****************************************
EXTERNAL DEFINITIONS
=========================================
***************************************** */
#include <stdlib.h>
#include "setup.h"
#if OBJECT_SYSTEM
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
#include "bload.h"
#endif
#include "classcom.h"
#include "classini.h"
#include "constant.h"
#include "constrct.h"
#include "cstrccom.h"
#include "cstrcpsr.h"
#include "envrnmnt.h"
#include "evaluatn.h"
#include "inscom.h"
#include "insfun.h"
#include "insmngr.h"
#include "memalloc.h"
#include "modulutl.h"
#include "msgfun.h"
#include "router.h"
#include "scanner.h"
#include "utility.h"
#define _CLASSFUN_SOURCE_
#include "classfun.h"
/* =========================================
*****************************************
CONSTANTS
=========================================
***************************************** */
#define BIG_PRIME 11329
#define CLASS_ID_MAP_CHUNK 30
#define PUT_PREFIX "put-"
#define PUT_PREFIX_LENGTH 4
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTION HEADERS
=========================================
***************************************** */
static unsigned HashSlotName(SYMBOL_HN *);
#if (! RUN_TIME)
static unsigned NewSlotNameID(void *);
static void DeassignClassID(void *,unsigned);
#endif
/* =========================================
*****************************************
EXTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/***************************************************
NAME : IncrementDefclassBusyCount
DESCRIPTION : Increments use count of defclass
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Busy count incremented
NOTES : None
***************************************************/
#if IBM_TBC
#pragma argsused
#endif
globle void IncrementDefclassBusyCount(
void *theEnv,
void *theDefclass)
{
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(theEnv)
#endif
((DEFCLASS *) theDefclass)->busy++;
}
/***************************************************
NAME : DecrementDefclassBusyCount
DESCRIPTION : Decrements use count of defclass
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Busy count decremented
NOTES : Since use counts are ignored on
a clear and defclasses might be
deleted already anyway, this is
a no-op on a clear
***************************************************/
globle void DecrementDefclassBusyCount(
void *theEnv,
void *theDefclass)
{
if (! ConstructData(theEnv)->ClearInProgress)
((DEFCLASS *) theDefclass)->busy--;
}
/****************************************************
NAME : InstancesPurge
DESCRIPTION : Removes all instances
INPUTS : None
RETURNS : TRUE if all instances deleted,
FALSE otherwise
SIDE EFFECTS : The instance hash table is cleared
NOTES : None
****************************************************/
globle intBool InstancesPurge(
void *theEnv)
{
int svdepth;
DestroyAllInstances(theEnv);
svdepth = EvaluationData(theEnv)->CurrentEvaluationDepth;
if (EvaluationData(theEnv)->CurrentEvaluationDepth == 0)
EvaluationData(theEnv)->CurrentEvaluationDepth = -1;
CleanupInstances(theEnv);
EvaluationData(theEnv)->CurrentEvaluationDepth = svdepth;
return((InstanceData(theEnv)->InstanceList != NULL) ? FALSE : TRUE);
}
#if ! RUN_TIME
/***************************************************
NAME : InitializeClasses
DESCRIPTION : Allocates class hash table
Initializes class hash table
to all NULL addresses
Creates system classes
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Hash table initialized
NOTES : None
***************************************************/
globle void InitializeClasses(
void *theEnv)
{
register int i;
DefclassData(theEnv)->ClassTable =
(DEFCLASS **) gm2(theEnv,(int) (sizeof(DEFCLASS *) * CLASS_TABLE_HASH_SIZE));
for (i = 0 ; i < CLASS_TABLE_HASH_SIZE ; i++)
DefclassData(theEnv)->ClassTable[i] = NULL;
DefclassData(theEnv)->SlotNameTable =
(SLOT_NAME **) gm2(theEnv,(int) (sizeof(SLOT_NAME *) * SLOT_NAME_TABLE_HASH_SIZE));
for (i = 0 ; i < SLOT_NAME_TABLE_HASH_SIZE ; i++)
DefclassData(theEnv)->SlotNameTable[i] = NULL;
}
#endif
/********************************************************
NAME : FindClassSlot
DESCRIPTION : Searches for a named slot in a class
INPUTS : 1) The class address
2) The symbolic slot name
RETURNS : Address of slot if found, NULL otherwise
SIDE EFFECTS : None
NOTES : Only looks in class defn, does not
examine inheritance paths
********************************************************/
globle SLOT_DESC *FindClassSlot(
DEFCLASS *cls,
SYMBOL_HN *sname)
{
register unsigned i;
for (i = 0 ; i < cls->slotCount ; i++)
{
if (cls->slots[i].slotName->name == sname)
return(&cls->slots[i]);
}
return(NULL);
}
/***************************************************************
NAME : ClassExistError
DESCRIPTION : Prints out error message for non-existent class
INPUTS : 1) Name of function having the error
2) The name of the non-existent class
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : None
***************************************************************/
globle void ClassExistError(
void *theEnv,
char *func,
char *cname)
{
PrintErrorID(theEnv,"CLASSFUN",1,FALSE);
EnvPrintRouter(theEnv,WERROR,"Unable to find class ");
EnvPrintRouter(theEnv,WERROR,cname);
EnvPrintRouter(theEnv,WERROR," in function ");
EnvPrintRouter(theEnv,WERROR,func);
EnvPrintRouter(theEnv,WERROR,".\n");
SetEvaluationError(theEnv,TRUE);
}
/*********************************************
NAME : DeleteClassLinks
DESCRIPTION : Deallocates a class link list
INPUTS : The address of the list
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : None
*********************************************/
globle void DeleteClassLinks(
void *theEnv,
CLASS_LINK *clink)
{
CLASS_LINK *ctmp;
for (ctmp = clink ; ctmp != NULL ; ctmp = clink)
{
clink = clink->nxt;
rtn_struct(theEnv,classLink,ctmp);
}
}
/******************************************************
NAME : PrintClassName
DESCRIPTION : Displays a class's name
INPUTS : 1) Logical name of output
2) The class
3) Flag indicating whether to
print carriage-return at end
RETURNS : Nothing useful
SIDE EFFECTS : Class name printed (and module name
too if class is not in current module)
NOTES : None
******************************************************/
globle void PrintClassName(
void *theEnv,
char *logicalName,
DEFCLASS *theDefclass,
intBool linefeedFlag)
{
if ((theDefclass->header.whichModule->theModule != ((struct defmodule *) EnvGetCurrentModule(theEnv))) &&
(theDefclass->system == 0))
{
EnvPrintRouter(theEnv,logicalName,
EnvGetDefmoduleName(theEnv,theDefclass->header.whichModule->theModule));
EnvPrintRouter(theEnv,logicalName,"::");
}
EnvPrintRouter(theEnv,logicalName,ValueToString(theDefclass->header.name));
if (linefeedFlag)
EnvPrintRouter(theEnv,logicalName,"\n");
}
#if DEBUGGING_FUNCTIONS || ((! BLOAD_ONLY) && (! RUN_TIME))
/***************************************************
NAME : PrintPackedClassLinks
DESCRIPTION : Displays the names of classes in
a list with a title
INPUTS : 1) The logical name of the output
2) Title string
3) List of class links
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : None
***************************************************/
globle void PrintPackedClassLinks(
void *theEnv,
char *logicalName,
char *title,
PACKED_CLASS_LINKS *plinks)
{
register unsigned i;
EnvPrintRouter(theEnv,logicalName,title);
for (i = 0 ; i < plinks->classCount ; i++)
{
EnvPrintRouter(theEnv,logicalName," ");
PrintClassName(theEnv,logicalName,plinks->classArray[i],FALSE);
}
EnvPrintRouter(theEnv,logicalName,"\n");
}
#endif
#if ! RUN_TIME
/*******************************************************
NAME : PutClassInTable
DESCRIPTION : Inserts a class in the class hash table
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Class inserted
NOTES : None
*******************************************************/
globle void PutClassInTable(
void *theEnv,
DEFCLASS *cls)
{
cls->hashTableIndex = HashClass(GetDefclassNamePointer((void *) cls));
cls->nxtHash = DefclassData(theEnv)->ClassTable[cls->hashTableIndex];
DefclassData(theEnv)->ClassTable[cls->hashTableIndex] = cls;
}
/*********************************************************
NAME : RemoveClassFromTable
DESCRIPTION : Removes a class from the class hash table
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Class removed
NOTES : None
*********************************************************/
globle void RemoveClassFromTable(
void *theEnv,
DEFCLASS *cls)
{
DEFCLASS *prvhsh,*hshptr;
prvhsh = NULL;
hshptr = DefclassData(theEnv)->ClassTable[cls->hashTableIndex];
while (hshptr != cls)
{
prvhsh = hshptr;
hshptr = hshptr->nxtHash;
}
if (prvhsh == NULL)
DefclassData(theEnv)->ClassTable[cls->hashTableIndex] = cls->nxtHash;
else
prvhsh->nxtHash = cls->nxtHash;
}
/***************************************************
NAME : AddClassLink
DESCRIPTION : Adds a class link from one class to
another
INPUTS : 1) The packed links in which to
insert the new class
2) The subclass pointer
3) Index of where to place the
class (-1 to append)
RETURNS : Nothing useful
SIDE EFFECTS : Link created and attached
NOTES : Assumes the pack structure belongs
to a class and does not need to
be deallocated
***************************************************/
globle void AddClassLink(
void *theEnv,
PACKED_CLASS_LINKS *src,
DEFCLASS *cls,
int posn)
{
PACKED_CLASS_LINKS dst;
dst.classArray = (DEFCLASS **) gm2(theEnv,(sizeof(DEFCLASS *) * (src->classCount + 1)));
if (posn == -1)
{
GenCopyMemory(DEFCLASS *,src->classCount,dst.classArray,src->classArray);
dst.classArray[src->classCount] = cls;
}
else
{
if (posn != 0)
GenCopyMemory(DEFCLASS *,posn,dst.classArray,src->classArray);
GenCopyMemory(DEFCLASS *,src->classCount - posn,
dst.classArray + posn + 1,src->classArray + posn);
dst.classArray[posn] = cls;
}
dst.classCount = (unsigned short) (src->classCount + 1);
DeletePackedClassLinks(theEnv,src,FALSE);
src->classCount = dst.classCount;
src->classArray = dst.classArray;
}
/***************************************************
NAME : DeleteSubclassLink
DESCRIPTION : Removes a class from another
class's subclass list
INPUTS : 1) The superclass whose subclass
list is to be modified
2) The subclass to be removed
RETURNS : Nothing useful
SIDE EFFECTS : The subclass list is changed
NOTES : None
***************************************************/
globle void DeleteSubclassLink(
void *theEnv,
DEFCLASS *sclass,
DEFCLASS *cls)
{
register unsigned deletedIndex;
PACKED_CLASS_LINKS *src,dst;
src = &sclass->directSubclasses;
for (deletedIndex = 0 ; deletedIndex < src->classCount ; deletedIndex++)
if (src->classArray[deletedIndex] == cls)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -