?? msgfun.c
字號:
}/********************************************************************* 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( void *theEnv, DEFCLASS *cls, SYMBOL_HN *mname, int mtype, int indicate_missing) { long i; HANDLER *hnd; int found,success = 1; if (cls->handlerCount == 0) { if (indicate_missing) { HandlerDeleteError(theEnv,EnvGetDefclassName(theEnv,(void *) cls)); return(0); } return(1); } if (HandlersExecuting(cls)) { HandlerDeleteError(theEnv,EnvGetDefclassName(theEnv,(void *) cls)); return(0); } if (mtype == -1) { found = FALSE; for (i = MAROUND ; i <= MAFTER ; i++) { hnd = FindHandlerByAddress(cls,mname,(unsigned) i); if (hnd != NULL) { found = TRUE; if (hnd->system == 0) hnd->mark = 1; else { PrintErrorID(theEnv,"MSGPSR",3,FALSE); EnvPrintRouter(theEnv,WERROR,"System message-handlers may not be modified.\n"); success = 0; } } } if ((found == FALSE) ? (strcmp(ValueToString(mname),"*") == 0) : 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 == (unsigned) mtype) && (cls->handlers[i].system == 0)) cls->handlers[i].mark = 1; } else { if (indicate_missing) HandlerDeleteError(theEnv,EnvGetDefclassName(theEnv,(void *) cls)); success = 0; } } else if (hnd->system == 0) hnd->mark = 1; else { if (indicate_missing) { PrintErrorID(theEnv,"MSGPSR",3,FALSE); EnvPrintRouter(theEnv,WERROR,"System message-handlers may not be modified.\n"); } success = 0; } } DeallocateMarkedHandlers(theEnv,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( void *theEnv, DEFCLASS *cls) { short count; HANDLER *hnd,*nhnd; unsigned *arr,*narr; long i,j; for (i = 0 , count = 0 ; i < cls->handlerCount ; i++) { hnd = &cls->handlers[i]; if (hnd->mark == 1) { count++; DecrementSymbolCount(theEnv,hnd->name); ExpressionDeinstall(theEnv,hnd->actions); ReturnPackedExpression(theEnv,hnd->actions); ClearUserDataList(theEnv,hnd->usrData); if (hnd->ppForm != NULL) rm(theEnv,(void *) hnd->ppForm, (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(theEnv,(void *) cls->handlers,(sizeof(HANDLER) * cls->handlerCount)); rm(theEnv,(void *) cls->handlerOrderMap,(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(theEnv,(sizeof(HANDLER) * count)); narr = (unsigned *) gm2(theEnv,(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; GenCopyMemory(HANDLER,1,&nhnd[j],&hnd[i]); j++; } } rm(theEnv,(void *) hnd,(sizeof(HANDLER) * cls->handlerCount)); rm(theEnv,(void *) arr,(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 unsigned HandlerType( void *theEnv, char *func, char *str) { register unsigned i; for (i = MAROUND ; i <= MAFTER ; i++) if (strcmp(str,MessageHandlerData(theEnv)->hndquals[i]) == 0) { return(i); } PrintErrorID(theEnv,"MSGFUN",7,FALSE); EnvPrintRouter(theEnv,"werror","Unrecognized message-handler type in "); EnvPrintRouter(theEnv,"werror",func); EnvPrintRouter(theEnv,"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 primitive type) RETURNS : TRUE if all OK, FALSE otherwise SIDE EFFECTS : EvaluationError set on errors NOTES : None *****************************************************************/globle int CheckCurrentMessage( void *theEnv, char *func, int ins_reqd) { register DATA_OBJECT *activeMsgArg; if (!MessageHandlerData(theEnv)->CurrentCore || (MessageHandlerData(theEnv)->CurrentCore->hnd->actions != ProceduralPrimitiveData(theEnv)->CurrentProcActions)) { PrintErrorID(theEnv,"MSGFUN",4,FALSE); EnvPrintRouter(theEnv,WERROR,func); EnvPrintRouter(theEnv,WERROR," may only be called from within message-handlers.\n"); SetEvaluationError(theEnv,TRUE); return(FALSE); } activeMsgArg = GetNthMessageArgument(theEnv,0); if ((ins_reqd == TRUE) ? (activeMsgArg->type != INSTANCE_ADDRESS) : FALSE) { PrintErrorID(theEnv,"MSGFUN",5,FALSE); EnvPrintRouter(theEnv,WERROR,func); EnvPrintRouter(theEnv,WERROR," operates only on instances.\n"); SetEvaluationError(theEnv,TRUE); return(FALSE); } if ((activeMsgArg->type == INSTANCE_ADDRESS) ? (((INSTANCE_TYPE *) activeMsgArg->value)->garbage == 1) : FALSE) { StaleInstanceAddress(theEnv,func,0); SetEvaluationError(theEnv,TRUE); return(FALSE); } return(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( void *theEnv, char *logName, HANDLER *theHandler, int crtn) { EnvPrintRouter(theEnv,logName,ValueToString(theHandler->name)); EnvPrintRouter(theEnv,logName," "); EnvPrintRouter(theEnv,logName,MessageHandlerData(theEnv)->hndquals[theHandler->type]); EnvPrintRouter(theEnv,logName," in class "); PrintClassName(theEnv,logName,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( DEFCLASS *cls, SYMBOL_HN *name, unsigned type) { register int b; long i; HANDLER *hnd; unsigned *arr; if ((b = FindHandlerNameGroup(cls,name)) == -1) return(NULL); arr = cls->handlerOrderMap; hnd = cls->handlers; for (i = (unsigned) b ; i < cls->handlerCount ; i++) { if (hnd[arr[i]].name != name) return(NULL); if (hnd[arr[i]].type == type) return(&hnd[arr[i]]); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -