Merge remote-tracking branch 'upstream/master'

develop
Robert Heinrich 2012-03-26 04:17:06 +02:00
commit af344e57bd
16 changed files with 609 additions and 138 deletions

@ -3,4 +3,4 @@ IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010
cd VC2010
echo generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX=%_DF_PATH% -DBUILD_DEVEL=1 -DBUILD_DEV_PLUGINS=1 -DBUILD_DF2MC=1 -DBUILD_DFUSION=1 -DBUILD_STONESENSE=1 -DBUILD_SERVER=1
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX="%_DF_PATH%" -DBUILD_DEVEL=1 -DBUILD_DEV_PLUGINS=1 -DBUILD_DF2MC=1 -DBUILD_DFUSION=1 -DBUILD_STONESENSE=1 -DBUILD_SERVER=1

@ -3,5 +3,5 @@ IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010
cd VC2010
echo Pre-generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX=%_DF_PATH%
cmake-gui .
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX="%_DF_PATH%"
cmake-gui .

@ -3,4 +3,4 @@ IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010
cd VC2010
echo generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX=%_DF_PATH% -DBUILD_DEVEL=0 -DBUILD_DEV_PLUGINS=0 -DBUILD_DF2MC=0 -DBUILD_DFUSION=0 -DBUILD_STONESENSE=0 -DBUILD_SERVER=0
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX="%_DF_PATH%" -DBUILD_DEVEL=0 -DBUILD_DEV_PLUGINS=0 -DBUILD_DF2MC=0 -DBUILD_DFUSION=0 -DBUILD_STONESENSE=0 -DBUILD_SERVER=0

@ -152,7 +152,7 @@
** LUA_BUILD_AS_DLL to get it).
*/
#ifdef __cplusplus
#define LUA_API_EXTERN extern "C"
#define LUA_API_EXTERN extern
#else
#define LUA_API_EXTERN extern
#endif

@ -51,6 +51,11 @@ void type_identity::do_copy_pod(void *tgt, const void *src) {
memmove(tgt, src, size);
};
bool type_identity::do_destroy_pod(void *obj) {
free(obj);
return true;
}
void *type_identity::allocate() {
if (can_allocate())
return do_allocate();
@ -65,6 +70,13 @@ bool type_identity::copy(void *tgt, const void *src) {
return false;
}
bool type_identity::destroy(void *obj) {
if (can_allocate() && obj)
return do_destroy(obj);
else
return false;
}
void *enum_identity::do_allocate() {
void *p = malloc(byte_size());
memcpy(p, &first_item_value, std::min(byte_size(), sizeof(int64_t)));
@ -137,10 +149,11 @@ enum_identity::enum_identity(size_t size,
compound_identity *scope_parent, const char *dfhack_name,
type_identity *base_type,
int64_t first_item_value, int64_t last_item_value,
const char *const *keys)
const char *const *keys,
const void *attrs, struct_identity *attr_type)
: compound_identity(size, NULL, scope_parent, dfhack_name),
first_item_value(first_item_value), last_item_value(last_item_value),
keys(keys), base_type(base_type)
keys(keys), base_type(base_type), attrs(attrs), attr_type(attr_type)
{
}

@ -8,6 +8,7 @@
#include "df/ui.h"
#include "DataIdentity.h"
#include "DataFuncs.h"
#include <stddef.h>
@ -30,6 +31,8 @@ namespace df {
bool_identity identity_traits<bool>::identity;
stl_string_identity identity_traits<std::string>::identity;
ptr_string_identity identity_traits<char*>::identity;
ptr_string_identity identity_traits<const char*>::identity;
pointer_identity identity_traits<void*>::identity;
stl_ptr_vector_identity identity_traits<std::vector<void*> >::identity;
stl_bit_vector_identity identity_traits<std::vector<bool> >::identity;
@ -43,6 +46,7 @@ namespace df {
#define FLD(mode, name) struct_field_info::mode, #name, offsetof(CUR_STRUCT, name)
#define GFLD(mode, name) struct_field_info::mode, #name, (size_t)&df::global::name
#define METHOD(mode, name) struct_field_info::mode, #name, 0, wrap_function(&CUR_STRUCT::name)
#define FLD_END struct_field_info::END
// Field definitions

@ -36,6 +36,7 @@ distribution.
#include "DataDefs.h"
#include "DataIdentity.h"
#include "LuaWrapper.h"
#include "DataFuncs.h"
#include "MiscUtils.h"
@ -49,6 +50,16 @@ using namespace DFHack::LuaWrapper;
* Identity object read/write methods *
**************************************/
void function_identity_base::lua_read(lua_State *state, int fname_idx, void *ptr)
{
field_error(state, fname_idx, "executable code", "read");
}
void function_identity_base::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
field_error(state, fname_idx, "executable code", "write");
}
void constructed_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
push_object_internal(state, this, ptr);
@ -99,6 +110,20 @@ void df::bool_identity::lua_write(lua_State *state, int fname_idx, void *ptr, in
field_error(state, fname_idx, "boolean or number expected", "write");
}
void df::ptr_string_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
auto pstr = (char**)ptr;
if (*pstr)
lua_pushstring(state, *pstr);
else
lua_pushnil(state);
}
void df::ptr_string_identity::lua_write(lua_State *state, int fname_idx, void *ptr, int val_index)
{
field_error(state, fname_idx, "raw pointer string", "write");
}
void df::stl_string_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{
auto pstr = (std::string*)ptr;
@ -264,12 +289,31 @@ static void lookup_field(lua_State *state, int index, const char *mode)
field_error(state, index, "not found", mode);
}
// Resolve the field in the metatable and return
static int get_metafield(lua_State *state)
{
lua_rawget(state, UPVAL_METATABLE);
return 1;
}
static void *find_field(lua_State *state, int index, const char *mode)
{
lookup_field(state, index, mode);
// Methods
if (lua_isfunction(state, -1))
return NULL;
// Otherwise must be a pointer
if (!lua_isuserdata(state, -1))
field_error(state, index, "corrupted field table", mode);
void *p = lua_touserdata(state, -1);
lua_pop(state, 1);
// NULL => metafield
if (!p)
get_metafield(state);
return p;
}
@ -295,6 +339,10 @@ static void read_field(lua_State *state, const struct_field_info *field, void *p
return;
}
case struct_field_info::OBJ_METHOD:
case struct_field_info::CLASS_METHOD:
// error
case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT:
field->type->lua_read(state, 2, ptr);
@ -339,6 +387,10 @@ static void field_reference(lua_State *state, const struct_field_info *field, vo
push_adhoc_pointer(state, ptr, field->type);
return;
case struct_field_info::OBJ_METHOD:
case struct_field_info::CLASS_METHOD:
// error
case struct_field_info::CONTAINER:
read_field(state, field, ptr);
return;
@ -371,6 +423,10 @@ static void write_field(lua_State *state, const struct_field_info *field, void *
return;
}
case struct_field_info::OBJ_METHOD:
case struct_field_info::CLASS_METHOD:
// error
case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT:
case struct_field_info::CONTAINER:
@ -418,13 +474,6 @@ static int meta_ptr_tostring(lua_State *state)
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.
*/
@ -433,7 +482,7 @@ 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);
return 1;
read_field(state, field, ptr + field->offset);
return 1;
}
@ -448,7 +497,7 @@ static int meta_struct_field_reference(lua_State *state)
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_error(state, 2, "builtin property or method", "reference");
field_reference(state, field, ptr + field->offset);
return 1;
}
@ -461,7 +510,7 @@ 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");
field_error(state, 2, "builtin property or method", "write");
write_field(state, field, ptr + field->offset, 3);
return 0;
}
@ -475,7 +524,7 @@ 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);
return 1;
type->lua_read(state, 2, ptr);
return 1;
}
@ -488,7 +537,7 @@ 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");
field_error(state, 2, "builtin property or method", "write");
type->lua_write(state, 2, ptr, 3);
return 0;
}
@ -521,7 +570,7 @@ static int lookup_container_field(lua_State *state, int field, const char *mode
if (lua_isuserdata(state, -1) && !lua_touserdata(state, -1))
{
if (mode)
field_error(state, field, "builtin property", mode);
field_error(state, field, "builtin property or method", mode);
lua_pop(state, 1);
get_metafield(state);
@ -727,7 +776,7 @@ static int meta_global_index(lua_State *state)
{
auto field = (struct_field_info*)find_field(state, 2, "read");
if (!field)
return get_metafield(state);
return 1;
void *ptr = *(void**)field->offset;
if (!ptr)
field_error(state, 2, "global address not known", "read");
@ -742,7 +791,7 @@ 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");
field_error(state, 2, "builtin property or method", "write");
void *ptr = *(void**)field->offset;
if (!ptr)
field_error(state, 2, "global address not known", "write");
@ -750,27 +799,92 @@ static int meta_global_newindex(lua_State *state)
return 0;
}
/**
* Wrapper for c++ methods and functions.
*/
static int meta_call_function(lua_State *state)
{
auto id = (function_identity_base*)lua_touserdata(state, UPVAL_CONTAINER_ID);
if (lua_gettop(state) != id->getNumArgs())
field_error(state, UPVAL_METHOD_NAME, "invalid argument count", "invoke");
id->invoke(state, 1);
return 1;
}
/**
* Create a closure invoking the given function, and add it to the field table.
*/
static void AddMethodWrapper(lua_State *state, int meta_idx, int field_idx,
const char *name, function_identity_base *fun)
{
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
lua_pushvalue(state, meta_idx);
lua_pushfstring(state, "%s()", name);
lua_pushlightuserdata(state, fun);
lua_pushcclosure(state, meta_call_function, 4);
lua_setfield(state, field_idx, name);
}
/**
* Add fields in the array to the UPVAL_FIELDTABLE candidates on the stack.
*/
static void IndexFields(lua_State *state, struct_identity *pstruct)
{
// stack: fieldtable
// stack: metatable fieldtable
int base = lua_gettop(state);
int base = lua_gettop(state) - 2;
for (struct_identity *p = pstruct; p; p = p->getParent())
{
auto fields = p->getFields();
if (!fields)
continue;
for (int i = 0; fields[i].mode != struct_field_info::END; ++i)
{
switch (fields[i].mode)
{
case struct_field_info::OBJ_METHOD:
AddMethodWrapper(state, base+1, base+2, fields[i].name,
(function_identity_base*)fields[i].type);
break;
case struct_field_info::CLASS_METHOD:
break;
default:
lua_pushstring(state,fields[i].name);
lua_pushlightuserdata(state,(void*)&fields[i]);
lua_rawset(state,base+2);
break;
}
}
}
}
void LuaWrapper::IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct)
{
// stack: metatable fieldtable
for (struct_identity *p = pstruct; p; p = p->getParent())
{
auto fields = p->getFields();
if (!fields)
continue;
for (; fields; ++fields)
for (int i = 0; fields[i].mode != struct_field_info::END; ++i)
{
if (fields->mode == struct_field_info::END)
switch (fields[i].mode)
{
case struct_field_info::CLASS_METHOD:
AddMethodWrapper(state, meta_idx, ftable_idx, fields[i].name,
(function_identity_base*)fields[i].type);
break;
lua_pushstring(state,fields->name);
lua_pushlightuserdata(state,(void*)fields);
lua_rawset(state,base);
default:
break;
}
}
}
}

@ -593,10 +593,7 @@ static int meta_new(lua_State *state)
void *ptr = id->allocate();
if (!ptr)
{
lua_pushnil(state);
return 1;
}
luaL_error(state, "Cannot allocate %s", id->getFullName().c_str());
if (lua_isuserdata(state, 1))
{
@ -630,6 +627,30 @@ static int meta_assign(lua_State *state)
return 0;
}
/**
* Method: deallocation for DF object references.
*/
static int meta_delete(lua_State *state)
{
int argc = lua_gettop(state);
if (argc != 1)
luaL_error(state, "Usage: object:delete() or df.delete(object)");
if (lua_isnil(state, 1))
{
lua_pushboolean(state, true);
return 1;
}
type_identity *id = get_object_identity(state, 1, "df.delete()", false);
bool ok = id->destroy(get_object_ref(state, 1));
lua_pushboolean(state, ok);
return 1;
}
/**
* Verify that the object is a DF ref with UPVAL_METATABLE.
* If everything ok, extract the address.
@ -677,6 +698,30 @@ static int meta_ptr_tostring(lua_State *state)
return 1;
}
/**
* Metamethod: __index for enum.attrs
*/
static int meta_enum_attr_index(lua_State *state)
{
if (!lua_isnumber(state, 2))
lua_rawget(state, UPVAL_FIELDTABLE);
if (!lua_isnumber(state, 2))
luaL_error(state, "Invalid index in enum.attrs[]");
auto id = (enum_identity*)lua_touserdata(state, lua_upvalueindex(2));
int64_t idx = lua_tonumber(state, 2);
if (idx < id->getFirstItem() || idx > id->getLastItem())
idx = id->getLastItem()+1;
idx -= id->getFirstItem();
uint8_t *ptr = (uint8_t*)id->getAttrs();
auto atype = id->getAttrType();
push_object_internal(state, atype, ptr + unsigned(atype->byte_size()*idx));
return 1;
}
/**
* Make a metatable with most common fields, and an empty table for UPVAL_FIELDTABLE.
*/
@ -741,6 +786,10 @@ void LuaWrapper::SetPtrMethods(lua_State *state, int meta_idx, int read_idx)
lua_setfield(state, meta_idx, "new");
EnableMetaField(state, read_idx, "new");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME);
lua_setfield(state, meta_idx, "delete");
EnableMetaField(state, read_idx, "delete");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
lua_setfield(state, meta_idx, "assign");
EnableMetaField(state, read_idx, "assign");
@ -835,82 +884,152 @@ static void AssociateId(lua_State *state, int table, int val, const char *name)
lua_rawset(state, table);
}
static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid)
{
const char *const *keys = eid->getKeys();
// Create a new table attached to ftable as __index
lua_newtable(state);
lua_dup(state);
lua_setmetatable(state, ftable);
int base = lua_gettop(state);
lua_newtable(state);
// For enums, set mapping between keys and values
for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++)
{
if (keys[j])
AssociateId(state, base+1, i, keys[j]);
}
if (eid->getFirstItem() <= eid->getLastItem())
{
lua_pushinteger(state, eid->getFirstItem());
lua_setfield(state, base+1, "_first_item");
lua_pushinteger(state, eid->getLastItem());
lua_setfield(state, base+1, "_last_item");
}
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
// Add an attribute table if any
if (eid->getAttrs())
{
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
lua_pushlightuserdata(state, eid);
lua_pushvalue(state, base+1);
lua_pushcclosure(state, meta_enum_attr_index, 3);
freeze_table(state, false, (eid->getFullName()+".attrs").c_str());
lua_setfield(state, ftable, "attrs");
}
lua_setfield(state, base, "__index");
lua_pop(state, 1);
}
static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *eid)
{
auto bits = eid->getBits();
for (int i = 0; i < eid->getNumBits(); i++)
{
if (bits[i].name)
AssociateId(state, ftable, i, bits[i].name);
if (bits[i].size > 1)
i += bits[i].size-1;
}
lua_pushinteger(state, 0);
lua_setfield(state, ftable, "_first_item");
lua_pushinteger(state, eid->getNumBits()-1);
lua_setfield(state, ftable, "_last_item");
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
}
static void RenderType(lua_State *state, compound_identity *node)
{
assert(node->getName());
std::string name = node->getFullName();
int base = lua_gettop(state);
lua_newtable(state);
if (!lua_checkstack(state, 20))
return;
int base = lua_gettop(state);
SaveInTable(state, node, DFHACK_TYPEID_TABLE_NAME);
// metatable
lua_newtable(state);
lua_dup(state);
lua_setmetatable(state, base+1);
lua_pushstring(state, name.c_str());
lua_setfield(state, base+2, "__metatable");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPE_TOSTRING_NAME);
lua_setfield(state, base+2, "__tostring");
lua_pushlightuserdata(state, node);
lua_setfield(state, base+2, "_identity");
// inner table
lua_newtable(state);
lua_dup(state);
lua_setfield(state, base+2, "__index");
int ftable = base+3;
switch (node->type())
{
case IDTYPE_STRUCT:
lua_pushstring(state, "struct-type");
lua_setfield(state, base, "_kind");
lua_setfield(state, ftable, "_kind");
IndexStatics(state, base+2, base+3, (struct_identity*)node);
break;
case IDTYPE_CLASS:
lua_pushstring(state, "class-type");
lua_setfield(state, base, "_kind");
lua_setfield(state, ftable, "_kind");
IndexStatics(state, base+2, base+3, (struct_identity*)node);
break;
case IDTYPE_ENUM:
{
lua_pushstring(state, "enum-type");
lua_setfield(state, base, "_kind");
enum_identity *eid = (enum_identity*)node;
const char *const *keys = eid->getKeys();
// For enums, set mapping between keys and values
for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++)
{
if (keys[j])
AssociateId(state, base, i, keys[j]);
}
if (eid->getFirstItem() <= eid->getLastItem())
{
lua_pushinteger(state, eid->getFirstItem());
lua_setfield(state, base, "_first_item");
lua_pushinteger(state, eid->getLastItem());
lua_setfield(state, base, "_last_item");
}
SaveInTable(state, node, DFHACK_ENUM_TABLE_NAME);
}
lua_pushstring(state, "enum-type");
lua_setfield(state, ftable, "_kind");
FillEnumKeys(state, ftable, (enum_identity*)node);
break;
case IDTYPE_BITFIELD:
{
lua_pushstring(state, "bitfield-type");
lua_setfield(state, base, "_kind");
lua_pushstring(state, "bitfield-type");
lua_setfield(state, ftable, "_kind");
FillBitfieldKeys(state, ftable, (bitfield_identity*)node);
break;
bitfield_identity *eid = (bitfield_identity*)node;
auto bits = eid->getBits();
case IDTYPE_GLOBAL:
{
RenderTypeChildren(state, node->getScopeChildren());
for (int i = 0; i < eid->getNumBits(); i++)
{
if (bits[i].name)
AssociateId(state, base, i, bits[i].name);
if (bits[i].size > 1)
i += bits[i].size-1;
}
BuildTypeMetatable(state, node);
lua_pushinteger(state, 0);
lua_setfield(state, base, "_first_item");
lua_dup(state);
lua_setmetatable(state, base+3);
lua_pushinteger(state, eid->getNumBits()-1);
lua_setfield(state, base, "_last_item");
lua_getfield(state, -1, "__newindex");
lua_setfield(state, base+2, "__newindex");
SaveInTable(state, node, DFHACK_ENUM_TABLE_NAME);
lua_pop(state, 3);
return;
}
break;
default:
break;
@ -918,44 +1037,13 @@ static void RenderType(lua_State *state, compound_identity *node)
RenderTypeChildren(state, node->getScopeChildren());
assert(base == lua_gettop(state));
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME);
lua_setfield(state, base, "sizeof");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME);
lua_setfield(state, base, "new");
if (node->type() == IDTYPE_GLOBAL)
{
BuildTypeMetatable(state, node);
// Set metatable for the inner table
lua_dup(state);
lua_setmetatable(state, base);
lua_swap(state); // -> meta curtable
lua_setfield(state, ftable, "sizeof");
freeze_table(state, true, "global");
// Copy __newindex to the outer metatable
lua_getfield(state, base, "__newindex");
lua_setfield(state, -2, "__newindex");
lua_remove(state, base);
}
else
{
freeze_table(state, true, name.c_str());
}
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPE_TOSTRING_NAME);
lua_setfield(state, -2, "__tostring");
lua_pushlightuserdata(state, node);
lua_setfield(state, -2, "_identity");
lua_pop(state, 1);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME);
lua_setfield(state, ftable, "new");
SaveInTable(state, node, DFHACK_TYPEID_TABLE_NAME);
lua_pop(state, 2);
}
static void RenderTypeChildren(lua_State *state, const std::vector<compound_identity*> &children)
@ -1007,6 +1095,10 @@ static void DoAttach(lua_State *state)
lua_pushcclosure(state, meta_assign, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
lua_pushcclosure(state, meta_delete, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME);
luaL_register(state, "df", no_functions);
{
@ -1020,6 +1112,8 @@ static void DoAttach(lua_State *state)
lua_setfield(state, -2, "sizeof");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME);
lua_setfield(state, -2, "new");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME);
lua_setfield(state, -2, "delete");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_DISPLACE_NAME);
lua_setfield(state, -2, "_displace");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);

@ -49,6 +49,7 @@ namespace DFHack
enum identity_type {
IDTYPE_GLOBAL,
IDTYPE_FUNCTION,
IDTYPE_PRIMITIVE,
IDTYPE_POINTER,
IDTYPE_CONTAINER,
@ -72,10 +73,12 @@ namespace DFHack
void *do_allocate_pod();
void do_copy_pod(void *tgt, const void *src);
bool do_destroy_pod(void *obj);
virtual bool can_allocate() { return true; }
virtual void *do_allocate() { return do_allocate_pod(); }
virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); }
virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); }
public:
virtual ~type_identity() {}
@ -100,6 +103,7 @@ namespace DFHack
void *allocate();
bool copy(void *tgt, const void *src);
bool destroy(void *obj);
};
class DFHACK_EXPORT constructed_identity : public type_identity {
@ -109,12 +113,13 @@ 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); }
virtual bool do_destroy(void *obj) { return allocator(NULL,obj) == obj; }
public:
virtual bool isPrimitive() { return false; }
virtual bool isConstructed() { 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);
@ -161,6 +166,7 @@ namespace DFHack
virtual bool can_allocate() { return true; }
virtual void *do_allocate() { return do_allocate_pod(); }
virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); }
virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); }
public:
bitfield_identity(size_t size,
@ -177,6 +183,8 @@ namespace DFHack
virtual void build_metatable(lua_State *state);
};
class struct_identity;
class DFHACK_EXPORT enum_identity : public compound_identity {
const char *const *keys;
int64_t first_item_value;
@ -184,17 +192,22 @@ namespace DFHack
type_identity *base_type;
const void *attrs;
struct_identity *attr_type;
protected:
virtual bool can_allocate() { return true; }
virtual void *do_allocate();
virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); }
virtual bool do_destroy(void *obj) { return do_destroy_pod(obj); }
public:
enum_identity(size_t size,
compound_identity *scope_parent, const char *dfhack_name,
type_identity *base_type,
int64_t first_item_value, int64_t last_item_value,
const char *const *keys);
const char *const *keys,
const void *attrs, struct_identity *attr_type);
virtual identity_type type() { return IDTYPE_ENUM; }
@ -204,6 +217,8 @@ namespace DFHack
const char *const *getKeys() { return keys; }
type_identity *getBaseType() { return base_type; }
const void *getAttrs() { return attrs; }
struct_identity *getAttrType() { return attr_type; }
virtual bool isPrimitive() { return true; }
virtual bool isConstructed() { return false; }
@ -221,7 +236,9 @@ namespace DFHack
STATIC_ARRAY,
SUBSTRUCT,
CONTAINER,
STL_VECTOR_PTR
STL_VECTOR_PTR,
OBJ_METHOD,
CLASS_METHOD
};
Mode mode;
const char *name;
@ -409,6 +426,14 @@ namespace df
template<class T>
void *allocator_fn(void *out, const void *in) {
if (out) { *(T*)out = *(const T*)in; return out; }
else if (in) { delete (T*)in; return (T*)in; }
else return new T();
}
template<class T>
void *allocator_nodel_fn(void *out, const void *in) {
if (out) { *(T*)out = *(const T*)in; return out; }
else if (in) { return NULL; }
else return new T();
}

@ -0,0 +1,129 @@
/*
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 "DataIdentity.h"
#include "LuaWrapper.h"
namespace df {
template<class T> struct function_wrapper {};
/*
* Since templates can't match variable arg count,
* a separate specialization is needed for every
* supported count value...
*
* The FW_TARGS ugliness is needed because of
* commas not wrapped in ()
*/
#define INVOKE_VOID(call) \
call; lua_pushnil(state);
#define INVOKE_RV(call) \
RT rv = call; df::identity_traits<RT>::get()->lua_read(state, UPVAL_METHOD_NAME, &rv);
#define LOAD_CLASS() \
CT *self = (CT*)DFHack::LuaWrapper::get_object_addr(state, base++, UPVAL_METHOD_NAME, "invoke");
#define LOAD_ARG(type) \
type v##type; df::identity_traits<type>::get()->lua_write(state, UPVAL_METHOD_NAME, &v##type, base++);
#define INSTANTIATE_WRAPPERS(Count, FArgs, Args, Loads) \
template<FW_TARGS> struct function_wrapper<void (*) FArgs> { \
static const bool is_method = false; \
static const int num_args = Count; \
static void execute(lua_State *state, int base, void (*cb) FArgs) { Loads; INVOKE_VOID(cb Args); } \
}; \
template<FW_TARGSC class RT> struct function_wrapper<RT (*) FArgs> { \
static const bool is_method = false; \
static const int num_args = Count; \
static void execute(lua_State *state, int base, RT (*cb) FArgs) { Loads; INVOKE_RV(cb Args); } \
}; \
template<FW_TARGSC class CT> struct function_wrapper<void (CT::*) FArgs> { \
static const bool is_method = true; \
static const int num_args = Count+1; \
static void execute(lua_State *state, int base, void (CT::*cb) FArgs) { \
LOAD_CLASS() Loads; INVOKE_VOID((self->*cb) Args); } \
}; \
template<FW_TARGSC class RT, class CT> struct function_wrapper<RT (CT::*) FArgs> { \
static const bool is_method = true; \
static const int num_args = Count+1; \
static void execute(lua_State *state, int base, RT (CT::*cb) FArgs) { \
LOAD_CLASS(); Loads; INVOKE_RV((self->*cb) Args); } \
};
#define FW_TARGSC
#define FW_TARGS
INSTANTIATE_WRAPPERS(0, (), (), ;)
#undef FW_TARGS
#undef FW_TARGSC
#define FW_TARGSC FW_TARGS,
#define FW_TARGS class A1
INSTANTIATE_WRAPPERS(1, (A1), (vA1), LOAD_ARG(A1);)
#undef FW_TARGS
#define FW_TARGS class A1, class A2
INSTANTIATE_WRAPPERS(2, (A1,A2), (vA1,vA2), LOAD_ARG(A1); LOAD_ARG(A2);)
#undef FW_TARGS
#define FW_TARGS class A1, class A2, class A3
INSTANTIATE_WRAPPERS(3, (A1,A2,A3), (vA1,vA2,vA3), LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3);)
#undef FW_TARGS
#define FW_TARGS class A1, class A2, class A3, class A4
INSTANTIATE_WRAPPERS(4, (A1,A2,A3,A4), (vA1,vA2,vA3,vA4),
LOAD_ARG(A1); LOAD_ARG(A2); LOAD_ARG(A3); LOAD_ARG(A4);)
#undef FW_TARGS
#undef FW_TARGSC
#undef INSTANTIATE_WRAPPERS
#undef INVOKE_VOID
#undef INVOKE_RV
#undef LOAD_CLASS
#undef LOAD_ARG
template<class T>
class function_identity : public function_identity_base {
T ptr;
public:
typedef function_wrapper<T> wrapper;
function_identity(T ptr)
: function_identity_base(wrapper::num_args), ptr(ptr) {};
virtual void invoke(lua_State *state, int base) { wrapper::execute(state, base, ptr); }
};
template<class T>
inline function_identity_base *wrap_function(T ptr) {
// bah, but didn't have any idea how to allocate statically
return new function_identity<T>(ptr);
}
}

@ -37,6 +37,23 @@ distribution.
namespace DFHack
{
class DFHACK_EXPORT function_identity_base : public type_identity {
int num_args;
public:
function_identity_base(int num_args) : type_identity(0), num_args(num_args) {};
virtual identity_type type() { return IDTYPE_FUNCTION; }
int getNumArgs() { return num_args; }
std::string getFullName() { return "function"; }
virtual void invoke(lua_State *state, int base) = 0;
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 DFHACK_EXPORT primitive_identity : public type_identity {
public:
primitive_identity(size_t size) : type_identity(size) {};
@ -145,6 +162,7 @@ namespace DFHack
namespace df
{
using DFHack::function_identity_base;
using DFHack::primitive_identity;
using DFHack::pointer_identity;
using DFHack::container_identity;
@ -187,6 +205,16 @@ namespace df
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index);
};
class ptr_string_identity : public primitive_identity {
public:
ptr_string_identity() : primitive_identity(sizeof(char*)) {};
std::string getFullName() { return "char*"; }
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_string_identity : public DFHack::constructed_identity {
public:
stl_string_identity()
@ -370,6 +398,28 @@ namespace df
}
};
template<class T>
class enum_list_attr_identity : public container_identity {
public:
typedef enum_list_attr<T> container;
enum_list_attr_identity(type_identity *item)
: container_identity(sizeof(container), NULL, item, NULL)
{}
std::string getFullName(type_identity *item) {
return "enum_list_attr" + container_identity::getFullName(item);
}
protected:
virtual int item_count(void *ptr, CountMode cm) {
return cm == COUNT_WRITE ? 0 : ((container*)ptr)->size;
}
virtual void *item_pointer(type_identity *item, void *ptr, int idx) {
return (void*)&((container*)ptr)->items[idx];
}
};
#define NUMBER_IDENTITY_TRAITS(type) \
template<> struct identity_traits<type> { \
static number_identity<type> identity; \
@ -397,6 +447,16 @@ namespace df
static stl_string_identity *get() { return &identity; }
};
template<> struct identity_traits<char*> {
static ptr_string_identity identity;
static ptr_string_identity *get() { return &identity; }
};
template<> struct identity_traits<const char*> {
static ptr_string_identity identity;
static ptr_string_identity *get() { return &identity; }
};
template<> struct identity_traits<void*> {
static pointer_identity identity;
static pointer_identity *get() { return &identity; }
@ -448,47 +508,51 @@ namespace df
static container_identity *get();
};
template<class T> struct identity_traits<enum_list_attr<T> > {
static container_identity *get();
};
// Container definitions
template<class Enum, class FT>
primitive_identity *identity_traits<enum_field<Enum,FT> >::get() {
inline primitive_identity *identity_traits<enum_field<Enum,FT> >::get() {
return identity_traits<FT>::get();
}
template<class T>
pointer_identity *identity_traits<T *>::get() {
inline pointer_identity *identity_traits<T *>::get() {
static pointer_identity identity(identity_traits<T>::get());
return &identity;
}
template<class T, int sz>
container_identity *identity_traits<T [sz]>::get() {
inline container_identity *identity_traits<T [sz]>::get() {
static buffer_container_identity identity(sz, identity_traits<T>::get());
return &identity;
}
template<class T>
container_identity *identity_traits<std::vector<T> >::get() {
inline container_identity *identity_traits<std::vector<T> >::get() {
typedef std::vector<T> container;
static stl_container_identity<container> identity("vector", identity_traits<T>::get());
return &identity;
}
template<class T>
stl_ptr_vector_identity *identity_traits<std::vector<T*> >::get() {
inline stl_ptr_vector_identity *identity_traits<std::vector<T*> >::get() {
static stl_ptr_vector_identity identity(identity_traits<T>::get());
return &identity;
}
template<class T>
container_identity *identity_traits<std::deque<T> >::get() {
inline container_identity *identity_traits<std::deque<T> >::get() {
typedef std::deque<T> container;
static stl_container_identity<container> identity("deque", identity_traits<T>::get());
return &identity;
}
template<class T>
bit_container_identity *identity_traits<BitArray<T> >::get() {
inline bit_container_identity *identity_traits<BitArray<T> >::get() {
static type_identity *eid = identity_traits<T>::get();
static enum_identity *reid = eid->type() == DFHack::IDTYPE_ENUM ? (enum_identity*)eid : NULL;
static bit_array_identity identity(reid);
@ -496,10 +560,16 @@ namespace df
}
template<class T>
container_identity *identity_traits<DfArray<T> >::get() {
inline container_identity *identity_traits<DfArray<T> >::get() {
typedef DfArray<T> container;
static stl_container_identity<container> identity("DfArray", identity_traits<T>::get());
return &identity;
}
template<class T>
inline container_identity *identity_traits<enum_list_attr<T> >::get() {
static enum_list_attr_identity<T> identity(identity_traits<T>::get());
return &identity;
}
}

@ -68,6 +68,7 @@ namespace DFHack { namespace LuaWrapper {
#define DFHACK_DISPLACE_NAME "DFHack::Displace"
#define DFHACK_NEW_NAME "DFHack::New"
#define DFHACK_ASSIGN_NAME "DFHack::Assign"
#define DFHACK_DELETE_NAME "DFHack::Delete"
/*
* Upvalue: contents of DFHACK_TYPETABLE_NAME
@ -186,5 +187,7 @@ namespace DFHack { namespace LuaWrapper {
* and the enum itself to the _enum metafield.
*/
void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum);
void IndexStatics(lua_State *state, int meta_idx, int ftable_idx, struct_identity *pstruct);
}}

@ -1 +1 @@
Subproject commit 55a120d5bc823b783aeb8b6931ccaa31402fd850
Subproject commit f7c535a64b0858acbb56d38f13dde0c820e2c4bc

@ -61,7 +61,7 @@ dofile("dfusion/editor.lua")
unlockDF()
plugins={}
table.insert(plugins,{"simple_embark","A simple embark dwarf count editor"})
--table.insert(plugins,{"tools","some misc tools"})
table.insert(plugins,{"tools","some misc tools"})
table.insert(plugins,{"embark","Multi race embark"})
table.insert(plugins,{"friendship","Multi race fort enabler"})
--[=[table.insert(plugins,{"items","A collection of item hacking tools"})

@ -272,23 +272,42 @@ function tools.empregnate(unit)
if unit==nil then
error("Failed to empregnate. Unit not selected/valide")
end
print(string.format("%x %x",df.sizeof(unit)))
local arr1=unit.appearance.unk_51c
local arr2=unit.appearance.unk_51c
local created=false
if unit.relations.pregnancy_ptr == nil then
print("creating preg ptr.")
unit.relations.pregnancy_ptr=unit.relations:_field("pregnancy_ptr"):new()--=df.new(unit.relations.pregnancy_ptr._kind)
if false then
print(string.format("%x %x",df.sizeof(unit.relations:_field("pregnancy_ptr"))))
return
end
local size,offset=df.sizeof(unit.relations:_field("pregnancy_ptr"))
local s1=df.sizeof(arr1)
local s2=df.sizeof(arr2)
engine.poked(offset,engine.alloc(s1+s2))
created=true
end
local tarr1=unit.relations.pregnancy_ptr:deref().anon_1
local tarr2=unit.relations.pregnancy_ptr:deref().anon_2
if created or tarr1.size~= arr1.size then
local tarr1=unit.relations.pregnancy_ptr.anon_1
local tarr2=unit.relations.pregnancy_ptr.anon_2
if created or #tarr1~= #arr1 then
print(string.format("Before: %d vs %d",#tarr1,#arr1))
print("Setting up arr1")
initType(tarr1,arr1.size)
print(string.format("%x %x",df.sizeof(tarr1)))
--tarr1=arr1:new()
local size,offset=df.sizeof(tarr1)
engine.poked(offset,engine.alloc(#arr1))
engine.poked(offset+4,#arr1)
print(string.format("after: %d vs %d",#tarr1,#arr1))
end
if created or tarr2.size~= arr2.size then
print("Setting up arr1")
initType(tarr2,arr2.size)
if created or #tarr2~= #arr2 then
print("Setting up arr2")
--tarr2=arr2:new()
local size,offset=df.sizeof(tarr2)
engine.poked(offset,engine.alloc(#arr2*2))
engine.poked(offset+4,#arr2)
end
print("Setting preg timer.")
unit.relations.pregnancy_timer=10

@ -1 +1 @@
Subproject commit 7525c003089367823183eaf5093a90271a5eb9b4
Subproject commit a0f6808254168063449b4f7e93afbd879bd1fafd