memory.xml invalidation (untested)

develop
Petr Mrázek 2010-11-08 00:10:59 +01:00
parent 8a675364e5
commit 9ac7c1a9f2
15 changed files with 249 additions and 67 deletions

@ -1892,7 +1892,7 @@
<Address name="vector" value="0x92D9AC0" /> <Address name="vector" value="0x92D9AC0" />
<Address name="current_race" value="0x92C1628" /> <Address name="current_race" value="0x92C1628" />
<Address name="current_civ" value="0x92C161C" /> <Address name="current_civ" value="0x92C161C" />
<Group name="creature" valid="verify" > <Group name="creature" valid="true" >
<Offset name="name" value="0x0" /> <Offset name="name" value="0x0" />
<Offset name="custom_profession" value="0x3c" /> <Offset name="custom_profession" value="0x3c" />
<Offset name="profession" value="0x40" /> <Offset name="profession" value="0x40" />
@ -2028,12 +2028,12 @@
<Group name="creature" valid="verify" > <Group name="creature" valid="verify" >
<Group name="advanced"> <Group name="advanced">
<Offset name="soul_vector" value="0x0524" /> <Offset name="soul_vector" value="0x0524" />
<Offset name="current_soul" value="0x0530" valid="verify" /> <Offset name="current_soul" value="0x0530" />
<Offset name="labors" value="0x540" /> <Offset name="labors" value="0x540" />
<Offset name="happiness" value="0x5d0" /> <Offset name="happiness" value="0x5d0" />
</Group> </Group>
</Group> </Group>
<Group name="soul" valid="verify"> <Group name="soul">
<Offset name="name" value="0x0" /> <Offset name="name" value="0x0" />
<Offset name="mental" value="0x88" /> <Offset name="mental" value="0x88" />
<Offset name="skills_vector" value="0x1C4" /> CHMOD <Offset name="skills_vector" value="0x1C4" /> CHMOD
@ -2144,7 +2144,7 @@
<Address name="window_z" value="0x8ceb240" /> <Address name="window_z" value="0x8ceb240" />
<Address name="cursor_xyz" value="0x8b2e740" /> <Address name="cursor_xyz" value="0x8b2e740" />
<Address name="window_dims" value="0x8b2ec48" /> <Address name="window_dims" value="0x8b2ec48" />
<Address name="screen_tiles_pointer" invalid = "true" /> <Address name="screen_tiles_pointer" valid = "false" />
</Group> </Group>
<Group name="GUI"> <Group name="GUI">
<Address name="pause_state" value="0x92e0e90"/> <Address name="pause_state" value="0x92e0e90"/>
@ -2208,7 +2208,7 @@
<Address name="window_z" value="0x8cee540 0x8ceb240" /> <Address name="window_z" value="0x8cee540 0x8ceb240" />
<Address name="cursor_xyz" value="0x8b31a30 0x8b2e740" /> <Address name="cursor_xyz" value="0x8b31a30 0x8b2e740" />
<Address name="window_dims" value="0x8b31f48 0x8b2ec48" /> <Address name="window_dims" value="0x8b31f48 0x8b2ec48" />
<Address name="screen_tiles_pointer" invalid = "true" /> <Address name="screen_tiles_pointer" valid = "false" />
</Group> </Group>
<Group name="GUI"> <Group name="GUI">
<Address name="pause_state" value="0x92e0e90"/> <Address name="pause_state" value="0x92e0e90"/>
@ -2231,7 +2231,7 @@
<Offsets> <Offsets>
<Group name="Position"> <Group name="Position">
<Address name="cursor_xyz" value="0x8b33550 0x8b311f8" /> <Address name="cursor_xyz" value="0x8b33550 0x8b311f8" />
<Address name="screen_tiles_pointer" invalid = "true" /> <Address name="screen_tiles_pointer" valid = "false" />
</Group> </Group>
<Group name="GUI"> <Group name="GUI">
<Address name="pause_state" value="0x92e5cb0"/> <Address name="pause_state" value="0x92e5cb0"/>

@ -334,7 +334,7 @@ bool API::InitReadEffects ( uint32_t & numeffects )
{ {
effects = d->offset_descriptor->getAddress ("effects_vector"); effects = d->offset_descriptor->getAddress ("effects_vector");
} }
catch(Error::MissingMemoryDefinition) catch(Error::AllMemdef)
{ {
return false; return false;
} }
@ -400,7 +400,7 @@ bool API::InitReadNotes( uint32_t &numnotes )
numnotes = d->p_notes->getSize(); numnotes = d->p_notes->getSize();
return true; return true;
} }
catch (Error::MissingMemoryDefinition&) catch (Error::AllMemdef&)
{ {
d->notesInited = false; d->notesInited = false;
numnotes = 0; numnotes = 0;
@ -438,7 +438,7 @@ bool API::InitReadSettlements( uint32_t & numsettlements )
numsettlements = d->p_settlements->getSize(); numsettlements = d->p_settlements->getSize();
return true; return true;
} }
catch (Error::MissingMemoryDefinition&) catch (Error::AllMemdef&)
{ {
d->settlementsInited = false; d->settlementsInited = false;
numsettlements = 0; numsettlements = 0;
@ -543,7 +543,7 @@ bool API::InitReadItems(uint32_t & numitems)
numitems = d->p_itm->getSize(); numitems = d->p_itm->getSize();
return true; return true;
} }
catch (Error::MissingMemoryDefinition&) catch (Error::AllMemdef&)
{ {
d->itemsInited = false; d->itemsInited = false;
numitems = 0; numitems = 0;

@ -339,7 +339,7 @@ bool SHMProcess::Private::validate(vector <VersionInfo *> & known_versions)
return true; return true;
} }
} }
catch (Error::MissingMemoryDefinition&) catch (Error::AllMemdef&)
{ {
continue; continue;
} }

@ -142,7 +142,7 @@ bool WineProcess::Private::validate(char* exe_file, uint32_t pid, char* mem_file
{ {
thishash = (*it)->getMD5(); thishash = (*it)->getMD5();
} }
catch (Error::MissingMemoryDefinition& e) catch (Error::AllMemdef& e)
{ {
continue; continue;
} }

@ -142,7 +142,7 @@ bool NormalProcess::Private::validate(char * exe_file,uint32_t pid, char * memFi
return true; return true;
} }
} }
catch (Error::MissingMemoryDefinition&) catch (Error::AllMemdef&)
{ {
continue; continue;
} }

@ -353,7 +353,7 @@ bool SHMProcess::Private::validate(vector <VersionInfo *> & known_versions)
{ {
pe_timestamp = (*it)->getPE(); pe_timestamp = (*it)->getPE();
} }
catch(Error::MissingMemoryDefinition&) catch(Error::AllMemdef&)
{ {
continue; continue;
} }

