Ejemplo n.º 1
0
bool install_slot(struct objc_object *obj, 
		int offset,
		IMP method,
		char * types,
		uint32_t sel)
{
	//Type must match selector type
	char * seltypes = types_for_selector(sel);
	if(safestrcmp(seltypes, types) != 0)
	{
		return false;
	}
	objc_lock_object(obj);
	if(SLOTS(obj) == NULL)
	{
		SLOTS(obj) = SparseArrayNew();
	}
	struct objc_slot * oldSlot = SparseArrayLookup(SLOTS(obj), sel);
	if(oldSlot)
	{
		if(safestrcmp(types, oldSlot->types) != 0)
		{
			objc_unlock_object(obj);
			return false;
		}
		oldSlot->offset = offset;
		oldSlot->method = method;
	}
	else
	{
		//We are adding a new slot, not modifying an old one, so we need to 
		//invalidate a load of caches.
		id object = obj;
		oldSlot = slot_lookup(&object, sel, nil);
		struct objc_slot * newslot = calloc(1, sizeof(struct objc_slot));
		//TODO: Factor this out into a slot constructor
		newslot->offset = offset;
		newslot->method = method;
		if(types == NULL)
		{
			newslot->types = NULL;
		}
		else
		{
			newslot->types = strdup(types);
		}
		if(oldSlot != NULL)
		{
			oldSlot->version++;
		}
		SparseArrayInsert(SLOTS(obj), sel, newslot);
	}
	objc_unlock_object(obj);
	return true;
}
Ejemplo n.º 2
0
static inline struct objc_slot * real_slot_lookup(struct objc_object ** obj, uint32_t sel, id sender)
{
	id object = *obj;
	struct objc_slot * ret = NULL;
	do
	{
		if(LOOKUP(object))
		{
			return (*LOOKUP(object))(obj, object, sel, sender);
		}
		if(SLOTS(object))
		{
			ret = SparseArrayLookup(SLOTS(object), sel);
		}
		object = object->isa;
	} while(object != NULL && ret == NULL);
	return ret;
}
Ejemplo n.º 3
0
static ATOMID get_value(WORD wType, OBJECTID idObj, ATOMID idName, 
                        BOOL *bMlt, SLOTID *idSlot)
{
    LPSLOT lpSlot;
    ATOMID idValue;
    WORD wLen;
    
    *idSlot = NULLID;
    
    while (!*idSlot) {
        LPOBJECT lpObj = (LPOBJECT) KppGetItem(wType, idObj);
        OBJECTID idClass = CLASSOF(lpObj);
        
        if (!(FLAGS(lpObj) & REMOTE))
            *idSlot = KppGetElemPair(SLOTS(lpObj), idName);
        KppReleaseItem(wType, idObj);
        
        if (!*idSlot)
        {
            wType = CLASS;
            idObj = idClass;
            
            if (!idObj)
                return NULLID;
        }
    }
    
    lpSlot = (LPSLOT) KppGetItem(SLOT, *idSlot);
    *bMlt = ISOPTMULTI(lpSlot);
    idValue = VALUE(lpSlot);
    KppReleaseItem(SLOT, *idSlot);
    
    if (*bMlt)
        KppCheckList(idValue, &wLen);
    
    if (!idValue || *bMlt && !wLen)
        idValue = lpIDs->idNull;
    
    return idValue;
}
Ejemplo n.º 4
0
WORD PEXPORT Kpp_Set_SlotValue(WORD wType, OBJECTID idObj,
                               ATOMID idSlotName, ITEMID idValue,
                               WORD wIdType)
{
    LPOBJECT lpObj = (LPOBJECT) KppGetItem(wType, idObj);
    LPSLOT lpSlot = NULL;
    ATOMID idObjName;
    SLOTID idSlot = NULLID, idSlot2;
    LISTID idList;
    OBJECTID idClass;
    WORD wCode, wInherited = FALSE;

    if (!lpObj)
        return ERROR;
    
    idObjName = NAME(lpObj);
    idClass = CLASSOF(lpObj);
    idList = SLOTS(lpObj);
    if (idList)
        idSlot = KppGetElemPair(idList, idSlotName);
    
    if (!idSlot)
    {
        wInherited = TRUE;
        idSlot = Kpp_Get_Slot(CLASS, idClass, idSlotName);
    }
    
    if (KppIsRemoteObject(wType, idObj) &&
        IsRemoteSlot(idSlot, &lpSlot, TRUE))
    {
        if (!InvokeRemoteSlotOP(idObj, idSlotName,
                                (BOOL *) &wIdType, idSlot, lpSlot, &idValue,
                                REMOTE_SET_VALUE))
            return NULLID;
        
        if (!idSlot || wIdType == EXPLIST)
            return idValue;
    }        

    if (!idSlot)
    {
        KppReleaseItem(wType, idObj);
        return ERROR;
    }

    lpSlot = (LPSLOT) KppGetItem(SLOT, idSlot);
    if (!lpSlot)
    {
        KppReleaseItem(wType, idObj);
        return ERROR;
    }

    /* Check if compatible value & slot (single or multi) */
    if (idValue && idValue != lpIDs->idNull)
    {
        wCode = ISOPTMULTI(lpSlot);
        if (wCode && wIdType != EXPLIST || !wCode && wIdType != EXPATOM)
        {
            KppReleaseItem(SLOT, idSlot);
            KppReleaseItem(wType, idObj);
            return ERROR;
        }
    }

    if (!idValue)        /* ResetValue */
    {
        WORD wDelete;
        
        KppReleaseItem(wType, idObj);
        if (wInherited == TRUE)
        {
            KppReleaseItem(SLOT, idSlot);
            return lpIDs->idNull;
        }
        if (!_ResetSlotValue(LOBYTE(wType), lpSlot, idObj,
                             idObjName, wIdType, &wDelete))
        {
            KppReleaseItem(SLOT, idSlot);
            return ERROR;
        }
        if (wDelete)
        {
            KppDeleteElemPair(idList, idSlotName);
            KppDeleteItem(SLOT, idSlot);
        }
        KppReleaseItem(SLOT, idSlot);
        
        return lpIDs->idNull;
    }

    if (wInherited == TRUE)        /* make a copy before setting the value */
    {
        KppReleaseItem(SLOT, idSlot);
        idSlot2 = Kpp__Inherit_Slot(idSlot, (LPLPSTR) &lpSlot);

        if (!idSlot2)
        {
            KppReleaseItem(wType, idObj);
            return ERROR;
        }
        idSlot = idSlot2;
        if (!idList)
            idList = SLOTS(lpObj) = KppMakeList(0);

        KppAppendElemPair(idList, idSlotName, idSlot);
    }

    KppReleaseItem(wType, idObj);
    wCode = __SetSlotValue(wType, idObj, idSlot, lpSlot, idValue,
                           idObjName, wIdType);
    KppReleaseItem(SLOT, idSlot);
    
    return wCode;
}
Ejemplo n.º 5
0
ITEMID PEXPORT Kpp_Get_SlotListValue(WORD wType, OBJECTID idObj,
                                     ATOMID idSlotName)
{
    LPOBJECT lpObj;
    ITEMID idSlot;
    LPSLOT lpSlot = NULL;
    ITEMID idValue = NULLID, idList, idMethod;
    ATOMID idINMethodName, idWAMethodName;
    LPMETHOD lpMethod;
    CLASSID idClass;
    WORD wNumVars;
    WORD i = FALSE;
    BOOL bMonitor;

    idSlot = Kpp_Get_LocalSlot(wType, idObj, idSlotName);
    
    if (KppIsRemoteObject(wType, idObj) &&
        IsRemoteSlot(idSlot, &lpSlot, FALSE))
    {
        BOOL bMulti;
        ITEMID idValue;
        
        if (!InvokeRemoteSlotOP(idObj, idSlotName,
                                &bMulti, idSlot, lpSlot, &idValue, 
                                REMOTE_GET_VALUE))
            return NULLID;
        
        if (!bMulti)
            return NULLID;
        
        return idValue;
    }            

    if (!idSlot)
    {
        lpObj = (LPOBJECT) KppGetItem(wType, idObj);
        if (!lpObj)
            return ERROR;
        idClass = CLASSOF(lpObj);

        if (!idClass ||
            (!(idSlot = Kpp_Copy_Slot(CLASS, idClass, idSlotName))) ||
            (!(lpSlot = (LPSLOT) KppGetItem(SLOT, idSlot))))
        {
            KppReleaseItem(wType, idObj);
            if (idSlot)
                KppDeleteItem(SLOT, idSlot);
            
            return NULLID;
        }

        if (!ISOPTMULTI(lpSlot))
        {
            KppReleaseItem(wType, idObj);
            KppReleaseItem(SLOT, idSlot);
            KppDeleteItem(SLOT, idSlot);
            
            return NULLID;
        }
        idValue = VALUE(lpSlot);

        if (!(idList = SLOTS(lpObj)))
            idList = SLOTS(lpObj) = KppMakeList(0);
        KppReleaseItem(wType, idObj);
        KppAppendElemPair(idList, idSlotName, idSlot);
    }
    else
    {
        if (!(lpSlot = (LPSLOT) KppGetItem(SLOT, idSlot)))
            return NULLID;
        if (!ISOPTMULTI(lpSlot))
        {
            KppReleaseItem(SLOT, idSlot);
            return NULLID;
        }
        idValue = VALUE(lpSlot);
    }

    idINMethodName = OPTNEEDED(lpSlot);
    idWAMethodName = OPTWACCESS(lpSlot);
    KppReleaseItem(SLOT, idSlot);

    bMonitor = KppGetFileMonitor();        
    
    /* Do the IF_NEEDED demon */
    if (!idValue || !KppListLen(idValue))
    {        
        long lReturnSet;
        
        if (idINMethodName && idINMethodName != lpIDs->idNull && bMonitor)
        {
            if (!(idMethod = Kpp_Get_Method(wType, idObj, idINMethodName)))
                return RegisterKappaMessage(IDE_NOTEXIST, lpIDs->idIfNeeded,
                                            idINMethodName, NULLID);
            if (!(lpMethod = (LPMETHOD) KppGetItem(METHOD, idMethod)))
                return ERROR;

            idList = KppMakeList(0);
            wNumVars = NUMVARS(lpMethod);

            if (wNumVars == 4)
                KppAppendElem(idList, idSlotName);
            if (wNumVars > 4)
            {
                KppDeleteList(idList);
                KppReleaseItem(METHOD, idMethod);
                return RegisterKappaMessage(IDE_BADNUMARG, lpIDs->idIfNeeded,
                                            NULLID, NULLID);
            }

            UnwindProtect(cleanup);
            i = Kpp_Eval_Method(wType, idObj, idINMethodName, idList, FALSE);
          cleanup:
            KppReleaseItem(METHOD, idMethod);
            KppDeleteList(idList);
            EndProtect();

            if (!i)
                return NULLID;

            lReturnSet = KppGetKappaReturnSet();
            
            if (!(FAST_RETURNFLAGS & EXPLIST))
                return RegisterKappaMessage(IDE_IFBADRETURN,
                                            KppGetItemName(wType, idObj),
                                            idSlotName, NULLID);

            if (FAST_RETURNVALUE != lpIDs->idNull)
                idValue = FAST_RETURNVALUE;
        }
        /* no IF_NEEDED method is defined and the list is empty */
        else if (!idValue)
            idValue = lpIDs->idNull;
    }

    if (idWAMethodName && idWAMethodName != lpIDs->idNull && bMonitor)
    {
        long lReturnSet;
        
        if (!(idMethod = Kpp_Get_Method(wType, idObj, idWAMethodName)))
            return RegisterKappaMessage(IDE_NOTEXIST, lpIDs->idWhenAccess,
                                        idWAMethodName, NULLID);
        if (!(lpMethod = (LPMETHOD) KppGetItem(METHOD, idMethod)))
            return ERROR;

        idList = KppMakeList(0);
        wNumVars = NUMVARS(lpMethod);

        if (wNumVars >= 4)
            KppAppendElem(idList, idSlotName);
        if (wNumVars == 5)
            KppAppendElem(idList, idValue);

        if (wNumVars > 5)
        {
            KppReleaseItem(METHOD, idMethod);
            KppDeleteList(idList);
            return RegisterKappaMessage(IDE_BADNUMARG,
                                        lpIDs->idWhenAccess, NULLID, NULLID);
        }

        UnwindProtect(cleanup2);
        i = Kpp_Eval_Method(wType, idObj, idWAMethodName, idList, FALSE);
      cleanup2:
        KppReleaseItem(METHOD, idMethod);
        KppDeleteList(idList);
        EndProtect();

        if (!i)
            return NULLID;

        lReturnSet = KppGetKappaReturnSet();
        
        if (!(FAST_RETURNFLAGS & EXPLIST))
            return RegisterKappaMessage(IDE_WABADRETURN,
                          KppGetItemName(wType, idObj), idSlotName, NULLID);

        if (FAST_RETURNVALUE && FAST_RETURNVALUE != lpIDs->idNull)
            idValue = FAST_RETURNVALUE;
    }

    return idValue;
}
Ejemplo n.º 6
0
struct objc_slot * objc_object_next_slot(id obj, SEL * selector)
{
	return SparseArrayNext(SLOTS(obj), selector);
}