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>
66 LuaContext::LuaContext(
bool enable_tracebacks)
69 __enable_tracebacks = enable_tracebacks;
73 __lua_mutex =
new Mutex();
75 __start_script = NULL;
87 LuaContext::LuaContext(lua_State *L)
91 __lua_mutex =
new Mutex();
92 __start_script = NULL;
98 LuaContext::~LuaContext()
102 __fam_thread->cancel();
103 __fam_thread->join();
107 if ( __start_script ) free(__start_script);
124 LuaContext::setup_fam(
bool auto_restart,
bool conc_thread)
127 __fam->add_filter(
"^[^.].*\\.lua$");
129 __fam->add_listener(
this);
133 __fam_thread->start();
143 LuaContext::get_fam()
const
154 LuaContext::init_state()
156 lua_State *L = luaL_newstate();
159 if (__enable_tracebacks) {
160 lua_getglobal(L,
"debug");
161 lua_getfield(L, -1,
"traceback");
166 for (__slit = __package_dirs.begin(); __slit != __package_dirs.end(); ++__slit) {
167 do_string(L,
"package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", __slit->c_str(), __slit->c_str());
170 for (__slit = __cpackage_dirs.begin(); __slit != __cpackage_dirs.end(); ++__slit) {
171 do_string(L,
"package.cpath = package.cpath .. \";%s/?.so\"", __slit->c_str());
175 for (__slit = __packages.begin(); __slit != __packages.end(); ++__slit) {
176 do_string(L,
"require(\"%s\")", __slit->c_str());
179 for ( __utit = __usertypes.begin(); __utit != __usertypes.end(); ++__utit) {
180 tolua_pushusertype(L, __utit->second.first, __utit->second.second.c_str());
181 lua_setglobal(L, __utit->first.c_str());
184 for ( __strings_it = __strings.begin(); __strings_it != __strings.end(); ++__strings_it) {
185 lua_pushstring(L, __strings_it->second.c_str());
186 lua_setglobal(L, __strings_it->first.c_str());
189 for ( __booleans_it = __booleans.begin(); __booleans_it != __booleans.end(); ++__booleans_it) {
190 lua_pushboolean(L, __booleans_it->second);
191 lua_setglobal(L, __booleans_it->first.c_str());
194 for ( __numbers_it = __numbers.begin(); __numbers_it != __numbers.end(); ++__numbers_it) {
195 lua_pushnumber(L, __numbers_it->second);
196 lua_setglobal(L, __numbers_it->first.c_str());
199 for ( __integers_it = __integers.begin(); __integers_it != __integers.end(); ++__integers_it) {
200 lua_pushinteger(L, __integers_it->second);
201 lua_setglobal(L, __integers_it->first.c_str());
204 for ( __cfuncs_it = __cfuncs.begin(); __cfuncs_it != __cfuncs.end(); ++__cfuncs_it)
206 lua_pushcfunction(L, __cfuncs_it->second);
207 lua_setglobal(L, __cfuncs_it->first.c_str());
210 LuaContext *tmpctx =
new LuaContext(L);
211 MutexLocker(__watchers.mutex());
212 LockList<LuaContextWatcher *>::iterator i;
213 for (i = __watchers.begin(); i != __watchers.end(); ++i) {
215 (*i)->lua_restarted(tmpctx);
224 if ( __start_script ) {
225 if (access(__start_script, R_OK) == 0) {
227 do_file(L, __start_script);
229 do_string(L,
"require(\"%s\")", __start_script);
249 LuaContext::set_start_script(
const char *start_script)
251 if ( __start_script ) free(__start_script);
252 if ( start_script ) {
253 __start_script = strdup(start_script);
254 if (access(__start_script, R_OK) == 0) {
256 do_file(__start_script);
258 do_string(
"require(\"%s\")", __start_script);
261 __start_script = NULL;
271 LuaContext::restart()
275 lua_State *L = init_state();
281 LibLogger::log_error(
"LuaContext",
"Could not restart Lua instance, an error "
282 "occured while initializing new state. Keeping old state.");
283 LibLogger::log_error(
"LuaContext", e);
294 LuaContext::add_package_dir(
const char *path)
298 do_string(__L,
"package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", path, path);
300 __package_dirs.push_back(path);
301 if ( __fam ) __fam->watch_dir(path);
311 LuaContext::add_cpackage_dir(
const char *path)
315 do_string(__L,
"package.cpath = package.cpath .. \";%s/?.so\"", path);
317 __cpackage_dirs.push_back(path);
318 if ( __fam ) __fam->watch_dir(path);
328 LuaContext::add_package(
const char *package)
331 if (find(__packages.begin(), __packages.end(), package) == __packages.end()) {
332 do_string(__L,
"require(\"%s\")", package);
334 __packages.push_back(package);
345 LuaContext::get_lua_state()
363 LuaContext::try_lock()
365 return __lua_mutex->try_lock();
373 __lua_mutex->unlock();
381 LuaContext::do_file(
const char *filename)
384 do_file(__L, filename);
393 LuaContext::do_file(lua_State *L,
const char *filename)
398 if ( (err = luaL_loadfile(L, filename)) != 0) {
399 errmsg = lua_tostring(L, -1);
413 int errfunc = __enable_tracebacks ? 1 : 0;
414 if ( (err = lua_pcall(L, 0, LUA_MULTRET, errfunc)) != 0 ) {
416 errmsg = lua_tostring(L, -1);
420 throw LuaRuntimeException(
"do_file", errmsg.c_str());
423 throw OutOfMemoryException(
"Could not execute Lua file %s", filename);
426 throw LuaErrorException(
"do_file", errmsg.c_str());
429 throw LuaErrorException(
"do_file/unknown error", errmsg.c_str());
442 LuaContext::do_string(lua_State *L,
const char *format, ...)
445 va_start(arg, format);
447 if (vasprintf(&s, format, arg) == -1) {
448 throw Exception(
"LuaContext::do_string: Could not form string");
452 int errfunc = __enable_tracebacks ? 1 : 0;
453 rv = (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, errfunc));
459 std::string errmsg = lua_tostring(L, -1);
461 throw LuaRuntimeException(
"do_string", errmsg.c_str());
471 LuaContext::do_string(
const char *format, ...)
475 va_start(arg, format);
477 if (vasprintf(&s, format, arg) == -1) {
478 throw Exception(
"LuaContext::do_string: Could not form string");
482 int errfunc = __enable_tracebacks ? 1 : 0;
483 rv = (luaL_loadstring(__L, s) || lua_pcall(__L, 0, LUA_MULTRET, errfunc));
489 std::string errmsg = lua_tostring(__L, -1);
501 LuaContext::load_string(
const char *s)
504 if ( (err = luaL_loadstring(__L, s)) != 0 ) {
505 std::string errmsg = lua_tostring(__L, -1);
529 LuaContext::pcall(
int nargs,
int nresults,
int errfunc)
532 if ( ! errfunc && __enable_tracebacks ) errfunc = 1;
533 if ( (err = lua_pcall(__L, nargs, nresults, errfunc)) != 0 ) {
534 std::string errmsg = lua_tostring(__L, -1);
559 LuaContext::assert_unique_name(
const char *name, std::string type)
561 if ( (type ==
"usertype") && (__usertypes.find(name) != __usertypes.end()) ) {
562 throw Exception(
"User type entry already exists for name %s", name);
564 if ( (type ==
"string") && (__strings.find(name) != __strings.end()) ) {
565 throw Exception(
"String entry already exists for name %s", name);
567 if ( (type ==
"boolean") && (__booleans.find(name) != __booleans.end()) ) {
568 throw Exception(
"Boolean entry already exists for name %s", name);
570 if ( (type ==
"number") && (__numbers.find(name) != __numbers.end()) ) {
571 throw Exception(
"Number entry already exists for name %s", name);
573 if ( (type ==
"integer") && (__integers.find(name) != __integers.end()) ) {
574 throw Exception(
"Integer entry already exists for name %s", name);
576 if ( (type ==
"cfunction") && (__cfuncs.find(name) != __cfuncs.end()) ) {
577 throw Exception(
"C function entry already exists for name %s", name);
589 LuaContext::set_usertype(
const char *name,
void *data,
590 const char *type_name,
const char *name_space)
594 std::string type_n = type_name;
596 type_n = std::string(name_space) +
"::" + type_name;
599 assert_unique_name(name,
"usertype");
601 __usertypes[name] = std::make_pair(data, type_n);
603 tolua_pushusertype(__L, data, type_n.c_str());
604 lua_setglobal(__L, name);
613 LuaContext::set_string(
const char *name,
const char *value)
616 assert_unique_name(name,
"string");
618 __strings[name] = value;
620 lua_pushstring(__L, value);
621 lua_setglobal(__L, name);
630 LuaContext::set_boolean(
const char *name,
bool value)
633 assert_unique_name(name,
"boolean");
635 __booleans[name] = value;
637 lua_pushboolean(__L, value ? 1 : 0);
638 lua_setglobal(__L, name);
647 LuaContext::set_number(
const char *name, lua_Number value)
650 assert_unique_name(name,
"number");
652 __numbers[name] = value;
654 lua_pushnumber(__L, value);
655 lua_setglobal(__L, name);
664 LuaContext::set_integer(
const char *name, lua_Integer value)
667 assert_unique_name(name,
"integer");
669 __integers[name] = value;
671 lua_pushinteger(__L, value);
672 lua_setglobal(__L, name);
681 LuaContext::set_cfunction(
const char *name, lua_CFunction f)
684 assert_unique_name(name,
"cfunction");
688 lua_pushcfunction(__L, f);
689 lua_setglobal(__L, name);
697 LuaContext::push_boolean(
bool value)
700 lua_pushboolean(__L, value ? 1 : 0);
709 LuaContext::push_fstring(
const char *format, ...)
713 va_start(arg, format);
714 lua_pushvfstring(__L, format, arg);
723 LuaContext::push_integer(lua_Integer value)
726 lua_pushinteger(__L, value);
734 LuaContext::push_light_user_data(
void *p)
737 lua_pushlightuserdata(__L, p);
746 LuaContext::push_lstring(
const char *s,
size_t len)
749 lua_pushlstring(__L, s, len);
756 LuaContext::push_nil()
767 LuaContext::push_number(lua_Number value)
770 lua_pushnumber(__L, value);
778 LuaContext::push_string(
const char *value)
781 lua_pushstring(__L, value);
788 LuaContext::push_thread()
799 LuaContext::push_value(
int idx)
802 lua_pushvalue(__L, idx);
812 LuaContext::push_vfstring(
const char *format, va_list arg)
815 lua_pushvfstring(__L, format, arg);
825 LuaContext::push_usertype(
void *data,
const char *type_name,
826 const char *name_space)
830 std::string type_n = type_name;
832 type_n = std::string(name_space) +
"::" + type_name;
835 tolua_pushusertype(__L, data, type_n.c_str());
843 LuaContext::push_cfunction(lua_CFunction f)
846 lua_pushcfunction(__L, f);
854 LuaContext::pop(
int n)
857 if (__enable_tracebacks && (n >= stack_size())) {
867 LuaContext::remove(
int idx)
870 if (__enable_tracebacks && ((idx == 1) || (idx == -stack_size()))) {
873 lua_remove(__L, idx);
881 LuaContext::stack_size()
883 return lua_gettop(__L);
892 LuaContext::create_table(
int narr,
int nrec)
894 lua_createtable(__L, narr, nrec);
905 LuaContext::set_table(
int t_index)
907 lua_settable(__L, t_index);
920 LuaContext::set_field(
const char *key,
int t_index)
922 lua_setfield(__L, t_index, key);
932 LuaContext::set_global(
const char *name)
934 lua_setglobal(__L, name);
946 LuaContext::get_table(
int idx)
948 lua_gettable(__L, idx);
959 LuaContext::get_field(
int idx,
const char *k)
961 lua_getfield(__L, idx, k);
970 LuaContext::raw_set(
int idx)
972 lua_rawset(__L, idx);
983 LuaContext::raw_seti(
int idx,
int n)
985 lua_rawseti(__L, idx, n);
994 LuaContext::raw_get(
int idx)
996 lua_rawget(__L, idx);
1006 LuaContext::raw_geti(
int idx,
int n)
1008 lua_rawgeti(__L, idx, n);
1016 LuaContext::get_global(
const char *name)
1018 lua_getglobal(__L, name);
1028 LuaContext::remove_global(
const char *name)
1032 __usertypes.erase(name);
1033 __strings.erase(name);
1034 __booleans.erase(name);
1035 __numbers.erase(name);
1036 __integers.erase(name);
1037 __cfuncs.erase(name);
1040 lua_setglobal(__L, name);
1049 LuaContext::to_number(
int idx)
1051 return lua_tonumber(__L, idx);
1060 LuaContext::to_integer(
int idx)
1062 return lua_tointeger(__L, idx);
1071 LuaContext::to_boolean(
int idx)
1073 return lua_toboolean(__L, idx);
1082 LuaContext::to_string(
int idx)
1084 return lua_tostring(__L, idx);
1093 LuaContext::is_boolean(
int idx)
1095 return lua_isboolean(__L, idx);
1104 LuaContext::is_cfunction(
int idx)
1106 return lua_iscfunction(__L, idx);
1115 LuaContext::is_function(
int idx)
1117 return lua_isfunction(__L, idx);
1126 LuaContext::is_light_user_data(
int idx)
1128 return lua_islightuserdata(__L, idx);
1137 LuaContext::is_nil(
int idx)
1139 return lua_isnil(__L, idx);
1148 LuaContext::is_number(
int idx)
1150 return lua_isnumber(__L, idx);
1159 LuaContext::is_string(
int idx)
1161 return lua_isstring(__L, idx);
1170 LuaContext::is_table(
int idx)
1172 return lua_istable(__L, idx);
1181 LuaContext::is_thread(
int idx)
1183 return lua_isthread(__L, idx);
1192 LuaContext::objlen(
int idx)
1194 return lua_objlen(__L, idx);
1204 LuaContext::setfenv(
int idx)
1206 lua_setfenv(__L, idx);
1216 __watchers.push_back_locked(watcher);
1226 __watchers.remove_locked(watcher);
1233 LuaContext::process_fam_events()
1235 if ( __fam) __fam->process_events();
1240 LuaContext::fam_event(
const char *filename,
unsigned int mask)
File could not be opened.
Fawkes library namespace.
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.