5 #include "memorymanip.hpp"
6 #include "mainloop.hpp"
18 std::map
<std::string
, lua_function
*>* functions
;
19 lua_State
* lua_initialized
;
20 int lua_trampoline_function(lua_State
* L
)
22 void* ptr
= lua_touserdata(L
, lua_upvalueindex(1));
23 lua_function
* f
= reinterpret_cast<lua_function
*>(ptr
);
27 //Pushes given table to top of stack, creating if needed.
28 void recursive_lookup_table(lua_State
* L
, const std::string
& tab
)
31 lua_pushvalue(L
, LUA_GLOBALSINDEX
);
35 size_t split
= u
.find_last_of(".");
38 if(split
< u
.length()) {
39 u1
= u
.substr(0, split
);
40 u2
= u
.substr(split
+ 1);
42 recursive_lookup_table(L
, u1
);
43 lua_getfield(L
, -1, u2
.c_str());
44 if(lua_type(L
, -1) != LUA_TTABLE
) {
45 //Not a table, create a table.
48 lua_setfield(L
, -2, u2
.c_str());
49 lua_getfield(L
, -1, u2
.c_str());
51 //Get rid of previous table.
56 void register_lua_function(lua_State
* L
, const std::string
& fun
)
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 void* ptr
= reinterpret_cast<void*>((*functions
)[fun
]);
68 lua_pushlightuserdata(L
, ptr
);
69 lua_pushcclosure(L
, lua_trampoline_function
, 1);
70 lua_setfield(L
, -2, u2
.c_str());
74 void register_lua_functions(lua_State
* L
)
77 for(auto i
= functions
->begin(); i
!= functions
->end(); i
++)
78 register_lua_function(L
, i
->first
);
83 lua_function::lua_function(const std::string
& name
) throw(std::bad_alloc
)
86 functions
= new std::map
<std::string
, lua_function
*>();
87 (*functions
)[fname
= name
] = this;
89 register_lua_function(lua_initialized
, fname
);
92 lua_function::~lua_function() throw()
96 functions
->erase(fname
);
99 std::string
get_string_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
101 if(lua_isnone(LS
, argindex
)) {
103 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
104 lua_pushstring(LS
, buffer
);
108 const char* f
= lua_tolstring(LS
, argindex
, &len
);
111 sprintf(buffer
, "argument #%i to %s must be string", argindex
, fname
);
112 lua_pushstring(LS
, buffer
);
115 return std::string(f
, f
+ len
);
118 bool get_boolean_argument(lua_State
* LS
, unsigned argindex
, const char* fname
)
120 if(lua_isnone(LS
, argindex
) || !lua_isboolean(LS
, argindex
)) {
122 sprintf(buffer
, "argument #%i to %s must be boolean", argindex
, fname
);
123 lua_pushstring(LS
, buffer
);
126 return (lua_toboolean(LS
, argindex
) != 0);
129 lua_render_context
* lua_render_ctx
= NULL
;
130 controls_t
* lua_input_controllerdata
= NULL
;
135 bool recursive_flag
= false;
136 const char* luareader_fragment
= NULL
;
138 const char* read_lua_fragment(lua_State
* LS
, void* dummy
, size_t* size
)
140 if(luareader_fragment
) {
141 const char* ret
= luareader_fragment
;
142 *size
= strlen(luareader_fragment
);
143 luareader_fragment
= NULL
;
151 void* alloc(void* user
, void* old
, size_t olds
, size_t news
)
154 return realloc(old
, news
);
160 bool callback_exists(const char* name
)
164 lua_getglobal(L
, name
);
165 int t
= lua_type(L
, -1);
166 if(t
!= LUA_TFUNCTION
)
168 return (t
== LUA_TFUNCTION
);
171 void push_string(const std::string
& s
)
173 lua_pushlstring(L
, s
.c_str(), s
.length());
176 void push_boolean(bool b
)
178 lua_pushboolean(L
, b
? 1 : 0);
181 #define TEMPORARY "LUAINTERP_INTERNAL_COMMAND_TEMPORARY"
183 const char* eval_lua_lua
= "loadstring(" TEMPORARY
")();";
184 const char* run_lua_lua
= "dofile(" TEMPORARY
");";
186 void run_lua_fragment() throw(std::bad_alloc
)
190 int t
= lua_load(L
, read_lua_fragment
, NULL
, "run_lua_fragment");
191 if(t
== LUA_ERRSYNTAX
) {
192 messages
<< "Can't run Lua: Internal syntax error: " << lua_tostring(L
, -1) << std::endl
;
196 if(t
== LUA_ERRMEM
) {
197 messages
<< "Can't run Lua: Out of memory" << std::endl
;
201 recursive_flag
= true;
202 int r
= lua_pcall(L
, 0, 0, 0);
203 recursive_flag
= false;
204 if(r
== LUA_ERRRUN
) {
205 messages
<< "Error running Lua hunk: " << lua_tostring(L
, -1) << std::endl
;
208 if(r
== LUA_ERRMEM
) {
209 messages
<< "Error running Lua hunk: Out of memory" << std::endl
;
212 if(r
== LUA_ERRERR
) {
213 messages
<< "Error running Lua hunk: Double Fault???" << std::endl
;
216 if(lua_requests_repaint
) {
217 lua_requests_repaint
= false;
218 command::invokeC("repaint");
222 void do_eval_lua(const std::string
& c
) throw(std::bad_alloc
)
225 lua_setglobal(L
, TEMPORARY
);
226 luareader_fragment
= eval_lua_lua
;
230 void do_run_lua(const std::string
& c
) throw(std::bad_alloc
)
233 lua_setglobal(L
, TEMPORARY
);
234 luareader_fragment
= run_lua_lua
;
238 void run_lua_cb(int args
) throw()
240 recursive_flag
= true;
241 int r
= lua_pcall(L
, args
, 0, 0);
242 recursive_flag
= false;
243 if(r
== LUA_ERRRUN
) {
244 messages
<< "Error running Lua callback: " << lua_tostring(L
, -1) << std::endl
;
247 if(r
== LUA_ERRMEM
) {
248 messages
<< "Error running Lua callback: Out of memory" << std::endl
;
251 if(r
== LUA_ERRERR
) {
252 messages
<< "Error running Lua callback: Double Fault???" << std::endl
;
255 if(lua_requests_repaint
) {
256 lua_requests_repaint
= false;
257 command::invokeC("repaint");
262 void lua_callback_do_paint(struct lua_render_context
* ctx
) throw()
264 if(!callback_exists("on_paint"))
266 lua_render_ctx
= ctx
;
268 lua_render_ctx
= NULL
;
271 void lua_callback_do_video(struct lua_render_context
* ctx
) throw()
273 if(!callback_exists("on_video"))
275 lua_render_ctx
= ctx
;
277 lua_render_ctx
= NULL
;
280 void lua_callback_do_reset() throw()
282 if(!callback_exists("on_reset"))
287 void lua_callback_do_readwrite() throw()
289 if(!callback_exists("on_readwrite"))
294 void lua_callback_startup() throw()
296 if(!callback_exists("on_startup"))
301 void lua_callback_pre_load(const std::string
& name
) throw()
303 if(!callback_exists("on_pre_load"))
309 void lua_callback_err_load(const std::string
& name
) throw()
311 if(!callback_exists("on_err_load"))
317 void lua_callback_post_load(const std::string
& name
, bool was_state
) throw()
319 if(!callback_exists("on_post_load"))
322 push_boolean(was_state
);
326 void lua_callback_pre_save(const std::string
& name
, bool is_state
) throw()
328 if(!callback_exists("on_pre_save"))
331 push_boolean(is_state
);
335 void lua_callback_err_save(const std::string
& name
) throw()
337 if(!callback_exists("on_err_save"))
343 void lua_callback_post_save(const std::string
& name
, bool is_state
) throw()
345 if(!callback_exists("on_post_save"))
348 push_boolean(is_state
);
352 void lua_callback_do_input(controls_t
& data
, bool subframe
) throw()
354 if(!callback_exists("on_input"))
356 lua_input_controllerdata
= &data
;
357 push_boolean(subframe
);
359 lua_input_controllerdata
= NULL
;
362 void lua_callback_snoop_input(uint32_t port
, uint32_t controller
, uint32_t index
, short value
) throw()
364 if(!callback_exists("on_snoop"))
366 lua_pushnumber(L
, port
);
367 lua_pushnumber(L
, controller
);
368 lua_pushnumber(L
, index
);
369 lua_pushnumber(L
, value
);
375 function_ptr_command
<const std::string
&> evaluate_lua("evaluate-lua", "Evaluate expression in Lua VM",
376 "Syntax: evaluate-lua <expression>\nEvaluates <expression> in Lua VM.\n",
377 [](const std::string
& args
) throw(std::bad_alloc
, std::runtime_error
) {
379 throw std::runtime_error("Expected expression to evaluate");
383 function_ptr_command
<arg_filename
> run_lua("run-lua", "Run Lua script in Lua VM",
384 "Syntax: run-lua <file>\nRuns <file> in Lua VM.\n",
385 [](arg_filename args
) throw(std::bad_alloc
, std::runtime_error
)
391 void lua_callback_quit() throw()
393 if(!callback_exists("on_quit"))
398 void init_lua() throw()
400 L
= lua_newstate(alloc
, NULL
);
402 messages
<< "Can't initialize Lua." << std::endl
;
407 register_lua_functions(L
);
410 bool lua_requests_repaint
= false;
411 bool lua_requests_subframe_paint
= false;