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 if (! __finalize_call.empty())
103 do_string(__L,
"%s", __finalize_call.c_str());
106 __fam_thread->cancel();
107 __fam_thread->join();
111 if ( __start_script ) free(__start_script);
128 LuaContext::setup_fam(
bool auto_restart,
bool conc_thread)
131 __fam->add_filter(
"^[^.].*\\.lua$");
133 __fam->add_listener(
this);
137 __fam_thread->start();
147 LuaContext::get_fam()
const 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());
214 LuaContext *tmpctx =
new LuaContext(L);
216 MutexLocker(__watchers.mutex());
217 LockList<LuaContextWatcher *>::iterator i;
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());
225 }
catch (Exception &e) {}
235 if ( __start_script ) {
236 if (access(__start_script, R_OK) == 0) {
238 do_file(L, __start_script);
240 do_string(L,
"require(\"%s\")", __start_script);
244 if (! __finalize_call.empty())
245 do_string(L,
"%s", __finalize_call.c_str());
266 LuaContext::set_start_script(
const char *start_script)
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) {
273 do_file(__start_script);
275 do_string(
"require(\"%s\")", __start_script);
278 __start_script = NULL;
288 LuaContext::restart()
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());
304 LibLogger::log_warn(
"LuaContext",
"Finalization call on old context failed, " 305 "exception follows, ignoring.");
306 LibLogger::log_warn(
"LuaContext", e);
310 if (__owns_L) lua_close(tL);
314 LibLogger::log_error(
"LuaContext",
"Could not restart Lua instance, an error " 315 "occured while initializing new state. Keeping old state.");
316 LibLogger::log_error(
"LuaContext", e);
317 if (! __finalize_cancel_call.empty())
318 do_string(__L,
"%s", __finalize_cancel_call.c_str());
331 LuaContext::add_package_dir(
const char *path,
bool prefix)
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);
360 LuaContext::add_cpackage_dir(
const char *path,
bool prefix)
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);
383 LuaContext::add_package(
const char *package)
386 if (find(__packages.begin(), __packages.end(), package) == __packages.end()) {
387 do_string(__L,
"require(\"%s\")", package);
389 __packages.push_back(package);
400 LuaContext::get_lua_state()
418 LuaContext::try_lock()
420 return __lua_mutex->try_lock();
428 __lua_mutex->unlock();
436 LuaContext::do_file(
const char *filename)
439 do_file(__L, filename);
448 LuaContext::do_file(lua_State *L,
const char *filename)
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);
475 throw LuaRuntimeException(
"do_file", errmsg.c_str());
478 throw OutOfMemoryException(
"Could not execute Lua file %s", filename);
481 throw LuaErrorException(
"do_file", errmsg.c_str());
484 throw LuaErrorException(
"do_file/unknown error", errmsg.c_str());
497 LuaContext::do_string(lua_State *L,
const char *format, ...)
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);
516 throw SyntaxErrorException(
"Lua syntax error in string %s: %s", ss.c_str(), errmsg.c_str());
519 throw OutOfMemoryException(
"Could not load Lua string %s", ss.c_str());
523 int errfunc = __enable_tracebacks ? 1 : 0;
524 err = lua_pcall(L, 0, LUA_MULTRET, errfunc);
527 std::string errmsg = lua_tostring(L, -1);
531 throw LuaRuntimeException(
"do_string", errmsg.c_str());
534 throw OutOfMemoryException(
"Could not execute Lua chunk via pcall");
537 throw LuaErrorException(
"do_string", errmsg.c_str());
548 LuaContext::do_string(
const char *format, ...)
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);
601 LuaContext::load_string(
const char *s)
604 if ( (err = luaL_loadstring(__L, s)) != 0 ) {
605 std::string errmsg = lua_tostring(__L, -1);
629 LuaContext::pcall(
int nargs,
int nresults,
int errfunc)
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);
689 LuaContext::set_usertype(
const char *name,
void *data,
690 const char *type_name,
const char *name_space)
694 std::string type_n = type_name;
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);
713 LuaContext::set_string(
const char *name,
const char *value)
716 assert_unique_name(name,
"string");
718 __strings[name] = value;
720 lua_pushstring(__L, value);
721 lua_setglobal(__L, name);
730 LuaContext::set_boolean(
const char *name,
bool value)
733 assert_unique_name(name,
"boolean");
735 __booleans[name] = value;
737 lua_pushboolean(__L, value ? 1 : 0);
738 lua_setglobal(__L, name);
747 LuaContext::set_number(
const char *name, lua_Number value)
750 assert_unique_name(name,
"number");
752 __numbers[name] = value;
754 lua_pushnumber(__L, value);
755 lua_setglobal(__L, name);
764 LuaContext::set_integer(
const char *name, lua_Integer value)
767 assert_unique_name(name,
"integer");
769 __integers[name] = value;
771 lua_pushinteger(__L, value);
772 lua_setglobal(__L, name);
781 LuaContext::set_cfunction(
const char *name, lua_CFunction f)
784 assert_unique_name(name,
"cfunction");
788 lua_pushcfunction(__L, f);
789 lua_setglobal(__L, name);
797 LuaContext::push_boolean(
bool value)
800 lua_pushboolean(__L, value ? 1 : 0);
809 LuaContext::push_fstring(
const char *format, ...)
813 va_start(arg, format);
814 lua_pushvfstring(__L, format, arg);
823 LuaContext::push_integer(lua_Integer value)
826 lua_pushinteger(__L, value);
834 LuaContext::push_light_user_data(
void *p)
837 lua_pushlightuserdata(__L, p);
846 LuaContext::push_lstring(
const char *s,
size_t len)
849 lua_pushlstring(__L, s, len);
856 LuaContext::push_nil()
867 LuaContext::push_number(lua_Number value)
870 lua_pushnumber(__L, value);
878 LuaContext::push_string(
const char *value)
881 lua_pushstring(__L, value);
888 LuaContext::push_thread()
899 LuaContext::push_value(
int idx)
902 lua_pushvalue(__L, idx);
912 LuaContext::push_vfstring(
const char *format, va_list arg)
915 lua_pushvfstring(__L, format, arg);
925 LuaContext::push_usertype(
void *data,
const char *type_name,
926 const char *name_space)
930 std::string type_n = type_name;
932 type_n = std::string(name_space) +
"::" + type_name;
935 tolua_pushusertype(__L, data, type_n.c_str());
943 LuaContext::push_cfunction(lua_CFunction f)
946 lua_pushcfunction(__L, f);
955 LuaContext::type_name(
int idx)
957 return lua_typename(__L, lua_type(__L, idx));
964 LuaContext::pop(
int n)
967 if (__enable_tracebacks && (n >= stack_size())) {
977 LuaContext::remove(
int idx)
980 if (__enable_tracebacks && ((idx == 1) || (idx == -stack_size()))) {
983 lua_remove(__L, idx);
991 LuaContext::stack_size()
993 return lua_gettop(__L);
1002 LuaContext::create_table(
int narr,
int nrec)
1004 lua_createtable(__L, narr, nrec);
1015 LuaContext::set_table(
int t_index)
1017 lua_settable(__L, t_index);
1030 LuaContext::set_field(
const char *key,
int t_index)
1032 lua_setfield(__L, t_index, key);
1042 LuaContext::set_global(
const char *name)
1044 lua_setglobal(__L, name);
1056 LuaContext::get_table(
int idx)
1058 lua_gettable(__L, idx);
1069 LuaContext::get_field(
int idx,
const char *k)
1071 lua_getfield(__L, idx, k);
1080 LuaContext::raw_set(
int idx)
1082 lua_rawset(__L, idx);
1093 LuaContext::raw_seti(
int idx,
int n)
1095 lua_rawseti(__L, idx, n);
1104 LuaContext::raw_get(
int idx)
1106 lua_rawget(__L, idx);
1116 LuaContext::raw_geti(
int idx,
int n)
1118 lua_rawgeti(__L, idx, n);
1126 LuaContext::get_global(
const char *name)
1128 lua_getglobal(__L, name);
1138 LuaContext::remove_global(
const char *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);
1160 LuaContext::table_next(
int idx)
1162 return lua_next(__L, idx) != 0;
1171 LuaContext::to_number(
int idx)
1173 return lua_tonumber(__L, idx);
1182 LuaContext::to_integer(
int idx)
1184 return lua_tointeger(__L, idx);
1193 LuaContext::to_boolean(
int idx)
1195 return lua_toboolean(__L, idx);
1204 LuaContext::to_string(
int idx)
1206 return lua_tostring(__L, idx);
1214 LuaContext::to_userdata(
int idx)
1216 return lua_touserdata(__L, idx);
1225 LuaContext::to_pointer(
int idx)
1227 return (
void *)lua_topointer(__L, idx);
1236 LuaContext::to_usertype(
int idx)
1238 return tolua_tousertype(__L, idx, 0);
1247 LuaContext::is_boolean(
int idx)
1249 return lua_isboolean(__L, idx);
1258 LuaContext::is_cfunction(
int idx)
1260 return lua_iscfunction(__L, idx);
1269 LuaContext::is_function(
int idx)
1271 return lua_isfunction(__L, idx);
1280 LuaContext::is_light_user_data(
int idx)
1282 return lua_islightuserdata(__L, idx);
1291 LuaContext::is_nil(
int idx)
1293 return lua_isnil(__L, idx);
1302 LuaContext::is_number(
int idx)
1304 return lua_isnumber(__L, idx);
1313 LuaContext::is_string(
int idx)
1315 return lua_isstring(__L, idx);
1324 LuaContext::is_table(
int idx)
1326 return lua_istable(__L, idx);
1335 LuaContext::is_thread(
int idx)
1337 return lua_isthread(__L, idx);
1346 LuaContext::objlen(
int idx)
1348 return lua_objlen(__L, idx);
1358 LuaContext::setfenv(
int 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);
1423 LuaContext::set_finalization_calls(std::string finalize, std::string finalize_prepare,
1424 std::string finalize_cancel)
1426 __finalize_call = finalize;
1427 __finalize_prepare_call = finalize_prepare;
1428 __finalize_cancel_call = finalize_cancel;
1436 LuaContext::process_fam_events()
1438 if ( __fam) __fam->process_events();
1443 LuaContext::fam_event(
const char *filename,
unsigned int mask)
File could not be opened.
Fawkes library namespace.
void unlock()
Unlock the mutex.
Base class for exceptions in Fawkes.
void relock()
Lock this mutex, again.
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.