23 #include <lua/context.h> 24 #include <lua/context_watcher.h> 25 #include <core/threading/mutex.h> 26 #include <core/threading/mutex_locker.h> 27 #include <core/exceptions/system.h> 28 #include <core/exceptions/software.h> 29 #include <logging/liblogger.h> 69 __enable_tracebacks = enable_tracebacks;
73 __lua_mutex =
new Mutex();
75 __start_script = NULL;
91 __lua_mutex =
new Mutex();
92 __start_script = NULL;
102 if (! __finalize_call.empty())
103 do_string(__L,
"%s", __finalize_call.c_str());
107 __fam_thread->
join();
111 if ( __start_script ) free(__start_script);
131 __fam->add_filter(
"^[^.].*\\.lua$");
133 __fam->add_listener(
this);
137 __fam_thread->
start();
158 LuaContext::init_state()
160 lua_State *L = luaL_newstate();
163 if (__enable_tracebacks) {
164 lua_getglobal(L,
"debug");
165 lua_getfield(L, -1,
"traceback");
170 for (__slit = __package_dirs.begin(); __slit != __package_dirs.end(); ++__slit) {
171 do_string(L,
"package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", __slit->c_str(), __slit->c_str());
174 for (__slit = __cpackage_dirs.begin(); __slit != __cpackage_dirs.end(); ++__slit) {
175 do_string(L,
"package.cpath = package.cpath .. \";%s/?.so\"", __slit->c_str());
179 for (__slit = __packages.begin(); __slit != __packages.end(); ++__slit) {
180 do_string(L,
"require(\"%s\")", __slit->c_str());
183 for ( __utit = __usertypes.begin(); __utit != __usertypes.end(); ++__utit) {
184 tolua_pushusertype(L, __utit->second.first, __utit->second.second.c_str());
185 lua_setglobal(L, __utit->first.c_str());
188 for ( __strings_it = __strings.begin(); __strings_it != __strings.end(); ++__strings_it) {
189 lua_pushstring(L, __strings_it->second.c_str());
190 lua_setglobal(L, __strings_it->first.c_str());
193 for ( __booleans_it = __booleans.begin(); __booleans_it != __booleans.end(); ++__booleans_it) {
194 lua_pushboolean(L, __booleans_it->second);
195 lua_setglobal(L, __booleans_it->first.c_str());
198 for ( __numbers_it = __numbers.begin(); __numbers_it != __numbers.end(); ++__numbers_it) {
199 lua_pushnumber(L, __numbers_it->second);
200 lua_setglobal(L, __numbers_it->first.c_str());
203 for ( __integers_it = __integers.begin(); __integers_it != __integers.end(); ++__integers_it) {
204 lua_pushinteger(L, __integers_it->second);
205 lua_setglobal(L, __integers_it->first.c_str());
208 for ( __cfuncs_it = __cfuncs.begin(); __cfuncs_it != __cfuncs.end(); ++__cfuncs_it)
210 lua_pushcfunction(L, __cfuncs_it->second);
211 lua_setglobal(L, __cfuncs_it->first.c_str());
218 for (i = __watchers.begin(); i != __watchers.end(); ++i) {
220 (*i)->lua_restarted(tmpctx);
223 if (! __finalize_call.empty())
224 do_string(L,
"%s", __finalize_call.c_str());
235 if ( __start_script ) {
236 if (access(__start_script, R_OK) == 0) {
240 do_string(L,
"require(\"%s\")", __start_script);
244 if (! __finalize_call.empty())
245 do_string(L,
"%s", __finalize_call.c_str());
268 if ( __start_script ) free(__start_script);
269 if ( start_script ) {
270 __start_script = strdup(start_script);
271 if (access(__start_script, R_OK) == 0) {
275 do_string(
"require(\"%s\")", __start_script);
278 __start_script = NULL;
292 if (! __finalize_prepare_call.empty())
293 do_string(__L,
"%s", __finalize_prepare_call.c_str());
296 lua_State *L = init_state();
301 if (! __finalize_call.empty())
302 do_string(__L,
"%s", __finalize_call.c_str());
305 "exception follows, ignoring.");
310 if (__owns_L) lua_close(tL);
315 "occured while initializing new state. Keeping old state.");
317 if (! __finalize_cancel_call.empty())
318 do_string(__L,
"%s", __finalize_cancel_call.c_str());
337 "package.path = \"%s/?.lua;%s/?/init.lua;\"" 338 ".. package.path", path, path);
340 __package_dirs.push_front(path);
343 "package.path = package.path .. " 344 "\";%s/?.lua;%s/?/init.lua\"", path, path);
346 __package_dirs.push_back(path);
348 if ( __fam ) __fam->watch_dir(path);
365 do_string(__L,
"package.cpath = \"%s/?.so;\" .. package.cpath", path);
367 __cpackage_dirs.push_front(path);
369 do_string(__L,
"package.cpath = package.cpath .. \";%s/?.so\"", path);
371 __cpackage_dirs.push_back(path);
373 if ( __fam ) __fam->watch_dir(path);
386 if (find(__packages.begin(), __packages.end(), package) == __packages.end()) {
387 do_string(__L,
"require(\"%s\")", package);
389 __packages.push_back(package);
453 if ( (err = luaL_loadfile(L, filename)) != 0) {
454 errmsg = lua_tostring(L, -1);
468 int errfunc = __enable_tracebacks ? 1 : 0;
469 if ( (err = lua_pcall(L, 0, LUA_MULTRET, errfunc)) != 0 ) {
471 errmsg = lua_tostring(L, -1);
500 va_start(arg, format);
502 if (vasprintf(&s, format, arg) == -1) {
503 throw Exception(
"LuaContext::do_string: Could not form string");
511 if ( (err = luaL_loadstring(L, ss.c_str())) != 0) {
512 errmsg = lua_tostring(L, -1);
523 int errfunc = __enable_tracebacks ? 1 : 0;
524 err = lua_pcall(L, 0, LUA_MULTRET, errfunc);
527 std::string errmsg = lua_tostring(L, -1);
553 va_start(arg, format);
555 if (vasprintf(&s, format, arg) == -1) {
556 throw Exception(
"LuaContext::do_string: Could not form string");
564 if ( (err = luaL_loadstring(__L, ss.c_str())) != 0) {
565 errmsg = lua_tostring(__L, -1);
576 int errfunc = __enable_tracebacks ? 1 : 0;
577 err = lua_pcall(__L, 0, LUA_MULTRET, errfunc);
580 std::string errmsg = lua_tostring(__L, -1);
604 if ( (err = luaL_loadstring(__L, s)) != 0 ) {
605 std::string errmsg = lua_tostring(__L, -1);
632 if ( ! errfunc && __enable_tracebacks ) errfunc = 1;
633 if ( (err = lua_pcall(__L, nargs, nresults, errfunc)) != 0 ) {
634 std::string errmsg = lua_tostring(__L, -1);
659 LuaContext::assert_unique_name(
const char *name, std::string type)
661 if ( (type ==
"usertype") && (__usertypes.find(name) != __usertypes.end()) ) {
662 throw Exception(
"User type entry already exists for name %s", name);
664 if ( (type ==
"string") && (__strings.find(name) != __strings.end()) ) {
665 throw Exception(
"String entry already exists for name %s", name);
667 if ( (type ==
"boolean") && (__booleans.find(name) != __booleans.end()) ) {
668 throw Exception(
"Boolean entry already exists for name %s", name);
670 if ( (type ==
"number") && (__numbers.find(name) != __numbers.end()) ) {
671 throw Exception(
"Number entry already exists for name %s", name);
673 if ( (type ==
"integer") && (__integers.find(name) != __integers.end()) ) {
674 throw Exception(
"Integer entry already exists for name %s", name);
676 if ( (type ==
"cfunction") && (__cfuncs.find(name) != __cfuncs.end()) ) {
677 throw Exception(
"C function entry already exists for name %s", name);
690 const char *
type_name,
const char *name_space)
696 type_n = std::string(name_space) +
"::" +
type_name;
699 assert_unique_name(name,
"usertype");
701 __usertypes[name] = std::make_pair(data, type_n);
703 tolua_pushusertype(__L, data, type_n.c_str());
704 lua_setglobal(__L, name);
716 assert_unique_name(name,
"string");
718 __strings[name] = value;
720 lua_pushstring(__L, value);
721 lua_setglobal(__L, name);
733 assert_unique_name(name,
"boolean");
735 __booleans[name] = value;
737 lua_pushboolean(__L, value ? 1 : 0);
738 lua_setglobal(__L, name);
750 assert_unique_name(name,
"number");
752 __numbers[name] = value;
754 lua_pushnumber(__L, value);
755 lua_setglobal(__L, name);
767 assert_unique_name(name,
"integer");
769 __integers[name] = value;
771 lua_pushinteger(__L, value);
772 lua_setglobal(__L, name);
784 assert_unique_name(name,
"cfunction");
788 lua_pushcfunction(__L, f);
789 lua_setglobal(__L, name);
800 lua_pushboolean(__L, value ? 1 : 0);
813 va_start(arg, format);
814 lua_pushvfstring(__L, format, arg);
826 lua_pushinteger(__L, value);
837 lua_pushlightuserdata(__L, p);
849 lua_pushlstring(__L, s, len);
870 lua_pushnumber(__L, value);
881 lua_pushstring(__L, value);
902 lua_pushvalue(__L, idx);
915 lua_pushvfstring(__L, format, arg);
926 const char *name_space)
932 type_n = std::string(name_space) +
"::" +
type_name;
935 tolua_pushusertype(__L, data, type_n.c_str());
946 lua_pushcfunction(__L, f);
957 return lua_typename(__L, lua_type(__L, idx));
967 if (__enable_tracebacks && (n >=
stack_size())) {
980 if (__enable_tracebacks && ((idx == 1) || (idx == -
stack_size()))) {
983 lua_remove(__L, idx);
993 return lua_gettop(__L);
1004 lua_createtable(__L, narr, nrec);
1017 lua_settable(__L, t_index);
1032 lua_setfield(__L, t_index, key);
1044 lua_setglobal(__L, name);
1058 lua_gettable(__L, idx);
1071 lua_getfield(__L, idx, k);
1082 lua_rawset(__L, idx);
1095 lua_rawseti(__L, idx, n);
1106 lua_rawget(__L, idx);
1118 lua_rawgeti(__L, idx, n);
1128 lua_getglobal(__L, name);
1142 __usertypes.erase(name);
1143 __strings.erase(name);
1144 __booleans.erase(name);
1145 __numbers.erase(name);
1146 __integers.erase(name);
1147 __cfuncs.erase(name);
1150 lua_setglobal(__L, name);
1162 return lua_next(__L, idx) != 0;
1173 return lua_tonumber(__L, idx);
1184 return lua_tointeger(__L, idx);
1195 return lua_toboolean(__L, idx);
1206 return lua_tostring(__L, idx);
1216 return lua_touserdata(__L, idx);
1227 return (
void *)lua_topointer(__L, idx);
1238 return tolua_tousertype(__L, idx, 0);
1249 return lua_isboolean(__L, idx);
1260 return lua_iscfunction(__L, idx);
1271 return lua_isfunction(__L, idx);
1282 return lua_islightuserdata(__L, idx);
1293 return lua_isnil(__L, idx);
1304 return lua_isnumber(__L, idx);
1315 return lua_isstring(__L, idx);
1326 return lua_istable(__L, idx);
1337 return lua_isthread(__L, idx);
1348 return lua_objlen(__L, idx);
1360 #if LUA_VERSION_NUM > 501 1364 const char *val_name;
1365 while ((val_name = lua_getupvalue(__L, idx, ++n)) != NULL) {
1366 if (strcmp(val_name,
"_ENV") == 0) {
1376 if (val_name != NULL) {
1378 luaL_loadstring(__L,
"");
1379 lua_pushvalue(__L, -3);
1380 lua_setupvalue(__L, -2, 1);
1381 int act_idx = idx > 0 ? idx : idx - 2;
1382 lua_upvaluejoin(__L, act_idx, n, -1, 1);
1385 throw Exception(
"No environment found");
1388 lua_setfenv(__L, idx);
1398 __watchers.push_back_locked(watcher);
1408 __watchers.remove_locked(watcher);
1424 std::string finalize_cancel)
1426 __finalize_call = finalize;
1427 __finalize_prepare_call = finalize_prepare;
1428 __finalize_cancel_call = finalize_cancel;
1438 if ( __fam) __fam->process_events();
void restart()
Restart Lua.
void push_thread()
Push thread on top of stack.
File could not be opened.
void push_light_user_data(void *p)
Push light user data on top of stack.
void setup_fam(bool auto_restart, bool conc_thread)
Setup file alteration monitor.
void push_vfstring(const char *format, va_list arg)
Push formatted string on top of stack.
bool is_light_user_data(int idx)
Check if stack value is light user data.
bool is_number(int idx)
Check if stack value is a number.
void push_integer(lua_Integer value)
Push integer on top of stack.
void raw_geti(int idx, int n)
Get indexed value without invoking meta methods.
Fawkes library namespace.
void unlock()
Unlock the mutex.
bool is_thread(int idx)
Check if stack value is a thread.
void pop(int n)
Pop value(s) from stack.
void push_lstring(const char *s, size_t len)
Push substring on top of stack.
void remove(int idx)
Remove value from stack.
void set_cfunction(const char *name, lua_CFunction f)
Assign cfunction to global variable.
void raw_seti(int idx, int n)
Set indexed value without invoking meta methods.
virtual void fam_event(const char *filename, unsigned int mask)
Event has been raised.
void load_string(const char *s)
Load Lua string.
void add_package_dir(const char *path, bool prefix=false)
Add a Lua package directory.
void remove_watcher(LuaContextWatcher *watcher)
Remove a context watcher.
bool is_cfunction(int idx)
Check if stack value is a C function.
bool try_lock()
Try to lock the Lua state.
void set_field(const char *key, int t_index=-2)
Set field of a table.
void set_table(int t_index=-3)
Set value of a table.
void add_package(const char *package)
Add a default package.
void unlock()
Unlock the mutex.
void unlock()
Unlock Lua state.
static void log_error(const char *component, const char *format,...)
Log error message.
void push_value(int idx)
Push a copy of the element at the given index on top of the stack.
void push_nil()
Push nil on top of stack.
int stack_size()
Get size of stack.
void pcall(int nargs=0, int nresults=0, int errfunc=0)
Protected call.
bool is_nil(int idx)
Check if stack value is nil.
Base class for exceptions in Fawkes.
lua_Number to_number(int idx)
Retrieve stack value as number.
void push_cfunction(lua_CFunction f)
Push C function on top of stack.
void do_string(const char *format,...)
Execute string.
void do_file(const char *filename)
Execute file.
void set_number(const char *name, lua_Number value)
Assign number to global variable.
LuaContext(bool enable_tracebacks=true)
Constructor.
void setfenv(int idx=-2)
Set function environment.
void get_field(int idx, const char *k)
Get named value from table.
void relock()
Lock this mutex, again.
void set_integer(const char *name, lua_Integer value)
Assign integer to global variable.
Monitors files for changes.
lua_Integer to_integer(int idx)
Retrieve stack value as integer.
void set_usertype(const char *name, void *data, const char *type_name, const char *name_space=0)
Assign usertype to global variable.
void push_usertype(void *data, const char *type_name, const char *name_space=0)
Push usertype on top of stack.
static void log_warn(const char *component, const char *format,...)
Log warning message.
bool try_lock()
Tries to lock the mutex.
void set_string(const char *name, const char *value)
Assign string to global variable.
void push_string(const char *value)
Push string on top of stack.
bool is_table(int idx)
Check if stack value is a table.
void cancel()
Cancel a thread.
void set_finalization_calls(std::string finalize, std::string finalize_prepare, std::string finalize_cancel)
Set code to execute during finalization.
void process_fam_events()
Process FAM events.
void set_boolean(const char *name, bool value)
Assign boolean to global variable.
RefPtr<> is a reference-counting shared smartpointer.
bool is_string(int idx)
Check if stack value is a string.
void get_global(const char *name)
Get global variable.
void push_boolean(bool value)
Push boolean on top of stack.
void add_cpackage_dir(const char *path, bool prefix=false)
Add a Lua C package directory.
void set_start_script(const char *start_script)
Set start script.
bool is_function(int idx)
Check if stack value is a function.
bool to_boolean(int idx)
Retrieve stack value as boolean.
bool table_next(int idx)
Iterate to next entry of table.
lua_State * get_lua_state()
Get Lua state.
void join()
Join the thread.
void get_table(int idx)
Get value from table.
FileAlterationMonitor thread wrapper.
void lock()
Lock this mutex.
void lock()
Lock Lua state.
void remove_global(const char *name)
Remove global variable.
Mutex mutual exclusion lock.
void set_global(const char *name)
Set a global value.
void * to_pointer(int idx)
Retrieve stack value as pointer.
void create_table(int narr=0, int nrec=0)
Create a table on top of the stack.
void push_number(lua_Number value)
Push number on top of stack.
void * to_userdata(int idx)
Retrieve stack value as userdata.
void * to_usertype(int idx)
Retrieve stack value as a tolua++ user type.
const char * to_string(int idx)
Retrieve stack value as string.
void raw_get(int idx)
Get value without invoking meta methods.
size_t objlen(int idx)
Get object length.
System ran out of memory and desired operation could not be fulfilled.
void start(bool wait=true)
Call this method to start the thread.
std::string type_name(int idx)
Get name of type of value at a given index.
RefPtr< FileAlterationMonitor > get_fam() const
Get file alteration monitor.
void add_watcher(LuaContextWatcher *watcher)
Add a context watcher.
bool is_boolean(int idx)
Check if stack value is a boolean.
void push_fstring(const char *format,...)
Push formatted string on top of stack.
void raw_set(int idx)
Set value without invoking meta methods.