OrocosComponentLibrary  2.7.0
rtt.cpp
00001 /*
00002  * Lua-RTT bindings
00003  *
00004  * (C) Copyright 2010 Markus Klotzbuecher
00005  * markus.klotzbuecher@mech.kuleuven.be
00006  * Department of Mechanical Engineering,
00007  * Katholieke Universiteit Leuven, Belgium.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public
00011  * License as published by the Free Software Foundation;
00012  * version 2 of the License.
00013  *
00014  * As a special exception, you may use this file as part of a free
00015  * software library without restriction.  Specifically, if other files
00016  * instantiate templates or use macros or inline functions from this
00017  * file, or you compile this file and link it with other files to
00018  * produce an executable, this file does not by itself cause the
00019  * resulting executable to be covered by the GNU General Public
00020  * License.  This exception does not however invalidate any other
00021  * reasons why the executable file might be covered by the GNU General
00022  * Public License.
00023  *
00024  * This library is distributed in the hope that it will be useful,
00025  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00026  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027  * Lesser General Public License for more details.
00028  *
00029  * You should have received a copy of the GNU General Public
00030  * License along with this library; if not, write to the Free Software
00031  * Foundation, Inc., 59 Temple Place,
00032  * Suite 330, Boston, MA  02111-1307  USA
00033  */
00034 
00035 #include "rtt.hpp"
00036 
00037 using namespace std;
00038 using namespace RTT;
00039 using namespace RTT::detail;
00040 using namespace RTT::base;
00041 using namespace RTT::internal;
00042 
00043 static TaskContext* __getTC(lua_State*);
00044 
00045 #define DEBUG
00046 
00047 #ifdef MSVC
00048 #ifdef DEBUG
00049 # define _DBG(fmt, ...) printf("%s:%d\t" fmt "\n", __FUNCTION__, __LINE__, __VA_ARGS__)
00050 #else
00051 # define _DBG(fmt, ...) do { } while(0);
00052 #endif
00053 #else
00054 #ifdef DEBUG
00055 # define _DBG(fmt, args...) printf("%s:%d\t" fmt "\n", __FUNCTION__, __LINE__, ##args)
00056 #else
00057 # define _DBG(fmt, args...) do { } while(0);
00058 #endif
00059 #endif
00060 
00061 /*
00062  * Inspired by tricks from here: http://lua-users.org/wiki/DoItYourselfCppBinding
00063  */
00064 
00065 /* overloading new */
00066 void* operator new(size_t size, lua_State* L, const char* mt)
00067 {
00068     void* ptr = lua_newuserdata(L, size);
00069     luaL_getmetatable(L, mt);
00070     /* assert(lua_istable(L, -1)) */  /* if you're paranoid */
00071     lua_setmetatable(L, -2);
00072     return ptr;
00073 }
00074 
00075 /*
00076  * luaM_pushobject_mt(L, "Port", InputPortInterface )(ctr_arg,...)
00077  * expands to
00078  * new(L, "Port") InputPortInterface(ctr_arg,...)
00079  */
00080 
00081 #define luaM_pushobject(L, T) new(L, #T) T
00082 #define luaM_pushobject_mt(L, MT, T) new(L, MT) T
00083 
00084 /* return udata ptr or fail if wrong metatable */
00085 #define luaM_checkudata(L, pos, T) reinterpret_cast<T*>(luaL_checkudata((L), (pos), #T))
00086 #define luaM_checkudata_mt(L, pos, MT, T) reinterpret_cast<T*>(luaL_checkudata((L), (pos), MT))
00087 
00088 /* return udata ptr or NULL if wrong metatable */
00089 #define luaM_testudata(L, pos, T) (T*) (luaL_testudata((L), (pos), #T))
00090 #define luaM_testudata_mt(L, pos, MT, T) (T*) (luaL_testudata((L), (pos), MT))
00091 
00092 /*
00093  * boxed variants
00094  */
00095 
00096 /* return boxed udata ptr or fail if wrong metatable */
00097 #define luaM_checkudata_bx(L, pos, T) (T**) (luaL_checkudata((L), (pos), #T))
00098 #define luaM_checkudata_mt_bx(L, pos, MT, T) (T**) (luaL_checkudata((L), (pos), MT))
00099 
00100 /* return udata ptr or NULL if wrong metatable */
00101 #define luaM_testudata_bx(L, pos, T) (T**) (luaL_testudata((L), (pos), #T))
00102 #define luaM_testudata_mt_bx(L, pos, MT, T) (T**) (luaL_testudata((L), (pos), MT))
00103 
00104 /* generate a function to push boxed pointers to lua */
00105 #define gen_push_bxptr(name, MT, T)            \
00106 static void name(lua_State *L, T* ptr)             \
00107 {                              \
00108     T** ptrptr = (T**) lua_newuserdata(L, sizeof(T*)); \
00109     *ptrptr = ptr;                     \
00110     luaL_getmetatable(L, MT);              \
00111     lua_setmetatable(L, -2);               \
00112 }                              \
00113 
00114 /* template for generating GC function */
00115 template<typename T>
00116 int GCMethod(lua_State* L)
00117 {
00118     reinterpret_cast<T*>(lua_touserdata(L, 1))->~T();
00119     return 0;
00120 }
00121 
00122 
00123 /***************************************************************
00124  * Some generic helpers
00125  ***************************************************************/
00126 
00127 /* test if userdata on position ud has metatable tname */
00128 void* luaL_testudata (lua_State *L, int ud, const char *tname)
00129 {
00130     void *p = lua_touserdata(L, ud);
00131 
00132     if (p == NULL)
00133         goto out;
00134 
00135     if (!lua_getmetatable(L, ud))  {
00136         p = NULL;
00137         goto out;
00138     }
00139 
00140     /* it has a MT, is it the right one? */
00141     lua_pushstring(L, tname);
00142     lua_rawget(L, LUA_REGISTRYINDEX);
00143 
00144     if (!lua_rawequal(L, -1, -2))
00145         p = NULL;
00146 
00147     lua_pop(L, 2);  /* remove both metatables */
00148  out:
00149     return p;
00150 }
00151 
00152 
00153 void push_vect_str(lua_State *L, const std::vector<std::string> &v)
00154 {
00155     int key = 1;
00156     lua_createtable(L, v.size(), 0);
00157 
00158     for(vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it) {
00159         lua_pushstring(L, it->c_str());
00160         lua_rawseti(L, -2, key++);
00161     }
00162 }
00163 
00164 /* forw decl */
00165 static void Variable_fromlua(lua_State *L, DataSourceBase::shared_ptr& dsb, int valind);
00166 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const types::TypeInfo* ti, int valind);
00167 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const char* type, int valind);
00168 
00169 /***************************************************************
00170  * Variable (DataSourceBase)
00171  ***************************************************************/
00172 
00173 static const TypeInfo* ti_lookup(lua_State *L, const char *name)
00174 {
00175 #ifndef TYPEINFO_CACHING
00176     return types::TypeInfoRepository::Instance()->type(name);
00177 #else
00178 /* name-> TypeInfo* cache */
00179     int top = lua_gettop(L);
00180     const TypeInfo* ti;
00181 
00182     /* try lookup */
00183     lua_pushstring(L, "typeinfo_cache");
00184     lua_rawget(L, LUA_REGISTRYINDEX);
00185 
00186     if(lua_type(L, -1) == LUA_TTABLE)
00187         goto table_on_top;
00188 
00189     /* first lookup, create table */
00190     lua_pop(L, 1); /* pop nil */
00191     lua_newtable(L); /* stays on top after the next three lines */
00192     lua_pushstring(L, "typeinfo_cache"); /* key */
00193     lua_pushvalue(L, -2); /* duplicates table */
00194     lua_rawset(L, LUA_REGISTRYINDEX);   /* REG['typeinfo_cache']={} */
00195 
00196  table_on_top:
00197     /* try to lookup name in table */
00198     lua_pushstring(L, name);
00199     lua_rawget(L, -2);
00200 
00201     if(lua_type(L, -1) != LUA_TLIGHTUSERDATA)
00202         goto cache_miss;
00203 
00204     ti = (const TypeInfo*) lua_touserdata(L, -1);
00205     goto out;
00206 
00207  cache_miss:
00208     lua_pop(L, 1); /* pop the nil */
00209     ti = types::TypeInfoRepository::Instance()->type(name);
00210     if (ti) { // only save if type exists !
00211         lua_pushstring(L, name);
00212         lua_pushlightuserdata(L, (void*) ti);
00213         lua_rawset(L, -3);
00214     }
00215  out:
00216     /* everyone happy! */
00217     lua_settop(L, top);
00218     return ti;
00219 #endif /* TYPEINFO_CACHING */
00220 }
00221 
00222 /* helper, check if two type names are alias to the same TypeInfo */
00223 static bool __typenames_cmp(lua_State *L, const char* type1, const char* type2)
00224 {
00225     const types::TypeInfo *ti1 = ti_lookup(L, type1);
00226     const types::TypeInfo *ti2 = ti_lookup(L, type2);
00227     return ti1 == ti2;
00228 }
00229 
00230 static bool __typenames_cmp(lua_State *L, const types::TypeInfo *ti1, const char* type2)
00231 {
00232     const types::TypeInfo *ti2 = ti_lookup(L, type2);
00233     return ti1 == ti2;
00234 }
00235 
00236 /* helper, check if a dsb is of type type. Works also if dsb is known
00237    under an alias of type */
00238 static bool Variable_is_a(lua_State *L, const types::TypeInfo *ti1, const char* type)
00239 {
00240     const types::TypeInfo *ti2 = ti_lookup(L, type);
00241     return ti1 == ti2;
00242 }
00243 
00244 /* helper, check if a variable is basic, that is _tolua will succeed */
00245 static bool __Variable_isbasic(lua_State *L, DataSourceBase::shared_ptr &dsb)
00246 {
00247     const types::TypeInfo *ti = dsb->getTypeInfo();
00248 
00249     if ( Variable_is_a(L, ti, "bool") ||
00250          Variable_is_a(L, ti, "double") ||
00251          Variable_is_a(L, ti, "float") ||
00252          Variable_is_a(L, ti, "uint") ||
00253          Variable_is_a(L, ti, "int") ||
00254          Variable_is_a(L, ti, "long") ||
00255          Variable_is_a(L, ti, "char") ||
00256          Variable_is_a(L, ti, "uint8") || Variable_is_a(L, ti, "int8") ||
00257          Variable_is_a(L, ti, "uint16") || Variable_is_a(L, ti, "int16") ||
00258          Variable_is_a(L, ti, "uint32") || Variable_is_a(L, ti, "int32") ||
00259          Variable_is_a(L, ti, "uint64") || Variable_is_a(L, ti, "int64") ||
00260          Variable_is_a(L, ti, "string") ||
00261          Variable_is_a(L, ti, "void"))
00262         return true;
00263     else
00264         return false;
00265 }
00266 
00267 static int Variable_isbasic(lua_State *L)
00268 {
00269     DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
00270     lua_pushboolean(L, __Variable_isbasic(L, dsb));
00271     return 1;
00272 }
00273 
00274 
00275 /*
00276  * converts a DataSourceBase to the corresponding Lua value and pushes
00277  * that on the stack.
00278  */
00279 static int __Variable_tolua(lua_State *L, DataSourceBase::shared_ptr dsb)
00280 {
00281     DataSourceBase *ds = dsb.get();
00282     const types::TypeInfo* ti = dsb->getTypeInfo();
00283     assert(ds);
00284 
00285     if(Variable_is_a(L, ti, "bool")) { // bool
00286         DataSource<bool>* dsb = DataSource<bool>::narrow(ds);
00287         if(dsb) lua_pushboolean(L, dsb->get());
00288         else goto out_nodsb;
00289     } else if (Variable_is_a(L, ti, "float")) { // float
00290         DataSource<float>* dsb = DataSource<float>::narrow(ds);
00291         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00292         else goto out_nodsb;
00293     } else if (Variable_is_a(L, ti, "double")) { // double
00294         DataSource<double>* dsb = DataSource<double>::narrow(ds);
00295         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00296         else goto out_nodsb;
00297     } else if (Variable_is_a(L, ti, "uint8")) { // uint8_t
00298         DataSource<uint8_t>* dsb = DataSource<uint8_t>::narrow(ds);
00299         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00300         else goto out_nodsb;
00301     } else if (Variable_is_a(L, ti, "int8")) { // int8_t
00302         DataSource<int8_t>* dsb = DataSource<int8_t>::narrow(ds);
00303         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00304         else goto out_nodsb;
00305     } else if (Variable_is_a(L, ti, "uint16")) { // uint16_t
00306         DataSource<uint16_t>* dsb = DataSource<uint16_t>::narrow(ds);
00307         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00308         else goto out_nodsb;
00309     } else if (Variable_is_a(L, ti, "int16")) { // int16_t
00310         DataSource<int16_t>* dsb = DataSource<int16_t>::narrow(ds);
00311         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00312         else goto out_nodsb;
00313     } else if (Variable_is_a(L, ti, "uint32")) { // uint32_t
00314         DataSource<uint32_t>* dsb = DataSource<uint32_t>::narrow(ds);
00315         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00316         else goto out_nodsb;
00317     } else if (Variable_is_a(L, ti, "int32")) { // int32_t
00318         DataSource<int32_t>* dsb = DataSource<int32_t>::narrow(ds);
00319         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00320         else goto out_nodsb;
00321     } else if (Variable_is_a(L, ti, "uint64")) { // uint64_t
00322         DataSource<uint64_t>* dsb = DataSource<uint64_t>::narrow(ds);
00323         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00324         else goto out_nodsb;
00325     } else if (Variable_is_a(L, ti, "int64")) { // int64_t
00326         DataSource<int64_t>* dsb = DataSource<int64_t>::narrow(ds);
00327         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00328         else goto out_nodsb;
00329     } else if (Variable_is_a(L, ti, "uint")) { // uint
00330         DataSource<unsigned int>* dsb = DataSource<unsigned int>::narrow(ds);
00331         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00332         else goto out_nodsb;
00333     } else if (Variable_is_a(L, ti, "long")) { //long
00334         DataSource<long>* dsb = DataSource<long>::narrow(ds);
00335         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00336         else goto out_nodsb;
00337     } else if (Variable_is_a(L, ti, "int")) { // int
00338         DataSource<int>* dsb = DataSource<int>::narrow(ds);
00339         if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
00340         else goto out_nodsb;
00341     } else if (Variable_is_a(L, ti, "char")) { // char
00342         DataSource<char>* dsb = DataSource<char>::narrow(ds);
00343         char c = dsb->get();
00344         if(dsb) lua_pushlstring(L, &c, 1);
00345         else goto out_nodsb;
00346     } else if (Variable_is_a(L, ti, "string")) { //string
00347         DataSource<std::string>* dsb = DataSource<std::string>::narrow(ds);
00348         if(dsb) lua_pushlstring(L, dsb->get().c_str(), dsb->get().size());
00349         else goto out_nodsb;
00350     } else if (Variable_is_a(L, ti, "void")) {
00351         DataSource<void>* dsb = DataSource<void>::narrow(ds);
00352         if(dsb) lua_pushnil(L);
00353         else goto out_nodsb;
00354     } else {
00355         goto out_conv_err;
00356     }
00357 
00358     /* all ok */
00359     return 1;
00360 
00361  out_conv_err:
00362     luaL_error(L, "Variable.tolua: can't convert type %s", dsb->getTypeName().c_str());
00363     return 0;
00364 
00365  out_nodsb:
00366     luaL_error(L, "Variable.tolua: narrow failed for %s Variable", dsb->getTypeName().c_str());
00367     return 0;
00368 }
00369 
00370 static int Variable_tolua(lua_State *L)
00371 {
00372     DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
00373     return __Variable_tolua(L, dsb);
00374 }
00375 
00376 /* Function takes a DSB, that is also expected on the top of the
00377  * stack. If the DSB is basic, it replaces the dsb with the
00378  * corresponding Lua value. Otherwise it does nothing, leaving the DSB
00379  * on the top of the stack.
00380  */
00381 static void Variable_coerce(lua_State *L, DataSourceBase::shared_ptr dsb)
00382 {
00383     if (__Variable_isbasic(L, dsb)) {
00384         lua_pop(L, 1);
00385         __Variable_tolua(L, dsb);
00386     }
00387 }
00388 
00389 /* this function takes a dsb and either pushes it as a Lua type if the
00390  * dsb is basic or otherwise as at Variable
00391  */
00392 static void Variable_push_coerce(lua_State *L, DataSourceBase::shared_ptr dsb)
00393 {
00394     if (__Variable_isbasic(L, dsb))
00395         __Variable_tolua(L, dsb);
00396     else
00397         luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(dsb);
00398 
00399 }
00400 
00401 static int Variable_getTypes(lua_State *L)
00402 {
00403     push_vect_str(L, Types()->getTypes());
00404     return 1;
00405 }
00406 
00407 static int Variable_getMemberNames(lua_State *L)
00408 {
00409     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00410     push_vect_str(L, (*dsbp)->getMemberNames());
00411     return 1;
00412 }
00413 
00414 static int Variable_tolightuserdata(lua_State *L)
00415 {
00416     DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
00417     lua_pushlightuserdata(L, dsb->getRawPointer());
00418     return 1;
00419 }
00420 
00421 
00422 /* caching of DSB members
00423  * lookup of DSB using getMember and caches result.
00424  * returns DSB (or nil if lookup fails) on top of stack.
00425  */
00426 static DataSourceBase::shared_ptr lookup_member(lua_State *L, DataSourceBase::shared_ptr parent, const char* mem)
00427 {
00428     DataSourceBase *varptr;
00429     DataSourceBase::shared_ptr *dsbp;
00430     DataSourceBase::shared_ptr memdsb;
00431     int top = lua_gettop(L);
00432 
00433     varptr = parent.get();
00434 
00435     lua_pushlightuserdata(L, (void*) varptr);
00436     lua_rawget(L, LUA_REGISTRYINDEX);
00437 
00438     if(lua_type(L, -1) == LUA_TNIL)
00439         goto cache_miss;
00440 
00441     lua_pushstring(L, mem);
00442     lua_rawget(L, -2);
00443 
00444     if ((dsbp = luaM_testudata_mt(L, -1, "Variable", DataSourceBase::shared_ptr)) != NULL) {
00445         memdsb=*dsbp;
00446         goto out;
00447     }
00448 
00449     lua_pop(L, 1); /* pop nil from table lookup */
00450 
00451  cache_miss:
00452     /* slowpath */
00453     memdsb = parent->getMember(mem);
00454 
00455     if(memdsb == 0)
00456         goto out;
00457 
00458     /* if nil is on top of stack, we have to create a new table */
00459     if(lua_type(L, -1) == LUA_TNIL) {
00460         lua_newtable(L);                /* member lookup tab for this Variable */
00461         lua_pushlightuserdata(L, (void*) varptr); /* index for REGISTRY */
00462         lua_pushvalue(L, -2);           /* duplicates table */
00463         lua_rawset(L, LUA_REGISTRYINDEX);   /* REG[varptr]=newtab */
00464     }
00465 
00466     /* cache dsb in table */
00467     lua_pushstring(L, mem);
00468     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(memdsb);
00469     lua_rawset(L, -3);          /* newtab[mem]=memdsb, top is newtab */
00470     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(memdsb);
00471 
00472  out:
00473     lua_replace(L, top+1); // make new var top of stack
00474     lua_settop(L, top+1);
00475 
00476     return memdsb;
00477 }
00478 
00479 /* set reg[varptr] to nil so table will be garbage collected */
00480 static void cache_clear(lua_State *L, DataSourceBase *varptr)
00481 {
00482     lua_pushlightuserdata(L, (void*) varptr);
00483     lua_pushnil(L);
00484     lua_rawset(L, LUA_REGISTRYINDEX);
00485 }
00486 
00487 static int Variable_getMember(lua_State *L)
00488 {
00489     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00490     DataSourceBase::shared_ptr memdsb;
00491     const char *mem = luaL_checkstring(L, 2);
00492 
00493     if ((memdsb = lookup_member(L, *dsbp, mem)) == 0)
00494         luaL_error(L, "Variable.getMember: indexing failed, no member %s", mem);
00495     else
00496         Variable_coerce(L, memdsb);
00497 
00498     return 1;
00499 }
00500 
00501 static int Variable_getMemberRaw(lua_State *L)
00502 {
00503     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00504     DataSourceBase::shared_ptr memdsb;
00505     const char *mem = luaL_checkstring(L, 2);
00506 
00507     if ((memdsb = lookup_member(L, (*dsbp), mem)) == 0)
00508         luaL_error(L, "Variable.getMemberRaw: indexing failed, no member %s", mem);
00509 
00510     /* else: Variable is already on top of stack */
00511 
00512     return 1;
00513 }
00514 
00515 static int Variable_update(lua_State *L)
00516 {
00517     int ret;
00518     DataSourceBase::shared_ptr dsb;
00519     DataSourceBase::shared_ptr *dsbp;
00520     DataSourceBase::shared_ptr self = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
00521 
00522     if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
00523         dsb = *dsbp;
00524         ret = self->update(dsb.get());
00525         if (!ret) luaL_error(L, "Variable.assign: assignment failed");
00526     } else {
00527         Variable_fromlua(L, self, 2);
00528     }
00529 
00530     return 0;
00531 }
00532 
00533 /* create variable */
00534 static int Variable_create(lua_State *L)
00535 {
00536     const char *type;
00537     type = luaL_checkstring(L, 1);
00538 
00539     if(!strcmp(type, "void"))
00540         luaL_error(L, "Variable.new: can't create void variable");
00541 
00542     TypeInfo* ti = Types()->type(type);
00543 
00544     if(ti==0)
00545         luaL_error(L, "Variable.new: unknown type %s", type);
00546 
00547     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(ti->buildValue());
00548     return 1;
00549 }
00550 
00551 #define CONVERT_TO_NUMBER(CTGT) \
00552     lua_Number x; \
00553     if (luatype == LUA_TNUMBER) x = lua_tonumber(L, valind); \
00554     else goto out_conv_err; \
00555     AssignableDataSource<CTGT> *ads = ValueDataSource<CTGT>::narrow(dsb.get()); \
00556     if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to %s.", #CTGT ); \
00557     ads->set((CTGT) x)\
00558 
00559 /* Try to convert the Lua value on stack at valind to given DSB
00560  * if it returns, evertthing is ok */
00561 static void Variable_fromlua(lua_State *L, DataSourceBase::shared_ptr& dsb, int valind)
00562 {
00563     const types::TypeInfo* ti = dsb->getTypeInfo();
00564 
00565     luaL_checkany(L, valind);
00566     int luatype = lua_type(L, valind);  /* type of lua variable */
00567 
00568     if(__typenames_cmp(L, ti, "bool")) {
00569         lua_Number x;
00570         if(luatype == LUA_TBOOLEAN)
00571             x = (lua_Number) lua_toboolean(L, valind);
00572         else if (luatype == LUA_TNUMBER)
00573             x = lua_tonumber(L, valind);
00574         else
00575             goto out_conv_err;
00576 
00577         AssignableDataSource<bool> *ads = ValueDataSource<bool>::narrow(dsb.get());
00578         if (ads == NULL)
00579             luaL_error(L, "Variable_fromlua: failed to narrow target dsb to bool");
00580         ads->set((bool) x);
00581     }
00582     else if (__typenames_cmp(L, ti, "uint"))   { CONVERT_TO_NUMBER(unsigned int); }
00583     else if (__typenames_cmp(L, ti, "int"))    { CONVERT_TO_NUMBER(int); }
00584     else if (__typenames_cmp(L, ti, "double")) { CONVERT_TO_NUMBER(double); }
00585     else if (__typenames_cmp(L, ti, "long"))   { CONVERT_TO_NUMBER(double); }
00586     else if (__typenames_cmp(L, ti, "uint8"))  { CONVERT_TO_NUMBER(uint8_t); }
00587     else if (__typenames_cmp(L, ti, "int8"))   { CONVERT_TO_NUMBER(int8_t); }
00588     else if (__typenames_cmp(L, ti, "uint16")) { CONVERT_TO_NUMBER(uint16_t); }
00589     else if (__typenames_cmp(L, ti, "int16"))  { CONVERT_TO_NUMBER(int16_t); }
00590     else if (__typenames_cmp(L, ti, "uint32")) { CONVERT_TO_NUMBER(uint32_t); }
00591     else if (__typenames_cmp(L, ti, "int32"))  { CONVERT_TO_NUMBER(int32_t); }
00592     else if (__typenames_cmp(L, ti, "uint64")) { CONVERT_TO_NUMBER(uint64_t); }
00593     else if (__typenames_cmp(L, ti, "int64"))  { CONVERT_TO_NUMBER(int64_t); }
00594     else if (__typenames_cmp(L, ti, "float"))  { CONVERT_TO_NUMBER(float); }
00595 
00596     else if (__typenames_cmp(L, ti, "char")) {
00597         const char *x;
00598         size_t l;
00599         if (luatype == LUA_TSTRING) x = lua_tolstring(L, valind, &l);
00600         else goto out_conv_err;
00601         AssignableDataSource<char> *ads = ValueDataSource<char>::narrow(dsb.get());
00602         if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to char");
00603         ads->set((char) x[0]);
00604 
00605     } else if (__typenames_cmp(L, ti, "string")) {
00606         const char *x;
00607         if (luatype == LUA_TSTRING) x = lua_tostring(L, valind);
00608         else goto out_conv_err;
00609         AssignableDataSource<std::string> *ads = ValueDataSource<std::string>::narrow(dsb.get());
00610         if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to std::string");
00611         ads->set((std::string) x);
00612 
00613     } else {
00614         goto out_conv_err;
00615     }
00616 
00617     /* everybody happy */
00618     return;
00619 
00620  out_conv_err:
00621     luaL_error(L, "__lua_todsb: can't convert lua %s to %s variable",
00622            lua_typename(L, luatype), ti->getTypeName().c_str());
00623     return;
00624 }
00625 
00626 /* Create a DSB of RTT ti from the Lua value at stack[valind]
00627  * This one will create a dsb - NRT!*/
00628 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const types::TypeInfo *ti, int valind)
00629 {
00630     DataSourceBase::shared_ptr dsb = ti->buildValue();
00631     Variable_fromlua(L, dsb, valind);
00632     return dsb;
00633 }
00634 
00635 /* Create a DSB of RTT type 'type' from the Lua value at stack[valind]
00636  * This one will create a dsb - NRT!
00637  * This one should be avoided, to reduce needless name-ti lookups.
00638  * preferred variant is the one taking TypeInfo * as second arg */
00639 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const char* type, int valind)
00640 {
00641     const types::TypeInfo* ti = ti_lookup(L, type);
00642     if(!ti) luaL_error(L, "Variable_fromlua: %s is not a known type. Load typekit?", type);
00643     return Variable_fromlua(L, ti, valind);
00644 }
00645 
00646 
00647 static int Variable_create_ival(lua_State *L, int typeind, int valind)
00648 {
00649     DataSourceBase::shared_ptr dsb;
00650     luaL_checkany(L, valind);
00651     const char* type = luaL_checkstring(L, typeind);    /* target dsb type */
00652     dsb = Variable_fromlua(L, type, valind);
00653     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(dsb);
00654     return 1;
00655 }
00656 
00657 static int Variable_new(lua_State *L)
00658 {
00659     int argc = lua_gettop(L);
00660     if(argc == 1)
00661         return Variable_create(L);
00662     else if(argc == 2)
00663         return Variable_create_ival(L, 1, 2);
00664     else
00665         luaL_error(L, "Variable.new: invalid number of args");
00666 
00667     return 0;
00668 }
00669 
00670 static int Variable_toString(lua_State *L)
00671 {
00672     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00673     lua_pushstring(L, ((*dsbp)->toString()).c_str());
00674     return 1;
00675 }
00676 
00677 static int Variable_getType(lua_State *L)
00678 {
00679     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00680     lua_pushstring(L, (*dsbp)->getType().c_str());
00681     return 1;
00682 }
00683 
00684 static int Variable_getTypeIdName(lua_State *L)
00685 {
00686     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00687     lua_pushstring(L, (*dsbp)->getTypeInfo()->getTypeIdName());
00688     return 1;
00689 }
00690 
00691 static int Variable_getTypeName(lua_State *L)
00692 {
00693     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00694     lua_pushstring(L, (*dsbp)->getTypeName().c_str());
00695     return 1;
00696 }
00697 
00698 static int Variable_resize(lua_State *L)
00699 {
00700     int size;
00701     DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
00702     size = luaL_checknumber(L, 2);
00703     const TypeInfo *ti = (*dsbp)->getTypeInfo();
00704     lua_pushboolean(L, ti->resize(*dsbp, size));
00705     return 1;
00706 }
00707 
00708 
00709 /*
00710  * Operators
00711  */
00712 static int Variable_unm(lua_State *L)
00713 {
00714     types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance();
00715     DataSourceBase::shared_ptr arg = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
00716     DataSourceBase::shared_ptr res = opreg->applyUnary("-", arg.get());
00717     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res);
00718     return 1;
00719 }
00720 
00721 
00722 /* don't try this at home */
00723 #define gen_opmet(name, op)                 \
00724 static int name(lua_State *L)                   \
00725 {                               \
00726     DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); \
00727     DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)); \
00728     types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); \
00729     DataSourceBase *res = opreg->applyBinary(#op, arg1.get(), arg2.get()); \
00730     if(res == 0)                            \
00731         luaL_error(L , "%s (operator %s) failed", #name, #op);  \
00732     res->evaluate();                        \
00733     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res); \
00734     return 1;                           \
00735 }                                   \
00736 
00737 gen_opmet(Variable_add, +)
00738 gen_opmet(Variable_sub, -)
00739 gen_opmet(Variable_mul, *)
00740 gen_opmet(Variable_div, /)
00741 gen_opmet(Variable_mod, %)
00742 gen_opmet(Variable_pow, ^)
00743 
00744 /* these flavors convert the boolean return dsb to a lua bool */
00745 #define gen_opmet_bool(name, op)                \
00746 static int name(lua_State *L)                   \
00747 {                               \
00748     DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); \
00749     DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)); \
00750     types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); \
00751     DataSourceBase *res = opreg->applyBinary(#op, arg1.get(), arg2.get()); \
00752     if(res == 0)                            \
00753         luaL_error(L , "%s (operator %s) failed", #name, #op);  \
00754     res->evaluate();                        \
00755     return __Variable_tolua(L, res);                \
00756 }                                   \
00757 
00758 gen_opmet_bool(Variable_eq, ==)
00759 gen_opmet_bool(Variable_lt, <)
00760 gen_opmet_bool(Variable_le, <=)
00761 
00762 static int Variable_opBinary(lua_State *L)
00763 {
00764     types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance();
00765     const char *op = luaL_checkstring(L, 1);
00766     DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr));
00767     DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 3, "Variable", DataSourceBase::shared_ptr));
00768     DataSourceBase *res;
00769 
00770     res = opreg->applyBinary(op, arg1.get(), arg2.get());
00771     if(res == 0)
00772         luaL_error(L , "Variable.opBinary '%s' not applicable to args", op);
00773 
00774     res->evaluate();
00775 
00776     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res);
00777     return 1;
00778 }
00779 
00780 /*
00781  * this is a dispatcher which checks if the key is a method, otherwise
00782  * calls get for looking up the field. Inspired by
00783  * http://lua-users.org/wiki/ObjectProperties
00784  */
00785 static int Variable_index(lua_State *L)
00786 {
00787     const char* key = luaL_checkstring(L, 2);
00788 
00789     lua_getmetatable(L, 1);
00790     lua_getfield(L, -1, key);
00791 
00792     /* Either key is name of a method in the metatable */
00793     if(!lua_isnil(L, -1))
00794         return 1;
00795 
00796     /* ... or its a field access, so recall as self.get(self, value). */
00797     lua_settop(L, 2);
00798     return Variable_getMember(L);
00799 }
00800 
00801 static int Variable_newindex(lua_State *L)
00802 {
00803     DataSourceBase::shared_ptr *newvalp;
00804     DataSourceBase::shared_ptr newval;
00805     DataSourceBase::shared_ptr parent = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
00806     const char* mem = luaL_checkstring(L, 2);
00807 
00808     /* get dsb to be updated: we need its type before get-or-create'ing arg3 */
00809     types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance();
00810     DataSourceBase::shared_ptr curval;
00811 
00812     if ((curval = lookup_member(L, parent, mem)) == 0)
00813         luaL_error(L, "Variable.newindex: indexing failed, no member %s", mem);
00814 
00815 
00816     /* assigning a DSB */
00817     if ((newvalp = luaM_testudata_mt(L, 3, "Variable", DataSourceBase::shared_ptr)) != NULL) {
00818         newval = *newvalp;
00819         if(!curval->update(newval.get())) {
00820             luaL_error(L, "Variable.newindex: failed to assign %s to member %s of type %s",
00821                    newval->getType().c_str(), mem, curval->getType().c_str());
00822         }
00823     } else /* assigning basic type */
00824         Variable_fromlua(L, curval, 3);
00825     return 1;
00826 }
00827 
00828 // Why doesn't the following work:
00829 // static int Variable_gc(lua_State *L)
00830 // {
00831 //  DataSourceBase::shared_ptr *dsbp = (DataSourceBase::shared_ptr*) lua_touserdata(L, 1);
00832 //  cache_clear(L, dsbp->get());
00833 //  dsbp->~DataSourceBase::shared_ptr();
00834 //  return 0;
00835 // }
00836 
00837 template<typename T>
00838 int VariableGC(lua_State* L)
00839 {
00840     T* dsbp = (T*) lua_touserdata(L, 1);
00841     cache_clear(L, dsbp->get());
00842     reinterpret_cast<T*>(dsbp)->~T();
00843     return 0;
00844 }
00845 
00846 
00847 static const struct luaL_Reg Variable_f [] = {
00848     { "new", Variable_new },
00849     { "tolua", Variable_tolua },
00850     { "isbasic", Variable_isbasic },
00851     { "toString", Variable_toString },
00852     { "getTypes", Variable_getTypes },
00853     { "getType", Variable_getType },
00854     { "getTypeName", Variable_getTypeName },
00855     { "getTypeIdName", Variable_getTypeIdName },
00856     { "getMemberNames", Variable_getMemberNames },
00857     { "getMember", Variable_getMember },
00858     { "getMemberRaw", Variable_getMemberRaw },
00859     { "tolud", Variable_tolightuserdata },
00860     { "resize", Variable_resize },
00861     { "opBinary", Variable_opBinary },
00862     { "assign", Variable_update }, /* assign seems a better name than update */
00863     { "unm", Variable_unm },
00864     { "add", Variable_add },
00865     { "sub", Variable_sub },
00866     { "mul", Variable_mul },
00867     { "div", Variable_div },
00868     { "mod", Variable_mod },
00869     { "pow", Variable_pow },
00870     { "eq", Variable_eq },
00871     { "lt", Variable_lt },
00872     { "le", Variable_le },
00873     { NULL, NULL}
00874 };
00875 
00876 static const struct luaL_Reg Variable_m [] = {
00877     { "tolua", Variable_tolua },
00878     { "isbasic", Variable_isbasic },
00879     { "toString", Variable_toString },
00880     { "getType", Variable_getType },
00881     { "getTypeName", Variable_getTypeName },
00882     { "getTypeIdName", Variable_getTypeIdName },
00883     { "getMemberNames", Variable_getMemberNames },
00884     { "getMember", Variable_getMember },
00885     { "getMemberRaw", Variable_getMemberRaw },
00886     { "tolud", Variable_tolightuserdata },
00887     { "resize", Variable_resize },
00888     { "opBinary", Variable_opBinary },
00889     { "assign", Variable_update }, /* assign seems a better name than update */
00890     { "__unm", Variable_unm },
00891     { "__add", Variable_add },
00892     { "__sub", Variable_sub },
00893     { "__mul", Variable_mul },
00894     { "__div", Variable_div },
00895     { "__mod", Variable_mod },
00896     { "__pow", Variable_pow },
00897     { "__eq", Variable_eq },
00898     { "__lt", Variable_lt },
00899     { "__le", Variable_le },
00900     { "__index", Variable_index },
00901     { "__newindex", Variable_newindex },
00902     // { "__gc", GCMethod<DataSourceBase::shared_ptr> },
00903     // {"__gc", Variable_gc},
00904     {"__gc", VariableGC<DataSourceBase::shared_ptr> },
00905     { NULL, NULL}
00906 };
00907 
00908 
00909 /***************************************************************
00910  * Property (boxed)
00911  ***************************************************************/
00912 
00913 gen_push_bxptr(Property_push, "Property", PropertyBase)
00914 
00915 static int Property_new(lua_State *L)
00916 {
00917     const char *type, *name, *desc;
00918     PropertyBase *pb;
00919     int argc = lua_gettop(L);
00920     type = luaL_checkstring(L, 1);
00921 
00922     /* name and description are optional */
00923     name = (argc > 1) ? luaL_checkstring(L, 2) : "";
00924     desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
00925 
00926     types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
00927 
00928     if(!ti)
00929         luaL_error(L, "Property.new: unknown type %s", type);
00930 
00931     pb =  ti->buildProperty(name, desc);
00932     Property_push(L, pb);
00933     return 1;
00934 }
00935 
00936 static int Property_get(lua_State *L)
00937 {
00938     PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
00939     Variable_push_coerce(L, pb->getDataSource());
00940     return 1;
00941 }
00942 
00943 static int Property_getRaw(lua_State *L)
00944 {
00945     PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
00946     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(pb->getDataSource());
00947     return 1;
00948 }
00949 
00950 static int Property_set(lua_State *L)
00951 {
00952     DataSourceBase::shared_ptr newdsb;
00953     DataSourceBase::shared_ptr *newdsbp;
00954     DataSourceBase::shared_ptr propdsb;
00955     PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
00956     propdsb = pb->getDataSource();
00957 
00958     /* assigning a DSB */
00959     if ((newdsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
00960         newdsb = *newdsbp;
00961         if(!propdsb->update(newdsb.get()))
00962             luaL_error(L, "Property.set: failed to assign type %s to type %s",
00963                    newdsb->getType().c_str(), propdsb->getType().c_str());
00964     } else { /* assigning a Lua value */
00965         Variable_fromlua(L, propdsb, 2);
00966     }
00967     return 1;
00968 }
00969 
00970 static int Property_info(lua_State *L)
00971 {
00972     PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
00973     lua_newtable(L);
00974     lua_pushstring(L, "name"); lua_pushstring(L, pb->getName().c_str()); lua_rawset(L, -3);
00975     lua_pushstring(L, "desc"); lua_pushstring(L, pb->getDescription().c_str()); lua_rawset(L, -3);
00976     lua_pushstring(L, "type"); lua_pushstring(L, pb->getType().c_str()); lua_rawset(L, -3);
00977     return 1;
00978 }
00979 
00980 #if NOT_USED_YET
00981 /*
00982  * Race condition if we collect properties: if we add this property to
00983  * a TC and our life ends before that of the TC, the property will be
00984  * deleted before the TaskContext.
00985  */
00986 static int Property_gc(lua_State *L)
00987 {
00988     PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
00989     delete pb;
00990     return 0;
00991 }
00992 #endif
00993 
00994 /* only explicit destruction allowed */
00995 static int Property_del(lua_State *L)
00996 {
00997     PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
00998     delete pb;
00999 
01000     /* this prevents calling rtt methods which would cause a crash */
01001     luaL_getmetatable(L, "__dead__");
01002     lua_setmetatable(L, -2);
01003     return 0;
01004 }
01005 
01006 /* indexability of properties */
01007 /*
01008  * this is a dispatcher which checks if the key is a method, otherwise
01009  * calls get for looking up the field. Inspired by
01010  * http://lua-users.org/wiki/ObjectProperties
01011  */
01012 static int Property_index(lua_State *L)
01013 {
01014     const char* key = luaL_checkstring(L, 2);
01015 
01016     lua_getmetatable(L, 1);
01017     lua_getfield(L, -1, key); /* this actually calls the method */
01018 
01019     /* Either key is name of a method in the metatable */
01020     if(!lua_isnil(L, -1))
01021         return 1;
01022 
01023     lua_settop(L, 2);   /* reset stack */
01024     Property_get(L);    /* pushes property var */
01025     lua_replace(L, 1);  /* replace prop with var */
01026     return Variable_index(L);
01027 }
01028 
01029 static int Property_newindex(lua_State *L)
01030 {
01031     Property_get(L);
01032     lua_replace(L, 1);
01033     return Variable_newindex(L);
01034 }
01035 
01036 static const struct luaL_Reg Property_f [] = {
01037     {"new", Property_new },
01038     {"get", Property_get },
01039     {"getRaw", Property_getRaw },
01040     {"set", Property_set },
01041     {"info", Property_info },
01042     {"delete", Property_del },
01043     {NULL, NULL}
01044 };
01045 
01046 static const struct luaL_Reg Property_m [] = {
01047     {"get", Property_get },
01048     {"getRaw", Property_getRaw },
01049     {"set", Property_set },
01050     {"info", Property_info },
01051     // todo: shall we or not? s.o. {"__gc", Property_gc },
01052     {"delete", Property_del },
01053     {"__index", Property_index },
01054     {"__newindex", Property_newindex },
01055     {NULL, NULL}
01056 };
01057 
01058 /***************************************************************
01059  * Attribute (boxed)
01060  ***************************************************************/
01061 
01062 gen_push_bxptr(Attribute_push, "Attribute", AttributeBase)
01063 
01064 static int Attribute_new(lua_State *L)
01065 {
01066     const char *type, *name;
01067     AttributeBase *pb;
01068     int argc = lua_gettop(L);
01069     type = luaL_checkstring(L, 1);
01070 
01071     /* name and description are optional */
01072     name = (argc > 1) ? luaL_checkstring(L, 2) : "";
01073 
01074     types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
01075 
01076     if(!ti)
01077         luaL_error(L, "Attribute.new: unknown type %s", type);
01078 
01079     pb =  ti->buildAttribute(name);
01080     Attribute_push(L, pb);
01081     return 1;
01082 }
01083 
01084 static int Attribute_get(lua_State *L)
01085 {
01086     AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
01087     Variable_push_coerce(L, pb->getDataSource());
01088     return 1;
01089 }
01090 
01091 static int Attribute_getRaw(lua_State *L)
01092 {
01093     AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
01094     luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(pb->getDataSource());
01095     return 1;
01096 }
01097 
01098 static int Attribute_set(lua_State *L)
01099 {
01100     DataSourceBase::shared_ptr newdsb;
01101     DataSourceBase::shared_ptr *newdsbp;
01102     DataSourceBase::shared_ptr propdsb;
01103     AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
01104     propdsb = pb->getDataSource();
01105 
01106     /* assigning a DSB */
01107     if ((newdsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
01108         newdsb = *newdsbp;
01109         if(!propdsb->update(newdsb.get()))
01110             luaL_error(L, "Attribute.set: failed to assign type %s to type %s",
01111                    newdsb->getType().c_str(), propdsb->getType().c_str());
01112     } else { /* assigning a Lua value */
01113         Variable_fromlua(L, propdsb, 2);
01114     }
01115     return 1;
01116 }
01117 
01118 static int Attribute_info(lua_State *L)
01119 {
01120     AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
01121     lua_newtable(L);
01122     lua_pushstring(L, "name"); lua_pushstring(L, pb->getName().c_str()); lua_rawset(L, -3);
01123     lua_pushstring(L, "type"); lua_pushstring(L, pb->getDataSource()->getType().c_str()); lua_rawset(L, -3);
01124     return 1;
01125 }
01126 
01127 #if NOT_USED_YET
01128 /*
01129  * Race condition if we collect properties: if we add this attribute to
01130  * a TC and our life ends before that of the TC, the attribute will be
01131  * deleted before the TaskContext.
01132  */
01133 static int Attribute_gc(lua_State *L)
01134 {
01135     AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
01136     delete pb;
01137     return 0;
01138 }
01139 #endif
01140 
01141 
01142 /* only explicit destruction allowed */
01143 static int Attribute_del(lua_State *L)
01144 {
01145     AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
01146     delete pb;
01147 
01148     /* this prevents calling rtt methods which would cause a crash */
01149     luaL_getmetatable(L, "__dead__");
01150     lua_setmetatable(L, -2);
01151     return 0;
01152 }
01153 
01154 /* indexability of properties */
01155 /*
01156  * this is a dispatcher which checks if the key is a method, otherwise
01157  * calls get for looking up the field. Inspired by
01158  * http://lua-users.org/wiki/ObjectProperties
01159  */
01160 static int Attribute_index(lua_State *L)
01161 {
01162     const char* key = luaL_checkstring(L, 2);
01163 
01164     lua_getmetatable(L, 1);
01165     lua_getfield(L, -1, key); /* this actually calls the method */
01166 
01167     /* Either key is name of a method in the metatable */
01168     if(!lua_isnil(L, -1))
01169         return 1;
01170 
01171     lua_settop(L, 2);   /* reset stack */
01172     Attribute_get(L);   /* pushes attribute var */
01173     lua_replace(L, 1);  /* replace prop with var */
01174     return Variable_index(L);
01175 }
01176 
01177 static int Attribute_newindex(lua_State *L)
01178 {
01179     Attribute_get(L);
01180     lua_replace(L, 1);
01181     return Variable_newindex(L);
01182 }
01183 
01184 static const struct luaL_Reg Attribute_f [] = {
01185     {"new", Attribute_new },
01186     {"get", Attribute_get },
01187     {"getRaw", Attribute_getRaw },
01188     {"set", Attribute_set },
01189     {"info", Attribute_info },
01190     {"delete", Attribute_del },
01191     {NULL, NULL}
01192 };
01193 
01194 static const struct luaL_Reg Attribute_m [] = {
01195     {"get", Attribute_get },
01196     {"getRaw", Attribute_getRaw },
01197     {"set", Attribute_set },
01198     {"info", Attribute_info },
01199     // todo: shall we or not? s.o. {"__gc", Attribute_gc },
01200     {"delete", Attribute_del },
01201     {"__index", Attribute_index },
01202     {"__newindex", Attribute_newindex },
01203     {NULL, NULL}
01204 };
01205 
01206 /***************************************************************
01207  * Ports (boxed)
01208  ***************************************************************/
01209 
01210 /* both input or output */
01211 static int Port_info(lua_State *L)
01212 {
01213     int arg_type;
01214     const char* port_type = NULL;
01215     PortInterface **pip;
01216     PortInterface *pi = NULL;
01217 
01218     if((pip = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
01219         pi = *pip;
01220         port_type = "in";
01221     } else if((pip = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
01222         pi = *pip;
01223         port_type = "out";
01224     }
01225     else {
01226         arg_type = lua_type(L, 1);
01227         luaL_error(L, "Port.info: invalid argument, expected Port, got %s",
01228                lua_typename(L, arg_type));
01229     }
01230 
01231     lua_newtable(L);
01232     lua_pushstring(L, "name"); lua_pushstring(L, pi->getName().c_str()); lua_rawset(L, -3);
01233     lua_pushstring(L, "desc"); lua_pushstring(L, pi->getDescription().c_str()); lua_rawset(L, -3);
01234     lua_pushstring(L, "connected"); lua_pushboolean(L, pi->connected()); lua_rawset(L, -3);
01235     lua_pushstring(L, "isLocal"); lua_pushboolean(L, pi->isLocal()); lua_rawset(L, -3);
01236     lua_pushstring(L, "type"); lua_pushstring(L, pi->getTypeInfo()->getTypeName().c_str()); lua_rawset(L, -3);
01237     lua_pushstring(L, "porttype"); lua_pushstring(L, port_type); lua_rawset(L, -3);
01238 
01239     return 1;
01240 }
01241 
01242 static int Port_connect(lua_State *L)
01243 {
01244     int arg_type, ret;
01245     PortInterface **pip1, **pip2;
01246     PortInterface *pi1 = NULL;
01247     PortInterface *pi2 = NULL;
01248     ConnPolicy **cpp;
01249     ConnPolicy *cp = NULL;
01250 
01251     if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
01252         pi1= *pip1;
01253     } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
01254         pi1= *pip1;
01255     }
01256     else {
01257         arg_type = lua_type(L, 1);
01258         luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s",
01259                lua_typename(L, arg_type));
01260     }
01261     if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) {
01262         pi2= *pip2;
01263     } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) {
01264         pi2= *pip2;
01265     }
01266     else {
01267         arg_type = lua_type(L, 2);
01268         luaL_error(L, "Port.connect: invalid argument 2, expected Port, got %s",
01269                lua_typename(L, arg_type));
01270     }
01271 
01272     if((cpp = (ConnPolicy**) luaL_testudata(L, 3, "ConnPolicy")) != NULL) {
01273         cp=*cpp;
01274     }
01275 
01276     if ( cp )
01277         ret = pi1->connectTo(pi2, *cp);
01278     else
01279         ret = pi1->connectTo(pi2);
01280 
01281     lua_pushboolean(L, ret);
01282 
01283     return 1;
01284 }
01285 
01286 static int Port_disconnect(lua_State *L)
01287 {
01288     int arg_type, ret;
01289     PortInterface **pip1, **pip2;
01290     PortInterface *pi1 = NULL;
01291     PortInterface *pi2 = NULL;
01292 
01293     if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
01294         pi1= *pip1;
01295     } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
01296         pi1= *pip1;
01297     }
01298     else {
01299         arg_type = lua_type(L, 1);
01300         luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s",
01301                lua_typename(L, arg_type));
01302     }
01303     if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) {
01304     pi2= *pip2;
01305     } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) {
01306     pi2= *pip2;
01307     }
01308 
01309     if (pi2 != NULL)
01310     ret = pi1->disconnect(pi2);
01311     else{
01312     pi1->disconnect();
01313     ret = 1;
01314     }
01315     lua_pushboolean(L, ret);
01316 
01317     return 1;
01318 }
01319 
01320 
01321 
01322 /* InputPort (boxed) */
01323 
01324 gen_push_bxptr(InputPort_push, "InputPort", InputPortInterface)
01325 
01326 static int InputPort_new(lua_State *L)
01327 {
01328     const char *type, *name, *desc;
01329     InputPortInterface* ipi;
01330     int argc = lua_gettop(L);
01331 
01332     type = luaL_checkstring(L, 1);
01333 
01334     /* name and description are optional */
01335     name = (argc > 1) ? luaL_checkstring(L, 2) : "";
01336     desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
01337 
01338     types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
01339     if(ti==0)
01340         luaL_error(L, "InputPort.new: unknown type %s", type);
01341 
01342     ipi = ti->inputPort(name);
01343 
01344     if(!ipi)
01345         luaL_error(L, "InputPort.new: creating port of type %s failed", type);
01346 
01347     ipi->doc(desc);
01348     InputPort_push(L, ipi);
01349     return 1;
01350 }
01351 
01352 static int InputPort_read(lua_State *L)
01353 {
01354     int ret = 1;
01355     InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
01356     DataSourceBase::shared_ptr dsb;
01357     DataSourceBase::shared_ptr *dsbp;
01358     FlowStatus fs;
01359 
01360     /* if we get don't get a DS to store the result, create one */
01361     if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL)
01362         dsb = *dsbp;
01363     else {
01364         dsb = ip->getTypeInfo()->buildValue();
01365         ret = 2;
01366     }
01367 
01368     fs = ip->read(dsb);
01369 
01370     if(fs == NoData) lua_pushstring(L, "NoData");
01371     else if (fs == NewData) lua_pushstring(L, "NewData");
01372     else if (fs == OldData) lua_pushstring(L, "OldData");
01373     else luaL_error(L, "InputPort.read: unknown FlowStatus returned");
01374 
01375     if(ret>1)
01376         Variable_push_coerce(L, dsb);
01377 
01378     return ret;
01379 }
01380 
01381 #ifdef NOT_USED_YET
01382 static int InputPort_gc(lua_State *L)
01383 {
01384     InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
01385     delete ip;
01386     return 0;
01387 }
01388 #endif
01389 
01390 /* only explicit destruction allowed */
01391 static int InputPort_del(lua_State *L)
01392 {
01393     InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
01394     delete ip;
01395 
01396     /* this prevents calling rtt methods which would cause a crash */
01397     luaL_getmetatable(L, "__dead__");
01398     lua_setmetatable(L, -2);
01399     return 0;
01400 }
01401 
01402 static const struct luaL_Reg InputPort_f [] = {
01403     {"new", InputPort_new },
01404     {"read", InputPort_read },
01405     {"info", Port_info },
01406     {"connect", Port_connect },
01407     {"disconnect", Port_disconnect },
01408     {"delete", InputPort_del },
01409     {NULL, NULL}
01410 };
01411 
01412 static const struct luaL_Reg InputPort_m [] = {
01413     {"read", InputPort_read },
01414     {"info", Port_info },
01415     {"delete", InputPort_del },
01416     {"connect", Port_connect },
01417     {"disconnect", Port_disconnect },
01418     /* {"__gc", InputPort_gc }, */
01419     {NULL, NULL}
01420 };
01421 
01422 /* OutputPort */
01423 
01424 gen_push_bxptr(OutputPort_push, "OutputPort", OutputPortInterface)
01425 
01426 
01427 static int OutputPort_new(lua_State *L)
01428 {
01429     const char *type, *name, *desc;
01430     OutputPortInterface* opi;
01431     int argc = lua_gettop(L);
01432 
01433     type = luaL_checkstring(L, 1);
01434 
01435     /* name and description are optional */
01436     name = (argc > 1) ? luaL_checkstring(L, 2) : "";
01437     desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
01438 
01439     types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
01440 
01441     if(ti==0)
01442         luaL_error(L, "OutputPort.new: unknown type %s", type);
01443 
01444     opi = ti->outputPort(name);
01445 
01446     if(!opi)
01447         luaL_error(L, "OutputPort.new: creating port of type %s failed", type);
01448 
01449     opi->doc(desc);
01450     OutputPort_push(L, opi);
01451     return 1;
01452 }
01453 
01454 static int OutputPort_write(lua_State *L)
01455 {
01456     DataSourceBase::shared_ptr dsb;
01457     DataSourceBase::shared_ptr *dsbp;
01458 
01459     OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
01460 
01461     /* fastpath: Variable argument */
01462     if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
01463         dsb = *dsbp;
01464     } else  {
01465         /* slowpath: convert lua value to dsb */
01466         dsb = Variable_fromlua(L, op->getTypeInfo(), 2);
01467     }
01468     op->write(dsb);
01469     return 0;
01470 }
01471 
01472 #ifdef NOT_USED_YET
01473 static int OutputPort_gc(lua_State *L)
01474 {
01475     OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
01476     delete op;
01477     return 0;
01478 }
01479 #endif
01480 
01481 /* only explicit destruction allowed */
01482 static int OutputPort_del(lua_State *L)
01483 {
01484     OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
01485     delete op;
01486 
01487     /* this prevents calling rtt methods which would cause a crash */
01488     luaL_getmetatable(L, "__dead__");
01489     lua_setmetatable(L, -2);
01490     return 0;
01491 }
01492 
01493 static const struct luaL_Reg OutputPort_f [] = {
01494     {"new", OutputPort_new },
01495     {"write", OutputPort_write },
01496     {"info", Port_info },
01497     {"connect", Port_connect },
01498     {"disconnect", Port_disconnect },
01499     {"delete", OutputPort_del },
01500     {NULL, NULL}
01501 };
01502 
01503 static const struct luaL_Reg OutputPort_m [] = {
01504     {"write", OutputPort_write },
01505     {"info", Port_info },
01506     {"connect", Port_connect },
01507     {"disconnect", Port_disconnect },
01508     {"delete", OutputPort_del },
01509     /* {"__gc", OutputPort_gc }, */
01510     {NULL, NULL}
01511 };
01512 
01513 /***************************************************************
01514  * Operation
01515  ***************************************************************/
01516 
01517 struct OperationHandle {
01518     OperationInterfacePart *oip;
01519     OperationCallerC *occ;
01520     unsigned int arity;
01521     bool is_void;
01522 
01523     /* we need to store references to the dsb which we created
01524        on-the-fly, because the ReferenceDSB does not hold a
01525        shared_ptr, and hence these DSN might get destructed
01526        before/during the call
01527      */
01528     std::vector<base::DataSourceBase::shared_ptr> dsb_store;
01529     std::vector<internal::Reference*> args;
01530     base::DataSourceBase::shared_ptr call_dsb;
01531     base::DataSourceBase::shared_ptr ret_dsb;
01532 };
01533 
01534 template<typename T>
01535 int OperationGC(lua_State* L)
01536 {
01537     T* oh = (T*) lua_touserdata(L, 1);
01538     delete oh->occ;
01539     reinterpret_cast<T*>(lua_touserdata(L, 1))->~T();
01540     return 0;
01541 }
01542 
01543 static int Operation_info(lua_State *L)
01544 {
01545     int i=1;
01546     std::vector<ArgumentDescription> args;
01547     OperationHandle *op = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
01548 
01549     lua_pushstring(L, op->oip->getName().c_str());      /* name */
01550     lua_pushstring(L, op->oip->description().c_str());  /* description */
01551     lua_pushstring(L, op->oip->resultType().c_str());   /* result type */
01552     lua_pushinteger(L, op->arity);              /* arity */
01553 
01554     args = op->oip->getArgumentList();
01555 
01556     lua_newtable(L);
01557 
01558     for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) {
01559         lua_newtable(L);
01560         lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3);
01561         lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3);
01562         lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3);
01563         lua_rawseti(L, -2, i++);
01564     }
01565     return 5;
01566 }
01567 
01568 static int __Operation_call(lua_State *L)
01569 {
01570     bool ret;
01571     DataSourceBase::shared_ptr dsb, *dsbp;
01572 
01573     OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
01574     OperationInterfacePart *oip = oh->oip;
01575     unsigned int argc = lua_gettop(L);
01576 
01577     if(oh->arity != argc-1)
01578         luaL_error(L, "Operation.call: wrong number of args. expected %d, got %d", oh->arity, argc-1);
01579 
01580     /* update dsbs */
01581     for(unsigned int arg=2; arg<=argc; arg++) {
01582         /* fastpath: Variable argument */
01583         if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) {
01584             dsb = *dsbp;
01585         } else {
01586             /* slowpath: convert lua value to dsb */
01587             dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg);
01588             /* this dsb must outlive occ->call (see comment in
01589                OperationHandle def.): */
01590             oh->dsb_store.push_back(dsb);
01591         }
01592         if(!dsb->isAssignable())
01593             luaL_error(L, "Operation.call: argument %d is not assignable.", arg-1);
01594 
01595         ret = oh->args[arg-2]->setReference(dsb);
01596         if (!ret)
01597             luaL_error(L, "Operation_call: setReference failed, wrong type of argument?");
01598     }
01599 
01600     if(!oh->occ->call())
01601         luaL_error(L, "Operation.call: call failed.");
01602 
01603     oh->dsb_store.clear();
01604 
01605     if(!oh->is_void)
01606         Variable_push_coerce(L, oh->ret_dsb);
01607     else
01608         lua_pushnil(L);
01609     return 1;
01610 }
01611 
01612 static int __Operation_send(lua_State *L)
01613 {
01614     DataSourceBase::shared_ptr dsb, *dsbp;
01615 
01616     OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
01617     OperationInterfacePart *oip = oh->oip;
01618     unsigned int argc = lua_gettop(L);
01619 
01620     if(oh->arity != argc-1)
01621         luaL_error(L, "Operation.send: wrong number of args. expected %d, got %d", oh->arity, argc-1);
01622 
01623     /* update dsbs */
01624     for(unsigned int arg=2; arg<=argc; arg++) {
01625         /* fastpath: Variable argument */
01626         if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) {
01627             dsb = *dsbp;
01628         } else {
01629             /* slowpath: convert lua value to dsb */
01630             dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg);
01631             /* this dsb must outlive occ->call (see comment in
01632                OperationHandle def.): */
01633             oh->dsb_store.push_back(dsb);
01634         }
01635         oh->args[arg-2]->setReference(dsb);
01636     }
01637 
01638     luaM_pushobject_mt(L, "SendHandle", SendHandleC)(oh->occ->send());
01639     return 1;
01640 }
01641 
01642 static int Operation_call(lua_State *L)
01643 {
01644     int ret;
01645     try {
01646         ret = __Operation_call(L);
01647     } catch(const std::exception &exc) {
01648         luaL_error(L, "Operation.call: caught exception '%s'", exc.what());
01649     } catch(...) {
01650         luaL_error(L, "Operation.call: caught unknown exception");
01651     }
01652     return ret;
01653 }
01654 
01655 static int Operation_send(lua_State *L)
01656 {
01657     int ret;
01658     try {
01659         ret = __Operation_send(L);
01660     } catch(const std::exception &exc) {
01661         luaL_error(L, "Operation.send: caught exception '%s'", exc.what());
01662     } catch(...) {
01663         luaL_error(L, "Operation.send: caught unknown exception");
01664     }
01665     return ret;
01666 }
01667 
01668 
01669 static const struct luaL_Reg Operation_f [] = {
01670     { "info", Operation_info },
01671     { "call", Operation_call },
01672     { "send", Operation_send },
01673     { NULL, NULL }
01674 
01675 };
01676 
01677 static const struct luaL_Reg Operation_m [] = {
01678     { "info", Operation_info },
01679     { "send", Operation_send },
01680     { "__call", Operation_call },
01681     { "__gc", OperationGC<OperationHandle> },
01682     { NULL, NULL }
01683 };
01684 
01685 /***************************************************************
01686  * Service (boxed)
01687  ***************************************************************/
01688 
01689 static int Service_getName(lua_State *L)
01690 {
01691     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01692     lua_pushstring(L, srv->getName().c_str());
01693     return 1;
01694 }
01695 
01696 static int Service_doc(lua_State *L)
01697 {
01698     int ret;
01699     const char* doc;
01700     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01701     if(lua_gettop(L) == 1) {
01702         lua_pushstring(L, srv->doc().c_str());
01703         ret = 1;
01704     } else {
01705         doc = luaL_checkstring(L, 2);
01706         srv->doc(doc);
01707         ret = 0;
01708     }
01709 
01710     return ret;
01711 }
01712 
01713 static int Service_getProviderNames(lua_State *L)
01714 {
01715     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01716     push_vect_str(L, srv->getProviderNames());
01717     return 1;
01718 }
01719 
01720 static int Service_getOperationNames(lua_State *L)
01721 {
01722     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01723     push_vect_str(L, srv->getOperationNames());
01724     return 1;
01725 }
01726 
01727 
01728 static int Service_hasOperation(lua_State *L)
01729 {
01730     int ret;
01731     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01732     const char* op = luaL_checkstring(L, 2);
01733     ret = srv->hasOperation(op);
01734     lua_pushboolean(L, ret);
01735     return 1;
01736 }
01737 
01738 static int Service_getPortNames(lua_State *L)
01739 {
01740     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01741     push_vect_str(L, srv->getPortNames());
01742     return 1;
01743 }
01744 
01745 static int Service_provides(lua_State *L)
01746 {
01747     int ret, i, argc;
01748     const char* subsrv_str;
01749     Service::shared_ptr srv, subsrv;
01750 
01751     srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01752     argc=lua_gettop(L);
01753 
01754     /* return "this" if no args given */
01755     if(argc == 1) {
01756         ret = 1;
01757         goto out;
01758     }
01759 
01760     for(i=2; i<=argc; i++) {
01761         subsrv_str = luaL_checkstring(L, i);
01762         subsrv = srv->getService(subsrv_str);
01763         if (subsrv == 0)
01764             luaL_error(L, "Service.provides: no subservice %s of service %s",
01765                        subsrv_str, srv->getName().c_str() );
01766         else
01767             luaM_pushobject_mt(L, "Service", Service::shared_ptr)(subsrv);
01768     }
01769     ret = argc - 1;
01770 
01771  out:
01772     return ret;
01773 }
01774 
01775 static int Service_getOperation(lua_State *L)
01776 {
01777     const char *op_str;
01778     OperationInterfacePart *oip;
01779     Service::shared_ptr srv;
01780     DataSourceBase::shared_ptr dsb;
01781     const types::TypeInfo *ti;
01782     OperationHandle *oh;
01783     TaskContext *this_tc;
01784 
01785     srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01786     op_str = luaL_checkstring(L, 2);
01787     oip = srv->getOperation(op_str);
01788 
01789     if(!oip)
01790         luaL_error(L, "Service_getOperation: service %s has no operation %s",
01791                srv->getName().c_str(), op_str);
01792 
01793     oh = (OperationHandle*) luaM_pushobject_mt(L, "Operation", OperationHandle)();
01794     oh->oip = oip;
01795     oh->arity = oip->arity();
01796     oh->args.reserve(oh->arity);
01797     this_tc = __getTC(L);
01798 
01799     oh->occ = new OperationCallerC(oip, op_str, this_tc->engine());
01800 
01801     /* create args
01802      * getArgumentType(0) is return value
01803      */
01804     for(unsigned int arg=1; arg <= oh->arity; arg++) {
01805         std::string type = oip->getArgumentType(arg)->getTypeName();
01806         ti = types::TypeInfoRepository::Instance()->type(type);
01807         if(!ti)
01808             luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for arg %d of type '%s'",
01809                    op_str, arg, type.c_str());
01810 
01811         dsb = ti->buildReference((void*) 0xdeadbeef);
01812         if(!dsb)
01813             luaL_error(L, "Operation.call: '%s', failed to build DSB for arg %d of type '%s'",
01814                    op_str, arg, type.c_str());
01815 
01816         oh->args.push_back(dynamic_cast<internal::Reference*>(dsb.get()));
01817         oh->occ->arg(dsb);
01818     }
01819 
01820     /* return value */
01821     if(oip->resultType() != "void"){
01822         ti = oip->getArgumentType(0); // 0 == return type
01823         if(!ti)
01824             luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for return value of type '%s'",
01825                    op_str, oip->resultType().c_str());
01826         oh->ret_dsb=ti->buildValue();
01827         if(!oh->ret_dsb)
01828             luaL_error(L, "Operation.call: '%s', failed to build DSB for return value of type '%s'",
01829                    op_str, oip->resultType().c_str());
01830 
01831         oh->occ->ret(oh->ret_dsb);
01832         oh->is_void=false;
01833     } else {
01834         oh->is_void=true;
01835     }
01836 
01837     if(!oh->occ->ready())
01838         luaL_error(L, "Service.getOperation: OperationCallerC not ready!");
01839 
01840     return 1;
01841 }
01842 
01843 static int Service_getPort(lua_State *L)
01844 {
01845     const char* name;
01846     PortInterface *pi;
01847     InputPortInterface *ipi;
01848     OutputPortInterface *opi;
01849 
01850     Service::shared_ptr srv;
01851 
01852     srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01853     name = luaL_checkstring(L, 2);
01854 
01855     pi = srv->getPort(name);
01856     if(!pi)
01857         luaL_error(L, "Service.getPort: service %s has no port %",
01858                srv->getName().c_str(), name);
01859 
01860     /* input or output? */
01861     if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL)
01862         InputPort_push(L, ipi);
01863     else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL)
01864         OutputPort_push(L, opi);
01865     else
01866         luaL_error(L, "Service.getPort: unknown port type returned");
01867 
01868     return 1;
01869 }
01870 
01871 static int Service_getProperty(lua_State *L)
01872 {
01873     const char *name;
01874     PropertyBase *prop;
01875 
01876     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01877     name = luaL_checkstring(L, 2);
01878 
01879     prop = srv->getProperty(name);
01880 
01881     if(!prop)
01882         luaL_error(L, "%s failed. No such property", __FILE__);
01883 
01884     Property_push(L, prop);
01885     return 1;
01886 }
01887 
01888 static int Service_getPropertyNames(lua_State *L)
01889 {
01890     Service::shared_ptr srv;
01891     srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01892     std::vector<std::string> plist = srv->properties()->list();
01893     push_vect_str(L, plist);
01894     return 1;
01895 }
01896 
01897 static int Service_getProperties(lua_State *L)
01898 {
01899     Service::shared_ptr srv;
01900     srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01901     vector<PropertyBase*> props = srv->properties()->getProperties();
01902 
01903     int key = 1;
01904     lua_createtable(L, props.size(), 0);
01905     for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) {
01906         Property_push(L, *it);
01907         lua_rawseti(L, -2, key++);
01908     }
01909 
01910     return 1;
01911 }
01912 
01913 static int Service_getAttribute(lua_State *L)
01914 {
01915     const char *name;
01916     AttributeBase *prop;
01917 
01918     Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01919     name = luaL_checkstring(L, 2);
01920 
01921     prop = srv->getAttribute(name);
01922 
01923     if(!prop)
01924         luaL_error(L, "%s failed. No such Attribute", __FILE__);
01925 
01926     Attribute_push(L, prop);
01927     return 1;
01928 }
01929 
01930 static int Service_getAttributeNames(lua_State *L)
01931 {
01932     Service::shared_ptr srv;
01933     srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01934     std::vector<std::string> plist = srv->getAttributeNames();
01935     push_vect_str(L, plist);
01936     return 1;
01937 }
01938 
01939 static int Service_getAttributes(lua_State *L)
01940 {
01941     Service::shared_ptr srv;
01942     srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01943     vector<AttributeBase*> props = srv->getValues();
01944 
01945     int key = 1;
01946     lua_createtable(L, props.size(), 0);
01947     for(vector<AttributeBase*>::iterator it = props.begin(); it != props.end(); ++it) {
01948         Attribute_push(L, *it);
01949         lua_rawseti(L, -2, key++);
01950     }
01951 
01952     return 1;
01953 }
01954 
01955 static const struct luaL_Reg Service_f [] = {
01956     { "getName", Service_getName },
01957     { "doc", Service_doc },
01958     { "getProviderNames", Service_getProviderNames },
01959     { "getOperationNames", Service_getOperationNames },
01960     { "hasOperation", Service_hasOperation },
01961     { "getPortNames", Service_getPortNames },
01962     { "provides", Service_provides },
01963     { "getOperation", Service_getOperation },
01964     { "getPort", Service_getPort },
01965     { "getProperty", Service_getProperty },
01966     { "getProperties", Service_getProperties },
01967     { "getPropertyNames", Service_getPropertyNames },
01968     { "getAttribute", Service_getAttribute },
01969     { "getAttributes", Service_getAttributes },
01970     { "getAttributeNames", Service_getAttributeNames },
01971     { NULL, NULL }
01972 };
01973 
01974 static const struct luaL_Reg Service_m [] = {
01975     { "getName", Service_getName },
01976     { "doc", Service_doc },
01977     { "getProviderNames", Service_getProviderNames },
01978     { "getOperationNames", Service_getOperationNames },
01979     { "hasOperation", Service_hasOperation },
01980     { "getPortNames", Service_getPortNames },
01981     { "provides", Service_provides },
01982     { "getOperation", Service_getOperation },
01983     { "getPort", Service_getPort },
01984     { "getProperty", Service_getProperty },
01985     { "getProperties", Service_getProperties },
01986     { "getPropertyNames", Service_getPropertyNames },
01987     { "getAttribute", Service_getAttribute },
01988     { "getAttributes", Service_getAttributes },
01989     { "getAttributeNames", Service_getAttributeNames },
01990     { "__gc", GCMethod<Service::shared_ptr> },
01991     { NULL, NULL }
01992 };
01993 
01994 /***************************************************************
01995  * ServiceRequester
01996  ***************************************************************/
01997 
01998 gen_push_bxptr(ServiceRequester_push, "ServiceRequester", ServiceRequester)
01999 
02000 static int ServiceRequester_getRequestName(lua_State *L)
02001 {
02002     ServiceRequester *sr;
02003 
02004     sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
02005     lua_pushstring(L, sr->getRequestName().c_str());
02006     return 1;
02007 }
02008 
02009 static int ServiceRequester_getRequesterNames(lua_State *L)
02010 {
02011     ServiceRequester *sr;
02012     sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
02013     push_vect_str(L, sr->getRequesterNames());
02014     return 1;
02015 }
02016 
02017 static int ServiceRequester_ready(lua_State *L)
02018 {
02019     int ret;
02020     ServiceRequester *sr;
02021     sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
02022     ret = sr->ready();
02023     lua_pushboolean(L, ret);
02024     return 1;
02025 }
02026 
02027 static int ServiceRequester_disconnect(lua_State *L)
02028 {
02029     ServiceRequester *sr;
02030     sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
02031     sr->disconnect();
02032     return 0;
02033 }
02034 
02035 static int ServiceRequester_requires(lua_State *L)
02036 {
02037     int argc, ret, i;
02038     const char* subsr_str;
02039     ServiceRequester *sr;
02040     ServiceRequester::shared_ptr subsr;
02041 
02042     sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
02043     argc = lua_gettop(L);
02044 
02045     /* return "this" if no args given */
02046     if(argc == 1) {
02047         ret = 1;
02048         goto out;
02049     }
02050 
02051     for(i=2; i<=argc; i++) {
02052         subsr_str = luaL_checkstring(L, i);
02053         subsr = sr->requires(subsr_str);
02054         if (subsr == 0)
02055             luaL_error(L, "ServiceRequester: no required subservice %s of service %s",
02056                    subsr_str, sr->getRequestName().c_str());
02057         else
02058             ServiceRequester_push(L, subsr.get());
02059     }
02060     ret = argc - 1;
02061 
02062  out:
02063     return ret;
02064 }
02065 
02066 static const struct luaL_Reg ServiceRequester_f [] = {
02067     { "getRequestName", ServiceRequester_getRequestName },
02068     { "getRequesterNames", ServiceRequester_getRequesterNames },
02069     { "ready", ServiceRequester_ready },
02070     { "disconnect", ServiceRequester_disconnect },
02071     { "requires", ServiceRequester_requires },
02072     { NULL, NULL }
02073 };
02074 
02075 static const struct luaL_Reg ServiceRequester_m [] = {
02076     { "getRequestName", ServiceRequester_getRequestName },
02077     { "getRequesterNames", ServiceRequester_getRequesterNames },
02078     { "ready", ServiceRequester_ready },
02079     { "disconnect", ServiceRequester_disconnect },
02080     { "requires", ServiceRequester_requires },
02081     { NULL, NULL }
02082 };
02083 
02084 
02085 /***************************************************************
02086  * TaskContext (boxed)
02087  ***************************************************************/
02088 
02089 gen_push_bxptr(TaskContext_push, "TaskContext", TaskContext)
02090 
02091 static int TaskContext_getName(lua_State *L)
02092 {
02093     const char *s;
02094     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02095     s = tc->getName().c_str();
02096     lua_pushstring(L, s);
02097     return 1;
02098 }
02099 
02100 static int TaskContext_start(lua_State *L)
02101 {
02102     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02103     bool b = tc->start();
02104     lua_pushboolean(L, b);
02105     return 1;
02106 }
02107 
02108 static int TaskContext_stop(lua_State *L)
02109 {
02110     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02111     bool b = tc->stop();
02112     lua_pushboolean(L, b);
02113     return 1;
02114 }
02115 
02116 static int TaskContext_configure(lua_State *L)
02117 {
02118     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02119     bool ret = tc->configure();
02120     lua_pushboolean(L, ret);
02121     return 1;
02122 }
02123 
02124 static int TaskContext_activate(lua_State *L)
02125 {
02126     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02127     bool ret = tc->activate();
02128     lua_pushboolean(L, ret);
02129     return 1;
02130 }
02131 
02132 static int TaskContext_cleanup(lua_State *L)
02133 {
02134     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02135     bool ret = tc->cleanup();
02136     lua_pushboolean(L, ret);
02137     return 1;
02138 }
02139 
02140 static int TaskContext_error(lua_State *L)
02141 {
02142     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02143     tc->error();
02144     return 0;
02145 }
02146 
02147 static int TaskContext_recover(lua_State *L)
02148 {
02149     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02150     bool ret = tc->recover();
02151     lua_pushboolean(L, ret);
02152     return 1;
02153 }
02154 
02155 static int TaskContext_getState(lua_State *L)
02156 {
02157     TaskCore::TaskState ts;
02158     TaskContext **tc = (TaskContext**) luaM_checkudata_bx(L, 1, TaskContext);
02159     ts = (*tc)->getTaskState();
02160 
02161     switch(ts) {
02162     case TaskCore::Init:        lua_pushstring(L, "Init"); break;
02163     case TaskCore::PreOperational:  lua_pushstring(L, "PreOperational"); break;
02164     case TaskCore::FatalError:  lua_pushstring(L, "FatalError"); break;
02165     case TaskCore::Exception:   lua_pushstring(L, "Exception"); break;
02166     case TaskCore::Stopped:     lua_pushstring(L, "Stopped"); break;
02167     case TaskCore::Running:     lua_pushstring(L, "Running"); break;
02168     case TaskCore::RunTimeError:    lua_pushstring(L, "RunTimeError"); break;
02169     default:            lua_pushstring(L, "unknown");
02170     }
02171     return 1;
02172 }
02173 
02174 /* string-table getPeers(TaskContext self)*/
02175 /* should better return array of TC's */
02176 static int TaskContext_getPeers(lua_State *L)
02177 {
02178     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02179     std::vector<std::string> plist = tc->getPeerList();
02180     push_vect_str(L, plist);
02181     return 1;
02182 }
02183 
02184 /* bool addPeer(TaskContext self, TaskContext peer)*/
02185 static int TaskContext_addPeer(lua_State *L)
02186 {
02187     bool ret;
02188     TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
02189     TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext));
02190     ret = self->addPeer(peer);
02191     lua_pushboolean(L, ret);
02192     return 1;
02193 }
02194 
02195 /* void removePeer(TaskContext self, string peer)*/
02196 static int TaskContext_removePeer(lua_State *L)
02197 {
02198     std::string peer;
02199     TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
02200     peer = luaL_checkstring(L, 2);
02201     self->removePeer(peer);
02202     return 0;
02203 }
02204 
02205 /* TaskContext getPeer(string name) */
02206 static int TaskContext_getPeer(lua_State *L)
02207 {
02208     std::string strpeer;
02209     TaskContext *peer;
02210     TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
02211     strpeer = luaL_checkstring(L, 2);
02212     peer = self->getPeer(strpeer);
02213 
02214     if(!peer) {
02215         luaL_error(L, "TaskContext.getPeer: no peer %s", strpeer.c_str());
02216         goto out;
02217     }
02218 
02219     TaskContext_push(L, peer);
02220  out:
02221     return 1;
02222 }
02223 
02224 static int TaskContext_getPortNames(lua_State *L)
02225 {
02226     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02227     std::vector<std::string> plist = tc->ports()->getPortNames();
02228     push_vect_str(L, plist);
02229     return 1;
02230 }
02231 
02232 static int TaskContext_addPort(lua_State *L)
02233 {
02234     const char* name, *desc;
02235     PortInterface **pi;
02236     int argc = lua_gettop(L);
02237     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02238 
02239     pi = (PortInterface**) luaL_testudata(L, 2, "InputPort");
02240     if(pi) goto check_name;
02241 
02242     pi = (PortInterface**) luaL_testudata(L, 2, "OutputPort");
02243     if(pi) goto check_name;
02244 
02245     return luaL_error(L, "addPort: invalid argument, not a Port");
02246 
02247  check_name:
02248     if(argc > 2) {
02249         name = luaL_checkstring(L, 3);
02250         (*pi)->setName(name);
02251     }
02252 
02253     if(argc > 3) {
02254         desc = luaL_checkstring(L, 4);
02255         (*pi)->doc(desc);
02256     }
02257 
02258     tc->ports()->addPort(**pi);
02259     return 0;
02260 }
02261 
02262 static int TaskContext_addEventPort(lua_State *L)
02263 {
02264     const char* name, *desc;
02265     InputPortInterface **ipi;
02266     int argc = lua_gettop(L);
02267     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02268 
02269     if((ipi = (InputPortInterface**) luaL_testudata(L, 2, "InputPort")) == NULL)
02270         return luaL_error(L, "addEventPort: invalid argument, not an InputPort");
02271 
02272     if(argc > 2) {
02273         name = luaL_checkstring(L, 3);
02274         (*ipi)->setName(name);
02275     }
02276 
02277     if(argc > 3) {
02278         desc = luaL_checkstring(L, 4);
02279         (*ipi)->doc(desc);
02280     }
02281 
02282     tc->ports()->addEventPort(**ipi);
02283     return 0;
02284 }
02285 
02286 static int TaskContext_getPort(lua_State *L)
02287 {
02288     const char* name;
02289     PortInterface *pi;
02290     InputPortInterface *ipi;
02291     OutputPortInterface *opi;
02292 
02293     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02294     name = luaL_checkstring(L, 2);
02295 
02296     pi = tc->getPort(name);
02297     if(!pi)
02298         luaL_error(L, "TaskContext.getPort: no port %s for taskcontext %s",
02299                name, tc->getName().c_str());
02300 
02301     /* input or output? */
02302     if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL)
02303         InputPort_push(L, ipi);
02304     else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL)
02305         OutputPort_push(L, opi);
02306     else
02307         luaL_error(L, "TaskContext.getPort: unknown port returned");
02308 
02309     return 1;
02310 }
02311 
02312 static int TaskContext_removePort(lua_State *L)
02313 {
02314     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02315     const char *port = luaL_checkstring(L, 2);
02316     tc->ports()->removePort(port);
02317     return 0;
02318 }
02319 
02320 static int TaskContext_addProperty(lua_State *L)
02321 {
02322     const char *name, *desc;
02323     int argc = lua_gettop(L);
02324     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02325     PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Property", PropertyBase));
02326 
02327     if(argc > 2) {
02328         name = luaL_checkstring(L, 3);
02329         pb->setName(name);
02330     }
02331 
02332     if(argc > 3) {
02333         desc = luaL_checkstring(L, 4);
02334         pb->setDescription(desc);
02335     }
02336 
02337 
02338     if(!tc->addProperty(*pb))
02339         luaL_error(L, "TaskContext.addProperty: failed to add property %s.",
02340                pb->getName().c_str());
02341 
02342     return 0;
02343 }
02344 
02345 static int TaskContext_getProperty(lua_State *L)
02346 {
02347     const char *name;
02348     PropertyBase *prop;
02349 
02350     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02351     name = luaL_checkstring(L, 2);
02352 
02353     prop = tc->getProperty(name);
02354 
02355     if(!prop)
02356         luaL_error(L, "%s failed. No such property", __FILE__);
02357 
02358     Property_push(L, prop);
02359     return 1;
02360 }
02361 
02362 
02363 static int TaskContext_getPropertyNames(lua_State *L)
02364 {
02365     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02366     std::vector<std::string> plist = tc->properties()->list();
02367     push_vect_str(L, plist);
02368     return 1;
02369 }
02370 
02371 static int TaskContext_getProperties(lua_State *L)
02372 {
02373     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02374     vector<PropertyBase*> props = tc->properties()->getProperties();
02375 
02376     int key = 1;
02377     lua_createtable(L, props.size(), 0);
02378     for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) {
02379         Property_push(L, *it);
02380         lua_rawseti(L, -2, key++);
02381     }
02382 
02383     return 1;
02384 }
02385 
02386 static int TaskContext_removeProperty(lua_State *L)
02387 {
02388     const char *name;
02389     PropertyBase *prop;
02390 
02391     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02392     name = luaL_checkstring(L, 2);
02393 
02394     prop = tc->getProperty(name);
02395 
02396     if(!prop)
02397         luaL_error(L, "%s failed. No such property", __FILE__);
02398 
02399     tc->properties()->remove(prop);
02400     return 0;
02401 }
02402 
02403 static int TaskContext_addAttribute(lua_State *L)
02404 {
02405     const char *name, *desc;
02406     int argc = lua_gettop(L);
02407     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02408     AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Attribute", AttributeBase));
02409 
02410     if(argc > 2) {
02411         name = luaL_checkstring(L, 3);
02412         pb->setName(name);
02413     }
02414 
02415     if(!tc->addAttribute(*pb))
02416         luaL_error(L, "TaskContext.addAttribute: failed to add attribute %s.",
02417                pb->getName().c_str());
02418 
02419     return 0;
02420 }
02421 
02422 static int TaskContext_getAttribute(lua_State *L)
02423 {
02424     const char *name;
02425     AttributeBase *prop;
02426 
02427     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02428     name = luaL_checkstring(L, 2);
02429 
02430     prop = tc->getAttribute(name);
02431 
02432     if(!prop)
02433         luaL_error(L, "%s failed. No such Attribute", __FILE__);
02434 
02435     Attribute_push(L, prop);
02436     return 1;
02437 }
02438 
02439 
02440 static int TaskContext_getAttributeNames(lua_State *L)
02441 {
02442     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02443     std::vector<std::string> plist = tc->attributes()->getAttributeNames();
02444     push_vect_str(L, plist);
02445     return 1;
02446 }
02447 
02448 static int TaskContext_getAttributes(lua_State *L)
02449 {
02450     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02451     vector<AttributeBase*> props = tc->attributes()->getValues();
02452 
02453     int key = 1;
02454     lua_createtable(L, props.size(), 0);
02455     for(vector<AttributeBase*>::iterator it = props.begin(); it != props.end(); ++it) {
02456         Attribute_push(L, *it);
02457         lua_rawseti(L, -2, key++);
02458     }
02459 
02460     return 1;
02461 }
02462 
02463 static int TaskContext_removeAttribute(lua_State *L)
02464 {
02465     const char *name;
02466     AttributeBase *prop;
02467 
02468     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02469     name = luaL_checkstring(L, 2);
02470 
02471     if(!tc->attributes()->hasAttribute(name))
02472         luaL_error(L, "%s failed. No such attribute", __FILE__);
02473 
02474     tc->attributes()->removeAttribute(name);
02475 
02476     return 0;
02477 }
02478 
02479 static int TaskContext_getOps(lua_State *L)
02480 {
02481     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02482     std::vector<std::string> oplst = tc->operations()->getNames();
02483     push_vect_str(L, oplst);
02484     return 1;
02485 }
02486 
02487 /* returns restype, arity, table-of-arg-descr */
02488 static int TaskContext_getOpInfo(lua_State *L)
02489 {
02490     int i=1;
02491     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02492     const char *op = luaL_checkstring(L, 2);
02493     std::vector<ArgumentDescription> args;
02494 
02495     if(!tc->operations()->hasMember(op))
02496         luaL_error(L, "TaskContext.getOpInfo failed: no such operation");
02497 
02498     lua_pushstring(L, tc->operations()->getResultType(op).c_str()); /* result type */
02499     lua_pushinteger(L, tc->operations()->getArity(op));     /* arity */
02500     lua_pushstring(L, tc->operations()->getDescription(op).c_str()); /* description */
02501 
02502     args = tc->operations()->getArgumentList(op);
02503 
02504     lua_newtable(L);
02505 
02506     for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) {
02507         lua_newtable(L);
02508         lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3);
02509         lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3);
02510         lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3);
02511         lua_rawseti(L, -2, i++);
02512     }
02513 
02514     return 4;
02515 }
02516 
02517 static int TaskContext_provides(lua_State *L)
02518 {
02519     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02520     Service::shared_ptr srv = tc->provides();
02521 
02522     if(srv == 0)
02523         luaL_error(L, "TaskContext.provides: no default service");
02524 
02525     /* forward to Serivce.provides */
02526     luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
02527     lua_replace(L, 1);
02528     return Service_provides(L);
02529 }
02530 
02531 static int TaskContext_getProviderNames(lua_State *L)
02532 {
02533     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02534     Service::shared_ptr srv = tc->provides();
02535     push_vect_str(L, srv->getProviderNames());
02536     return 1;
02537 }
02538 
02539 static int TaskContext_requires(lua_State *L)
02540 {
02541     ServiceRequester::shared_ptr sr;
02542     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02543     sr = tc->requires();
02544 
02545     if(!sr)
02546         luaL_error(L, "TaskContext.requires returned NULL");
02547 
02548     ServiceRequester_push(L, sr.get());
02549     lua_replace(L, 1);
02550     return ServiceRequester_requires(L);
02551 }
02552 
02553 static int TaskContext_connectServices(lua_State *L)
02554 {
02555     int ret;
02556     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02557     TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext));
02558     ret = tc->connectServices(peer);
02559     lua_pushboolean(L, ret);
02560     return 1;
02561 }
02562 
02563 static int TaskContext_hasOperation(lua_State *L)
02564 {
02565     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02566     Service::shared_ptr srv = tc->provides();
02567 
02568     if(srv == 0)
02569         luaL_error(L, "TaskContext.provides: no default service");
02570 
02571     /* forward to Serivce.hasOperation */
02572     luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
02573     lua_replace(L, 1);
02574     return Service_hasOperation(L);
02575 }
02576 
02577 
02578 static int TaskContext_getOperation(lua_State *L)
02579 {
02580     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02581     Service::shared_ptr srv = tc->provides();
02582 
02583     if(srv == 0)
02584         luaL_error(L, "TaskContext.getOperation: no default service");
02585 
02586     /* forward to Serivce.getOperation */
02587     luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
02588     lua_replace(L, 1);
02589     return Service_getOperation(L);
02590 }
02591 
02592 /*
02593  * SendHandle (required for send)
02594  */
02595 
02596 static void SendStatus_push(lua_State *L, SendStatus ss)
02597 {
02598     switch (ss) {
02599     case SendSuccess:  lua_pushstring(L, "SendSuccess"); break;
02600     case SendNotReady: lua_pushstring(L, "SendNotReady"); break;
02601     case SendFailure:  lua_pushstring(L, "SendFailure"); break;
02602     default:       lua_pushstring(L, "unkown");
02603     }
02604 }
02605 
02606 static int __SendHandle_collect(lua_State *L, bool block)
02607 {
02608     unsigned int coll_argc;
02609     std::vector<DataSourceBase::shared_ptr> coll_args; /* temporarily store args */
02610     SendStatus ss;
02611     const types::TypeInfo *ti;
02612     OperationInterfacePart *oip;
02613     DataSourceBase::shared_ptr dsb, *dsbp;
02614 
02615     unsigned int argc = lua_gettop(L);
02616     SendHandleC *shc = luaM_checkudata_mt(L, 1, "SendHandle", SendHandleC);
02617 
02618     /* get orp pointer */
02619     oip = shc->getOrp();
02620     coll_argc = oip->collectArity();
02621 
02622     if(argc == 1) {
02623         // No args supplied, create them.
02624         for(unsigned int i=1; i<=coll_argc; i++) {
02625             ti = oip->getCollectType(i);
02626             dsb = ti->buildValue();
02627             coll_args.push_back(dsb);
02628             shc->arg(dsb);
02629         }
02630     } else if (argc-1 == coll_argc) {
02631         // args supplied, use them.
02632         for(unsigned int arg=2; arg<=argc; arg++) {
02633             if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL)
02634                 dsb = *dsbp;
02635             else
02636                 luaL_error(L, "SendHandle.collect: expected Variable argument at position %d", arg-1);
02637             shc->arg(dsb);
02638         }
02639     } else {
02640         luaL_error(L, "SendHandle.collect: wrong number of args. expected either 0 or %d, got %d",
02641                coll_argc, argc-1);
02642     }
02643 
02644     if(block) ss = shc->collect();
02645     else ss = shc->collectIfDone();
02646 
02647     SendStatus_push(L, ss);
02648 
02649     if(ss == SendSuccess) {
02650         for (unsigned int i=0; i<coll_args.size(); i++)
02651             Variable_push_coerce(L, coll_args[i]);
02652     }
02653     /* SendStatus + collect args */
02654     return coll_args.size() + 1;
02655 }
02656 
02657 static int SendHandle_collect(lua_State *L) { return __SendHandle_collect(L, true); }
02658 static int SendHandle_collectIfDone(lua_State *L) { return __SendHandle_collect(L, false); }
02659 
02660 static const struct luaL_Reg SendHandle_f [] = {
02661     { "collect", SendHandle_collect },
02662     { "collectIfDone", SendHandle_collectIfDone },
02663     { NULL, NULL }
02664 };
02665 
02666 static const struct luaL_Reg SendHandle_m [] = {
02667     { "collect", SendHandle_collect },
02668     { "collectIfDone", SendHandle_collectIfDone },
02669     { "__gc", GCMethod<SendHandleC> },
02670     { NULL, NULL }
02671 };
02672 
02673 /* only explicit destruction allowed */
02674 static int TaskContext_del(lua_State *L)
02675 {
02676     TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02677     delete tc;
02678 
02679     /* this prevents calling rtt methods which would cause a crash */
02680     luaL_getmetatable(L, "__dead__");
02681     lua_setmetatable(L, -2);
02682     return 0;
02683 }
02684 
02685 static const struct luaL_Reg TaskContext_f [] = {
02686     { "getName", TaskContext_getName },
02687     { "start", TaskContext_start },
02688     { "stop", TaskContext_stop },
02689     { "configure", TaskContext_configure },
02690     { "activate", TaskContext_activate },
02691     { "cleanup", TaskContext_cleanup },
02692     { "error", TaskContext_error },
02693     { "recover", TaskContext_recover },
02694     { "getState", TaskContext_getState },
02695     { "getPeers", TaskContext_getPeers },
02696     { "addPeer", TaskContext_addPeer },
02697     { "removePeer", TaskContext_removePeer },
02698     { "getPeer", TaskContext_getPeer },
02699     { "getPortNames", TaskContext_getPortNames },
02700     { "addPort", TaskContext_addPort },
02701     { "addEventPort", TaskContext_addEventPort },
02702     { "getPort", TaskContext_getPort },
02703     { "removePort", TaskContext_removePort },
02704     { "addProperty", TaskContext_addProperty },
02705     { "getProperty", TaskContext_getProperty },
02706     { "getProperties", TaskContext_getProperties },
02707     { "getPropertyNames", TaskContext_getPropertyNames },
02708     { "removeProperty", TaskContext_removeProperty },
02709     { "addAttribute", TaskContext_addAttribute },
02710     { "getAttribute", TaskContext_getAttribute },
02711     { "getAttributes", TaskContext_getAttributes },
02712     { "getAttributeNames", TaskContext_getAttributeNames },
02713     { "removeAttribute", TaskContext_removeAttribute },
02714     { "getOps", TaskContext_getOps },
02715     { "getOpInfo", TaskContext_getOpInfo },
02716     { "hasOperation", TaskContext_hasOperation },
02717     { "provides", TaskContext_provides },
02718     { "getProviderNames", TaskContext_getProviderNames },
02719     { "connectServices", TaskContext_connectServices },
02720     { "getOperation", TaskContext_getOperation },
02721     { "delete", TaskContext_del },
02722     { NULL, NULL}
02723 };
02724 
02725 static const struct luaL_Reg TaskContext_m [] = {
02726     { "getName", TaskContext_getName },
02727     { "start", TaskContext_start },
02728     { "stop", TaskContext_stop },
02729     { "configure", TaskContext_configure },
02730     { "activate", TaskContext_activate },
02731     { "cleanup", TaskContext_cleanup },
02732     { "error", TaskContext_error },
02733     { "recover", TaskContext_recover },
02734     { "getState", TaskContext_getState },
02735     { "getPeers", TaskContext_getPeers },
02736     { "addPeer", TaskContext_addPeer },
02737     { "removePeer", TaskContext_removePeer },
02738     { "getPeer", TaskContext_getPeer },
02739     { "getPortNames", TaskContext_getPortNames },
02740     { "addPort", TaskContext_addPort },
02741     { "addEventPort", TaskContext_addEventPort },
02742     { "getPort", TaskContext_getPort },
02743     { "removePort", TaskContext_removePort },
02744     { "addProperty", TaskContext_addProperty },
02745     { "getProperty", TaskContext_getProperty },
02746     { "getProperties", TaskContext_getProperties },
02747     { "getPropertyNames", TaskContext_getPropertyNames },
02748     { "addAttribute", TaskContext_addAttribute },
02749     { "getAttribute", TaskContext_getAttribute },
02750     { "getAttributes", TaskContext_getAttributes },
02751     { "getAttributeNames", TaskContext_getAttributeNames },
02752     { "removeAttribute", TaskContext_removeAttribute },
02753     { "removeProperty", TaskContext_removeProperty },
02754     { "getOps", TaskContext_getOps },
02755     { "getOpInfo", TaskContext_getOpInfo },
02756     { "hasOperation", TaskContext_hasOperation },
02757     { "provides", TaskContext_provides },
02758     { "getProviderNames", TaskContext_getProviderNames },
02759     { "requires", TaskContext_requires },
02760     { "connectServices", TaskContext_connectServices },
02761     { "getOperation", TaskContext_getOperation },
02762     { "delete", TaskContext_del },
02763     // { "__index", TaskContext_index },
02764     /* we don't GC TaskContexts
02765      * { "__gc", GCMethod<TaskContext> }, */
02766     { NULL, NULL}
02767 };
02768 
02769 /*
02770  * Execution engine hook registration
02771  */
02772 
02773 /* executable IF */
02774 class EEHook : public base::ExecutableInterface
02775 {
02776 protected:
02777     std::string func;
02778     lua_State *L;
02779     TaskContext *tc; /* remember this to be able to print TC name
02780                 in error messages */
02781 public:
02782     EEHook(lua_State *_L, std::string _func) { L = _L; func = _func; tc = __getTC(L); }
02783     bool execute() { return call_func(L, func.c_str(), tc, 1, 1); }
02784 };
02785 
02786 static int EEHook_new(lua_State *L)
02787 {
02788     const char *func;
02789     func = luaL_checkstring(L, 1);
02790     luaM_pushobject(L, EEHook)(L, func);
02791     return 1;
02792 }
02793 
02794 static int EEHook_enable(lua_State *L)
02795 {
02796     EEHook *eeh = luaM_checkudata(L, 1, EEHook);
02797     TaskContext *tc = __getTC(L);
02798     lua_pushboolean(L, tc->engine()->runFunction(eeh));
02799     return 1;
02800 }
02801 
02802 static int EEHook_disable(lua_State *L)
02803 {   EEHook *eeh = luaM_checkudata(L, 1, EEHook);
02804     TaskContext *tc = __getTC(L);
02805     lua_pushboolean(L, tc->engine()->removeFunction(eeh));
02806     return 1;
02807 }
02808 
02809 #if 0
02810 static int EEHook_gc(lua_State *L)
02811 {
02812     EEHook_disable(L);
02813     lua_settop(L, 1);
02814     reinterpret_cast<EEHook*>(lua_touserdata(L, 1))->~EEHook();
02815     return 0;
02816 }
02817 #endif
02818 
02819 static const struct luaL_Reg EEHook_f [] = {
02820     { "new", EEHook_new },
02821     { "enable", EEHook_enable },
02822     { "disable", EEHook_disable },
02823 };
02824 
02825 
02826 static const struct luaL_Reg EEHook_m [] = {
02827     { "enable", EEHook_enable },
02828     { "disable", EEHook_disable },
02829     /* { "__gc", EEHook_gc }, */
02830 };
02831 
02832 
02833 /*
02834  * Logger and miscellaneous
02835  */
02836 static const char *const loglevels[] = {
02837     "Never", "Fatal", "Critical", "Error", "Warning", "Info", "Debug", "RealTime", NULL
02838 };
02839 
02840 static int Logger_setLogLevel(lua_State *L)
02841 {
02842     Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels);
02843     log().setLogLevel(ll);
02844     return 0;
02845 }
02846 
02847 static int Logger_getLogLevel(lua_State *L)
02848 {
02849     Logger::LogLevel ll = log().getLogLevel();
02850 
02851     switch(ll) {
02852     case Logger::Never: lua_pushstring(L, "Never"); break;
02853     case Logger::Fatal: lua_pushstring(L, "Fatal"); break;
02854     case Logger::Critical:  lua_pushstring(L, "Critical"); break;
02855     case Logger::Error: lua_pushstring(L, "Error"); break;
02856     case Logger::Warning:   lua_pushstring(L, "Warning"); break;
02857     case Logger::Info:  lua_pushstring(L, "Info"); break;
02858     case Logger::Debug: lua_pushstring(L, "Debug"); break;
02859     case Logger::RealTime:  lua_pushstring(L, "RealTime"); break;
02860     default:
02861         lua_pushstring(L, "unknown");
02862     }
02863     return 1;
02864 }
02865 
02866 static int Logger_log(lua_State *L)
02867 {
02868     const char *mes;
02869     for(int i=1; i<=lua_gettop(L); i++) {
02870         mes = luaL_checkstring(L, i);
02871         Logger::log() << mes;
02872     }
02873     Logger::log() << endlog();
02874     return 0;
02875 }
02876 
02877 static int Logger_logl(lua_State *L)
02878 {
02879     const char *mes;
02880     Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels);
02881     for(int i=2; i<=lua_gettop(L); i++) {
02882         mes = luaL_checkstring(L, i);
02883         Logger::log(ll) << mes;
02884     }
02885     Logger::log(ll) << endlog();
02886     return 0;
02887 }
02888 
02889 /* misc stuff */
02890 
02891 static int getTime(lua_State *L)
02892 {
02893     unsigned long nsec, sec;
02894     RTT::os::TimeService::nsecs total_nsec = TimeService::Instance()->getNSecs();
02895     sec =  total_nsec / 1000000000;
02896     nsec = total_nsec % 1000000000;
02897     lua_pushinteger(L, sec);
02898     lua_pushinteger(L, nsec);
02899     return 2;
02900 }
02901 
02902 static int rtt_sleep(lua_State *L)
02903 {
02904     TIME_SPEC ts;
02905     ts.tv_sec = luaL_checknumber(L, 1);
02906     ts.tv_nsec = luaL_checknumber(L, 2);
02907     rtos_nanosleep(&ts, NULL);
02908     return 0;
02909 }
02910 
02911 static int getTC(lua_State *L)
02912 {
02913     lua_pushstring(L, "this_TC");
02914     lua_rawget(L, LUA_REGISTRYINDEX);
02915     return 1;
02916 }
02917 
02918 static TaskContext* __getTC(lua_State *L)
02919 {
02920     TaskContext *tc;
02921     getTC(L);
02922     tc = *(luaM_checkudata_bx(L, -1, TaskContext));
02923     lua_pop(L, 1);
02924     return tc;
02925 }
02926 
02927 /* access to the globals repository */
02928 static int globals_getNames(lua_State *L)
02929 {
02930     GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance();
02931     push_vect_str(L, gr->getAttributeNames() );
02932     return 1;
02933 }
02934 
02935 static int globals_get(lua_State *L)
02936 {
02937     const char *name;
02938     base::AttributeBase *ab;
02939     DataSourceBase::shared_ptr dsb;
02940 
02941     name = luaL_checkstring(L, 1);
02942     GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance();
02943 
02944     ab = gr->getAttribute(name);
02945 
02946     if (ab)
02947         Variable_push_coerce(L, ab->getDataSource());
02948     else
02949         lua_pushnil(L);
02950 
02951     return 1;
02952 }
02953 
02954 /* global service */
02955 static int provides_global(lua_State *L)
02956 {
02957     luaM_pushobject_mt(L, "Service", Service::shared_ptr)(GlobalService::Instance());
02958     lua_insert(L, 1);
02959     return Service_provides(L);
02960 }
02961 
02962 static int rtt_services(lua_State *L)
02963 {
02964     push_vect_str(L, PluginLoader::Instance()->listServices());
02965     return 1;
02966 }
02967 
02968 static int rtt_typekits(lua_State *L)
02969 {
02970     push_vect_str(L, PluginLoader::Instance()->listTypekits());
02971     return 1;
02972 }
02973 
02974 static int rtt_types(lua_State *L)
02975 {
02976     push_vect_str(L, TypeInfoRepository::Instance()->getTypes());
02977     return 1;
02978 }
02979 
02980 static const struct luaL_Reg rtt_f [] = {
02981     {"getTime", getTime },
02982     {"sleep", rtt_sleep },
02983     {"getTC", getTC },
02984     {"globals_getNames", globals_getNames },
02985     {"globals_get", globals_get },
02986     {"provides", provides_global },
02987     {"services", rtt_services },
02988     {"typekits", rtt_typekits },
02989     {"types", rtt_types },
02990     {"setLogLevel", Logger_setLogLevel },
02991     {"getLogLevel", Logger_getLogLevel },
02992     {"log", Logger_log },
02993     {"logl", Logger_logl },
02994     {NULL, NULL}
02995 };
02996 
02997 extern "C" int luaopen_rtt(lua_State *L);
02998 
02999 int luaopen_rtt(lua_State *L)
03000 {
03001     lua_newtable(L);
03002     lua_replace(L, LUA_ENVIRONINDEX);
03003 
03004     luaL_newmetatable(L, "__dead__");
03005 
03006     /* register MyObj
03007      * 1. line creates metatable MyObj and registers name in registry
03008      * 2. line duplicates metatable
03009      * 3. line sets metatable[__index]=metatable
03010      *    (more precisely: table at -2 [__index] = top_of_stack, pops top of stack)
03011      * 4. line register methods in metatable
03012      * 5. line registers free functions in global mystuff.MyObj table
03013      */
03014     luaL_newmetatable(L, "TaskContext");
03015     lua_pushvalue(L, -1); /* duplicates metatable */
03016     lua_setfield(L, -2, "__index");
03017     luaL_register(L, NULL, TaskContext_m);
03018     luaL_register(L, "rtt.TaskContext", TaskContext_f);
03019 
03020     luaL_newmetatable(L, "Operation");
03021     lua_pushvalue(L, -1);
03022     lua_setfield(L, -2, "__index");
03023     luaL_register(L, NULL, Operation_m);
03024     luaL_register(L, "rtt.Operation", Operation_f);
03025 
03026     luaL_newmetatable(L, "Service");
03027     lua_pushvalue(L, -1);
03028     lua_setfield(L, -2, "__index");
03029     luaL_register(L, NULL, Service_m);
03030     luaL_register(L, "rtt.Service", Service_f);
03031 
03032     luaL_newmetatable(L, "ServiceRequester");
03033     lua_pushvalue(L, -1);
03034     lua_setfield(L, -2, "__index");
03035     luaL_register(L, NULL, ServiceRequester_m);
03036     luaL_register(L, "rtt.ServiceRequester", ServiceRequester_f);
03037 
03038     luaL_newmetatable(L, "SendHandle");
03039     lua_pushvalue(L, -1); /* duplicates metatable */
03040     lua_setfield(L, -2, "__index");
03041     luaL_register(L, NULL, SendHandle_m);
03042     luaL_register(L, "rtt.SendHandle", SendHandle_f);
03043 
03044     luaL_newmetatable(L, "InputPort");
03045     lua_pushvalue(L, -1); /* duplicates metatable */
03046     lua_setfield(L, -2, "__index");
03047     luaL_register(L, NULL, InputPort_m);
03048     luaL_register(L, "rtt.InputPort", InputPort_f);
03049 
03050     luaL_newmetatable(L, "OutputPort");
03051     lua_pushvalue(L, -1); /* duplicates metatable */
03052     lua_setfield(L, -2, "__index");
03053     luaL_register(L, NULL, OutputPort_m);
03054     luaL_register(L, "rtt.OutputPort", OutputPort_f);
03055 
03056     luaL_newmetatable(L, "Variable");
03057     lua_pushvalue(L, -1); /* duplicates metatable */
03058     lua_setfield(L, -2, "__index");
03059     luaL_register(L, NULL, Variable_m);
03060     luaL_register(L, "rtt.Variable", Variable_f);
03061 
03062     luaL_newmetatable(L, "Property");
03063     lua_pushvalue(L, -1); /* duplicates metatable */
03064     lua_setfield(L, -2, "__index");
03065     luaL_register(L, NULL, Property_m);
03066     luaL_register(L, "rtt.Property", Property_f);
03067 
03068     luaL_newmetatable(L, "Attribute");
03069     lua_pushvalue(L, -1); /* duplicates metatable */
03070     lua_setfield(L, -2, "__index");
03071     luaL_register(L, NULL, Attribute_m);
03072     luaL_register(L, "rtt.Attribute", Attribute_f);
03073 
03074     luaL_newmetatable(L, "EEHook");
03075     lua_pushvalue(L, -1); /* duplicates metatable */
03076     lua_setfield(L, -2, "__index");
03077     luaL_register(L, NULL, EEHook_m);
03078     luaL_register(L, "rtt.EEHook", EEHook_f);
03079 
03080     /* misc toplevel functions */
03081     luaL_register(L, "rtt", rtt_f);
03082 
03083     return 1;
03084 }
03085 
03086 /* store the TC to be returned by getTC() in registry */
03087 int set_context_tc(TaskContext *tc, lua_State *L)
03088 {
03089     TaskContext **new_tc;
03090     lua_pushstring(L, "this_TC");
03091     new_tc = (TaskContext**) lua_newuserdata(L, sizeof(TaskContext*));
03092     *new_tc = (TaskContext*) tc;
03093     luaL_getmetatable(L, "TaskContext");
03094     lua_setmetatable(L, -2);
03095     lua_rawset(L, LUA_REGISTRYINDEX);
03096     return 0;
03097 }
03098 
03099 
03100 /* call a zero arity function with a boolean return value
03101  * used to call various hooks */
03102 bool call_func(lua_State *L, const char *fname, TaskContext *tc,
03103            int require_function, int require_result)
03104 {
03105     bool ret = true;
03106     int num_res = (require_result != 0) ? 1 : 0;
03107     lua_getglobal(L, fname);
03108 
03109     if(lua_isnil(L, -1)) {
03110         lua_pop(L, 1);
03111         if(require_function)
03112             luaL_error(L, "%s: no (required) Lua function %s", tc->getName().c_str(), fname);
03113         else
03114             goto out;
03115     }
03116 
03117     if (lua_pcall(L, 0, num_res, 0) != 0) {
03118         Logger::log(Logger::Error) << "LuaComponent '"<< tc->getName()  <<"': error calling function "
03119                        << fname << ": " << lua_tostring(L, -1) << endlog();
03120         ret = false;
03121         goto out;
03122     }
03123 
03124     if(require_result) {
03125         if (!lua_isboolean(L, -1)) {
03126             Logger::log(Logger::Error) << "LuaComponent '" << tc->getName() << "': " << fname
03127                            << " must return a bool but returned a "
03128                            << lua_typename(L, lua_type(L, -1)) << endlog();
03129             ret = false;
03130             goto out;
03131         }
03132         ret = lua_toboolean(L, -1);
03133         lua_pop(L, 1); /* pop result */
03134     }
03135  out:
03136     return ret;
03137 }