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