@ -111,7 +111,7 @@ NormalProcess::NormalProcess(uint32_t pid, vector <VersionInfo *> & known_versio
{ {
pe_timestamp = (*it)->getPE(); pe_timestamp = (*it)->getPE();
} }
catch(Error::MissingMemoryDefinition&) catch(Error::AllMemdef&)
{ {
continue; continue;
} }

@ -127,11 +127,11 @@ namespace DFHack
*/ */
namespace DFHack namespace DFHack
{ {
typedef pair <bool, uint32_t> nullableUint32; typedef pair <INVAL_TYPE, uint32_t> nullableUint32;
typedef map <string, nullableUint32 >::iterator uint32_Iter; typedef map <string, nullableUint32 >::iterator uint32_Iter;
typedef pair <bool, int32_t> nullableInt32; typedef pair <INVAL_TYPE, int32_t> nullableInt32;
typedef map <string, nullableInt32 >::iterator int32_Iter; typedef map <string, nullableInt32 >::iterator int32_Iter;
typedef pair <bool, string> nullableString; typedef pair <INVAL_TYPE, string> nullableString;
typedef map <string, nullableString >::iterator strings_Iter; typedef map <string, nullableString >::iterator strings_Iter;
typedef map <string, OffsetGroup *>::iterator groups_Iter; typedef map <string, OffsetGroup *>::iterator groups_Iter;
class OffsetGroupPrivate class OffsetGroupPrivate
@ -149,69 +149,73 @@ namespace DFHack
void OffsetGroup::createOffset(const string & key) void OffsetGroup::createOffset(const string & key)
{ {
OGd->offsets[key] = nullableInt32(false, 0); OGd->offsets[key] = nullableInt32(NOT_SET, 0);
} }
void OffsetGroup::createAddress(const string & key) void OffsetGroup::createAddress(const string & key)
{ {
OGd->addresses[key] = nullableUint32(false, 0); OGd->addresses[key] = nullableUint32(NOT_SET, 0);
} }
void OffsetGroup::createHexValue(const string & key) void OffsetGroup::createHexValue(const string & key)
{ {
OGd->hexvals[key] = nullableUint32(false, 0); OGd->hexvals[key] = nullableUint32(NOT_SET, 0);
} }
void OffsetGroup::createString(const string & key) void OffsetGroup::createString(const string & key)
{ {
OGd->strings[key] = nullableString(false, std::string()); OGd->strings[key] = nullableString(NOT_SET, std::string());
} }
void OffsetGroup::setOffset (const string & key, const string & value) void OffsetGroup::setOffset (const string & key, const string & value, const INVAL_TYPE inval)
{ {
int32_Iter it = OGd->offsets.find(key); int32_Iter it = OGd->offsets.find(key);
if(it != OGd->offsets.end()) if(it != OGd->offsets.end())
{ {
int32_t offset = strtol(value.c_str(), NULL, 16); int32_t offset = strtol(value.c_str(), NULL, 16);
(*it).second.second = offset; (*it).second.second = offset;
(*it).second.first = true; if(inval != NOT_SET)
(*it).second.first = inval;
} }
else throw Error::MissingMemoryDefinition("offset", getFullName() + key); else throw Error::MissingMemoryDefinition("offset", getFullName() + key);
} }
void OffsetGroup::setAddress (const string & key, const string & value) void OffsetGroup::setAddress (const string & key, const string & value, const INVAL_TYPE inval)
{ {
uint32_Iter it = OGd->addresses.find(key); uint32_Iter it = OGd->addresses.find(key);
if(it != OGd->addresses.end()) if(it != OGd->addresses.end())
{ {
int32_t address = strtol(value.c_str(), NULL, 16); int32_t address = strtol(value.c_str(), NULL, 16);
(*it).second.second = address; (*it).second.second = address;
(*it).second.first = true; if(inval != NOT_SET)
(*it).second.first = inval;
} }
else throw Error::MissingMemoryDefinition("address", getFullName() + key); else throw Error::MissingMemoryDefinition("address", getFullName() + key);
} }
void OffsetGroup::setHexValue (const string & key, const string & value) void OffsetGroup::setHexValue (const string & key, const string & value, const INVAL_TYPE inval)
{ {
uint32_Iter it = OGd->hexvals.find(key); uint32_Iter it = OGd->hexvals.find(key);
if(it != OGd->hexvals.end()) if(it != OGd->hexvals.end())
{ {
(*it).second.second = strtol(value.c_str(), NULL, 16); (*it).second.second = strtol(value.c_str(), NULL, 16);
(*it).second.first = true; if(inval != NOT_SET)
(*it).second.first = inval;
} }
else throw Error::MissingMemoryDefinition("hexvalue", getFullName() + key); else throw Error::MissingMemoryDefinition("hexvalue", getFullName() + key);
} }
void OffsetGroup::setString (const string & key, const string & value) void OffsetGroup::setString (const string & key, const string & value, const INVAL_TYPE inval)
{ {
strings_Iter it = OGd->strings.find(key); strings_Iter it = OGd->strings.find(key);
if(it != OGd->strings.end()) if(it != OGd->strings.end())
{ {
(*it).second.second = value; (*it).second.second = value;
(*it).second.first = true; if(inval != NOT_SET)
(*it).second.first = inval;
} }
else throw Error::MissingMemoryDefinition("string", getFullName() + key); else throw Error::MissingMemoryDefinition("string", getFullName() + key);
} }
@ -224,8 +228,10 @@ uint32_t OffsetGroup::getAddress (const string & key)
if(iter != OGd->addresses.end()) if(iter != OGd->addresses.end())
{ {
if((*iter).second.first) if((*iter).second.first == IS_VALID)
return (*iter).second.second; return (*iter).second.second;
if((*iter).second.first == IS_INVALID)
throw Error::InvalidMemoryDefinition("address", getFullName() + key);
throw Error::UnsetMemoryDefinition("address", getFullName() + key); throw Error::UnsetMemoryDefinition("address", getFullName() + key);
} }
throw Error::MissingMemoryDefinition("address", getFullName() + key); throw Error::MissingMemoryDefinition("address", getFullName() + key);
@ -238,8 +244,10 @@ int32_t OffsetGroup::getOffset (const string & key)
int32_Iter iter = OGd->offsets.find(key); int32_Iter iter = OGd->offsets.find(key);
if(iter != OGd->offsets.end()) if(iter != OGd->offsets.end())
{ {
if((*iter).second.first) if((*iter).second.first == IS_VALID)
return (*iter).second.second; return (*iter).second.second;
if((*iter).second.first == IS_INVALID)
throw Error::InvalidMemoryDefinition("offset", getFullName() + key);
throw Error::UnsetMemoryDefinition("offset", getFullName() + key); throw Error::UnsetMemoryDefinition("offset", getFullName() + key);
} }
throw Error::MissingMemoryDefinition("offset", getFullName() + key); throw Error::MissingMemoryDefinition("offset", getFullName() + key);
@ -252,8 +260,10 @@ uint32_t OffsetGroup::getHexValue (const string & key)
uint32_Iter iter = OGd->hexvals.find(key); uint32_Iter iter = OGd->hexvals.find(key);
if(iter != OGd->hexvals.end()) if(iter != OGd->hexvals.end())
{ {
if((*iter).second.first) if((*iter).second.first == IS_VALID)
return (*iter).second.second; return (*iter).second.second;
if((*iter).second.first == IS_INVALID)
throw Error::InvalidMemoryDefinition("hexvalue", getFullName() + key);
throw Error::UnsetMemoryDefinition("hexvalue", getFullName() + key); throw Error::UnsetMemoryDefinition("hexvalue", getFullName() + key);
} }
throw Error::MissingMemoryDefinition("hexvalue", getFullName() + key); throw Error::MissingMemoryDefinition("hexvalue", getFullName() + key);
@ -265,8 +275,10 @@ std::string OffsetGroup::getString (const string &key)
strings_Iter iter = OGd->strings.find(key); strings_Iter iter = OGd->strings.find(key);
if(iter != OGd->strings.end()) if(iter != OGd->strings.end())
{ {
if((*iter).second.first) if((*iter).second.first == IS_VALID)
return (*iter).second.second; return (*iter).second.second;
if((*iter).second.first == IS_INVALID)
throw Error::InvalidMemoryDefinition("string", getFullName() + key);
throw Error::UnsetMemoryDefinition("string", getFullName() + key); throw Error::UnsetMemoryDefinition("string", getFullName() + key);
} }
throw Error::MissingMemoryDefinition("string", getFullName() + key); throw Error::MissingMemoryDefinition("string", getFullName() + key);
@ -361,6 +373,8 @@ std::string OffsetGroup::PrintOffsets(int indentation)
if((*iter).second.first) if((*iter).second.first)
ss << " value=\"" << hex << "0x" << (*iter).second.second << "\""; ss << " value=\"" << hex << "0x" << (*iter).second.second << "\"";
ss << " />"; ss << " />";
if((*iter).second.first == IS_INVALID)
ss << " INVALID!";
if(!(*iter).second.first) if(!(*iter).second.first)
ss << " MISSING!"; ss << " MISSING!";
ss << endl; ss << endl;
@ -372,6 +386,8 @@ std::string OffsetGroup::PrintOffsets(int indentation)
if((*iter2).second.first) if((*iter2).second.first)
ss << " value=\"" << hex << "0x" << (*iter2).second.second << "\""; ss << " value=\"" << hex << "0x" << (*iter2).second.second << "\"";
ss << " />"; ss << " />";
if((*iter2).second.first == IS_INVALID)
ss << " INVALID!";
if(!(*iter2).second.first) if(!(*iter2).second.first)
ss << " MISSING!"; ss << " MISSING!";
ss << endl; ss << endl;
@ -382,6 +398,8 @@ std::string OffsetGroup::PrintOffsets(int indentation)
if((*iter).second.first) if((*iter).second.first)
ss << " value=\"" << hex << "0x" << (*iter).second.second << "\""; ss << " value=\"" << hex << "0x" << (*iter).second.second << "\"";
ss << " />"; ss << " />";
if((*iter).second.first == IS_INVALID)
ss << " INVALID!";
if(!(*iter).second.first) if(!(*iter).second.first)
ss << " MISSING!"; ss << " MISSING!";
ss << endl; ss << endl;
@ -393,6 +411,8 @@ std::string OffsetGroup::PrintOffsets(int indentation)
if((*iter3).second.first) if((*iter3).second.first)
ss << " value=\"" << (*iter3).second.second << "\""; ss << " value=\"" << (*iter3).second.second << "\"";
ss << " />"; ss << " />";
if((*iter3).second.first == IS_INVALID)
ss << " INVALID!";
if(!(*iter3).second.first) if(!(*iter3).second.first)
ss << " MISSING!"; ss << " MISSING!";
ss << endl; ss << endl;
@ -409,6 +429,42 @@ std::string OffsetGroup::PrintOffsets(int indentation)
return ss.str(); return ss.str();
} }
// the big ugly method behind the curtain...
void OffsetGroup::setInvalid(INVAL_TYPE invalidity)
{
if(invalidity == NOT_SET)
return;
uint32_Iter iter;
for(iter = OGd->addresses.begin(); iter != OGd->addresses.end(); iter++)
{
if((*iter).second.first)
(*iter).second.first = invalidity;
}
int32_Iter iter2;
for(iter2 = OGd->offsets.begin(); iter2 != OGd->offsets.end(); iter2++)
{
if((*iter2).second.first)
(*iter2).second.first = invalidity;
}
for(iter = OGd->hexvals.begin(); iter != OGd->hexvals.end(); iter++)
{
if((*iter).second.first)
(*iter).second.first = invalidity;
}
strings_Iter iter3;
for(iter3 = OGd->strings.begin(); iter3 != OGd->strings.end(); iter3++)
{
if((*iter3).second.first)
(*iter3).second.first = invalidity;
}
groups_Iter iter4;
for(iter4 = OGd->groups.begin(); iter4 != OGd->groups.end(); iter4++)
{
(*iter4).second->setInvalid(invalidity);
}
}
/* /*
* Private data * Private data
*/ */

@ -31,6 +31,65 @@ distribution.
using namespace DFHack; using namespace DFHack;
template<class _T1, class _T2, class _T3>
struct triple
{
typedef _T1 first_type;
typedef _T2 second_type;
typedef _T3 third_type;
_T1 first;
_T2 second;
_T3 third;
triple() : first(), second(), third() { }
triple(const _T1& __a, const _T2& __b, const _T3& __c) : first(__a), second(__b), third(__c) { }
template<class _U1, class _U2, class _U3>
triple(const triple<_U1, _U2, _U3>& __p) : first(__p.first), second(__p.second), third(__p.third) { }
};
template<class _T1, class _T2, class _T3>
inline bool operator==(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return __x.first == __y.first && __x.second == __y.second && __x.third == __y.third;
}
template<class _T1, class _T2, class _T3>
inline bool operator<(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return
__x.first < __y.first ||
(!(__y.first < __x.first) && __x.second < __y.second) ||
(!(__y.first < __x.first) && !(__x.second < __y.second) && (__x.third < __y.third));
}
template<class _T1, class _T2, class _T3>
inline bool operator!=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return !(__x == __y);
}
template<class _T1, class _T2, class _T3>
inline bool operator>(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return __y < __x;
}
template<class _T1, class _T2, class _T3>
inline bool operator<=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return !(__y < __x);
}
template<class _T1, class _T2, class _T3>
inline bool operator>=(const triple<_T1, _T2, _T3>& __x, const triple<_T1, _T2, _T3>& __y)
{
return !(__x < __y);
}
VersionInfoFactory::~VersionInfoFactory() VersionInfoFactory::~VersionInfoFactory()
{ {
// for each stored version, delete // for each stored version, delete
@ -95,35 +154,51 @@ void VersionInfoFactory::ParseVTable(TiXmlElement* vtable, VersionInfo* mem)
} }
} }
// FIXME: this is ripe for replacement with a more generic approach struct breadcrumb
{
TiXmlElement * first;
OffsetGroup * second;
};
void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target, bool initial) void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target, bool initial)
{ {
// we parse the groups iteratively instead of recursively // we parse the groups iteratively instead of recursively
// breadcrubs acts like a makeshift stack // breadcrubs acts like a makeshift stack
// first pair entry stores the current element of that level // first pair entry stores the current element of that level
// second pair entry the group object from OffsetGroup // second pair entry the group object from OffsetGroup
typedef pair < TiXmlElement *, OffsetGroup * > groupPair; typedef triple< TiXmlElement *, OffsetGroup *, INVAL_TYPE> groupTriple;
vector< groupPair > breadcrumbs; vector< groupTriple > breadcrumbs;
{ {
TiXmlElement* pEntry; TiXmlElement* pEntry;
// we get the <Offsets>, look at the children // we get the <Offsets>, look at the children
pEntry = parent->FirstChildElement(); pEntry = parent->FirstChildElement();
if(!pEntry) if(!pEntry)
return; return;
const char *cstr_invalid = parent->Attribute("valid");
INVAL_TYPE parent_inval = NOT_SET;
if(cstr_invalid)
{
if(strcmp(cstr_invalid,"false") == 0)
parent_inval = IS_INVALID;
else if(strcmp(cstr_invalid,"true") == 0)
parent_inval = IS_VALID;
}
OffsetGroup * currentGroup = reinterpret_cast<OffsetGroup *> (target); OffsetGroup * currentGroup = reinterpret_cast<OffsetGroup *> (target);
breadcrumbs.push_back(groupPair(pEntry,currentGroup)); currentGroup->setInvalid(parent_inval);
breadcrumbs.push_back(groupTriple(pEntry,currentGroup, parent_inval));
} }
// work variables // work variables
OffsetGroup * currentGroup = 0; OffsetGroup * currentGroup = 0;
TiXmlElement * currentElem = 0; TiXmlElement * currentElem = 0;
INVAL_TYPE parent_inval = NOT_SET;
//cerr << "<Offsets>"<< endl; //cerr << "<Offsets>"<< endl;
while(1) while(1)
{ {
// get current work variables // get current work variables
currentElem = breadcrumbs.back().first; currentElem = breadcrumbs.back().first;
currentGroup = breadcrumbs.back().second; currentGroup = breadcrumbs.back().second;
parent_inval = breadcrumbs.back().third;
// we reached the end of the current group? // we reached the end of the current group?
if(!currentElem) if(!currentElem)
@ -144,7 +219,7 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
if(!currentGroup) if(!currentGroup)
{ {
groupPair & gp = breadcrumbs.back(); groupTriple & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement(); gp.first = gp.first->NextSiblingElement();
continue; continue;
} }
@ -152,7 +227,7 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
// skip non-elements // skip non-elements
if (currentElem->Type() != TiXmlNode::ELEMENT) if (currentElem->Type() != TiXmlNode::ELEMENT)
{ {
groupPair & gp = breadcrumbs.back(); groupTriple & gp = breadcrumbs.back();
gp.first = gp.first->NextSiblingElement(); gp.first = gp.first->NextSiblingElement();
continue; continue;
} }
@ -169,18 +244,27 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
// evaluate elements // evaluate elements
const char *cstr_value = currentElem->Attribute("value"); const char *cstr_value = currentElem->Attribute("value");
const char *cstr_invalid = currentElem->Attribute("valid");
INVAL_TYPE child_inval = parent_inval;
if(cstr_invalid)
{
if(strcmp(cstr_invalid,"false") == 0)
child_inval = IS_INVALID;
else if(strcmp(cstr_invalid,"true") == 0)
child_inval = IS_VALID;
}
if(type == "group") if(type == "group")
{ {
// FIXME: possibly use setGroup always, with the initial flag as parameter?
// create or get group // create or get group
OffsetGroup * og; OffsetGroup * og;
if(initial) if(initial)
og = currentGroup->createGroup(cstr_name); og = currentGroup->createGroup(cstr_name);
else else
og = currentGroup->getGroup(cstr_name); og = currentGroup->getGroup(cstr_name);
//cerr << "<group name=\"" << cstr_name << "\">" << endl;
// advance this level to the next element // advance this level to the next element
groupPair & gp = breadcrumbs.back(); groupTriple & gp = breadcrumbs.back();
gp.first = currentElem->NextSiblingElement(); gp.first = currentElem->NextSiblingElement();
if(!og) if(!og)
@ -189,8 +273,9 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
throw Error::MissingMemoryDefinition("group", fullname); throw Error::MissingMemoryDefinition("group", fullname);
} }
// add a new level that will be processed next // add a new level that will be processed in the next step
breadcrumbs.push_back(groupPair(currentElem->FirstChildElement(), og)); breadcrumbs.push_back(groupTriple(currentElem->FirstChildElement(), og, child_inval));
og->setInvalid(child_inval);
continue; continue;
} }
else if(type == "address") else if(type == "address")
@ -201,7 +286,7 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
} }
else if(cstr_value) else if(cstr_value)
{ {
currentGroup->setAddress(cstr_name, cstr_value); currentGroup->setAddress(cstr_name, cstr_value, child_inval);
} }
else else
{ {
@ -216,7 +301,7 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
} }
else if(cstr_value) else if(cstr_value)
{ {
currentGroup->setOffset(cstr_name, cstr_value); currentGroup->setOffset(cstr_name, cstr_value, child_inval);
} }
else else
{ {
@ -231,7 +316,7 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
} }
else if(cstr_value) else if(cstr_value)
{ {
currentGroup->setString(cstr_name, cstr_value); currentGroup->setString(cstr_name, cstr_value, child_inval);
} }
else else
{ {
@ -246,7 +331,7 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
} }
else if(cstr_value) else if(cstr_value)
{ {
currentGroup->setHexValue(cstr_name, cstr_value); currentGroup->setHexValue(cstr_name, cstr_value, child_inval);
} }
else else
{ {
@ -255,7 +340,7 @@ void VersionInfoFactory::ParseOffsets(TiXmlElement * parent, VersionInfo* target
} }
// advance to next element // advance to next element
groupPair & gp = breadcrumbs.back(); groupTriple & gp = breadcrumbs.back();
gp.first = currentElem->NextSiblingElement(); gp.first = currentElem->NextSiblingElement();
continue; continue;
} }

