📄 msgpass.c
字号:
/*******************************************************/ /* "C" Language Integrated Production System */ /* */ /* CLIPS Version 6.24 05/17/06 */ /* */ /* OBJECT MESSAGE DISPATCH CODE */ /*******************************************************//*************************************************************//* Purpose: *//* *//* Principal Programmer(s): *//* Brian L. Donnell *//* *//* Contributing Programmer(s): *//* *//* Revision History: *//* 6.23: Correction for FalseSymbol/TrueSymbol. DR0859 *//* *//* 6.24: Removed IMPERATIVE_MESSAGE_HANDLERS and *//* AUXILIARY_MESSAGE_HANDLERS compilation flags. *//* *//* Renamed BOOLEAN macro type to intBool. *//* *//*************************************************************//* ========================================= ***************************************** EXTERNAL DEFINITIONS ========================================= ***************************************** */#include "setup.h"#if OBJECT_SYSTEM#ifndef _STDIO_INCLUDED_#include <stdio.h>#define _STDIO_INCLUDED_#endif#include <stdlib.h>#include "argacces.h"#include "classcom.h"#include "classfun.h"#include "memalloc.h"#include "constrct.h"#include "envrnmnt.h"#include "exprnpsr.h"#include "insfun.h"#include "msgcom.h"#include "msgfun.h"#include "multifld.h"#include "prcdrfun.h"#include "prccode.h"#include "proflfun.h"#include "router.h"#include "strngfun.h"#include "utility.h"#include "commline.h"#define _MSGPASS_SOURCE_#include "msgpass.h"#include "inscom.h"/* ========================================= ***************************************** INTERNALLY VISIBLE FUNCTION HEADERS ========================================= ***************************************** */static void PerformMessage(void *,DATA_OBJECT *,EXPRESSION *,SYMBOL_HN *);static HANDLER_LINK *FindApplicableHandlers(void *,DEFCLASS *,SYMBOL_HN *);static void CallHandlers(void *,DATA_OBJECT *);static void EarlySlotBindError(void *,INSTANCE_TYPE *,DEFCLASS *,unsigned);/* ========================================= ***************************************** 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( void *theEnv, 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(theEnv,resultbuf,&args,msg); }/*************************************************** NAME : EnvSend 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 EnvSend( void *theEnv, DATA_OBJECT *idata, char *msg, char *args, DATA_OBJECT *result) { int error; EXPRESSION *iexp; SYMBOL_HN *msym; if ((EvaluationData(theEnv)->CurrentEvaluationDepth == 0) && (! CommandLineData(theEnv)->EvaluatingTopLevelCommand) && (EvaluationData(theEnv)->CurrentExpression == NULL)) { PeriodicCleanup(theEnv,TRUE,FALSE); } SetEvaluationError(theEnv,FALSE); result->type = SYMBOL; result->value = EnvFalseSymbol(theEnv); msym = FindSymbolHN(theEnv,msg); if (msym == NULL) { PrintNoHandlerError(theEnv,msg); SetEvaluationError(theEnv,TRUE); return; } iexp = GenConstant(theEnv,idata->type,idata->value); iexp->nextArg = ParseConstantArguments(theEnv,args,&error); if (error == TRUE) { ReturnExpression(theEnv,iexp); SetEvaluationError(theEnv,TRUE); return; } PerformMessage(theEnv,result,iexp,msym); ReturnExpression(theEnv,iexp); }/***************************************************** 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( void *theEnv, HANDLER_LINK *mhead) { HANDLER_LINK *tmp; while (mhead != NULL) { tmp = mhead; mhead = mhead->nxt; tmp->hnd->busy--; DecrementDefclassBusyCount(theEnv,(void *) tmp->hnd->cls); rtn_struct(theEnv,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 : H/L Syntax : (send <instance> <hnd> <args>*) ***********************************************************************/globle void SendCommand( void *theEnv, DATA_OBJECT *result) { EXPRESSION args; SYMBOL_HN *msg; DATA_OBJECT temp; result->type = SYMBOL; result->value = EnvFalseSymbol(theEnv); if (EnvArgTypeCheck(theEnv,"send",2,SYMBOL,&temp) == 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(theEnv,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( void *theEnv, int n) { return(&ProceduralPrimitiveData(theEnv)->ProcParamArray[n]); }/***************************************************** NAME : NextHandlerAvailable DESCRIPTION : Determines if there the currently executing handler can call a shadowed handler Used before calling call-next-handler INPUTS : None RETURNS : TRUE if shadow ready, FALSE otherwise SIDE EFFECTS : None NOTES : H/L Syntax: (next-handlerp) *****************************************************/globle int NextHandlerAvailable( void *theEnv) { if (MessageHandlerData(theEnv)->CurrentCore == NULL) return(FALSE); if (MessageHandlerData(theEnv)->CurrentCore->hnd->type == MAROUND) return((MessageHandlerData(theEnv)->NextInCore != NULL) ? TRUE : FALSE); if ((MessageHandlerData(theEnv)->CurrentCore->hnd->type == MPRIMARY) && (MessageHandlerData(theEnv)->NextInCore != NULL)) return((MessageHandlerData(theEnv)->NextInCore->hnd->type == MPRIMARY) ? TRUE : FALSE); return(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 : H/L Syntax: (call-next-handler) OR (override-next-handler <arg> ...) ********************************************************/globle void CallNextHandler( void *theEnv, DATA_OBJECT *result) { EXPRESSION args; int overridep; HANDLER_LINK *oldNext,*oldCurrent;#if PROFILING_FUNCTIONS struct profileFrameInfo profileFrame;#endif SetpType(result,SYMBOL); SetpValue(result,EnvFalseSymbol(theEnv)); EvaluationData(theEnv)->EvaluationError = FALSE; if (EvaluationData(theEnv)->HaltExecution) return; if (NextHandlerAvailable(theEnv) == FALSE) { PrintErrorID(theEnv,"MSGPASS",1,FALSE); EnvPrintRouter(theEnv,WERROR,"Shadowed message-handlers not applicable in current context.\n"); SetEvaluationError(theEnv,TRUE); return; } if (EvaluationData(theEnv)->CurrentExpression->value == (void *) FindFunction(theEnv,"override-next-handler")) { overridep = 1; args.type = ProceduralPrimitiveData(theEnv)->ProcParamArray[0].type; if (args.type != MULTIFIELD) args.value = (void *) ProceduralPrimitiveData(theEnv)->ProcParamArray[0].value; else args.value = (void *) &ProceduralPrimitiveData(theEnv)->ProcParamArray[0]; args.nextArg = GetFirstArgument(); args.argList = NULL; PushProcParameters(theEnv,&args,CountArguments(&args), ValueToString(MessageHandlerData(theEnv)->CurrentMessageName),"message", UnboundHandlerErr); if (EvaluationData(theEnv)->EvaluationError) { ProcedureFunctionData(theEnv)->ReturnFlag = FALSE; return; } } else overridep = 0; oldNext = MessageHandlerData(theEnv)->NextInCore; oldCurrent = MessageHandlerData(theEnv)->CurrentCore; if (MessageHandlerData(theEnv)->CurrentCore->hnd->type == MAROUND) { if (MessageHandlerData(theEnv)->NextInCore->hnd->type == MAROUND) { MessageHandlerData(theEnv)->CurrentCore = MessageHandlerData(theEnv)->NextInCore; MessageHandlerData(theEnv)->NextInCore = MessageHandlerData(theEnv)->NextInCore->nxt;#if DEBUGGING_FUNCTIONS if (MessageHandlerData(theEnv)->CurrentCore->hnd->trace)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -