/// 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); } }
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; }
// QC:P void ScriptVariable::setval(void) { if(isPointer()) { getPointee()->setval(); return; } setType(VAR_NULL); }
Type Cursor::nonPointerTupe() const { auto typeResult = type(); if (typeResult.isPointer()) typeResult = typeResult.pointeeType(); return typeResult; }
// QC:P void ScriptVariable::setval(Context* c) { if(isPointer()) { getPointee()->setval(c); return; } setType(VAR_HTBL); data = (char*) c; }
// 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); }
// QC:P void ScriptVariable::setval(const bool b) { if(isPointer()) { getPointee()->setval(b); return; } setType(VAR_INT); value = b ? 1 : 0; }
// QC:P void ScriptVariable::setval(const int i) { if(isPointer()) { getPointee()->setval(i); return; } setType(VAR_INT); value = i; }
// QC:P void ScriptVariable::setptr(const ScriptVariable& v) { if(isPointer()) { getPointee()->setptr(v); return; } setType(VAR_PTR); data = (char*) (&v); }
// 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); }
// 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); }
// QC:? char* ScriptVariable::getblock() const { if(isPointer()) { return getPointee()->getblock(); } if(type != VAR_FCT) return NULL; return block; }
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); }
// 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; }
// QC:? ScriptTable* ScriptVariable::gettable() const { if(isPointer()) { return getPointee()->gettable(); } if(type != VAR_TBL) { return NULL; } return (ScriptTable*)data; }
// 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; }
// QC:? void ScriptVariable::setval(TiXmlNode* xml) { if(isPointer()) { getPointee()->setval(xml); return; } if(xml) { setType(VAR_XML); data = (char*)xml; } else { setType(VAR_NULL); } }
// 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); }
// 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; }
// 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); } }
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; } } } }
// 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); }
// 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; }