Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * context.cpp - Fawkes Lua Context 00004 * 00005 * Created: Fri May 23 15:53:54 2008 00006 * Copyright 2006-2009 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include <lua/context.h> 00024 #include <lua/context_watcher.h> 00025 #include <core/threading/mutex.h> 00026 #include <core/threading/mutex_locker.h> 00027 #include <core/exceptions/system.h> 00028 #include <core/exceptions/software.h> 00029 #include <logging/liblogger.h> 00030 00031 #include <algorithm> 00032 #include <tolua++.h> 00033 #include <cstdlib> 00034 #include <cstring> 00035 #include <unistd.h> 00036 00037 namespace fawkes { 00038 #if 0 /* just to make Emacs auto-indent happy */ 00039 } 00040 #endif 00041 00042 /** @class LuaContext <lua/context.h> 00043 * Lua C++ wrapper. 00044 * This thin wrapper allows for easy integration of Fawkes into other 00045 * applications. It provides convenience methods to some Lua and 00046 * tolua++ features like setting global variables or pushing/popping 00047 * values. 00048 * 00049 * It allows raw access to the Lua state since this class does not and 00050 * should not provide all the features Lua provides. If you use this 00051 * make sure that you lock the Lua context to avoid multi-threading 00052 * problems (if that is a possible concern in your application). 00053 * 00054 * LuaContext can use a FileAlterationMonitor on all added package and 00055 * C package directories. If anything changes in these directories the 00056 * Lua instance is then automatically restarted (closed, re-opened and 00057 * re-initialized). 00058 * 00059 * @author Tim Niemueller 00060 */ 00061 00062 /** Constructor. 00063 * @param enable_tracebacks if true an error function is installed at the top 00064 * of the stackand used for pcalls where errfunc is 0. 00065 */ 00066 LuaContext::LuaContext(bool enable_tracebacks) 00067 { 00068 __owns_L = true; 00069 __enable_tracebacks = enable_tracebacks; 00070 __fam = NULL; 00071 __fam_thread = NULL; 00072 00073 __lua_mutex = new Mutex(); 00074 00075 __start_script = NULL; 00076 __L = init_state(); 00077 } 00078 00079 /** Wrapper contstructor. 00080 * This wraps around an existing Lua state. It does not initialize the state in 00081 * the sense that it would add variables etc. It only provides convenient access 00082 * to the state methods via a C++ interface. It's mainly intended to be used to 00083 * create a LuaContext to be passed to LuaContextWatcher::lua_restarted(). The 00084 * state is not closed on destruction as is done when using the other ctor. 00085 * @param L Lua state to wrap 00086 */ 00087 LuaContext::LuaContext(lua_State *L) 00088 { 00089 __owns_L = false; 00090 __L = L; 00091 __lua_mutex = new Mutex(); 00092 __start_script = NULL; 00093 __fam = NULL; 00094 __fam_thread = NULL; 00095 } 00096 00097 /** Destructor. */ 00098 LuaContext::~LuaContext() 00099 { 00100 __lua_mutex->lock(); 00101 if (__fam_thread) { 00102 __fam_thread->cancel(); 00103 __fam_thread->join(); 00104 delete __fam_thread; 00105 } 00106 delete __lua_mutex; 00107 if ( __start_script ) free(__start_script); 00108 if ( __owns_L) { 00109 lua_close(__L); 00110 } 00111 } 00112 00113 00114 /** Setup file alteration monitor. 00115 * Setup an internal file alteration monitor that can react to changes 00116 * on Lua files and packages. 00117 * @param auto_restart automatically restart the Lua context in case 00118 * of an event 00119 * @param conc_thread true to run a concurrent thread for event 00120 * processing. If and only if you set this to false, ensure that 00121 * process_fam_events() periodically. 00122 */ 00123 void 00124 LuaContext::setup_fam(bool auto_restart, bool conc_thread) 00125 { 00126 __fam = new FileAlterationMonitor(); 00127 __fam->add_filter("^[^.].*\\.lua$"); 00128 if (auto_restart) { 00129 __fam->add_listener(this); 00130 } 00131 if (conc_thread) { 00132 __fam_thread = new FamThread(__fam); 00133 __fam_thread->start(); 00134 } 00135 } 00136 00137 00138 /** Get file alteration monitor. 00139 * @return reference counted pointer to file alteration monitor. Note 00140 * that the pointer might be invalid if setup_fam() has not been called. 00141 */ 00142 RefPtr<FileAlterationMonitor> 00143 LuaContext::get_fam() const 00144 { 00145 return __fam; 00146 } 00147 00148 00149 /** Initialize Lua state. 00150 * Initializes the state and makes all necessary initializations. 00151 * @return fresh initialized Lua state 00152 */ 00153 lua_State * 00154 LuaContext::init_state() 00155 { 00156 lua_State *L = luaL_newstate(); 00157 luaL_openlibs(L); 00158 00159 if (__enable_tracebacks) { 00160 lua_getglobal(L, "debug"); 00161 lua_getfield(L, -1, "traceback"); 00162 lua_remove(L, -2); 00163 } 00164 00165 // Add package paths 00166 for (__slit = __package_dirs.begin(); __slit != __package_dirs.end(); ++__slit) { 00167 do_string(L, "package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", __slit->c_str(), __slit->c_str()); 00168 } 00169 00170 for (__slit = __cpackage_dirs.begin(); __slit != __cpackage_dirs.end(); ++__slit) { 00171 do_string(L, "package.cpath = package.cpath .. \";%s/?.so\"", __slit->c_str()); 00172 } 00173 00174 // load base packages 00175 for (__slit = __packages.begin(); __slit != __packages.end(); ++__slit) { 00176 do_string(L, "require(\"%s\")", __slit->c_str()); 00177 } 00178 00179 for ( __utit = __usertypes.begin(); __utit != __usertypes.end(); ++__utit) { 00180 tolua_pushusertype(L, __utit->second.first, __utit->second.second.c_str()); 00181 lua_setglobal(L, __utit->first.c_str()); 00182 } 00183 00184 for ( __strings_it = __strings.begin(); __strings_it != __strings.end(); ++__strings_it) { 00185 lua_pushstring(L, __strings_it->second.c_str()); 00186 lua_setglobal(L, __strings_it->first.c_str()); 00187 } 00188 00189 for ( __booleans_it = __booleans.begin(); __booleans_it != __booleans.end(); ++__booleans_it) { 00190 lua_pushboolean(L, __booleans_it->second); 00191 lua_setglobal(L, __booleans_it->first.c_str()); 00192 } 00193 00194 for ( __numbers_it = __numbers.begin(); __numbers_it != __numbers.end(); ++__numbers_it) { 00195 lua_pushnumber(L, __numbers_it->second); 00196 lua_setglobal(L, __numbers_it->first.c_str()); 00197 } 00198 00199 for ( __integers_it = __integers.begin(); __integers_it != __integers.end(); ++__integers_it) { 00200 lua_pushinteger(L, __integers_it->second); 00201 lua_setglobal(L, __integers_it->first.c_str()); 00202 } 00203 00204 for ( __cfuncs_it = __cfuncs.begin(); __cfuncs_it != __cfuncs.end(); ++__cfuncs_it) 00205 { 00206 lua_pushcfunction(L, __cfuncs_it->second); 00207 lua_setglobal(L, __cfuncs_it->first.c_str()); 00208 } 00209 00210 LuaContext *tmpctx = new LuaContext(L); 00211 MutexLocker(__watchers.mutex()); 00212 LockList<LuaContextWatcher *>::iterator i; 00213 for (i = __watchers.begin(); i != __watchers.end(); ++i) { 00214 try { 00215 (*i)->lua_restarted(tmpctx); 00216 } catch (...) { 00217 delete tmpctx; 00218 lua_close(L); 00219 throw; 00220 } 00221 } 00222 delete tmpctx; 00223 00224 if ( __start_script ) { 00225 if (access(__start_script, R_OK) == 0) { 00226 // it's a file and we can access it, execute it! 00227 do_file(L, __start_script); 00228 } else { 00229 do_string(L, "require(\"%s\")", __start_script); 00230 } 00231 } 00232 00233 return L; 00234 } 00235 00236 00237 /** Set start script. 00238 * The script will be executed once immediately in this method, make 00239 * sure you call this after all other init-relevant routines like 00240 * add_* if you need to access these in the start script! 00241 * @param start_script script to execute now and on restart(). If the 00242 * string is the path and name of an accessible file it is loaded via 00243 * do_file(), otherwise it is considered to be the name of a module and 00244 * loaded via Lua's require(). Note however, that if you use a module, 00245 * special care has to be taken to correctly modify the global 00246 * environment! 00247 */ 00248 void 00249 LuaContext::set_start_script(const char *start_script) 00250 { 00251 if ( __start_script ) free(__start_script); 00252 if ( start_script ) { 00253 __start_script = strdup(start_script); 00254 if (access(__start_script, R_OK) == 0) { 00255 // it's a file and we can access it, execute it! 00256 do_file(__start_script); 00257 } else { 00258 do_string("require(\"%s\")", __start_script); 00259 } 00260 } else { 00261 __start_script = NULL; 00262 } 00263 } 00264 00265 00266 /** Restart Lua. 00267 * Creates a new Lua state, initializes it, anf if this went well the 00268 * current state is swapped with the new state. 00269 */ 00270 void 00271 LuaContext::restart() 00272 { 00273 MutexLocker lock(__lua_mutex); 00274 try { 00275 lua_State *L = init_state(); 00276 lua_State *tL = __L; 00277 __L = L; 00278 lua_close(tL); 00279 00280 } catch (Exception &e) { 00281 LibLogger::log_error("LuaContext", "Could not restart Lua instance, an error " 00282 "occured while initializing new state. Keeping old state."); 00283 LibLogger::log_error("LuaContext", e); 00284 } 00285 } 00286 00287 00288 /** Add a Lua package directory. 00289 * The directory is added to the search path for lua packages. Files with 00290 * a .lua suffix will be considered as Lua modules. 00291 * @param path path to add 00292 */ 00293 void 00294 LuaContext::add_package_dir(const char *path) 00295 { 00296 MutexLocker lock(__lua_mutex); 00297 00298 do_string(__L, "package.path = package.path .. \";%s/?.lua;%s/?/init.lua\"", path, path); 00299 00300 __package_dirs.push_back(path); 00301 if ( __fam ) __fam->watch_dir(path); 00302 } 00303 00304 00305 /** Add a Lua C package directory. 00306 * The directory is added to the search path for lua C packages. Files 00307 * with a .so suffix will be considered as Lua modules. 00308 * @param path path to add 00309 */ 00310 void 00311 LuaContext::add_cpackage_dir(const char *path) 00312 { 00313 MutexLocker lock(__lua_mutex); 00314 00315 do_string(__L, "package.cpath = package.cpath .. \";%s/?.so\"", path); 00316 00317 __cpackage_dirs.push_back(path); 00318 if ( __fam ) __fam->watch_dir(path); 00319 } 00320 00321 00322 /** Add a default package. 00323 * Packages that are added this way are automatically loaded now and 00324 * on restart(). 00325 * @param package package to add 00326 */ 00327 void 00328 LuaContext::add_package(const char *package) 00329 { 00330 MutexLocker lock(__lua_mutex); 00331 if (find(__packages.begin(), __packages.end(), package) == __packages.end()) { 00332 do_string(__L, "require(\"%s\")", package); 00333 00334 __packages.push_back(package); 00335 } 00336 } 00337 00338 00339 /** Get Lua state. 00340 * Allows for raw modification of the used Lua state. Remember proper 00341 * locking! 00342 * @return Currently used Lua state 00343 */ 00344 lua_State * 00345 LuaContext::get_lua_state() 00346 { 00347 return __L; 00348 } 00349 00350 00351 /** Lock Lua state. */ 00352 void 00353 LuaContext::lock() 00354 { 00355 __lua_mutex->lock(); 00356 } 00357 00358 00359 /** Try to lock the Lua state. 00360 * @return true if the state has been locked, false otherwise. 00361 */ 00362 bool 00363 LuaContext::try_lock() 00364 { 00365 return __lua_mutex->try_lock(); 00366 } 00367 00368 00369 /** Unlock Lua state. */ 00370 void 00371 LuaContext::unlock() 00372 { 00373 __lua_mutex->unlock(); 00374 } 00375 00376 00377 /** Execute file. 00378 * @param filename filet to load and excute. 00379 */ 00380 void 00381 LuaContext::do_file(const char *filename) 00382 { 00383 MutexLocker lock(__lua_mutex); 00384 do_file(__L, filename); 00385 } 00386 00387 00388 /** Execute file on a specific Lua state. 00389 * @param L Lua state to execute the file in. 00390 * @param filename filet to load and excute. 00391 */ 00392 void 00393 LuaContext::do_file(lua_State *L, const char *filename) 00394 { 00395 // Load initialization code 00396 int err = 0; 00397 std::string errmsg; 00398 if ( (err = luaL_loadfile(L, filename)) != 0) { 00399 errmsg = lua_tostring(L, -1); 00400 lua_pop(L, 1); 00401 switch (err) { 00402 case LUA_ERRSYNTAX: 00403 throw SyntaxErrorException("Lua syntax error in file %s: %s", filename, errmsg.c_str()); 00404 00405 case LUA_ERRMEM: 00406 throw OutOfMemoryException("Could not load Lua file %s", filename); 00407 00408 case LUA_ERRFILE: 00409 throw CouldNotOpenFileException(filename, errmsg.c_str()); 00410 } 00411 } 00412 00413 int errfunc = __enable_tracebacks ? 1 : 0; 00414 if ( (err = lua_pcall(L, 0, LUA_MULTRET, errfunc)) != 0 ) { 00415 // There was an error while executing the initialization file 00416 errmsg = lua_tostring(L, -1); 00417 lua_pop(L, 1); 00418 switch (err) { 00419 case LUA_ERRRUN: 00420 throw LuaRuntimeException("do_file", errmsg.c_str()); 00421 00422 case LUA_ERRMEM: 00423 throw OutOfMemoryException("Could not execute Lua file %s", filename); 00424 00425 case LUA_ERRERR: 00426 throw LuaErrorException("do_file", errmsg.c_str()); 00427 00428 default: 00429 throw LuaErrorException("do_file/unknown error", errmsg.c_str()); 00430 } 00431 } 00432 00433 } 00434 00435 00436 /** Execute string on a specific Lua state. 00437 * @param L Lua state to execute the string in 00438 * @param format format of string to execute, arguments can be the same as 00439 * for vasprintf. 00440 */ 00441 void 00442 LuaContext::do_string(lua_State *L, const char *format, ...) 00443 { 00444 va_list arg; 00445 va_start(arg, format); 00446 char *s; 00447 if (vasprintf(&s, format, arg) == -1) { 00448 throw Exception("LuaContext::do_string: Could not form string"); 00449 } 00450 00451 int rv = 0; 00452 int errfunc = __enable_tracebacks ? 1 : 0; 00453 rv = (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, errfunc)); 00454 00455 free(s); 00456 va_end(arg); 00457 00458 if (rv != 0) { 00459 std::string errmsg = lua_tostring(L, -1); 00460 lua_pop(L, 1); 00461 throw LuaRuntimeException("do_string", errmsg.c_str()); 00462 } 00463 } 00464 00465 00466 /** Execute string. 00467 * @param format format of string to execute, arguments can be the same as 00468 * for vasprintf. 00469 */ 00470 void 00471 LuaContext::do_string(const char *format, ...) 00472 { 00473 MutexLocker lock(__lua_mutex); 00474 va_list arg; 00475 va_start(arg, format); 00476 char *s; 00477 if (vasprintf(&s, format, arg) == -1) { 00478 throw Exception("LuaContext::do_string: Could not form string"); 00479 } 00480 00481 int rv = 0; 00482 int errfunc = __enable_tracebacks ? 1 : 0; 00483 rv = (luaL_loadstring(__L, s) || lua_pcall(__L, 0, LUA_MULTRET, errfunc)); 00484 00485 free(s); 00486 va_end(arg); 00487 00488 if ( rv != 0 ) { 00489 std::string errmsg = lua_tostring(__L, -1); 00490 lua_pop(__L, 1); 00491 throw LuaRuntimeException("do_string", errmsg.c_str()); 00492 } 00493 } 00494 00495 00496 /** Load Lua string. 00497 * Loads the Lua string and places it as a function on top of the stack. 00498 * @param s string to load 00499 */ 00500 void 00501 LuaContext::load_string(const char *s) 00502 { 00503 int err; 00504 if ( (err = luaL_loadstring(__L, s)) != 0 ) { 00505 std::string errmsg = lua_tostring(__L, -1); 00506 lua_pop(__L, 1); 00507 switch (err) { 00508 case LUA_ERRSYNTAX: 00509 throw SyntaxErrorException("Lua syntax error in string '%s': %s", 00510 s, errmsg.c_str()); 00511 00512 case LUA_ERRMEM: 00513 throw OutOfMemoryException("Could not load Lua string '%s'", s); 00514 } 00515 } 00516 } 00517 00518 00519 /** Protected call. 00520 * Calls the function on top of the stack. Errors are handled gracefully. 00521 * @param nargs number of arguments 00522 * @param nresults number of results 00523 * @param errfunc stack index of an error handling function 00524 * @exception Exception thrown for generic runtime error or if the 00525 * error function could not be executed. 00526 * @exception OutOfMemoryException thrown if not enough memory was available 00527 */ 00528 void 00529 LuaContext::pcall(int nargs, int nresults, int errfunc) 00530 { 00531 int err = 0; 00532 if ( ! errfunc && __enable_tracebacks ) errfunc = 1; 00533 if ( (err = lua_pcall(__L, nargs, nresults, errfunc)) != 0 ) { 00534 std::string errmsg = lua_tostring(__L, -1); 00535 lua_pop(__L, 1); 00536 switch (err) { 00537 case LUA_ERRRUN: 00538 throw LuaRuntimeException("pcall", errmsg.c_str()); 00539 00540 case LUA_ERRMEM: 00541 throw OutOfMemoryException("Could not execute Lua chunk via pcall"); 00542 00543 case LUA_ERRERR: 00544 throw LuaErrorException("pcall", errmsg.c_str()); 00545 } 00546 } 00547 } 00548 00549 00550 /** Assert that the name is unique. 00551 * Checks the internal context structures if the name has been used 00552 * already. It will accept a value that has already been set that is of the same 00553 * type as the one supplied. Pass the empty string to avoid this. 00554 * @param name name to check 00555 * @param type type of value 00556 * @exception Exception thrown if name is not unique 00557 */ 00558 void 00559 LuaContext::assert_unique_name(const char *name, std::string type) 00560 { 00561 if ( (type == "usertype") && (__usertypes.find(name) != __usertypes.end()) ) { 00562 throw Exception("User type entry already exists for name %s", name); 00563 } 00564 if ( (type == "string") && (__strings.find(name) != __strings.end()) ) { 00565 throw Exception("String entry already exists for name %s", name); 00566 } 00567 if ( (type == "boolean") && (__booleans.find(name) != __booleans.end()) ) { 00568 throw Exception("Boolean entry already exists for name %s", name); 00569 } 00570 if ( (type == "number") && (__numbers.find(name) != __numbers.end()) ) { 00571 throw Exception("Number entry already exists for name %s", name); 00572 } 00573 if ( (type == "integer") && (__integers.find(name) != __integers.end()) ) { 00574 throw Exception("Integer entry already exists for name %s", name); 00575 } 00576 if ( (type == "cfunction") && (__cfuncs.find(name) != __cfuncs.end()) ) { 00577 throw Exception("C function entry already exists for name %s", name); 00578 } 00579 } 00580 00581 00582 /** Assign usertype to global variable. 00583 * @param name name of global variable to assign the value to 00584 * @param data usertype data 00585 * @param type_name type name of the data 00586 * @param name_space C++ namespace of type, prepended to type_name 00587 */ 00588 void 00589 LuaContext::set_usertype(const char *name, void *data, 00590 const char *type_name, const char *name_space) 00591 { 00592 MutexLocker lock(__lua_mutex); 00593 00594 std::string type_n = type_name; 00595 if ( name_space ) { 00596 type_n = std::string(name_space) + "::" + type_name; 00597 } 00598 00599 assert_unique_name(name, "usertype"); 00600 00601 __usertypes[name] = std::make_pair(data, type_n); 00602 00603 tolua_pushusertype(__L, data, type_n.c_str()); 00604 lua_setglobal(__L, name); 00605 } 00606 00607 00608 /** Assign string to global variable. 00609 * @param name name of global variable to assign the value to 00610 * @param value value to assign 00611 */ 00612 void 00613 LuaContext::set_string(const char *name, const char *value) 00614 { 00615 MutexLocker lock(__lua_mutex); 00616 assert_unique_name(name, "string"); 00617 00618 __strings[name] = value; 00619 00620 lua_pushstring(__L, value); 00621 lua_setglobal(__L, name); 00622 } 00623 00624 00625 /** Assign boolean to global variable. 00626 * @param name name of global variable to assign the value to 00627 * @param value value to assign 00628 */ 00629 void 00630 LuaContext::set_boolean(const char *name, bool value) 00631 { 00632 MutexLocker lock(__lua_mutex); 00633 assert_unique_name(name, "boolean"); 00634 00635 __booleans[name] = value; 00636 00637 lua_pushboolean(__L, value ? 1 : 0); 00638 lua_setglobal(__L, name); 00639 } 00640 00641 00642 /** Assign number to global variable. 00643 * @param name name of global variable to assign the value to 00644 * @param value value to assign 00645 */ 00646 void 00647 LuaContext::set_number(const char *name, lua_Number value) 00648 { 00649 MutexLocker lock(__lua_mutex); 00650 assert_unique_name(name, "number"); 00651 00652 __numbers[name] = value; 00653 00654 lua_pushnumber(__L, value); 00655 lua_setglobal(__L, name); 00656 } 00657 00658 00659 /** Assign integer to global variable. 00660 * @param name name of global variable to assign the value to 00661 * @param value value to assign 00662 */ 00663 void 00664 LuaContext::set_integer(const char *name, lua_Integer value) 00665 { 00666 MutexLocker lock(__lua_mutex); 00667 assert_unique_name(name, "integer"); 00668 00669 __integers[name] = value; 00670 00671 lua_pushinteger(__L, value); 00672 lua_setglobal(__L, name); 00673 } 00674 00675 00676 /** Assign cfunction to global variable. 00677 * @param name name of global variable to assign the value to 00678 * @param f function 00679 */ 00680 void 00681 LuaContext::set_cfunction(const char *name, lua_CFunction f) 00682 { 00683 MutexLocker lock(__lua_mutex); 00684 assert_unique_name(name, "cfunction"); 00685 00686 __cfuncs[name] = f; 00687 00688 lua_pushcfunction(__L, f); 00689 lua_setglobal(__L, name); 00690 } 00691 00692 00693 /** Push boolean on top of stack. 00694 * @param value value to push 00695 */ 00696 void 00697 LuaContext::push_boolean(bool value) 00698 { 00699 MutexLocker lock(__lua_mutex); 00700 lua_pushboolean(__L, value ? 1 : 0); 00701 } 00702 00703 00704 /** Push formatted string on top of stack. 00705 * @param format string format 00706 * @see man 3 sprintf 00707 */ 00708 void 00709 LuaContext::push_fstring(const char *format, ...) 00710 { 00711 MutexLocker lock(__lua_mutex); 00712 va_list arg; 00713 va_start(arg, format); 00714 lua_pushvfstring(__L, format, arg); 00715 va_end(arg); 00716 } 00717 00718 00719 /** Push integer on top of stack. 00720 * @param value value to push 00721 */ 00722 void 00723 LuaContext::push_integer(lua_Integer value) 00724 { 00725 MutexLocker lock(__lua_mutex); 00726 lua_pushinteger(__L, value); 00727 } 00728 00729 00730 /** Push light user data on top of stack. 00731 * @param p pointer to light user data to push 00732 */ 00733 void 00734 LuaContext::push_light_user_data(void *p) 00735 { 00736 MutexLocker lock(__lua_mutex); 00737 lua_pushlightuserdata(__L, p); 00738 } 00739 00740 00741 /** Push substring on top of stack. 00742 * @param s string to push 00743 * @param len length of string to push 00744 */ 00745 void 00746 LuaContext::push_lstring(const char *s, size_t len) 00747 { 00748 MutexLocker lock(__lua_mutex); 00749 lua_pushlstring(__L, s, len); 00750 } 00751 00752 00753 /** Push nil on top of stack. 00754 */ 00755 void 00756 LuaContext::push_nil() 00757 { 00758 MutexLocker lock(__lua_mutex); 00759 lua_pushnil(__L); 00760 } 00761 00762 00763 /** Push number on top of stack. 00764 * @param value value to push 00765 */ 00766 void 00767 LuaContext::push_number(lua_Number value) 00768 { 00769 MutexLocker lock(__lua_mutex); 00770 lua_pushnumber(__L, value); 00771 } 00772 00773 00774 /** Push string on top of stack. 00775 * @param value value to push 00776 */ 00777 void 00778 LuaContext::push_string(const char *value) 00779 { 00780 MutexLocker lock(__lua_mutex); 00781 lua_pushstring(__L, value); 00782 } 00783 00784 00785 /** Push thread on top of stack. 00786 */ 00787 void 00788 LuaContext::push_thread() 00789 { 00790 MutexLocker lock(__lua_mutex); 00791 lua_pushthread(__L); 00792 } 00793 00794 00795 /** Push a copy of the element at the given index on top of the stack. 00796 * @param idx index of the value to copy 00797 */ 00798 void 00799 LuaContext::push_value(int idx) 00800 { 00801 MutexLocker lock(__lua_mutex); 00802 lua_pushvalue(__L, idx); 00803 } 00804 00805 00806 /** Push formatted string on top of stack. 00807 * @param format string format 00808 * @param arg variadic argument list 00809 * @see man 3 sprintf 00810 */ 00811 void 00812 LuaContext::push_vfstring(const char *format, va_list arg) 00813 { 00814 MutexLocker lock(__lua_mutex); 00815 lua_pushvfstring(__L, format, arg); 00816 } 00817 00818 00819 /** Push usertype on top of stack. 00820 * @param data usertype data 00821 * @param type_name type name of the data 00822 * @param name_space C++ namespace of type, prepended to type_name 00823 */ 00824 void 00825 LuaContext::push_usertype(void *data, const char *type_name, 00826 const char *name_space) 00827 { 00828 MutexLocker lock(__lua_mutex); 00829 00830 std::string type_n = type_name; 00831 if ( name_space ) { 00832 type_n = std::string(name_space) + "::" + type_name; 00833 } 00834 00835 tolua_pushusertype(__L, data, type_n.c_str()); 00836 } 00837 00838 00839 /** Push C function on top of stack. 00840 * @param f C Function to push 00841 */ 00842 void 00843 LuaContext::push_cfunction(lua_CFunction f) 00844 { 00845 MutexLocker lock(__lua_mutex); 00846 lua_pushcfunction(__L, f); 00847 } 00848 00849 00850 /** Pop value(s) from stack. 00851 * @param n number of values to pop 00852 */ 00853 void 00854 LuaContext::pop(int n) 00855 { 00856 MutexLocker lock(__lua_mutex); 00857 if (__enable_tracebacks && (n >= stack_size())) { 00858 throw LuaRuntimeException("pop", "Cannot pop traceback function, invalid n"); 00859 } 00860 lua_pop(__L, n); 00861 } 00862 00863 /** Remove value from stack. 00864 * @param idx index of element to remove 00865 */ 00866 void 00867 LuaContext::remove(int idx) 00868 { 00869 MutexLocker lock(__lua_mutex); 00870 if (__enable_tracebacks && ((idx == 1) || (idx == -stack_size()))) { 00871 throw LuaRuntimeException("pop", "Cannot remove traceback function"); 00872 } 00873 lua_remove(__L, idx); 00874 } 00875 00876 00877 /** Get size of stack. 00878 * @return number of elements on the stack 00879 */ 00880 int 00881 LuaContext::stack_size() 00882 { 00883 return lua_gettop(__L); 00884 } 00885 00886 00887 /** Create a table on top of the stack. 00888 * @param narr number of array elements 00889 * @param nrec number of non-array elements 00890 */ 00891 void 00892 LuaContext::create_table(int narr, int nrec) 00893 { 00894 lua_createtable(__L, narr, nrec); 00895 } 00896 00897 00898 /** Set value of a table. 00899 * Sets value t[k] = v. t is the table at the given index, by default it is the 00900 * third-last entry (index is -3). v is the value at the top of the stack, k 00901 * is the element just below the top. 00902 * @param t_index index of the table on the stack 00903 */ 00904 void 00905 LuaContext::set_table(int t_index) 00906 { 00907 lua_settable(__L, t_index); 00908 } 00909 00910 00911 /** Set field of a table. Does the equivalent to t[k] = v, where t is 00912 * the value at the given valid index and v is the value at the top of 00913 * the stack. This function pops the value from the stack. As in Lua, 00914 * this function may trigger a metamethod for the "newindex" event. 00915 * @param key key of the field to set @param t_index index of the 00916 * table on the stack, defaults to the element just below the value to 00917 * set (-2, second last element on the stack). 00918 */ 00919 void 00920 LuaContext::set_field(const char *key, int t_index) 00921 { 00922 lua_setfield(__L, t_index, key); 00923 } 00924 00925 00926 /** Set a global value. 00927 * Sets the global variable with the given name to the value currently on top 00928 * of the stack. No check whatsoever regarding the name is done. 00929 * @param name name of the variable to assign 00930 */ 00931 void 00932 LuaContext::set_global(const char *name) 00933 { 00934 lua_setglobal(__L, name); 00935 } 00936 00937 00938 /** Get value from table. 00939 * Assumes that an index k is at the top of the stack. Then t[k] is retrieved, 00940 * where t is a table at the given index idx. The resulting value is pushed 00941 * onto the stack, while the key k is popped from the stack, thus the value 00942 * replaces the key. 00943 * @param idx index of the table on the stack 00944 */ 00945 void 00946 LuaContext::get_table(int idx) 00947 { 00948 lua_gettable(__L, idx); 00949 } 00950 00951 00952 /** Get named value from table. 00953 * Retrieves the t[k], where k is the given key and t is a table at the given 00954 * index idx. The value is pushed onto the stack. 00955 * @param idx index of the table 00956 * @param k key of the table entry 00957 */ 00958 void 00959 LuaContext::get_field(int idx, const char *k) 00960 { 00961 lua_getfield(__L, idx, k); 00962 } 00963 00964 00965 /** Set value without invoking meta methods. 00966 * Similar to set_table(), but does raw access, i.e. without invoking meta-methods. 00967 * @param idx index of the table 00968 */ 00969 void 00970 LuaContext::raw_set(int idx) 00971 { 00972 lua_rawset(__L, idx); 00973 } 00974 00975 00976 /** Set indexed value without invoking meta methods. 00977 * Sets t[n]=v, where t is a table at index idx and v is the value at the 00978 * top of the stack. 00979 * @param idx index of the table 00980 * @param n index in the table 00981 */ 00982 void 00983 LuaContext::raw_seti(int idx, int n) 00984 { 00985 lua_rawseti(__L, idx, n); 00986 } 00987 00988 00989 /** Get value without invoking meta methods. 00990 * Similar to get_table(), but does raw access, i.e. without invoking meta-methods. 00991 * @param idx index of the table 00992 */ 00993 void 00994 LuaContext::raw_get(int idx) 00995 { 00996 lua_rawget(__L, idx); 00997 } 00998 00999 01000 /** Get indexed value without invoking meta methods. 01001 * Pushes t[n] onto the stack, where t is a table at index idx. 01002 * @param idx index of the table 01003 * @param n index in the table 01004 */ 01005 void 01006 LuaContext::raw_geti(int idx, int n) 01007 { 01008 lua_rawgeti(__L, idx, n); 01009 } 01010 01011 01012 /** Get global variable. 01013 * @param name name of the global variable 01014 */ 01015 void 01016 LuaContext::get_global(const char *name) 01017 { 01018 lua_getglobal(__L, name); 01019 } 01020 01021 01022 /** Remove global variable. 01023 * Assigns nil to the given variable and removes it from internal 01024 * assignment maps. 01025 * @param name name of value to remove 01026 */ 01027 void 01028 LuaContext::remove_global(const char *name) 01029 { 01030 MutexLocker lock(__lua_mutex); 01031 01032 __usertypes.erase(name); 01033 __strings.erase(name); 01034 __booleans.erase(name); 01035 __numbers.erase(name); 01036 __integers.erase(name); 01037 __cfuncs.erase(name); 01038 01039 lua_pushnil(__L); 01040 lua_setglobal(__L, name); 01041 } 01042 01043 01044 /** Retrieve stack value as number. 01045 * @param idx stack index of value 01046 * @return value as number 01047 */ 01048 lua_Number 01049 LuaContext::to_number(int idx) 01050 { 01051 return lua_tonumber(__L, idx); 01052 } 01053 01054 01055 /** Retrieve stack value as integer. 01056 * @param idx stack index of value 01057 * @return value as integer 01058 */ 01059 lua_Integer 01060 LuaContext::to_integer(int idx) 01061 { 01062 return lua_tointeger(__L, idx); 01063 } 01064 01065 01066 /** Retrieve stack value as boolean. 01067 * @param idx stack index of value 01068 * @return value as boolean 01069 */ 01070 bool 01071 LuaContext::to_boolean(int idx) 01072 { 01073 return lua_toboolean(__L, idx); 01074 } 01075 01076 01077 /** Retrieve stack value as string. 01078 * @param idx stack index of value 01079 * @return value as string 01080 */ 01081 const char * 01082 LuaContext::to_string(int idx) 01083 { 01084 return lua_tostring(__L, idx); 01085 } 01086 01087 01088 /** Check if stack value is a boolean. 01089 * @param idx stack index of value 01090 * @return true if value is a boolean, false otherwise 01091 */ 01092 bool 01093 LuaContext::is_boolean(int idx) 01094 { 01095 return lua_isboolean(__L, idx); 01096 } 01097 01098 01099 /** Check if stack value is a C function. 01100 * @param idx stack index of value 01101 * @return true if value is a C function, false otherwise 01102 */ 01103 bool 01104 LuaContext::is_cfunction(int idx) 01105 { 01106 return lua_iscfunction(__L, idx); 01107 } 01108 01109 01110 /** Check if stack value is a function. 01111 * @param idx stack index of value 01112 * @return true if value is a function, false otherwise 01113 */ 01114 bool 01115 LuaContext::is_function(int idx) 01116 { 01117 return lua_isfunction(__L, idx); 01118 } 01119 01120 01121 /** Check if stack value is light user data. 01122 * @param idx stack index of value 01123 * @return true if value is light user data , false otherwise 01124 */ 01125 bool 01126 LuaContext::is_light_user_data(int idx) 01127 { 01128 return lua_islightuserdata(__L, idx); 01129 } 01130 01131 01132 /** Check if stack value is nil. 01133 * @param idx stack index of value 01134 * @return true if value is nil, false otherwise 01135 */ 01136 bool 01137 LuaContext::is_nil(int idx) 01138 { 01139 return lua_isnil(__L, idx); 01140 } 01141 01142 01143 /** Check if stack value is a number. 01144 * @param idx stack index of value 01145 * @return true if value is a number, false otherwise 01146 */ 01147 bool 01148 LuaContext::is_number(int idx) 01149 { 01150 return lua_isnumber(__L, idx); 01151 } 01152 01153 01154 /** Check if stack value is a string. 01155 * @param idx stack index of value 01156 * @return true if value is a string, false otherwise 01157 */ 01158 bool 01159 LuaContext::is_string(int idx) 01160 { 01161 return lua_isstring(__L, idx); 01162 } 01163 01164 01165 /** Check if stack value is a table. 01166 * @param idx stack index of value 01167 * @return true if value is a table, false otherwise 01168 */ 01169 bool 01170 LuaContext::is_table(int idx) 01171 { 01172 return lua_istable(__L, idx); 01173 } 01174 01175 01176 /** Check if stack value is a thread. 01177 * @param idx stack index of value 01178 * @return true if value is a thread, false otherwise 01179 */ 01180 bool 01181 LuaContext::is_thread(int idx) 01182 { 01183 return lua_isthread(__L, idx); 01184 } 01185 01186 01187 /** Get object length 01188 * @param idx stack index of value 01189 * @return size of object 01190 */ 01191 size_t 01192 LuaContext::objlen(int idx) 01193 { 01194 return lua_objlen(__L, idx); 01195 } 01196 01197 01198 /** Set function environment. 01199 * Sets the table on top of the stack as environment of the function 01200 * at the given stack index. 01201 * @param idx stack index of function 01202 */ 01203 void 01204 LuaContext::setfenv(int idx) 01205 { 01206 lua_setfenv(__L, idx); 01207 } 01208 01209 01210 /** Add a context watcher. 01211 * @param watcher watcher to add 01212 */ 01213 void 01214 LuaContext::add_watcher(fawkes::LuaContextWatcher *watcher) 01215 { 01216 __watchers.push_back_locked(watcher); 01217 } 01218 01219 01220 /** Remove a context watcher. 01221 * @param watcher watcher to remove 01222 */ 01223 void 01224 LuaContext::remove_watcher(fawkes::LuaContextWatcher *watcher) 01225 { 01226 __watchers.remove_locked(watcher); 01227 } 01228 01229 01230 01231 /** Process FAM events. */ 01232 void 01233 LuaContext::process_fam_events() 01234 { 01235 if ( __fam) __fam->process_events(); 01236 } 01237 01238 01239 void 01240 LuaContext::fam_event(const char *filename, unsigned int mask) 01241 { 01242 restart(); 01243 } 01244 01245 01246 } // end of namespace fawkes