예제 #1
0
파일: runtime.cpp 프로젝트: maximecb/bjrn
/// Extract a pointer from a value
Value::operator void* () const
{
    if (!isPointer())
        throw RunError("trying to cast non-pointer value to pointer");

    return word.ptr;
}
// QC:A (Encore pas checkée à 100%, des problèmes de gestion de buffers ont été trouvés)
void ScriptVariable::setval(const char* str) {
	if(isPointer()) {
		getPointee()->setval(str);
		return;
	}

	setType(VAR_STR);
	value = strlen(str);

	if(data != NULL && data + value >= params) {
		// Pas assez de place dans le buffer, on le supprime
		AOEFREE(data);
		data = NULL;
	}

	if(data == NULL) {
		int newBufSize = value + (value > 48 ? 255 : 32);
		data = (char*) AOEMALLOC(newBufSize + 1);
		params = data + newBufSize; // params montre la fin du buffer
	}

	// memmove est generalement plus rapide que strcpy
	// le +1 copie le \0 en fin de chaine
	memmove(data, str, value + 1);
}
// QC:P
Context* ScriptVariable::gethashtable() const {
	if(isPointer())
		return getPointee()->gethashtable();
	if(type != VAR_HTBL)
		return NULL;
	return (Context*) data;
}
// QC:P
ScriptableObject* ScriptVariable::getobj() const {
	if(isPointer())
		return getPointee()->getobj();
	if(type != VAR_OBJ)
		return NULL;
	return (ScriptableObject*) data;
}
// QC:P
bool ScriptVariable::getbool() const {
	if(isPointer()) {
		return getPointee()->getbool();
	}

	switch(type){
	case VAR_NULL:
		return false;
	case VAR_INT:
		return value != 0;
	case VAR_PAIR:
		return data != 0 && params != 0;
	case VAR_STR:
		return value > 0;
	case VAR_PACK:
		return value != 0;
	case VAR_TBL:
		return data && ((ScriptTable*) data)->size();
	case VAR_RECT:
	case VAR_FCT:
	case VAR_HTBL:
	case VAR_XML:
	case VAR_OBJ:
	case VAR_RAW:
	case VAR_PTR:
	case VAR_TXTFCT:
		break;
	}

	return true;
}
// QC:G
void ScriptVariable::callNativeFunction(Context* params, Context* tc) {
	if(isPointer()) {
		getPointee()->callNativeFunction(params, tc);
		return;
	}

	assert(type == VAR_FCT || type == VAR_TXTFCT);

	params->registerScriptVariable("@retval");
	if(type == VAR_FCT) {
		ScriptVariable* retVal = params->getVar("@retval");

		if(value & FCTFLAG_STATIC) {
			// Appel direct de la fonction statique
			((void(*)(ScriptVariable&, Context&)) data)(*retVal, *params);
		} else {
			ScriptableObject* scriptThis = (ScriptableObject*) (((*params)["this"])->getobj());

			if(scriptThis != NULL) {
				// Appel indirect de la fonction membre
				((void(*)(ScriptableObject*, ScriptVariable&, Context&)) data)(scriptThis, *retVal, *params);
			}
		}
	} else // type == VAR_TXTFCT
	{
		assert(!(value & FCTFLAG_BLOCKING));
		assert(!(value & FCTFLAG_CLASS));
		ScriptedFunction* tmpThread = new ScriptedFunction(params->engine(), NULL, getstr(), params, tc, false, true);
#ifndef NDEBUG
		bool blocked = 
#endif
		tmpThread->run();
		assert(!blocked);
	}
}
예제 #7
0
reg_t reg_t::operator+(const reg_t right) const {
	if (isPointer() && right.isNumber()) {
		// Pointer arithmetics. Only some pointer types make sense here
		SegmentObj *mobj = g_sci->getEngineState()->_segMan->getSegmentObj(getSegment());

		if (!mobj)
			error("[VM]: Attempt to add %d to invalid pointer %04x:%04x", right.getOffset(), PRINT_REG(*this));

		switch (mobj->getType()) {
		case SEG_TYPE_LOCALS:
		case SEG_TYPE_SCRIPT:
		case SEG_TYPE_STACK:
		case SEG_TYPE_DYNMEM:
			return make_reg(getSegment(), getOffset() + right.toSint16());
		default:
			return lookForWorkaround(right, "addition");
		}
	} else if (isNumber() && right.isPointer()) {
		// Adding a pointer to a number, flip the order
		return right + *this;
	} else if (isNumber() && right.isNumber()) {
		// Normal arithmetics
		return make_reg(0, toSint16() + right.toSint16());
	} else {
		return lookForWorkaround(right, "addition");
	}
}
// QC:P
varType ScriptVariable::gettype() const {
	if(isPointer()) {
		return getPointee()->gettype();
	}

	return type;
}
// QC:A (discussion possible sur l'utilisation de snprintf. Les buffers statiques ne sont pas thread safe.)
char* ScriptVariable::getstr() const {
	if(isPointer()) {
		return getPointee()->getstr();
	}

	if(type == VAR_NULL) {
		return NULL;
	}

	if(type == VAR_INT) {
		static char number[32];
		snprintf(number, 32, "%d", value);
		number[31] ='\0';
		return number;
	}

	if(type == VAR_XML) {
		static TiXmlPrinter printer;
		printer = TiXmlPrinter();
		printer.SetStreamPrinting();
		TiXmlNode* node = (TiXmlNode*) data;
		node->Accept(&printer);
		return (char*)printer.CStr();
	}

	if(type == VAR_OBJ) {
		static char address[256];
		snprintf(address, 256, "(*%p:%s)", data, ((ScriptableObject*)data)->getClassName());
		address[255] ='\0';
		return address;
	}

	if(type == VAR_PAIR) {
		static char number[64];
		snprintf(number, 64, "(%ld:%ld)", (long) data, (long) params);
		number[63] ='\0';
		return number;
	}

	if(type == VAR_PACK) {
		static char info[4096]; // XXX : NOT thread safe
		snprintf(info, 4096, "(*%p => \"%s\")", data, params);
		info[4095] ='\0';
		return info;
	}

	if(type == VAR_TBL) {
		static char info[4096]; // XXX : NOT thread safe
		snprintf(info, 4096, "(tbl[%ld]:*%p)", (long)(data?(((ScriptTable*)data)->size()):0), data);
		info[4095] ='\0';
		return info;
	}

	if(type == VAR_FCT) {
		return params;
	}

	return data;
}
예제 #10
0
// QC:P
void ScriptVariable::setval(void) {
	if(isPointer()) {
		getPointee()->setval();
		return;
	}

	setType(VAR_NULL);
}
예제 #11
0
Type Cursor::nonPointerTupe() const
{
    auto typeResult = type();

    if (typeResult.isPointer())
        typeResult = typeResult.pointeeType();

    return typeResult;
}
예제 #12
0
// QC:P
void ScriptVariable::setval(Context* c) {
	if(isPointer()) {
		getPointee()->setval(c);
		return;
	}

	setType(VAR_HTBL);
	data = (char*) c;
}
예제 #13
0
// QC:B
void ScriptVariable::setval(const double d) {
	if(isPointer()) {
		getPointee()->setval(d);
		return;
	}

	assert(false); // Not implemented
// TODO : implement VAR_FLOAT	setType(VAR_FLOAT);
}
예제 #14
0
// QC:P
void ScriptVariable::setval(const bool b) {
	if(isPointer()) {
		getPointee()->setval(b);
		return;
	}

	setType(VAR_INT);
	value = b ? 1 : 0;
}
예제 #15
0
// QC:P
void ScriptVariable::setval(const int i) {
	if(isPointer()) {
		getPointee()->setval(i);
		return;
	}

	setType(VAR_INT);
	value = i;
}
예제 #16
0
// QC:P
void ScriptVariable::setptr(const ScriptVariable& v) {
	if(isPointer()) {
		getPointee()->setptr(v);
		return;
	}

	setType(VAR_PTR);
	data = (char*) (&v);
}
예제 #17
0
// QC:?
void ScriptVariable::setval(int x, int y, int w, int h) {
	if(isPointer()) {
		getPointee()->setval(x, y, w, h);
		return;
	}

	setType(VAR_RECT);

	data = (char*) new Rect(x, y, w, h);
}
예제 #18
0
// QC:S (le param devrait etre une reference const. Fonctionnelement parfaite)
void ScriptVariable::setval(Point p, Point s) {
	if(isPointer()) {
		getPointee()->setval(p, s);
		return;
	}

	setType(VAR_RECT);

	data = (char*) new Rect(p, s);
}
예제 #19
0
// QC:?
char* ScriptVariable::getblock() const {
	if(isPointer()) {
		return getPointee()->getblock();
	}

	if(type != VAR_FCT)
		return NULL;

	return block;
}
예제 #20
0
bool Inst::CastMatch(CodeContext& context, RValue& lhs, RValue& rhs, bool upcast)
{
	auto ltype = lhs.stype();
	auto rtype = rhs.stype();

	if (ltype == rtype) {
		return false;
	} else if (ltype->isComplex() || rtype->isComplex()) {
		context.addError("can not cast complex types");
		return true;
	} else if (ltype->isPointer() || rtype->isPointer()) {
		// different pointer types can't be cast automatically
		// the operations need to handle pointers specially
		return false;
	}

	auto toType = SType::numericConv(context, ltype, rtype, upcast);
	return CastTo(context, lhs, toType, upcast) || CastTo(context, rhs, toType, upcast);
}
예제 #21
0
// QC:F (cette fonction est un hack, elle ne peut etre parfaite. A considerer comme fonctionnelement parfaite)
void ScriptVariable::setval(char* d, char* p, int v) {
	if(isPointer()) {
		getPointee()->setval(d, p, v);
		return;
	}

	setType(VAR_RAW);
	data = d;
	params = p;
	value = v;
}
예제 #22
0
// QC:?
ScriptTable* ScriptVariable::gettable() const {
	if(isPointer()) {
		return getPointee()->gettable();
	}

	if(type != VAR_TBL) {
		return NULL;
	}

	return (ScriptTable*)data;
}
예제 #23
0
// QC:P
void ScriptVariable::settxtfct(char* code, char* fparams, const int flags) {
	if(isPointer()) {
		getPointee()->settxtfct(code, fparams, flags);
		return;
	}

	setType(VAR_TXTFCT);

	data = code;
	params = fparams;
	value = flags;
}
예제 #24
0
// QC:?
void ScriptVariable::setval(TiXmlNode* xml) {
	if(isPointer()) {
		getPointee()->setval(xml);
		return;
	}

	if(xml) {
		setType(VAR_XML);
		data = (char*)xml;
	} else {
		setType(VAR_NULL);
	}
}
예제 #25
0
// QC:P
Point ScriptVariable::getPointPercent() const {
	if(isPointer())
		return getPointee()->getPoint();
	if(type != VAR_PAIR) {
		if(type == VAR_INT) {
			return Point(value, 0);
		}

		return Point(100, 100);
	}

	return Point((long) data, (long) params);
}
예제 #26
0
// QC:P
int ScriptVariable::getY() const {
	if(isPointer())
		return getPointee()->getY();
	if(type == VAR_RECT) {
		return ((Rect*) data)->getY();
	}

	if(type != VAR_PAIR) {
		return 0;
	}

	return (long) params;
}
예제 #27
0
// QC:?
void ScriptVariable::setval(const char* format, const char* content) {
	if(isPointer()) {
		getPointee()->setval(format, content);
		return;
	}

	setType(VAR_PACK);

	if(format && content && *format) {
		params = AOESTRDUP(format);
		data = packedStructureDup(format, content);
		value = getPackedStructureLength(params, data);
	}
}
예제 #28
0
void CheckNullPointer::nullPointerAfterLoop()
{
    // Locate insufficient null-pointer handling after loop
    for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
    {
        // only interested in while ( %var% )
        // TODO: Aren't there false negatives. Shouldn't other loops be handled such as:
        //       - while ( ! %var% )
        //       - while ( %var% && .. )
        if (! Token::Match(tok, "while ( %var% )"))
            continue;

        // Get variable id for the loop variable
        const unsigned int varid(tok->tokAt(2)->varId());
        if (varid == 0)
            continue;

        // Is variable a pointer?
        if (!isPointer(varid))
            continue;

        // Get variable name for the loop variable
        const std::string varname(tok->strAt(2));

        // Locate the end of the while loop body..
        const Token *tok2 = tok->tokAt(4)->link();

        // Check if the variable is dereferenced after the while loop
        while (0 != (tok2 = tok2 ? tok2->next() : 0))
        {
            // Don't check into inner scopes or outer scopes. Stop checking if "break" is found
            if (tok2->str() == "{" || tok2->str() == "}" || tok2->str() == "break")
                break;

            // loop variable is found..
            if (tok2->varId() == varid)
            {
                // dummy variable.. is it unknown if pointer is dereferenced or not?
                bool unknown = false;

                // Is the loop variable dereferenced?
                if (CheckNullPointer::isPointerDeRef(tok2, unknown))
                {
                    nullPointerError(tok2, varname, tok->linenr());
                }
                break;
            }
        }
    }
}
예제 #29
0
// QC:?
Rect ScriptVariable::getRect() const {
	if(isPointer())
		return getPointee()->getRect();
	if(type != VAR_RECT) {
		if(type == VAR_PAIR) {
			return Rect((int) value, (int)(long) data, 0, 0);
		} else if(type == VAR_INT) {
			return Rect(value, 0, 0, 0);
		}

		return Rect();
	}
	return Rect((Rect*) data);
}
예제 #30
0
// QC:?
VFS::File* ScriptVariable::getfile(VFS::File* pathRoot) const {
	if(isPointer()) {
		return getPointee()->getfile();
	}

	if(type == VAR_OBJ) {
		return getobj()->source();
	}

	static VFS::File* f = NULL;
	if(f)
		delete f;
	f = VFS::openFile(getstr(), pathRoot);
	return f;
}