23 #include <core/exceptions/software.h>
24 #include <core/exceptions/system.h>
25 #include <core/threading/mutex.h>
26 #include <core/threading/mutex_locker.h>
27 #include <logging/liblogger.h>
28 #include <lua/context.h>
29 #include <lua/context_watcher.h>
66 enable_tracebacks_ = enable_tracebacks;
70 lua_mutex_ =
new Mutex();
88 lua_mutex_ =
new Mutex();
99 if (!finalize_call_.empty())
100 do_string(L_,
"%s", finalize_call_.c_str());
128 fam_->add_filter(
"^[^.].*\\.lua$");
130 fam_->add_listener(
this);
134 fam_thread_->
start();
153 LuaContext::init_state()
155 lua_State *L = luaL_newstate();
158 if (enable_tracebacks_) {
159 lua_getglobal(L,
"debug");
160 lua_getfield(L, -1,
"traceback");
165 for (slit_ = package_dirs_.begin(); slit_ != package_dirs_.end(); ++slit_) {
167 "package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"",
172 for (slit_ = cpackage_dirs_.begin(); slit_ != cpackage_dirs_.end(); ++slit_) {
173 do_string(L,
"package.cpath = package.cpath .. \";%s/?.so\"", slit_->c_str());
177 for (slit_ = packages_.begin(); slit_ != packages_.end(); ++slit_) {
178 do_string(L,
"require(\"%s\")", slit_->c_str());
181 for (utit_ = usertypes_.begin(); utit_ != usertypes_.end(); ++utit_) {
182 tolua_pushusertype(L, utit_->second.first, utit_->second.second.c_str());
183 lua_setglobal(L, utit_->first.c_str());
186 for (strings_it_ = strings_.begin(); strings_it_ != strings_.end(); ++strings_it_) {
187 lua_pushstring(L, strings_it_->second.c_str());
188 lua_setglobal(L, strings_it_->first.c_str());
191 for (booleans_it_ = booleans_.begin(); booleans_it_ != booleans_.end(); ++booleans_it_) {
192 lua_pushboolean(L, booleans_it_->second);
193 lua_setglobal(L, booleans_it_->first.c_str());
196 for (numbers_it_ = numbers_.begin(); numbers_it_ != numbers_.end(); ++numbers_it_) {
197 lua_pushnumber(L, numbers_it_->second);
198 lua_setglobal(L, numbers_it_->first.c_str());
201 for (integers_it_ = integers_.begin(); integers_it_ != integers_.end(); ++integers_it_) {
202 lua_pushinteger(L, integers_it_->second);
203 lua_setglobal(L, integers_it_->first.c_str());
206 for (cfuncs_it_ = cfuncs_.begin(); cfuncs_it_ != cfuncs_.end(); ++cfuncs_it_) {
207 lua_pushcfunction(L, cfuncs_it_->second);
208 lua_setglobal(L, cfuncs_it_->first.c_str());
213 MutexLocker(watchers_.mutex());
214 LockList<LuaContextWatcher *>::iterator i;
215 for (i = watchers_.begin(); i != watchers_.end(); ++i) {
217 (*i)->lua_restarted(tmpctx);
220 if (!finalize_call_.empty())
221 do_string(L,
"%s", finalize_call_.c_str());
222 }
catch (Exception &e) {
234 if (access(start_script_, R_OK) == 0) {
238 do_string(L,
"require(\"%s\")", start_script_);
242 if (!finalize_call_.empty())
243 do_string(L,
"%s", finalize_call_.c_str());
268 start_script_ = strdup(start_script);
269 if (access(start_script_, R_OK) == 0) {
273 do_string(
"require(\"%s\")", start_script_);
276 start_script_ = NULL;
289 if (!finalize_prepare_call_.empty())
290 do_string(L_,
"%s", finalize_prepare_call_.c_str());
293 lua_State *L = init_state();
298 if (!finalize_call_.empty())
299 do_string(L_,
"%s", finalize_call_.c_str());
302 "Finalization call on old context failed, "
303 "exception follows, ignoring.");
314 "Could not restart Lua instance, an error "
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());
336 "package.path = \"%s/?.lua;%s/?/init.lua;\""
341 package_dirs_.push_front(path);
344 "package.path = package.path .. "
345 "\";%s/?.lua;%s/?/init.lua\"",
349 package_dirs_.push_back(path);
352 fam_->watch_dir(path);
368 do_string(L_,
"package.cpath = \"%s/?.so;\" .. package.cpath", path);
370 cpackage_dirs_.push_front(path);
372 do_string(L_,
"package.cpath = package.cpath .. \";%s/?.so\"", path);
374 cpackage_dirs_.push_back(path);
377 fam_->watch_dir(path);
389 if (find(packages_.begin(), packages_.end(), package) == packages_.end()) {
390 do_string(L_,
"require(\"%s\")", package);
392 packages_.push_back(package);
450 if ((err = luaL_loadfile(L, filename)) != 0) {
451 errmsg = lua_tostring(L, -1);
463 int errfunc = enable_tracebacks_ ? 1 : 0;
464 if ((err = lua_pcall(L, 0, LUA_MULTRET, errfunc)) != 0) {
466 errmsg = lua_tostring(L, -1);
469 case LUA_ERRRUN:
throw LuaRuntimeException(
"do_file", errmsg.c_str());
471 case LUA_ERRMEM:
throw OutOfMemoryException(
"Could not execute Lua file %s", filename);
473 case LUA_ERRERR:
throw LuaErrorException(
"do_file", errmsg.c_str());
475 default:
throw LuaErrorException(
"do_file/unknown error", errmsg.c_str());
489 va_start(arg, format);
491 if (vasprintf(&s, format, arg) == -1) {
492 throw Exception(
"LuaContext::do_string: Could not form string");
500 if ((err = luaL_loadstring(L, ss.c_str())) != 0) {
501 errmsg = lua_tostring(L, -1);
505 throw SyntaxErrorException(
"Lua syntax error in string %s: %s", ss.c_str(), errmsg.c_str());
507 case LUA_ERRMEM:
throw OutOfMemoryException(
"Could not load Lua string %s", ss.c_str());
511 int errfunc = enable_tracebacks_ ? 1 : 0;
512 err = lua_pcall(L, 0, LUA_MULTRET, errfunc);
515 std::string errmsg = lua_tostring(L, -1);
518 case LUA_ERRRUN:
throw LuaRuntimeException(
"do_string", errmsg.c_str());
520 case LUA_ERRMEM:
throw OutOfMemoryException(
"Could not execute Lua chunk via pcall");
522 case LUA_ERRERR:
throw LuaErrorException(
"do_string", errmsg.c_str());
537 va_start(arg, format);
539 if (vasprintf(&s, format, arg) == -1) {
540 throw Exception(
"LuaContext::do_string: Could not form string");
548 if ((err = luaL_loadstring(L_, ss.c_str())) != 0) {
549 errmsg = lua_tostring(L_, -1);
559 int errfunc = enable_tracebacks_ ? 1 : 0;
560 err = lua_pcall(L_, 0, LUA_MULTRET, errfunc);
563 std::string errmsg = lua_tostring(L_, -1);
583 if ((err = luaL_loadstring(L_, s)) != 0) {
584 std::string errmsg = lua_tostring(L_, -1);
608 if (!errfunc && enable_tracebacks_)
610 if ((err = lua_pcall(L_, nargs, nresults, errfunc)) != 0) {
611 std::string errmsg = lua_tostring(L_, -1);
632 LuaContext::assert_unique_name(
const char *name, std::string type)
634 if ((type ==
"usertype") && (usertypes_.find(name) != usertypes_.end())) {
635 throw Exception(
"User type entry already exists for name %s", name);
637 if ((type ==
"string") && (strings_.find(name) != strings_.end())) {
638 throw Exception(
"String entry already exists for name %s", name);
640 if ((type ==
"boolean") && (booleans_.find(name) != booleans_.end())) {
641 throw Exception(
"Boolean entry already exists for name %s", name);
643 if ((type ==
"number") && (numbers_.find(name) != numbers_.end())) {
644 throw Exception(
"Number entry already exists for name %s", name);
646 if ((type ==
"integer") && (integers_.find(name) != integers_.end())) {
647 throw Exception(
"Integer entry already exists for name %s", name);
649 if ((type ==
"cfunction") && (cfuncs_.find(name) != cfuncs_.end())) {
650 throw Exception(
"C function entry already exists for name %s", name);
663 const char *type_name,
664 const char *name_space)
670 type_n = std::string(name_space) +
"::" +
type_name;
673 assert_unique_name(name,
"usertype");
675 usertypes_[name] = std::make_pair(data, type_n);
677 tolua_pushusertype(L_, data, type_n.c_str());
678 lua_setglobal(L_, name);
689 assert_unique_name(name,
"string");
691 strings_[name] = value;
693 lua_pushstring(L_, value);
694 lua_setglobal(L_, name);
705 assert_unique_name(name,
"boolean");
707 booleans_[name] = value;
709 lua_pushboolean(L_, value ? 1 : 0);
710 lua_setglobal(L_, name);
721 assert_unique_name(name,
"number");
723 numbers_[name] = value;
725 lua_pushnumber(L_, value);
726 lua_setglobal(L_, name);
737 assert_unique_name(name,
"integer");
739 integers_[name] = value;
741 lua_pushinteger(L_, value);
742 lua_setglobal(L_, name);
753 assert_unique_name(name,
"cfunction");
757 lua_pushcfunction(L_, f);
758 lua_setglobal(L_, name);
768 lua_pushboolean(L_, value ? 1 : 0);
780 va_start(arg, format);
781 lua_pushvfstring(L_, format, arg);
792 lua_pushinteger(L_, value);
802 lua_pushlightuserdata(L_, p);
813 lua_pushlstring(L_, s, len);
832 lua_pushnumber(L_, value);
842 lua_pushstring(L_, value);
861 lua_pushvalue(L_, idx);
873 lua_pushvfstring(L_, format, arg);
888 type_n = std::string(name_space) +
"::" +
type_name;
891 tolua_pushusertype(L_, data, type_n.c_str());
901 lua_pushcfunction(L_, f);
911 return lua_typename(L_, lua_type(L_, idx));
921 if (enable_tracebacks_ && (n >=
stack_size())) {
934 if (enable_tracebacks_ && ((idx == 1) || (idx == -
stack_size()))) {
946 return lua_gettop(L_);
956 lua_createtable(L_, narr, nrec);
968 lua_settable(L_, t_index);
982 lua_setfield(L_, t_index, key);
993 lua_setglobal(L_, name);
1006 lua_gettable(L_, idx);
1018 lua_getfield(L_, idx, k);
1028 lua_rawset(L_, idx);
1040 lua_rawseti(L_, idx, n);
1050 lua_rawget(L_, idx);
1061 lua_rawgeti(L_, idx, n);
1070 lua_getglobal(L_, name);
1083 usertypes_.erase(name);
1084 strings_.erase(name);
1085 booleans_.erase(name);
1086 numbers_.erase(name);
1087 integers_.erase(name);
1088 cfuncs_.erase(name);
1091 lua_setglobal(L_, name);
1102 return lua_next(L_, idx) != 0;
1112 return lua_tonumber(L_, idx);
1122 return lua_tointeger(L_, idx);
1132 return lua_toboolean(L_, idx);
1142 return lua_tostring(L_, idx);
1152 return lua_touserdata(L_, idx);
1162 return (
void *)lua_topointer(L_, idx);
1172 return tolua_tousertype(L_, idx, 0);
1182 return lua_isboolean(L_, idx);
1192 return lua_iscfunction(L_, idx);
1202 return lua_isfunction(L_, idx);
1212 return lua_islightuserdata(L_, idx);
1222 return lua_isnil(L_, idx);
1232 return lua_isnumber(L_, idx);
1242 return lua_isstring(L_, idx);
1252 return lua_istable(L_, idx);
1262 return lua_isthread(L_, idx);
1272 return lua_objlen(L_, idx);
1283 #if LUA_VERSION_NUM > 501
1287 const char *val_name;
1288 while ((val_name = lua_getupvalue(L_, idx, ++n)) != NULL) {
1289 if (strcmp(val_name,
"_ENV") == 0) {
1299 if (val_name != NULL) {
1301 luaL_loadstring(L_,
"");
1302 lua_pushvalue(L_, -3);
1303 lua_setupvalue(L_, -2, 1);
1304 int act_idx = idx > 0 ? idx : idx - 2;
1305 lua_upvaluejoin(L_, act_idx, n, -1, 1);
1308 throw Exception(
"No environment found");
1311 lua_setfenv(L_, idx);
1321 watchers_.push_back_locked(watcher);
1330 watchers_.remove_locked(watcher);
1345 std::string finalize_prepare,
1346 std::string finalize_cancel)
1348 finalize_call_ = finalize;
1349 finalize_prepare_call_ = finalize_prepare;
1350 finalize_cancel_call_ = finalize_cancel;
1358 fam_->process_events();