develop
Warmist 2012-03-24 16:49:17 +02:00
commit b56917f91b
21 changed files with 1615 additions and 1486 deletions

@ -1,4 +1,4 @@
PROJECT ( lua C )
PROJECT ( lua CXX )
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# TODO: make this RelWithDebInfo only
@ -77,9 +77,12 @@ src/lundump.c
src/lvm.c
src/lzio.c
)
# compile with C++ compiler
set_source_files_properties(${SRC_LIBLUA} PROPERTIES LANGUAGE CXX)
# append headers to sources to make them show up in MSVC GUI
LIST(APPEND SRC_LIBLUA ${HDR_LIBLUA})
ADD_LIBRARY ( lua SHARED EXCLUDE_FROM_ALL ${SRC_LIBLUA} )
ADD_LIBRARY ( lua SHARED ${SRC_LIBLUA} )
TARGET_LINK_LIBRARIES ( lua ${LIBS})
install(TARGETS lua

@ -27,6 +27,8 @@ include/Console.h
include/Core.h
include/ColorText.h
include/DataDefs.h
include/DataIdentity.h
include/LuaWrapper.h
include/Error.h
include/Export.h
include/Hooks.h
@ -41,7 +43,6 @@ include/TileTypes.h
include/Types.h
include/VersionInfo.h
include/VersionInfoFactory.h
include/Virtual.h
include/RemoteClient.h
include/RemoteServer.h
include/RemoteTools.h
@ -56,6 +57,7 @@ Core.cpp
ColorText.cpp
DataDefs.cpp
LuaWrapper.cpp
LuaTypes.cpp
DataStatics.cpp
DataStaticsCtor.cpp
DataStaticsFields.cpp
@ -63,7 +65,6 @@ MiscUtils.cpp
PluginManager.cpp
TileTypes.cpp
VersionInfoFactory.cpp
Virtual.cpp
RemoteClient.cpp
RemoteServer.cpp
RemoteTools.cpp

@ -164,6 +164,9 @@ void struct_identity::doInit(Core *core)
bool struct_identity::is_subclass(struct_identity *actual)
{
if (!has_children && actual != this)
return false;
for (; actual; actual = actual->getParent())
if (actual == this) return true;

@ -0,0 +1,979 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
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.
*/
#include "Internal.h"
#include <string>
#include <vector>
#include <map>
#include "MemAccess.h"
#include "Core.h"
#include "VersionInfo.h"
#include "tinythread.h"
// must be last due to MS stupidity
#include "DataDefs.h"
#include "DataIdentity.h"
#include "LuaWrapper.h"
#include "MiscUtils.h"
#include <lua.h>
#include <lauxlib.h>
using namespace DFHack;
using namespace DFHack::LuaWrapper;
/**************************************
* Identity object read/write methods *
**************************************/
void constructed_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
push_object_internal(state, this, ptr);
}
void constructed_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
field_error(state, fname_idx, "complex object", "write");
}
void enum_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
base_type->lua_read(state, fname_idx, ptr);
}
void enum_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
base_type->lua_write(state, fname_idx, ptr, val_index);
}
void df::number_identity_base::lua_read(lua_State *state, int fname_idx, void *ptr)
{
lua_pushnumber(state, read(ptr));
}
void df::number_identity_base::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
if (!lua_isnumber(state, val_index))
field_error(state, fname_idx, "number expected", "write");
write(ptr, lua_tonumber(state, val_index));
}
void df::bool_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
lua_pushboolean(state, *(bool*)ptr);
}
void df::bool_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
char *pb = (char*)ptr;
if (lua_isboolean(state, val_index) || lua_isnil(state, val_index))
*pb = lua_toboolean(state, val_index);
else if (lua_isnumber(state, val_index))
*pb = lua_tointeger(state, val_index);
else
field_error(state, fname_idx, "boolean or number expected", "write");
}
void df::stl_string_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
auto pstr = (std::string*)ptr;
lua_pushlstring(state, pstr->data(), pstr->size());
}
void df::stl_string_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
size_t size;
const char *bytes = lua_tolstring(state, val_index, &size);
if (!bytes)
field_error(state, fname_idx, "string expected", "write");
*(std::string*)ptr = std::string(bytes, size);
}
void df::pointer_identity::lua_read(lua_State *state, int fname_idx, void *ptr, type_identity *target)
{
push_object_internal(state, target, *(void**)ptr);
}
void df::pointer_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
lua_read(state, fname_idx, ptr, target);
}
void df::pointer_identity::lua_write(lua_State *state, int fname_idx, void *ptr,
type_identity *target, int val_index)
{
auto pptr = (void**)ptr;
if (lua_isnil(state, val_index))
*pptr = NULL;
else
{
void *nval = get_object_internal(state, target, val_index, false);
if (nval)
*pptr = nval;
else
field_error(state, fname_idx, "incompatible pointer type", "write");
}
}
void df::pointer_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
lua_write(state, fname_idx, ptr, target, val_index);
}
int container_identity::lua_item_count(lua_State *state, void *ptr, CountMode mode)
{
if (lua_isnumber(state, UPVAL_ITEM_COUNT))
return lua_tointeger(state, UPVAL_ITEM_COUNT);
else
return item_count(ptr, mode);
}
void container_identity::lua_item_reference(lua_State *state, int fname_idx, void *ptr, int idx)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
void *pitem = item_pointer(id, ptr, idx);
push_object_internal(state, id, pitem);
}
void container_identity::lua_item_read(lua_State *state, int fname_idx, void *ptr, int idx)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
void *pitem = item_pointer(id, ptr, idx);
id->lua_read(state, fname_idx, pitem);
}
void container_identity::lua_item_write(lua_State *state, int fname_idx, void *ptr, int idx, int val_index)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
void *pitem = item_pointer(id, ptr, idx);
id->lua_write(state, fname_idx, pitem, val_index);
}
bool container_identity::lua_insert(lua_State *state, int fname_idx, void *ptr, int idx, int val_index)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
char tmp[32];
void *pitem = &tmp;
if (id->isPrimitive())
{
if (id->isConstructed())
luaL_error(state, "Temporaries of type %s not supported", id->getFullName().c_str());
assert(id->byte_size() <= sizeof(tmp));
id->lua_write(state, fname_idx, pitem, val_index);
}
else
{
pitem = get_object_internal(state, id, val_index, false);
if (!pitem)
field_error(state, fname_idx, "incompatible object type", "insert");
}
return insert(ptr, idx, pitem);
}
void ptr_container_identity::lua_item_reference(lua_State *state, int fname_idx, void *ptr, int idx)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
void *pitem = item_pointer(id, ptr, idx);
push_adhoc_pointer(state, pitem, id);
}
void ptr_container_identity::lua_item_read(lua_State *state, int fname_idx, void *ptr, int idx)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
void *pitem = item_pointer(&df::identity_traits<void*>::identity, ptr, idx);
df::pointer_identity::lua_read(state, fname_idx, pitem, id);
}
void ptr_container_identity::lua_item_write(lua_State *state, int fname_idx, void *ptr, int idx, int val_index)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
void *pitem = item_pointer(&df::identity_traits<void*>::identity, ptr, idx);
df::pointer_identity::lua_write(state, fname_idx, pitem, id, val_index);
}
bool ptr_container_identity::lua_insert(lua_State *state, int fname_idx, void *ptr, int idx, int val_index)
{
auto id = (type_identity*)lua_touserdata(state, UPVAL_ITEM_ID);
void *pitem = NULL;
df::pointer_identity::lua_write(state, fname_idx, &pitem, id, val_index);
return insert(ptr, idx, pitem);
}
void bit_container_identity::lua_item_reference(lua_State *state, int, void *, int)
{
lua_pushnil(state);
}
void bit_container_identity::lua_item_read(lua_State *state, int fname_idx, void *ptr, int idx)
{
lua_pushboolean(state, get_item(ptr, idx));
}
void bit_container_identity::lua_item_write(lua_State *state, int fname_idx, void *ptr, int idx, int val_index)
{
if (lua_isboolean(state, val_index) || lua_isnil(state, val_index))
set_item(ptr, idx, lua_toboolean(state, val_index));
else if (lua_isnumber(state, val_index))
set_item(ptr, idx, lua_tointeger(state, val_index) != 0);
else
field_error(state, fname_idx, "boolean or number expected", "write");
}
/**
* Resolve the field name in UPVAL_FIELDTABLE, die if not found.
*/
static void lookup_field(lua_State *state, int index, const char *mode)
{
lua_pushvalue(state, index);
lua_gettable(state, UPVAL_FIELDTABLE); // uses metatable with enum keys
if (lua_isnil(state, -1))
field_error(state, index, "not found", mode);
}
static void *find_field(lua_State *state, int index, const char *mode)
{
lookup_field(state, index, mode);
void *p = lua_touserdata(state, -1);
lua_pop(state, 1);
return p;
}
static uint8_t *check_method_call(lua_State *state, int min_args, int max_args)
{
int argc = lua_gettop(state)-1;
if (argc < min_args || argc > max_args)
field_error(state, UPVAL_METHOD_NAME, "wrong argument count", "call");
return get_object_addr(state, 1, UPVAL_METHOD_NAME, "call");
}
static void GetAdHocMetatable(lua_State *state, const struct_field_info *field);
static void read_field(lua_State *state, const struct_field_info *field, void *ptr)
{
switch (field->mode)
{
case struct_field_info::STATIC_STRING:
{
int len = strnlen((char*)ptr, field->count);
lua_pushlstring(state, (char*)ptr, len);
return;
}
case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT:
field->type->lua_read(state, 2, ptr);
return;
case struct_field_info::POINTER:
df::pointer_identity::lua_read(state, 2, ptr, field->type);
return;
case struct_field_info::CONTAINER:
if (!field->eid || !field->type->isContainer() ||
field->eid == ((container_identity*)field->type)->getIndexEnumType())
{
field->type->lua_read(state, 2, ptr);
return;
}
// fallthrough
case struct_field_info::STATIC_ARRAY:
case struct_field_info::STL_VECTOR_PTR:
GetAdHocMetatable(state, field);
push_object_ref(state, ptr);
return;
case struct_field_info::END:
break;
}
lua_pushnil(state);
}
static void field_reference(lua_State *state, const struct_field_info *field, void *ptr)
{
switch (field->mode)
{
case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT:
push_object_internal(state, field->type, ptr);
return;
case struct_field_info::POINTER:
push_adhoc_pointer(state, ptr, field->type);
return;
case struct_field_info::CONTAINER:
read_field(state, field, ptr);
return;
case struct_field_info::STATIC_STRING:
case struct_field_info::STATIC_ARRAY:
case struct_field_info::STL_VECTOR_PTR:
GetAdHocMetatable(state, field);
push_object_ref(state, ptr);
return;
case struct_field_info::END:
break;
}
lua_pushnil(state);
}
static void write_field(lua_State *state, const struct_field_info *field, void *ptr, int value_idx)
{
switch (field->mode)
{
case struct_field_info::STATIC_STRING:
{
size_t size;
const char *str = lua_tolstring(state, value_idx, &size);
if (!str)
field_error(state, 2, "string expected", "write");
memcpy(ptr, str, std::min(size+1, size_t(field->count)));
return;
}
case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT:
case struct_field_info::CONTAINER:
field->type->lua_write(state, 2, ptr, value_idx);
return;
case struct_field_info::POINTER:
df::pointer_identity::lua_write(state, 2, ptr, field->type, value_idx);
case struct_field_info::STATIC_ARRAY:
case struct_field_info::STL_VECTOR_PTR:
field_error(state, 2, "complex object", "write");
case struct_field_info::END:
return;
}
}
/**
* Metamethod: represent a type node as string.
*/
static int meta_type_tostring(lua_State *state)
{
if (!lua_getmetatable(state, 1))
return 0;
lua_getfield(state, -1, "__metatable");
const char *cname = lua_tostring(state, -1);
lua_pushstring(state, stl_sprintf("<type: %s>", cname).c_str());
return 1;
}
/**
* Metamethod: represent a DF object reference as string.
*/
static int meta_ptr_tostring(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 0, "access");
lua_getfield(state, UPVAL_METATABLE, "__metatable");
const char *cname = lua_tostring(state, -1);
lua_pushstring(state, stl_sprintf("<%s: 0x%08x>", cname, (unsigned)ptr).c_str());
return 1;
}
// Resolve the field in the metatable and return
static int get_metafield(lua_State *state)
{
lua_rawget(state, UPVAL_METATABLE);
return 1;
}
/**
* Metamethod: __index for structures.
*/
static int meta_struct_index(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "read");
auto field = (struct_field_info*)find_field(state, 2, "read");
if (!field)
return get_metafield(state);
read_field(state, field, ptr + field->offset);
return 1;
}
/**
* Method: _field for structures.
*/
static int meta_struct_field_reference(lua_State *state)
{
if (lua_gettop(state) != 2)
luaL_error(state, "Usage: object._field(name)");
uint8_t *ptr = get_object_addr(state, 1, 2, "reference");
auto field = (struct_field_info*)find_field(state, 2, "reference");
if (!field)
field_error(state, 2, "builtin property", "reference");
field_reference(state, field, ptr + field->offset);
return 1;
}
/**
* Metamethod: __newindex for structures.
*/
static int meta_struct_newindex(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "write");
auto field = (struct_field_info*)find_field(state, 2, "write");
if (!field)
field_error(state, 2, "builtin property", "write");
write_field(state, field, ptr + field->offset, 3);
return 0;
}
/**
* Metamethod: __index for primitives, i.e. simple object references.
* Fields point to identity, or NULL for metafields.
*/
static int meta_primitive_index(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "read");
auto type = (type_identity*)find_field(state, 2, "read");
if (!type)
return get_metafield(state);
type->lua_read(state, 2, ptr);
return 1;
}
/**
* Metamethod: __newindex for primitives.
*/
static int meta_primitive_newindex(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "write");
auto type = (type_identity*)find_field(state, 2, "write");
if (!type)
field_error(state, 2, "builtin property", "write");
type->lua_write(state, 2, ptr, 3);
return 0;
}
/**
* Metamethod: __len for containers.
*/
static int meta_container_len(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 0, "get length");
auto id = (container_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
int len = id->lua_item_count(state, ptr, container_identity::COUNT_LEN);
lua_pushinteger(state, len);
return 1;
}
/**
* Field lookup for containers:
*
* - Numbers are indices and handled directly.
* - NULL userdata are metafields; push and exit;
*/
static int lookup_container_field(lua_State *state, int field, const char *mode = NULL)
{
if (lua_type(state, field) == LUA_TNUMBER)
return field;
lookup_field(state, field, mode ? mode : "read");
if (lua_isuserdata(state, -1) && !lua_touserdata(state, -1))
{
if (mode)
field_error(state, field, "builtin property", mode);
lua_pop(state, 1);
get_metafield(state);
return 0;
}
return -1;
}
/**
* Index verification: number and in range.
*/
static int check_container_index(lua_State *state, int len,
int fidx, int iidx, const char *mode)
{
if (!lua_isnumber(state, iidx))
field_error(state, fidx, "invalid index", mode);
int idx = lua_tointeger(state, iidx);
if (idx < 0 || (idx >= len && len >= 0))
field_error(state, fidx, "index out of bounds", mode);
return idx;
}
/**
* Metamethod: __index for containers.
*/
static int meta_container_index(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "read");
int iidx = lookup_container_field(state, 2);
if (!iidx)
return 1;
auto id = (container_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
int len = id->lua_item_count(state, ptr, container_identity::COUNT_READ);
int idx = check_container_index(state, len, 2, iidx, "read");
id->lua_item_read(state, 2, ptr, idx);
return 1;
}
/**
* Method: _field for containers.
*/
static int meta_container_field_reference(lua_State *state)
{
if (lua_gettop(state) != 2)
luaL_error(state, "Usage: object._field(index)");
uint8_t *ptr = get_object_addr(state, 1, 2, "reference");
int iidx = lookup_container_field(state, 2, "reference");
auto id = (container_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
int len = id->lua_item_count(state, ptr, container_identity::COUNT_WRITE);
int idx = check_container_index(state, len, 2, iidx, "reference");
id->lua_item_reference(state, 2, ptr, idx);
return 1;
}
/**
* Metamethod: __index for containers.
*/
static int meta_container_newindex(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "write");
int iidx = lookup_container_field(state, 2, "write");
auto id = (container_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
int len = id->lua_item_count(state, ptr, container_identity::COUNT_WRITE);
int idx = check_container_index(state, len, 2, iidx, "write");
id->lua_item_write(state, 2, ptr, idx, 3);
return 0;
}
/**
* Method: resize container
*/
static int method_container_resize(lua_State *state)
{
uint8_t *ptr = check_method_call(state, 1, 1);
auto id = (container_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
int idx = check_container_index(state, -1, UPVAL_METHOD_NAME, 2, "call");
if (!id->resize(ptr, idx))
field_error(state, UPVAL_METHOD_NAME, "not supported", "call");
return 0;
}
/**
* Method: erase item from container
*/
static int method_container_erase(lua_State *state)
{
uint8_t *ptr = check_method_call(state, 1, 1);
auto id = (container_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
int len = id->lua_item_count(state, ptr, container_identity::COUNT_LEN);
int idx = check_container_index(state, len, UPVAL_METHOD_NAME, 2, "call");
if (!id->erase(ptr, idx))
field_error(state, UPVAL_METHOD_NAME, "not supported", "call");
return 0;
}
/**
* Method: insert item into container
*/
static int method_container_insert(lua_State *state)
{
uint8_t *ptr = check_method_call(state, 2, 2);
auto id = (container_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
int len = id->lua_item_count(state, ptr, container_identity::COUNT_LEN);
if (len >= 0) len++;
int idx = check_container_index(state, len, UPVAL_METHOD_NAME, 2, "call");
if (!id->lua_insert(state, UPVAL_METHOD_NAME, ptr, idx, 3))
field_error(state, UPVAL_METHOD_NAME, "not supported", "call");
return 0;
}
/**
* Metamethod: __len for bitfields.
*/
static int meta_bitfield_len(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 0, "get size");
auto id = (bitfield_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
lua_pushinteger(state, id->getNumBits());
return 1;
}
/**
* Metamethod: __index for bitfields.
*/
static int meta_bitfield_index(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "read");
int iidx = lookup_container_field(state, 2);
if (!iidx)
return 1;
auto id = (bitfield_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
// whole
if (lua_isuserdata(state, iidx) && lua_touserdata(state, iidx) == id)
{
size_t intv = 0;
memcpy(&intv, ptr, std::min(sizeof(intv), size_t(id->byte_size())));
lua_pushnumber(state, intv);
return 1;
}
int idx = check_container_index(state, id->getNumBits(), 2, iidx, "read");
int size = id->getBits()[idx].size;
int value = getBitfieldField(ptr, idx, size);
if (size <= 1)
lua_pushboolean(state, value != 0);
else
lua_pushinteger(state, value);
return 1;
}
/**
* Metamethod: __newindex for bitfields.
*/
static int meta_bitfield_newindex(lua_State *state)
{
uint8_t *ptr = get_object_addr(state, 1, 2, "write");
int iidx = lookup_container_field(state, 2, "write");
auto id = (bitfield_identity*)lua_touserdata(state, UPVAL_CONTAINER_ID);
// whole
if (lua_isuserdata(state, iidx) && lua_touserdata(state, iidx) == id)
{
if (!lua_isnumber(state, 3))
field_error(state, 2, "number expected", "write");
size_t intv = (size_t)lua_tonumber(state, 3);
memcpy(ptr, &intv, std::min(sizeof(intv), size_t(id->byte_size())));
return 0;
}
int idx = check_container_index(state, id->getNumBits(), 2, iidx, "write");
int size = id->getBits()[idx].size;
if (lua_isboolean(state, 3) || lua_isnil(state, 3))
setBitfieldField(ptr, idx, size, lua_toboolean(state, 3));
else if (lua_isnumber(state, 3))
setBitfieldField(ptr, idx, size, lua_tointeger(state, 3));
else
field_error(state, 2, "number or boolean expected", "write");
return 0;
}
/**
* Metamethod: __index for df.global
*/
static int meta_global_index(lua_State *state)
{
auto field = (struct_field_info*)find_field(state, 2, "read");
if (!field)
return get_metafield(state);
void *ptr = *(void**)field->offset;
if (!ptr)
field_error(state, 2, "global address not known", "read");
read_field(state, field, ptr);
return 1;
}
/**
* Metamethod: __newindex for df.global
*/
static int meta_global_newindex(lua_State *state)
{
auto field = (struct_field_info*)find_field(state, 2, "write");
if (!field)
field_error(state, 2, "builtin property", "write");
void *ptr = *(void**)field->offset;
if (!ptr)
field_error(state, 2, "global address not known", "write");
write_field(state, field, ptr, 3);
return 0;
}
/**
* Add fields in the array to the UPVAL_FIELDTABLE candidates on the stack.
*/
static void IndexFields(lua_State *state, struct_identity *pstruct)
{
// stack: fieldtable
int base = lua_gettop(state);
for (struct_identity *p = pstruct; p; p = p->getParent())
{
auto fields = p->getFields();
for (; fields; ++fields)
{
if (fields->mode == struct_field_info::END)
break;
lua_pushstring(state,fields->name);
lua_pushlightuserdata(state,(void*)fields);
lua_rawset(state,base);
}
}
}
/**
* Make a struct-style object metatable.
*/
static void MakeFieldMetatable(lua_State *state, struct_identity *pstruct,
lua_CFunction reader, lua_CFunction writer)
{
int base = lua_gettop(state);
MakeMetatable(state, pstruct, "struct"); // meta, fields
IndexFields(state, pstruct);
SetStructMethod(state, base+1, base+2, reader, "__index");
SetStructMethod(state, base+1, base+2, writer, "__newindex");
// returns: [metatable readfields writefields];
}
/**
* Make a primitive-style metatable
*/
static void MakePrimitiveMetatable(lua_State *state, type_identity *type)
{
int base = lua_gettop(state);
MakeMetatable(state, type, "primitive");
SetPtrMethods(state, base+1, base+2);
EnableMetaField(state, base+2, "value", type);
SetStructMethod(state, base+1, base+2, meta_primitive_index, "__index");
SetStructMethod(state, base+1, base+2, meta_primitive_newindex, "__newindex");
}
static void AddContainerMethodFun(lua_State *state, int meta_idx, int field_idx,
lua_CFunction function, const char *name,
type_identity *container, type_identity *item, int count)
{
lua_pushfstring(state, "%s()", name);
SetContainerMethod(state, meta_idx, lua_gettop(state), function, name, container, item, count);
lua_pop(state, 1);
EnableMetaField(state, field_idx, name);
}
/**
* Make a container-style object metatable.
*/
static void MakeContainerMetatable(lua_State *state, container_identity *type,
type_identity *item, int count, type_identity *ienum)
{
int base = lua_gettop(state);
MakeMetatable(state, type, "container");
SetPtrMethods(state, base+1, base+2);
// Update the type name using full info
lua_pushstring(state, type->getFullName(item).c_str());
lua_dup(state);
lua_setfield(state, base+1, "__metatable");
lua_setfield(state, base+1, "_type");
lua_pushlightuserdata(state, item);
lua_setfield(state, base+1, "_field_identity");
if (count >= 0)
{
lua_pushinteger(state, count);
lua_setfield(state, base+1, "_count");
}
SetContainerMethod(state, base+1, base+2, meta_container_len, "__len", type, item, count);
SetContainerMethod(state, base+1, base+2, meta_container_index, "__index", type, item, count);
SetContainerMethod(state, base+1, base+2, meta_container_newindex, "__newindex", type, item, count);
SetContainerMethod(state, base+1, base+2, meta_container_field_reference, "_field", type, item, count);
AddContainerMethodFun(state, base+1, base+2, method_container_resize, "resize", type, item, count);
AddContainerMethodFun(state, base+1, base+2, method_container_erase, "erase", type, item, count);
AddContainerMethodFun(state, base+1, base+2, method_container_insert, "insert", type, item, count);
AttachEnumKeys(state, base+1, base+2, ienum);
}
/*
* Metatable construction identity methods.
*/
void type_identity::build_metatable(lua_State *state)
{
MakePrimitiveMetatable(state, this);
}
void container_identity::build_metatable(lua_State *state)
{
MakeContainerMetatable(state, this, getItemType(), -1, getIndexEnumType());
}
void bitfield_identity::build_metatable(lua_State *state)
{
int base = lua_gettop(state);
MakeMetatable(state, this, "bitfield");
SetPtrMethods(state, base+1, base+2);
SetContainerMethod(state, base+1, base+2, meta_bitfield_len, "__len", this, NULL, -1);
SetContainerMethod(state, base+1, base+2, meta_bitfield_index, "__index", this, NULL, -1);
SetContainerMethod(state, base+1, base+2, meta_bitfield_newindex, "__newindex", this, NULL, -1);
AttachEnumKeys(state, base+1, base+2, this);
EnableMetaField(state, base+2, "whole", this);
}
void struct_identity::build_metatable(lua_State *state)
{
int base = lua_gettop(state);
MakeFieldMetatable(state, this, meta_struct_index, meta_struct_newindex);
SetStructMethod(state, base+1, base+2, meta_struct_field_reference, "_field");
SetPtrMethods(state, base+1, base+2);
}
void global_identity::build_metatable(lua_State *state)
{
MakeFieldMetatable(state, this, meta_global_index, meta_global_newindex);
}
/**
* Construct a metatable for an object type folded into the field descriptor.
* This is done to reduce compile-time symbol table bloat due to templates.
*/
static void GetAdHocMetatable(lua_State *state, const struct_field_info *field)
{
lua_pushlightuserdata(state, (void*)field);
if (!LookupTypeInfo(state, true))
{
switch (field->mode)
{
case struct_field_info::CONTAINER:
{
auto ctype = (container_identity*)field->type;
MakeContainerMetatable(state, ctype, ctype->getItemType(), -1, field->eid);
break;
}
case struct_field_info::STATIC_STRING:
MakeContainerMetatable(state, &df::buffer_container_identity::base_instance,
&df::identity_traits<char>::identity, field->count, NULL);
break;
case struct_field_info::STATIC_ARRAY:
MakeContainerMetatable(state, &df::buffer_container_identity::base_instance,
field->type, field->count, field->eid);
break;
case struct_field_info::STL_VECTOR_PTR:
MakeContainerMetatable(state, &df::identity_traits<std::vector<void*> >::identity,
field->type, -1, field->eid);
break;
default:
luaL_error(state, "Invalid ad-hoc field: %d", field->mode);
}
lua_pop(state, 1);
SaveTypeInfo(state, (void*)field);
}
}
void LuaWrapper::push_adhoc_pointer(lua_State *state, void *ptr, type_identity *target)
{
if (!target)
{
push_object_internal(state, &df::identity_traits<void*>::identity, ptr);
return;
}
LookupInTable(state, target, DFHACK_PTR_IDTABLE_NAME);
type_identity *id = (type_identity*)lua_touserdata(state, -1);
lua_pop(state, 1);
if (!id)
{
/*
* HACK: relies on
* 1) pointer_identity destructor being no-op
* 2) lua gc never moving objects in memory
*/
void *newobj = lua_newuserdata(state, sizeof(pointer_identity));
id = new (newobj) pointer_identity(target);
SaveInTable(state, target, DFHACK_PTR_IDTABLE_NAME);
lua_pop(state, 1);
}
push_object_internal(state, id, ptr);
}

File diff suppressed because it is too large Load Diff

@ -47,6 +47,7 @@ VersionInfoFactory::~VersionInfoFactory()
{
clear();
}
void VersionInfoFactory::clear()
{
// for each stored version, delete
@ -83,11 +84,11 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
TiXmlElement* pMemEntry;
const char *cstr_name = entry->Attribute("name");
if (!cstr_name)
throw Error::MemoryXmlBadAttribute("name");
throw Error::SymbolsXmlBadAttribute("name");
const char *cstr_os = entry->Attribute("os-type");
if (!cstr_os)
throw Error::MemoryXmlBadAttribute("os-type");
throw Error::SymbolsXmlBadAttribute("os-type");
string os = cstr_os;
mem->setVersion(cstr_name);
@ -106,7 +107,7 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
}
else
{
throw Error::MemoryXmlBadAttribute("os-type");
throw Error::SymbolsXmlBadAttribute("os-type");
}
// process additional entries
@ -121,7 +122,7 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
{
const char *cstr_key = pMemEntry->Attribute("name");
if(!cstr_key)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
{
@ -134,14 +135,14 @@ void VersionInfoFactory::ParseVersion (TiXmlElement* entry, VersionInfo* mem)
{
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
mem->addMD5(cstr_value);
}
else if (type == "binary-timestamp")
{
const char *cstr_value = pMemEntry->Attribute("value");
if(!cstr_value)
throw Error::MemoryXmlUnderspecifiedEntry(cstr_name);
throw Error::SymbolsXmlUnderspecifiedEntry(cstr_name);
mem->addPE(strtol(cstr_value, 0, 16));
}
} // for
@ -157,7 +158,7 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
{
error = true;
cerr << "failed!\n";
throw Error::MemoryXmlParse(doc.ErrorDesc(), doc.ErrorId(), doc.ErrorRow(), doc.ErrorCol());
throw Error::SymbolsXmlParse(doc.ErrorDesc(), doc.ErrorId(), doc.ErrorRow(), doc.ErrorCol());
}
else
{
@ -174,13 +175,13 @@ bool VersionInfoFactory::loadFile(string path_to_xml)
if (!pElem)
{
error = true;
throw Error::MemoryXmlNoRoot();
throw Error::SymbolsXmlNoRoot();
}
string m_name=pElem->Value();
if(m_name != "data-definition")
{
error = true;
throw Error::MemoryXmlNoRoot();
throw Error::SymbolsXmlNoRoot();
}
// save this for later
hRoot=TiXmlHandle(pElem);

@ -1,16 +0,0 @@
#include "Internal.h"
#include <string>
#include <vector>
#include <map>
#include "MemAccess.h"
#include "Core.h"
#include "Virtual.h"
using namespace DFHack;
std::string t_virtual::getClassName() const
{
Core & c = Core::getInstance();
return c.p->readClassName(vptr);
}

@ -184,10 +184,15 @@ namespace DFHack
memcpy(m_data, other.m_data,m_size*sizeof(T));
}
typedef T value_type;
T *data() { return m_data; }
const T *data() const { return m_data; }
unsigned size() const { return m_size; }
T *begin() { return m_data; }
T *end() { return m_data+m_size; }
T& operator[] (unsigned i) { return m_data[i]; }
const T& operator[] (unsigned i) const { return m_data[i]; }
@ -217,5 +222,15 @@ namespace DFHack
memcpy(data(), other.data(), sizeof(T)*size());
return *this;
}
void erase(T *ptr) {
memmove(ptr, ptr+1, sizeof(T)*(m_size - (ptr - m_data))); m_size--;
}
void insert(T *ptr, const T &item) {
int idx = ptr - m_data;
resize(m_size+1);
memmove(m_data + idx + 1, m_data + idx, sizeof(T)*(m_size - idx - 1));
m_data[idx] = item;
}
};
}

@ -58,6 +58,7 @@ namespace DFHack
IDTYPE_ENUM,
IDTYPE_STRUCT,
IDTYPE_CLASS,
IDTYPE_BUFFER,
IDTYPE_STL_PTR_VECTOR
};
@ -90,6 +91,11 @@ namespace DFHack
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index) = 0;
virtual void build_metatable(lua_State *state);
// lua_read doesn't just return a reference to the object
virtual bool isPrimitive() { return true; }
// needs constructor/destructor
virtual bool isConstructed() { return false; }
// inherits from container_identity
virtual bool isContainer() { return false; }
void *allocate();
@ -103,6 +109,9 @@ namespace DFHack
constructed_identity(size_t size, TAllocateFn alloc)
: type_identity(size), allocator(alloc) {};
virtual bool isPrimitive() { return false; }
virtual bool isConstructed() { return true; }
virtual bool can_allocate() { return (allocator != NULL); }
virtual void *do_allocate() { return allocator(NULL,NULL); }
virtual void do_copy(void *tgt, const void *src) { allocator(tgt,src); }
@ -160,6 +169,8 @@ namespace DFHack
virtual identity_type type() { return IDTYPE_BITFIELD; }
virtual bool isConstructed() { return false; }
int getNumBits() { return num_bits; }
const bitfield_item_info *getBits() { return bits; }
@ -194,6 +205,9 @@ namespace DFHack
type_identity *getBaseType() { return base_type; }
virtual bool isPrimitive() { return true; }
virtual bool isConstructed() { return false; }
virtual void lua_read(lua_State *state, int fname_idx, void *ptr);
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index);
};
@ -344,7 +358,7 @@ namespace DFHack
/**
* Check that the value is a wrapped DF object of the given type, and if so return the pointer.
*/
DFHACK_EXPORT void *GetDFObject(lua_State *state, type_identity *type, int val_index);
DFHACK_EXPORT void *GetDFObject(lua_State *state, type_identity *type, int val_index, bool exact_type = false);
template<class T>
T *ifnull(T *a, T *b) { return a ? a : b; }
@ -639,7 +653,7 @@ namespace DFHack {
* Represent flag array bits as a string, using sep as join separator.
*/
template<class T>
inline std::string bitfield_to_string(const BitArray<T> &val, const std::string &sep = " ") {
inline std::string flagarray_to_string(const BitArray<T> &val, const std::string &sep = " ") {
std::vector<std::string> tmp;
flagarray_to_string<T>(&tmp, val);
return join_strings(sep, tmp);
@ -659,8 +673,8 @@ namespace DFHack {
* Check that the value is a wrapped DF object of the correct type, and if so return the pointer.
*/
template<class T>
T *GetDFObject(lua_State *state, int val_index) {
return GetDFObject(state, df::identity_traits<T>::get(), val_index);
T *GetDFObject(lua_State *state, int val_index, bool exact_type = false) {
return (T*)GetDFObject(state, df::identity_traits<T>::get(), val_index, exact_type);
}
}

@ -84,14 +84,24 @@ namespace DFHack
virtual std::string getFullName(type_identity *item);
int lua_item_count(lua_State *state, void *ptr);
enum CountMode {
COUNT_LEN, COUNT_READ, COUNT_WRITE
};
int lua_item_count(lua_State *state, void *ptr, CountMode cnt);
virtual void lua_item_reference(lua_State *state, int fname_idx, void *ptr, int idx);
virtual void lua_item_read(lua_State *state, int fname_idx, void *ptr, int idx);
virtual void lua_item_write(lua_State *state, int fname_idx, void *ptr, int idx, int val_index);
virtual bool resize(void *ptr, int size) { return false; }
virtual bool erase(void *ptr, int index) { return false; }
virtual bool insert(void *ptr, int index, void *pitem) { return false; }
virtual bool lua_insert(lua_State *state, int fname_idx, void *ptr, int idx, int val_index);
protected:
virtual int item_count(void *ptr) = 0;
virtual int item_count(void *ptr, CountMode cnt) = 0;
virtual void *item_pointer(type_identity *item, void *ptr, int idx) = 0;
};
@ -108,6 +118,8 @@ namespace DFHack
virtual void lua_item_reference(lua_State *state, int fname_idx, void *ptr, int idx);
virtual void lua_item_read(lua_State *state, int fname_idx, void *ptr, int idx);
virtual void lua_item_write(lua_State *state, int fname_idx, void *ptr, int idx, int val_index);
virtual bool lua_insert(lua_State *state, int fname_idx, void *ptr, int idx, int val_index);
};
class DFHACK_EXPORT bit_container_identity : public container_identity {
@ -175,25 +187,33 @@ namespace df
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index);
};
class stl_string_identity : public primitive_identity {
class stl_string_identity : public DFHack::constructed_identity {
public:
stl_string_identity() : primitive_identity(sizeof(std::string)) {};
stl_string_identity()
: constructed_identity(sizeof(std::string), &allocator_fn<std::string>)
{};
std::string getFullName() { return "string"; }
virtual DFHack::identity_type type() { return DFHack::IDTYPE_PRIMITIVE; }
virtual bool isPrimitive() { return true; }
virtual void lua_read(lua_State *state, int fname_idx, void *ptr);
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index);
};
class stl_ptr_vector_identity : public ptr_container_identity {
public:
typedef std::vector<void*> container;
/*
* This class assumes that std::vector<T*> is equivalent
* in layout and behavior to std::vector<void*> for any T.
*/
stl_ptr_vector_identity(type_identity *item = NULL, enum_identity *ienum = NULL)
: ptr_container_identity(sizeof(std::vector<void*>),allocator_fn<std::vector<void*> >,item, ienum)
: ptr_container_identity(sizeof(container),allocator_fn<container>,item, ienum)
{};
std::string getFullName(type_identity *item) {
@ -202,12 +222,27 @@ namespace df
virtual DFHack::identity_type type() { return DFHack::IDTYPE_STL_PTR_VECTOR; }
virtual bool resize(void *ptr, int size) {
(*(container*)ptr).resize(size);
return true;
}
virtual bool erase(void *ptr, int size) {
auto &ct = *(container*)ptr;
ct.erase(ct.begin()+size);
return true;
}
virtual bool insert(void *ptr, int idx, void *item) {
auto &ct = *(container*)ptr;
ct.insert(ct.begin()+idx, item);
return true;
}
protected:
virtual int item_count(void *ptr) {
return ((std::vector<void*>*)ptr)->size();
virtual int item_count(void *ptr, CountMode) {
return ((container*)ptr)->size();
};
virtual void *item_pointer(type_identity *, void *ptr, int idx) {
return &(*(std::vector<void*>*)ptr)[idx];
return &(*(container*)ptr)[idx];
}
};
@ -224,11 +259,14 @@ namespace df
{}
std::string getFullName(type_identity *item);
int getSize() { return size; }
virtual DFHack::identity_type type() { return DFHack::IDTYPE_BUFFER; }
static buffer_container_identity base_instance;
protected:
virtual int item_count(void *ptr) { return size; }
virtual int item_count(void *ptr, CountMode) { return size; }
virtual void *item_pointer(type_identity *item, void *ptr, int idx) {
return ((uint8_t*)ptr) + idx * item->byte_size();
}
@ -247,8 +285,23 @@ namespace df
return name + container_identity::getFullName(item);
}
virtual bool resize(void *ptr, int size) {
(*(T*)ptr).resize(size);
return true;
}
virtual bool erase(void *ptr, int size) {
auto &ct = *(T*)ptr;
ct.erase(ct.begin()+size);
return true;
}
virtual bool insert(void *ptr, int idx, void *item) {
auto &ct = *(T*)ptr;
ct.insert(ct.begin()+idx, *(typename T::value_type*)item);
return true;
}
protected:
virtual int item_count(void *ptr) { return ((T*)ptr)->size(); }
virtual int item_count(void *ptr, CountMode) { return ((T*)ptr)->size(); }
virtual void *item_pointer(type_identity *item, void *ptr, int idx) {
return &(*(T*)ptr)[idx];
}
@ -271,8 +324,15 @@ namespace df
return "BitArray<>";
}
virtual bool resize(void *ptr, int size) {
((container*)ptr)->resize(size);
return true;
}
protected:
virtual int item_count(void *ptr) { return ((container*)ptr)->size * 8; }
virtual int item_count(void *ptr, CountMode cnt) {
return cnt == COUNT_LEN ? ((container*)ptr)->size * 8 : -1;
}
virtual bool get_item(void *ptr, int idx) {
return ((container*)ptr)->is_set(idx);
}
@ -293,8 +353,15 @@ namespace df
return "vector" + bit_container_identity::getFullName(item);
}
virtual bool resize(void *ptr, int size) {
(*(container*)ptr).resize(size);
return true;
}
protected:
virtual int item_count(void *ptr) { return ((container*)ptr)->size(); }
virtual int item_count(void *ptr, CountMode) {
return ((container*)ptr)->size();
}
virtual bool get_item(void *ptr, int idx) {
return (*(container*)ptr)[idx];
}

