📄 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)
{
register unsigned 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)
{
unsigned count;
HANDLER *hnd,*nhnd;
unsigned *arr,*narr;
register unsigned 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;
unsigned 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 + -