1 #include "core/lua.hpp"
4 struct lua_State
{ int x
; };
5 lua_function::lua_function(const std::string
& name
) throw(std::bad_alloc
) {}
6 lua_function::~lua_function() throw() {}
7 void lua_callback_do_paint(struct lua_render_context
* ctx
) throw() {}
8 void lua_callback_do_video(struct lua_render_context
* ctx
) throw() {}
9 void lua_callback_do_input(controller_frame
& data
, bool subframe
) throw() {}
10 void lua_callback_do_reset() throw() {}
11 void lua_callback_do_frame() throw() {}
12 void lua_callback_do_readwrite() throw() {}
13 void lua_callback_startup() throw() {}
14 void lua_callback_pre_load(const std::string
& name
) throw() {}
15 void lua_callback_err_load(const std::string
& name
) throw() {}
16 void lua_callback_post_load(const std::string
& name
, bool was_state
) throw() {}
17 void lua_callback_pre_save(const std::string
& name
, bool is_state
) throw() {}
18 void lua_callback_err_save(const std::string
& name
) throw() {}
19 void lua_callback_post_save(const std::string
& name
, bool is_state
) throw() {}
20 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
) throw() {}
21 void lua_callback_quit() throw() {}
22 void init_lua() throw() {}
23 void quit_lua() throw() {}
24 bool lua_requests_repaint
= false;
25 bool lua_requests_subframe_paint
= false;
26 bool lua_supported
= false;
29 #include "core/command.hpp"
30 #include "core/globalwrap.hpp"
31 #include "core/lua-int.hpp"
32 #include "core/mainloop.hpp"
33 #include "core/memorymanip.hpp"
34 #include "core/misc.hpp"
47 globalwrap
<std::map
<std::string
, lua_function
*>> functions
;
48 lua_State
* lua_initialized
;
49 int lua_trampoline_function(lua_State
* L
)
51 void* ptr
= lua_touserdata(L
, lua_upvalueindex(1));
52 lua_function
* f
= reinterpret_cast<lua_function
*>(ptr
);
56 //Pushes given table to top of stack, creating if needed.
57 void recursive_lookup_table(lua_State
* L
, const std::string
& tab
)
60 lua_pushvalue(L
, LUA_GLOBALSINDEX
);
64 size_t split
= u
.find_last_of(".");
67 if(split
< u
.length()) {
68 u1
= u
.substr(0, split
);
69 u2
= u
.substr(split
+ 1);
71 recursive_lookup_table(L
, u1
);
72 lua_getfield(L
, -1, u2
.c_str());
73 if(lua_type(L
, -1) != LUA_TTABLE
) {
74 //Not a table, create a table.
77 lua_setfield(L
, -2, u2
.c_str());
78 lua_getfield(L
, -1, u2
.c_str());
80 //Get rid of previous table.
85 void register_lua_function(lua_State
* L
, const std::string
& fun
)
88 size_t split
= u
.find_last_of(".");
91 if(split
< u
.length()) {
92 u1
= u
.substr(0, split
);
93 u2
= u
.substr(split
+ 1);
95 recursive_lookup_table(L
, u1
);
96 void* ptr
= reinterpret_cast<void*>(functions()[fun
]);
97 lua_pushlightuserdata(L
, ptr
);
98 lua_pushcclosure(L
, lua_trampoline_function
, 1);
99 lua_setfield(L
, -2, u2
.c_str());
103 void register_lua_functions(lua_State
* L
)
105 for(auto i
: functions())
106 register_lua_function(L
, i
.first
);
111 lua_function::lua_function(const std::string
& name
) throw(std::bad_alloc
)
113 functions()[fname
= name
] = this;
115 register_lua_function(lua_initialized
, fname
);
118 lua_function::~lua_function() throw()
120 functions().erase(fname
);
123 std::string
get_string_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
125 if(lua_isnone(LS
, argindex
)) {
127 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
128 lua_pushstring(LS
, buffer
);
132 const char* f
= lua_tolstring(LS
, argindex
, &len
);
135 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
136 lua_pushstring(LS
, buffer
);
139 return std::string(f
, f
+ len
);
142 bool get_boolean_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
144 if(lua_isnone(LS
, argindex
) || !lua_isboolean(LS
, argindex
)) {
146 sprintf(buffer
, "argument #%i to %s must be boolean", argindex
, fname
);
147 lua_pushstring(LS
, buffer
);
150 return (lua_toboolean(LS
, argindex
) != 0);
153 lua_render_context
* lua_render_ctx
= NULL
;
154 controller_frame
* lua_input_controllerdata
= NULL
;
159 bool recursive_flag
= false;
160 const char* luareader_fragment
= NULL
;
162 const char* read_lua_fragment(lua_State
* LS
, void* dummy
, size_t* size
)
164 if(luareader_fragment
) {
165 const char* ret
= luareader_fragment
;
166 *size
= strlen(luareader_fragment
);
167 luareader_fragment
= NULL
;
175 void* alloc(void* user
, void* old
, size_t olds
, size_t news
)
178 void* m
= realloc(old
, news
);
187 bool callback_exists(const char* name
)
191 lua_getglobal(L
, name
);
192 int t
= lua_type(L
, -1);
193 if(t
!= LUA_TFUNCTION
)
195 return (t
== LUA_TFUNCTION
);
198 void push_string(const std::string
& s
)
200 lua_pushlstring(L
, s
.c_str(), s
.length());
203 void push_boolean(bool b
)
205 lua_pushboolean(L
, b
? 1 : 0);
208 #define TEMPORARY "LUAINTERP_INTERNAL_COMMAND_TEMPORARY"
210 const char* eval_lua_lua
= "loadstring(" TEMPORARY
")();";
211 const char* run_lua_lua
= "dofile(" TEMPORARY
");";
213 void run_lua_fragment() throw(std::bad_alloc
)
217 int t
= lua_load(L
, read_lua_fragment
, NULL
, "run_lua_fragment");
218 if(t
== LUA_ERRSYNTAX
) {
219 messages
<< "Can't run Lua: Internal syntax error: " << lua_tostring(L
, -1) << std::endl
;
223 if(t
== LUA_ERRMEM
) {
224 messages
<< "Can't run Lua: Out of memory" << std::endl
;
228 recursive_flag
= true;
229 int r
= lua_pcall(L
, 0, 0, 0);
230 recursive_flag
= false;
231 if(r
== LUA_ERRRUN
) {
232 messages
<< "Error running Lua hunk: " << lua_tostring(L
, -1) << std::endl
;
235 if(r
== LUA_ERRMEM
) {
236 messages
<< "Error running Lua hunk: Out of memory" << std::endl
;
239 if(r
== LUA_ERRERR
) {
240 messages
<< "Error running Lua hunk: Double Fault???" << std::endl
;
243 if(lua_requests_repaint
) {
244 lua_requests_repaint
= false;
245 command::invokeC("repaint");
249 void do_eval_lua(const std::string
& c
) throw(std::bad_alloc
)
252 lua_setglobal(L
, TEMPORARY
);
253 luareader_fragment
= eval_lua_lua
;
257 void do_run_lua(const std::string
& c
) throw(std::bad_alloc
)
260 lua_setglobal(L
, TEMPORARY
);
261 luareader_fragment
= run_lua_lua
;
265 void run_lua_cb(int args
) throw()
267 recursive_flag
= true;
268 int r
= lua_pcall(L
, args
, 0, 0);
269 recursive_flag
= false;
270 if(r
== LUA_ERRRUN
) {
271 messages
<< "Error running Lua callback: " << lua_tostring(L
, -1) << std::endl
;
274 if(r
== LUA_ERRMEM
) {
275 messages
<< "Error running Lua callback: Out of memory" << std::endl
;
278 if(r
== LUA_ERRERR
) {
279 messages
<< "Error running Lua callback: Double Fault???" << std::endl
;
282 if(lua_requests_repaint
) {
283 lua_requests_repaint
= false;
284 command::invokeC("repaint");
288 int system_write_error(lua_State
* L
)
290 lua_pushstring(L
, "_SYSTEM is write-protected");
295 void copy_system_tables(lua_State
* L
)
299 while(lua_next(L
, LUA_GLOBALSINDEX
)) {
300 //Stack: _SYSTEM, KEY, VALUE
301 lua_pushvalue(L
, -2);
302 lua_pushvalue(L
, -2);
303 //Stack: _SYSTEM, KEY, VALUE, KEY, VALUE
305 //Stack: _SYSTEM, KEY, VALUE
307 //Stack: _SYSTEM, KEY
310 lua_pushcfunction(L
, system_write_error
);
311 lua_setfield(L
, -2, "__newindex");
312 lua_setmetatable(L
, -2);
313 lua_setglobal(L
, "_SYSTEM");
317 void lua_callback_do_paint(struct lua_render_context
* ctx
) throw()
319 if(!callback_exists("on_paint"))
321 lua_render_ctx
= ctx
;
323 lua_render_ctx
= NULL
;
326 void lua_callback_do_video(struct lua_render_context
* ctx
) throw()
328 if(!callback_exists("on_video"))
330 lua_render_ctx
= ctx
;
332 lua_render_ctx
= NULL
;
335 void lua_callback_do_reset() throw()
337 if(!callback_exists("on_reset"))
342 void lua_callback_do_frame() throw()
344 if(!callback_exists("on_frame"))
349 void lua_callback_do_readwrite() throw()
351 if(!callback_exists("on_readwrite"))
356 void lua_callback_startup() throw()
358 if(!callback_exists("on_startup"))
363 void lua_callback_pre_load(const std::string
& name
) throw()
365 if(!callback_exists("on_pre_load"))
371 void lua_callback_err_load(const std::string
& name
) throw()
373 if(!callback_exists("on_err_load"))
379 void lua_callback_post_load(const std::string
& name
, bool was_state
) throw()
381 if(!callback_exists("on_post_load"))
384 push_boolean(was_state
);
388 void lua_callback_pre_save(const std::string
& name
, bool is_state
) throw()
390 if(!callback_exists("on_pre_save"))
393 push_boolean(is_state
);
397 void lua_callback_err_save(const std::string
& name
) throw()
399 if(!callback_exists("on_err_save"))
405 void lua_callback_post_save(const std::string
& name
, bool is_state
) throw()
407 if(!callback_exists("on_post_save"))
410 push_boolean(is_state
);
414 void lua_callback_do_input(controller_frame
& data
, bool subframe
) throw()
416 if(!callback_exists("on_input"))
418 lua_input_controllerdata
= &data
;
419 push_boolean(subframe
);
421 lua_input_controllerdata
= NULL
;
424 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
) throw()
426 if(!callback_exists("on_snoop"))
428 lua_pushnumber(L
, port
);
429 lua_pushnumber(L
, controller
);
430 lua_pushnumber(L
, index
);
431 lua_pushnumber(L
, value
);
437 function_ptr_command
<const std::string
&> evaluate_lua("evaluate-lua", "Evaluate expression in Lua VM",
438 "Syntax: evaluate-lua <expression>\nEvaluates <expression> in Lua VM.\n",
439 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
441 throw std::runtime_error("Expected expression to evaluate");
445 function_ptr_command
<arg_filename
> run_lua("run-lua", "Run Lua script in Lua VM",
446 "Syntax: run-lua <file>\nRuns <file> in Lua VM.\n",
447 [](arg_filename args
) throw(std::bad_alloc
, std::runtime_error
)
453 void lua_callback_quit() throw()
455 if(!callback_exists("on_quit"))
460 void init_lua() throw()
462 L
= lua_newstate(alloc
, NULL
);
464 messages
<< "Can't initialize Lua." << std::endl
;
469 register_lua_functions(L
);
470 copy_system_tables(L
);
473 void quit_lua() throw()
476 lua_close(lua_initialized
);
479 bool lua_requests_repaint
= false;
480 bool lua_requests_subframe_paint
= false;
481 bool lua_supported
= true;