@ -24,9 +24,6 @@ distribution.
#pragma once
#ifndef ERROR_H_INCLUDED
#define ERROR_H_INCLUDED
#include "Export.h"
#include "Pragma.h"
#include <string>
@ -42,176 +39,34 @@ namespace DFHack
* the whole array of DFHack exceptions from the rest
*/
class DFHACK_EXPORT All : public std::exception{};
class DFHACK_EXPORT AllMemdef : public All{};
class DFHACK_EXPORT NoProcess : public All
{
public:
virtual const char* what() const throw()
{
return "couldn't find a suitable process";
}
};
class DFHACK_EXPORT CantAttach : public All
{
public:
virtual const char* what() const throw()
{
return "couldn't attach to process";
}
};
class DFHACK_EXPORT NoMapLoaded : public All
{
public:
virtual const char* what() const throw()
{
return "no map has been loaded in the dwarf fortress process";
}
};
class DFHACK_EXPORT BadMapDimensions : public All
{
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 DFHACK_EXPORT MissingMemoryDefinition : public AllMemdef
{
public:
MissingMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
{
std::stringstream s;
s << "memory object not declared: type=" << type << " key=" << key;
full = s.str();
}
// Used by functios using integer keys, such as getTrait
MissingMemoryDefinition(const char* _type, uint32_t _key) : type(_type)
{
std::stringstream s1;
s1 << _key;
key = s1.str();
std::stringstream s;
s << "memory object not declared: type=" << type << " key=" << key;
full = s.str();
}
virtual ~MissingMemoryDefinition() throw(){};
std::string full;
const std::string type;
std::string key;
virtual const char* what() const throw()
{
return full.c_str();
}
};
// a call to DFHack::mem_info::get* failed
class DFHACK_EXPORT UnsetMemoryDefinition : public AllMemdef
{
public:
UnsetMemoryDefinition(const char* _type, const std::string _key) : type(_type), key(_key)
{
std::stringstream s;
s << "memory object not set: type " << type << " key " << key;
full = s.str();
}
// Used by functios using integer keys, such as getTrait
UnsetMemoryDefinition(const char* _type, uint32_t _key) : type(_type)
{
std::stringstream s1;
s1 << _key;
key = s1.str();
std::stringstream s;
s << "memory object not set: type " << type << " key " << key;
full = s.str();
}
virtual ~UnsetMemoryDefinition() throw(){};
std::string full;
const std::string type;
std::string key;
virtual const char* what() const throw()
{
return full.c_str();
}
};
// 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();
}
};
class DFHACK_EXPORT AllSymbols : public All{};
// Syntax errors and whatnot, the xml can't be read
class DFHACK_EXPORT MemoryXmlParse : public All
class DFHACK_EXPORT SymbolsXmlParse : public AllSymbols
{
public:
MemoryXmlParse(const char* _desc, int _id, int _row, int _col)
SymbolsXmlParse(const char* _desc, int _id, int _row, int _col)
:desc(_desc), id(_id), row(_row), col(_col)
{
std::stringstream s;
s << "error " << id << ": " << desc << ", at row " << row << " col " << col;
full = s.str();
}
std::string full;
const std::string desc;
const int id;
const int row;
const int col;
virtual ~MemoryXmlParse() throw(){};
virtual ~SymbolsXmlParse() throw(){};
virtual const char* what() const throw()
{
return full.c_str();
}
};
class DFHACK_EXPORT MemoryXmlBadAttribute : public All
class DFHACK_EXPORT SymbolsXmlBadAttribute : public All
{
public:
MemoryXmlBadAttribute(const char* _attr) : attr(_attr)
SymbolsXmlBadAttribute(const char* _attr) : attr(_attr)
{
std::stringstream s;
s << "attribute is either missing or invalid: " << attr;
@ -219,58 +74,34 @@ namespace DFHack
}
std::string full;
std::string attr;
virtual ~MemoryXmlBadAttribute() throw(){};
virtual ~SymbolsXmlBadAttribute() throw(){};
virtual const char* what() const throw()
{
return full.c_str();
}
};
class DFHACK_EXPORT MemoryXmlNoRoot : public All
class DFHACK_EXPORT SymbolsXmlNoRoot : public All
{
public:
MemoryXmlNoRoot() {}
virtual ~MemoryXmlNoRoot() throw(){};
virtual const char* what() const throw()
{
return "no pElem found";
}
};
class DFHACK_EXPORT MemoryXmlNoDFExtractor : public All
{
public:
MemoryXmlNoDFExtractor(const char* _name) : name(_name)
{
std::stringstream s;
s << "DFExtractor != " << name;
full = s.str();
}
virtual ~MemoryXmlNoDFExtractor() throw(){};
std::string name;
std::string full;
SymbolsXmlNoRoot() {}
virtual ~SymbolsXmlNoRoot() throw(){};
virtual const char* what() const throw()
{
return full.c_str();
return "Symbol file is missing root element.";
}
};
class DFHACK_EXPORT MemoryXmlUnderspecifiedEntry : public All
class DFHACK_EXPORT SymbolsXmlUnderspecifiedEntry : public All
{
public:
MemoryXmlUnderspecifiedEntry(const char * _where) : where(_where)
SymbolsXmlUnderspecifiedEntry(const char * _where) : where(_where)
{
std::stringstream s;
s << "underspecified MemInfo entry, each entry needs to set both the name attribute and have a value. parent: " << where;
s << "Underspecified symbol file entry, each entry needs to set both the name attribute and have a value. parent: " << where;
full = s.str();
}
virtual ~MemoryXmlUnderspecifiedEntry() throw(){};
virtual ~SymbolsXmlUnderspecifiedEntry() throw(){};
std::string where;
std::string full;
virtual const char* what() const throw()
@ -278,104 +109,6 @@ namespace DFHack
return full.c_str();
}
};
class DFHACK_EXPORT MemoryXmlUnknownType : public All
{
public:
MemoryXmlUnknownType(const char* _type) : type(_type)
{
std::stringstream s;
s << "unknown MemInfo type: " << type;
full = s.str();
}
virtual ~MemoryXmlUnknownType() throw(){};
std::string type;
std::string full;
virtual const char* what() const throw()
{
return full.c_str();
}
};
class DFHACK_EXPORT SHMServerDisappeared : public All
{
public:
SHMServerDisappeared(){}
virtual ~SHMServerDisappeared() throw(){};
virtual const char* what() const throw()
{
return "The server process has disappeared";
}
};
class DFHACK_EXPORT SHMLockingError : public All
{
public:
SHMLockingError(const char* _type) : type(_type)
{
std::stringstream s;
s << "SHM locking error: " << type;
full = s.str();
}
virtual ~SHMLockingError() throw(){};
std::string type;
std::string full;
virtual const char* what() const throw()
{
return full.c_str();
}
};
class DFHACK_EXPORT MemoryAccessDenied : public All
{
public:
std::string descr;
MemoryAccessDenied(uint64_t address)
{
std::stringstream s;
s << "Invalid memory access @0x" << std::hex << address;
descr = s.str();
}
virtual ~MemoryAccessDenied() throw(){};
virtual const char* what() const throw()
{
return descr.c_str();
}
};
class DFHACK_EXPORT SHMVersionMismatch : public All
{
public:
SHMVersionMismatch() {}
virtual ~SHMVersionMismatch() throw(){};
virtual const char* what() const throw()
{
return "SHM VERSION MISMATCH";
}
};
class DFHACK_EXPORT SHMAttachFailure : public All
{
public:
SHMAttachFailure() {}
virtual ~SHMAttachFailure() throw(){};
virtual const char* what() const throw()
{
return "SHM ATTACH FAILURE";
}
};
class DFHACK_EXPORT ModuleNotInitialized : public All
{
public:
ModuleNotInitialized() {}
virtual ~ModuleNotInitialized() throw(){};
virtual const char* what() const throw()
{
return "Programmer error: module not initialized!";
}
};
}
}
#endif // ERROR_H_INCLUDED

@ -0,0 +1,190 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
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.
*/
#pragma once
#include <string>
#include <sstream>
#include <vector>
#include <map>
#include "DataDefs.h"
#include <lua.h>
#include <lauxlib.h>
/**
* Internal header file of the lua wrapper.
*/
namespace DFHack { namespace LuaWrapper {
/*
* Registry name: hash of type metatables <-> type identities.
*/
#define DFHACK_TYPETABLE_NAME "DFHack::DFTypes"
/*
* Registry name: hash of type identity -> node in df.etc...
*/
#define DFHACK_TYPEID_TABLE_NAME "DFHack::DFTypeIds"
/*
* Registry name: hash of enum/bitfield identity -> index lookup table
*/
#define DFHACK_ENUM_TABLE_NAME "DFHack::DFEnums"
/*
* Registry name: hash of pointer target identity <-> adhoc pointer identity userdata.
*/
#define DFHACK_PTR_IDTABLE_NAME "DFHack::PtrDFTypes"
// Function registry names
#define DFHACK_CHANGEERROR_NAME "DFHack::ChangeError"
#define DFHACK_COMPARE_NAME "DFHack::ComparePtrs"
#define DFHACK_TYPE_TOSTRING_NAME "DFHack::TypeToString"
#define DFHACK_SIZEOF_NAME "DFHack::Sizeof"
#define DFHACK_DISPLACE_NAME "DFHack::Displace"
#define DFHACK_NEW_NAME "DFHack::New"
#define DFHACK_ASSIGN_NAME "DFHack::Assign"
/*
* Upvalue: contents of DFHACK_TYPETABLE_NAME
*/
#define UPVAL_TYPETABLE lua_upvalueindex(1)
/*
* Expected metatable of the current object.
*/
#define UPVAL_METATABLE lua_upvalueindex(2)
/*
* Table mapping field names to indices or data structure pointers.
* Enum index table is linked into here via getmetatable($).__index.
* Fields that are actually in UPVAL_METATABLE are marked with NULL light udata.
*/
#define UPVAL_FIELDTABLE lua_upvalueindex(3)
#define UPVAL_METHOD_NAME lua_upvalueindex(3)
/*
* Only for containers: light udata with container identity.
*/
#define UPVAL_CONTAINER_ID lua_upvalueindex(4)
/*
* Only for containers: light udata with item identity.
*/
#define UPVAL_ITEM_ID lua_upvalueindex(5)
/*
* Only for containers: if not nil, overrides the item count.
*/
#define UPVAL_ITEM_COUNT lua_upvalueindex(6)
inline void lua_dup(lua_State *state) { lua_pushvalue(state, -1); }
inline void lua_swap(lua_State *state) { lua_insert(state, -2); }
/**
* Object references are represented as userdata instances
* with an appropriate metatable; the payload of userdata is
* this structure:
*/
struct DFRefHeader {
void *ptr;
};
/**
* Push the pointer as DF object ref using metatable on the stack.
*/
void push_object_ref(lua_State *state, void *ptr);
void *get_object_ref(lua_State *state, int val_index);
/*
* The system might be extended to carry some simple
* objects inline inside the reference buffer.
*/
inline bool is_self_contained(DFRefHeader *ptr) {
void **pp = &ptr->ptr;
return **(void****)pp == (pp + 1);
}
/**
* Report an error while accessing a field (index = field name).
*/
void field_error(lua_State *state, int index, const char *err, const char *mode);
/*
* If is_method is true, these use UPVAL_TYPETABLE to save a hash lookup.
*/
void push_object_internal(lua_State *state, type_identity *type, void *ptr, bool in_method = true);
void *get_object_internal(lua_State *state, type_identity *type, int val_index, bool exact_type, bool in_method = true);
void push_adhoc_pointer(lua_State *state, void *ptr, type_identity *target);
/**
* Verify that the object is a DF ref with UPVAL_METATABLE.
* If everything ok, extract the address.
*/
uint8_t *get_object_addr(lua_State *state, int obj, int field, const char *mode);
void LookupInTable(lua_State *state, void *id, const char *tname);
void SaveInTable(lua_State *state, void *node, const char *tname);
void SaveTypeInfo(lua_State *state, void *node);
/**
* Look up the key on the stack in DFHACK_TYPETABLE;
* if found, put result on the stack and return true.
*/
bool LookupTypeInfo(lua_State *state, bool in_method);
/**
* Make a metatable with most common fields, and an empty table for UPVAL_FIELDTABLE.
*/
void MakeMetatable(lua_State *state, type_identity *type, const char *kind);
/**
* Enable a metafield by injecting an entry into a UPVAL_FIELDTABLE.
*/
void EnableMetaField(lua_State *state, int ftable_idx, const char *name, void *id = NULL);
/**
* Set metatable properties common to all actual DF object references.
*/
void SetPtrMethods(lua_State *state, int meta_idx, int read_idx);
/**
* Add a struct-style (3 upvalues) metamethod to the metatable.
*/
void SetStructMethod(lua_State *state, int meta_idx, int ftable_idx,
lua_CFunction function, const char *name);
/**
* Add a 6 upvalue metamethod to the metatable.
*/
void SetContainerMethod(lua_State *state, int meta_idx, int ftable_idx,
lua_CFunction function, const char *name,
type_identity *container, type_identity *item, int count);
/**
* If ienum refers to a valid enum, attach its keys to UPVAL_FIELDTABLE,
* and the enum itself to the _enum metafield.
*/
void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum);
}}

