📄 msgfun.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 05/17/06 */
/* */
/* OBJECT MESSAGE FUNCTIONS */
/*******************************************************/
/*************************************************************/
/* Purpose: */
/* */
/* Principal Programmer(s): */
/* Brian L. Donnell */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* 6.23: Changed name of variable log to logName */
/* because of Unix compiler warnings of shadowed */
/* definitions. */
/* */
/* 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
#include "classcom.h"
#include "classfun.h"
#include "memalloc.h"
#include "envrnmnt.h"
#include "extnfunc.h"
#include "insfun.h"
#include "msgcom.h"
#include "prccode.h"
#include "router.h"
#define _MSGFUN_SOURCE_
#include "msgfun.h"
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTION HEADERS
=========================================
***************************************** */
#if DEBUGGING_FUNCTIONS
static HANDLER_LINK *DisplayPrimaryCore(void *,char *,HANDLER_LINK *,int);
static void PrintPreviewHandler(void *,char *,HANDLER_LINK *,int,char *);
#endif
/* =========================================
*****************************************
EXTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/********************************************************
NAME : UnboundHandlerErr
DESCRIPTION : Print out a synopis of the currently
executing handler for unbound variable
errors
INPUTS : None
RETURNS : Nothing useful
SIDE EFFECTS : Error synopsis printed to WERROR
NOTES : None
********************************************************/
globle void UnboundHandlerErr(
void *theEnv)
{
EnvPrintRouter(theEnv,WERROR,"message-handler ");
PrintHandler(theEnv,WERROR,MessageHandlerData(theEnv)->CurrentCore->hnd,TRUE);
}
/*****************************************************************
NAME : PrintNoHandlerError
DESCRIPTION : Print "No primaries found" error message for send
INPUTS : The name of the message
RETURNS : Nothing useful
SIDE EFFECTS : None
NOTES : None
*****************************************************************/
globle void PrintNoHandlerError(
void *theEnv,
char *msg)
{
PrintErrorID(theEnv,"MSGFUN",1,FALSE);
EnvPrintRouter(theEnv,WERROR,"No applicable primary message-handlers found for ");
EnvPrintRouter(theEnv,WERROR,msg);
EnvPrintRouter(theEnv,WERROR,".\n");
}
/***************************************************************
NAME : CheckHandlerArgCount
DESCRIPTION : Verifies that the current argument
list satisfies the current
handler's parameter count restriction
INPUTS : None
RETURNS : TRUE if all OK, FALSE otherwise
SIDE EFFECTS : EvaluationError set on errors
NOTES : Uses ProcParamArraySize and CurrentCore globals
***************************************************************/
globle int CheckHandlerArgCount(
void *theEnv)
{
HANDLER *hnd;
hnd = MessageHandlerData(theEnv)->CurrentCore->hnd;
if ((hnd->maxParams == -1) ? (ProceduralPrimitiveData(theEnv)->ProcParamArraySize < hnd->minParams) :
(ProceduralPrimitiveData(theEnv)->ProcParamArraySize != hnd->minParams))
{
SetEvaluationError(theEnv,TRUE);
PrintErrorID(theEnv,"MSGFUN",2,FALSE);
EnvPrintRouter(theEnv,WERROR,"Message-handler ");
EnvPrintRouter(theEnv,WERROR,ValueToString(hnd->name));
EnvPrintRouter(theEnv,WERROR," ");
EnvPrintRouter(theEnv,WERROR,MessageHandlerData(theEnv)->hndquals[hnd->type]);
EnvPrintRouter(theEnv,WERROR," in class ");
EnvPrintRouter(theEnv,WERROR,EnvGetDefclassName(theEnv,(void *) hnd->cls));
EnvPrintRouter(theEnv,WERROR," expected ");
EnvPrintRouter(theEnv,WERROR,(char *) ((hnd->maxParams == -1) ? "at least " : "exactly "));
PrintLongInteger(theEnv,WERROR,(long) (hnd->minParams-1));
EnvPrintRouter(theEnv,WERROR," argument(s).\n");
return(FALSE);
}
return(TRUE);
}
/***************************************************
NAME : SlotAccessViolationError
DESCRIPTION : Prints out an error message when
attempt is made to set a read-only
or initialize-only slot improperly
INPUTS : 1) The slot name
2) A flag indicating if the source
is a class or an instance
3) A pointer to the source
instance/class
RETURNS : Nothing useful
SIDE EFFECTS : Error message printed
NOTES : None
***************************************************/
globle void SlotAccessViolationError(
void *theEnv,
char *slotName,
intBool instanceFlag,
void *theInstanceOrClass)
{
PrintErrorID(theEnv,"MSGFUN",3,FALSE);
EnvPrintRouter(theEnv,WERROR,slotName);
EnvPrintRouter(theEnv,WERROR," slot in ");
if (instanceFlag)
PrintInstanceNameAndClass(theEnv,WERROR,(INSTANCE_TYPE *) theInstanceOrClass,FALSE);
else
{
EnvPrintRouter(theEnv,WERROR,"class ");
PrintClassName(theEnv,WERROR,(DEFCLASS *) theInstanceOrClass,FALSE);
}
EnvPrintRouter(theEnv,WERROR,": write access denied.\n");
}
/***************************************************
NAME : SlotVisibilityViolationError
DESCRIPTION : Prints out an error message when
attempt is made to access a
private slot improperly
INPUTS : 1) The slot descriptor
2) A pointer to the source class
RETURNS : Nothing useful
SIDE EFFECTS : Error message printed
NOTES : None
***************************************************/
globle void SlotVisibilityViolationError(
void *theEnv,
SLOT_DESC *sd,
DEFCLASS *theDefclass)
{
PrintErrorID(theEnv,"MSGFUN",6,FALSE);
EnvPrintRouter(theEnv,WERROR,"Private slot ");
EnvPrintRouter(theEnv,WERROR,ValueToString(sd->slotName->name));
EnvPrintRouter(theEnv,WERROR," of class ");
PrintClassName(theEnv,WERROR,sd->cls,FALSE);
EnvPrintRouter(theEnv,WERROR," cannot be accessed directly\n by handlers attached to class ");
PrintClassName(theEnv,WERROR,theDefclass,TRUE);
}
#if ! RUN_TIME
/******************************************************************************
NAME : NewSystemHandler
DESCRIPTION : Adds a new system handler for a system class
The handler is assumed to be primary and of
the form:
(defmessage-handler <class> <handler> () (<func>))
INPUTS : 1) Name-string of the system class
2) Name-string of the system handler
3) Name-string of the internal H/L function to implement
this handler
4) The number of extra arguments (past the instance itself)
that the handler willl accept
RETURNS : Nothing useful
SIDE EFFECTS : Creates the new handler and inserts it in the system class's
handler array
On errors, generate a system error and exits.
NOTES : Does not check to see if handler already exists
*******************************************************************************/
globle void NewSystemHandler(
void *theEnv,
char *cname,
char *mname,
char *fname,
int extraargs)
{
DEFCLASS *cls;
HANDLER *hnd;
cls = LookupDefclassInScope(theEnv,cname);
hnd = InsertHandlerHeader(theEnv,cls,(SYMBOL_HN *) EnvAddSymbol(theEnv,mname),MPRIMARY);
IncrementSymbolCount(hnd->name);
hnd->system = 1;
hnd->minParams = hnd->maxParams = extraargs + 1;
hnd->localVarCount = 0;
hnd->actions = get_struct(theEnv,expr);
hnd->actions->argList = NULL;
hnd->actions->type = FCALL;
hnd->actions->value = (void *) FindFunction(theEnv,fname);
hnd->actions->nextArg = NULL;
}
/***************************************************
NAME : InsertHandlerHeader
DESCRIPTION : Allocates a new handler header and
inserts it in the proper (sorted)
position in the class hnd array
INPUTS : 1) The class
2) The handler name
3) The handler type
RETURNS : The address of the new handler
header, NULL on errors
SIDE EFFECTS : Class handler array reallocated
and resorted
NOTES : Assumes handler does not exist
***************************************************/
globle HANDLER *InsertHandlerHeader(
void *theEnv,
DEFCLASS *cls,
SYMBOL_HN *mname,
int mtype)
{
HANDLER *nhnd,*hnd;
unsigned *narr,*arr;
unsigned i;
register int j,ni = -1;
hnd = cls->handlers;
arr = cls->handlerOrderMap;
nhnd = (HANDLER *) gm2(theEnv,(sizeof(HANDLER) * (cls->handlerCount+1)));
narr = (unsigned *) gm2(theEnv,(sizeof(unsigned) * (cls->handlerCount+1)));
GenCopyMemory(HANDLER,cls->handlerCount,nhnd,hnd);
for (i = 0 , j = 0 ; i < cls->handlerCount ; i++ , j++)
{
if (ni == -1)
{
if ((hnd[arr[i]].name->bucket > mname->bucket) ? TRUE :
(hnd[arr[i]].name == mname))
{
ni = (int) i;
j++;
}
}
narr[j] = arr[i];
}
if (ni == -1)
ni = (int) cls->handlerCount;
narr[ni] = cls->handlerCount;
nhnd[cls->handlerCount].system = 0;
nhnd[cls->handlerCount].type = mtype;
nhnd[cls->handlerCount].busy = 0;
nhnd[cls->handlerCount].mark = 0;
#if DEBUGGING_FUNCTIONS
nhnd[cls->handlerCount].trace = MessageHandlerData(theEnv)->WatchHandlers;
#endif
nhnd[cls->handlerCount].name = mname;
nhnd[cls->handlerCount].cls = cls;
nhnd[cls->handlerCount].minParams = 0;
nhnd[cls->handlerCount].maxParams = 0;
nhnd[cls->handlerCount].localVarCount = 0;
nhnd[cls->handlerCount].actions = NULL;
nhnd[cls->handlerCount].ppForm = NULL;
nhnd[cls->handlerCount].usrData = NULL;
if (cls->handlerCount != 0)
{
rm(theEnv,(void *) hnd,(sizeof(HANDLER) * cls->handlerCount));
rm(theEnv,(void *) arr,(sizeof(unsigned) * cls->handlerCount));
}
cls->handlers = nhnd;
cls->handlerOrderMap = narr;
cls->handlerCount++;
return(&nhnd[cls->handlerCount-1]);
}
#endif
#if (! BLOAD_ONLY) && (! RUN_TIME)
/*****************************************************
NAME : HandlersExecuting
DESCRIPTION : Determines if any message-handlers
for a class are currently executing
INPUTS : The class address
RETURNS : TRUE if any handlers are executing,
FALSE otherwise
SIDE EFFECTS : None
NOTES : None
*****************************************************/
globle int HandlersExecuting(
DEFCLASS *cls)
{
register unsigned i;
for (i = 0 ; i < cls->handlerCount ; i++)
if (cls->handlers[i].busy > 0)
return(TRUE);
return(FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -