📄 msgpsr.c
字号:
oldString = RouterData(theEnv)->FastCharGetString;
oldIndex = RouterData(theEnv)->FastCharGetIndex;
RouterData(theEnv)->FastCharGetRouter = handlerRouter;
RouterData(theEnv)->FastCharGetIndex = 0;
RouterData(theEnv)->FastCharGetString = buf;
ParseDefmessageHandler(theEnv,handlerRouter);
DestroyPPBuffer(theEnv);
/*
if (OpenStringSource(theEnv,handlerRouter,buf,0))
{
ParseDefmessageHandler(handlerRouter);
DestroyPPBuffer();
CloseStringSource(theEnv,handlerRouter);
}
*/
RouterData(theEnv)->FastCharGetRouter = oldRouter;
RouterData(theEnv)->FastCharGetIndex = oldIndex;
RouterData(theEnv)->FastCharGetString = oldString;
}
if (sd->createWriteAccessor)
{
sprintf(buf,"%s put-%s ($?value) (bind ?self:%s ?value))",
className,slotName,slotName);
oldRouter = RouterData(theEnv)->FastCharGetRouter;
oldString = RouterData(theEnv)->FastCharGetString;
oldIndex = RouterData(theEnv)->FastCharGetIndex;
RouterData(theEnv)->FastCharGetRouter = handlerRouter;
RouterData(theEnv)->FastCharGetIndex = 0;
RouterData(theEnv)->FastCharGetString = buf;
ParseDefmessageHandler(theEnv,handlerRouter);
DestroyPPBuffer(theEnv);
/*
if (OpenStringSource(theEnv,handlerRouter,buf,0))
{
ParseDefmessageHandler(handlerRouter);
DestroyPPBuffer();
CloseStringSource(theEnv,handlerRouter);
}
*/
RouterData(theEnv)->FastCharGetRouter = oldRouter;
RouterData(theEnv)->FastCharGetIndex = oldIndex;
RouterData(theEnv)->FastCharGetString = oldString;
}
SetPrintWhileLoading(theEnv,oldPWL);
EnvSetConserveMemory(theEnv,oldCM);
rm(theEnv,(void *) buf,bufsz);
}
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/*****************************************************************
NAME : IsParameterSlotReference
DESCRIPTION : Determines if a message-handler parameter is of
the form ?self:<name>, which is not allowed since
this is slot reference syntax
INPUTS : The paramter name
RETURNS : TRUE if the parameter is a slot reference,
FALSE otherwise
SIDE EFFECTS : None
NOTES : None
*****************************************************************/
static intBool IsParameterSlotReference(
void *theEnv,
char *pname)
{
if ((strncmp(pname,SELF_STRING,SELF_LEN) == 0) ?
(pname[SELF_LEN] == SELF_SLOT_REF) : FALSE)
{
PrintErrorID(theEnv,"MSGPSR",4,FALSE);
EnvPrintRouter(theEnv,WERROR,"Illegal slot reference in parameter list.\n");
return(TRUE);
}
return(FALSE);
}
/****************************************************************************
NAME : SlotReferenceVar
DESCRIPTION : Replaces direct slot references in handler body
with special function calls to reference active instance
at run-time
The slot in in the class bound at parse-time is always
referenced (early binding).
Slot references of the form ?self:<name> directly reference
ProcParamArray[0] (the message object - ?self) to
find the specified slot at run-time
INPUTS : 1) Variable expression
2) The class of the handler being parsed
RETURNS : 0 if not recognized, 1 if so, -1 on errors
SIDE EFFECTS : Handler body SF_VARIABLE and MF_VARIABLE replaced with
direct slot access function
NOTES : Objects are allowed to directly access their own slots
without sending a message to themselves. Since the object
is "within the boundary of its internals", this does not
violate the encapsulation principle of OOP.
****************************************************************************/
static int SlotReferenceVar(
void *theEnv,
EXPRESSION *varexp,
void *userBuffer)
{
struct token itkn;
int oldpp;
SLOT_DESC *sd;
if ((varexp->type != SF_VARIABLE) && (varexp->type != MF_VARIABLE))
return(0);
if ((strncmp(ValueToString(varexp->value),SELF_STRING,SELF_LEN) == 0) ?
(ValueToString(varexp->value)[SELF_LEN] == SELF_SLOT_REF) : FALSE)
{
OpenStringSource(theEnv,"hnd-var",ValueToString(varexp->value) + SELF_LEN + 1,0);
oldpp = GetPPBufferStatus(theEnv);
SetPPBufferStatus(theEnv,OFF);
GetToken(theEnv,"hnd-var",&itkn);
SetPPBufferStatus(theEnv,oldpp);
CloseStringSource(theEnv,"hnd-var");
if (itkn.type != STOP)
{
sd = CheckSlotReference(theEnv,(DEFCLASS *) userBuffer,itkn.type,itkn.value,
FALSE,NULL);
if (sd == NULL)
return(-1);
GenHandlerSlotReference(theEnv,varexp,HANDLER_GET,sd);
return(1);
}
}
return(0);
}
/****************************************************************************
NAME : BindSlotReference
DESCRIPTION : Replaces direct slot binds in handler body with special
function calls to reference active instance at run-time
The slot in in the class bound at parse-time is always
referenced (early binding).
Slot references of the form ?self:<name> directly reference
ProcParamArray[0] (the message object - ?self) to
find the specified slot at run-time
INPUTS : 1) Variable expression
2) The class for the message-handler being parsed
RETURNS : 0 if not recognized, 1 if so, -1 on errors
SIDE EFFECTS : Handler body "bind" call replaced with direct slot access
function
NOTES : Objects are allowed to directly access their own slots
without sending a message to themselves. Since the object
is "within the boundary of its internals", this does not
violate the encapsulation principle of OOP.
****************************************************************************/
static int BindSlotReference(
void *theEnv,
EXPRESSION *bindExp,
void *userBuffer)
{
char *bindName;
struct token itkn;
int oldpp;
SLOT_DESC *sd;
EXPRESSION *saveExp;
bindName = ValueToString(bindExp->argList->value);
if (strcmp(bindName,SELF_STRING) == 0)
{
PrintErrorID(theEnv,"MSGPSR",5,FALSE);
EnvPrintRouter(theEnv,WERROR,"Active instance parameter cannot be changed.\n");
return(-1);
}
if ((strncmp(bindName,SELF_STRING,SELF_LEN) == 0) ?
(bindName[SELF_LEN] == SELF_SLOT_REF) : FALSE)
{
OpenStringSource(theEnv,"hnd-var",bindName + SELF_LEN + 1,0);
oldpp = GetPPBufferStatus(theEnv);
SetPPBufferStatus(theEnv,OFF);
GetToken(theEnv,"hnd-var",&itkn);
SetPPBufferStatus(theEnv,oldpp);
CloseStringSource(theEnv,"hnd-var");
if (itkn.type != STOP)
{
saveExp = bindExp->argList->nextArg;
sd = CheckSlotReference(theEnv,(DEFCLASS *) userBuffer,itkn.type,itkn.value,
TRUE,saveExp);
if (sd == NULL)
return(-1);
GenHandlerSlotReference(theEnv,bindExp,HANDLER_PUT,sd);
bindExp->argList->nextArg = NULL;
ReturnExpression(theEnv,bindExp->argList);
bindExp->argList = saveExp;
return(1);
}
}
return(0);
}
/*********************************************************
NAME : CheckSlotReference
DESCRIPTION : Examines a ?self:<slot-name> reference
If the reference is a single-field or
global variable, checking and evaluation
is delayed until run-time. If the
reference is a symbol, this routine
verifies that the slot is a legal
slot for the reference (i.e., it exists
in the class to which the message-handler
is being attached, it is visible and it
is writable for write reference)
INPUTS : 1) A buffer holding the class
of the handler being parsed
2) The type of the slot reference
3) The value of the slot reference
4) A flag indicating if this is a read
or write access
5) Value expression for write
RETURNS : Class slot on success, NULL on errors
SIDE EFFECTS : Messages printed on errors.
NOTES : For static references, this function
insures that the slot is either
publicly visible or that the handler
is being attached to the same class in
which the private slot is defined.
*********************************************************/
static SLOT_DESC *CheckSlotReference(
void *theEnv,
DEFCLASS *theDefclass,
int theType,
void *theValue,
intBool writeFlag,
EXPRESSION *writeExpression)
{
int slotIndex;
SLOT_DESC *sd;
int vCode;
if (theType != SYMBOL)
{
PrintErrorID(theEnv,"MSGPSR",7,FALSE);
EnvPrintRouter(theEnv,WERROR,"Illegal value for ?self reference.\n");
return(NULL);
}
slotIndex = FindInstanceTemplateSlot(theEnv,theDefclass,(SYMBOL_HN *) theValue);
if (slotIndex == -1)
{
PrintErrorID(theEnv,"MSGPSR",6,FALSE);
EnvPrintRouter(theEnv,WERROR,"No such slot ");
EnvPrintRouter(theEnv,WERROR,ValueToString(theValue));
EnvPrintRouter(theEnv,WERROR," in class ");
EnvPrintRouter(theEnv,WERROR,EnvGetDefclassName(theEnv,(void *) theDefclass));
EnvPrintRouter(theEnv,WERROR," for ?self reference.\n");
return(NULL);
}
sd = theDefclass->instanceTemplate[slotIndex];
if ((sd->publicVisibility == 0) && (sd->cls != theDefclass))
{
SlotVisibilityViolationError(theEnv,sd,theDefclass);
return(NULL);
}
if (! writeFlag)
return(sd);
/* =================================================
If a slot is initialize-only, the WithinInit flag
still needs to be checked at run-time, for the
handler could be called out of the context of
an init.
================================================= */
if (sd->noWrite && (sd->initializeOnly == 0))
{
SlotAccessViolationError(theEnv,ValueToString(theValue),
FALSE,(void *) theDefclass);
return(NULL);
}
if (EnvGetStaticConstraintChecking(theEnv))
{
vCode = ConstraintCheckExpressionChain(theEnv,writeExpression,sd->constraint);
if (vCode != NO_VIOLATION)
{
PrintErrorID(theEnv,"CSTRNCHK",1,FALSE);
EnvPrintRouter(theEnv,WERROR,"Expression for ");
PrintSlot(theEnv,WERROR,sd,NULL,"direct slot write");
ConstraintViolationErrorMessage(theEnv,NULL,NULL,0,0,NULL,0,
vCode,sd->constraint,FALSE);
return(NULL);
}
}
return(sd);
}
/***************************************************
NAME : GenHandlerSlotReference
DESCRIPTION : Creates a bitmap of the class id
and slot index for the get or put
operation. The bitmap and operation
type are stored in the given
expression.
INPUTS : 1) The expression
2) The operation type
3) The class slot
RETURNS : Nothing useful
SIDE EFFECTS : Bitmap created and expression
initialized
NOTES : None
***************************************************/
static void GenHandlerSlotReference(
void *theEnv,
EXPRESSION *theExp,
unsigned short theType,
SLOT_DESC *sd)
{
HANDLER_SLOT_REFERENCE handlerReference;
ClearBitString(&handlerReference,sizeof(HANDLER_SLOT_REFERENCE));
handlerReference.classID = (unsigned short) sd->cls->id;
handlerReference.slotID = (unsigned) sd->slotName->id;
theExp->type = theType;
theExp->value = AddBitMap(theEnv,(void *) &handlerReference,
(int) sizeof(HANDLER_SLOT_REFERENCE));
}
#endif
/***************************************************
NAME :
DESCRIPTION :
INPUTS :
RETURNS :
SIDE EFFECTS :
NOTES :
***************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -