📄 msgfun.c
字号:
CLIPS_FALSE otherwise SIDE EFFECTS : None NOTES : None *****************************************************/globle int HandlersExecuting(cls) DEFCLASS *cls; { register unsigned i; for (i = 0 ; i < cls->handlerCount ; i++) if (cls->handlers[i].busy > 0) return(CLIPS_TRUE); return(CLIPS_FALSE); } /********************************************************************* NAME : DeleteHandler DESCRIPTION : Deletes one or more message-handlers from a class definition INPUTS : 1) The class address 2) The message-handler name (if this is * and there is no handler called *, then the delete operations will be applied to all handlers matching the type 3) The message-handler type (if this is -1, then the delete operations will be applied to all handlers matching the name 4) A flag saying whether to print error messages when handlers are not found meeting specs RETURNS : 1 if successful, 0 otherwise SIDE EFFECTS : Handlers deleted NOTES : If any handlers for the class are currently executing, this routine will fail **********************************************************************/globle int DeleteHandler(cls,mname,mtype,indicate_missing) DEFCLASS *cls; SYMBOL_HN *mname; int mtype,indicate_missing; { register int i; HANDLER *hnd; int found,success = 1; if (cls->handlerCount == 0) { if (indicate_missing) { HandlerDeleteError(GetDefclassName((VOID *) cls)); return(0); } return(1); } if (HandlersExecuting(cls)) { HandlerDeleteError(GetDefclassName((VOID *) cls)); return(0); } if (mtype == -1) { found = CLIPS_FALSE; for (i = MAROUND ; i <= MAFTER ; i++) { hnd = FindHandlerByAddress(cls,mname,(unsigned) i); if (hnd != NULL) { found = CLIPS_TRUE; if (hnd->system == 0) hnd->mark = 1; else { PrintErrorID("MSGPSR",3,CLIPS_FALSE); PrintCLIPS(WERROR,"System message-handlers may not be modified.\n"); success = 0; } } } if ((found == CLIPS_FALSE) ? (strcmp(ValueToString(mname),"*") == 0) : CLIPS_FALSE) { for (i = 0 ; i < cls->handlerCount ; i++) if (cls->handlers[i].system == 0) cls->handlers[i].mark = 1; } } else { hnd = FindHandlerByAddress(cls,mname,(unsigned) mtype); if (hnd == NULL) { if (strcmp(ValueToString(mname),"*") == 0) { for (i = 0 ; i < cls->handlerCount ; i++) if ((cls->handlers[i].type == mtype) && (cls->handlers[i].system == 0)) cls->handlers[i].mark = 1; } else { if (indicate_missing) HandlerDeleteError(GetDefclassName((VOID *) cls)); success = 0; } } else if (hnd->system == 0) hnd->mark = 1; else { if (indicate_missing) { PrintErrorID("MSGPSR",3,CLIPS_FALSE); PrintCLIPS(WERROR,"System message-handlers may not be modified.\n"); } success = 0; } } DeallocateMarkedHandlers(cls); return(success); }/*************************************************** NAME : DeallocateMarkedHandlers DESCRIPTION : Removes any handlers from a class that have been previously marked for deletion. INPUTS : The class RETURNS : Nothing useful SIDE EFFECTS : Marked handlers are deleted NOTES : Assumes none of the handlers are currently executing or have a busy count != 0 for any reason ***************************************************/globle VOID DeallocateMarkedHandlers(cls) DEFCLASS *cls; { unsigned count; HANDLER *hnd,*nhnd; unsigned *arr,*narr; register int i,j; for (i = 0 , count = 0 ; i < cls->handlerCount ; i++) { hnd = &cls->handlers[i]; if (hnd->mark == 1) { count++; DecrementSymbolCount(hnd->name); ExpressionDeinstall(hnd->actions); ReturnPackedExpression(hnd->actions); if (hnd->ppForm != NULL) rm((VOID *) hnd->ppForm, (int) (sizeof(char) * (strlen(hnd->ppForm)+1))); } else /* ============================================ Use the busy field to count how many message-handlers are removed before this one ============================================ */ hnd->busy = count; } if (count == 0) return; if (count == cls->handlerCount) { rm((VOID *) cls->handlers,(int) (sizeof(HANDLER) * cls->handlerCount)); rm((VOID *) cls->handlerOrderMap,(int) (sizeof(unsigned) * cls->handlerCount)); cls->handlers = NULL; cls->handlerOrderMap = NULL; cls->handlerCount = 0; } else { count = cls->handlerCount - count; hnd = cls->handlers; arr = cls->handlerOrderMap; nhnd = (HANDLER *) gm2((int) (sizeof(HANDLER) * count)); narr = (unsigned *) gm2((int) (sizeof(unsigned) * count)); for (i = 0 , j = 0 ; j < count ; i++) { if (hnd[arr[i]].mark == 0) { /* ============================================================== The offsets in the map need to be decremented by the number of preceding nodes which were deleted. Use the value of the busy field set in the first loop. ============================================================== */ narr[j] = arr[i] - hnd[arr[i]].busy; j++; } } for (i = 0 , j = 0 ; j < count ; i++) { if (hnd[i].mark == 0) { hnd[i].busy = 0; CopyMemory(HANDLER,1,&nhnd[j],&hnd[i]); j++; } } rm((VOID *) hnd,(int) (sizeof(HANDLER) * cls->handlerCount)); rm((VOID *) arr,(int) (sizeof(unsigned) * cls->handlerCount)); cls->handlers = nhnd; cls->handlerOrderMap = narr; cls->handlerCount = count; } } #endif/***************************************************** NAME : HandlerType DESCRIPTION : Determines type of message-handler INPUTS : 1) Calling function string 2) String representing type RETURNS : MAROUND (0) for "around" MBEFORE (1) for "before" MPRIMARY (2) for "primary" MAFTER (3) for "after" MERROR (4) on errors SIDE EFFECTS : None NOTES : None *****************************************************/globle int HandlerType(func,str) char *func,*str; { register int i; for (i = MAROUND ; i <= MAFTER ; i++) if (strcmp(str,hndquals[i]) == 0) {#if ! IMPERATIVE_MESSAGE_HANDLERS if (i == MAROUND) break;#endif#if ! AUXILIARY_MESSAGE_HANDLERS if ((i == MBEFORE) || (i == MAFTER)) break;#endif return(i); } PrintErrorID("MSGFUN",7,CLIPS_FALSE); PrintCLIPS("werror","Unrecognized message-handler type in "); PrintCLIPS("werror",func); PrintCLIPS("werror",".\n"); return(MERROR); } /***************************************************************** NAME : CheckCurrentMessage DESCRIPTION : Makes sure that a message is available and active for an internal message function INPUTS : 1) The name of the function checking the message 2) A flag indicating whether the object must be a class instance or not (it could be a CLIPS primitive type) RETURNS : CLIPS_TRUE if all OK, CLIPS_FALSE otherwise SIDE EFFECTS : EvaluationError set on errors NOTES : None *****************************************************************/globle int CheckCurrentMessage(func,ins_reqd) char *func; int ins_reqd; { register DATA_OBJECT *activeMsgArg; if (!CurrentCore || (CurrentCore->hnd->actions != CurrentProcActions)) { PrintErrorID("MSGFUN",4,CLIPS_FALSE); PrintCLIPS(WERROR,func); PrintCLIPS(WERROR," may only be called from within message-handlers.\n"); SetEvaluationError(CLIPS_TRUE); return(CLIPS_FALSE); } activeMsgArg = GetNthMessageArgument(0); if ((ins_reqd == CLIPS_TRUE) ? (activeMsgArg->type != INSTANCE_ADDRESS) : CLIPS_FALSE) { PrintErrorID("MSGFUN",5,CLIPS_FALSE); PrintCLIPS(WERROR,func); PrintCLIPS(WERROR," operates only on instances.\n"); SetEvaluationError(CLIPS_TRUE); return(CLIPS_FALSE); } if ((activeMsgArg->type == INSTANCE_ADDRESS) ? (((INSTANCE_TYPE *) activeMsgArg->value)->garbage == 1) : CLIPS_FALSE) { StaleInstanceAddress(func); SetEvaluationError(CLIPS_TRUE); return(CLIPS_FALSE); } return(CLIPS_TRUE); } /*************************************************** NAME : PrintHandler DESCRIPTION : Displays a handler synopsis INPUTS : 1) Logical name of output 2) The handler 5) Flag indicating whether to printout a terminating newline RETURNS : Nothing useful SIDE EFFECTS : None NOTES : None ***************************************************/globle VOID PrintHandler(log,theHandler,crtn) char *log; HANDLER *theHandler; int crtn; { PrintCLIPS(log,ValueToString(theHandler->name)); PrintCLIPS(log," "); PrintCLIPS(log,hndquals[theHandler->type]); PrintCLIPS(log," in class "); PrintClassName(log,theHandler->cls,crtn); } /*********************************************************** NAME : FindHandlerByAddress DESCRIPTION : Uses a binary search on a class's handler header array INPUTS : 1) The class address 2) The handler symbolic name 3) The handler type (MPRIMARY,etc.) RETURNS : The address of the found handler, NULL if not found SIDE EFFECTS : None NOTES : Assumes array is in ascending order 1st key: symbolic name of handler 2nd key: type of handler ***********************************************************/globle HANDLER *FindHandlerByAddress(cls,name,type) DEFCLASS *cls; SYMBOL_HN *name; unsigned type; { register int b,i; HANDLER *hnd; unsigned *arr; if ((b = FindHandlerNameGroup(cls,name)) == -1) return(NULL); arr = cls->handlerOrderMap; hnd = cls->handlers; for (i = b ; i < cls->handlerCount ; i++) { if (hnd[arr[i]].name != name) return(NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -