void BIF_ObjCreate(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount) { IObject *obj = NULL; if (aParamCount == 1) // L33: POTENTIALLY UNSAFE - Cast IObject address to object reference. { if (obj = TokenToObject(*aParam[0])) { // Allow &obj == Object(obj), but AddRef() for equivalence with ComObjActive(comobj). obj->AddRef(); aResultToken.value_int64 = (__int64)obj; return; // symbol is already SYM_INTEGER. } obj = (IObject *)TokenToInt64(*aParam[0]); if (obj < (IObject *)1024) // Prevent some obvious errors. obj = NULL; else obj->AddRef(); } else obj = Object::Create(aParam, aParamCount); if (obj) { aResultToken.symbol = SYM_OBJECT; aResultToken.object = obj; // DO NOT ADDREF: after we return, the only reference will be in aResultToken. } else { aResultToken.symbol = SYM_STRING; aResultToken.marker = _T(""); } }
void BIF_ObjCreate(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount) { IObject *obj = NULL; if (aParamCount == 1) // L33: POTENTIALLY UNSAFE - Cast IObject address to object reference. { obj = (IObject *)TokenToInt64(*aParam[0]); if (obj < (IObject *)1024) // Prevent some obvious errors. obj = NULL; else obj->AddRef(); } else obj = Object::Create(aParam, aParamCount); if (obj) { aResultToken.symbol = SYM_OBJECT; aResultToken.object = obj; // DO NOT ADDREF: after we return, the only reference will be in aResultToken. } else { aResultToken.symbol = SYM_STRING; aResultToken.marker = _T(""); } }
void BIF_ObjGetInPlace(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount) { // Since the most common cases have two params, the "param count" param is omitted in // those cases. Otherwise we have one visible parameter, which indicates the number of // actual parameters below it on the stack. aParamCount = aParamCount ? (int)TokenToInt64(*aParam[0]) : 2; // x[<n-1 params>] : x.y BIF_ObjInvoke(aResultToken, aParam - aParamCount, aParamCount); }
void BIF_ObjAddRefRelease(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount) { IObject *obj = (IObject *)TokenToInt64(*aParam[0]); if (obj < (IObject *)4096) // Rule out some obvious errors. { aResultToken.symbol = SYM_STRING; aResultToken.marker = _T(""); return; } if (aResultToken.marker[3] == 'A') aResultToken.value_int64 = obj->AddRef(); else aResultToken.value_int64 = obj->Release(); }
void BIF_ObjIncDec(ExprTokenType &aResultToken, ExprTokenType *aParam[], int aParamCount) { // Func::mName (which aResultToken.marker is set to) has been overloaded to pass // the type of increment/decrement to be performed on this object's field. SymbolType op = (SymbolType)(INT_PTR)aResultToken.marker; ExprTokenType temp_result, current_value, value_to_set; // Set the defaults expected by BIF_ObjInvoke: temp_result.symbol = SYM_INTEGER; temp_result.marker = (LPTSTR)IT_GET; temp_result.buf = aResultToken.buf; temp_result.mem_to_free = NULL; // Retrieve the current value. Do it this way instead of calling Object::Invoke // so that if aParam[0] is not an object, g_MetaObject is correctly invoked. BIF_ObjInvoke(temp_result, aParam, aParamCount); // Change SYM_STRING to SYM_OPERAND so below may treat it as a numeric string. if (temp_result.symbol == SYM_STRING) { temp_result.symbol = SYM_OPERAND; temp_result.buf = NULL; // Indicate that this SYM_OPERAND token LACKS a pre-converted binary integer. } switch (value_to_set.symbol = current_value.symbol = TokenIsPureNumeric(temp_result)) { case PURE_INTEGER: value_to_set.value_int64 = (current_value.value_int64 = TokenToInt64(temp_result)) + ((op == SYM_POST_INCREMENT || op == SYM_PRE_INCREMENT) ? +1 : -1); break; case PURE_FLOAT: value_to_set.value_double = (current_value.value_double = TokenToDouble(temp_result)) + ((op == SYM_POST_INCREMENT || op == SYM_PRE_INCREMENT) ? +1 : -1); break; } // Free the object or string returned by BIF_ObjInvoke, if applicable. if (temp_result.symbol == SYM_OBJECT) temp_result.object->Release(); if (temp_result.mem_to_free) free(temp_result.mem_to_free); if (current_value.symbol == PURE_NOT_NUMERIC) { // Value is non-numeric, so return "". aResultToken.symbol = SYM_STRING; aResultToken.marker = _T(""); return; } // Although it's likely our caller's param array has enough space to hold the extra // parameter, there's no way to know for sure whether it's safe, so we allocate our own: ExprTokenType **param = (ExprTokenType **)_alloca((aParamCount + 1) * sizeof(ExprTokenType *)); memcpy(param, aParam, aParamCount * sizeof(ExprTokenType *)); // Copy caller's param pointers. param[aParamCount++] = &value_to_set; // Append new value as the last parameter. if (op == SYM_PRE_INCREMENT || op == SYM_PRE_DECREMENT) { aResultToken.marker = (LPTSTR)IT_SET; // Set the new value and pass the return value of the invocation back to our caller. // This should be consistent with something like x.y := x.y + 1. BIF_ObjInvoke(aResultToken, param, aParamCount); } else // SYM_POST_INCREMENT || SYM_POST_DECREMENT { // Must be re-initialized (and must use IT_SET instead of IT_GET): temp_result.symbol = SYM_INTEGER; temp_result.marker = (LPTSTR)IT_SET; temp_result.buf = aResultToken.buf; temp_result.mem_to_free = NULL; // Set the new value. BIF_ObjInvoke(temp_result, param, aParamCount); // Dispose of the result safely. if (temp_result.symbol == SYM_OBJECT) temp_result.object->Release(); if (temp_result.mem_to_free) free(temp_result.mem_to_free); // Return the previous value. aResultToken.symbol = current_value.symbol; aResultToken.value_int64 = current_value.value_int64; // Union copy. } }