Export the type tree with enum keys to lua.

develop
Alexander Gavrilov 2012-03-19 20:12:27 +04:00
parent 296d3a0af3
commit dbbd9acfad
8 changed files with 267 additions and 7 deletions

@ -103,6 +103,7 @@ ENDIF()
# use shared libraries for protobuf # use shared libraries for protobuf
ADD_DEFINITIONS(-DPROTOBUF_USE_DLLS) ADD_DEFINITIONS(-DPROTOBUF_USE_DLLS)
ADD_DEFINITIONS(-DLUA_BUILD_AS_DLL)
if(UNIX) if(UNIX)
add_definitions(-D_LINUX) add_definitions(-D_LINUX)

@ -76,8 +76,13 @@ src/lzio.c
) )
LIST(APPEND SRC_LIBLUA ${HDR_LIBLUA}) LIST(APPEND SRC_LIBLUA ${HDR_LIBLUA})
ADD_LIBRARY ( lua STATIC EXCLUDE_FROM_ALL ${SRC_LIBLUA} ) ADD_LIBRARY ( lua SHARED EXCLUDE_FROM_ALL ${SRC_LIBLUA} )
TARGET_LINK_LIBRARIES ( lua ${LIBS}) TARGET_LINK_LIBRARIES ( lua ${LIBS})
install(TARGETS lua
LIBRARY DESTINATION ${DFHACK_LIBRARY_DESTINATION}
RUNTIME DESTINATION ${DFHACK_LIBRARY_DESTINATION})
IDE_FOLDER(lua "Depends") IDE_FOLDER(lua "Depends")
#SET ( SRC_LUA src/lua.c ) #SET ( SRC_LUA src/lua.c )

@ -151,11 +151,20 @@
** the libraries, you may want to use the following definition (define ** the libraries, you may want to use the following definition (define
** LUA_BUILD_AS_DLL to get it). ** LUA_BUILD_AS_DLL to get it).
*/ */
#ifdef __cplusplus
#define LUA_API_EXTERN extern "C"
#else
#define LUA_API_EXTERN extern
#endif
#if defined(LUA_BUILD_AS_DLL) #if defined(LUA_BUILD_AS_DLL)
#if defined(LUA_CORE) || defined(LUA_LIB) #if defined(_MSC_VER)
#define LUA_API __declspec(dllexport) #if defined(LUA_CORE) || defined(LUA_LIB)
#define LUA_API __declspec(dllexport) LUA_API_EXTERN
#else
#define LUA_API __declspec(dllimport) LUA_API_EXTERN
#endif
#else #else
#define LUA_API __declspec(dllimport) #define LUA_API LUA_API_EXTERN __attribute__ ((visibility("default")))
#endif #endif
#else #else
#ifdef __cplusplus #ifdef __cplusplus

@ -55,6 +55,7 @@ SET(MAIN_SOURCES
Core.cpp Core.cpp
ColorText.cpp ColorText.cpp
DataDefs.cpp DataDefs.cpp
LuaWrapper.cpp
DataStatics.cpp DataStatics.cpp
DataStaticsCtor.cpp DataStaticsCtor.cpp
DataStaticsFields.cpp DataStaticsFields.cpp
@ -251,7 +252,7 @@ ENDIF()
#effectively disables debug builds... #effectively disables debug builds...
SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" ) SET_TARGET_PROPERTIES(dfhack PROPERTIES DEBUG_POSTFIX "-debug" )
TARGET_LINK_LIBRARIES(dfhack protobuf-lite clsocket ${PROJECT_LIBS}) TARGET_LINK_LIBRARIES(dfhack protobuf-lite clsocket lua ${PROJECT_LIBS})
SET_TARGET_PROPERTIES(dfhack PROPERTIES LINK_INTERFACE_LIBRARIES "") SET_TARGET_PROPERTIES(dfhack PROPERTIES LINK_INTERFACE_LIBRARIES "")
TARGET_LINK_LIBRARIES(dfhack-client protobuf-lite clsocket) TARGET_LINK_LIBRARIES(dfhack-client protobuf-lite clsocket)

@ -13,6 +13,27 @@
#pragma GCC diagnostic ignored "-Winvalid-offsetof" #pragma GCC diagnostic ignored "-Winvalid-offsetof"
namespace df {
#define ATOM_IDENTITY_TRAITS(type) \
primitive_identity identity_traits<type>::identity(sizeof(type));
ATOM_IDENTITY_TRAITS(char);
ATOM_IDENTITY_TRAITS(int8_t);
ATOM_IDENTITY_TRAITS(uint8_t);
ATOM_IDENTITY_TRAITS(int16_t);
ATOM_IDENTITY_TRAITS(uint16_t);
ATOM_IDENTITY_TRAITS(int32_t);
ATOM_IDENTITY_TRAITS(uint32_t);
ATOM_IDENTITY_TRAITS(int64_t);
ATOM_IDENTITY_TRAITS(uint64_t);
ATOM_IDENTITY_TRAITS(bool);
ATOM_IDENTITY_TRAITS(float);
ATOM_IDENTITY_TRAITS(std::string);
ATOM_IDENTITY_TRAITS(void*);
#undef ATOM_IDENTITY_TRAITS
}
#define TID(type) (&identity_traits< type >::identity) #define TID(type) (&identity_traits< type >::identity)
#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)

@ -0,0 +1,218 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "Internal.h"
#include <string>
#include <vector>
#include <map>
#include "MemAccess.h"
#include "Core.h"
#include "VersionInfo.h"
#include "tinythread.h"
// must be last due to MS stupidity
#include "DataDefs.h"
#include "DataIdentity.h"
#include "MiscUtils.h"
#include <lua.h>
#include <lauxlib.h>
using namespace DFHack;
static luaL_Reg no_functions[] = { { NULL, NULL } };
inline void lua_dup(lua_State *state) { lua_pushvalue(state, -1); }
inline void lua_swap(lua_State *state) { lua_insert(state, -2); }
static int change_error(lua_State *state)
{
luaL_error(state, "Attempt to change a read-only table.\n");
}
static void freeze_table(lua_State *state, bool leave_metatable = false, const char *name = NULL)
{
// rv = {}; setmetatable(rv, { __index = in, __newindex = change_error, __metatable = name })
int base = lua_gettop(state);
lua_newtable(state);
lua_swap(state);
lua_setfield(state, base, "__index");
lua_getfield(state, LUA_REGISTRYINDEX, "DFHack.ChangeError");
lua_setfield(state, base, "__newindex");
lua_newtable(state);
lua_swap(state);
lua_dup(state);
lua_setmetatable(state, base);
if (name)
{
lua_pushstring(state, name);
lua_setfield(state, -2, "__metatable");
}
// result: [frozen table] [metatable]
if (!leave_metatable)
lua_pop(state, 1);
}
static void SaveTypeInfo(lua_State *state, void *node)
{
lua_getfield(state, LUA_REGISTRYINDEX, "DFHack.DFTypes");
lua_pushlightuserdata(state, node);
lua_pushvalue(state, -3);
lua_settable(state, -3);
lua_pop(state, 1);
}
static bool RegisterTypeInfo(lua_State *state, void *node)
{
lua_getfield(state, LUA_REGISTRYINDEX, "DFHack.DFTypes");
int base = lua_gettop(state);
lua_pushlightuserdata(state, node);
lua_rawget(state, base);
bool added = false;
if (lua_isnil(state, -1))
{
lua_pop(state, 1);
lua_newtable(state);
lua_pushlightuserdata(state, node);
lua_pushvalue(state, -2);
lua_rawset(state, base);
added = true;
}
lua_remove(state, -2);
return added;
}
static void RenderTypeChildren(lua_State *state, const std::vector<compound_identity*> &children);
static void RenderType(lua_State *state, compound_identity *node)
{
assert(node->getName());
lua_newtable(state);
if (!lua_checkstack(state, 20))
return;
int base = lua_gettop(state);
lua_pushlightuserdata(state, node);
lua_setfield(state, base, "_identity");
switch (node->type())
{
case IDTYPE_ENUM:
{
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])
continue;
lua_pushinteger(state, i);
lua_pushstring(state, keys[j]);
lua_dup(state);
lua_pushinteger(state, i);
lua_settable(state, base);
lua_settable(state, base);
}
if (eid->getFirstItem() <= eid->getLastItem())
{
lua_pushstring(state, "_first_item");
lua_pushinteger(state, eid->getFirstItem());
lua_settable(state, base);
lua_pushstring(state, "_last_item");
lua_pushinteger(state, eid->getLastItem());
lua_settable(state, base);
}
SaveTypeInfo(state, node);
}
break;
default:
break;
}
RenderTypeChildren(state, node->getScopeChildren());
assert(base == lua_gettop(state));
freeze_table(state, false, node->getName());
}
static void RenderTypeChildren(lua_State *state, const std::vector<compound_identity*> &children)
{
for (size_t i = 0; i < children.size(); i++)
{
RenderType(state, children[i]);
lua_pushstring(state, children[i]->getName());
lua_swap(state);
lua_settable(state, -3);
}
}
static void DoAttach(lua_State *state)
{
int base = lua_gettop(state);
lua_pushcfunction(state, change_error);
lua_setfield(state, LUA_REGISTRYINDEX, "DFHack.ChangeError");
luaL_register(state, "df", no_functions);
{
// Assign df a metatable with read-only contents
lua_newtable(state);
// Render the type structure
RenderTypeChildren(state, compound_identity::getTopScope());
freeze_table(state, true, "df");
lua_remove(state, -2);
lua_setmetatable(state, -2);
}
lua_pop(state, 1);
}
void DFHack::AttachDFGlobals(lua_State *state)
{
if (luaL_newmetatable(state, "DFHack.DFTypes"))
DoAttach(state);
lua_pop(state, 1);
}

@ -37,6 +37,8 @@ distribution.
#undef interface #undef interface
#endif #endif
typedef struct lua_State lua_State;
/* /*
* Definitions of DFHack namespace structs used by generated headers. * Definitions of DFHack namespace structs used by generated headers.
*/ */
@ -155,6 +157,8 @@ namespace DFHack
virtual identity_type type() { return IDTYPE_ENUM; } virtual identity_type type() { return IDTYPE_ENUM; }
int64_t getFirstItem() { return first_item_value; }
int64_t getLastItem() { return last_item_value; }
int getCount() { return int(last_item_value-first_item_value+1); } int getCount() { return int(last_item_value-first_item_value+1); }
const char *const *getKeys() { return keys; } const char *const *getKeys() { return keys; }
}; };
@ -280,6 +284,8 @@ namespace DFHack
void InitDataDefGlobals(Core *core); void InitDataDefGlobals(Core *core);
DFHACK_EXPORT void AttachDFGlobals(lua_State *state);
template<class T> template<class T>
T *ifnull(T *a, T *b) { return a ? a : b; } T *ifnull(T *a, T *b) { return a ? a : b; }

@ -65,8 +65,7 @@ namespace df
template<> struct identity_traits<type> { \ template<> struct identity_traits<type> { \
static primitive_identity identity; \ static primitive_identity identity; \
static primitive_identity *get() { return &identity; } \ static primitive_identity *get() { return &identity; } \
}; \ };
primitive_identity identity_traits<type>::identity(sizeof(type));
ATOM_IDENTITY_TRAITS(char); ATOM_IDENTITY_TRAITS(char);
ATOM_IDENTITY_TRAITS(int8_t); ATOM_IDENTITY_TRAITS(int8_t);