@ -39,6 +39,7 @@ namespace DFHack
* the whole array of DFHack exceptions from the rest * the whole array of DFHack exceptions from the rest
*/ */
class DFHACK_EXPORT All : public std::exception{}; class DFHACK_EXPORT All : public std::exception{};
class DFHACK_EXPORT AllMemdef : public All{};
class DFHACK_EXPORT NoProcess : public All class DFHACK_EXPORT NoProcess : public All
{ {
public: public:
@ -80,7 +81,7 @@ namespace DFHack
}; };
// a call to DFHack::mem_info::get* failed // a call to DFHack::mem_info::get* failed
class DFHACK_EXPORT MissingMemoryDefinition : public All class DFHACK_EXPORT MissingMemoryDefinition : public AllMemdef
{ {
public: public:
MissingMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key) MissingMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
@ -113,7 +114,7 @@ namespace DFHack
}; };
// a call to DFHack::mem_info::get* failed // a call to DFHack::mem_info::get* failed
class DFHACK_EXPORT UnsetMemoryDefinition : public All class DFHACK_EXPORT UnsetMemoryDefinition : public AllMemdef
{ {
public: public:
UnsetMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key) UnsetMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
@ -145,7 +146,41 @@ namespace DFHack
} }
}; };
// Syntax errors and whatnot, the xml cant be read // a call to DFHack::mem_info::get* failed
class DFHACK_EXPORT InvalidMemoryDefinition : public AllMemdef
{
public:
InvalidMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
{
std::stringstream s;
s << "memory object is INVALID: type " << type << " key " << key;
full = s.str();
}
// Used by functios using integer keys, such as getTrait
InvalidMemoryDefinition(const char* _type, uint32_t _key) : type(_type)
{
std::stringstream s1;
s1 << _key;
key = s1.str();
std::stringstream s;
s << "memory object is INVALID: type " << type << " key " << key;
full = s.str();
}
virtual ~InvalidMemoryDefinition() throw(){};
std::string full;
const std::string type;
std::string key;
virtual const char* what() const throw()
{
return full.c_str();
}
};
// Syntax errors and whatnot, the xml can't be read
class DFHACK_EXPORT MemoryXmlParse : public All class DFHACK_EXPORT MemoryXmlParse : public All
{ {
public: public:
@ -157,13 +192,11 @@ namespace DFHack
full = s.str(); full = s.str();
} }
std::string full; std::string full;
const std::string desc; const std::string desc;
const int id; const int id;
const int row; const int row;
const int col; const int col;
virtual ~MemoryXmlParse() throw(){}; virtual ~MemoryXmlParse() throw(){};
virtual const char* what() const throw() virtual const char* what() const throw()

