Fawkes API Fawkes Development Version
context.cpp
1
2/***************************************************************************
3 * context.cpp - Fawkes Lua Context
4 *
5 * Created: Fri May 23 15:53:54 2008
6 * Copyright 2006-2009 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library General Public License for more details.
19 *
20 * Read the full text in the LICENSE.GPL file in the doc directory.
21 */
22
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>
30
31#include <algorithm>
32#include <cstdlib>
33#include <cstring>
34#include <tolua++.h>
35#include <unistd.h>
36
37namespace fawkes {
38
39/** @class LuaContext <lua/context.h>
40 * Lua C++ wrapper.
41 * This thin wrapper allows for easy integration of Fawkes into other
42 * applications. It provides convenience methods to some Lua and
43 * tolua++ features like setting global variables or pushing/popping
44 * values.
45 *
46 * It allows raw access to the Lua state since this class does not and
47 * should not provide all the features Lua provides. If you use this
48 * make sure that you lock the Lua context to avoid multi-threading
49 * problems (if that is a possible concern in your application).
50 *
51 * LuaContext can use a FileAlterationMonitor on all added package and
52 * C package directories. If anything changes in these directories the
53 * Lua instance is then automatically restarted (closed, re-opened and
54 * re-initialized).
55 *
56 * @author Tim Niemueller
57 */
58
59/** Constructor.
60 * @param enable_tracebacks if true an error function is installed at the top
61 * of the stackand used for pcalls where errfunc is 0.
62 */
63LuaContext::LuaContext(bool enable_tracebacks)
64{
65 owns_L_ = true;
66 enable_tracebacks_ = enable_tracebacks;
67 fam_ = NULL;
68 fam_thread_ = NULL;
69
70 lua_mutex_ = new Mutex();
71
72 start_script_ = NULL;
73 L_ = init_state();
74}
75
76/** Wrapper contstructor.
77 * This wraps around an existing Lua state. It does not initialize the state in
78 * the sense that it would add variables etc. It only provides convenient access
79 * to the state methods via a C++ interface. It's mainly intended to be used to
80 * create a LuaContext to be passed to LuaContextWatcher::lua_restarted(). The
81 * state is not closed on destruction as is done when using the other ctor.
82 * @param L Lua state to wrap
83 */
85{
86 owns_L_ = false;
87 L_ = L;
88 lua_mutex_ = new Mutex();
89 start_script_ = NULL;
90 fam_ = NULL;
91 fam_thread_ = NULL;
92}
93
94/** Destructor. */
96{
97 lua_mutex_->lock();
98
99 if (!finalize_call_.empty())
100 do_string(L_, "%s", finalize_call_.c_str());
101
102 if (fam_thread_) {
103 fam_thread_->cancel();
104 fam_thread_->join();
105 delete fam_thread_;
106 }
107 delete lua_mutex_;
108 if (start_script_)
109 free(start_script_);
110 if (owns_L_) {
111 lua_close(L_);
112 }
113}
114
115/** Setup file alteration monitor.
116 * Setup an internal file alteration monitor that can react to changes
117 * on Lua files and packages.
118 * @param auto_restart automatically restart the Lua context in case
119 * of an event
120 * @param conc_thread true to run a concurrent thread for event
121 * processing. If and only if you set this to false, ensure that
122 * process_fam_events() periodically.
123 */
124void
125LuaContext::setup_fam(bool auto_restart, bool conc_thread)
126{
127 fam_ = new FileAlterationMonitor();
128 fam_->add_filter("^[^.].*\\.lua$");
129 if (auto_restart) {
130 fam_->add_listener(this);
131 }
132 if (conc_thread) {
133 fam_thread_ = new FamThread(fam_);
134 fam_thread_->start();
135 }
136}
137
138/** Get file alteration monitor.
139 * @return reference counted pointer to file alteration monitor. Note
140 * that the pointer might be invalid if setup_fam() has not been called.
141 */
144{
145 return fam_;
146}
147
148/** Initialize Lua state.
149 * Initializes the state and makes all necessary initializations.
150 * @return fresh initialized Lua state
151 */
152lua_State *
153LuaContext::init_state()
154{
155 lua_State *L = luaL_newstate();
156 luaL_openlibs(L);
157
158 if (enable_tracebacks_) {
159 lua_getglobal(L, "debug");
160 lua_getfield(L, -1, "traceback");
161 lua_remove(L, -2);
162 }
163
164 // Add package paths
165 for (slit_ = package_dirs_.begin(); slit_ != package_dirs_.end(); ++slit_) {
166 do_string(L,
167 "package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"",
168 slit_->c_str(),
169 slit_->c_str());
170 }
171
172 for (slit_ = cpackage_dirs_.begin(); slit_ != cpackage_dirs_.end(); ++slit_) {
173 do_string(L, "package.cpath = package.cpath .. \";%s/?.so\"", slit_->c_str());
174 }
175
176 // load base packages
177 for (slit_ = packages_.begin(); slit_ != packages_.end(); ++slit_) {
178 do_string(L, "require(\"%s\")", slit_->c_str());
179 }
180
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());
184 }
185
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());
189 }
190
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());
194 }
195
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());
199 }
200
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());
204 }
205
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());
209 }
210
211 LuaContext *tmpctx = new LuaContext(L);
212
213 MutexLocker(watchers_.mutex());
214 LockList<LuaContextWatcher *>::iterator i;
215 for (i = watchers_.begin(); i != watchers_.end(); ++i) {
216 try {
217 (*i)->lua_restarted(tmpctx);
218 } catch (...) {
219 try {
220 if (!finalize_call_.empty())
221 do_string(L, "%s", finalize_call_.c_str());
222 } catch (Exception &e) {
223 } // ignored
224
225 delete tmpctx;
226 lua_close(L);
227 throw;
228 }
229 }
230 delete tmpctx;
231
232 try {
233 if (start_script_) {
234 if (access(start_script_, R_OK) == 0) {
235 // it's a file and we can access it, execute it!
236 do_file(L, start_script_);
237 } else {
238 do_string(L, "require(\"%s\")", start_script_);
239 }
240 }
241 } catch (...) {
242 if (!finalize_call_.empty())
243 do_string(L, "%s", finalize_call_.c_str());
244 lua_close(L);
245 throw;
246 }
247
248 return L;
249}
250
251/** Set start script.
252 * The script will be executed once immediately in this method, make
253 * sure you call this after all other init-relevant routines like
254 * add_* if you need to access these in the start script!
255 * @param start_script script to execute now and on restart(). If the
256 * string is the path and name of an accessible file it is loaded via
257 * do_file(), otherwise it is considered to be the name of a module and
258 * loaded via Lua's require(). Note however, that if you use a module,
259 * special care has to be taken to correctly modify the global
260 * environment!
261 */
262void
263LuaContext::set_start_script(const char *start_script)
264{
265 if (start_script_)
266 free(start_script_);
267 if (start_script) {
268 start_script_ = strdup(start_script);
269 if (access(start_script_, R_OK) == 0) {
270 // it's a file and we can access it, execute it!
271 do_file(start_script_);
272 } else {
273 do_string("require(\"%s\")", start_script_);
274 }
275 } else {
276 start_script_ = NULL;
277 }
278}
279
280/** Restart Lua.
281 * Creates a new Lua state, initializes it, anf if this went well the
282 * current state is swapped with the new state.
283 */
284void
286{
287 MutexLocker lock(lua_mutex_);
288 try {
289 if (!finalize_prepare_call_.empty())
290 do_string(L_, "%s", finalize_prepare_call_.c_str());
291
292 lock.unlock();
293 lua_State *L = init_state();
294 lock.relock();
295 lua_State *tL = L_;
296
297 try {
298 if (!finalize_call_.empty())
299 do_string(L_, "%s", finalize_call_.c_str());
300 } catch (Exception &e) {
301 LibLogger::log_warn("LuaContext",
302 "Finalization call on old context failed, "
303 "exception follows, ignoring.");
304 LibLogger::log_warn("LuaContext", e);
305 }
306
307 L_ = L;
308 if (owns_L_)
309 lua_close(tL);
310 owns_L_ = true;
311
312 } catch (Exception &e) {
313 LibLogger::log_error("LuaContext",
314 "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());
319 }
320}
321
322/** Add a Lua package directory.
323 * The directory is added to the search path for lua packages. Files with
324 * a .lua suffix will be considered as Lua modules.
325 * @param path path to add
326 * @param prefix if true, insert path at the beginning of the search path,
327 * append to end otherwise
328 */
329void
330LuaContext::add_package_dir(const char *path, bool prefix)
331{
332 MutexLocker lock(lua_mutex_);
333
334 if (prefix) {
335 do_string(L_,
336 "package.path = \"%s/?.lua;%s/?/init.lua;\""
337 ".. package.path",
338 path,
339 path);
340
341 package_dirs_.push_front(path);
342 } else {
343 do_string(L_,
344 "package.path = package.path .. "
345 "\";%s/?.lua;%s/?/init.lua\"",
346 path,
347 path);
348
349 package_dirs_.push_back(path);
350 }
351 if (fam_)
352 fam_->watch_dir(path);
353}
354
355/** Add a Lua C package directory.
356 * The directory is added to the search path for lua C packages. Files
357 * with a .so suffix will be considered as Lua modules.
358 * @param path path to add
359 * @param prefix if true, insert path at the beginning of the search path,
360 * append to end otherwise
361 */
362void
363LuaContext::add_cpackage_dir(const char *path, bool prefix)
364{
365 MutexLocker lock(lua_mutex_);
366
367 if (prefix) {
368 do_string(L_, "package.cpath = \"%s/?.so;\" .. package.cpath", path);
369
370 cpackage_dirs_.push_front(path);
371 } else {
372 do_string(L_, "package.cpath = package.cpath .. \";%s/?.so\"", path);
373
374 cpackage_dirs_.push_back(path);
375 }
376 if (fam_)
377 fam_->watch_dir(path);
378}
379
380/** Add a default package.
381 * Packages that are added this way are automatically loaded now and
382 * on restart().
383 * @param package package to add
384 */
385void
386LuaContext::add_package(const char *package)
387{
388 MutexLocker lock(lua_mutex_);
389 if (find(packages_.begin(), packages_.end(), package) == packages_.end()) {
390 do_string(L_, "require(\"%s\")", package);
391
392 packages_.push_back(package);
393 }
394}
395
396/** Get Lua state.
397 * Allows for raw modification of the used Lua state. Remember proper
398 * locking!
399 * @return Currently used Lua state
400 */
401lua_State *
403{
404 return L_;
405}
406
407/** Lock Lua state. */
408void
410{
411 lua_mutex_->lock();
412}
413
414/** Try to lock the Lua state.
415 * @return true if the state has been locked, false otherwise.
416 */
417bool
419{
420 return lua_mutex_->try_lock();
421}
422
423/** Unlock Lua state. */
424void
426{
427 lua_mutex_->unlock();
428}
429
430/** Execute file.
431 * @param filename filet to load and excute.
432 */
433void
434LuaContext::do_file(const char *filename)
435{
436 MutexLocker lock(lua_mutex_);
437 do_file(L_, filename);
438}
439
440/** Execute file on a specific Lua state.
441 * @param L Lua state to execute the file in.
442 * @param filename filet to load and excute.
443 */
444void
445LuaContext::do_file(lua_State *L, const char *filename)
446{
447 // Load initialization code
448 int err = 0;
449 std::string errmsg;
450 if ((err = luaL_loadfile(L, filename)) != 0) {
451 errmsg = lua_tostring(L, -1);
452 lua_pop(L, 1);
453 switch (err) {
454 case LUA_ERRSYNTAX:
455 throw SyntaxErrorException("Lua syntax error in file %s: %s", filename, errmsg.c_str());
456
457 case LUA_ERRMEM: throw OutOfMemoryException("Could not load Lua file %s", filename);
458
459 case LUA_ERRFILE: throw CouldNotOpenFileException(filename, errmsg.c_str());
460 }
461 }
462
463 int errfunc = enable_tracebacks_ ? 1 : 0;
464 if ((err = lua_pcall(L, 0, LUA_MULTRET, errfunc)) != 0) {
465 // There was an error while executing the initialization file
466 errmsg = lua_tostring(L, -1);
467 lua_pop(L, 1);
468 switch (err) {
469 case LUA_ERRRUN: throw LuaRuntimeException("do_file", errmsg.c_str());
470
471 case LUA_ERRMEM: throw OutOfMemoryException("Could not execute Lua file %s", filename);
472
473 case LUA_ERRERR: throw LuaErrorException("do_file", errmsg.c_str());
474
475 default: throw LuaErrorException("do_file/unknown error", errmsg.c_str());
476 }
477 }
478}
479
480/** Execute string on a specific Lua state.
481 * @param L Lua state to execute the string in
482 * @param format format of string to execute, arguments can be the same as
483 * for vasprintf.
484 */
485void
486LuaContext::do_string(lua_State *L, const char *format, ...)
487{
488 va_list arg;
489 va_start(arg, format);
490 char *s;
491 if (vasprintf(&s, format, arg) == -1) {
492 throw Exception("LuaContext::do_string: Could not form string");
493 }
494 std::string ss(s);
495 free(s);
496 va_end(arg);
497
498 int err = 0;
499 std::string errmsg;
500 if ((err = luaL_loadstring(L, ss.c_str())) != 0) {
501 errmsg = lua_tostring(L, -1);
502 lua_pop(L, 1);
503 switch (err) {
504 case LUA_ERRSYNTAX:
505 throw SyntaxErrorException("Lua syntax error in string %s: %s", ss.c_str(), errmsg.c_str());
506
507 case LUA_ERRMEM: throw OutOfMemoryException("Could not load Lua string %s", ss.c_str());
508 }
509 }
510
511 int errfunc = enable_tracebacks_ ? 1 : 0;
512 err = lua_pcall(L, 0, LUA_MULTRET, errfunc);
513
514 if (err != 0) {
515 std::string errmsg = lua_tostring(L, -1);
516 lua_pop(L, 1);
517 switch (err) {
518 case LUA_ERRRUN: throw LuaRuntimeException("do_string", errmsg.c_str());
519
520 case LUA_ERRMEM: throw OutOfMemoryException("Could not execute Lua chunk via pcall");
521
522 case LUA_ERRERR: throw LuaErrorException("do_string", errmsg.c_str());
523 }
524 }
525}
526
527/** Execute string.
528 * @param format format of string to execute, arguments can be the same as
529 * for vasprintf.
530 */
531void
532LuaContext::do_string(const char *format, ...)
533{
534 MutexLocker lock(lua_mutex_);
535
536 va_list arg;
537 va_start(arg, format);
538 char *s;
539 if (vasprintf(&s, format, arg) == -1) {
540 throw Exception("LuaContext::do_string: Could not form string");
541 }
542 std::string ss(s);
543 free(s);
544 va_end(arg);
545
546 int err = 0;
547 std::string errmsg;
548 if ((err = luaL_loadstring(L_, ss.c_str())) != 0) {
549 errmsg = lua_tostring(L_, -1);
550 lua_pop(L_, 1);
551 switch (err) {
552 case LUA_ERRSYNTAX:
553 throw SyntaxErrorException("Lua syntax error in string %s: %s", ss.c_str(), errmsg.c_str());
554
555 case LUA_ERRMEM: throw OutOfMemoryException("Could not load Lua string %s", ss.c_str());
556 }
557 }
558
559 int errfunc = enable_tracebacks_ ? 1 : 0;
560 err = lua_pcall(L_, 0, LUA_MULTRET, errfunc);
561
562 if (err != 0) {
563 std::string errmsg = lua_tostring(L_, -1);
564 lua_pop(L_, 1);
565 switch (err) {
566 case LUA_ERRRUN: throw LuaRuntimeException("do_string", errmsg.c_str());
567
568 case LUA_ERRMEM: throw OutOfMemoryException("Could not execute Lua chunk via pcall");
569
570 case LUA_ERRERR: throw LuaErrorException("do_string", errmsg.c_str());
571 }
572 }
573}
574
575/** Load Lua string.
576 * Loads the Lua string and places it as a function on top of the stack.
577 * @param s string to load
578 */
579void
581{
582 int err;
583 if ((err = luaL_loadstring(L_, s)) != 0) {
584 std::string errmsg = lua_tostring(L_, -1);
585 lua_pop(L_, 1);
586 switch (err) {
587 case LUA_ERRSYNTAX:
588 throw SyntaxErrorException("Lua syntax error in string '%s': %s", s, errmsg.c_str());
589
590 case LUA_ERRMEM: throw OutOfMemoryException("Could not load Lua string '%s'", s);
591 }
592 }
593}
594
595/** Protected call.
596 * Calls the function on top of the stack. Errors are handled gracefully.
597 * @param nargs number of arguments
598 * @param nresults number of results
599 * @param errfunc stack index of an error handling function
600 * @exception Exception thrown for generic runtime error or if the
601 * error function could not be executed.
602 * @exception OutOfMemoryException thrown if not enough memory was available
603 */
604void
605LuaContext::pcall(int nargs, int nresults, int errfunc)
606{
607 int err = 0;
608 if (!errfunc && enable_tracebacks_)
609 errfunc = 1;
610 if ((err = lua_pcall(L_, nargs, nresults, errfunc)) != 0) {
611 std::string errmsg = lua_tostring(L_, -1);
612 lua_pop(L_, 1);
613 switch (err) {
614 case LUA_ERRRUN: throw LuaRuntimeException("pcall", errmsg.c_str());
615
616 case LUA_ERRMEM: throw OutOfMemoryException("Could not execute Lua chunk via pcall");
617
618 case LUA_ERRERR: throw LuaErrorException("pcall", errmsg.c_str());
619 }
620 }
621}
622
623/** Assert that the name is unique.
624 * Checks the internal context structures if the name has been used
625 * already. It will accept a value that has already been set that is of the same
626 * type as the one supplied. Pass the empty string to avoid this.
627 * @param name name to check
628 * @param type type of value
629 * @exception Exception thrown if name is not unique
630 */
631void
632LuaContext::assert_unique_name(const char *name, std::string type)
633{
634 if ((type == "usertype") && (usertypes_.find(name) != usertypes_.end())) {
635 throw Exception("User type entry already exists for name %s", name);
636 }
637 if ((type == "string") && (strings_.find(name) != strings_.end())) {
638 throw Exception("String entry already exists for name %s", name);
639 }
640 if ((type == "boolean") && (booleans_.find(name) != booleans_.end())) {
641 throw Exception("Boolean entry already exists for name %s", name);
642 }
643 if ((type == "number") && (numbers_.find(name) != numbers_.end())) {
644 throw Exception("Number entry already exists for name %s", name);
645 }
646 if ((type == "integer") && (integers_.find(name) != integers_.end())) {
647 throw Exception("Integer entry already exists for name %s", name);
648 }
649 if ((type == "cfunction") && (cfuncs_.find(name) != cfuncs_.end())) {
650 throw Exception("C function entry already exists for name %s", name);
651 }
652}
653
654/** Assign usertype to global variable.
655 * @param name name of global variable to assign the value to
656 * @param data usertype data
657 * @param type_name type name of the data
658 * @param name_space C++ namespace of type, prepended to type_name
659 */
660void
662 void * data,
663 const char *type_name,
664 const char *name_space)
665{
666 MutexLocker lock(lua_mutex_);
667
668 std::string type_n = type_name;
669 if (name_space) {
670 type_n = std::string(name_space) + "::" + type_name;
671 }
672
673 assert_unique_name(name, "usertype");
674
675 usertypes_[name] = std::make_pair(data, type_n);
676
677 tolua_pushusertype(L_, data, type_n.c_str());
678 lua_setglobal(L_, name);
679}
680
681/** Assign string to global variable.
682 * @param name name of global variable to assign the value to
683 * @param value value to assign
684 */
685void
686LuaContext::set_string(const char *name, const char *value)
687{
688 MutexLocker lock(lua_mutex_);
689 assert_unique_name(name, "string");
690
691 strings_[name] = value;
692
693 lua_pushstring(L_, value);
694 lua_setglobal(L_, name);
695}
696
697/** Assign boolean to global variable.
698 * @param name name of global variable to assign the value to
699 * @param value value to assign
700 */
701void
702LuaContext::set_boolean(const char *name, bool value)
703{
704 MutexLocker lock(lua_mutex_);
705 assert_unique_name(name, "boolean");
706
707 booleans_[name] = value;
708
709 lua_pushboolean(L_, value ? 1 : 0);
710 lua_setglobal(L_, name);
711}
712
713/** Assign number to global variable.
714 * @param name name of global variable to assign the value to
715 * @param value value to assign
716 */
717void
718LuaContext::set_number(const char *name, lua_Number value)
719{
720 MutexLocker lock(lua_mutex_);
721 assert_unique_name(name, "number");
722
723 numbers_[name] = value;
724
725 lua_pushnumber(L_, value);
726 lua_setglobal(L_, name);
727}
728
729/** Assign integer to global variable.
730 * @param name name of global variable to assign the value to
731 * @param value value to assign
732 */
733void
734LuaContext::set_integer(const char *name, lua_Integer value)
735{
736 MutexLocker lock(lua_mutex_);
737 assert_unique_name(name, "integer");
738
739 integers_[name] = value;
740
741 lua_pushinteger(L_, value);
742 lua_setglobal(L_, name);
743}
744
745/** Assign cfunction to global variable.
746 * @param name name of global variable to assign the value to
747 * @param f function
748 */
749void
750LuaContext::set_cfunction(const char *name, lua_CFunction f)
751{
752 MutexLocker lock(lua_mutex_);
753 assert_unique_name(name, "cfunction");
754
755 cfuncs_[name] = f;
756
757 lua_pushcfunction(L_, f);
758 lua_setglobal(L_, name);
759}
760
761/** Push boolean on top of stack.
762 * @param value value to push
763 */
764void
766{
767 MutexLocker lock(lua_mutex_);
768 lua_pushboolean(L_, value ? 1 : 0);
769}
770
771/** Push formatted string on top of stack.
772 * @param format string format
773 * @see man 3 sprintf
774 */
775void
776LuaContext::push_fstring(const char *format, ...)
777{
778 MutexLocker lock(lua_mutex_);
779 va_list arg;
780 va_start(arg, format);
781 lua_pushvfstring(L_, format, arg);
782 va_end(arg);
783}
784
785/** Push integer on top of stack.
786 * @param value value to push
787 */
788void
789LuaContext::push_integer(lua_Integer value)
790{
791 MutexLocker lock(lua_mutex_);
792 lua_pushinteger(L_, value);
793}
794
795/** Push light user data on top of stack.
796 * @param p pointer to light user data to push
797 */
798void
800{
801 MutexLocker lock(lua_mutex_);
802 lua_pushlightuserdata(L_, p);
803}
804
805/** Push substring on top of stack.
806 * @param s string to push
807 * @param len length of string to push
808 */
809void
810LuaContext::push_lstring(const char *s, size_t len)
811{
812 MutexLocker lock(lua_mutex_);
813 lua_pushlstring(L_, s, len);
814}
815
816/** Push nil on top of stack.
817 */
818void
820{
821 MutexLocker lock(lua_mutex_);
822 lua_pushnil(L_);
823}
824
825/** Push number on top of stack.
826 * @param value value to push
827 */
828void
829LuaContext::push_number(lua_Number value)
830{
831 MutexLocker lock(lua_mutex_);
832 lua_pushnumber(L_, value);
833}
834
835/** Push string on top of stack.
836 * @param value value to push
837 */
838void
839LuaContext::push_string(const char *value)
840{
841 MutexLocker lock(lua_mutex_);
842 lua_pushstring(L_, value);
843}
844
845/** Push thread on top of stack.
846 */
847void
849{
850 MutexLocker lock(lua_mutex_);
851 lua_pushthread(L_);
852}
853
854/** Push a copy of the element at the given index on top of the stack.
855 * @param idx index of the value to copy
856 */
857void
859{
860 MutexLocker lock(lua_mutex_);
861 lua_pushvalue(L_, idx);
862}
863
864/** Push formatted string on top of stack.
865 * @param format string format
866 * @param arg variadic argument list
867 * @see man 3 sprintf
868 */
869void
870LuaContext::push_vfstring(const char *format, va_list arg)
871{
872 MutexLocker lock(lua_mutex_);
873 lua_pushvfstring(L_, format, arg);
874}
875
876/** Push usertype on top of stack.
877 * @param data usertype data
878 * @param type_name type name of the data
879 * @param name_space C++ namespace of type, prepended to type_name
880 */
881void
882LuaContext::push_usertype(void *data, const char *type_name, const char *name_space)
883{
884 MutexLocker lock(lua_mutex_);
885
886 std::string type_n = type_name;
887 if (name_space) {
888 type_n = std::string(name_space) + "::" + type_name;
889 }
890
891 tolua_pushusertype(L_, data, type_n.c_str());
892}
893
894/** Push C function on top of stack.
895 * @param f C Function to push
896 */
897void
899{
900 MutexLocker lock(lua_mutex_);
901 lua_pushcfunction(L_, f);
902}
903
904/** Get name of type of value at a given index.
905 * @param idx index of value to get type for
906 * @return name of type of the value at the given index
907 */
908std::string
910{
911 return lua_typename(L_, lua_type(L_, idx));
912}
913
914/** Pop value(s) from stack.
915 * @param n number of values to pop
916 */
917void
919{
920 MutexLocker lock(lua_mutex_);
921 if (enable_tracebacks_ && (n >= stack_size())) {
922 throw LuaRuntimeException("pop", "Cannot pop traceback function, invalid n");
923 }
924 lua_pop(L_, n);
925}
926
927/** Remove value from stack.
928 * @param idx index of element to remove
929 */
930void
932{
933 MutexLocker lock(lua_mutex_);
934 if (enable_tracebacks_ && ((idx == 1) || (idx == -stack_size()))) {
935 throw LuaRuntimeException("pop", "Cannot remove traceback function");
936 }
937 lua_remove(L_, idx);
938}
939
940/** Get size of stack.
941 * @return number of elements on the stack
942 */
943int
945{
946 return lua_gettop(L_);
947}
948
949/** Create a table on top of the stack.
950 * @param narr number of array elements
951 * @param nrec number of non-array elements
952 */
953void
954LuaContext::create_table(int narr, int nrec)
955{
956 lua_createtable(L_, narr, nrec);
957}
958
959/** Set value of a table.
960 * Sets value t[k] = v. t is the table at the given index, by default it is the
961 * third-last entry (index is -3). v is the value at the top of the stack, k
962 * is the element just below the top.
963 * @param t_index index of the table on the stack
964 */
965void
967{
968 lua_settable(L_, t_index);
969}
970
971/** Set field of a table. Does the equivalent to t[k] = v, where t is
972 * the value at the given valid index and v is the value at the top of
973 * the stack. This function pops the value from the stack. As in Lua,
974 * this function may trigger a metamethod for the "newindex" event.
975 * @param key key of the field to set @param t_index index of the
976 * table on the stack, defaults to the element just below the value to
977 * set (-2, second last element on the stack).
978 */
979void
980LuaContext::set_field(const char *key, int t_index)
981{
982 lua_setfield(L_, t_index, key);
983}
984
985/** Set a global value.
986 * Sets the global variable with the given name to the value currently on top
987 * of the stack. No check whatsoever regarding the name is done.
988 * @param name name of the variable to assign
989 */
990void
991LuaContext::set_global(const char *name)
992{
993 lua_setglobal(L_, name);
994}
995
996/** Get value from table.
997 * Assumes that an index k is at the top of the stack. Then t[k] is retrieved,
998 * where t is a table at the given index idx. The resulting value is pushed
999 * onto the stack, while the key k is popped from the stack, thus the value
1000 * replaces the key.
1001 * @param idx index of the table on the stack
1002 */
1003void
1005{
1006 lua_gettable(L_, idx);
1007}
1008
1009/** Get named value from table.
1010 * Retrieves the t[k], where k is the given key and t is a table at the given
1011 * index idx. The value is pushed onto the stack.
1012 * @param idx index of the table
1013 * @param k key of the table entry
1014 */
1015void
1016LuaContext::get_field(int idx, const char *k)
1017{
1018 lua_getfield(L_, idx, k);
1019}
1020
1021/** Set value without invoking meta methods.
1022 * Similar to set_table(), but does raw access, i.e. without invoking meta-methods.
1023 * @param idx index of the table
1024 */
1025void
1027{
1028 lua_rawset(L_, idx);
1029}
1030
1031/** Set indexed value without invoking meta methods.
1032 * Sets t[n]=v, where t is a table at index idx and v is the value at the
1033 * top of the stack.
1034 * @param idx index of the table
1035 * @param n index in the table
1036 */
1037void
1039{
1040 lua_rawseti(L_, idx, n);
1041}
1042
1043/** Get value without invoking meta methods.
1044 * Similar to get_table(), but does raw access, i.e. without invoking meta-methods.
1045 * @param idx index of the table
1046 */
1047void
1049{
1050 lua_rawget(L_, idx);
1051}
1052
1053/** Get indexed value without invoking meta methods.
1054 * Pushes t[n] onto the stack, where t is a table at index idx.
1055 * @param idx index of the table
1056 * @param n index in the table
1057 */
1058void
1060{
1061 lua_rawgeti(L_, idx, n);
1062}
1063
1064/** Get global variable.
1065 * @param name name of the global variable
1066 */
1067void
1068LuaContext::get_global(const char *name)
1069{
1070 lua_getglobal(L_, name);
1071}
1072
1073/** Remove global variable.
1074 * Assigns nil to the given variable and removes it from internal
1075 * assignment maps.
1076 * @param name name of value to remove
1077 */
1078void
1080{
1081 MutexLocker lock(lua_mutex_);
1082
1083 usertypes_.erase(name);
1084 strings_.erase(name);
1085 booleans_.erase(name);
1086 numbers_.erase(name);
1087 integers_.erase(name);
1088 cfuncs_.erase(name);
1089
1090 lua_pushnil(L_);
1091 lua_setglobal(L_, name);
1092}
1093
1094/** Iterate to next entry of table.
1095 * @param idx stack index of table
1096 * @return true if there was another iterable value in the table,
1097 * false otherwise
1098 */
1099bool
1101{
1102 return lua_next(L_, idx) != 0;
1103}
1104
1105/** Retrieve stack value as number.
1106 * @param idx stack index of value
1107 * @return value as number
1108 */
1109lua_Number
1111{
1112 return lua_tonumber(L_, idx);
1113}
1114
1115/** Retrieve stack value as integer.
1116 * @param idx stack index of value
1117 * @return value as integer
1118 */
1119lua_Integer
1121{
1122 return lua_tointeger(L_, idx);
1123}
1124
1125/** Retrieve stack value as boolean.
1126 * @param idx stack index of value
1127 * @return value as boolean
1128 */
1129bool
1131{
1132 return lua_toboolean(L_, idx);
1133}
1134
1135/** Retrieve stack value as string.
1136 * @param idx stack index of value
1137 * @return value as string
1138 */
1139const char *
1141{
1142 return lua_tostring(L_, idx);
1143}
1144
1145/** Retrieve stack value as userdata.
1146 * @param idx stack index of value
1147 * @return value as userdata, maybe NULL
1148 */
1149void *
1151{
1152 return lua_touserdata(L_, idx);
1153}
1154
1155/** Retrieve stack value as pointer.
1156 * @param idx stack index of value
1157 * @return value as pointer, maybe NULL
1158 */
1159void *
1161{
1162 return (void *)lua_topointer(L_, idx);
1163}
1164
1165/** Retrieve stack value as a tolua++ user type.
1166 * @param idx stack index of value
1167 * @return value as pointer, maybe NULL
1168 */
1169void *
1171{
1172 return tolua_tousertype(L_, idx, 0);
1173}
1174
1175/** Check if stack value is a boolean.
1176 * @param idx stack index of value
1177 * @return true if value is a boolean, false otherwise
1178 */
1179bool
1181{
1182 return lua_isboolean(L_, idx);
1183}
1184
1185/** Check if stack value is a C function.
1186 * @param idx stack index of value
1187 * @return true if value is a C function, false otherwise
1188 */
1189bool
1191{
1192 return lua_iscfunction(L_, idx);
1193}
1194
1195/** Check if stack value is a function.
1196 * @param idx stack index of value
1197 * @return true if value is a function, false otherwise
1198 */
1199bool
1201{
1202 return lua_isfunction(L_, idx);
1203}
1204
1205/** Check if stack value is light user data.
1206 * @param idx stack index of value
1207 * @return true if value is light user data , false otherwise
1208 */
1209bool
1211{
1212 return lua_islightuserdata(L_, idx);
1213}
1214
1215/** Check if stack value is nil.
1216 * @param idx stack index of value
1217 * @return true if value is nil, false otherwise
1218 */
1219bool
1221{
1222 return lua_isnil(L_, idx);
1223}
1224
1225/** Check if stack value is a number.
1226 * @param idx stack index of value
1227 * @return true if value is a number, false otherwise
1228 */
1229bool
1231{
1232 return lua_isnumber(L_, idx);
1233}
1234
1235/** Check if stack value is a string.
1236 * @param idx stack index of value
1237 * @return true if value is a string, false otherwise
1238 */
1239bool
1241{
1242 return lua_isstring(L_, idx);
1243}
1244
1245/** Check if stack value is a table.
1246 * @param idx stack index of value
1247 * @return true if value is a table, false otherwise
1248 */
1249bool
1251{
1252 return lua_istable(L_, idx);
1253}
1254
1255/** Check if stack value is a thread.
1256 * @param idx stack index of value
1257 * @return true if value is a thread, false otherwise
1258 */
1259bool
1261{
1262 return lua_isthread(L_, idx);
1263}
1264
1265/** Get object length
1266 * @param idx stack index of value
1267 * @return size of object
1268 */
1269size_t
1271{
1272 return lua_objlen(L_, idx);
1273}
1274
1275/** Set function environment.
1276 * Sets the table on top of the stack as environment of the function
1277 * at the given stack index.
1278 * @param idx stack index of function
1279 */
1280void
1282{
1283#if LUA_VERSION_NUM > 501
1284 // stack: ... func@idx ... env
1285 // find _ENV
1286 int n = 0;
1287 const char *val_name;
1288 while ((val_name = lua_getupvalue(L_, idx, ++n)) != NULL) { // ... env upval
1289 if (strcmp(val_name, "_ENV") == 0) {
1290 // found environment
1291 break;
1292 } else {
1293 // we're not interested, remove value from stack
1294 lua_pop(L_, 1); // ... env
1295 }
1296 }
1297
1298 // found an environment
1299 if (val_name != NULL) { // ... env upval
1300 // create a new simple up value
1301 luaL_loadstring(L_, ""); // ... env upval chunk
1302 lua_pushvalue(L_, -3); // ... env upval chunk env
1303 lua_setupvalue(L_, -2, 1); // ... env upval func
1304 int act_idx = idx > 0 ? idx : idx - 2;
1305 lua_upvaluejoin(L_, act_idx, n, -1, 1); // ... env upval chunk
1306 lua_pop(L_, 3); // ...
1307 } else {
1308 throw Exception("No environment found");
1309 }
1310#else
1311 lua_setfenv(L_, idx);
1312#endif
1313}
1314
1315/** Add a context watcher.
1316 * @param watcher watcher to add
1317 */
1318void
1320{
1321 watchers_.push_back_locked(watcher);
1322}
1323
1324/** Remove a context watcher.
1325 * @param watcher watcher to remove
1326 */
1327void
1329{
1330 watchers_.remove_locked(watcher);
1331}
1332
1333/** Set code to execute during finalization.
1334 * @param finalize code string to execute (via do_string()) when eventually
1335 * finalizing a context
1336 * @param finalize_prepare code string to execute (via do_string()) before
1337 * finalization is performed, for example during a context restart before the
1338 * new context is initialized
1339 * @param finalize_cancel code string to execute (via do_string()) if,
1340 * during a restart, the initialization of the new context failed and therefore
1341 * the previously prepared finalization must be cancelled
1342 */
1343void
1345 std::string finalize_prepare,
1346 std::string finalize_cancel)
1347{
1348 finalize_call_ = finalize;
1349 finalize_prepare_call_ = finalize_prepare;
1350 finalize_cancel_call_ = finalize_cancel;
1351}
1352
1353/** Process FAM events. */
1354void
1356{
1357 if (fam_)
1358 fam_->process_events();
1359}
1360
1361void
1362LuaContext::fam_event(const char *filename, unsigned int mask)
1363{
1364 restart();
1365}
1366
1367} // end of namespace fawkes
File could not be opened.
Definition: system.h:53
Base class for exceptions in Fawkes.
Definition: exception.h:36
FileAlterationMonitor thread wrapper.
Definition: fam_thread.h:33
Monitors files for changes.
Definition: fam.h:71
static void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: liblogger.cpp:156
static void log_error(const char *component, const char *format,...)
Log error message.
Definition: liblogger.cpp:174
Lua context watcher.
bool is_nil(int idx)
Check if stack value is nil.
Definition: context.cpp:1220
bool is_light_user_data(int idx)
Check if stack value is light user data.
Definition: context.cpp:1210
bool is_function(int idx)
Check if stack value is a function.
Definition: context.cpp:1200
bool is_number(int idx)
Check if stack value is a number.
Definition: context.cpp:1230
void push_string(const char *value)
Push string on top of stack.
Definition: context.cpp:839
void push_value(int idx)
Push a copy of the element at the given index on top of the stack.
Definition: context.cpp:858
lua_Number to_number(int idx)
Retrieve stack value as number.
Definition: context.cpp:1110
std::string type_name(int idx)
Get name of type of value at a given index.
Definition: context.cpp:909
void push_vfstring(const char *format, va_list arg)
Push formatted string on top of stack.
Definition: context.cpp:870
void remove_global(const char *name)
Remove global variable.
Definition: context.cpp:1079
void set_global(const char *name)
Set a global value.
Definition: context.cpp:991
bool is_thread(int idx)
Check if stack value is a thread.
Definition: context.cpp:1260
void * to_usertype(int idx)
Retrieve stack value as a tolua++ user type.
Definition: context.cpp:1170
void setfenv(int idx=-2)
Set function environment.
Definition: context.cpp:1281
void push_nil()
Push nil on top of stack.
Definition: context.cpp:819
void setup_fam(bool auto_restart, bool conc_thread)
Setup file alteration monitor.
Definition: context.cpp:125
void get_global(const char *name)
Get global variable.
Definition: context.cpp:1068
void remove(int idx)
Remove value from stack.
Definition: context.cpp:931
bool to_boolean(int idx)
Retrieve stack value as boolean.
Definition: context.cpp:1130
void set_integer(const char *name, lua_Integer value)
Assign integer to global variable.
Definition: context.cpp:734
void lock()
Lock Lua state.
Definition: context.cpp:409
void restart()
Restart Lua.
Definition: context.cpp:285
void process_fam_events()
Process FAM events.
Definition: context.cpp:1355
void add_cpackage_dir(const char *path, bool prefix=false)
Add a Lua C package directory.
Definition: context.cpp:363
void set_start_script(const char *start_script)
Set start script.
Definition: context.cpp:263
void remove_watcher(LuaContextWatcher *watcher)
Remove a context watcher.
Definition: context.cpp:1328
void raw_set(int idx)
Set value without invoking meta methods.
Definition: context.cpp:1026
void set_field(const char *key, int t_index=-2)
Set field of a table.
Definition: context.cpp:980
void push_lstring(const char *s, size_t len)
Push substring on top of stack.
Definition: context.cpp:810
void push_light_user_data(void *p)
Push light user data on top of stack.
Definition: context.cpp:799
const char * to_string(int idx)
Retrieve stack value as string.
Definition: context.cpp:1140
void push_usertype(void *data, const char *type_name, const char *name_space=0)
Push usertype on top of stack.
Definition: context.cpp:882
RefPtr< FileAlterationMonitor > get_fam() const
Get file alteration monitor.
Definition: context.cpp:143
void push_thread()
Push thread on top of stack.
Definition: context.cpp:848
lua_Integer to_integer(int idx)
Retrieve stack value as integer.
Definition: context.cpp:1120
bool is_cfunction(int idx)
Check if stack value is a C function.
Definition: context.cpp:1190
lua_State * get_lua_state()
Get Lua state.
Definition: context.cpp:402
void set_usertype(const char *name, void *data, const char *type_name, const char *name_space=0)
Assign usertype to global variable.
Definition: context.cpp:661
void raw_geti(int idx, int n)
Get indexed value without invoking meta methods.
Definition: context.cpp:1059
void push_boolean(bool value)
Push boolean on top of stack.
Definition: context.cpp:765
void * to_userdata(int idx)
Retrieve stack value as userdata.
Definition: context.cpp:1150
void push_integer(lua_Integer value)
Push integer on top of stack.
Definition: context.cpp:789
void raw_seti(int idx, int n)
Set indexed value without invoking meta methods.
Definition: context.cpp:1038
void add_package_dir(const char *path, bool prefix=false)
Add a Lua package directory.
Definition: context.cpp:330
void set_cfunction(const char *name, lua_CFunction f)
Assign cfunction to global variable.
Definition: context.cpp:750
void do_file(const char *filename)
Execute file.
Definition: context.cpp:434
void push_number(lua_Number value)
Push number on top of stack.
Definition: context.cpp:829
bool is_boolean(int idx)
Check if stack value is a boolean.
Definition: context.cpp:1180
void create_table(int narr=0, int nrec=0)
Create a table on top of the stack.
Definition: context.cpp:954
void pop(int n)
Pop value(s) from stack.
Definition: context.cpp:918
void set_number(const char *name, lua_Number value)
Assign number to global variable.
Definition: context.cpp:718
void set_boolean(const char *name, bool value)
Assign boolean to global variable.
Definition: context.cpp:702
void unlock()
Unlock Lua state.
Definition: context.cpp:425
~LuaContext()
Destructor.
Definition: context.cpp:95
LuaContext(bool enable_tracebacks=true)
Constructor.
Definition: context.cpp:63
void * to_pointer(int idx)
Retrieve stack value as pointer.
Definition: context.cpp:1160
void add_watcher(LuaContextWatcher *watcher)
Add a context watcher.
Definition: context.cpp:1319
void pcall(int nargs=0, int nresults=0, int errfunc=0)
Protected call.
Definition: context.cpp:605
void do_string(const char *format,...)
Execute string.
Definition: context.cpp:532
bool is_string(int idx)
Check if stack value is a string.
Definition: context.cpp:1240
virtual void fam_event(const char *filename, unsigned int mask)
Event has been raised.
Definition: context.cpp:1362
void set_string(const char *name, const char *value)
Assign string to global variable.
Definition: context.cpp:686
bool try_lock()
Try to lock the Lua state.
Definition: context.cpp:418
void push_fstring(const char *format,...)
Push formatted string on top of stack.
Definition: context.cpp:776
void set_table(int t_index=-3)
Set value of a table.
Definition: context.cpp:966
void set_finalization_calls(std::string finalize, std::string finalize_prepare, std::string finalize_cancel)
Set code to execute during finalization.
Definition: context.cpp:1344
void add_package(const char *package)
Add a default package.
Definition: context.cpp:386
void raw_get(int idx)
Get value without invoking meta methods.
Definition: context.cpp:1048
bool table_next(int idx)
Iterate to next entry of table.
Definition: context.cpp:1100
size_t objlen(int idx)
Get object length.
Definition: context.cpp:1270
void load_string(const char *s)
Load Lua string.
Definition: context.cpp:580
int stack_size()
Get size of stack.
Definition: context.cpp:944
void get_table(int idx)
Get value from table.
Definition: context.cpp:1004
bool is_table(int idx)
Check if stack value is a table.
Definition: context.cpp:1250
void push_cfunction(lua_CFunction f)
Push C function on top of stack.
Definition: context.cpp:898
void get_field(int idx, const char *k)
Get named value from table.
Definition: context.cpp:1016
Lua error exception.
Definition: exceptions.h:37
Lua runtime exception.
Definition: exceptions.h:31
Mutex locking helper.
Definition: mutex_locker.h:34
Mutex mutual exclusion lock.
Definition: mutex.h:33
bool try_lock()
Tries to lock the mutex.
Definition: mutex.cpp:117
void lock()
Lock this mutex.
Definition: mutex.cpp:87
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:50
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:499
void join()
Join the thread.
Definition: thread.cpp:597
void cancel()
Cancel a thread.
Definition: thread.cpp:646
Fawkes library namespace.