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 mkdir VC2010
cd VC2010 cd VC2010
echo generating a build folder 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 mkdir VC2010
cd VC2010 cd VC2010
echo Pre-generating a build folder echo Pre-generating a build folder
cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX=%_DF_PATH% cmake ..\.. -G"Visual Studio 10" -DCMAKE_INSTALL_PREFIX="%_DF_PATH%"
cmake-gui . cmake-gui .

@ -3,4 +3,4 @@ IF NOT EXIST DF_PATH.txt SET _DF_PATH=%CD%\DF
mkdir VC2010 mkdir VC2010
cd VC2010 cd VC2010
echo generating a build folder 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). ** LUA_BUILD_AS_DLL to get it).
*/ */
#ifdef __cplusplus #ifdef __cplusplus
#define LUA_API_EXTERN extern "C" #define LUA_API_EXTERN extern
#else #else
#define LUA_API_EXTERN extern #define LUA_API_EXTERN extern
#endif #endif

@ -51,6 +51,11 @@ void type_identity::do_copy_pod(void *tgt, const void *src) {
memmove(tgt, src, size); memmove(tgt, src, size);
}; };
bool type_identity::do_destroy_pod(void *obj) {
free(obj);
return true;
}
void *type_identity::allocate() { void *type_identity::allocate() {
if (can_allocate()) if (can_allocate())
return do_allocate(); return do_allocate();
@ -65,6 +70,13 @@ bool type_identity::copy(void *tgt, const void *src) {
return false; 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 *enum_identity::do_allocate() {
void *p = malloc(byte_size()); void *p = malloc(byte_size());
memcpy(p, &first_item_value, std::min(byte_size(), sizeof(int64_t))); 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, compound_identity *scope_parent, const char *dfhack_name,
type_identity *base_type, type_identity *base_type,
int64_t first_item_value, int64_t last_item_value, 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), : compound_identity(size, NULL, scope_parent, dfhack_name),
first_item_value(first_item_value), last_item_value(last_item_value), 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 "df/ui.h"
#include "DataIdentity.h" #include "DataIdentity.h"
#include "DataFuncs.h"
#include <stddef.h> #include <stddef.h>
@ -30,6 +31,8 @@ namespace df {
bool_identity identity_traits<bool>::identity; bool_identity identity_traits<bool>::identity;
stl_string_identity identity_traits<std::string>::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; pointer_identity identity_traits<void*>::identity;
stl_ptr_vector_identity identity_traits<std::vector<void*> >::identity; stl_ptr_vector_identity identity_traits<std::vector<void*> >::identity;
stl_bit_vector_identity identity_traits<std::vector<bool> >::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 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 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 #define FLD_END struct_field_info::END
// Field definitions // Field definitions

@ -36,6 +36,7 @@ distribution.
#include "DataDefs.h" #include "DataDefs.h"
#include "DataIdentity.h" #include "DataIdentity.h"
#include "LuaWrapper.h" #include "LuaWrapper.h"
#include "DataFuncs.h"
#include "MiscUtils.h" #include "MiscUtils.h"
@ -49,6 +50,16 @@ using namespace DFHack::LuaWrapper;
* Identity object read/write methods * * 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) void constructed_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{ {
push_object_internal(state, this, 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"); 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) void df::stl_string_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
{ {
auto pstr = (std::string*)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); 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) static void *find_field(lua_State *state, int index, const char *mode)
{ {
lookup_field(state, index, 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); void *p = lua_touserdata(state, -1);
lua_pop(state, 1); lua_pop(state, 1);
// NULL => metafield
if (!p)
get_metafield(state);
return p; return p;
} }
@ -295,6 +339,10 @@ static void read_field(lua_State *state, const struct_field_info *field, void *p
return; return;
} }
case struct_field_info::OBJ_METHOD:
case struct_field_info::CLASS_METHOD:
// error
case struct_field_info::PRIMITIVE: case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT: case struct_field_info::SUBSTRUCT:
field->type->lua_read(state, 2, ptr); 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); push_adhoc_pointer(state, ptr, field->type);
return; return;
case struct_field_info::OBJ_METHOD:
case struct_field_info::CLASS_METHOD:
// error
case struct_field_info::CONTAINER: case struct_field_info::CONTAINER:
read_field(state, field, ptr); read_field(state, field, ptr);
return; return;
@ -371,6 +423,10 @@ static void write_field(lua_State *state, const struct_field_info *field, void *
return; return;
} }
case struct_field_info::OBJ_METHOD:
case struct_field_info::CLASS_METHOD:
// error
case struct_field_info::PRIMITIVE: case struct_field_info::PRIMITIVE:
case struct_field_info::SUBSTRUCT: case struct_field_info::SUBSTRUCT:
case struct_field_info::CONTAINER: case struct_field_info::CONTAINER:
@ -418,13 +474,6 @@ static int meta_ptr_tostring(lua_State *state)
return 1; 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. * 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"); uint8_t *ptr = get_object_addr(state, 1, 2, "read");
auto field = (struct_field_info*)find_field(state, 2, "read"); auto field = (struct_field_info*)find_field(state, 2, "read");
if (!field) if (!field)
return get_metafield(state); return 1;
read_field(state, field, ptr + field->offset); read_field(state, field, ptr + field->offset);
return 1; 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"); uint8_t *ptr = get_object_addr(state, 1, 2, "reference");
auto field = (struct_field_info*)find_field(state, 2, "reference"); auto field = (struct_field_info*)find_field(state, 2, "reference");
if (!field) 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); field_reference(state, field, ptr + field->offset);
return 1; return 1;
} }
@ -461,7 +510,7 @@ static int meta_struct_newindex(lua_State *state)
uint8_t *ptr = get_object_addr(state, 1, 2, "write"); uint8_t *ptr = get_object_addr(state, 1, 2, "write");
auto field = (struct_field_info*)find_field(state, 2, "write"); auto field = (struct_field_info*)find_field(state, 2, "write");
if (!field) 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); write_field(state, field, ptr + field->offset, 3);
return 0; return 0;
} }
@ -475,7 +524,7 @@ static int meta_primitive_index(lua_State *state)
uint8_t *ptr = get_object_addr(state, 1, 2, "read"); uint8_t *ptr = get_object_addr(state, 1, 2, "read");
auto type = (type_identity*)find_field(state, 2, "read"); auto type = (type_identity*)find_field(state, 2, "read");
if (!type) if (!type)
return get_metafield(state); return 1;
type->lua_read(state, 2, ptr); type->lua_read(state, 2, ptr);
return 1; return 1;
} }
@ -488,7 +537,7 @@ static int meta_primitive_newindex(lua_State *state)
uint8_t *ptr = get_object_addr(state, 1, 2, "write"); uint8_t *ptr = get_object_addr(state, 1, 2, "write");
auto type = (type_identity*)find_field(state, 2, "write"); auto type = (type_identity*)find_field(state, 2, "write");
if (!type) 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); type->lua_write(state, 2, ptr, 3);
return 0; 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 (lua_isuserdata(state, -1) && !lua_touserdata(state, -1))
{ {
if (mode) if (mode)
field_error(state, field, "builtin property", mode); field_error(state, field, "builtin property or method", mode);
lua_pop(state, 1); lua_pop(state, 1);
get_metafield(state); 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"); auto field = (struct_field_info*)find_field(state, 2, "read");
if (!field) if (!field)
return get_metafield(state); return 1;
void *ptr = *(void**)field->offset; void *ptr = *(void**)field->offset;
if (!ptr) if (!ptr)
field_error(state, 2, "global address not known", "read"); 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"); auto field = (struct_field_info*)find_field(state, 2, "write");
if (!field) if (!field)
field_error(state, 2, "builtin property", "write"); field_error(state, 2, "builtin property or method", "write");
void *ptr = *(void**)field->offset; void *ptr = *(void**)field->offset;
if (!ptr) if (!ptr)
field_error(state, 2, "global address not known", "write"); field_error(state, 2, "global address not known", "write");
@ -750,27 +799,92 @@ static int meta_global_newindex(lua_State *state)
return 0; 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. * Add fields in the array to the UPVAL_FIELDTABLE candidates on the stack.
*/ */
static void IndexFields(lua_State *state, struct_identity *pstruct) 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()) for (struct_identity *p = pstruct; p; p = p->getParent())
{ {
auto fields = p->getFields(); auto fields = p->getFields();
if (!fields)
continue;
for (; fields; ++fields) for (int i = 0; fields[i].mode != struct_field_info::END; ++i)
{
switch (fields[i].mode)
{ {
if (fields->mode == struct_field_info::END) case struct_field_info::OBJ_METHOD:
AddMethodWrapper(state, base+1, base+2, fields[i].name,
(function_identity_base*)fields[i].type);
break; break;
lua_pushstring(state,fields->name); case struct_field_info::CLASS_METHOD:
lua_pushlightuserdata(state,(void*)fields); break;
lua_rawset(state,base);
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 (int i = 0; fields[i].mode != struct_field_info::END; ++i)
{
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;
default:
break;
}
} }
} }
} }

@ -593,10 +593,7 @@ static int meta_new(lua_State *state)
void *ptr = id->allocate(); void *ptr = id->allocate();
if (!ptr) if (!ptr)
{ luaL_error(state, "Cannot allocate %s", id->getFullName().c_str());
lua_pushnil(state);
return 1;
}
if (lua_isuserdata(state, 1)) if (lua_isuserdata(state, 1))
{ {
@ -630,6 +627,30 @@ static int meta_assign(lua_State *state)
return 0; 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. * Verify that the object is a DF ref with UPVAL_METATABLE.
* If everything ok, extract the address. * If everything ok, extract the address.
@ -677,6 +698,30 @@ static int meta_ptr_tostring(lua_State *state)
return 1; 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. * 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"); lua_setfield(state, meta_idx, "new");
EnableMetaField(state, read_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_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
lua_setfield(state, meta_idx, "assign"); lua_setfield(state, meta_idx, "assign");
EnableMetaField(state, read_idx, "assign"); EnableMetaField(state, read_idx, "assign");
@ -835,127 +884,166 @@ static void AssociateId(lua_State *state, int table, int val, const char *name)
lua_rawset(state, table); lua_rawset(state, table);
} }
static void RenderType(lua_State *state, compound_identity *node) static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid)
{ {
assert(node->getName()); const char *const *keys = eid->getKeys();
std::string name = node->getFullName();
// Create a new table attached to ftable as __index
lua_newtable(state); lua_newtable(state);
if (!lua_checkstack(state, 20))
return;
int base = lua_gettop(state); lua_dup(state);
lua_setmetatable(state, ftable);
switch (node->type())
{
case IDTYPE_STRUCT:
lua_pushstring(state, "struct-type");
lua_setfield(state, base, "_kind");
break;
case IDTYPE_CLASS:
lua_pushstring(state, "class-type");
lua_setfield(state, base, "_kind");
break;
case IDTYPE_ENUM: int base = lua_gettop(state);
{
lua_pushstring(state, "enum-type");
lua_setfield(state, base, "_kind");
enum_identity *eid = (enum_identity*)node; lua_newtable(state);
const char *const *keys = eid->getKeys();
// For enums, set mapping between keys and values // For enums, set mapping between keys and values
for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++) for (int64_t i = eid->getFirstItem(), j = 0; i <= eid->getLastItem(); i++, j++)
{ {
if (keys[j]) if (keys[j])
AssociateId(state, base, i, keys[j]); AssociateId(state, base+1, i, keys[j]);
} }
if (eid->getFirstItem() <= eid->getLastItem()) if (eid->getFirstItem() <= eid->getLastItem())
{ {
lua_pushinteger(state, eid->getFirstItem()); lua_pushinteger(state, eid->getFirstItem());
lua_setfield(state, base, "_first_item"); lua_setfield(state, base+1, "_first_item");
lua_pushinteger(state, eid->getLastItem()); lua_pushinteger(state, eid->getLastItem());
lua_setfield(state, base, "_last_item"); lua_setfield(state, base+1, "_last_item");
} }
SaveInTable(state, node, DFHACK_ENUM_TABLE_NAME); SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
}
break;
case IDTYPE_BITFIELD: // Add an attribute table if any
if (eid->getAttrs())
{ {
lua_pushstring(state, "bitfield-type"); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME);
lua_setfield(state, base, "_kind"); 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);
}
bitfield_identity *eid = (bitfield_identity*)node; static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *eid)
{
auto bits = eid->getBits(); auto bits = eid->getBits();
for (int i = 0; i < eid->getNumBits(); i++) for (int i = 0; i < eid->getNumBits(); i++)
{ {
if (bits[i].name) if (bits[i].name)
AssociateId(state, base, i, bits[i].name); AssociateId(state, ftable, i, bits[i].name);
if (bits[i].size > 1) if (bits[i].size > 1)
i += bits[i].size-1; i += bits[i].size-1;
} }
lua_pushinteger(state, 0); lua_pushinteger(state, 0);
lua_setfield(state, base, "_first_item"); lua_setfield(state, ftable, "_first_item");
lua_pushinteger(state, eid->getNumBits()-1); lua_pushinteger(state, eid->getNumBits()-1);
lua_setfield(state, base, "_last_item"); lua_setfield(state, ftable, "_last_item");
SaveInTable(state, node, DFHACK_ENUM_TABLE_NAME); SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME);
} }
break;
default: 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;
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, ftable, "_kind");
IndexStatics(state, base+2, base+3, (struct_identity*)node);
break; break;
}
RenderTypeChildren(state, node->getScopeChildren()); case IDTYPE_CLASS:
lua_pushstring(state, "class-type");
lua_setfield(state, ftable, "_kind");
IndexStatics(state, base+2, base+3, (struct_identity*)node);
break;
assert(base == lua_gettop(state)); case IDTYPE_ENUM:
lua_pushstring(state, "enum-type");
lua_setfield(state, ftable, "_kind");
FillEnumKeys(state, ftable, (enum_identity*)node);
break;
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME); case IDTYPE_BITFIELD:
lua_setfield(state, base, "sizeof"); lua_pushstring(state, "bitfield-type");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME); lua_setfield(state, ftable, "_kind");
lua_setfield(state, base, "new"); FillBitfieldKeys(state, ftable, (bitfield_identity*)node);
break;
if (node->type() == IDTYPE_GLOBAL) case IDTYPE_GLOBAL:
{ {
RenderTypeChildren(state, node->getScopeChildren());
BuildTypeMetatable(state, node); BuildTypeMetatable(state, node);
// Set metatable for the inner table
lua_dup(state); lua_dup(state);
lua_setmetatable(state, base); lua_setmetatable(state, base+3);
lua_swap(state); // -> meta curtable
freeze_table(state, true, "global"); lua_getfield(state, -1, "__newindex");
lua_setfield(state, base+2, "__newindex");
// Copy __newindex to the outer metatable lua_pop(state, 3);
lua_getfield(state, base, "__newindex"); return;
lua_setfield(state, -2, "__newindex");
lua_remove(state, base);
} }
else
{ default:
freeze_table(state, true, name.c_str()); break;
} }
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPE_TOSTRING_NAME); RenderTypeChildren(state, node->getScopeChildren());
lua_setfield(state, -2, "__tostring");
lua_pushlightuserdata(state, node); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME);
lua_setfield(state, -2, "_identity"); lua_setfield(state, ftable, "sizeof");
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) 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_pushcclosure(state, meta_assign, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); 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); luaL_register(state, "df", no_functions);
{ {
@ -1020,6 +1112,8 @@ static void DoAttach(lua_State *state)
lua_setfield(state, -2, "sizeof"); lua_setfield(state, -2, "sizeof");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME);
lua_setfield(state, -2, "new"); 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_getfield(state, LUA_REGISTRYINDEX, DFHACK_DISPLACE_NAME);
lua_setfield(state, -2, "_displace"); lua_setfield(state, -2, "_displace");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);

@ -49,6 +49,7 @@ namespace DFHack
enum identity_type { enum identity_type {
IDTYPE_GLOBAL, IDTYPE_GLOBAL,
IDTYPE_FUNCTION,
IDTYPE_PRIMITIVE, IDTYPE_PRIMITIVE,
IDTYPE_POINTER, IDTYPE_POINTER,
IDTYPE_CONTAINER, IDTYPE_CONTAINER,
@ -72,10 +73,12 @@ namespace DFHack
void *do_allocate_pod(); void *do_allocate_pod();
void do_copy_pod(void *tgt, const void *src); void do_copy_pod(void *tgt, const void *src);
bool do_destroy_pod(void *obj);
virtual bool can_allocate() { return true; } virtual bool can_allocate() { return true; }
virtual void *do_allocate() { return do_allocate_pod(); } virtual void *do_allocate() { return do_allocate_pod(); }
virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } 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: public:
virtual ~type_identity() {} virtual ~type_identity() {}
@ -100,6 +103,7 @@ namespace DFHack
void *allocate(); void *allocate();
bool copy(void *tgt, const void *src); bool copy(void *tgt, const void *src);
bool destroy(void *obj);
}; };
class DFHACK_EXPORT constructed_identity : public type_identity { class DFHACK_EXPORT constructed_identity : public type_identity {
@ -109,12 +113,13 @@ namespace DFHack
constructed_identity(size_t size, TAllocateFn alloc) constructed_identity(size_t size, TAllocateFn alloc)
: type_identity(size), allocator(alloc) {}; : type_identity(size), allocator(alloc) {};
virtual bool isPrimitive() { return false; }
virtual bool isConstructed() { return true; }
virtual bool can_allocate() { return (allocator != NULL); } virtual bool can_allocate() { return (allocator != NULL); }
virtual void *do_allocate() { return allocator(NULL,NULL); } virtual void *do_allocate() { return allocator(NULL,NULL); }
virtual void do_copy(void *tgt, const void *src) { allocator(tgt,src); } 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_read(lua_State *state, int fname_idx, void *ptr);
virtual void lua_write(lua_State *state, int fname_idx, void *ptr, int val_index); 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 bool can_allocate() { return true; }
virtual void *do_allocate() { return do_allocate_pod(); } virtual void *do_allocate() { return do_allocate_pod(); }
virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } 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: public:
bitfield_identity(size_t size, bitfield_identity(size_t size,
@ -177,6 +183,8 @@ namespace DFHack
virtual void build_metatable(lua_State *state); virtual void build_metatable(lua_State *state);
}; };
class struct_identity;
class DFHACK_EXPORT enum_identity : public compound_identity { class DFHACK_EXPORT enum_identity : public compound_identity {
const char *const *keys; const char *const *keys;
int64_t first_item_value; int64_t first_item_value;
@ -184,17 +192,22 @@ namespace DFHack
type_identity *base_type; type_identity *base_type;
const void *attrs;
struct_identity *attr_type;
protected: protected:
virtual bool can_allocate() { return true; } virtual bool can_allocate() { return true; }
virtual void *do_allocate(); virtual void *do_allocate();
virtual void do_copy(void *tgt, const void *src) { do_copy_pod(tgt, src); } 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: public:
enum_identity(size_t size, enum_identity(size_t size,
compound_identity *scope_parent, const char *dfhack_name, compound_identity *scope_parent, const char *dfhack_name,
type_identity *base_type, type_identity *base_type,
int64_t first_item_value, int64_t last_item_value, 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; } virtual identity_type type() { return IDTYPE_ENUM; }
@ -204,6 +217,8 @@ namespace DFHack
const char *const *getKeys() { return keys; } const char *const *getKeys() { return keys; }
type_identity *getBaseType() { return base_type; } type_identity *getBaseType() { return base_type; }
const void *getAttrs() { return attrs; }
struct_identity *getAttrType() { return attr_type; }
virtual bool isPrimitive() { return true; } virtual bool isPrimitive() { return true; }
virtual bool isConstructed() { return false; } virtual bool isConstructed() { return false; }
@ -221,7 +236,9 @@ namespace DFHack
STATIC_ARRAY, STATIC_ARRAY,
SUBSTRUCT, SUBSTRUCT,
CONTAINER, CONTAINER,
STL_VECTOR_PTR STL_VECTOR_PTR,
OBJ_METHOD,
CLASS_METHOD
}; };
Mode mode; Mode mode;
const char *name; const char *name;
@ -409,6 +426,14 @@ namespace df
template<class T> template<class T>
void *allocator_fn(void *out, const void *in) { void *allocator_fn(void *out, const void *in) {
if (out) { *(T*)out = *(const T*)in; return out; } 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(); 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 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 { class DFHACK_EXPORT primitive_identity : public type_identity {
public: public:
primitive_identity(size_t size) : type_identity(size) {}; primitive_identity(size_t size) : type_identity(size) {};
@ -145,6 +162,7 @@ namespace DFHack
namespace df namespace df
{ {
using DFHack::function_identity_base;
using DFHack::primitive_identity; using DFHack::primitive_identity;
using DFHack::pointer_identity; using DFHack::pointer_identity;
using DFHack::container_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); 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 { class stl_string_identity : public DFHack::constructed_identity {
public: public:
stl_string_identity() 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) \ #define NUMBER_IDENTITY_TRAITS(type) \
template<> struct identity_traits<type> { \ template<> struct identity_traits<type> { \
static number_identity<type> identity; \ static number_identity<type> identity; \
@ -397,6 +447,16 @@ namespace df
static stl_string_identity *get() { return &identity; } 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*> { template<> struct identity_traits<void*> {
static pointer_identity identity; static pointer_identity identity;
static pointer_identity *get() { return &identity; } static pointer_identity *get() { return &identity; }
@ -448,47 +508,51 @@ namespace df
static container_identity *get(); static container_identity *get();
}; };
template<class T> struct identity_traits<enum_list_attr<T> > {
static container_identity *get();
};
// Container definitions // Container definitions
template<class Enum, class FT> 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(); return identity_traits<FT>::get();
} }
template<class T> template<class T>
pointer_identity *identity_traits<T *>::get() { inline pointer_identity *identity_traits<T *>::get() {
static pointer_identity identity(identity_traits<T>::get()); static pointer_identity identity(identity_traits<T>::get());
return &identity; return &identity;
} }
template<class T, int sz> 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()); static buffer_container_identity identity(sz, identity_traits<T>::get());
return &identity; return &identity;
} }
template<class T> 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; typedef std::vector<T> container;
static stl_container_identity<container> identity("vector", identity_traits<T>::get()); static stl_container_identity<container> identity("vector", identity_traits<T>::get());
return &identity; return &identity;
} }
template<class T> 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()); static stl_ptr_vector_identity identity(identity_traits<T>::get());
return &identity; return &identity;
} }
template<class T> 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; typedef std::deque<T> container;
static stl_container_identity<container> identity("deque", identity_traits<T>::get()); static stl_container_identity<container> identity("deque", identity_traits<T>::get());
return &identity; return &identity;
} }
template<class T> 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 type_identity *eid = identity_traits<T>::get();
static enum_identity *reid = eid->type() == DFHack::IDTYPE_ENUM ? (enum_identity*)eid : NULL; static enum_identity *reid = eid->type() == DFHack::IDTYPE_ENUM ? (enum_identity*)eid : NULL;
static bit_array_identity identity(reid); static bit_array_identity identity(reid);
@ -496,10 +560,16 @@ namespace df
} }
template<class T> template<class T>
container_identity *identity_traits<DfArray<T> >::get() { inline container_identity *identity_traits<DfArray<T> >::get() {
typedef DfArray<T> container; typedef DfArray<T> container;
static stl_container_identity<container> identity("DfArray", identity_traits<T>::get()); static stl_container_identity<container> identity("DfArray", identity_traits<T>::get());
return &identity; 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_DISPLACE_NAME "DFHack::Displace"
#define DFHACK_NEW_NAME "DFHack::New" #define DFHACK_NEW_NAME "DFHack::New"
#define DFHACK_ASSIGN_NAME "DFHack::Assign" #define DFHACK_ASSIGN_NAME "DFHack::Assign"
#define DFHACK_DELETE_NAME "DFHack::Delete"
/* /*
* Upvalue: contents of DFHACK_TYPETABLE_NAME * Upvalue: contents of DFHACK_TYPETABLE_NAME
@ -186,5 +187,7 @@ namespace DFHack { namespace LuaWrapper {
* and the enum itself to the _enum metafield. * and the enum itself to the _enum metafield.
*/ */
void AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx, type_identity *ienum); 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() unlockDF()
plugins={} plugins={}
table.insert(plugins,{"simple_embark","A simple embark dwarf count editor"}) 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,{"embark","Multi race embark"})
table.insert(plugins,{"friendship","Multi race fort enabler"}) table.insert(plugins,{"friendship","Multi race fort enabler"})
--[=[table.insert(plugins,{"items","A collection of item hacking tools"}) --[=[table.insert(plugins,{"items","A collection of item hacking tools"})

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

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