5 #include "memorymanip.hpp"
6 #include "mainloop.hpp"
14 #include "fieldsplit.hpp"
18 std::map
<std::string
, lua_function
*>* functions
;
19 lua_State
* lua_initialized
;
22 int lua_trampoline_function(lua_State
* L
)
24 void* ptr
= lua_touserdata(L
, lua_upvalueindex(1));
25 lua_function
* f
= reinterpret_cast<lua_function
*>(ptr
);
26 return f
->invoke(L
, tmp_win
);
29 //Pushes given table to top of stack, creating if needed.
30 void recursive_lookup_table(lua_State
* L
, const std::string
& tab
)
33 lua_pushvalue(L
, LUA_GLOBALSINDEX
);
37 size_t split
= u
.find_last_of(".");
40 if(split
< u
.length()) {
41 u1
= u
.substr(0, split
);
42 u2
= u
.substr(split
+ 1);
44 recursive_lookup_table(L
, u1
);
45 lua_getfield(L
, -1, u2
.c_str());
46 if(lua_type(L
, -1) != LUA_TTABLE
) {
47 //Not a table, create a table.
50 lua_setfield(L
, -2, u2
.c_str());
51 lua_getfield(L
, -1, u2
.c_str());
53 //Get rid of previous table.
58 void register_lua_function(lua_State
* L
, const std::string
& fun
)
61 size_t split
= u
.find_last_of(".");
64 if(split
< u
.length()) {
65 u1
= u
.substr(0, split
);
66 u2
= u
.substr(split
+ 1);
68 recursive_lookup_table(L
, u1
);
69 void* ptr
= reinterpret_cast<void*>((*functions
)[fun
]);
70 lua_pushlightuserdata(L
, ptr
);
71 lua_pushcclosure(L
, lua_trampoline_function
, 1);
72 lua_setfield(L
, -2, u2
.c_str());
76 void register_lua_functions(lua_State
* L
)
79 for(auto i
= functions
->begin(); i
!= functions
->end(); i
++)
80 register_lua_function(L
, i
->first
);
85 lua_function::lua_function(const std::string
& name
) throw(std::bad_alloc
)
88 functions
= new std::map
<std::string
, lua_function
*>();
89 (*functions
)[fname
= name
] = this;
91 register_lua_function(lua_initialized
, fname
);
94 lua_function::~lua_function() throw()
98 functions
->erase(fname
);
101 std::string
get_string_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
103 if(lua_isnone(LS
, argindex
)) {
104 lua_pushfstring(LS
, "argument #%i to %s must be string", argindex
, fname
);
108 const char* f
= lua_tolstring(LS
, argindex
, &len
);
110 lua_pushfstring(LS
, "argument #%i to %s must be string", argindex
, fname
);
113 return std::string(f
, f
+ len
);
116 bool get_boolean_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
118 if(lua_isnone(LS
, argindex
) || !lua_isboolean(LS
, argindex
)) {
119 lua_pushfstring(LS
, "argument #%i to %s must be boolean", argindex
, fname
);
122 return (lua_toboolean(LS
, argindex
) != 0);
125 lua_render_context
* lua_render_ctx
= NULL
;
126 controls_t
* lua_input_controllerdata
= NULL
;
131 bool recursive_flag
= false;
132 const char* luareader_fragment
= NULL
;
134 const char* read_lua_fragment(lua_State
* LS
, void* dummy
, size_t* size
)
136 if(luareader_fragment
) {
137 const char* ret
= luareader_fragment
;
138 *size
= strlen(luareader_fragment
);
139 luareader_fragment
= NULL
;
147 void* alloc(void* user
, void* old
, size_t olds
, size_t news
)
150 return realloc(old
, news
);
156 bool callback_exists(const char* name
)
160 lua_getglobal(L
, name
);
161 int t
= lua_type(L
, -1);
162 if(t
!= LUA_TFUNCTION
)
164 return (t
== LUA_TFUNCTION
);
167 void push_string(const std::string
& s
)
169 lua_pushlstring(L
, s
.c_str(), s
.length());
172 void push_boolean(bool b
)
174 lua_pushboolean(L
, b
? 1 : 0);
177 #define TEMPORARY "LUAINTERP_INTERNAL_COMMAND_TEMPORARY"
179 const char* eval_lua_lua
= "loadstring(" TEMPORARY
")();";
180 const char* run_lua_lua
= "dofile(" TEMPORARY
");";
182 void run_lua_fragment(window
* win
) throw(std::bad_alloc
)
186 int t
= lua_load(L
, read_lua_fragment
, NULL
, "run_lua_fragment");
187 if(t
== LUA_ERRSYNTAX
) {
188 out(win
) << "Can't run Lua: Internal syntax error: " << lua_tostring(L
, -1) << std::endl
;
192 if(t
== LUA_ERRMEM
) {
193 out(win
) << "Can't run Lua: Out of memory" << std::endl
;
197 recursive_flag
= true;
199 int r
= lua_pcall(L
, 0, 0, 0);
200 recursive_flag
= false;
201 if(r
== LUA_ERRRUN
) {
202 out(win
) << "Error running Lua hunk: " << lua_tostring(L
, -1) << std::endl
;
205 if(r
== LUA_ERRMEM
) {
206 out(win
) << "Error running Lua hunk: Out of memory" << std::endl
;
209 if(r
== LUA_ERRERR
) {
210 out(win
) << "Error running Lua hunk: Double Fault???" << std::endl
;
213 if(lua_requests_repaint
) {
214 lua_requests_repaint
= false;
215 command::invokeC("repaint", win
);
219 void do_eval_lua(const std::string
& c
, window
* win
) throw(std::bad_alloc
)
222 lua_setglobal(L
, TEMPORARY
);
223 luareader_fragment
= eval_lua_lua
;
224 run_lua_fragment(win
);
227 void do_run_lua(const std::string
& c
, window
* win
) throw(std::bad_alloc
)
230 lua_setglobal(L
, TEMPORARY
);
231 luareader_fragment
= run_lua_lua
;
232 run_lua_fragment(win
);
235 void run_lua_cb(int args
, window
* win
) throw()
237 recursive_flag
= true;
239 int r
= lua_pcall(L
, args
, 0, 0);
240 recursive_flag
= false;
241 if(r
== LUA_ERRRUN
) {
242 out(win
) << "Error running Lua callback: " << lua_tostring(L
, -1) << std::endl
;
245 if(r
== LUA_ERRMEM
) {
246 out(win
) << "Error running Lua callback: Out of memory" << std::endl
;
249 if(r
== LUA_ERRERR
) {
250 out(win
) << "Error running Lua callback: Double Fault???" << std::endl
;
253 if(lua_requests_repaint
) {
254 lua_requests_repaint
= false;
255 command::invokeC("repaint", win
);
260 void lua_callback_do_paint(struct lua_render_context
* ctx
, window
* win
) throw()
262 if(!callback_exists("on_paint"))
264 lua_render_ctx
= ctx
;
266 lua_render_ctx
= NULL
;
269 void lua_callback_do_video(struct lua_render_context
* ctx
, window
* win
) throw()
271 if(!callback_exists("on_video"))
273 lua_render_ctx
= ctx
;
275 lua_render_ctx
= NULL
;
278 void lua_callback_do_reset(window
* win
) throw()
280 if(!callback_exists("on_reset"))
285 void lua_callback_do_readwrite(window
* win
) throw()
287 if(!callback_exists("on_readwrite"))
292 void lua_callback_startup(window
* win
) throw()
294 if(!callback_exists("on_startup"))
299 void lua_callback_pre_load(const std::string
& name
, window
* win
) throw()
301 if(!callback_exists("on_pre_load"))
307 void lua_callback_err_load(const std::string
& name
, window
* win
) throw()
309 if(!callback_exists("on_err_load"))
315 void lua_callback_post_load(const std::string
& name
, bool was_state
, window
* win
) throw()
317 if(!callback_exists("on_post_load"))
320 push_boolean(was_state
);
324 void lua_callback_pre_save(const std::string
& name
, bool is_state
, window
* win
) throw()
326 if(!callback_exists("on_pre_save"))
329 push_boolean(is_state
);
333 void lua_callback_err_save(const std::string
& name
, window
* win
) throw()
335 if(!callback_exists("on_err_save"))
341 void lua_callback_post_save(const std::string
& name
, bool is_state
, window
* win
) throw()
343 if(!callback_exists("on_post_save"))
346 push_boolean(is_state
);
350 void lua_callback_do_input(controls_t
& data
, bool subframe
, window
* win
) throw()
352 if(!callback_exists("on_input"))
354 lua_input_controllerdata
= &data
;
355 push_boolean(subframe
);
357 lua_input_controllerdata
= NULL
;
360 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
, window
* win
) throw()
362 if(!callback_exists("on_snoop"))
364 lua_pushnumber(L
, port
);
365 lua_pushnumber(L
, controller
);
366 lua_pushnumber(L
, index
);
367 lua_pushnumber(L
, value
);
373 class evallua
: public command
376 evallua() throw(std::bad_alloc
) : command("evaluate-lua") {}
377 void invoke(const std::string
& args
, window
* win
) throw(std::bad_alloc
, std::runtime_error
)
380 throw std::runtime_error("Expected expression to evaluate");
381 do_eval_lua(args
, win
);
383 std::string
get_short_help() throw(std::bad_alloc
) { return "Evaluate expression in Lua VM"; }
384 std::string
get_long_help() throw(std::bad_alloc
)
386 return "Syntax: evaluate-lua <expression>\n"
387 "Evaluates <expression> in Lua VM.\n";
391 class runlua
: public command
394 runlua() throw(std::bad_alloc
) : command("run-lua") {}
395 void invoke(const std::string
& args
, window
* win
) throw(std::bad_alloc
, std::runtime_error
)
398 throw std::runtime_error("Expected script to run");
399 do_run_lua(args
, win
);
401 std::string
get_short_help() throw(std::bad_alloc
) { return "Run Lua script in Lua VM"; }
402 std::string
get_long_help() throw(std::bad_alloc
)
404 return "Syntax: run-lua <file>\n"
405 "Runs <file> in Lua VM.\n";
410 void lua_callback_quit(window
* win
) throw()
412 if(!callback_exists("on_quit"))
417 void init_lua(window
* win
) throw()
419 L
= lua_newstate(alloc
, NULL
);
421 out(win
) << "Can't initialize Lua." << std::endl
;
426 register_lua_functions(L
);
429 bool lua_requests_repaint
= false;
430 bool lua_requests_subframe_paint
= false;