📄 classfun.c
字号:
break;
if (deletedIndex == src->classCount)
return;
if (src->classCount > 1)
{
dst.classArray = (DEFCLASS **) gm2(theEnv,(sizeof(DEFCLASS *) * (src->classCount - 1)));
if (deletedIndex != 0)
GenCopyMemory(DEFCLASS *,deletedIndex,dst.classArray,src->classArray);
GenCopyMemory(DEFCLASS *,src->classCount - deletedIndex - 1,
dst.classArray + deletedIndex,src->classArray + deletedIndex + 1);
}
else
dst.classArray = NULL;
dst.classCount = (unsigned short) (src->classCount - 1);
DeletePackedClassLinks(theEnv,src,FALSE);
src->classCount = dst.classCount;
src->classArray = dst.classArray;
}
/**************************************************************
NAME : NewClass
DESCRIPTION : Allocates and initalizes a new class structure
INPUTS : The symbolic name of the new class
RETURNS : The address of the new class
SIDE EFFECTS : None
NOTES : None
**************************************************************/
globle DEFCLASS *NewClass(
void *theEnv,
SYMBOL_HN *className)
{
register DEFCLASS *cls;
cls = get_struct(theEnv,defclass);
InitializeConstructHeader(theEnv,"defclass",(struct constructHeader *) cls,className);
cls->id = 0;
cls->installed = 0;
cls->busy = 0;
cls->system = 0;
cls->abstract = 0;
cls->reactive = 1;
#if DEBUGGING_FUNCTIONS
cls->traceInstances = DefclassData(theEnv)->WatchInstances;
cls->traceSlots = DefclassData(theEnv)->WatchSlots;
#endif
cls->hashTableIndex = 0;
cls->directSuperclasses.classCount = 0;
cls->directSuperclasses.classArray = NULL;
cls->directSubclasses.classCount = 0;
cls->directSubclasses.classArray = NULL;
cls->allSuperclasses.classCount = 0;
cls->allSuperclasses.classArray = NULL;
cls->slots = NULL;
cls->instanceTemplate = NULL;
cls->slotNameMap = NULL;
cls->instanceSlotCount = 0;
cls->localInstanceSlotCount = 0;
cls->slotCount = 0;
cls->maxSlotNameID = 0;
cls->handlers = NULL;
cls->handlerOrderMap = NULL;
cls->handlerCount = 0;
cls->instanceList = NULL;
cls->instanceListBottom = NULL;
cls->nxtHash = NULL;
cls->scopeMap = NULL;
ClearBitString(cls->traversalRecord,TRAVERSAL_BYTES);
return(cls);
}
/***************************************************
NAME : DeletePackedClassLinks
DESCRIPTION : Dealloacates a contiguous array
holding class links
INPUTS : 1) The class link segment
2) A flag indicating whether to
delete the top pack structure
RETURNS : Nothing useful
SIDE EFFECTS : Class links deallocated
NOTES : None
***************************************************/
globle void DeletePackedClassLinks(
void *theEnv,
PACKED_CLASS_LINKS *plp,
int deleteTop)
{
if (plp->classCount > 0)
{
rm(theEnv,(void *) plp->classArray,(sizeof(DEFCLASS *) * plp->classCount));
plp->classCount = 0;
plp->classArray = NULL;
}
if (deleteTop)
rtn_struct(theEnv,packedClassLinks,plp);
}
/***************************************************
NAME : AssignClassID
DESCRIPTION : Assigns a unique id to a class
and puts its address in the
id map
INPUTS : The class
RETURNS : Nothing useful
SIDE EFFECTS : Class id assigned and map set
NOTES : None
***************************************************/
globle void AssignClassID(
void *theEnv,
DEFCLASS *cls)
{
register unsigned i;
if ((DefclassData(theEnv)->MaxClassID % CLASS_ID_MAP_CHUNK) == 0)
{
DefclassData(theEnv)->ClassIDMap = (DEFCLASS **) genrealloc(theEnv,(void *) DefclassData(theEnv)->ClassIDMap,
(unsigned) (DefclassData(theEnv)->MaxClassID * sizeof(DEFCLASS *)),
(unsigned) ((DefclassData(theEnv)->MaxClassID + CLASS_ID_MAP_CHUNK) * sizeof(DEFCLASS *)));
DefclassData(theEnv)->AvailClassID += (unsigned short) CLASS_ID_MAP_CHUNK;
for (i = DefclassData(theEnv)->MaxClassID ; i < (unsigned) (DefclassData(theEnv)->MaxClassID + CLASS_ID_MAP_CHUNK) ; i++)
DefclassData(theEnv)->ClassIDMap[i] = NULL;
}
DefclassData(theEnv)->ClassIDMap[DefclassData(theEnv)->MaxClassID] = cls;
cls->id = DefclassData(theEnv)->MaxClassID++;
}
/*********************************************************
NAME : AddSlotName
DESCRIPTION : Adds a new slot entry (or increments
the use count of an existing node).
INPUTS : 1) The slot name
2) The new canonical id for the slot name
3) A flag indicating whether the
given id must be used or not
RETURNS : The id of the (old) node
SIDE EFFECTS : Slot name entry added or use count
incremented
NOTES : None
*********************************************************/
globle SLOT_NAME *AddSlotName(
void *theEnv,
SYMBOL_HN *slotName,
unsigned newid,
int usenewid)
{
SLOT_NAME *snp;
unsigned hashTableIndex;
char *buf;
unsigned bufsz;
hashTableIndex = HashSlotName(slotName);
snp = DefclassData(theEnv)->SlotNameTable[hashTableIndex];
while ((snp != NULL) ? (snp->name != slotName) : FALSE)
snp = snp->nxt;
if (snp != NULL)
{
if (usenewid && (newid != snp->id))
{
SystemError(theEnv,"CLASSFUN",1);
EnvExitRouter(theEnv,EXIT_FAILURE);
}
snp->use++;
}
else
{
snp = get_struct(theEnv,slotName);
snp->name = slotName;
snp->hashTableIndex = hashTableIndex;
snp->use = 1;
snp->id = usenewid ? newid : NewSlotNameID(theEnv);
snp->nxt = DefclassData(theEnv)->SlotNameTable[hashTableIndex];
DefclassData(theEnv)->SlotNameTable[hashTableIndex] = snp;
IncrementSymbolCount(slotName);
bufsz = (sizeof(char) *
(PUT_PREFIX_LENGTH + strlen(ValueToString(slotName)) + 1));
buf = (char *) gm2(theEnv,bufsz);
strcpy(buf,PUT_PREFIX);
strcat(buf,ValueToString(slotName));
snp->putHandlerName = (SYMBOL_HN *) EnvAddSymbol(theEnv,buf);
IncrementSymbolCount(snp->putHandlerName);
rm(theEnv,(void *) buf,bufsz);
snp->bsaveIndex = 0L;
}
return(snp);
}
/***************************************************
NAME : DeleteSlotName
DESCRIPTION : Removes a slot name entry from
the table of all slot names if
no longer in use
INPUTS : The slot name hash node
RETURNS : Nothing useful
SIDE EFFECTS : Slot name entry deleted or use
count decremented
NOTES : None
***************************************************/
globle void DeleteSlotName(
void *theEnv,
SLOT_NAME *slotName)
{
SLOT_NAME *snp,*prv;
if (slotName == NULL)
return;
prv = NULL;
snp = DefclassData(theEnv)->SlotNameTable[slotName->hashTableIndex];
while (snp != slotName)
{
prv = snp;
snp = snp->nxt;
}
snp->use--;
if (snp->use != 0)
return;
if (prv == NULL)
DefclassData(theEnv)->SlotNameTable[snp->hashTableIndex] = snp->nxt;
else
prv->nxt = snp->nxt;
DecrementSymbolCount(theEnv,snp->name);
DecrementSymbolCount(theEnv,snp->putHandlerName);
rtn_struct(theEnv,slotName,snp);
}
/*******************************************************************
NAME : RemoveDefclass
DESCRIPTION : Deallocates a class structure and
all its fields - returns all symbols
in use by the class back to the symbol
manager for ephemeral removal
INPUTS : The address of the class
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : Assumes class has no subclasses
IMPORTANT WARNING!! : Assumes class
busy count and all instances' busy
counts are 0 and all handlers' busy counts are 0!
*******************************************************************/
LOCALE void RemoveDefclass(
void *theEnv,
void *vcls)
{
DEFCLASS *cls = (DEFCLASS *) vcls;
HANDLER *hnd;
register unsigned i;
/* ====================================================
Remove all of this class's superclasses' links to it
==================================================== */
for (i = 0 ; i < cls->directSuperclasses.classCount ; i++)
DeleteSubclassLink(theEnv,cls->directSuperclasses.classArray[i],cls);
RemoveClassFromTable(theEnv,cls);
InstallClass(theEnv,cls,FALSE);
DeletePackedClassLinks(theEnv,&cls->directSuperclasses,FALSE);
DeletePackedClassLinks(theEnv,&cls->allSuperclasses,FALSE);
DeletePackedClassLinks(theEnv,&cls->directSubclasses,FALSE);
for (i = 0 ; i < cls->slotCount ; i++)
{
if (cls->slots[i].defaultValue != NULL)
{
if (cls->slots[i].dynamicDefault)
ReturnPackedExpression(theEnv,(EXPRESSION *) cls->slots[i].defaultValue);
else
rtn_struct(theEnv,dataObject,cls->slots[i].defaultValue);
}
DeleteSlotName(theEnv,cls->slots[i].slotName);
RemoveConstraint(theEnv,cls->slots[i].constraint);
}
if (cls->instanceSlotCount != 0)
{
rm(theEnv,(void *) cls->instanceTemplate,
(sizeof(SLOT_DESC *) * cls->instanceSlotCount));
rm(theEnv,(void *) cls->slotNameMap,
(sizeof(unsigned) * (cls->maxSlotNameID + 1)));
}
if (cls->slotCount != 0)
rm(theEnv,(void *) cls->slots,(sizeof(SLOT_DESC) * cls->slotCount));
for (i = 0 ; i < cls->handlerCount ; i++)
{
hnd = &cls->handlers[i];
if (hnd->actions != NULL)
ReturnPackedExpression(theEnv,hnd->actions);
if (hnd->ppForm != NULL)
rm(theEnv,(void *) hnd->ppForm,(sizeof(char) * (strlen(hnd->ppForm)+1)));
if (hnd->usrData != NULL)
{ ClearUserDataList(theEnv,hnd->usrData); }
}
if (cls->handlerCount != 0)
{
rm(theEnv,(void *) cls->handlers,(sizeof(HANDLER) * cls->handlerCount));
rm(theEnv,(void *) cls->handlerOrderMap,(sizeof(unsigned) * cls->handlerCount));
}
SetDefclassPPForm((void *) cls,NULL);
DeassignClassID(theEnv,(unsigned) cls->id);
rtn_struct(theEnv,defclass,cls);
}
#endif
/*******************************************************************
NAME : DestroyDefclass
DESCRIPTION : Deallocates a class structure and
all its fields.
INPUTS : The address of the class
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES :
*******************************************************************/
LOCALE void DestroyDefclass(
void *theEnv,
void *vcls)
{
DEFCLASS *cls = (DEFCLASS *) vcls;
register unsigned i;
#if ! RUN_TIME
HANDLER *hnd;
DeletePackedClassLinks(theEnv,&cls->directSuperclasses,FALSE);
DeletePackedClassLinks(theEnv,&cls->allSuperclasses,FALSE);
DeletePackedClassLinks(theEnv,&cls->directSubclasses,FALSE);
#endif
for (i = 0 ; i < cls->slotCount ; i++)
{
if (cls->slots[i].defaultValue != NULL)
{
#if ! RUN_TIME
if (cls->slots[i].dynamicDefault)
ReturnPackedExpression(theEnv,(EXPRESSION *) cls->slots[i].defaultValue);
else
rtn_struct(theEnv,dataObject,cls->slots[i].defaultValue);
#else
if (cls->slots[i].dynamicDefault == 0)
rtn_struct(theEnv,dataObject,cls->slots[i].defaultValue);
#endif
}
}
#if ! RUN_TIME
if (cls->instanceSlotCount != 0)
{
rm(theEnv,(void *) cls->instanceTemplate,
(sizeof(SLOT_DESC *) * cls->instanceSlotCount));
rm(theEnv,(void *) cls->slotNameMap,
(sizeof(unsigned) * (cls->maxSlotNameID + 1)));
}
if (cls->slotCount != 0)
rm(theEnv,(void *) cls->slots,(sizeof(SLOT_DESC) * cls->slotCount));
for (i = 0 ; i < cls->handlerCount ; i++)
{
hnd = &cls->handlers[i];
if (hnd->actions != NULL)
ReturnPackedExpression(theEnv,hnd->actions);
if (hnd->ppForm != NULL)
rm(theEnv,(void *) hnd->ppForm,(sizeof(char) * (strlen(hnd->ppForm)+1)));
if (hnd->usrData != NULL)
{ ClearUserDataList(theEnv,hnd->usrData); }
}
if (cls->handlerCount != 0)
{
rm(theEnv,(void *) cls->handlers,(sizeof(HANDLER) * cls->handlerCount));
rm(theEnv,(void *) cls->handlerOrderMap,(sizeof(unsigned) * cls->handlerCount));
}
DestroyConstructHeader(theEnv,&cls->header);
rtn_struct(theEnv,defclass,cls);
#else
#if MAC_MCW || IBM_MCW || MAC_XCD
#pragma unused(hnd)
#endif
#endif
}
#if ! RUN_TIME
/***************************************************
NAME : InstallClass
DESCRIPTION : In(De)crements all symbol counts for
for symbols in use by class
Disallows (allows) symbols to become
ephemeral.
INPUTS : 1) The class address
2) 1 - install, 0 - deinstall
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : None
***************************************************/
globle void InstallClass(
void *theEnv,
DEFCLASS *cls,
int set)
{
SLOT_DESC *slot;
HANDLER *hnd;
register unsigned i;
if ((set && cls->installed) ||
((set == FALSE) && (cls->installed == 0)))
return;
/* ==================================================================
Handler installation is handled when message-handlers are defined:
see ParseDefmessageHandler() in MSGCOM.C
Slot installation is handled by ParseSlot() in CLASSPSR.C
Scope map installation is handled by CreateClassScopeMap()
================================================================== */
if (set == FALSE)
{
cls->installed = 0;
DecrementSymbolCount(theEnv,cls->header.name);
#if DEFMODULE_CONSTRUCT
DecrementBitMapCount(theEnv,cls->scopeMap);
#endif
ClearUserDataList(theEnv,cls->header.usrData);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -