3 struct lua_State
{ int x
; };
4 lua_function::lua_function(const std::string
& name
) throw(std::bad_alloc
) {}
5 lua_function::~lua_function() throw() {}
6 void lua_callback_do_paint(struct lua_render_context
* ctx
) throw() {}
7 void lua_callback_do_video(struct lua_render_context
* ctx
) throw() {}
8 void lua_callback_do_input(controls_t
& data
, bool subframe
) throw() {}
9 void lua_callback_do_reset() throw() {}
10 void lua_callback_do_readwrite() throw() {}
11 void lua_callback_startup() throw() {}
12 void lua_callback_pre_load(const std::string
& name
) throw() {}
13 void lua_callback_err_load(const std::string
& name
) throw() {}
14 void lua_callback_post_load(const std::string
& name
, bool was_state
) throw() {}
15 void lua_callback_pre_save(const std::string
& name
, bool is_state
) throw() {}
16 void lua_callback_err_save(const std::string
& name
) throw() {}
17 void lua_callback_post_save(const std::string
& name
, bool is_state
) throw() {}
18 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
) throw() {}
19 void lua_callback_quit() throw() {}
20 void init_lua() throw() {}
21 bool lua_requests_repaint
= false;
22 bool lua_requests_subframe_paint
= false;
25 #include "lua-int.hpp"
26 #include "command.hpp"
28 #include "memorymanip.hpp"
29 #include "mainloop.hpp"
30 #include "globalwrap.hpp"
42 globalwrap
<std::map
<std::string
, lua_function
*>> functions
;
43 lua_State
* lua_initialized
;
44 int lua_trampoline_function(lua_State
* L
)
46 void* ptr
= lua_touserdata(L
, lua_upvalueindex(1));
47 lua_function
* f
= reinterpret_cast<lua_function
*>(ptr
);
51 //Pushes given table to top of stack, creating if needed.
52 void recursive_lookup_table(lua_State
* L
, const std::string
& tab
)
55 lua_pushvalue(L
, LUA_GLOBALSINDEX
);
59 size_t split
= u
.find_last_of(".");
62 if(split
< u
.length()) {
63 u1
= u
.substr(0, split
);
64 u2
= u
.substr(split
+ 1);
66 recursive_lookup_table(L
, u1
);
67 lua_getfield(L
, -1, u2
.c_str());
68 if(lua_type(L
, -1) != LUA_TTABLE
) {
69 //Not a table, create a table.
72 lua_setfield(L
, -2, u2
.c_str());
73 lua_getfield(L
, -1, u2
.c_str());
75 //Get rid of previous table.
80 void register_lua_function(lua_State
* L
, const std::string
& fun
)
83 size_t split
= u
.find_last_of(".");
86 if(split
< u
.length()) {
87 u1
= u
.substr(0, split
);
88 u2
= u
.substr(split
+ 1);
90 recursive_lookup_table(L
, u1
);
91 void* ptr
= reinterpret_cast<void*>(functions()[fun
]);
92 lua_pushlightuserdata(L
, ptr
);
93 lua_pushcclosure(L
, lua_trampoline_function
, 1);
94 lua_setfield(L
, -2, u2
.c_str());
98 void register_lua_functions(lua_State
* L
)
100 for(auto i
: functions())
101 register_lua_function(L
, i
.first
);
106 lua_function::lua_function(const std::string
& name
) throw(std::bad_alloc
)
108 functions()[fname
= name
] = this;
110 register_lua_function(lua_initialized
, fname
);
113 lua_function::~lua_function() throw()
115 functions().erase(fname
);
118 std::string
get_string_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
120 if(lua_isnone(LS
, argindex
)) {
122 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
123 lua_pushstring(LS
, buffer
);
127 const char* f
= lua_tolstring(LS
, argindex
, &len
);
130 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
131 lua_pushstring(LS
, buffer
);
134 return std::string(f
, f
+ len
);
137 bool get_boolean_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
139 if(lua_isnone(LS
, argindex
) || !lua_isboolean(LS
, argindex
)) {
141 sprintf(buffer
, "argument #%i to %s must be boolean", argindex
, fname
);
142 lua_pushstring(LS
, buffer
);
145 return (lua_toboolean(LS
, argindex
) != 0);
148 lua_render_context
* lua_render_ctx
= NULL
;
149 controls_t
* lua_input_controllerdata
= NULL
;
154 bool recursive_flag
= false;
155 const char* luareader_fragment
= NULL
;
157 const char* read_lua_fragment(lua_State
* LS
, void* dummy
, size_t* size
)
159 if(luareader_fragment
) {
160 const char* ret
= luareader_fragment
;
161 *size
= strlen(luareader_fragment
);
162 luareader_fragment
= NULL
;
170 void* alloc(void* user
, void* old
, size_t olds
, size_t news
)
173 void* m
= realloc(old
, news
);
182 bool callback_exists(const char* name
)
186 lua_getglobal(L
, name
);
187 int t
= lua_type(L
, -1);
188 if(t
!= LUA_TFUNCTION
)
190 return (t
== LUA_TFUNCTION
);
193 void push_string(const std::string
& s
)
195 lua_pushlstring(L
, s
.c_str(), s
.length());
198 void push_boolean(bool b
)
200 lua_pushboolean(L
, b
? 1 : 0);
203 #define TEMPORARY "LUAINTERP_INTERNAL_COMMAND_TEMPORARY"
205 const char* eval_lua_lua
= "loadstring(" TEMPORARY
")();";
206 const char* run_lua_lua
= "dofile(" TEMPORARY
");";
208 void run_lua_fragment() throw(std::bad_alloc
)
212 int t
= lua_load(L
, read_lua_fragment
, NULL
, "run_lua_fragment");
213 if(t
== LUA_ERRSYNTAX
) {
214 messages
<< "Can't run Lua: Internal syntax error: " << lua_tostring(L
, -1) << std::endl
;
218 if(t
== LUA_ERRMEM
) {
219 messages
<< "Can't run Lua: Out of memory" << std::endl
;
223 recursive_flag
= true;
224 int r
= lua_pcall(L
, 0, 0, 0);
225 recursive_flag
= false;
226 if(r
== LUA_ERRRUN
) {
227 messages
<< "Error running Lua hunk: " << lua_tostring(L
, -1) << std::endl
;
230 if(r
== LUA_ERRMEM
) {
231 messages
<< "Error running Lua hunk: Out of memory" << std::endl
;
234 if(r
== LUA_ERRERR
) {
235 messages
<< "Error running Lua hunk: Double Fault???" << std::endl
;
238 if(lua_requests_repaint
) {
239 lua_requests_repaint
= false;
240 command::invokeC("repaint");
244 void do_eval_lua(const std::string
& c
) throw(std::bad_alloc
)
247 lua_setglobal(L
, TEMPORARY
);
248 luareader_fragment
= eval_lua_lua
;
252 void do_run_lua(const std::string
& c
) throw(std::bad_alloc
)
255 lua_setglobal(L
, TEMPORARY
);
256 luareader_fragment
= run_lua_lua
;
260 void run_lua_cb(int args
) throw()
262 recursive_flag
= true;
263 int r
= lua_pcall(L
, args
, 0, 0);
264 recursive_flag
= false;
265 if(r
== LUA_ERRRUN
) {
266 messages
<< "Error running Lua callback: " << lua_tostring(L
, -1) << std::endl
;
269 if(r
== LUA_ERRMEM
) {
270 messages
<< "Error running Lua callback: Out of memory" << std::endl
;
273 if(r
== LUA_ERRERR
) {
274 messages
<< "Error running Lua callback: Double Fault???" << std::endl
;
277 if(lua_requests_repaint
) {
278 lua_requests_repaint
= false;
279 command::invokeC("repaint");
284 void lua_callback_do_paint(struct lua_render_context
* ctx
) throw()
286 if(!callback_exists("on_paint"))
288 lua_render_ctx
= ctx
;
290 lua_render_ctx
= NULL
;
293 void lua_callback_do_video(struct lua_render_context
* ctx
) throw()
295 if(!callback_exists("on_video"))
297 lua_render_ctx
= ctx
;
299 lua_render_ctx
= NULL
;
302 void lua_callback_do_reset() throw()
304 if(!callback_exists("on_reset"))
309 void lua_callback_do_readwrite() throw()
311 if(!callback_exists("on_readwrite"))
316 void lua_callback_startup() throw()
318 if(!callback_exists("on_startup"))
323 void lua_callback_pre_load(const std::string
& name
) throw()
325 if(!callback_exists("on_pre_load"))
331 void lua_callback_err_load(const std::string
& name
) throw()
333 if(!callback_exists("on_err_load"))
339 void lua_callback_post_load(const std::string
& name
, bool was_state
) throw()
341 if(!callback_exists("on_post_load"))
344 push_boolean(was_state
);
348 void lua_callback_pre_save(const std::string
& name
, bool is_state
) throw()
350 if(!callback_exists("on_pre_save"))
353 push_boolean(is_state
);
357 void lua_callback_err_save(const std::string
& name
) throw()
359 if(!callback_exists("on_err_save"))
365 void lua_callback_post_save(const std::string
& name
, bool is_state
) throw()
367 if(!callback_exists("on_post_save"))
370 push_boolean(is_state
);
374 void lua_callback_do_input(controls_t
& data
, bool subframe
) throw()
376 if(!callback_exists("on_input"))
378 lua_input_controllerdata
= &data
;
379 push_boolean(subframe
);
381 lua_input_controllerdata
= NULL
;
384 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
) throw()
386 if(!callback_exists("on_snoop"))
388 lua_pushnumber(L
, port
);
389 lua_pushnumber(L
, controller
);
390 lua_pushnumber(L
, index
);
391 lua_pushnumber(L
, value
);
397 function_ptr_command
<const std::string
&> evaluate_lua("evaluate-lua", "Evaluate expression in Lua VM",
398 "Syntax: evaluate-lua <expression>\nEvaluates <expression> in Lua VM.\n",
399 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
401 throw std::runtime_error("Expected expression to evaluate");
405 function_ptr_command
<arg_filename
> run_lua("run-lua", "Run Lua script in Lua VM",
406 "Syntax: run-lua <file>\nRuns <file> in Lua VM.\n",
407 [](arg_filename args
) throw(std::bad_alloc
, std::runtime_error
)
413 void lua_callback_quit() throw()
415 if(!callback_exists("on_quit"))
420 void init_lua() throw()
422 L
= lua_newstate(alloc
, NULL
);
424 messages
<< "Can't initialize Lua." << std::endl
;
429 register_lua_functions(L
);
432 bool lua_requests_repaint
= false;
433 bool lua_requests_subframe_paint
= false;