00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00039 }
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
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
00088
00089
00090
00091
00092
00093
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
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
00118
00119
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
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
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
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
00200
00201
00202
00203
00204
00205
00206
00207
00208
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
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
00229
00230
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
00251
00252
00253
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
00268
00269
00270
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
00285
00286
00287
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
00302
00303
00304
00305
00306 lua_State *
00307 LuaContext::get_lua_state()
00308 {
00309 return __L;
00310 }
00311
00312
00313
00314 void
00315 LuaContext::lock()
00316 {
00317 __lua_mutex->lock();
00318 }
00319
00320
00321
00322
00323
00324 bool
00325 LuaContext::try_lock()
00326 {
00327 return __lua_mutex->try_lock();
00328 }
00329
00330
00331
00332 void
00333 LuaContext::unlock()
00334 {
00335 __lua_mutex->unlock();
00336 }
00337
00338
00339
00340
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
00351
00352
00353
00354 void
00355 LuaContext::do_file(lua_State *L, const char *filename)
00356 {
00357
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
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
00399
00400
00401
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
00429
00430
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
00459
00460
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
00482
00483
00484
00485
00486
00487
00488
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
00513
00514
00515
00516
00517
00518
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
00542
00543
00544
00545
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
00568
00569
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
00585
00586
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
00602
00603
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
00619
00620
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
00636
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
00647
00648
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
00662
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
00673
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
00684
00685
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
00696
00697 void
00698 LuaContext::push_nil()
00699 {
00700 MutexLocker lock(__lua_mutex);
00701 lua_pushnil(__L);
00702 }
00703
00704
00705
00706
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
00717
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
00728
00729 void
00730 LuaContext::push_thread()
00731 {
00732 MutexLocker lock(__lua_mutex);
00733 lua_pushthread(__L);
00734 }
00735
00736
00737
00738
00739
00740 void
00741 LuaContext::push_value(int idx)
00742 {
00743 MutexLocker lock(__lua_mutex);
00744 lua_pushvalue(__L, idx);
00745 }
00746
00747
00748
00749
00750
00751
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
00762
00763
00764
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
00782
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
00795
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
00809
00810
00811 int
00812 LuaContext::stack_size()
00813 {
00814 return lua_gettop(__L);
00815 }
00816
00817
00818
00819
00820
00821
00822 void
00823 LuaContext::create_table(int narr, int nrec)
00824 {
00825 lua_createtable(__L, narr, nrec);
00826 }
00827
00828
00829
00830
00831
00832
00833
00834
00835 void
00836 LuaContext::set_table(int t_index)
00837 {
00838 lua_settable(__L, t_index);
00839 }
00840
00841
00842
00843
00844
00845
00846
00847
00848
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
00858
00859
00860
00861
00862 void
00863 LuaContext::set_global(const char *name)
00864 {
00865 lua_setglobal(__L, name);
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876 void
00877 LuaContext::get_table(int idx)
00878 {
00879 lua_gettable(__L, idx);
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889 void
00890 LuaContext::get_field(int idx, const char *k)
00891 {
00892 lua_getfield(__L, idx, k);
00893 }
00894
00895
00896
00897
00898
00899
00900 void
00901 LuaContext::raw_set(int idx)
00902 {
00903 lua_rawset(__L, idx);
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913 void
00914 LuaContext::raw_seti(int idx, int n)
00915 {
00916 lua_rawseti(__L, idx, n);
00917 }
00918
00919
00920
00921
00922
00923
00924 void
00925 LuaContext::raw_get(int idx)
00926 {
00927 lua_rawget(__L, idx);
00928 }
00929
00930
00931
00932
00933
00934
00935
00936 void
00937 LuaContext::raw_geti(int idx, int n)
00938 {
00939 lua_rawgeti(__L, idx, n);
00940 }
00941
00942
00943
00944
00945
00946 void
00947 LuaContext::get_global(const char *name)
00948 {
00949 lua_getglobal(__L, name);
00950 }
00951
00952
00953
00954
00955
00956
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
00975
00976
00977
00978 lua_Number
00979 LuaContext::to_number(int idx)
00980 {
00981 return lua_tonumber(__L, idx);
00982 }
00983
00984
00985
00986
00987
00988
00989 lua_Integer
00990 LuaContext::to_integer(int idx)
00991 {
00992 return lua_tointeger(__L, idx);
00993 }
00994
00995
00996
00997
00998
00999
01000 bool
01001 LuaContext::to_boolean(int idx)
01002 {
01003 return lua_toboolean(__L, idx);
01004 }
01005
01006
01007
01008
01009
01010
01011 const char *
01012 LuaContext::to_string(int idx)
01013 {
01014 return lua_tostring(__L, idx);
01015 }
01016
01017
01018
01019
01020
01021
01022 bool
01023 LuaContext::is_boolean(int idx)
01024 {
01025 return lua_isboolean(__L, idx);
01026 }
01027
01028
01029
01030
01031
01032
01033 bool
01034 LuaContext::is_cfunction(int idx)
01035 {
01036 return lua_iscfunction(__L, idx);
01037 }
01038
01039
01040
01041
01042
01043
01044 bool
01045 LuaContext::is_function(int idx)
01046 {
01047 return lua_isfunction(__L, idx);
01048 }
01049
01050
01051
01052
01053
01054
01055 bool
01056 LuaContext::is_light_user_data(int idx)
01057 {
01058 return lua_islightuserdata(__L, idx);
01059 }
01060
01061
01062
01063
01064
01065
01066 bool
01067 LuaContext::is_nil(int idx)
01068 {
01069 return lua_isnil(__L, idx);
01070 }
01071
01072
01073
01074
01075
01076
01077 bool
01078 LuaContext::is_number(int idx)
01079 {
01080 return lua_isnumber(__L, idx);
01081 }
01082
01083
01084
01085
01086
01087
01088 bool
01089 LuaContext::is_string(int idx)
01090 {
01091 return lua_isstring(__L, idx);
01092 }
01093
01094
01095
01096
01097
01098
01099 bool
01100 LuaContext::is_table(int idx)
01101 {
01102 return lua_istable(__L, idx);
01103 }
01104
01105
01106
01107
01108
01109
01110 bool
01111 LuaContext::is_thread(int idx)
01112 {
01113 return lua_isthread(__L, idx);
01114 }
01115
01116
01117
01118
01119
01120
01121 size_t
01122 LuaContext::objlen(int idx)
01123 {
01124 return lua_objlen(__L, idx);
01125 }
01126
01127
01128
01129
01130
01131
01132
01133 void
01134 LuaContext::setfenv(int idx)
01135 {
01136 lua_setfenv(__L, idx);
01137 }
01138
01139
01140
01141
01142
01143 void
01144 LuaContext::add_watcher(fawkes::LuaContextWatcher *watcher)
01145 {
01146 __watchers.push_back_locked(watcher);
01147 }
01148
01149
01150
01151
01152
01153 void
01154 LuaContext::remove_watcher(fawkes::LuaContextWatcher *watcher)
01155 {
01156 __watchers.remove_locked(watcher);
01157 }
01158
01159
01160
01161
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 }