/src/lua/convert.lua
Lua | 629 lines | 538 code | 88 blank | 3 comment | 76 complexity | 4e791a4d181615728085ba528beae5b8 MD5 | raw file
Possible License(s): GPL-2.0
- function iif(a,b,c)
- if a then return b else return c end
- end
- structs = {}
- fcts = {}
- cur_struct = "???"
- function begin_struct(name)
- cur_struct = name
- structs[name] = {}
- table.insert(fcts, name)
- return "static void cache_loadsave_"..name.."("..name.." \*s, int flag)\n{\n"
- end
- convert =
- {
- default = "do_@type@(&(@field@), flag);",
- bool = "do_byte(&(@field@), flag);",
- cptr = "do_string_nolen((char**)&(@field@), flag);",
- flags_type = "do_flags(&(@field@), flag);",
- monster_blow = "cache_loadsave_monster_blow(&(@field@), flag);",
- obj_theme = "cache_loadsave_obj_theme(&(@field@), flag);",
- rule_type = "cache_loadsave_rule_type(&(@field@), flag);",
- abilities_gain = "cache_loadsave_abilities_gain(&(@field@), flag);",
- player_spec = "cache_loadsave_player_spec(&(@field@), flag);",
- __set_type_aux = "cache_loadsave___set_type_aux(&(@field@), flag);",
- }
- function do_field(typ, name)
- local c = convert[typ]
- if not c then c = convert["default"] end
- if type(c) == "function" then c = c() end
- c = string.gsub(c, "(@type@)", typ)
- c = string.gsub(c, "(@field@)", "s->"..name)
- return c
- end
- function simple_field(typ, name)
- structs[cur_struct][name] = typ
- return "\t"..do_field(typ, name).."\n"
- end
- function array_field(typ, name, size)
- local ret = "\t{ int i; for (i = 0; i < "..size.."; i++) "
- ret = ret..do_field(typ, name.."[i]").." }\n"
- structs[cur_struct][name] = { name=typ, size=size }
- return ret
- end
- function darray_field(typ, name, size1, size2)
- local ret = "\t{ int i; int j; for (i = 0; i < "..size1.."; i++) for (j = 0; j < "..size2.."; j++) "
- ret = ret..do_field(typ, name.."[i][j]").." }\n"
- structs[cur_struct][name] = { name=typ, size1=size1, size2=size2 }
- return ret
- end
- saving = {}
- function saving_info(name, size, file)
- saving[cur_struct] = { name=name, size=size, file=file..".lua" }
- end
- exec = {}
- function exec_info(e)
- exec[cur_struct] = e
- end
- function substruct()
- saving[cur_struct] = { substruct=1 }
- end
- function load_core_default(file)
- saving[cur_struct].core_file = file
- end
- function begin_file()
- return
- [[/*
- * Automatic cache load/save generated by Gel(Gema+Lua)
- */
- #include "angband.h"
- #include "lua.h"
- #include "lualib.h"
- #include "lauxlib.h"
- #include "tolua.h"
- #include "lobject.h"
- extern lua_State* L;
- /* Checks if file needs recompilation */
- static bool has_reloaded_some = FALSE;
- static bool must_reload_cache(char *src, char *obj)
- {
- char buf_src[1024];
- char buf_obj[1024];
- path_build(buf_obj, 1024, TENGINE_DIR_RAW, "registry.raw");
- /* If the registry file is missing, we must regenerate anyway */
- if (!file_exist(buf_obj))
- {
- /* Make sure the registry will be regenerated if we changed something */
- has_reloaded_some = TRUE;
- return (4);
- }
- path_build(buf_src, 1024, TENGINE_DIR_DATA, src);
- path_build(buf_obj, 1024, TENGINE_DIR_RAW, obj);
- /* Access stats on source file */
- if (!file_exist(buf_src))
- {
- /* Make sure the registry will be regenerated if we changed something */
- has_reloaded_some = TRUE;
- return (1);
- }
- /* Access stats on object file */
- if (!file_exist(buf_obj))
- {
- /* Make sure the registry will be regenerated if we changed something */
- has_reloaded_some = TRUE;
- return (2);
- }
- /* Ensure text file is not newer than raw file */
- if (PHYSFS_getLastModTime(buf_src) > PHYSFS_getLastModTime(buf_obj))
- {
- /* Make sure the registry will be regenerated if we changed something */
- has_reloaded_some = TRUE;
- return (3);
- }
- return (FALSE);
- }
- static PHYSFS_file *open_raw_cache(cptr name, char *mode)
- {
- PHYSFS_file *fff;
- char buf[1024];
- path_build(buf, 1024, TENGINE_DIR_RAW, name);
- /* Grab permission */
- safe_setuid_grab();
- /* Open the file */
- fff = my_fopen(buf, mode);
- /* Drop permission */
- safe_setuid_drop();
- /* Sets the stream to use by the load/save functions */
- set_loadsave_stream(fff);
- return fff;
- }
- ]]
- end
- function get_functions_registry()
- local load =
- [[
- errr load_functions_registry()
- {
- PHYSFS_file *fff;
- s32b i;
- /* Load the cache */
- fff = open_raw_cache("registry.raw", "rb");
- if (fff != NULL)
- {
- lua_getglobal(L, "__functions_registry");
- for (i = 1; i <= XXX; i++)
- {
- s32b j;
- s32b nb_ref;
- do_s32b(&nb_ref, LS_LOAD);
- lua_pushnumber(L, i);
- lua_gettable(L, -2);
- for (j = 0; j < nb_ref; j++)
- {
- s32b z;
- s32b ref;
- s32b size;
- char *buf;
- do_s32b(&ref, LS_LOAD);
- do_s32b(&size, LS_LOAD);
- C_MAKE(buf, size, char);
- for (z = 0; z < size; z++)
- do_char(&buf[z], LS_LOAD);
- lua_pushnumber(L, ref);
- lua_loadbuffer(L, buf, size, "(info file bytecode loaded)");
- lua_settable(L, -3);
- C_FREE(buf, size, char);
- }
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
- my_fclose(fff);
- }
- /* Success */
- return (0);
- }
- ]]
- local save =
- [[
- extern char *luaU_dumpchunk_buffer(const Proto* Main, size_t *len);
- extern Proto* lua_toluafunction (lua_State *L, int index);
- errr save_functions_registry()
- {
- PHYSFS_file *fff;
- s32b i;
- /* Do we actaully need to save it? */
- if (!has_reloaded_some) return 0;
- /* Load the cache */
- fff = open_raw_cache("registry.raw", "wb");
- if (fff == NULL) return 1;
- lua_getglobal(L, "__functions_registry");
- for (i = 1; i <= XXX; i++)
- {
- s32b ref;
- s32b nb_ref;
- s32b real_count = 0;
- s32b j;
- /* Get the table */
- lua_pushnumber(L, i);
- lua_gettable(L, -2);
- /* Get the size, and iterate */
- nb_ref = lua_getn(L, -1);
- /* Count the exact number to be saved */
- for (j = 0; j <= nb_ref; j++)
- {
- lua_rawgeti(L, -1, j);
- if (lua_isfunction(L, -1)) real_count++;
- lua_pop(L, 1);
- }
- do_s32b(&real_count, LS_SAVE);
- for (ref = 0; ref <= nb_ref; ref++)
- {
- s32b z;
- s32b size;
- lua_rawgeti(L, -1, ref);
- if (lua_isfunction(L, -1))
- {
- Proto *l;
- char *buf;
- size_t len;
- l = lua_toluafunction(L, -1);
- buf = luaU_dumpchunk_buffer(l, &len);
- size = len;
- do_s32b(&ref, LS_SAVE);
- do_s32b(&size, LS_SAVE);
- for (z = 0; z < size; z++)
- do_char(&buf[z], LS_SAVE);
- C_FREE(buf, len, char);
- }
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
- my_fclose(fff);
- /* Success */
- return (0);
- }
- ]]
- local i = 0
- for struct, save in saving do if type(save) == "table" and save.name then i = i + 1 end end
- load = string.gsub(load, "(XXX)", i)
- save = string.gsub(save, "(XXX)", i)
- return load..save
- end
- function end_file()
- local ret = get_wrappers()..get_functions_registry()..
- [[
- static const struct luaL_reg cache_wrappers_lib[] =
- {
- ]]
- for i = 1, table.getn(fcts) do
- if saving[fcts[i]] then
- ret = ret..'\t{"load_cache_'..fcts[i]..'", cache_wrap_'..fcts[i]..'},\n'
- if not saving[fcts[i]].substruct then
- ret = ret..'\t{"make_cache_'..fcts[i]..'", cache_wrap_make_'..fcts[i]..'},\n'
- end
- end
- end
- ret = ret..
- [[
- };
- void load_cache_wrappers()
- {
- luaL_openl(L, cache_wrappers_lib);
- lua_newtable(L);
- ]]
- local i = 1
- for struct, save in saving do
- if type(save) == "table" then
- if save.name then
- ret = ret .. "\tlua_pushstring(L, \""..save.name.."\"); lua_pushnumber(L, ".. i.."); lua_settable(L, -3);\n"
- i = i + 1
- end
- end
- end
- ret = ret..
- [[
- lua_setglobal(L, "__info_cache");
- lua_newtable(L);
- ]]
- local i = 1
- for struct, save in saving do
- if type(save) == "table" then
- if save.name then
- ret = ret .. "\tlua_pushnumber(L, "..i.."); lua_newtable(L); lua_settable(L, -3);\n"
- i = i + 1
- end
- end
- end
- ret = ret..
- [[
- lua_setglobal(L, "__functions_registry");
- }
- ]]
- return ret;
- end
- field_types =
- {
- bool = "s->@name@ = (@type@)lua_tonumber(L, -1);",
- byte = "s->@name@ = (@type@)lua_tonumber(L, -1);",
- char = "s->@name@ = (@type@)lua_tonumber(L, -1);",
- s16b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
- u16b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
- s32b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
- u32b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
- cptr = "s->@name@ = (@type@)string_make(lua_tostring(L, -1));",
- flags_type = "{ flags_type *f = (flags_type*)lua_touserdata(L, -1); s->@name@ = *f; FREE(f, flags_type); }",
- monster_blow = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_monster_blow(L);",
- obj_theme = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_obj_theme(L);",
- rule_type = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_rule_type(L);",
- abilities_gain = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_abilities_gain(L);",
- player_spec = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_player_spec(L);",
- __set_type_aux = "lua_pushuserdata(L, &(s->@name@)); cache_wrap___set_type_aux(L);",
- }
- out_debug = function(typ, name)
- return ''
- end
- function debug()
- out_debug = function(typ, name)
- return ' printf("Loading %dth of '..typ..' -> '..name..'\\n", i); '
- end
- end
- function wrap_field(typ, name)
- local ret =
- [[
- lua_pushstring(L, "]]..name..[[");
- lua_gettable(L, -2);
- ]]
- if type(typ) == "table" then
- local str = field_types[typ.name]
- if not field_types[typ.name] then
- io.stderr:write("LOG: " .. typ.name.."\n")
- end
- str = string.gsub(str, "(@type@)", typ.name)
- -- Simple array
- if typ.size then
- str = string.gsub(str, "(@name@)", name.."[i]")
- ret = ret..
- [[
- /* Indexed table */
- for (i = 0; i < ]]..typ.size..[[; i++)
- {
- lua_pushnumber(L, i + 1);
- lua_gettable(L, -2);
- ]]..str..out_debug(typ.name, name)..[[ lua_pop(L, 1);
- }
- lua_pop(L, 1);
- ]]
- -- Double array
- else
- str = string.gsub(str, "(@name@)", name.."[i][j]")
- ret = ret..
- [[
- /* Double Indexed table */
- for (i = 0; i < ]]..typ.size1..[[; i++)
- {
- int j;
- lua_pushnumber(L, i + 1);
- lua_gettable(L, -2);
- for (j = 0; j < ]]..typ.size2..[[; j++)
- {
- lua_pushnumber(L, j + 1);
- lua_gettable(L, -2);
- ]]..str..out_debug(typ.name, name)..[[ lua_pop(L, 1);
- }
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
- ]]
- end
- else
- local str = field_types[typ]
- str = string.gsub(str, "(@name@)", name)
- str = string.gsub(str, "(@type@)", typ)
- ret = ret..
- [[ ]]..str..out_debug(typ, name)..[[ lua_pop(L, 1);
- ]]
- end
- return ret
- end
- function get_wrappers()
- local ret = ""
- for s, tbl in structs do
- if saving[s] then
- ret = ret..
- [[
- static int cache_wrap_]]..s..[[(lua_State *L);
- ]]
- end
- end
- for s, tbl in structs do
- if saving[s] then
- if saving[s].substruct then
- ret = ret..
- [[static int cache_wrap_]]..s..[[(lua_State *L)
- {
- int i;
- ]]..s..[[ *s = (]]..s..[[*)lua_touserdata(L, -1);
- lua_pop(L, 1);
- /* Avoid silly warning */
- i = i;
- ]]
- for name, typ in tbl do
- ret = ret..wrap_field(typ, name)
- end
- ret = ret ..
- [[
- return 0;
- }
- ]]
- else
- ret = ret..
- [[static int cache_wrap_]]..s..[[(lua_State *L)
- {
- int i;
- ]]..s..[[ *s;
- lua_pushstring(L, "__index__");
- lua_gettable(L, -2);
- i = lua_tonumber(L, -1); lua_pop(L, 1);
- /* Must get bigger? */
- if (i == ]]..saving[s].size..[[)
- {
- RE_C_MAKE(]]..saving[s].name..[[, ]]..saving[s].size..[[, 1, ]]..s..[[);
- ]]..saving[s].size..[[++;
- }
- s = &(]]..saving[s].name..[[[i]);
- ]]
- for name, typ in tbl do
- ret = ret..wrap_field(typ, name)
- end
- ret = ret ..
- [[
- return 0;
- }
- ]]
- end
- if not saving[s].substruct then
- ret = ret..
- [[
- static int cache_wrap_make_]]..s..[[(lua_State *L)
- {
- ]]..saving[s].size..[[ = lua_tonumber(L, -1); lua_pop(L, 1);
- C_MAKE(]]..saving[s].name..[[, ]]..saving[s].size..[[, ]]..s..[[);
- return 0;
- }
- errr init_]]..saving[s].name..[[(void)
- {
- PHYSFS_file *fff = NULL;
- int i;
- bool test = must_reload_cache("]]..saving[s].file..'", "'..string.gsub(saving[s].file, "(\.lua)", ".raw")..[[");
- if (test)
- {
- /* Clear the functions registry of this file */
- exec_lua("__functions_registry[__info_cache.]]..saving[s].name..[[] = {}");
- ]]..iif(saving[s].core_file,
- [[/* Load the core data */
- tome_dofile_anywhere(TENGINE_DIR_ENGINE, "]]..tostring(saving[s].core_file)..[[", TRUE, FALSE);]],
- "")..[[
-
- /* Load the data */
- tome_dofile_anywhere(TENGINE_DIR_DATA, "]]..saving[s].file..[[", TRUE, FALSE);
- /* Finish it */
- exec_lua(
- "make_cache_]]..s..[[(__]]..string.gsub(saving[s].name, "(_info)", "_num")..[[)\n"
- "for i = 1, getn(__]]..saving[s].name..[[.data) do load_cache_]]..s..[[(__]]..saving[s].name..[[.data[i]) end\n"
- "__]]..saving[s].name..[[.data = {}"
- );
- /* Write the cache if requested */
- if (tome_write_raw_files)
- {
- fff = open_raw_cache("]]..string.gsub(saving[s].file, "(\.lua)", ".raw")..[[", "wb");
- do_s16b(&]]..saving[s].size..[[, LS_SAVE);
- for (i = 0; i < ]]..saving[s].size..[[; i++)
- cache_loadsave_]]..s..[[(&(]]..saving[s].name..[[[i]), LS_SAVE);
- }
- }
- else
- {
- /* Load the cache */
- fff = open_raw_cache("]]..string.gsub(saving[s].file, "(\.lua)", ".raw")..[[", "rb");
- do_s16b(&]]..saving[s].size..[[, LS_LOAD);
- C_MAKE(]]..saving[s].name..[[, ]]..saving[s].size..[[, ]]..s..[[);
- for (i = 0; i < ]]..saving[s].size..[[; i++)
- {
- /* Load it */
- cache_loadsave_]]..s..[[(&(]]..saving[s].name..[[[i]), LS_LOAD);
- ]]
- -- Need to add script execution upon loading
- if tbl.load_script then
- ret = ret..
- [[
- /* Execute the needed script */
- exec_lua(]]..saving[s].name..[[[i].load_script);
- ]]
- end
- ret = ret..
- [[
- }
- /* Must set it for possible patch additions */
- exec_lua(format("__]]..string.gsub(saving[s].name, '(info)', 'num')..[[ = %d", i));
- }
- ]]
- if saving[s].load_script then
- ret = ret ..
- [[
- {
- char *load;
- /* Data loaded from a .lua file, need to be written and executed */
- if (test)
- {
- get_lua_var("__]]..saving[s].name..[[.load_script", 's', &load);
- /* Write the cache if requested */
- if (tome_write_raw_files)
- do_string_nolen(&load, LS_SAVE);
- }
- /* Data loaded from a .raw file, need to be read and executed */
- else
- {
- do_string_nolen(&load, LS_LOAD);
- }
- exec_lua(load);
- }
- ]]
- end
- ret = ret ..
- [[ if (fff != NULL) my_fclose(fff);
- ]]
- if exec[s] then
- ret = ret..[[
- call_lua("]]..exec[s]..[[", "()", "");
- ]]
- end
- ret = ret..
- [[
- /* Success */
- return (0);
- }
- ]]
- end
- end
- end
- return ret;
- end