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 
37 namespace 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  */
63 LuaContext::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  */
124 void
125 LuaContext::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  */
152 lua_State *
153 LuaContext::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  */
262 void
263 LuaContext::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  */
284 void
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  */
329 void
330 LuaContext::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  */
362 void
363 LuaContext::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  */
385 void
386 LuaContext::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  */
401 lua_State *
403 {
404  return L_;
405 }
406 
407 /** Lock Lua state. */
408 void
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  */
417 bool
419 {
420  return lua_mutex_->try_lock();
421 }
422 
423 /** Unlock Lua state. */
424 void
426 {
427  lua_mutex_->unlock();
428 }
429 
430 /** Execute file.
431  * @param filename filet to load and excute.
432  */
433 void
434 LuaContext::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  */
444 void
445 LuaContext::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  */
485 void
486 LuaContext::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  */
531 void
532 LuaContext::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  */
579 void
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  */
604 void
605 LuaContext::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  */
631 void
632 LuaContext::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  */
660 void
661 LuaContext::set_usertype(const char *name,
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  */
685 void
686 LuaContext::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  */
701 void
702 LuaContext::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  */
717 void
718 LuaContext::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  */
733 void
734 LuaContext::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  */
749 void
750 LuaContext::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  */
764 void
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  */
775 void
776 LuaContext::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  */
788 void
789 LuaContext::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  */
798 void
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  */
809 void
810 LuaContext::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  */
818 void
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  */
828 void
829 LuaContext::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  */
838 void
839 LuaContext::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  */
847 void
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  */
857 void
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  */
869 void
870 LuaContext::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  */
881 void
882 LuaContext::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  */
897 void
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  */
908 std::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  */
917 void
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  */
930 void
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  */
943 int
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  */
953 void
954 LuaContext::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  */
965 void
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  */
979 void
980 LuaContext::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  */
990 void
991 LuaContext::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  */
1003 void
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  */
1015 void
1016 LuaContext::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  */
1025 void
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  */
1037 void
1038 LuaContext::raw_seti(int idx, int n)
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  */
1047 void
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  */
1058 void
1059 LuaContext::raw_geti(int idx, int n)
1060 {
1061  lua_rawgeti(L_, idx, n);
1062 }
1063 
1064 /** Get global variable.
1065  * @param name name of the global variable
1066  */
1067 void
1068 LuaContext::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  */
1078 void
1079 LuaContext::remove_global(const char *name)
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  */
1099 bool
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  */
1109 lua_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  */
1119 lua_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  */
1129 bool
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  */
1139 const 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  */
1149 void *
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  */
1159 void *
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  */
1169 void *
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  */
1179 bool
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  */
1189 bool
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  */
1199 bool
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  */
1209 bool
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  */
1219 bool
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  */
1229 bool
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  */
1239 bool
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  */
1249 bool
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  */
1259 bool
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  */
1269 size_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  */
1280 void
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  */
1318 void
1320 {
1321  watchers_.push_back_locked(watcher);
1322 }
1323 
1324 /** Remove a context watcher.
1325  * @param watcher watcher to remove
1326  */
1327 void
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  */
1343 void
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. */
1354 void
1356 {
1357  if (fam_)
1358  fam_->process_events();
1359 }
1360 
1361 void
1362 LuaContext::fam_event(const char *filename, unsigned int mask)
1363 {
1364  restart();
1365 }
1366 
1367 } // end of namespace fawkes
void restart()
Restart Lua.
Definition: context.cpp:285
void push_thread()
Push thread on top of stack.
Definition: context.cpp:848
File could not be opened.
Definition: system.h:52
void push_light_user_data(void *p)
Push light user data on top of stack.
Definition: context.cpp:799
void setup_fam(bool auto_restart, bool conc_thread)
Setup file alteration monitor.
Definition: context.cpp:125
void push_vfstring(const char *format, va_list arg)
Push formatted string on top of stack.
Definition: context.cpp:870
bool is_light_user_data(int idx)
Check if stack value is light user data.
Definition: context.cpp:1210
Lua context watcher.
bool is_number(int idx)
Check if stack value is a number.
Definition: context.cpp:1230
void push_integer(lua_Integer value)
Push integer on top of stack.
Definition: context.cpp:789
void raw_geti(int idx, int n)
Get indexed value without invoking meta methods.
Definition: context.cpp:1059
Fawkes library namespace.
void unlock()
Unlock the mutex.
Definition: mutex.cpp:131
bool is_thread(int idx)
Check if stack value is a thread.
Definition: context.cpp:1260
Mutex locking helper.
Definition: mutex_locker.h:33
void pop(int n)
Pop value(s) from stack.
Definition: context.cpp:918
void push_lstring(const char *s, size_t len)
Push substring on top of stack.
Definition: context.cpp:810
void remove(int idx)
Remove value from stack.
Definition: context.cpp:931
void set_cfunction(const char *name, lua_CFunction f)
Assign cfunction to global variable.
Definition: context.cpp:750
void raw_seti(int idx, int n)
Set indexed value without invoking meta methods.
Definition: context.cpp:1038
virtual void fam_event(const char *filename, unsigned int mask)
Event has been raised.
Definition: context.cpp:1362
void load_string(const char *s)
Load Lua string.
Definition: context.cpp:580
void add_package_dir(const char *path, bool prefix=false)
Add a Lua package directory.
Definition: context.cpp:330
void remove_watcher(LuaContextWatcher *watcher)
Remove a context watcher.
Definition: context.cpp:1328
bool is_cfunction(int idx)
Check if stack value is a C function.
Definition: context.cpp:1190
bool try_lock()
Try to lock the Lua state.
Definition: context.cpp:418
void set_field(const char *key, int t_index=-2)
Set field of a table.
Definition: context.cpp:980
void set_table(int t_index=-3)
Set value of a table.
Definition: context.cpp:966
void add_package(const char *package)
Add a default package.
Definition: context.cpp:386
void unlock()
Unlock Lua state.
Definition: context.cpp:425
static void log_error(const char *component, const char *format,...)
Log error message.
Definition: liblogger.cpp:174
void push_value(int idx)
Push a copy of the element at the given index on top of the stack.
Definition: context.cpp:858
void push_nil()
Push nil on top of stack.
Definition: context.cpp:819
int stack_size()
Get size of stack.
Definition: context.cpp:944
void pcall(int nargs=0, int nresults=0, int errfunc=0)
Protected call.
Definition: context.cpp:605
bool is_nil(int idx)
Check if stack value is nil.
Definition: context.cpp:1220
Base class for exceptions in Fawkes.
Definition: exception.h:35
lua_Number to_number(int idx)
Retrieve stack value as number.
Definition: context.cpp:1110
void push_cfunction(lua_CFunction f)
Push C function on top of stack.
Definition: context.cpp:898
void do_string(const char *format,...)
Execute string.
Definition: context.cpp:532
void do_file(const char *filename)
Execute file.
Definition: context.cpp:434
void set_number(const char *name, lua_Number value)
Assign number to global variable.
Definition: context.cpp:718
LuaContext(bool enable_tracebacks=true)
Constructor.
Definition: context.cpp:63
void setfenv(int idx=-2)
Set function environment.
Definition: context.cpp:1281
void get_field(int idx, const char *k)
Get named value from table.
Definition: context.cpp:1016
void set_integer(const char *name, lua_Integer value)
Assign integer to global variable.
Definition: context.cpp:734
Monitors files for changes.
Definition: fam.h:70
lua_Integer to_integer(int idx)
Retrieve stack value as integer.
Definition: context.cpp:1120
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 push_usertype(void *data, const char *type_name, const char *name_space=0)
Push usertype on top of stack.
Definition: context.cpp:882
static void log_warn(const char *component, const char *format,...)
Log warning message.
Definition: liblogger.cpp:156
bool try_lock()
Tries to lock the mutex.
Definition: mutex.cpp:117
void set_string(const char *name, const char *value)
Assign string to global variable.
Definition: context.cpp:686
void push_string(const char *value)
Push string on top of stack.
Definition: context.cpp:839
bool is_table(int idx)
Check if stack value is a table.
Definition: context.cpp:1250
void cancel()
Cancel a thread.
Definition: thread.cpp:646
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 process_fam_events()
Process FAM events.
Definition: context.cpp:1355
void set_boolean(const char *name, bool value)
Assign boolean to global variable.
Definition: context.cpp:702
RefPtr<> is a reference-counting shared smartpointer.
Definition: refptr.h:49
bool is_string(int idx)
Check if stack value is a string.
Definition: context.cpp:1240
void get_global(const char *name)
Get global variable.
Definition: context.cpp:1068
void push_boolean(bool value)
Push boolean on top of stack.
Definition: context.cpp:765
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
bool is_function(int idx)
Check if stack value is a function.
Definition: context.cpp:1200
bool to_boolean(int idx)
Retrieve stack value as boolean.
Definition: context.cpp:1130
bool table_next(int idx)
Iterate to next entry of table.
Definition: context.cpp:1100
lua_State * get_lua_state()
Get Lua state.
Definition: context.cpp:402
void join()
Join the thread.
Definition: thread.cpp:597
Lua runtime exception.
Definition: exceptions.h:30
void get_table(int idx)
Get value from table.
Definition: context.cpp:1004
Lua error exception.
Definition: exceptions.h:36
FileAlterationMonitor thread wrapper.
Definition: fam_thread.h:32
void lock()
Lock this mutex.
Definition: mutex.cpp:87
~LuaContext()
Destructor.
Definition: context.cpp:95
void lock()
Lock Lua state.
Definition: context.cpp:409
void remove_global(const char *name)
Remove global variable.
Definition: context.cpp:1079
Mutex mutual exclusion lock.
Definition: mutex.h:32
void set_global(const char *name)
Set a global value.
Definition: context.cpp:991
void * to_pointer(int idx)
Retrieve stack value as pointer.
Definition: context.cpp:1160
void create_table(int narr=0, int nrec=0)
Create a table on top of the stack.
Definition: context.cpp:954
void push_number(lua_Number value)
Push number on top of stack.
Definition: context.cpp:829
void * to_userdata(int idx)
Retrieve stack value as userdata.
Definition: context.cpp:1150
void * to_usertype(int idx)
Retrieve stack value as a tolua++ user type.
Definition: context.cpp:1170
const char * to_string(int idx)
Retrieve stack value as string.
Definition: context.cpp:1140
void raw_get(int idx)
Get value without invoking meta methods.
Definition: context.cpp:1048
size_t objlen(int idx)
Get object length.
Definition: context.cpp:1270
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:31
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:499
std::string type_name(int idx)
Get name of type of value at a given index.
Definition: context.cpp:909
RefPtr< FileAlterationMonitor > get_fam() const
Get file alteration monitor.
Definition: context.cpp:143
void add_watcher(LuaContextWatcher *watcher)
Add a context watcher.
Definition: context.cpp:1319
bool is_boolean(int idx)
Check if stack value is a boolean.
Definition: context.cpp:1180
void push_fstring(const char *format,...)
Push formatted string on top of stack.
Definition: context.cpp:776
void raw_set(int idx)
Set value without invoking meta methods.
Definition: context.cpp:1026