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(controls_t
& data
, bool subframe
) throw() {}
10 void lua_callback_do_reset() throw() {}
11 void lua_callback_do_readwrite() throw() {}
12 void lua_callback_startup() throw() {}
13 void lua_callback_pre_load(const std::string
& name
) throw() {}
14 void lua_callback_err_load(const std::string
& name
) throw() {}
15 void lua_callback_post_load(const std::string
& name
, bool was_state
) throw() {}
16 void lua_callback_pre_save(const std::string
& name
, bool is_state
) throw() {}
17 void lua_callback_err_save(const std::string
& name
) throw() {}
18 void lua_callback_post_save(const std::string
& name
, bool is_state
) throw() {}
19 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
) throw() {}
20 void lua_callback_quit() throw() {}
21 void init_lua() throw() {}
22 bool lua_requests_repaint
= false;
23 bool lua_requests_subframe_paint
= false;
24 bool lua_supported
= false;
27 #include "core/command.hpp"
28 #include "core/globalwrap.hpp"
29 #include "core/lua-int.hpp"
30 #include "core/mainloop.hpp"
31 #include "core/memorymanip.hpp"
32 #include "core/misc.hpp"
45 globalwrap
<std::map
<std::string
, lua_function
*>> functions
;
46 lua_State
* lua_initialized
;
47 int lua_trampoline_function(lua_State
* L
)
49 void* ptr
= lua_touserdata(L
, lua_upvalueindex(1));
50 lua_function
* f
= reinterpret_cast<lua_function
*>(ptr
);
54 //Pushes given table to top of stack, creating if needed.
55 void recursive_lookup_table(lua_State
* L
, const std::string
& tab
)
58 lua_pushvalue(L
, LUA_GLOBALSINDEX
);
62 size_t split
= u
.find_last_of(".");
65 if(split
< u
.length()) {
66 u1
= u
.substr(0, split
);
67 u2
= u
.substr(split
+ 1);
69 recursive_lookup_table(L
, u1
);
70 lua_getfield(L
, -1, u2
.c_str());
71 if(lua_type(L
, -1) != LUA_TTABLE
) {
72 //Not a table, create a table.
75 lua_setfield(L
, -2, u2
.c_str());
76 lua_getfield(L
, -1, u2
.c_str());
78 //Get rid of previous table.
83 void register_lua_function(lua_State
* L
, const std::string
& fun
)
86 size_t split
= u
.find_last_of(".");
89 if(split
< u
.length()) {
90 u1
= u
.substr(0, split
);
91 u2
= u
.substr(split
+ 1);
93 recursive_lookup_table(L
, u1
);
94 void* ptr
= reinterpret_cast<void*>(functions()[fun
]);
95 lua_pushlightuserdata(L
, ptr
);
96 lua_pushcclosure(L
, lua_trampoline_function
, 1);
97 lua_setfield(L
, -2, u2
.c_str());
101 void register_lua_functions(lua_State
* L
)
103 for(auto i
: functions())
104 register_lua_function(L
, i
.first
);
109 lua_function::lua_function(const std::string
& name
) throw(std::bad_alloc
)
111 functions()[fname
= name
] = this;
113 register_lua_function(lua_initialized
, fname
);
116 lua_function::~lua_function() throw()
118 functions().erase(fname
);
121 std::string
get_string_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
123 if(lua_isnone(LS
, argindex
)) {
125 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
126 lua_pushstring(LS
, buffer
);
130 const char* f
= lua_tolstring(LS
, argindex
, &len
);
133 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
134 lua_pushstring(LS
, buffer
);
137 return std::string(f
, f
+ len
);
140 bool get_boolean_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
142 if(lua_isnone(LS
, argindex
) || !lua_isboolean(LS
, argindex
)) {
144 sprintf(buffer
, "argument #%i to %s must be boolean", argindex
, fname
);
145 lua_pushstring(LS
, buffer
);
148 return (lua_toboolean(LS
, argindex
) != 0);
151 lua_render_context
* lua_render_ctx
= NULL
;
152 controls_t
* lua_input_controllerdata
= NULL
;
157 bool recursive_flag
= false;
158 const char* luareader_fragment
= NULL
;
160 const char* read_lua_fragment(lua_State
* LS
, void* dummy
, size_t* size
)
162 if(luareader_fragment
) {
163 const char* ret
= luareader_fragment
;
164 *size
= strlen(luareader_fragment
);
165 luareader_fragment
= NULL
;
173 void* alloc(void* user
, void* old
, size_t olds
, size_t news
)
176 void* m
= realloc(old
, news
);
185 bool callback_exists(const char* name
)
189 lua_getglobal(L
, name
);
190 int t
= lua_type(L
, -1);
191 if(t
!= LUA_TFUNCTION
)
193 return (t
== LUA_TFUNCTION
);
196 void push_string(const std::string
& s
)
198 lua_pushlstring(L
, s
.c_str(), s
.length());
201 void push_boolean(bool b
)
203 lua_pushboolean(L
, b
? 1 : 0);
206 #define TEMPORARY "LUAINTERP_INTERNAL_COMMAND_TEMPORARY"
208 const char* eval_lua_lua
= "loadstring(" TEMPORARY
")();";
209 const char* run_lua_lua
= "dofile(" TEMPORARY
");";
211 void run_lua_fragment() throw(std::bad_alloc
)
215 int t
= lua_load(L
, read_lua_fragment
, NULL
, "run_lua_fragment");
216 if(t
== LUA_ERRSYNTAX
) {
217 messages
<< "Can't run Lua: Internal syntax error: " << lua_tostring(L
, -1) << std::endl
;
221 if(t
== LUA_ERRMEM
) {
222 messages
<< "Can't run Lua: Out of memory" << std::endl
;
226 recursive_flag
= true;
227 int r
= lua_pcall(L
, 0, 0, 0);
228 recursive_flag
= false;
229 if(r
== LUA_ERRRUN
) {
230 messages
<< "Error running Lua hunk: " << lua_tostring(L
, -1) << std::endl
;
233 if(r
== LUA_ERRMEM
) {
234 messages
<< "Error running Lua hunk: Out of memory" << std::endl
;
237 if(r
== LUA_ERRERR
) {
238 messages
<< "Error running Lua hunk: Double Fault???" << std::endl
;
241 if(lua_requests_repaint
) {
242 lua_requests_repaint
= false;
243 command::invokeC("repaint");
247 void do_eval_lua(const std::string
& c
) throw(std::bad_alloc
)
250 lua_setglobal(L
, TEMPORARY
);
251 luareader_fragment
= eval_lua_lua
;
255 void do_run_lua(const std::string
& c
) throw(std::bad_alloc
)
258 lua_setglobal(L
, TEMPORARY
);
259 luareader_fragment
= run_lua_lua
;
263 void run_lua_cb(int args
) throw()
265 recursive_flag
= true;
266 int r
= lua_pcall(L
, args
, 0, 0);
267 recursive_flag
= false;
268 if(r
== LUA_ERRRUN
) {
269 messages
<< "Error running Lua callback: " << lua_tostring(L
, -1) << std::endl
;
272 if(r
== LUA_ERRMEM
) {
273 messages
<< "Error running Lua callback: Out of memory" << std::endl
;
276 if(r
== LUA_ERRERR
) {
277 messages
<< "Error running Lua callback: Double Fault???" << std::endl
;
280 if(lua_requests_repaint
) {
281 lua_requests_repaint
= false;
282 command::invokeC("repaint");
287 void lua_callback_do_paint(struct lua_render_context
* ctx
) throw()
289 if(!callback_exists("on_paint"))
291 lua_render_ctx
= ctx
;
293 lua_render_ctx
= NULL
;
296 void lua_callback_do_video(struct lua_render_context
* ctx
) throw()
298 if(!callback_exists("on_video"))
300 lua_render_ctx
= ctx
;
302 lua_render_ctx
= NULL
;
305 void lua_callback_do_reset() throw()
307 if(!callback_exists("on_reset"))
312 void lua_callback_do_readwrite() throw()
314 if(!callback_exists("on_readwrite"))
319 void lua_callback_startup() throw()
321 if(!callback_exists("on_startup"))
326 void lua_callback_pre_load(const std::string
& name
) throw()
328 if(!callback_exists("on_pre_load"))
334 void lua_callback_err_load(const std::string
& name
) throw()
336 if(!callback_exists("on_err_load"))
342 void lua_callback_post_load(const std::string
& name
, bool was_state
) throw()
344 if(!callback_exists("on_post_load"))
347 push_boolean(was_state
);
351 void lua_callback_pre_save(const std::string
& name
, bool is_state
) throw()
353 if(!callback_exists("on_pre_save"))
356 push_boolean(is_state
);
360 void lua_callback_err_save(const std::string
& name
) throw()
362 if(!callback_exists("on_err_save"))
368 void lua_callback_post_save(const std::string
& name
, bool is_state
) throw()
370 if(!callback_exists("on_post_save"))
373 push_boolean(is_state
);
377 void lua_callback_do_input(controls_t
& data
, bool subframe
) throw()
379 if(!callback_exists("on_input"))
381 lua_input_controllerdata
= &data
;
382 push_boolean(subframe
);
384 lua_input_controllerdata
= NULL
;
387 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
) throw()
389 if(!callback_exists("on_snoop"))
391 lua_pushnumber(L
, port
);
392 lua_pushnumber(L
, controller
);
393 lua_pushnumber(L
, index
);
394 lua_pushnumber(L
, value
);
400 function_ptr_command
<const std::string
&> evaluate_lua("evaluate-lua", "Evaluate expression in Lua VM",
401 "Syntax: evaluate-lua <expression>\nEvaluates <expression> in Lua VM.\n",
402 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
404 throw std::runtime_error("Expected expression to evaluate");
408 function_ptr_command
<arg_filename
> run_lua("run-lua", "Run Lua script in Lua VM",
409 "Syntax: run-lua <file>\nRuns <file> in Lua VM.\n",
410 [](arg_filename args
) throw(std::bad_alloc
, std::runtime_error
)
416 void lua_callback_quit() throw()
418 if(!callback_exists("on_quit"))
423 void init_lua() throw()
425 L
= lua_newstate(alloc
, NULL
);
427 messages
<< "Can't initialize Lua." << std::endl
;
432 register_lua_functions(L
);
435 bool lua_requests_repaint
= false;
436 bool lua_requests_subframe_paint
= false;
437 bool lua_supported
= true;