Merge branch 'errorhandling' of git://github.com/mizipzor/dfhack

develop
Petr Mrázek 2010-02-28 04:26:10 +01:00
commit 029f1a6cf8
6 changed files with 265 additions and 195 deletions

@ -9,23 +9,35 @@
using namespace std;
#include <DFTypes.h>
#include <DFHackAPI.h>
#include <DFError.h>
int main (void)
{
time_t start, end;
double time_diff;
DFHack::API DF("Memory.xml");
if(!DF.Attach())
//if(!DF.Attach())
//{
// cerr << "DF not found" << endl;
// return 1;
//}
//if(!DF.Detach())
//{
// cerr << "Can't detach from DF" << endl;
// return 1;
//}
try
{
cerr << "DF not found" << endl;
return 1;
DF.Attach();
DF.Detach();
}
if(!DF.Detach())
catch (DFHack::Error::NoProcess& e)
{
cerr << "Can't detach from DF" << endl;
cerr << e.what() << endl;
return 1;
}
// attach/detach test
cout << "Testing attach/detach" << endl;
time(&start);

@ -2,6 +2,7 @@
SET(PROJECT_HDRS
DFCommonInternal.h
DFError.h
DFHackAPI.h
DFMemInfo.h
DFMemInfoManager.h

@ -85,6 +85,7 @@ namespace DFHack
#include "DFMemInfoManager.h"
#include "DFVector.h"
#include "DFMemInfo.h"
#include "DFError.h"
#include <stdlib.h>
#include "tinyxml/tinyxml.h"

@ -0,0 +1,114 @@
/*
www.sourceforge.net/projects/dfhack
Copyright (c) 2009 Petr Mrázek (peterix), Kenneth Ferland (Impaler[WrG]), dorf
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef ERROR_H_INCLUDED
#define ERROR_H_INCLUDED
#include <string>
#include <sstream>
#include <exception>
namespace DFHack
{
namespace Error
{
class NoProcess : public exception
{
public:
virtual const char* what() const throw()
{
return "couldn't find a suitable process";
}
};
class CantAttach : public exception
{
public:
virtual const char* what() const throw()
{
return "couldn't attach to process";
}
};
class NoMapLoaded : public exception
{
public:
virtual const char* what() const throw()
{
return "no map has been loaded in the dwarf fortress process";
}
};
class BadMapDimensions : public exception
{
public:
BadMapDimensions(uint32_t& _x, uint32_t& _y) : x(_x), y(_y) {}
const uint32_t x;
const uint32_t y;
virtual const char* what() const throw()
{
return "both x and y needs to be between 0 and 48";
}
};
// a call to DFHack::mem_info::get* failed
class MissingMemoryDefinition : public exception
{
public:
MissingMemoryDefinition(const char* _type, const char* _key) : type(_type), key(_key) {}
// Used by functios using integer keys, such as getTrait
MissingMemoryDefinition(const char* _type, uint32_t _key) : type(_type)
{
// FIXME fancy hex printer goes here
std::stringstream s;
s << _key;
key = s.str();
}
// (perhaps it should be an enum, but this is intended for easy printing/logging)
// type can be any of the following:
//
// address
// offset
// hexvalue
// string
// profession
// job
// skill
// trait
// traitname
// labor
const std::string type;
std::string key;
virtual const char* what() const throw()
{
return "memory definition missing";
}
};
}
}
#endif // ERROR_H_INCLUDED

@ -183,12 +183,13 @@ bool API::InitMap()
d->offset_descriptor->resolveClassnameToVPtr("block_square_event_mineral",d->vein_mineral_vptr);
// get the map pointer
uint32_t x_array_loc = g_pProcess->readDWord (map_offset);
uint32_t x_array_loc = g_pProcess->readDWord (map_offset);
//FIXME: very inadequate
if (!x_array_loc)
{
throw Error::NoMapLoaded();
// bad stuffz happend
return false;
//return false;
}
uint32_t mx, my, mz;
@ -200,7 +201,8 @@ bool API::InitMap()
// test for wrong map dimensions
if (mx == 0 || mx > 48 || my == 0 || my > 48 || mz == 0)
{
return false;
throw Error::BadMapDimensions(mx, my);
//return false;
}
// alloc array for pointers to all blocks
@ -656,19 +658,6 @@ bool API::ReadGeology (vector < vector <uint16_t> >& assign)
uint32_t regionX, regionY, regionZ;
uint16_t worldSizeX, worldSizeY;
// check if we have 'em all
if (
! (
region_x_offset && region_y_offset && region_z_offset && world_size_x && world_size_y
&& world_offset && world_regions_offset && world_geoblocks_offset && region_size
&& region_geo_index_offset && geolayer_geoblock_offset
)
)
{
// fail if we don't have them
return false;
}
// read position of the region inside DF world
g_pProcess->readDWord (region_x_offset, regionX);
g_pProcess->readDWord (region_y_offset, regionY);
@ -737,19 +726,10 @@ bool API::ReadGeology (vector < vector <uint16_t> >& assign)
bool API::InitReadBuildings ( uint32_t& numbuildings )
{
int buildings = d->offset_descriptor->getAddress ("buildings");
if(buildings)
{
d->buildingsInited = true;
d->p_bld = new DfVector (d->p->readVector (buildings, 4));
numbuildings = d->p_bld->getSize();
return true;
}
else
{
d->buildingsInited = false;
numbuildings = 0;
return false;
}
d->buildingsInited = true;
d->p_bld = new DfVector (d->p->readVector (buildings, 4));
numbuildings = d->p_bld->getSize();
return true;
}
@ -800,19 +780,10 @@ void API::FinishReadBuildings()
bool API::InitReadConstructions(uint32_t & numconstructions)
{
int constructions = d->offset_descriptor->getAddress ("constructions");
if(constructions)
{
d->p_cons = new DfVector (d->p->readVector (constructions, 4));
d->constructionsInited = true;
numconstructions = d->p_cons->getSize();
return true;
}
else
{
d->constructionsInited = false;
numconstructions = 0;
return false;
}
d->p_cons = new DfVector (d->p->readVector (constructions, 4));
d->constructionsInited = true;
numconstructions = d->p_cons->getSize();
return true;
}
@ -850,20 +821,21 @@ void API::FinishReadConstructions()
bool API::InitReadVegetation(uint32_t & numplants)
{
int vegetation = d->offset_descriptor->getAddress ("vegetation");
d->tree_offset = d->offset_descriptor->getOffset ("tree_desc_offset");
if(vegetation && d->tree_offset)
try
{
int vegetation = d->offset_descriptor->getAddress ("vegetation");
d->tree_offset = d->offset_descriptor->getOffset ("tree_desc_offset");
d->vegetationInited = true;
d->p_veg = new DfVector (d->p->readVector (vegetation, 4));
numplants = d->p_veg->getSize();
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
d->vegetationInited = false;
numplants = 0;
return false;
throw;
}
}
@ -895,95 +867,69 @@ void API::FinishReadVegetation()
bool API::InitReadCreatures( uint32_t &numcreatures )
{
memory_info * minfo = d->offset_descriptor;
int creatures = d->offset_descriptor->getAddress ("creatures");
d->creature_pos_offset = minfo->getOffset ("creature_position");
d->creature_type_offset = minfo->getOffset ("creature_race");
d->creature_flags1_offset = minfo->getOffset ("creature_flags1");
d->creature_flags2_offset = minfo->getOffset ("creature_flags2");
d->creature_first_name_offset = minfo->getOffset ("creature_first_name");
d->creature_nick_name_offset = minfo->getOffset ("creature_nick_name");
d->creature_last_name_offset = minfo->getOffset ("creature_last_name");
d->creature_custom_profession_offset = minfo->getOffset ("creature_custom_profession");
d->creature_profession_offset = minfo->getOffset ("creature_profession");
d->creature_sex_offset = minfo->getOffset ("creature_sex");
d->creature_id_offset = minfo->getOffset ("creature_id");
d->creature_squad_name_offset = minfo->getOffset ("creature_squad_name");
d->creature_squad_leader_id_offset = minfo->getOffset ("creature_squad_leader_id");
d->creature_money_offset = minfo->getOffset ("creature_money");
d->creature_current_job_offset = minfo->getOffset ("creature_current_job");
d->creature_current_job_id_offset = minfo->getOffset ("current_job_id");
d->creature_strength_offset = minfo->getOffset ("creature_strength");
d->creature_agility_offset = minfo->getOffset ("creature_agility");
d->creature_toughness_offset = minfo->getOffset ("creature_toughness");
d->creature_skills_offset = minfo->getOffset ("creature_skills");
d->creature_labors_offset = minfo->getOffset ("creature_labors");
d->creature_happiness_offset = minfo->getOffset ("creature_happiness");
d->creature_traits_offset = minfo->getOffset ("creature_traits");
d->creature_likes_offset = minfo->getOffset("creature_likes");
if (creatures
&& d->creature_pos_offset
&& d->creature_type_offset
&& d->creature_flags1_offset
&& d->creature_flags2_offset
&& d->creature_nick_name_offset
&& d->creature_custom_profession_offset
&& d->creature_profession_offset
&& d->creature_sex_offset
&& d->creature_id_offset
&& d->creature_squad_name_offset
&& d->creature_squad_leader_id_offset
&& d->creature_money_offset
&& d->creature_current_job_offset
&& d->creature_strength_offset
&& d->creature_agility_offset
&& d->creature_toughness_offset
&& d->creature_skills_offset
&& d->creature_labors_offset
&& d->creature_happiness_offset
&& d->creature_traits_offset
// && d->creature_likes_offset
)
{
try
{
memory_info * minfo = d->offset_descriptor;
int creatures = d->offset_descriptor->getAddress ("creatures");
d->creature_pos_offset = minfo->getOffset ("creature_position");
d->creature_type_offset = minfo->getOffset ("creature_race");
d->creature_flags1_offset = minfo->getOffset ("creature_flags1");
d->creature_flags2_offset = minfo->getOffset ("creature_flags2");
d->creature_first_name_offset = minfo->getOffset ("creature_first_name");
d->creature_nick_name_offset = minfo->getOffset ("creature_nick_name");
d->creature_last_name_offset = minfo->getOffset ("creature_last_name");
d->creature_custom_profession_offset = minfo->getOffset ("creature_custom_profession");
d->creature_profession_offset = minfo->getOffset ("creature_profession");
d->creature_sex_offset = minfo->getOffset ("creature_sex");
d->creature_id_offset = minfo->getOffset ("creature_id");
d->creature_squad_name_offset = minfo->getOffset ("creature_squad_name");
d->creature_squad_leader_id_offset = minfo->getOffset ("creature_squad_leader_id");
d->creature_money_offset = minfo->getOffset ("creature_money");
d->creature_current_job_offset = minfo->getOffset ("creature_current_job");
d->creature_current_job_id_offset = minfo->getOffset ("current_job_id");
d->creature_strength_offset = minfo->getOffset ("creature_strength");
d->creature_agility_offset = minfo->getOffset ("creature_agility");
d->creature_toughness_offset = minfo->getOffset ("creature_toughness");
d->creature_skills_offset = minfo->getOffset ("creature_skills");
d->creature_labors_offset = minfo->getOffset ("creature_labors");
d->creature_happiness_offset = minfo->getOffset ("creature_happiness");
d->creature_traits_offset = minfo->getOffset ("creature_traits");
d->creature_likes_offset = minfo->getOffset("creature_likes");
d->p_cre = new DfVector (d->p->readVector (creatures, 4));
//InitReadNameTables();
d->creaturesInited = true;
numcreatures = d->p_cre->getSize();
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
d->creaturesInited = false;
numcreatures = 0;
return false;
throw;
}
}
bool API::InitReadNotes( uint32_t &numnotes )
{
memory_info * minfo = d->offset_descriptor;
int notes = minfo->getAddress ("notes");
d->note_foreground_offset = minfo->getOffset ("note_foreground");
d->note_background_offset = minfo->getOffset ("note_background");
d->note_name_offset = minfo->getOffset ("note_name");
d->note_xyz_offset = minfo->getOffset ("note_xyz");
if (notes
&& d->note_foreground_offset
&& d->note_background_offset
&& d->note_name_offset
&& d->note_xyz_offset
)
try
{
memory_info * minfo = d->offset_descriptor;
int notes = minfo->getAddress ("notes");
d->note_foreground_offset = minfo->getOffset ("note_foreground");
d->note_background_offset = minfo->getOffset ("note_background");
d->note_name_offset = minfo->getOffset ("note_name");
d->note_xyz_offset = minfo->getOffset ("note_xyz");
d->p_notes = new DfVector (d->p->readVector (notes, 4));
d->notesInited = true;
numnotes = d->p_notes->getSize();
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
d->notesInited = false;
numnotes = 0;
return false;
throw;
}
}
bool API::ReadNote (const int32_t index, t_note & note)
@ -1000,30 +946,26 @@ bool API::ReadNote (const int32_t index, t_note & note)
}
bool API::InitReadSettlements( uint32_t & numsettlements )
{
memory_info * minfo = d->offset_descriptor;
int allSettlements = minfo->getAddress ("settlements");
int currentSettlement = minfo->getAddress("settlement_current");
d->settlement_name_offset = minfo->getOffset ("settlement_name");
d->settlement_world_xy_offset = minfo->getOffset ("settlement_world_xy");
d->settlement_local_xy_offset = minfo->getOffset ("settlement_local_xy");
if (allSettlements && currentSettlement
&& d->settlement_name_offset
&& d->settlement_world_xy_offset
&& d->settlement_local_xy_offset
)
try
{
memory_info * minfo = d->offset_descriptor;
int allSettlements = minfo->getAddress ("settlements");
int currentSettlement = minfo->getAddress("settlement_current");
d->settlement_name_offset = minfo->getOffset ("settlement_name");
d->settlement_world_xy_offset = minfo->getOffset ("settlement_world_xy");
d->settlement_local_xy_offset = minfo->getOffset ("settlement_local_xy");
d->p_settlements = new DfVector (d->p->readVector (allSettlements, 4));
d->p_current_settlement = new DfVector(d->p->readVector(currentSettlement,4));
d->settlementsInited = true;
numsettlements = d->p_settlements->getSize();
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
d->settlementsInited = false;
numsettlements = 0;
return false;
throw;
}
}
bool API::ReadSettlement(const int32_t index, t_settlement & settlement)
@ -1039,6 +981,7 @@ bool API::ReadSettlement(const int32_t index, t_settlement & settlement)
g_pProcess->read(temp + d->settlement_local_xy_offset, 4 * sizeof(int16_t), (uint8_t *) &settlement.local_x1);
return true;
}
bool API::ReadCurrentSettlement(t_settlement & settlement)
{
if(!d->settlementsInited) return false;
@ -1070,21 +1013,21 @@ void API::FinishReadSettlements()
bool API::InitReadHotkeys( )
{
memory_info * minfo = d->offset_descriptor;
d->hotkey_start = minfo->getAddress("hotkey_start");
d->hotkey_mode_offset = minfo->getOffset ("hotkey_mode");
d->hotkey_xyz_offset = minfo->getOffset("hotkey_xyz");
d->hotkey_size = minfo->getHexValue("hotkey_size");
if (d->hotkey_start && d->hotkey_mode_offset && d->hotkey_size)
try
{
memory_info * minfo = d->offset_descriptor;
d->hotkey_start = minfo->getAddress("hotkey_start");
d->hotkey_mode_offset = minfo->getOffset ("hotkey_mode");
d->hotkey_xyz_offset = minfo->getOffset("hotkey_xyz");
d->hotkey_size = minfo->getHexValue("hotkey_size");
d->hotkeyInited = true;
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
d->hotkeyInited = false;
return false;
throw;
}
}
bool API::ReadHotkeys(t_hotkey hotkeys[])
@ -1157,6 +1100,7 @@ bool API::getItemIndexesInBox(vector<uint32_t> &indexes,
}
}
}
return true;
}
bool API::ReadCreature (const int32_t index, t_creature & furball)
@ -1241,12 +1185,12 @@ void API::WriteLabors(const uint32_t index, uint8_t labors[NUM_CREATURE_LABORS])
bool API::InitReadNameTables (map< string, vector<string> > & nameTable)
{
int genericAddress = d->offset_descriptor->getAddress ("language_vector");
int transAddress = d->offset_descriptor->getAddress ("translation_vector");
int word_table_offset = d->offset_descriptor->getOffset ("word_table");
if(genericAddress && transAddress && word_table_offset)
try
{
int genericAddress = d->offset_descriptor->getAddress ("language_vector");
int transAddress = d->offset_descriptor->getAddress ("translation_vector");
int word_table_offset = d->offset_descriptor->getOffset ("word_table");
DfVector genericVec (d->p->readVector (genericAddress, 4));
DfVector transVec (d->p->readVector (transAddress, 4));
@ -1272,10 +1216,10 @@ bool API::InitReadNameTables (map< string, vector<string> > & nameTable)
d->nameTablesInited = true;
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
d->nameTablesInited = false;
return false;
throw;
}
}
@ -1386,14 +1330,16 @@ bool API::Attach()
// find a process (ProcessManager can find multiple when used properly)
if (!d->pm->findProcessess())
{
cerr << "couldn't find a suitable process" << endl;
return false;
throw Error::NoProcess();
//cerr << "couldn't find a suitable process" << endl;
//return false;
}
d->p = (*d->pm) [0];
if (!d->p->attach())
{
cerr << "couldn't attach to process" << endl;
return false; // couldn't attach to process, no go
throw Error::CantAttach();
//cerr << "couldn't attach to process" << endl;
//return false; // couldn't attach to process, no go
}
d->offset_descriptor = d->p->getDescriptor();
// process is attached, everything went just fine... hopefully
@ -1456,40 +1402,39 @@ void API::WriteRaw (const uint32_t offset, const uint32_t size, uint8_t *source)
bool API::InitViewAndCursor()
{
d->window_x_offset = d->offset_descriptor->getAddress ("window_x");
d->window_y_offset = d->offset_descriptor->getAddress ("window_y");
d->window_z_offset = d->offset_descriptor->getAddress ("window_z");
d->cursor_xyz_offset = d->offset_descriptor->getAddress ("cursor_xyz");
d->current_cursor_creature_offset = d->offset_descriptor->getAddress ("current_cursor_creature");
d->current_menu_state_offset = d->offset_descriptor->getAddress("current_menu_state");
d->pause_state_offset = d->offset_descriptor->getAddress ("pause_state");
d->view_screen_offset = d->offset_descriptor->getAddress ("view_screen");
if (d->window_x_offset && d->window_y_offset && d->window_z_offset &&
d->current_cursor_creature_offset && d->current_menu_state_offset &&
d->pause_state_offset && d->view_screen_offset)
try
{
d->window_x_offset = d->offset_descriptor->getAddress ("window_x");
d->window_y_offset = d->offset_descriptor->getAddress ("window_y");
d->window_z_offset = d->offset_descriptor->getAddress ("window_z");
d->cursor_xyz_offset = d->offset_descriptor->getAddress ("cursor_xyz");
d->current_cursor_creature_offset = d->offset_descriptor->getAddress ("current_cursor_creature");
d->current_menu_state_offset = d->offset_descriptor->getAddress("current_menu_state");
d->pause_state_offset = d->offset_descriptor->getAddress ("pause_state");
d->view_screen_offset = d->offset_descriptor->getAddress ("view_screen");
d->cursorWindowInited = true;
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
return false;
throw;
}
}
bool API::InitViewSize()
{
d->window_dims_offset = d->offset_descriptor->getAddress ("window_dims");
if (d->window_dims_offset)
try
{
d->window_dims_offset = d->offset_descriptor->getAddress ("window_dims");
d->viewSizeInited = true;
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
return false;
throw;
}
}
@ -1567,21 +1512,21 @@ DFWindow * API::getWindow()
bool API::InitReadItems(uint32_t & numitems)
{
int items = d->offset_descriptor->getAddress ("items");
d->item_material_offset = d->offset_descriptor->getOffset ("item_materials");
if(items && d->item_material_offset)
try
{
int items = d->offset_descriptor->getAddress ("items");
d->item_material_offset = d->offset_descriptor->getOffset ("item_materials");
d->p_itm = new DfVector (d->p->readVector (items, 4));
d->itemsInited = true;
numitems = d->p_itm->getSize();
return true;
}
else
catch (Error::MissingMemoryDefinition&)
{
d->itemsInited = false;
numitems = 0;
return false;
throw;
}
}
bool API::ReadItem (const uint32_t index, t_item & item)

@ -450,7 +450,7 @@ uint32_t memory_info::getAddress (const char *key)
{
return (*iter).second;
}
return 0;
throw Error::MissingMemoryDefinition("address", key);
}
@ -462,7 +462,7 @@ uint32_t memory_info::getOffset (const char *key)
{
return (*iter).second;
}
return 0;
throw Error::MissingMemoryDefinition("offset", key);
}
// Get named numerical value
@ -473,7 +473,7 @@ uint32_t memory_info::getHexValue (const char *key)
{
return (*iter).second;
}
return 0;
throw Error::MissingMemoryDefinition("hexvalue", key);
}
@ -486,7 +486,7 @@ uint32_t memory_info::getAddress (const string &key)
{
return (*iter).second;
}
return 0;
throw Error::MissingMemoryDefinition("address", key.c_str());
}
@ -498,7 +498,7 @@ uint32_t memory_info::getOffset (const string &key)
{
return (*iter).second;
}
return 0;
throw Error::MissingMemoryDefinition("offset", key.c_str());
}
// Get named numerical value
@ -509,7 +509,7 @@ uint32_t memory_info::getHexValue (const string &key)
{
return (*iter).second;
}
return 0;
throw Error::MissingMemoryDefinition("hexvalue", key.c_str());
}
// Get named string
@ -520,7 +520,7 @@ std::string memory_info::getString (const string &key)
{
return (*iter).second;
}
return string("");
throw Error::MissingMemoryDefinition("string", key.c_str());
}
// Get Profession
@ -530,10 +530,7 @@ string memory_info::getProfession (const uint32_t key) const
{
return d->professions[key];
}
else
{
return string("");
}
throw Error::MissingMemoryDefinition("profession", key);
}
// Get Job
@ -543,7 +540,7 @@ string memory_info::getJob (const uint32_t key) const
{
return d->jobs[key];
}
return string("Job Does Not Exist");
throw Error::MissingMemoryDefinition("job", key);
}
string memory_info::getSkill (const uint32_t key) const
@ -552,7 +549,7 @@ string memory_info::getSkill (const uint32_t key) const
{
return d->skills[key];
}
return string("Skill is not Defined");
throw Error::MissingMemoryDefinition("skill", key);
}
// FIXME: ugly hack that needs to die
@ -585,7 +582,7 @@ string memory_info::getTrait (const uint32_t traitIdx, const uint32_t traitValue
else
return d->traits[traitIdx][0];
}
return string("Trait is not Defined");
throw Error::MissingMemoryDefinition("trait", traitIdx);
}
string memory_info::getTraitName(const uint32_t traitIdx) const
@ -594,7 +591,7 @@ string memory_info::getTraitName(const uint32_t traitIdx) const
{
return d->traits[traitIdx][d->traits[traitIdx].size()-1];
}
return string("Trait is not Defined");
throw Error::MissingMemoryDefinition("traitname", traitIdx);
}
string memory_info::getLabor (const uint32_t laborIdx)
@ -603,7 +600,7 @@ string memory_info::getLabor (const uint32_t laborIdx)
{
return d->labors[laborIdx];
}
return string("");
throw Error::MissingMemoryDefinition("labor", laborIdx);
}
// Reset everything