@ -41,6 +41,13 @@ namespace DFHack
class VersionInfoPrivate; class VersionInfoPrivate;
class OffsetGroupPrivate; class OffsetGroupPrivate;
enum INVAL_TYPE
{
NOT_SET,
IS_INVALID,
IS_VALID
};
/* /*
* Offset Group * Offset Group
*/ */
@ -68,14 +75,15 @@ namespace DFHack
std::string getString (const std::string & key); std::string getString (const std::string & key);
OffsetGroup * getGroup ( const std::string & name ); OffsetGroup * getGroup ( const std::string & name );
void setOffset (const std::string & key, const std::string & value); void setOffset (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setAddress (const std::string & key, const std::string & value); void setAddress (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setHexValue (const std::string & key, const std::string & value); void setHexValue (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
void setString (const std::string & key, const std::string & value); void setString (const std::string& key, const std::string& value, const DFHack::INVAL_TYPE inval = IS_VALID);
std::string PrintOffsets(int indentation); std::string PrintOffsets(int indentation);
std::string getName(); std::string getName();
std::string getFullName(); std::string getFullName();
OffsetGroup * getParent(); OffsetGroup * getParent();
void setInvalid(INVAL_TYPE arg1);
}; };
/* /*

@ -85,9 +85,9 @@ Buildings::Buildings(DFContextShared * d_)
mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id); mem->resolveClassnameToClassID("building_custom_workshop", d->custom_workshop_id);
d->hasCustomWorkshops = true; d->hasCustomWorkshops = true;
} }
catch(DFHack::Error::UnsetMemoryDefinition &e) catch(DFHack::Error::AllMemdef &e)
{ {
cerr << "Custom workshops not available. Unset Memory Definition: " << e.what() << endl; cerr << "Custom workshops not available. Memory Definition: " << e.what() << endl;
} }
d->Inited = true; d->Inited = true;
} }

@ -306,7 +306,7 @@ void printCreature(DFHack::Context * DF, const DFHack::t_creature & creature)
{ {
cout << mem->getSkill(creature.defaultSoul.skills[i].id) << ": " << creature.defaultSoul.skills[i].rating; cout << mem->getSkill(creature.defaultSoul.skills[i].id) << ": " << creature.defaultSoul.skills[i].rating;
} }
catch(DFHack::Error::MissingMemoryDefinition &e) catch(DFHack::Error::AllMemdef &e)
{ {
cout << "Unknown skill! : " << creature.defaultSoul.skills[i].id <<", rating: " << creature.defaultSoul.skills[i].rating << endl; cout << "Unknown skill! : " << creature.defaultSoul.skills[i].id <<", rating: " << creature.defaultSoul.skills[i].rating << endl;
cout << e.what() << endl; cout << e.what() << endl;

@ -449,7 +449,7 @@ start:
uint32_t nickname = mem->getOffset("creature_name") + mem->getOffset("name_nickname"); uint32_t nickname = mem->getOffset("creature_name") + mem->getOffset("name_nickname");
p->writeSTLString(toChange.origin+nickname,changeString); p->writeSTLString(toChange.origin+nickname,changeString);
} }
catch (DFHack::Error::MissingMemoryDefinition&) catch (DFHack::Error::AllMemdef&)
{ {
cerr << "Writing creature nicknames unsupported in this version!" << endl; cerr << "Writing creature nicknames unsupported in this version!" << endl;
} }
@ -461,7 +461,7 @@ start:
uint32_t custom_prof = mem->getOffset("creature_custom_profession"); uint32_t custom_prof = mem->getOffset("creature_custom_profession");
p->writeSTLString(toChange.origin+custom_prof,changeString); p->writeSTLString(toChange.origin+custom_prof,changeString);
} }
catch (DFHack::Error::MissingMemoryDefinition&) catch (DFHack::Error::AllMemdef&)
{ {
cerr << "Writing creature custom profession unsupported in this version!" << endl; cerr << "Writing creature custom profession unsupported in this version!" << endl;
} }

@ -39,7 +39,7 @@ int main ()
{ {
item_vec_offset = p->getDescriptor()->getAddress ("items_vector"); item_vec_offset = p->getDescriptor()->getAddress ("items_vector");
} }
catch(DFHack::Error::MissingMemoryDefinition & e) catch(DFHack::Error::AllMemdef & e)
{ {
cerr << "missing offset for the item vector, exiting :(" << endl; cerr << "missing offset for the item vector, exiting :(" << endl;
#ifndef LINUX_BUILD #ifndef LINUX_BUILD