@ -1,36 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
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.
*/
#pragma once
#include <string>
namespace DFHack
{
/// very generic representation of a virtual class... just the pointer to the vtable.
/// this is intended for instances where wrapping the classes properly hasn't been done yet.
struct t_virtual
{
void * vptr;
std::string getClassName() const;
};
}

@ -25,7 +25,6 @@ distribution.
#pragma once
#include "Export.h"
#include "Module.h"
#include "Virtual.h"
#include "BitArray.h"
#include "ColorText.h"
#include <string>

@ -29,7 +29,6 @@ distribution.
#include "Export.h"
#include "Module.h"
#include "Types.h"
#include "Virtual.h"
#include "modules/Materials.h"
#include "MemAccess.h"
@ -123,8 +122,6 @@ DFHACK_EXPORT bool copyItem(df::item * source, dfh_item & target);
/// write copied item back to its origin
DFHACK_EXPORT bool writeItem(const dfh_item & item);
/// get the class name of an item
DFHACK_EXPORT std::string getItemClass(const df::item * item);
/// who owns this item we already read?
DFHACK_EXPORT int32_t getItemOwnerID(const df::item * item);
DFHACK_EXPORT df::unit *getItemOwner(const df::item * item);

@ -34,7 +34,6 @@ distribution.
#include "Module.h"
#include "modules/Vegetation.h"
#include <vector>
#include "Virtual.h"
#include "BitArray.h"
#include "modules/Materials.h"

