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>
38 #define lua_objlen(L,i) lua_rawlen(L, (i))
41 #if LUA_VERSION_NUM < 502
42 # define lua_getuservalue lua_getfenv
43 # define lua_setuservalue lua_setfenv
75 LuaContext::LuaContext(
bool enable_tracebacks)
78 __enable_tracebacks = enable_tracebacks;
82 __lua_mutex =
new Mutex();
84 __start_script = NULL;
96 LuaContext::LuaContext(lua_State *L)
100 __lua_mutex =
new Mutex();
101 __start_script = NULL;
107 LuaContext::~LuaContext()
111 __fam_thread->cancel();
112 __fam_thread->join();
116 if ( __start_script ) free(__start_script);
133 LuaContext::setup_fam(
bool auto_restart,
bool conc_thread)
136 __fam->add_filter(
"^[^.].*\\.lua$");
138 __fam->add_listener(
this);
142 __fam_thread->start();
152 LuaContext::get_fam()
const
163 LuaContext::init_state()
165 lua_State *L = luaL_newstate();
168 if (__enable_tracebacks) {
169 lua_getglobal(L,
"debug");
170 lua_getfield(L, -1,
"traceback");
175 for (__slit = __package_dirs.begin(); __slit != __package_dirs.end(); ++__slit) {
176 do_string(L,
"package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", __slit->c_str(), __slit->c_str());
179 for (__slit = __cpackage_dirs.begin(); __slit != __cpackage_dirs.end(); ++__slit) {
180 do_string(L,
"package.cpath = package.cpath .. \";%s/?.so\"", __slit->c_str());
184 for (__slit = __packages.begin(); __slit != __packages.end(); ++__slit) {
185 do_string(L,
"require(\"%s\")", __slit->c_str());
188 for ( __utit = __usertypes.begin(); __utit != __usertypes.end(); ++__utit) {
189 tolua_pushusertype(L, __utit->second.first, __utit->second.second.c_str());
190 lua_setglobal(L, __utit->first.c_str());
193 for ( __strings_it = __strings.begin(); __strings_it != __strings.end(); ++__strings_it) {
194 lua_pushstring(L, __strings_it->second.c_str());
195 lua_setglobal(L, __strings_it->first.c_str());
198 for ( __booleans_it = __booleans.begin(); __booleans_it != __booleans.end(); ++__booleans_it) {
199 lua_pushboolean(L, __booleans_it->second);
200 lua_setglobal(L, __booleans_it->first.c_str());
203 for ( __numbers_it = __numbers.begin(); __numbers_it != __numbers.end(); ++__numbers_it) {
204 lua_pushnumber(L, __numbers_it->second);
205 lua_setglobal(L, __numbers_it->first.c_str());
208 for ( __integers_it = __integers.begin(); __integers_it != __integers.end(); ++__integers_it) {
209 lua_pushinteger(L, __integers_it->second);
210 lua_setglobal(L, __integers_it->first.c_str());
213 for ( __cfuncs_it = __cfuncs.begin(); __cfuncs_it != __cfuncs.end(); ++__cfuncs_it)
215 lua_pushcfunction(L, __cfuncs_it->second);
216 lua_setglobal(L, __cfuncs_it->first.c_str());
219 LuaContext *tmpctx =
new LuaContext(L);
220 MutexLocker(__watchers.mutex());
221 LockList<LuaContextWatcher *>::iterator i;
222 for (i = __watchers.begin(); i != __watchers.end(); ++i) {
224 (*i)->lua_restarted(tmpctx);
233 if ( __start_script ) {
234 if (access(__start_script, R_OK) == 0) {
236 do_file(L, __start_script);
238 do_string(L,
"require(\"%s\")", __start_script);
258 LuaContext::set_start_script(
const char *start_script)
260 if ( __start_script ) free(__start_script);
261 if ( start_script ) {
262 __start_script = strdup(start_script);
263 if (access(__start_script, R_OK) == 0) {
265 do_file(__start_script);
267 do_string(
"require(\"%s\")", __start_script);
270 __start_script = NULL;
280 LuaContext::restart()
284 lua_State *L = init_state();
290 LibLogger::log_error(
"LuaContext",
"Could not restart Lua instance, an error "
291 "occured while initializing new state. Keeping old state.");
292 LibLogger::log_error(
"LuaContext", e);
303 LuaContext::add_package_dir(
const char *path)
307 do_string(__L,
"package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", path, path);
309 __package_dirs.push_back(path);
310 if ( __fam ) __fam->watch_dir(path);
320 LuaContext::add_cpackage_dir(
const char *path)
324 do_string(__L,
"package.cpath = package.cpath .. \";%s/?.so\"", path);
326 __cpackage_dirs.push_back(path);
327 if ( __fam ) __fam->watch_dir(path);
337 LuaContext::add_package(
const char *package)
340 if (find(__packages.begin(), __packages.end(), package) == __packages.end()) {
341 do_string(__L,
"require(\"%s\")", package);
343 __packages.push_back(package);
354 LuaContext::get_lua_state()
372 LuaContext::try_lock()
374 return __lua_mutex->try_lock();
382 __lua_mutex->unlock();
390 LuaContext::do_file(
const char *filename)
393 do_file(__L, filename);
402 LuaContext::do_file(lua_State *L,
const char *filename)
407 if ( (err = luaL_loadfile(L, filename)) != 0) {
408 errmsg = lua_tostring(L, -1);
422 int errfunc = __enable_tracebacks ? 1 : 0;
423 if ( (err = lua_pcall(L, 0, LUA_MULTRET, errfunc)) != 0 ) {
425 errmsg = lua_tostring(L, -1);
429 throw LuaRuntimeException(
"do_file", errmsg.c_str());
432 throw OutOfMemoryException(
"Could not execute Lua file %s", filename);
435 throw LuaErrorException(
"do_file", errmsg.c_str());
438 throw LuaErrorException(
"do_file/unknown error", errmsg.c_str());
451 LuaContext::do_string(lua_State *L,
const char *format, ...)
454 va_start(arg, format);
456 if (vasprintf(&s, format, arg) == -1) {
457 throw Exception(
"LuaContext::do_string: Could not form string");
461 int errfunc = __enable_tracebacks ? 1 : 0;
462 rv = (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, errfunc));
468 std::string errmsg = lua_tostring(L, -1);
470 throw LuaRuntimeException(
"do_string", errmsg.c_str());
480 LuaContext::do_string(
const char *format, ...)
484 va_start(arg, format);
486 if (vasprintf(&s, format, arg) == -1) {
487 throw Exception(
"LuaContext::do_string: Could not form string");
491 int errfunc = __enable_tracebacks ? 1 : 0;
492 rv = (luaL_loadstring(__L, s) || lua_pcall(__L, 0, LUA_MULTRET, errfunc));
498 std::string errmsg = lua_tostring(__L, -1);
510 LuaContext::load_string(
const char *s)
513 if ( (err = luaL_loadstring(__L, s)) != 0 ) {
514 std::string errmsg = lua_tostring(__L, -1);
538 LuaContext::pcall(
int nargs,
int nresults,
int errfunc)
541 if ( ! errfunc && __enable_tracebacks ) errfunc = 1;
542 if ( (err = lua_pcall(__L, nargs, nresults, errfunc)) != 0 ) {
543 std::string errmsg = lua_tostring(__L, -1);
568 LuaContext::assert_unique_name(
const char *name, std::string type)
570 if ( (type ==
"usertype") && (__usertypes.find(name) != __usertypes.end()) ) {
571 throw Exception(
"User type entry already exists for name %s", name);
573 if ( (type ==
"string") && (__strings.find(name) != __strings.end()) ) {
574 throw Exception(
"String entry already exists for name %s", name);
576 if ( (type ==
"boolean") && (__booleans.find(name) != __booleans.end()) ) {
577 throw Exception(
"Boolean entry already exists for name %s", name);
579 if ( (type ==
"number") && (__numbers.find(name) != __numbers.end()) ) {
580 throw Exception(
"Number entry already exists for name %s", name);
582 if ( (type ==
"integer") && (__integers.find(name) != __integers.end()) ) {
583 throw Exception(
"Integer entry already exists for name %s", name);
585 if ( (type ==
"cfunction") && (__cfuncs.find(name) != __cfuncs.end()) ) {
586 throw Exception(
"C function entry already exists for name %s", name);
598 LuaContext::set_usertype(
const char *name,
void *data,
599 const char *type_name,
const char *name_space)
603 std::string type_n = type_name;
605 type_n = std::string(name_space) +
"::" + type_name;
608 assert_unique_name(name,
"usertype");
610 __usertypes[name] = std::make_pair(data, type_n);
612 tolua_pushusertype(__L, data, type_n.c_str());
613 lua_setglobal(__L, name);
622 LuaContext::set_string(
const char *name,
const char *value)
625 assert_unique_name(name,
"string");
627 __strings[name] = value;
629 lua_pushstring(__L, value);
630 lua_setglobal(__L, name);
639 LuaContext::set_boolean(
const char *name,
bool value)
642 assert_unique_name(name,
"boolean");
644 __booleans[name] = value;
646 lua_pushboolean(__L, value ? 1 : 0);
647 lua_setglobal(__L, name);
656 LuaContext::set_number(
const char *name, lua_Number value)
659 assert_unique_name(name,
"number");
661 __numbers[name] = value;
663 lua_pushnumber(__L, value);
664 lua_setglobal(__L, name);
673 LuaContext::set_integer(
const char *name, lua_Integer value)
676 assert_unique_name(name,
"integer");
678 __integers[name] = value;
680 lua_pushinteger(__L, value);
681 lua_setglobal(__L, name);
690 LuaContext::set_cfunction(
const char *name, lua_CFunction f)
693 assert_unique_name(name,
"cfunction");
697 lua_pushcfunction(__L, f);
698 lua_setglobal(__L, name);
706 LuaContext::push_boolean(
bool value)
709 lua_pushboolean(__L, value ? 1 : 0);
718 LuaContext::push_fstring(
const char *format, ...)
722 va_start(arg, format);
723 lua_pushvfstring(__L, format, arg);
732 LuaContext::push_integer(lua_Integer value)
735 lua_pushinteger(__L, value);
743 LuaContext::push_light_user_data(
void *p)
746 lua_pushlightuserdata(__L, p);
755 LuaContext::push_lstring(
const char *s,
size_t len)
758 lua_pushlstring(__L, s, len);
765 LuaContext::push_nil()
776 LuaContext::push_number(lua_Number value)
779 lua_pushnumber(__L, value);
787 LuaContext::push_string(
const char *value)
790 lua_pushstring(__L, value);
797 LuaContext::push_thread()
808 LuaContext::push_value(
int idx)
811 lua_pushvalue(__L, idx);
821 LuaContext::push_vfstring(
const char *format, va_list arg)
824 lua_pushvfstring(__L, format, arg);
834 LuaContext::push_usertype(
void *data,
const char *type_name,
835 const char *name_space)
839 std::string type_n = type_name;
841 type_n = std::string(name_space) +
"::" + type_name;
844 tolua_pushusertype(__L, data, type_n.c_str());
852 LuaContext::push_cfunction(lua_CFunction f)
855 lua_pushcfunction(__L, f);
863 LuaContext::pop(
int n)
866 if (__enable_tracebacks && (n >= stack_size())) {
876 LuaContext::remove(
int idx)
879 if (__enable_tracebacks && ((idx == 1) || (idx == -stack_size()))) {
882 lua_remove(__L, idx);
890 LuaContext::stack_size()
892 return lua_gettop(__L);
901 LuaContext::create_table(
int narr,
int nrec)
903 lua_createtable(__L, narr, nrec);
914 LuaContext::set_table(
int t_index)
916 lua_settable(__L, t_index);
929 LuaContext::set_field(
const char *key,
int t_index)
931 lua_setfield(__L, t_index, key);
941 LuaContext::set_global(
const char *name)
943 lua_setglobal(__L, name);
955 LuaContext::get_table(
int idx)
957 lua_gettable(__L, idx);
968 LuaContext::get_field(
int idx,
const char *k)
970 lua_getfield(__L, idx, k);
979 LuaContext::raw_set(
int idx)
981 lua_rawset(__L, idx);
992 LuaContext::raw_seti(
int idx,
int n)
994 lua_rawseti(__L, idx, n);
1003 LuaContext::raw_get(
int idx)
1005 lua_rawget(__L, idx);
1015 LuaContext::raw_geti(
int idx,
int n)
1017 lua_rawgeti(__L, idx, n);
1025 LuaContext::get_global(
const char *name)
1027 lua_getglobal(__L, name);
1037 LuaContext::remove_global(
const char *name)
1041 __usertypes.erase(name);
1042 __strings.erase(name);
1043 __booleans.erase(name);
1044 __numbers.erase(name);
1045 __integers.erase(name);
1046 __cfuncs.erase(name);
1049 lua_setglobal(__L, name);
1058 LuaContext::to_number(
int idx)
1060 return lua_tonumber(__L, idx);
1069 LuaContext::to_integer(
int idx)
1071 return lua_tointeger(__L, idx);
1080 LuaContext::to_boolean(
int idx)
1082 return lua_toboolean(__L, idx);
1091 LuaContext::to_string(
int idx)
1093 return lua_tostring(__L, idx);
1102 LuaContext::is_boolean(
int idx)
1104 return lua_isboolean(__L, idx);
1113 LuaContext::is_cfunction(
int idx)
1115 return lua_iscfunction(__L, idx);
1124 LuaContext::is_function(
int idx)
1126 return lua_isfunction(__L, idx);
1135 LuaContext::is_light_user_data(
int idx)
1137 return lua_islightuserdata(__L, idx);
1146 LuaContext::is_nil(
int idx)
1148 return lua_isnil(__L, idx);
1157 LuaContext::is_number(
int idx)
1159 return lua_isnumber(__L, idx);
1168 LuaContext::is_string(
int idx)
1170 return lua_isstring(__L, idx);
1179 LuaContext::is_table(
int idx)
1181 return lua_istable(__L, idx);
1190 LuaContext::is_thread(
int idx)
1192 return lua_isthread(__L, idx);
1201 LuaContext::objlen(
int idx)
1203 return lua_objlen(__L, idx);
1213 LuaContext::setfenv(
int idx)
1215 lua_setuservalue(__L, idx);
1225 __watchers.push_back_locked(watcher);
1235 __watchers.remove_locked(watcher);
1242 LuaContext::process_fam_events()
1244 if ( __fam) __fam->process_events();
1249 LuaContext::fam_event(
const char *filename,
unsigned int mask)
File could not be opened.
Base class for exceptions in Fawkes.
Monitors files for changes.
RefPtr<> is a reference-counting shared smartpointer.
FileAlterationMonitor thread wrapper.
Mutex mutual exclusion lock.
System ran out of memory and desired operation could not be fulfilled.