?? 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) { gensprintf(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 + -