PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/lua/convert.lua

https://bitbucket.org/elcugo/t-engine
Lua | 629 lines | 538 code | 88 blank | 3 comment | 76 complexity | 4e791a4d181615728085ba528beae5b8 MD5 | raw file
Possible License(s): GPL-2.0
  1. function iif(a,b,c)
  2. if a then return b else return c end
  3. end
  4. structs = {}
  5. fcts = {}
  6. cur_struct = "???"
  7. function begin_struct(name)
  8. cur_struct = name
  9. structs[name] = {}
  10. table.insert(fcts, name)
  11. return "static void cache_loadsave_"..name.."("..name.." \*s, int flag)\n{\n"
  12. end
  13. convert =
  14. {
  15. default = "do_@type@(&(@field@), flag);",
  16. bool = "do_byte(&(@field@), flag);",
  17. cptr = "do_string_nolen((char**)&(@field@), flag);",
  18. flags_type = "do_flags(&(@field@), flag);",
  19. monster_blow = "cache_loadsave_monster_blow(&(@field@), flag);",
  20. obj_theme = "cache_loadsave_obj_theme(&(@field@), flag);",
  21. rule_type = "cache_loadsave_rule_type(&(@field@), flag);",
  22. abilities_gain = "cache_loadsave_abilities_gain(&(@field@), flag);",
  23. player_spec = "cache_loadsave_player_spec(&(@field@), flag);",
  24. __set_type_aux = "cache_loadsave___set_type_aux(&(@field@), flag);",
  25. }
  26. function do_field(typ, name)
  27. local c = convert[typ]
  28. if not c then c = convert["default"] end
  29. if type(c) == "function" then c = c() end
  30. c = string.gsub(c, "(@type@)", typ)
  31. c = string.gsub(c, "(@field@)", "s->"..name)
  32. return c
  33. end
  34. function simple_field(typ, name)
  35. structs[cur_struct][name] = typ
  36. return "\t"..do_field(typ, name).."\n"
  37. end
  38. function array_field(typ, name, size)
  39. local ret = "\t{ int i; for (i = 0; i < "..size.."; i++) "
  40. ret = ret..do_field(typ, name.."[i]").." }\n"
  41. structs[cur_struct][name] = { name=typ, size=size }
  42. return ret
  43. end
  44. function darray_field(typ, name, size1, size2)
  45. local ret = "\t{ int i; int j; for (i = 0; i < "..size1.."; i++) for (j = 0; j < "..size2.."; j++) "
  46. ret = ret..do_field(typ, name.."[i][j]").." }\n"
  47. structs[cur_struct][name] = { name=typ, size1=size1, size2=size2 }
  48. return ret
  49. end
  50. saving = {}
  51. function saving_info(name, size, file)
  52. saving[cur_struct] = { name=name, size=size, file=file..".lua" }
  53. end
  54. exec = {}
  55. function exec_info(e)
  56. exec[cur_struct] = e
  57. end
  58. function substruct()
  59. saving[cur_struct] = { substruct=1 }
  60. end
  61. function load_core_default(file)
  62. saving[cur_struct].core_file = file
  63. end
  64. function begin_file()
  65. return
  66. [[/*
  67. * Automatic cache load/save generated by Gel(Gema+Lua)
  68. */
  69. #include "angband.h"
  70. #include "lua.h"
  71. #include "lualib.h"
  72. #include "lauxlib.h"
  73. #include "tolua.h"
  74. #include "lobject.h"
  75. extern lua_State* L;
  76. /* Checks if file needs recompilation */
  77. static bool has_reloaded_some = FALSE;
  78. static bool must_reload_cache(char *src, char *obj)
  79. {
  80. char buf_src[1024];
  81. char buf_obj[1024];
  82. path_build(buf_obj, 1024, TENGINE_DIR_RAW, "registry.raw");
  83. /* If the registry file is missing, we must regenerate anyway */
  84. if (!file_exist(buf_obj))
  85. {
  86. /* Make sure the registry will be regenerated if we changed something */
  87. has_reloaded_some = TRUE;
  88. return (4);
  89. }
  90. path_build(buf_src, 1024, TENGINE_DIR_DATA, src);
  91. path_build(buf_obj, 1024, TENGINE_DIR_RAW, obj);
  92. /* Access stats on source file */
  93. if (!file_exist(buf_src))
  94. {
  95. /* Make sure the registry will be regenerated if we changed something */
  96. has_reloaded_some = TRUE;
  97. return (1);
  98. }
  99. /* Access stats on object file */
  100. if (!file_exist(buf_obj))
  101. {
  102. /* Make sure the registry will be regenerated if we changed something */
  103. has_reloaded_some = TRUE;
  104. return (2);
  105. }
  106. /* Ensure text file is not newer than raw file */
  107. if (PHYSFS_getLastModTime(buf_src) > PHYSFS_getLastModTime(buf_obj))
  108. {
  109. /* Make sure the registry will be regenerated if we changed something */
  110. has_reloaded_some = TRUE;
  111. return (3);
  112. }
  113. return (FALSE);
  114. }
  115. static PHYSFS_file *open_raw_cache(cptr name, char *mode)
  116. {
  117. PHYSFS_file *fff;
  118. char buf[1024];
  119. path_build(buf, 1024, TENGINE_DIR_RAW, name);
  120. /* Grab permission */
  121. safe_setuid_grab();
  122. /* Open the file */
  123. fff = my_fopen(buf, mode);
  124. /* Drop permission */
  125. safe_setuid_drop();
  126. /* Sets the stream to use by the load/save functions */
  127. set_loadsave_stream(fff);
  128. return fff;
  129. }
  130. ]]
  131. end
  132. function get_functions_registry()
  133. local load =
  134. [[
  135. errr load_functions_registry()
  136. {
  137. PHYSFS_file *fff;
  138. s32b i;
  139. /* Load the cache */
  140. fff = open_raw_cache("registry.raw", "rb");
  141. if (fff != NULL)
  142. {
  143. lua_getglobal(L, "__functions_registry");
  144. for (i = 1; i <= XXX; i++)
  145. {
  146. s32b j;
  147. s32b nb_ref;
  148. do_s32b(&nb_ref, LS_LOAD);
  149. lua_pushnumber(L, i);
  150. lua_gettable(L, -2);
  151. for (j = 0; j < nb_ref; j++)
  152. {
  153. s32b z;
  154. s32b ref;
  155. s32b size;
  156. char *buf;
  157. do_s32b(&ref, LS_LOAD);
  158. do_s32b(&size, LS_LOAD);
  159. C_MAKE(buf, size, char);
  160. for (z = 0; z < size; z++)
  161. do_char(&buf[z], LS_LOAD);
  162. lua_pushnumber(L, ref);
  163. lua_loadbuffer(L, buf, size, "(info file bytecode loaded)");
  164. lua_settable(L, -3);
  165. C_FREE(buf, size, char);
  166. }
  167. lua_pop(L, 1);
  168. }
  169. lua_pop(L, 1);
  170. my_fclose(fff);
  171. }
  172. /* Success */
  173. return (0);
  174. }
  175. ]]
  176. local save =
  177. [[
  178. extern char *luaU_dumpchunk_buffer(const Proto* Main, size_t *len);
  179. extern Proto* lua_toluafunction (lua_State *L, int index);
  180. errr save_functions_registry()
  181. {
  182. PHYSFS_file *fff;
  183. s32b i;
  184. /* Do we actaully need to save it? */
  185. if (!has_reloaded_some) return 0;
  186. /* Load the cache */
  187. fff = open_raw_cache("registry.raw", "wb");
  188. if (fff == NULL) return 1;
  189. lua_getglobal(L, "__functions_registry");
  190. for (i = 1; i <= XXX; i++)
  191. {
  192. s32b ref;
  193. s32b nb_ref;
  194. s32b real_count = 0;
  195. s32b j;
  196. /* Get the table */
  197. lua_pushnumber(L, i);
  198. lua_gettable(L, -2);
  199. /* Get the size, and iterate */
  200. nb_ref = lua_getn(L, -1);
  201. /* Count the exact number to be saved */
  202. for (j = 0; j <= nb_ref; j++)
  203. {
  204. lua_rawgeti(L, -1, j);
  205. if (lua_isfunction(L, -1)) real_count++;
  206. lua_pop(L, 1);
  207. }
  208. do_s32b(&real_count, LS_SAVE);
  209. for (ref = 0; ref <= nb_ref; ref++)
  210. {
  211. s32b z;
  212. s32b size;
  213. lua_rawgeti(L, -1, ref);
  214. if (lua_isfunction(L, -1))
  215. {
  216. Proto *l;
  217. char *buf;
  218. size_t len;
  219. l = lua_toluafunction(L, -1);
  220. buf = luaU_dumpchunk_buffer(l, &len);
  221. size = len;
  222. do_s32b(&ref, LS_SAVE);
  223. do_s32b(&size, LS_SAVE);
  224. for (z = 0; z < size; z++)
  225. do_char(&buf[z], LS_SAVE);
  226. C_FREE(buf, len, char);
  227. }
  228. lua_pop(L, 1);
  229. }
  230. lua_pop(L, 1);
  231. }
  232. lua_pop(L, 1);
  233. my_fclose(fff);
  234. /* Success */
  235. return (0);
  236. }
  237. ]]
  238. local i = 0
  239. for struct, save in saving do if type(save) == "table" and save.name then i = i + 1 end end
  240. load = string.gsub(load, "(XXX)", i)
  241. save = string.gsub(save, "(XXX)", i)
  242. return load..save
  243. end
  244. function end_file()
  245. local ret = get_wrappers()..get_functions_registry()..
  246. [[
  247. static const struct luaL_reg cache_wrappers_lib[] =
  248. {
  249. ]]
  250. for i = 1, table.getn(fcts) do
  251. if saving[fcts[i]] then
  252. ret = ret..'\t{"load_cache_'..fcts[i]..'", cache_wrap_'..fcts[i]..'},\n'
  253. if not saving[fcts[i]].substruct then
  254. ret = ret..'\t{"make_cache_'..fcts[i]..'", cache_wrap_make_'..fcts[i]..'},\n'
  255. end
  256. end
  257. end
  258. ret = ret..
  259. [[
  260. };
  261. void load_cache_wrappers()
  262. {
  263. luaL_openl(L, cache_wrappers_lib);
  264. lua_newtable(L);
  265. ]]
  266. local i = 1
  267. for struct, save in saving do
  268. if type(save) == "table" then
  269. if save.name then
  270. ret = ret .. "\tlua_pushstring(L, \""..save.name.."\"); lua_pushnumber(L, ".. i.."); lua_settable(L, -3);\n"
  271. i = i + 1
  272. end
  273. end
  274. end
  275. ret = ret..
  276. [[
  277. lua_setglobal(L, "__info_cache");
  278. lua_newtable(L);
  279. ]]
  280. local i = 1
  281. for struct, save in saving do
  282. if type(save) == "table" then
  283. if save.name then
  284. ret = ret .. "\tlua_pushnumber(L, "..i.."); lua_newtable(L); lua_settable(L, -3);\n"
  285. i = i + 1
  286. end
  287. end
  288. end
  289. ret = ret..
  290. [[
  291. lua_setglobal(L, "__functions_registry");
  292. }
  293. ]]
  294. return ret;
  295. end
  296. field_types =
  297. {
  298. bool = "s->@name@ = (@type@)lua_tonumber(L, -1);",
  299. byte = "s->@name@ = (@type@)lua_tonumber(L, -1);",
  300. char = "s->@name@ = (@type@)lua_tonumber(L, -1);",
  301. s16b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
  302. u16b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
  303. s32b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
  304. u32b = "s->@name@ = (@type@)lua_tonumber(L, -1);",
  305. cptr = "s->@name@ = (@type@)string_make(lua_tostring(L, -1));",
  306. flags_type = "{ flags_type *f = (flags_type*)lua_touserdata(L, -1); s->@name@ = *f; FREE(f, flags_type); }",
  307. monster_blow = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_monster_blow(L);",
  308. obj_theme = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_obj_theme(L);",
  309. rule_type = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_rule_type(L);",
  310. abilities_gain = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_abilities_gain(L);",
  311. player_spec = "lua_pushuserdata(L, &(s->@name@)); cache_wrap_player_spec(L);",
  312. __set_type_aux = "lua_pushuserdata(L, &(s->@name@)); cache_wrap___set_type_aux(L);",
  313. }
  314. out_debug = function(typ, name)
  315. return ''
  316. end
  317. function debug()
  318. out_debug = function(typ, name)
  319. return ' printf("Loading %dth of '..typ..' -> '..name..'\\n", i); '
  320. end
  321. end
  322. function wrap_field(typ, name)
  323. local ret =
  324. [[
  325. lua_pushstring(L, "]]..name..[[");
  326. lua_gettable(L, -2);
  327. ]]
  328. if type(typ) == "table" then
  329. local str = field_types[typ.name]
  330. if not field_types[typ.name] then
  331. io.stderr:write("LOG: " .. typ.name.."\n")
  332. end
  333. str = string.gsub(str, "(@type@)", typ.name)
  334. -- Simple array
  335. if typ.size then
  336. str = string.gsub(str, "(@name@)", name.."[i]")
  337. ret = ret..
  338. [[
  339. /* Indexed table */
  340. for (i = 0; i < ]]..typ.size..[[; i++)
  341. {
  342. lua_pushnumber(L, i + 1);
  343. lua_gettable(L, -2);
  344. ]]..str..out_debug(typ.name, name)..[[ lua_pop(L, 1);
  345. }
  346. lua_pop(L, 1);
  347. ]]
  348. -- Double array
  349. else
  350. str = string.gsub(str, "(@name@)", name.."[i][j]")
  351. ret = ret..
  352. [[
  353. /* Double Indexed table */
  354. for (i = 0; i < ]]..typ.size1..[[; i++)
  355. {
  356. int j;
  357. lua_pushnumber(L, i + 1);
  358. lua_gettable(L, -2);
  359. for (j = 0; j < ]]..typ.size2..[[; j++)
  360. {
  361. lua_pushnumber(L, j + 1);
  362. lua_gettable(L, -2);
  363. ]]..str..out_debug(typ.name, name)..[[ lua_pop(L, 1);
  364. }
  365. lua_pop(L, 1);
  366. }
  367. lua_pop(L, 1);
  368. ]]
  369. end
  370. else
  371. local str = field_types[typ]
  372. str = string.gsub(str, "(@name@)", name)
  373. str = string.gsub(str, "(@type@)", typ)
  374. ret = ret..
  375. [[ ]]..str..out_debug(typ, name)..[[ lua_pop(L, 1);
  376. ]]
  377. end
  378. return ret
  379. end
  380. function get_wrappers()
  381. local ret = ""
  382. for s, tbl in structs do
  383. if saving[s] then
  384. ret = ret..
  385. [[
  386. static int cache_wrap_]]..s..[[(lua_State *L);
  387. ]]
  388. end
  389. end
  390. for s, tbl in structs do
  391. if saving[s] then
  392. if saving[s].substruct then
  393. ret = ret..
  394. [[static int cache_wrap_]]..s..[[(lua_State *L)
  395. {
  396. int i;
  397. ]]..s..[[ *s = (]]..s..[[*)lua_touserdata(L, -1);
  398. lua_pop(L, 1);
  399. /* Avoid silly warning */
  400. i = i;
  401. ]]
  402. for name, typ in tbl do
  403. ret = ret..wrap_field(typ, name)
  404. end
  405. ret = ret ..
  406. [[
  407. return 0;
  408. }
  409. ]]
  410. else
  411. ret = ret..
  412. [[static int cache_wrap_]]..s..[[(lua_State *L)
  413. {
  414. int i;
  415. ]]..s..[[ *s;
  416. lua_pushstring(L, "__index__");
  417. lua_gettable(L, -2);
  418. i = lua_tonumber(L, -1); lua_pop(L, 1);
  419. /* Must get bigger? */
  420. if (i == ]]..saving[s].size..[[)
  421. {
  422. RE_C_MAKE(]]..saving[s].name..[[, ]]..saving[s].size..[[, 1, ]]..s..[[);
  423. ]]..saving[s].size..[[++;
  424. }
  425. s = &(]]..saving[s].name..[[[i]);
  426. ]]
  427. for name, typ in tbl do
  428. ret = ret..wrap_field(typ, name)
  429. end
  430. ret = ret ..
  431. [[
  432. return 0;
  433. }
  434. ]]
  435. end
  436. if not saving[s].substruct then
  437. ret = ret..
  438. [[
  439. static int cache_wrap_make_]]..s..[[(lua_State *L)
  440. {
  441. ]]..saving[s].size..[[ = lua_tonumber(L, -1); lua_pop(L, 1);
  442. C_MAKE(]]..saving[s].name..[[, ]]..saving[s].size..[[, ]]..s..[[);
  443. return 0;
  444. }
  445. errr init_]]..saving[s].name..[[(void)
  446. {
  447. PHYSFS_file *fff = NULL;
  448. int i;
  449. bool test = must_reload_cache("]]..saving[s].file..'", "'..string.gsub(saving[s].file, "(\.lua)", ".raw")..[[");
  450. if (test)
  451. {
  452. /* Clear the functions registry of this file */
  453. exec_lua("__functions_registry[__info_cache.]]..saving[s].name..[[] = {}");
  454. ]]..iif(saving[s].core_file,
  455. [[/* Load the core data */
  456. tome_dofile_anywhere(TENGINE_DIR_ENGINE, "]]..tostring(saving[s].core_file)..[[", TRUE, FALSE);]],
  457. "")..[[
  458. /* Load the data */
  459. tome_dofile_anywhere(TENGINE_DIR_DATA, "]]..saving[s].file..[[", TRUE, FALSE);
  460. /* Finish it */
  461. exec_lua(
  462. "make_cache_]]..s..[[(__]]..string.gsub(saving[s].name, "(_info)", "_num")..[[)\n"
  463. "for i = 1, getn(__]]..saving[s].name..[[.data) do load_cache_]]..s..[[(__]]..saving[s].name..[[.data[i]) end\n"
  464. "__]]..saving[s].name..[[.data = {}"
  465. );
  466. /* Write the cache if requested */
  467. if (tome_write_raw_files)
  468. {
  469. fff = open_raw_cache("]]..string.gsub(saving[s].file, "(\.lua)", ".raw")..[[", "wb");
  470. do_s16b(&]]..saving[s].size..[[, LS_SAVE);
  471. for (i = 0; i < ]]..saving[s].size..[[; i++)
  472. cache_loadsave_]]..s..[[(&(]]..saving[s].name..[[[i]), LS_SAVE);
  473. }
  474. }
  475. else
  476. {
  477. /* Load the cache */
  478. fff = open_raw_cache("]]..string.gsub(saving[s].file, "(\.lua)", ".raw")..[[", "rb");
  479. do_s16b(&]]..saving[s].size..[[, LS_LOAD);
  480. C_MAKE(]]..saving[s].name..[[, ]]..saving[s].size..[[, ]]..s..[[);
  481. for (i = 0; i < ]]..saving[s].size..[[; i++)
  482. {
  483. /* Load it */
  484. cache_loadsave_]]..s..[[(&(]]..saving[s].name..[[[i]), LS_LOAD);
  485. ]]
  486. -- Need to add script execution upon loading
  487. if tbl.load_script then
  488. ret = ret..
  489. [[
  490. /* Execute the needed script */
  491. exec_lua(]]..saving[s].name..[[[i].load_script);
  492. ]]
  493. end
  494. ret = ret..
  495. [[
  496. }
  497. /* Must set it for possible patch additions */
  498. exec_lua(format("__]]..string.gsub(saving[s].name, '(info)', 'num')..[[ = %d", i));
  499. }
  500. ]]
  501. if saving[s].load_script then
  502. ret = ret ..
  503. [[
  504. {
  505. char *load;
  506. /* Data loaded from a .lua file, need to be written and executed */
  507. if (test)
  508. {
  509. get_lua_var("__]]..saving[s].name..[[.load_script", 's', &load);
  510. /* Write the cache if requested */
  511. if (tome_write_raw_files)
  512. do_string_nolen(&load, LS_SAVE);
  513. }
  514. /* Data loaded from a .raw file, need to be read and executed */
  515. else
  516. {
  517. do_string_nolen(&load, LS_LOAD);
  518. }
  519. exec_lua(load);
  520. }
  521. ]]
  522. end
  523. ret = ret ..
  524. [[ if (fff != NULL) my_fclose(fff);
  525. ]]
  526. if exec[s] then
  527. ret = ret..[[
  528. call_lua("]]..exec[s]..[[", "()", "");
  529. ]]
  530. end
  531. ret = ret..
  532. [[
  533. /* Success */
  534. return (0);
  535. }
  536. ]]
  537. end
  538. end
  539. end
  540. return ret;
  541. end