@ -41,7 +41,6 @@ using namespace std;
#include "modules/Units.h"
#include "ModuleFactory.h"
#include "Core.h"
#include "Virtual.h"
#include "MiscUtils.h"
#include "df/world.h"
@ -502,10 +501,3 @@ bool Items::removeItemOwner(df::item * item)
return true;
}
std::string Items::getItemClass(const df::item * item)
{
const t_virtual * virt = (t_virtual *) item;
return virt->getClassName();
}

@ -88,7 +88,10 @@ bool Maps::IsValid ()
void Maps::getSize (uint32_t& x, uint32_t& y, uint32_t& z)
{
if (!IsValid())
throw DFHack::Error::ModuleNotInitialized();
{
x = y = z = 0;
return;
}
x = world->map.x_count_block;
y = world->map.y_count_block;
z = world->map.z_count_block;
@ -98,7 +101,10 @@ void Maps::getSize (uint32_t& x, uint32_t& y, uint32_t& z)
void Maps::getPosition (int32_t& x, int32_t& y, int32_t& z)
{
if (!IsValid())
throw DFHack::Error::ModuleNotInitialized();
{
x = y = z = 0;
return;
}
x = world->map.region_x;
y = world->map.region_y;
z = world->map.region_z;

@ -24,7 +24,6 @@ distribution.
#include "Export.h"
#include "Module.h"
#include "Virtual.h"
#include "BitArray.h"
#include <string>

@ -60,6 +60,8 @@ ADD_CUSTOM_COMMAND(
DEPENDS protoc-bin ${PROJECT_PROTOS}
)
SET_SOURCE_FILES_PROPERTIES( Brushes.h PROPERTIES HEADER_FILE_ONLY TRUE )
# Plugins
OPTION(BUILD_SUPPORTED "Build the supported plugins (reveal, probe, etc.)." ON)
if (BUILD_SUPPORTED)
@ -79,8 +81,8 @@ if (BUILD_SUPPORTED)
DFHACK_PLUGIN(vdig vdig.cpp)
DFHACK_PLUGIN(colonies colonies.cpp)
DFHACK_PLUGIN(mode mode.cpp)
DFHACK_PLUGIN(liquids liquids.cpp)
DFHACK_PLUGIN(tiletypes tiletypes.cpp)
DFHACK_PLUGIN(liquids liquids.cpp Brushes.h)
DFHACK_PLUGIN(tiletypes tiletypes.cpp Brushes.h)
DFHACK_PLUGIN(tubefill tubefill.cpp)
DFHACK_PLUGIN(autodump autodump.cpp)
DFHACK_PLUGIN(cleanowned cleanowned.cpp)

@ -20,6 +20,7 @@ using std::set;
#include "TileTypes.h"
#include "modules/MapCache.h"
#include "df/tile_dig_designation.h"
#include "Brushes.h"
using namespace MapExtras;
using namespace DFHack;
using namespace df::enums;
@ -487,150 +488,6 @@ void help( std::ostream & out, const std::string &option)
}
}
typedef std::vector<DFHack::DFCoord> coord_vec;
class Brush
{
public:
virtual ~Brush() {};
virtual coord_vec points(MapExtras::MapCache &mc, DFHack::DFCoord start) = 0;
};
/**
* generic 3D rectangle brush. you can specify the dimensions of
* the rectangle and optionally which tile is its 'center'
*/
class RectangleBrush : public Brush
{
int x_, y_, z_;
int cx_, cy_, cz_;
public:
RectangleBrush(int x, int y, int z = 1, int centerx = -1, int centery = -1, int centerz = -1)
{
if (centerx == -1)
{
cx_ = x/2;
}
else
{
cx_ = centerx;
}
if (centery == -1)
{
cy_ = y/2;
}
else
{
cy_ = centery;
}
if (centerz == -1)
{
cz_ = z/2;
}
else
{
cz_ = centerz;
}
x_ = x;
y_ = y;
z_ = z;
};
coord_vec points(MapExtras::MapCache &mc, DFHack::DFCoord start)
{
coord_vec v;
DFHack::DFCoord iterstart(start.x - cx_, start.y - cy_, start.z - cz_);
DFHack::DFCoord iter = iterstart;
for (int xi = 0; xi < x_; xi++)
{
for (int yi = 0; yi < y_; yi++)
{
for (int zi = 0; zi < z_; zi++)
{
if(mc.testCoord(iter))
v.push_back(iter);
iter.z++;
}
iter.z = iterstart.z;
iter.y++;
}
iter.y = iterstart.y;
iter.x ++;
}
return v;
};
~RectangleBrush(){};
};
/**
* stupid block brush, legacy. use when you want to apply something to a whole DF map block.
*/
class BlockBrush : public Brush
{
public:
BlockBrush() {};
~BlockBrush() {};
coord_vec points(MapExtras::MapCache &mc, DFHack::DFCoord start)
{
coord_vec v;
DFHack::DFCoord blockc = start % 16;
DFHack::DFCoord iterc = blockc * 16;
if (!mc.testCoord(start))
return v;
for (int xi = 0; xi < 16; xi++)
{
for (int yi = 0; yi < 16; yi++)
{
v.push_back(iterc);
iterc.y++;
}
iterc.x++;
}
return v;
};
};
/**
* Column from a position through open space tiles
* example: create a column of magma
*/
class ColumnBrush : public Brush
{
public:
ColumnBrush(){};
~ColumnBrush(){};
coord_vec points(MapExtras::MapCache &mc, DFHack::DFCoord start)
{
coord_vec v;
bool juststarted = true;
while (mc.testCoord(start))
{
df::tiletype tt = mc.tiletypeAt(start);
if(LowPassable(tt) || juststarted && HighPassable(tt))
{
v.push_back(start);
juststarted = false;
start.z++;
}
else break;
}
return v;
};
};
CommandHistory tiletypes_hist;
command_result df_tiletypes (color_ostream &out, vector <string> & parameters);