📄 classfun.c
字号:
} } #endif#if (! BLOAD_ONLY) && (! RUN_TIME)/*************************************************** NAME : IsClassBeingUsed DESCRIPTION : Checks the busy flag of a class and ALL classes that inherit from it to make sure that it is not in use before deletion INPUTS : The class RETURNS : CLIPS_TRUE if in use, CLIPS_FALSE otherwise SIDE EFFECTS : None NOTES : Recursively examines all subclasses ***************************************************/globle int IsClassBeingUsed(cls) DEFCLASS *cls; { register unsigned i; if (cls->busy > 0) return(CLIPS_TRUE); for (i = 0 ; i < cls->directSubclasses.classCount ; i++) if (IsClassBeingUsed(cls->directSubclasses.classArray[i])) return(CLIPS_TRUE); return(CLIPS_FALSE); } /*************************************************** NAME : RemoveAllUserClasses DESCRIPTION : Removes all classes INPUTS : None RETURNS : CLIPS_TRUE if succesful, CLIPS_FALSE otherwise SIDE EFFECTS : The class hash table is cleared NOTES : None ***************************************************/globle int RemoveAllUserClasses() { VOID *userClasses,*ctmp; int success = CLIPS_TRUE; #if BLOAD || BLOAD_AND_BSAVE if (Bloaded()) return(CLIPS_FALSE);#endif /* ==================================================== Don't delete built-in system classes at head of list ==================================================== */ userClasses = GetNextDefclass(NULL); while (userClasses != NULL) { if (((DEFCLASS *) userClasses)->system == 0) break; userClasses = GetNextDefclass(userClasses); } while (userClasses != NULL) { ctmp = userClasses; userClasses = GetNextDefclass(userClasses); if (IsDefclassDeletable(ctmp)) { RemoveConstructFromModule((struct constructHeader *) ctmp); RemoveDefclass(ctmp); } else { success = CLIPS_FALSE; CantDeleteItemErrorMessage("defclass",GetDefclassName(ctmp)); } } return(success); } /**************************************************** NAME : DeleteClassUAG DESCRIPTION : Deallocates a class and all its subclasses INPUTS : The address of the class RETURNS : 1 if successful, 0 otherwise SIDE EFFECTS : Removes the class from each of its superclasses' subclass lists NOTES : None ****************************************************/globle int DeleteClassUAG(cls) DEFCLASS *cls; { unsigned subCount; while (cls->directSubclasses.classCount != 0) { subCount = cls->directSubclasses.classCount; DeleteClassUAG(cls->directSubclasses.classArray[0]); if (cls->directSubclasses.classCount == subCount) return(CLIPS_FALSE); } if (IsDefclassDeletable((VOID *) cls)) { RemoveConstructFromModule((struct constructHeader *) cls); RemoveDefclass((VOID *) cls); return(CLIPS_TRUE); } return(CLIPS_FALSE); }/********************************************************* NAME : MarkBitMapSubclasses DESCRIPTION : Recursively marks the ids of a class and all its subclasses in a bitmap INPUTS : 1) The bitmap 2) The class 3) A code indicating whether to set or clear the bits of the map corresponding to the class ids RETURNS : Nothing useful SIDE EFFECTS : BitMap marked NOTES : IMPORTANT!!!! Assumes the bitmap is large enough to hold all ids encountered! *********************************************************/globle VOID MarkBitMapSubclasses(map,cls,set) char *map; DEFCLASS *cls; int set; { register unsigned i; if (set) SetBitMap(map,cls->id); else ClearBitMap(map,cls->id); for (i = 0 ; i < cls->directSubclasses.classCount ; i++) MarkBitMapSubclasses(map,cls->directSubclasses.classArray[i],set); } #endif/*************************************************** NAME : FindSlotNameID DESCRIPTION : Finds the id of a slot name INPUTS : The slot name RETURNS : The slot name id (-1 if not found) SIDE EFFECTS : None NOTES : A slot name always has the same id regardless of what class uses it. In this way, a slot can be referred to by index independent of class. Each class stores a map showing which slot name indices go to which slot. This provides for immediate lookup of slots given the index (object pattern matching uses this). ***************************************************/globle int FindSlotNameID(slotName) SYMBOL_HN *slotName; { SLOT_NAME *snp; snp = SlotNameTable[HashSlotName(slotName)]; while ((snp != NULL) ? (snp->name != slotName) : CLIPS_FALSE) snp = snp->nxt; return((snp != NULL) ? (int) snp->id : -1); }/*************************************************** NAME : FindIDSlotName DESCRIPTION : Finds the slot anme for an id INPUTS : The id RETURNS : The slot name (NULL if not found) SIDE EFFECTS : None NOTES : None ***************************************************/globle SYMBOL_HN *FindIDSlotName(id) unsigned id; { SLOT_NAME *snp; snp = FindIDSlotNameHash(id); return((snp != NULL) ? snp->name : NULL); } /*************************************************** NAME : FindIDSlotNameHash DESCRIPTION : Finds the slot anme for an id INPUTS : The id RETURNS : The slot name (NULL if not found) SIDE EFFECTS : None NOTES : None ***************************************************/globle SLOT_NAME *FindIDSlotNameHash(id) unsigned id; { register int i; SLOT_NAME *snp; for (i = 0 ; i < SLOT_NAME_TABLE_HASH_SIZE ; i++) { snp = SlotNameTable[i]; while (snp != NULL) { if (snp->id == id) return(snp); snp = snp->nxt; } } return(NULL); } /*************************************************** NAME : GetTraversalID DESCRIPTION : Returns a unique integer ID for a traversal into the class hierarchy INPUTS : None RETURNS : The id, or -1 if none available SIDE EFFECTS : EvaluationError set when no ids available NOTES : Used for recursive traversals of class hierarchy to assure that a class is only visited once ***************************************************/globle int GetTraversalID() { register unsigned i; register DEFCLASS *cls; if (CTID >= MAX_TRAVERSALS) { PrintErrorID("CLASSFUN",2,CLIPS_FALSE); PrintCLIPS(WERROR,"Maximum number of simultaneous class hierarchy\n traversals exceeded "); PrintLongInteger(WERROR,(long) MAX_TRAVERSALS); PrintCLIPS(WERROR,".\n"); SetEvaluationError(CLIPS_TRUE); return(-1); } for (i = 0 ; i < CLASS_TABLE_HASH_SIZE ; i++) for (cls = ClassTable[i] ; cls != NULL ; cls = cls->nxtHash) ClearTraversalID(cls->traversalRecord,CTID); return(CTID++); } /*************************************************** NAME : ReleaseTraversalID DESCRIPTION : Releases an ID for future use Also clears id from all classes INPUTS : None RETURNS : Nothing useful SIDE EFFECTS : Old ID released for later reuse NOTES : Releases ID returned by most recent call to GetTraversalID() ***************************************************/globle VOID ReleaseTraversalID() { CTID--; } /******************************************************* NAME : HashClass DESCRIPTION : Generates a hash index for a given class name INPUTS : The address of the class name SYMBOL_HN RETURNS : The hash index value SIDE EFFECTS : None NOTES : Counts on the fact that the symbol has already been hashed into the CLIPS symbol table - uses that hash value multiplied by a prime for a new hash *******************************************************/globle unsigned HashClass(cname) SYMBOL_HN *cname; { unsigned long tally; tally = ((unsigned long) cname->bucket) * BIG_PRIME; return((unsigned) (tally % CLASS_TABLE_HASH_SIZE)); }/* ========================================= ***************************************** INTERNALLY VISIBLE FUNCTIONS ========================================= ***************************************** *//******************************************************* NAME : HashSlotName DESCRIPTION : Generates a hash index for a given slot name INPUTS : The address of the slot name SYMBOL_HN RETURNS : The hash index value SIDE EFFECTS : None NOTES : Counts on the fact that the symbol has already been hashed into the CLIPS symbol table - uses that hash value multiplied by a prime for a new hash *******************************************************/static unsigned HashSlotName(sname) SYMBOL_HN *sname; { unsigned long tally; tally = ((unsigned long) sname->bucket) * BIG_PRIME; return((unsigned) (tally % SLOT_NAME_TABLE_HASH_SIZE)); }#if (! RUN_TIME)/*********************************************** NAME : NewSlotNameID DESCRIPTION : Returns an unused slot name id as close to 1 as possible INPUTS : None RETURNS : The new unused id SIDE EFFECTS : None NOTES : None ***********************************************/static unsigned NewSlotNameID() { unsigned newid = 0; register unsigned i; SLOT_NAME *snp; while (CLIPS_TRUE) { for (i = 0 ; i < SLOT_NAME_TABLE_HASH_SIZE ; i++) { snp = SlotNameTable[i]; while ((snp != NULL) ? (snp->id != newid) : CLIPS_FALSE) snp = snp->nxt; if (snp != NULL) break; } if (i < SLOT_NAME_TABLE_HASH_SIZE) newid++; else break; } return(newid); } /*************************************************** NAME : DeassignClassID DESCRIPTION : Reduces id map and MaxClassID if no ids in use above the one being released. INPUTS : The id RETURNS : Nothing useful SIDE EFFECTS : ID map and MaxClassID possibly reduced NOTES : None ***************************************************/static VOID DeassignClassID(id) unsigned id; { register unsigned i; int reallocReqd; unsigned oldChunk,newChunk; ClassIDMap[id] = NULL; for (i = id + 1 ; i < MaxClassID ; i++) if (ClassIDMap[i] != NULL) return; reallocReqd = CLIPS_FALSE; while (ClassIDMap[id] == NULL) { MaxClassID = (unsigned short) id; if ((MaxClassID % CLASS_ID_MAP_CHUNK) == 0) { newChunk = MaxClassID; if (reallocReqd == CLIPS_FALSE) { oldChunk = MaxClassID + CLASS_ID_MAP_CHUNK; reallocReqd = CLIPS_TRUE; } } if (id == 0) break; id--; } if (reallocReqd) ClassIDMap = (DEFCLASS **) genrealloc((VOID *) ClassIDMap, (unsigned) (oldChunk * sizeof(DEFCLASS *)), (unsigned) (newChunk * sizeof(DEFCLASS *))); } #endif#endif/*************************************************** NAME : DESCRIPTION : INPUTS : RETURNS : SIDE EFFECTS : NOTES : ***************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -