|
|
@ -48,6 +48,155 @@ static luaL_Reg no_functions[] = { { NULL, NULL } };
|
|
|
|
inline void lua_dup(lua_State *state) { lua_pushvalue(state, -1); }
|
|
|
|
inline void lua_dup(lua_State *state) { lua_pushvalue(state, -1); }
|
|
|
|
inline void lua_swap(lua_State *state) { lua_insert(state, -2); }
|
|
|
|
inline void lua_swap(lua_State *state) { lua_insert(state, -2); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define UPVAL_TYPETABLE lua_upvalueindex(1)
|
|
|
|
|
|
|
|
#define UPVAL_METATABLE lua_upvalueindex(2)
|
|
|
|
|
|
|
|
#define UPVAL_FIELDTABLE lua_upvalueindex(3)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
struct DFRefHeader {
|
|
|
|
|
|
|
|
void *ptr;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline bool is_self_contained(DFRefHeader *ptr) {
|
|
|
|
|
|
|
|
void **pp = &ptr->ptr;
|
|
|
|
|
|
|
|
return **(void****)pp == (pp + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void field_error(lua_State *state, int index, const char *err, const char *mode = "read")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lua_getfield(state, UPVAL_METATABLE, "__metatable");
|
|
|
|
|
|
|
|
const char *cname = lua_tostring(state, -1);
|
|
|
|
|
|
|
|
const char *fname = lua_tostring(state, index);
|
|
|
|
|
|
|
|
luaL_error(state, "Cannot %s field %s.%s: %s.",
|
|
|
|
|
|
|
|
mode, (cname ? cname : "?"), (fname ? fname : "?"), err);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int push_object_internal(lua_State *state, type_identity *type, void *ptr, bool in_method = true);
|
|
|
|
|
|
|
|
static void *get_object_internal(lua_State *state, type_identity *type, int val_index, bool in_method = true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int DFHack::PushDFObject(lua_State *state, type_identity *type, void *ptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return push_object_internal(state, type, ptr, false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void *DFHack::GetDFObject(lua_State *state, type_identity *type, int val_index)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return get_object_internal(state, type, val_index, false);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Primitive identity methods */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int constructed_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return 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");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int enum_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return 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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int df::number_identity_base::lua_read(lua_State *state, int fname_idx, void *ptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lua_pushnumber(state, read(ptr));
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int df::bool_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lua_pushboolean(state, *(bool*)ptr);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
|
|
|
*pb = lua_toboolean(state, val_index);
|
|
|
|
|
|
|
|
else if (lua_isnumber(state, val_index))
|
|
|
|
|
|
|
|
*pb = lua_tonumber(state, val_index);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
field_error(state, fname_idx, "boolean or number expected", "write");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int 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());
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int do_read_pointer(lua_State *state, int, void *ptr, type_identity *target)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
void *val = *(void**)ptr;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (val == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lua_pushnil(state);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return push_object_internal(state, target, val);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int df::pointer_identity::lua_read(lua_State *state, int fname_idx, void *ptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return do_read_pointer(state, fname_idx, ptr, target);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void do_write_pointer(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);
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
do_write_pointer(state, fname_idx, ptr, target, val_index);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* */
|
|
|
|
|
|
|
|
|
|
|
|
static int change_error(lua_State *state)
|
|
|
|
static int change_error(lua_State *state)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
luaL_error(state, "Attempt to change a read-only table.\n");
|
|
|
|
luaL_error(state, "Attempt to change a read-only table.\n");
|
|
|
@ -111,6 +260,169 @@ static bool RegisterTypeInfo(lua_State *state, void *node)
|
|
|
|
return added;
|
|
|
|
return added;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const struct_field_info *find_field(lua_State *state, int index, const char *mode = "read")
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
lua_pushvalue(state, index);
|
|
|
|
|
|
|
|
lua_rawget(state, UPVAL_FIELDTABLE);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!lua_islightuserdata(state, -1))
|
|
|
|
|
|
|
|
field_error(state, index, "not found");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void *p = lua_touserdata(state, -1);
|
|
|
|
|
|
|
|
lua_pop(state, 1);
|
|
|
|
|
|
|
|
return (struct_field_info*)p;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int 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 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case struct_field_info::PRIMITIVE:
|
|
|
|
|
|
|
|
case struct_field_info::SUBSTRUCT:
|
|
|
|
|
|
|
|
case struct_field_info::CONTAINER:
|
|
|
|
|
|
|
|
return field->type->lua_read(state, 2, ptr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case struct_field_info::POINTER:
|
|
|
|
|
|
|
|
return do_read_pointer(state, 2, ptr, field->type);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case struct_field_info::STATIC_ARRAY:
|
|
|
|
|
|
|
|
case struct_field_info::STL_VECTOR_PTR:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case struct_field_info::END:
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void write_field(lua_State *state, const struct_field_info *field, void *ptr)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (field->mode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case struct_field_info::STATIC_STRING:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
const char *str = lua_tolstring(state, -1, &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, 3);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case struct_field_info::POINTER:
|
|
|
|
|
|
|
|
do_write_pointer(state, 2, ptr, field->type, 3);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int meta_global_index(lua_State *state)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const struct_field_info *field = find_field(state, 2);
|
|
|
|
|
|
|
|
void *ptr = *(void**)field->offset;
|
|
|
|
|
|
|
|
if (!ptr)
|
|
|
|
|
|
|
|
field_error(state, 2, "global address not known");
|
|
|
|
|
|
|
|
return read_field(state, field, ptr);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int meta_global_newindex(lua_State *state)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
const struct_field_info *field = find_field(state, 2);
|
|
|
|
|
|
|
|
void *ptr = *(void**)field->offset;
|
|
|
|
|
|
|
|
if (!ptr)
|
|
|
|
|
|
|
|
field_error(state, 2, "global address not known", "write");
|
|
|
|
|
|
|
|
write_field(state, field, ptr);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void IndexFields(lua_State *state, const struct_field_info *fields)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int base = lua_gettop(state);
|
|
|
|
|
|
|
|
lua_newtable(state); // read
|
|
|
|
|
|
|
|
lua_newtable(state); // write
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (; fields->mode != struct_field_info::END; ++fields)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
switch (fields->mode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case struct_field_info::END:
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case struct_field_info::PRIMITIVE:
|
|
|
|
|
|
|
|
case struct_field_info::STATIC_STRING:
|
|
|
|
|
|
|
|
case struct_field_info::POINTER:
|
|
|
|
|
|
|
|
lua_pushstring(state,fields->name);
|
|
|
|
|
|
|
|
lua_pushlightuserdata(state,(void*)fields);
|
|
|
|
|
|
|
|
lua_settable(state,base+2);
|
|
|
|
|
|
|
|
// fallthrough
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case struct_field_info::STATIC_ARRAY:
|
|
|
|
|
|
|
|
case struct_field_info::SUBSTRUCT:
|
|
|
|
|
|
|
|
case struct_field_info::CONTAINER:
|
|
|
|
|
|
|
|
case struct_field_info::STL_VECTOR_PTR:
|
|
|
|
|
|
|
|
lua_pushstring(state,fields->name);
|
|
|
|
|
|
|
|
lua_pushlightuserdata(state,(void*)fields);
|
|
|
|
|
|
|
|
lua_settable(state,base+1);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void MakeFieldMetatable(lua_State *state, struct_identity *pstruct,
|
|
|
|
|
|
|
|
lua_CFunction reader, lua_CFunction writer)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int base = lua_gettop(state);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_newtable(state); // metatable
|
|
|
|
|
|
|
|
IndexFields(state, pstruct->getFields()); // read, write
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_pushstring(state, pstruct->getName());
|
|
|
|
|
|
|
|
lua_setfield(state, base+1, "__metatable");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_pushlightuserdata(state, pstruct);
|
|
|
|
|
|
|
|
lua_setfield(state, base+1, "_identity");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_getfield(state, LUA_REGISTRYINDEX, "DFHack::DFTypes");
|
|
|
|
|
|
|
|
lua_pushvalue(state, base+1);
|
|
|
|
|
|
|
|
lua_pushvalue(state, base+2);
|
|
|
|
|
|
|
|
lua_pushcclosure(state, reader, 3);
|
|
|
|
|
|
|
|
lua_setfield(state, base+1, "__index");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_getfield(state, LUA_REGISTRYINDEX, "DFHack::DFTypes");
|
|
|
|
|
|
|
|
lua_pushvalue(state, base+1);
|
|
|
|
|
|
|
|
lua_pushvalue(state, base+3);
|
|
|
|
|
|
|
|
lua_pushcclosure(state, writer, 3);
|
|
|
|
|
|
|
|
lua_setfield(state, base+1, "__newindex");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// returns: [metatable readfields writefields];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int push_object_internal(lua_State *state, type_identity *type, void *ptr, bool in_method)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void *get_object_internal(lua_State *state, type_identity *type, int val_index, bool in_method)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void RenderTypeChildren(lua_State *state, const std::vector<compound_identity*> &children);
|
|
|
|
static void RenderTypeChildren(lua_State *state, const std::vector<compound_identity*> &children);
|
|
|
|
|
|
|
|
|
|
|
|
static void RenderType(lua_State *state, compound_identity *node)
|
|
|
|
static void RenderType(lua_State *state, compound_identity *node)
|
|
|
@ -150,13 +462,11 @@ static void RenderType(lua_State *state, compound_identity *node)
|
|
|
|
|
|
|
|
|
|
|
|
if (eid->getFirstItem() <= eid->getLastItem())
|
|
|
|
if (eid->getFirstItem() <= eid->getLastItem())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
lua_pushstring(state, "_first_item");
|
|
|
|
|
|
|
|
lua_pushinteger(state, eid->getFirstItem());
|
|
|
|
lua_pushinteger(state, eid->getFirstItem());
|
|
|
|
lua_settable(state, base);
|
|
|
|
lua_setfield(state, base, "_first_item");
|
|
|
|
|
|
|
|
|
|
|
|
lua_pushstring(state, "_last_item");
|
|
|
|
|
|
|
|
lua_pushinteger(state, eid->getLastItem());
|
|
|
|
lua_pushinteger(state, eid->getLastItem());
|
|
|
|
lua_settable(state, base);
|
|
|
|
lua_setfield(state, base, "_last_item");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SaveTypeInfo(state, node);
|
|
|
|
SaveTypeInfo(state, node);
|
|
|
@ -171,6 +481,25 @@ static void RenderType(lua_State *state, compound_identity *node)
|
|
|
|
|
|
|
|
|
|
|
|
assert(base == lua_gettop(state));
|
|
|
|
assert(base == lua_gettop(state));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (node->type() == IDTYPE_GLOBAL)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto gid = (global_identity*)node;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MakeFieldMetatable(state, gid, meta_global_index, meta_global_newindex);
|
|
|
|
|
|
|
|
lua_pop(state, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_dup(state);
|
|
|
|
|
|
|
|
lua_setmetatable(state, base);
|
|
|
|
|
|
|
|
lua_swap(state); // -> meta curtable
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
freeze_table(state, true, "global");
|
|
|
|
|
|
|
|
lua_getfield(state, base, "__newindex");
|
|
|
|
|
|
|
|
lua_setfield(state, -2, "__newindex");
|
|
|
|
|
|
|
|
lua_pop(state, 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lua_remove(state, base);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
freeze_table(state, false, node->getName());
|
|
|
|
freeze_table(state, false, node->getName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|