📄 msgpass.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.05 04/09/97 */ /* */ /* OBJECT MESSAGE DISPATCH CODE */ /*******************************************************//*************************************************************//* Purpose: *//* *//* Principal Programmer(s): *//* Brian L. Donnell *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* *//*************************************************************/ /* ========================================= ***************************************** EXTERNAL DEFINITIONS ========================================= ***************************************** */#include "setup.h"#if OBJECT_SYSTEM#ifndef _CLIPS_STDIO_#include <stdio.h>#define _CLIPS_STDIO_#endif#include "argacces.h"#include "classcom.h"#include "classfun.h"#include "clipsmem.h"#include "constrct.h"#include "exprnpsr.h"#include "insfun.h"#include "msgfun.h"#include "multifld.h"#include "prcdrfun.h"#include "prccode.h"#include "router.h"#include "utility.h"#include "commline.h"#define _MSGPASS_SOURCE_#include "msgpass.h"/* ========================================= ***************************************** CONSTANTS ========================================= ***************************************** *//* ========================================= ***************************************** INTERNALLY VISIBLE FUNCTION HEADERS ========================================= ***************************************** */#if ANSI_COMPILERstatic VOID PerformMessage(DATA_OBJECT *,EXPRESSION *,SYMBOL_HN *);static HANDLER_LINK *FindApplicableHandlers(DEFCLASS *,SYMBOL_HN *);static VOID CallHandlers(DATA_OBJECT *);static VOID EarlySlotBindError(INSTANCE_TYPE *,DEFCLASS *,unsigned);#elsestatic VOID PerformMessage();static HANDLER_LINK *FindApplicableHandlers();static VOID CallHandlers();static VOID EarlySlotBindError();#endif /* ========================================= ***************************************** EXTERNALLY VISIBLE GLOBAL VARIABLES ========================================= ***************************************** */globle SYMBOL_HN *CurrentMessageName = NULL;globle HANDLER_LINK *CurrentCore = NULL;/* ========================================= ***************************************** INTERNALLY VISIBLE GLOBAL VARIABLES ========================================= ***************************************** */static HANDLER_LINK *TopOfCore = NULL, *NextInCore = NULL;/* ========================================= ***************************************** EXTERNALLY VISIBLE FUNCTIONS ========================================= ***************************************** */ /***************************************************** NAME : DirectMessage DESCRIPTION : Plugs in given instance and performs specified message INPUTS : 1) Message symbolic name 2) The instance address 3) Address of DATA_OBJECT buffer (NULL if don't care) 4) Message argument expressions RETURNS : Nothing useful SIDE EFFECTS : Side effects of message execution NOTES : None *****************************************************/globle VOID DirectMessage(msg,ins,resultbuf,remargs) SYMBOL_HN *msg; INSTANCE_TYPE *ins; DATA_OBJECT *resultbuf; EXPRESSION *remargs; { EXPRESSION args; DATA_OBJECT temp; if (resultbuf == NULL) resultbuf = &temp; args.nextArg = remargs; args.argList = NULL; args.type = INSTANCE_ADDRESS; args.value = (VOID *) ins; PerformMessage(resultbuf,&args,msg); } /*************************************************** NAME : Send DESCRIPTION : C Interface for sending messages to instances INPUTS : 1) The data object of the instance 2) The message name-string 3) The message arguments string (Constants only) 4) Caller's buffer for result RETURNS : Nothing useful SIDE EFFECTS : Executes message and stores result caller's buffer NOTES : None ***************************************************/globle VOID Send(idata,msg,args,result) DATA_OBJECT *idata,*result; char *msg,*args; { int error; EXPRESSION *iexp; SYMBOL_HN *msym; SetEvaluationError(CLIPS_FALSE); result->type = SYMBOL; result->value = CLIPSFalseSymbol; msym = FindSymbol(msg); if (msym == NULL) { PrintNoHandlerError(msg); SetEvaluationError(CLIPS_TRUE); return; } iexp = GenConstant(idata->type,idata->value); iexp->nextArg = ParseConstantArguments(args,&error); if (error == CLIPS_TRUE) { ReturnExpression(iexp); SetEvaluationError(CLIPS_TRUE); return; } PerformMessage(result,iexp,msym); ReturnExpression(iexp); if ((CurrentEvaluationDepth == 0) && (! EvaluatingTopLevelCommand) && (CurrentExpression == NULL)) { PeriodicCleanup(CLIPS_TRUE,CLIPS_FALSE); } }/***************************************************** NAME : DestroyHandlerLinks DESCRIPTION : Iteratively deallocates handler-links INPUTS : The handler-link list RETURNS : Nothing useful SIDE EFFECTS : Deallocation of links NOTES : None *****************************************************/globle VOID DestroyHandlerLinks(mhead) HANDLER_LINK *mhead; { HANDLER_LINK *tmp; while (mhead != NULL) { tmp = mhead; mhead = mhead->nxt; tmp->hnd->busy--; DecrementDefclassBusyCount((VOID *) tmp->hnd->cls); rtn_struct(messageHandlerLink,tmp); } } /*********************************************************************** NAME : SendCommand DESCRIPTION : Determines the applicable handler(s) and sets up the core calling frame. Then calls the core frame. INPUTS : Caller's space for storing the result of the handler(s) RETURNS : Nothing useful SIDE EFFECTS : Any side-effects caused by the execution of handlers in the core framework NOTES : CLIPS Syntax : (send <instance> <hnd> <args>*) ***********************************************************************/globle VOID SendCommand(result) DATA_OBJECT *result; { EXPRESSION args; SYMBOL_HN *msg; DATA_OBJECT temp; result->type = SYMBOL; result->value = CLIPSFalseSymbol; if (ArgTypeCheck("send",2,SYMBOL,&temp) == CLIPS_FALSE) return; msg = (SYMBOL_HN *) temp.value; /* ============================================= Get the instance or primitive for the message ============================================= */ args.type = GetFirstArgument()->type; args.value = GetFirstArgument()->value; args.argList = GetFirstArgument()->argList; args.nextArg = GetFirstArgument()->nextArg->nextArg; PerformMessage(result,&args,msg); }/*************************************************** NAME : GetNthMessageArgument DESCRIPTION : Returns the address of the nth (starting at 1) which is an argument of the current message dispatch INPUTS : None RETURNS : The message argument SIDE EFFECTS : None NOTES : The active instance is always stored as the first argument (0) in the call frame of the message ***************************************************/globle DATA_OBJECT *GetNthMessageArgument(n) int n; { return(&ProcParamArray[n]); } #if IMPERATIVE_MESSAGE_HANDLERS/***************************************************** NAME : NextHandlerAvailable DESCRIPTION : Determines if there the currently executing handler can call a shadowed handler Used before calling call-next-handler INPUTS : None RETURNS : CLIPS_TRUE if shadow ready, CLIPS_FALSE otherwise SIDE EFFECTS : None NOTES : CLIPS Syntax: (next-handlerp) *****************************************************/globle int NextHandlerAvailable() { if (CurrentCore == NULL) return(CLIPS_FALSE); if (CurrentCore->hnd->type == MAROUND) return((NextInCore != NULL) ? CLIPS_TRUE : CLIPS_FALSE); if ((CurrentCore->hnd->type == MPRIMARY) && (NextInCore != NULL)) return((NextInCore->hnd->type == MPRIMARY) ? CLIPS_TRUE : CLIPS_FALSE); return(CLIPS_FALSE); } /******************************************************** NAME : CallNextHandler DESCRIPTION : This function allows around-handlers to execute the rest of the core frame. It also allows primary handlers to execute shadowed primaries. The original handler arguments are left intact. INPUTS : The caller's result-value buffer RETURNS : Nothing useful SIDE EFFECTS : The core frame is called and any appropriate changes are made when used in an around handler See CallHandlers() But when call-next-handler is called from a primary, the same shadowed primary is called over and over again for repeated calls to call-next-handler. NOTES : CLIPS Syntax: (call-next-handler) OR (override-next-handler <arg> ...) ********************************************************/globle VOID CallNextHandler(result) DATA_OBJECT *result; { EXPRESSION args; int overridep; HANDLER_LINK *oldNext,*oldCurrent; SetpType(result,SYMBOL); SetpValue(result,CLIPSFalseSymbol); EvaluationError = CLIPS_FALSE; if (HaltExecution) return; if (NextHandlerAvailable() == CLIPS_FALSE) { PrintErrorID("MSGPASS",1,CLIPS_FALSE); PrintCLIPS(WERROR,"Shadowed message-handlers not applicable in current context.\n"); SetEvaluationError(CLIPS_TRUE); return; } if (CurrentExpression->value == (VOID *) FindFunction("override-next-handler")) { overridep = 1; args.type = (short) ProcParamArray[0].type; if (args.type != MULTIFIELD) args.value = (VOID *) ProcParamArray[0].value; else args.value = (VOID *) &ProcParamArray[0]; args.nextArg = GetFirstArgument(); args.argList = NULL; PushProcParameters(&args,CountArguments(&args), ValueToString(CurrentMessageName),"message", UnboundHandlerErr); if (EvaluationError) { ReturnFlag = CLIPS_FALSE; return; } } else overridep = 0; oldNext = NextInCore; oldCurrent = CurrentCore; if (CurrentCore->hnd->type == MAROUND) { if (NextInCore->hnd->type == MAROUND) { CurrentCore = NextInCore; NextInCore = NextInCore->nxt;#if DEBUGGING_FUNCTIONS if (CurrentCore->hnd->trace) WatchHandler(WTRACE,CurrentCore,BEGIN_TRACE);#endif if (CheckHandlerArgCount()) EvaluateProcActions(CurrentCore->hnd->cls->header.whichModule->theModule, CurrentCore->hnd->actions, CurrentCore->hnd->localVarCount, result,UnboundHandlerErr);#if DEBUGGING_FUNCTIONS if (CurrentCore->hnd->trace) WatchHandler(WTRACE,CurrentCore,END_TRACE);#endif } else CallHandlers(result); } else { CurrentCore = NextInCore; NextInCore = NextInCore->nxt;#if DEBUGGING_FUNCTIONS if (CurrentCore->hnd->trace) WatchHandler(WTRACE,CurrentCore,BEGIN_TRACE);#endif if (CheckHandlerArgCount()) EvaluateProcActions(CurrentCore->hnd->cls->header.whichModule->theModule, CurrentCore->hnd->actions, CurrentCore->hnd->localVarCount, result,UnboundHandlerErr);#if DEBUGGING_FUNCTIONS if (CurrentCore->hnd->trace) WatchHandler(WTRACE,CurrentCore,END_TRACE);#endif } NextInCore = oldNext; CurrentCore = oldCurrent; if (overridep) PopProcParameters(); ReturnFlag = CLIPS_FALSE; }#endif /* IMPERATIVE_MESSAGE_HANDLERS *//************************************************************************* NAME : FindApplicableOfName DESCRIPTION : Groups all handlers of all types of the specified class of the specified name into the applicable handler list INPUTS : 1) The class address 2-3) The tops and bottoms of the four handler type lists: around, before, primary and after 4) The message name symbol RETURNS : Nothing useful SIDE EFFECTS : Modifies the handler lists to include applicable handlers NOTES : None *************************************************************************/globle VOID FindApplicableOfName(cls,tops,bots,mname) DEFCLASS *cls; HANDLER_LINK *tops[4],*bots[4]; SYMBOL_HN *mname; { register int i,e; HANDLER *hnd; unsigned *arr; HANDLER_LINK *tmp; i = FindHandlerNameGroup(cls,mname); if (i == -1) return; e = cls->handlerCount-1; hnd = cls->handlers; arr = cls->handlerOrderMap; for ( ; i <= e ; i++) { if (hnd[arr[i]].name != mname) break;#if ! IMPERATIVE_MESSAGE_HANDLERS if ((hnd[arr[i]].type == MPRIMARY) && (tops[MPRIMARY] != NULL))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -