rtt.cpp
Go to the documentation of this file.
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  * Ports (boxed)
01060  ***************************************************************/
01061 
01062 /* both input or output */
01063 static int Port_info(lua_State *L)
01064 {
01065         int arg_type;
01066         const char* port_type = NULL;
01067         PortInterface **pip;
01068         PortInterface *pi = NULL;
01069 
01070         if((pip = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
01071                 pi = *pip;
01072                 port_type = "in";
01073         } else if((pip = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
01074                 pi = *pip;
01075                 port_type = "out";
01076         }
01077         else {
01078                 arg_type = lua_type(L, 1);
01079                 luaL_error(L, "Port.info: invalid argument, expected Port, got %s",
01080                            lua_typename(L, arg_type));
01081         }
01082 
01083         lua_newtable(L);
01084         lua_pushstring(L, "name"); lua_pushstring(L, pi->getName().c_str()); lua_rawset(L, -3);
01085         lua_pushstring(L, "desc"); lua_pushstring(L, pi->getDescription().c_str()); lua_rawset(L, -3);
01086         lua_pushstring(L, "connected"); lua_pushboolean(L, pi->connected()); lua_rawset(L, -3);
01087         lua_pushstring(L, "isLocal"); lua_pushboolean(L, pi->isLocal()); lua_rawset(L, -3);
01088         lua_pushstring(L, "type"); lua_pushstring(L, pi->getTypeInfo()->getTypeName().c_str()); lua_rawset(L, -3);
01089         lua_pushstring(L, "porttype"); lua_pushstring(L, port_type); lua_rawset(L, -3);
01090 
01091         return 1;
01092 }
01093 
01094 static int Port_connect(lua_State *L)
01095 {
01096         int arg_type, ret;
01097         PortInterface **pip1, **pip2;
01098         PortInterface *pi1 = NULL;
01099         PortInterface *pi2 = NULL;
01100     ConnPolicy **cpp;
01101         ConnPolicy *cp = NULL;
01102 
01103         if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
01104                 pi1= *pip1;
01105         } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
01106                 pi1= *pip1;
01107         }
01108         else {
01109                 arg_type = lua_type(L, 1);
01110                 luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s",
01111                            lua_typename(L, arg_type));
01112         }
01113         if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) {
01114                 pi2= *pip2;
01115         } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) {
01116                 pi2= *pip2;
01117         }
01118         else {
01119                 arg_type = lua_type(L, 2);
01120                 luaL_error(L, "Port.connect: invalid argument 2, expected Port, got %s",
01121                            lua_typename(L, arg_type));
01122         }
01123 
01124         if((cpp = (ConnPolicy**) luaL_testudata(L, 3, "ConnPolicy")) != NULL) {
01125                 cp=*cpp;
01126         }
01127 
01128     if ( cp )
01129         ret = pi1->connectTo(pi2, *cp);
01130     else
01131         ret = pi1->connectTo(pi2);
01132 
01133         lua_pushboolean(L, ret);
01134 
01135         return 1;
01136 }
01137 
01138 static int Port_disconnect(lua_State *L)
01139 {
01140         int arg_type, ret;
01141         PortInterface **pip1, **pip2;
01142         PortInterface *pi1 = NULL;
01143         PortInterface *pi2 = NULL;
01144 
01145         if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
01146                 pi1= *pip1;
01147         } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
01148                 pi1= *pip1;
01149         }
01150         else {
01151                 arg_type = lua_type(L, 1);
01152                 luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s",
01153                            lua_typename(L, arg_type));
01154     }
01155     if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) {
01156         pi2= *pip2;
01157     } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) {
01158         pi2= *pip2;
01159     }
01160 
01161     if (pi2 != NULL)
01162         ret = pi1->disconnect(pi2);
01163     else{
01164         pi1->disconnect();
01165         ret = 1;
01166     }
01167     lua_pushboolean(L, ret);
01168 
01169     return 1;
01170 }
01171 
01172 
01173 
01174 /* InputPort (boxed) */
01175 
01176 gen_push_bxptr(InputPort_push, "InputPort", InputPortInterface)
01177 
01178 static int InputPort_new(lua_State *L)
01179 {
01180         const char *type, *name, *desc;
01181         InputPortInterface* ipi;
01182         int argc = lua_gettop(L);
01183 
01184         type = luaL_checkstring(L, 1);
01185 
01186         /* name and description are optional */
01187         name = (argc > 1) ? luaL_checkstring(L, 2) : "";
01188         desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
01189 
01190         types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
01191         if(ti==0)
01192                 luaL_error(L, "InputPort.new: unknown type %s", type);
01193 
01194         ipi = ti->inputPort(name);
01195 
01196         if(!ipi)
01197                 luaL_error(L, "InputPort.new: creating port of type %s failed", type);
01198 
01199         ipi->doc(desc);
01200         InputPort_push(L, ipi);
01201         return 1;
01202 }
01203 
01204 static int InputPort_read(lua_State *L)
01205 {
01206         int ret = 1;
01207         InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
01208         DataSourceBase::shared_ptr dsb;
01209         DataSourceBase::shared_ptr *dsbp;
01210         FlowStatus fs;
01211 
01212         /* if we get don't get a DS to store the result, create one */
01213         if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL)
01214                 dsb = *dsbp;
01215         else {
01216                 dsb = ip->getTypeInfo()->buildValue();
01217                 ret = 2;
01218         }
01219 
01220         fs = ip->read(dsb);
01221 
01222         if(fs == NoData) lua_pushstring(L, "NoData");
01223         else if (fs == NewData) lua_pushstring(L, "NewData");
01224         else if (fs == OldData) lua_pushstring(L, "OldData");
01225         else luaL_error(L, "InputPort.read: unknown FlowStatus returned");
01226 
01227         if(ret>1)
01228                 Variable_push_coerce(L, dsb);
01229 
01230         return ret;
01231 }
01232 
01233 #ifdef NOT_USED_YET
01234 static int InputPort_gc(lua_State *L)
01235 {
01236         InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
01237         delete ip;
01238         return 0;
01239 }
01240 #endif
01241 
01242 /* only explicit destruction allowed */
01243 static int InputPort_del(lua_State *L)
01244 {
01245         InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
01246         delete ip;
01247 
01248         /* this prevents calling rtt methods which would cause a crash */
01249         luaL_getmetatable(L, "__dead__");
01250         lua_setmetatable(L, -2);
01251         return 0;
01252 }
01253 
01254 static const struct luaL_Reg InputPort_f [] = {
01255         {"new", InputPort_new },
01256         {"read", InputPort_read },
01257         {"info", Port_info },
01258         {"connect", Port_connect },
01259         {"disconnect", Port_disconnect },
01260         {"delete", InputPort_del },
01261         {NULL, NULL}
01262 };
01263 
01264 static const struct luaL_Reg InputPort_m [] = {
01265         {"read", InputPort_read },
01266         {"info", Port_info },
01267         {"delete", InputPort_del },
01268         {"connect", Port_connect },
01269         {"disconnect", Port_disconnect },
01270         /* {"__gc", InputPort_gc }, */
01271         {NULL, NULL}
01272 };
01273 
01274 /* OutputPort */
01275 
01276 gen_push_bxptr(OutputPort_push, "OutputPort", OutputPortInterface)
01277 
01278 
01279 static int OutputPort_new(lua_State *L)
01280 {
01281         const char *type, *name, *desc;
01282         OutputPortInterface* opi;
01283         int argc = lua_gettop(L);
01284 
01285         type = luaL_checkstring(L, 1);
01286 
01287         /* name and description are optional */
01288         name = (argc > 1) ? luaL_checkstring(L, 2) : "";
01289         desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
01290 
01291         types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
01292 
01293         if(ti==0)
01294                 luaL_error(L, "OutputPort.new: unknown type %s", type);
01295 
01296         opi = ti->outputPort(name);
01297 
01298         if(!opi)
01299                 luaL_error(L, "OutputPort.new: creating port of type %s failed", type);
01300 
01301         opi->doc(desc);
01302         OutputPort_push(L, opi);
01303         return 1;
01304 }
01305 
01306 static int OutputPort_write(lua_State *L)
01307 {
01308         DataSourceBase::shared_ptr dsb;
01309         DataSourceBase::shared_ptr *dsbp;
01310 
01311         OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
01312 
01313         /* fastpath: Variable argument */
01314         if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
01315                 dsb = *dsbp;
01316         } else  {
01317                 /* slowpath: convert lua value to dsb */
01318                 dsb = Variable_fromlua(L, op->getTypeInfo(), 2);
01319         }
01320         op->write(dsb);
01321         return 0;
01322 }
01323 
01324 #ifdef NOT_USED_YET
01325 static int OutputPort_gc(lua_State *L)
01326 {
01327         OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
01328         delete op;
01329         return 0;
01330 }
01331 #endif
01332 
01333 /* only explicit destruction allowed */
01334 static int OutputPort_del(lua_State *L)
01335 {
01336         OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
01337         delete op;
01338 
01339         /* this prevents calling rtt methods which would cause a crash */
01340         luaL_getmetatable(L, "__dead__");
01341         lua_setmetatable(L, -2);
01342         return 0;
01343 }
01344 
01345 static const struct luaL_Reg OutputPort_f [] = {
01346         {"new", OutputPort_new },
01347         {"write", OutputPort_write },
01348         {"info", Port_info },
01349         {"connect", Port_connect },
01350         {"disconnect", Port_disconnect },
01351         {"delete", OutputPort_del },
01352         {NULL, NULL}
01353 };
01354 
01355 static const struct luaL_Reg OutputPort_m [] = {
01356         {"write", OutputPort_write },
01357         {"info", Port_info },
01358         {"connect", Port_connect },
01359         {"disconnect", Port_disconnect },
01360         {"delete", OutputPort_del },
01361         /* {"__gc", OutputPort_gc }, */
01362         {NULL, NULL}
01363 };
01364 
01365 /***************************************************************
01366  * Operation
01367  ***************************************************************/
01368 
01369 struct OperationHandle {
01370         OperationInterfacePart *oip;
01371         OperationCallerC *occ;
01372         unsigned int arity;
01373         bool is_void;
01374 
01375         /* we need to store references to the dsb which we created
01376            on-the-fly, because the ReferenceDSB does not hold a
01377            shared_ptr, and hence these DSN might get destructed
01378            before/during the call
01379          */
01380         std::vector<base::DataSourceBase::shared_ptr> dsb_store;
01381         std::vector<internal::Reference*> args;
01382         base::DataSourceBase::shared_ptr call_dsb;
01383         base::DataSourceBase::shared_ptr ret_dsb;
01384 };
01385 
01386 template<typename T>
01387 int OperationGC(lua_State* L)
01388 {
01389         T* oh = (T*) lua_touserdata(L, 1);
01390         delete oh->occ;
01391         reinterpret_cast<T*>(lua_touserdata(L, 1))->~T();
01392         return 0;
01393 }
01394 
01395 static int Operation_info(lua_State *L)
01396 {
01397         int i=1;
01398         std::vector<ArgumentDescription> args;
01399         OperationHandle *op = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
01400 
01401         lua_pushstring(L, op->oip->getName().c_str());          /* name */
01402         lua_pushstring(L, op->oip->description().c_str());      /* description */
01403         lua_pushstring(L, op->oip->resultType().c_str());       /* result type */
01404         lua_pushinteger(L, op->arity);                          /* arity */
01405 
01406         args = op->oip->getArgumentList();
01407 
01408         lua_newtable(L);
01409 
01410         for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) {
01411                 lua_newtable(L);
01412                 lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3);
01413                 lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3);
01414                 lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3);
01415                 lua_rawseti(L, -2, i++);
01416         }
01417         return 5;
01418 }
01419 
01420 static int __Operation_call(lua_State *L)
01421 {
01422         bool ret;
01423         DataSourceBase::shared_ptr dsb, *dsbp;
01424 
01425         OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
01426         OperationInterfacePart *oip = oh->oip;
01427         unsigned int argc = lua_gettop(L);
01428 
01429         if(oh->arity != argc-1)
01430                 luaL_error(L, "Operation.call: wrong number of args. expected %d, got %d", oh->arity, argc-1);
01431 
01432         /* update dsbs */
01433         for(unsigned int arg=2; arg<=argc; arg++) {
01434                 /* fastpath: Variable argument */
01435                 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) {
01436                         dsb = *dsbp;
01437                 } else {
01438                         /* slowpath: convert lua value to dsb */
01439                         dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg);
01440                         /* this dsb must outlive occ->call (see comment in
01441                            OperationHandle def.): */
01442                         oh->dsb_store.push_back(dsb);
01443                 }
01444                 if(!dsb->isAssignable())
01445                         luaL_error(L, "Operation.call: argument %d is not assignable.", arg-1);
01446 
01447                 ret = oh->args[arg-2]->setReference(dsb);
01448                 if (!ret)
01449                         luaL_error(L, "Operation_call: setReference failed, wrong type of argument?");
01450         }
01451 
01452         if(!oh->occ->call())
01453                 luaL_error(L, "Operation.call: call failed.");
01454 
01455         oh->dsb_store.clear();
01456 
01457         if(!oh->is_void)
01458                 Variable_push_coerce(L, oh->ret_dsb);
01459         else
01460                 lua_pushnil(L);
01461         return 1;
01462 }
01463 
01464 static int __Operation_send(lua_State *L)
01465 {
01466         DataSourceBase::shared_ptr dsb, *dsbp;
01467 
01468         OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
01469         OperationInterfacePart *oip = oh->oip;
01470         unsigned int argc = lua_gettop(L);
01471 
01472         if(oh->arity != argc-1)
01473                 luaL_error(L, "Operation.send: wrong number of args. expected %d, got %d", oh->arity, argc-1);
01474 
01475         /* update dsbs */
01476         for(unsigned int arg=2; arg<=argc; arg++) {
01477                 /* fastpath: Variable argument */
01478                 if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) {
01479                         dsb = *dsbp;
01480                 } else {
01481                         /* slowpath: convert lua value to dsb */
01482                         dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg);
01483                         /* this dsb must outlive occ->call (see comment in
01484                            OperationHandle def.): */
01485                         oh->dsb_store.push_back(dsb);
01486                 }
01487                 oh->args[arg-2]->setReference(dsb);
01488         }
01489 
01490         luaM_pushobject_mt(L, "SendHandle", SendHandleC)(oh->occ->send());
01491         return 1;
01492 }
01493 
01494 static int Operation_call(lua_State *L)
01495 {
01496         int ret;
01497         try {
01498                 ret = __Operation_call(L);
01499         } catch(const std::exception &exc) {
01500                 luaL_error(L, "Operation.call: caught exception '%s'", exc.what());
01501         } catch(...) {
01502                 luaL_error(L, "Operation.call: caught unknown exception");
01503         }
01504         return ret;
01505 }
01506 
01507 static int Operation_send(lua_State *L)
01508 {
01509         int ret;
01510         try {
01511                 ret = __Operation_send(L);
01512         } catch(const std::exception &exc) {
01513                 luaL_error(L, "Operation.send: caught exception '%s'", exc.what());
01514         } catch(...) {
01515                 luaL_error(L, "Operation.send: caught unknown exception");
01516         }
01517         return ret;
01518 }
01519 
01520 
01521 static const struct luaL_Reg Operation_f [] = {
01522         { "info", Operation_info },
01523         { "call", Operation_call },
01524         { "send", Operation_send },
01525         { NULL, NULL }
01526 
01527 };
01528 
01529 static const struct luaL_Reg Operation_m [] = {
01530         { "info", Operation_info },
01531         { "send", Operation_send },
01532         { "__call", Operation_call },
01533         { "__gc", OperationGC<OperationHandle> },
01534         { NULL, NULL }
01535 };
01536 
01537 /***************************************************************
01538  * Service (boxed)
01539  ***************************************************************/
01540 
01541 static int Service_getName(lua_State *L)
01542 {
01543         Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01544         lua_pushstring(L, srv->getName().c_str());
01545         return 1;
01546 }
01547 
01548 static int Service_doc(lua_State *L)
01549 {
01550         int ret;
01551         const char* doc;
01552         Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01553         if(lua_gettop(L) == 1) {
01554                 lua_pushstring(L, srv->doc().c_str());
01555                 ret = 1;
01556         } else {
01557                 doc = luaL_checkstring(L, 2);
01558                 srv->doc(doc);
01559                 ret = 0;
01560         }
01561 
01562         return ret;
01563 }
01564 
01565 static int Service_getProviderNames(lua_State *L)
01566 {
01567         Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01568         push_vect_str(L, srv->getProviderNames());
01569         return 1;
01570 }
01571 
01572 static int Service_getOperationNames(lua_State *L)
01573 {
01574         Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01575         push_vect_str(L, srv->getOperationNames());
01576         return 1;
01577 }
01578 
01579 
01580 static int Service_hasOperation(lua_State *L)
01581 {
01582         int ret;
01583         Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01584         const char* op = luaL_checkstring(L, 2);
01585         ret = srv->hasOperation(op);
01586         lua_pushboolean(L, ret);
01587         return 1;
01588 }
01589 
01590 static int Service_getPortNames(lua_State *L)
01591 {
01592         Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01593         push_vect_str(L, srv->getPortNames());
01594         return 1;
01595 }
01596 
01597 static int Service_provides(lua_State *L)
01598 {
01599         int ret, i, argc;
01600         const char* subsrv_str;
01601         Service::shared_ptr srv, subsrv;
01602 
01603         srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01604         argc=lua_gettop(L);
01605 
01606         /* return "this" if no args given */
01607         if(argc == 1) {
01608                 ret = 1;
01609                 goto out;
01610         }
01611 
01612         for(i=2; i<=argc; i++) {
01613                 subsrv_str = luaL_checkstring(L, i);
01614                 subsrv = srv->getService(subsrv_str);
01615                 if (subsrv == 0)
01616                         luaL_error(L, "Service.provides: no subservice %s of service %s",
01617                        subsrv_str, srv->getName().c_str() );
01618                 else
01619                         luaM_pushobject_mt(L, "Service", Service::shared_ptr)(subsrv);
01620         }
01621         ret = argc - 1;
01622 
01623  out:
01624         return ret;
01625 }
01626 
01627 static int Service_getOperation(lua_State *L)
01628 {
01629         const char *op_str;
01630         OperationInterfacePart *oip;
01631         Service::shared_ptr srv;
01632         DataSourceBase::shared_ptr dsb;
01633         const types::TypeInfo *ti;
01634         OperationHandle *oh;
01635         TaskContext *this_tc;
01636 
01637         srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01638         op_str = luaL_checkstring(L, 2);
01639         oip = srv->getOperation(op_str);
01640 
01641         if(!oip)
01642                 luaL_error(L, "Service_getOperation: service %s has no operation %s",
01643                            srv->getName().c_str(), op_str);
01644 
01645         oh = (OperationHandle*) luaM_pushobject_mt(L, "Operation", OperationHandle)();
01646         oh->oip = oip;
01647         oh->arity = oip->arity();
01648         oh->args.reserve(oh->arity);
01649         this_tc = __getTC(L);
01650 
01651         oh->occ = new OperationCallerC(oip, op_str, this_tc->engine());
01652 
01653         /* create args
01654          * getArgumentType(0) is return value
01655          */
01656         for(unsigned int arg=1; arg <= oh->arity; arg++) {
01657                 std::string type = oip->getArgumentType(arg)->getTypeName();
01658                 ti = types::TypeInfoRepository::Instance()->type(type);
01659                 if(!ti)
01660                         luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for arg %d of type '%s'",
01661                                    op_str, arg, type.c_str());
01662 
01663                 dsb = ti->buildReference((void*) 0xdeadbeef);
01664                 if(!dsb)
01665                         luaL_error(L, "Operation.call: '%s', failed to build DSB for arg %d of type '%s'",
01666                                    op_str, arg, type.c_str());
01667 
01668                 oh->args.push_back(dynamic_cast<internal::Reference*>(dsb.get()));
01669                 oh->occ->arg(dsb);
01670         }
01671 
01672         /* return value */
01673         if(oip->resultType() != "void"){
01674                 ti = oip->getArgumentType(0); // 0 == return type
01675                 if(!ti)
01676                         luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for return value of type '%s'",
01677                                    op_str, oip->resultType().c_str());
01678                 oh->ret_dsb=ti->buildValue();
01679                 if(!oh->ret_dsb)
01680                         luaL_error(L, "Operation.call: '%s', failed to build DSB for return value of type '%s'",
01681                                    op_str, oip->resultType().c_str());
01682 
01683                 oh->occ->ret(oh->ret_dsb);
01684                 oh->is_void=false;
01685         } else {
01686                 oh->is_void=true;
01687         }
01688 
01689         if(!oh->occ->ready())
01690                 luaL_error(L, "Service.getOperation: OperationCallerC not ready!");
01691 
01692         return 1;
01693 }
01694 
01695 static int Service_getPort(lua_State *L)
01696 {
01697         const char* name;
01698         PortInterface *pi;
01699         InputPortInterface *ipi;
01700         OutputPortInterface *opi;
01701 
01702         Service::shared_ptr srv;
01703 
01704         srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01705         name = luaL_checkstring(L, 2);
01706 
01707         pi = srv->getPort(name);
01708         if(!pi)
01709                 luaL_error(L, "Service.getPort: service %s has no port %",
01710                            srv->getName().c_str(), name);
01711 
01712         /* input or output? */
01713         if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL)
01714                 InputPort_push(L, ipi);
01715         else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL)
01716                 OutputPort_push(L, opi);
01717         else
01718                 luaL_error(L, "Service.getPort: unknown port type returned");
01719 
01720         return 1;
01721 }
01722 
01723 static int Service_getProperty(lua_State *L)
01724 {
01725         const char *name;
01726         PropertyBase *prop;
01727 
01728         Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01729         name = luaL_checkstring(L, 2);
01730 
01731         prop = srv->getProperty(name);
01732 
01733         if(!prop)
01734                 luaL_error(L, "%s failed. No such property", __FILE__);
01735 
01736         Property_push(L, prop);
01737         return 1;
01738 }
01739 
01740 static int Service_getPropertyNames(lua_State *L)
01741 {
01742         Service::shared_ptr srv;
01743         srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01744         std::vector<std::string> plist = srv->properties()->list();
01745         push_vect_str(L, plist);
01746         return 1;
01747 }
01748 
01749 static int Service_getProperties(lua_State *L)
01750 {
01751         Service::shared_ptr srv;
01752         srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
01753         vector<PropertyBase*> props = srv->properties()->getProperties();
01754 
01755         int key = 1;
01756         lua_createtable(L, props.size(), 0);
01757         for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) {
01758                 Property_push(L, *it);
01759                 lua_rawseti(L, -2, key++);
01760         }
01761 
01762         return 1;
01763 }
01764 
01765 static const struct luaL_Reg Service_f [] = {
01766         { "getName", Service_getName },
01767         { "doc", Service_doc },
01768         { "getProviderNames", Service_getProviderNames },
01769         { "getOperationNames", Service_getOperationNames },
01770         { "hasOperation", Service_hasOperation },
01771         { "getPortNames", Service_getPortNames },
01772         { "provides", Service_provides },
01773         { "getOperation", Service_getOperation },
01774         { "getPort", Service_getPort },
01775         { "getProperty", Service_getProperty },
01776         { "getProperties", Service_getProperties },
01777         { "getPropertyNames", Service_getPropertyNames },
01778         { NULL, NULL }
01779 };
01780 
01781 static const struct luaL_Reg Service_m [] = {
01782         { "getName", Service_getName },
01783         { "doc", Service_doc },
01784         { "getProviderNames", Service_getProviderNames },
01785         { "getOperationNames", Service_getOperationNames },
01786         { "hasOperation", Service_hasOperation },
01787         { "getPortNames", Service_getPortNames },
01788         { "provides", Service_provides },
01789         { "getOperation", Service_getOperation },
01790         { "getPort", Service_getPort },
01791         { "getProperty", Service_getProperty },
01792         { "getProperties", Service_getProperties },
01793         { "getPropertyNames", Service_getPropertyNames },
01794         { "__gc", GCMethod<Service::shared_ptr> },
01795         { NULL, NULL }
01796 };
01797 
01798 /***************************************************************
01799  * ServiceRequester
01800  ***************************************************************/
01801 
01802 gen_push_bxptr(ServiceRequester_push, "ServiceRequester", ServiceRequester)
01803 
01804 static int ServiceRequester_getRequestName(lua_State *L)
01805 {
01806         ServiceRequester *sr;
01807 
01808         sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
01809         lua_pushstring(L, sr->getRequestName().c_str());
01810         return 1;
01811 }
01812 
01813 static int ServiceRequester_getRequesterNames(lua_State *L)
01814 {
01815         ServiceRequester *sr;
01816         sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
01817         push_vect_str(L, sr->getRequesterNames());
01818         return 1;
01819 }
01820 
01821 static int ServiceRequester_ready(lua_State *L)
01822 {
01823         int ret;
01824         ServiceRequester *sr;
01825         sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
01826         ret = sr->ready();
01827         lua_pushboolean(L, ret);
01828         return 1;
01829 }
01830 
01831 static int ServiceRequester_disconnect(lua_State *L)
01832 {
01833         ServiceRequester *sr;
01834         sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
01835         sr->disconnect();
01836         return 0;
01837 }
01838 
01839 static int ServiceRequester_requires(lua_State *L)
01840 {
01841         int argc, ret, i;
01842         const char* subsr_str;
01843         ServiceRequester *sr;
01844         ServiceRequester *subsr;
01845 
01846         sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
01847         argc = lua_gettop(L);
01848 
01849         /* return "this" if no args given */
01850         if(argc == 1) {
01851                 ret = 1;
01852                 goto out;
01853         }
01854 
01855         for(i=2; i<=argc; i++) {
01856                 subsr_str = luaL_checkstring(L, i);
01857                 subsr = sr->requires(subsr_str);
01858                 if (subsr == 0)
01859                         luaL_error(L, "ServiceRequester: no required subservice %s of service %s",
01860                                    subsr_str, sr->getRequestName().c_str());
01861                 else
01862                         ServiceRequester_push(L, subsr);
01863         }
01864         ret = argc - 1;
01865 
01866  out:
01867         return ret;
01868 }
01869 
01870 static const struct luaL_Reg ServiceRequester_f [] = {
01871         { "getRequestName", ServiceRequester_getRequestName },
01872         { "getRequesterNames", ServiceRequester_getRequesterNames },
01873         { "ready", ServiceRequester_ready },
01874         { "disconnect", ServiceRequester_disconnect },
01875         { "requires", ServiceRequester_requires },
01876         { NULL, NULL }
01877 };
01878 
01879 static const struct luaL_Reg ServiceRequester_m [] = {
01880         { "getRequestName", ServiceRequester_getRequestName },
01881         { "getRequesterNames", ServiceRequester_getRequesterNames },
01882         { "ready", ServiceRequester_ready },
01883         { "disconnect", ServiceRequester_disconnect },
01884         { "requires", ServiceRequester_requires },
01885         { NULL, NULL }
01886 };
01887 
01888 
01889 /***************************************************************
01890  * TaskContext (boxed)
01891  ***************************************************************/
01892 
01893 gen_push_bxptr(TaskContext_push, "TaskContext", TaskContext)
01894 
01895 static int TaskContext_getName(lua_State *L)
01896 {
01897         const char *s;
01898         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01899         s = tc->getName().c_str();
01900         lua_pushstring(L, s);
01901         return 1;
01902 }
01903 
01904 static int TaskContext_start(lua_State *L)
01905 {
01906         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01907         bool b = tc->start();
01908         lua_pushboolean(L, b);
01909         return 1;
01910 }
01911 
01912 static int TaskContext_stop(lua_State *L)
01913 {
01914         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01915         bool b = tc->stop();
01916         lua_pushboolean(L, b);
01917         return 1;
01918 }
01919 
01920 static int TaskContext_configure(lua_State *L)
01921 {
01922         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01923         bool ret = tc->configure();
01924         lua_pushboolean(L, ret);
01925         return 1;
01926 }
01927 
01928 static int TaskContext_activate(lua_State *L)
01929 {
01930         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01931         bool ret = tc->activate();
01932         lua_pushboolean(L, ret);
01933         return 1;
01934 }
01935 
01936 static int TaskContext_cleanup(lua_State *L)
01937 {
01938         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01939         bool ret = tc->cleanup();
01940         lua_pushboolean(L, ret);
01941         return 1;
01942 }
01943 
01944 static int TaskContext_error(lua_State *L)
01945 {
01946         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01947         tc->error();
01948         return 0;
01949 }
01950 
01951 static int TaskContext_recover(lua_State *L)
01952 {
01953         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01954         bool ret = tc->recover();
01955         lua_pushboolean(L, ret);
01956         return 1;
01957 }
01958 
01959 static int TaskContext_getState(lua_State *L)
01960 {
01961         TaskCore::TaskState ts;
01962         TaskContext **tc = (TaskContext**) luaM_checkudata_bx(L, 1, TaskContext);
01963         ts = (*tc)->getTaskState();
01964 
01965         switch(ts) {
01966         case TaskCore::Init:            lua_pushstring(L, "Init"); break;
01967         case TaskCore::PreOperational:  lua_pushstring(L, "PreOperational"); break;
01968         case TaskCore::FatalError:      lua_pushstring(L, "FatalError"); break;
01969         case TaskCore::Exception:       lua_pushstring(L, "Exception"); break;
01970         case TaskCore::Stopped:         lua_pushstring(L, "Stopped"); break;
01971         case TaskCore::Running:         lua_pushstring(L, "Running"); break;
01972         case TaskCore::RunTimeError:    lua_pushstring(L, "RunTimeError"); break;
01973         default:                        lua_pushstring(L, "unknown");
01974         }
01975         return 1;
01976 }
01977 
01978 /* string-table getPeers(TaskContext self)*/
01979 /* should better return array of TC's */
01980 static int TaskContext_getPeers(lua_State *L)
01981 {
01982         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
01983         std::vector<std::string> plist = tc->getPeerList();
01984         push_vect_str(L, plist);
01985         return 1;
01986 }
01987 
01988 /* bool addPeer(TaskContext self, TaskContext peer)*/
01989 static int TaskContext_addPeer(lua_State *L)
01990 {
01991         bool ret;
01992         TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
01993         TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext));
01994         ret = self->addPeer(peer);
01995         lua_pushboolean(L, ret);
01996         return 1;
01997 }
01998 
01999 /* void removePeer(TaskContext self, string peer)*/
02000 static int TaskContext_removePeer(lua_State *L)
02001 {
02002         std::string peer;
02003         TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
02004         peer = luaL_checkstring(L, 2);
02005         self->removePeer(peer);
02006         return 0;
02007 }
02008 
02009 /* TaskContext getPeer(string name) */
02010 static int TaskContext_getPeer(lua_State *L)
02011 {
02012         std::string strpeer;
02013         TaskContext *peer;
02014         TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
02015         strpeer = luaL_checkstring(L, 2);
02016         peer = self->getPeer(strpeer);
02017 
02018         if(!peer) {
02019                 luaL_error(L, "TaskContext.getPeer: no peer %s", strpeer.c_str());
02020                 goto out;
02021         }
02022 
02023         TaskContext_push(L, peer);
02024  out:
02025         return 1;
02026 }
02027 
02028 static int TaskContext_getPortNames(lua_State *L)
02029 {
02030         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02031         std::vector<std::string> plist = tc->ports()->getPortNames();
02032         push_vect_str(L, plist);
02033         return 1;
02034 }
02035 
02036 static int TaskContext_addPort(lua_State *L)
02037 {
02038         const char* name, *desc;
02039         PortInterface **pi;
02040         int argc = lua_gettop(L);
02041         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02042 
02043         pi = (PortInterface**) luaL_testudata(L, 2, "InputPort");
02044         if(pi) goto check_name;
02045 
02046         pi = (PortInterface**) luaL_testudata(L, 2, "OutputPort");
02047         if(pi) goto check_name;
02048 
02049         return luaL_error(L, "addPort: invalid argument, not a Port");
02050 
02051  check_name:
02052         if(argc > 2) {
02053                 name = luaL_checkstring(L, 3);
02054                 (*pi)->setName(name);
02055         }
02056 
02057         if(argc > 3) {
02058                 desc = luaL_checkstring(L, 4);
02059                 (*pi)->doc(desc);
02060         }
02061 
02062         tc->ports()->addPort(**pi);
02063         return 0;
02064 }
02065 
02066 static int TaskContext_addEventPort(lua_State *L)
02067 {
02068         const char* name, *desc;
02069         InputPortInterface **ipi;
02070         int argc = lua_gettop(L);
02071         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02072 
02073         if((ipi = (InputPortInterface**) luaL_testudata(L, 2, "InputPort")) == NULL)
02074                 return luaL_error(L, "addEventPort: invalid argument, not an InputPort");
02075 
02076         if(argc > 2) {
02077                 name = luaL_checkstring(L, 3);
02078                 (*ipi)->setName(name);
02079         }
02080 
02081         if(argc > 3) {
02082                 desc = luaL_checkstring(L, 4);
02083                 (*ipi)->doc(desc);
02084         }
02085 
02086         tc->ports()->addEventPort(**ipi);
02087         return 0;
02088 }
02089 
02090 static int TaskContext_getPort(lua_State *L)
02091 {
02092         const char* name;
02093         PortInterface *pi;
02094         InputPortInterface *ipi;
02095         OutputPortInterface *opi;
02096 
02097         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02098         name = luaL_checkstring(L, 2);
02099 
02100         pi = tc->getPort(name);
02101         if(!pi)
02102                 luaL_error(L, "TaskContext.getPort: no port %s for taskcontext %s",
02103                            name, tc->getName().c_str());
02104 
02105         /* input or output? */
02106         if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL)
02107                 InputPort_push(L, ipi);
02108         else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL)
02109                 OutputPort_push(L, opi);
02110         else
02111                 luaL_error(L, "TaskContext.getPort: unknown port returned");
02112 
02113         return 1;
02114 }
02115 
02116 static int TaskContext_removePort(lua_State *L)
02117 {
02118         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02119         const char *port = luaL_checkstring(L, 2);
02120         tc->ports()->removePort(port);
02121         return 0;
02122 }
02123 
02124 static int TaskContext_addProperty(lua_State *L)
02125 {
02126         const char *name, *desc;
02127         int argc = lua_gettop(L);
02128         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02129         PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Property", PropertyBase));
02130 
02131         if(argc > 2) {
02132                 name = luaL_checkstring(L, 3);
02133                 pb->setName(name);
02134         }
02135 
02136         if(argc > 3) {
02137                 desc = luaL_checkstring(L, 4);
02138                 pb->setDescription(desc);
02139         }
02140 
02141 
02142         if(!tc->addProperty(*pb))
02143                 luaL_error(L, "TaskContext.addProperty: failed to add property %s.",
02144                            pb->getName().c_str());
02145 
02146         return 0;
02147 }
02148 
02149 static int TaskContext_getProperty(lua_State *L)
02150 {
02151         const char *name;
02152         PropertyBase *prop;
02153 
02154         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02155         name = luaL_checkstring(L, 2);
02156 
02157         prop = tc->getProperty(name);
02158 
02159         if(!prop)
02160                 luaL_error(L, "%s failed. No such property", __FILE__);
02161 
02162         Property_push(L, prop);
02163         return 1;
02164 }
02165 
02166 
02167 static int TaskContext_getPropertyNames(lua_State *L)
02168 {
02169         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02170         std::vector<std::string> plist = tc->properties()->list();
02171         push_vect_str(L, plist);
02172         return 1;
02173 }
02174 
02175 static int TaskContext_getProperties(lua_State *L)
02176 {
02177         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02178         vector<PropertyBase*> props = tc->properties()->getProperties();
02179 
02180         int key = 1;
02181         lua_createtable(L, props.size(), 0);
02182         for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) {
02183                 Property_push(L, *it);
02184                 lua_rawseti(L, -2, key++);
02185         }
02186 
02187         return 1;
02188 }
02189 
02190 static int TaskContext_removeProperty(lua_State *L)
02191 {
02192         const char *name;
02193         PropertyBase *prop;
02194 
02195         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02196         name = luaL_checkstring(L, 2);
02197 
02198         prop = tc->getProperty(name);
02199 
02200         if(!prop)
02201                 luaL_error(L, "%s failed. No such property", __FILE__);
02202 
02203         tc->properties()->remove(prop);
02204         return 0;
02205 }
02206 
02207 
02208 static int TaskContext_getOps(lua_State *L)
02209 {
02210         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02211         std::vector<std::string> oplst = tc->operations()->getNames();
02212         push_vect_str(L, oplst);
02213         return 1;
02214 }
02215 
02216 /* returns restype, arity, table-of-arg-descr */
02217 static int TaskContext_getOpInfo(lua_State *L)
02218 {
02219         int i=1;
02220         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02221         const char *op = luaL_checkstring(L, 2);
02222         std::vector<ArgumentDescription> args;
02223 
02224         if(!tc->operations()->hasMember(op))
02225                 luaL_error(L, "TaskContext.getOpInfo failed: no such operation");
02226 
02227         lua_pushstring(L, tc->operations()->getResultType(op).c_str()); /* result type */
02228         lua_pushinteger(L, tc->operations()->getArity(op));             /* arity */
02229         lua_pushstring(L, tc->operations()->getDescription(op).c_str()); /* description */
02230 
02231         args = tc->operations()->getArgumentList(op);
02232 
02233         lua_newtable(L);
02234 
02235         for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) {
02236                 lua_newtable(L);
02237                 lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3);
02238                 lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3);
02239                 lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3);
02240                 lua_rawseti(L, -2, i++);
02241         }
02242 
02243         return 4;
02244 }
02245 
02246 static int TaskContext_provides(lua_State *L)
02247 {
02248         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02249         Service::shared_ptr srv = tc->provides();
02250 
02251         if(srv == 0)
02252                 luaL_error(L, "TaskContext.provides: no default service");
02253 
02254         /* forward to Serivce.provides */
02255         luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
02256         lua_replace(L, 1);
02257         return Service_provides(L);
02258 }
02259 
02260 static int TaskContext_getProviderNames(lua_State *L)
02261 {
02262         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02263         Service::shared_ptr srv = tc->provides();
02264         push_vect_str(L, srv->getProviderNames());
02265         return 1;
02266 }
02267 
02268 static int TaskContext_requires(lua_State *L)
02269 {
02270         ServiceRequester *sr;
02271         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02272         sr = tc->requires();
02273 
02274         if(!sr)
02275                 luaL_error(L, "TaskContext.requires returned NULL");
02276 
02277         ServiceRequester_push(L, sr);
02278         lua_replace(L, 1);
02279         return ServiceRequester_requires(L);
02280 }
02281 
02282 static int TaskContext_connectServices(lua_State *L)
02283 {
02284         int ret;
02285         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02286         TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext));
02287         ret = tc->connectServices(peer);
02288         lua_pushboolean(L, ret);
02289         return 1;
02290 }
02291 
02292 static int TaskContext_hasOperation(lua_State *L)
02293 {
02294         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02295         Service::shared_ptr srv = tc->provides();
02296 
02297         if(srv == 0)
02298                 luaL_error(L, "TaskContext.provides: no default service");
02299 
02300         /* forward to Serivce.hasOperation */
02301         luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
02302         lua_replace(L, 1);
02303         return Service_hasOperation(L);
02304 }
02305 
02306 
02307 static int TaskContext_getOperation(lua_State *L)
02308 {
02309         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02310         Service::shared_ptr srv = tc->provides();
02311 
02312         if(srv == 0)
02313                 luaL_error(L, "TaskContext.getOperation: no default service");
02314 
02315         /* forward to Serivce.getOperation */
02316         luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
02317         lua_replace(L, 1);
02318         return Service_getOperation(L);
02319 }
02320 
02321 /*
02322  * SendHandle (required for send)
02323  */
02324 
02325 static void SendStatus_push(lua_State *L, SendStatus ss)
02326 {
02327         switch (ss) {
02328         case SendSuccess:  lua_pushstring(L, "SendSuccess"); break;
02329         case SendNotReady: lua_pushstring(L, "SendNotReady"); break;
02330         case SendFailure:  lua_pushstring(L, "SendFailure"); break;
02331         default:           lua_pushstring(L, "unkown");
02332         }
02333 }
02334 
02335 static int __SendHandle_collect(lua_State *L, bool block)
02336 {
02337         unsigned int coll_argc;
02338         std::vector<DataSourceBase::shared_ptr> coll_args; /* temporarily store args */
02339         SendStatus ss;
02340         const types::TypeInfo *ti;
02341         OperationInterfacePart *oip;
02342         DataSourceBase::shared_ptr dsb, *dsbp;
02343 
02344         unsigned int argc = lua_gettop(L);
02345         SendHandleC *shc = luaM_checkudata_mt(L, 1, "SendHandle", SendHandleC);
02346 
02347         /* get orp pointer */
02348         oip = shc->getOrp();
02349         coll_argc = oip->collectArity();
02350 
02351         if(argc == 1) {
02352                 // No args supplied, create them.
02353                 for(unsigned int i=1; i<=coll_argc; i++) {
02354                         ti = oip->getCollectType(i);
02355                         dsb = ti->buildValue();
02356                         coll_args.push_back(dsb);
02357                         shc->arg(dsb);
02358                 }
02359         } else if (argc-1 == coll_argc) {
02360                 // args supplied, use them.
02361                 for(unsigned int arg=2; arg<=argc; arg++) {
02362                         if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL)
02363                                 dsb = *dsbp;
02364                         else
02365                                 luaL_error(L, "SendHandle.collect: expected Variable argument at position %d", arg-1);
02366                         shc->arg(dsb);
02367                 }
02368         } else {
02369                 luaL_error(L, "SendHandle.collect: wrong number of args. expected either 0 or %d, got %d",
02370                            coll_argc, argc-1);
02371         }
02372 
02373         if(block) ss = shc->collect();
02374         else ss = shc->collectIfDone();
02375 
02376         SendStatus_push(L, ss);
02377 
02378         if(ss == SendSuccess) {
02379                 for (unsigned int i=0; i<coll_args.size(); i++)
02380                         Variable_push_coerce(L, coll_args[i]);
02381         }
02382         /* SendStatus + collect args */
02383         return coll_args.size() + 1;
02384 }
02385 
02386 static int SendHandle_collect(lua_State *L) { return __SendHandle_collect(L, true); }
02387 static int SendHandle_collectIfDone(lua_State *L) { return __SendHandle_collect(L, false); }
02388 
02389 static const struct luaL_Reg SendHandle_f [] = {
02390         { "collect", SendHandle_collect },
02391         { "collectIfDone", SendHandle_collectIfDone },
02392         { NULL, NULL }
02393 };
02394 
02395 static const struct luaL_Reg SendHandle_m [] = {
02396         { "collect", SendHandle_collect },
02397         { "collectIfDone", SendHandle_collectIfDone },
02398         { "__gc", GCMethod<SendHandleC> },
02399         { NULL, NULL }
02400 };
02401 
02402 /* only explicit destruction allowed */
02403 static int TaskContext_del(lua_State *L)
02404 {
02405         TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
02406         delete tc;
02407 
02408         /* this prevents calling rtt methods which would cause a crash */
02409         luaL_getmetatable(L, "__dead__");
02410         lua_setmetatable(L, -2);
02411         return 0;
02412 }
02413 
02414 static const struct luaL_Reg TaskContext_f [] = {
02415         { "getName", TaskContext_getName },
02416         { "start", TaskContext_start },
02417         { "stop", TaskContext_stop },
02418         { "configure", TaskContext_configure },
02419         { "activate", TaskContext_activate },
02420         { "cleanup", TaskContext_cleanup },
02421         { "error", TaskContext_error },
02422         { "recover", TaskContext_recover },
02423         { "getState", TaskContext_getState },
02424         { "getPeers", TaskContext_getPeers },
02425         { "addPeer", TaskContext_addPeer },
02426         { "removePeer", TaskContext_removePeer },
02427         { "getPeer", TaskContext_getPeer },
02428         { "getPortNames", TaskContext_getPortNames },
02429         { "addPort", TaskContext_addPort },
02430         { "addEventPort", TaskContext_addEventPort },
02431         { "getPort", TaskContext_getPort },
02432         { "removePort", TaskContext_removePort },
02433         { "addProperty", TaskContext_addProperty },
02434         { "getProperty", TaskContext_getProperty },
02435         { "getProperties", TaskContext_getProperties },
02436         { "getPropertyNames", TaskContext_getPropertyNames },
02437         { "removeProperty", TaskContext_removeProperty },
02438         { "getOps", TaskContext_getOps },
02439         { "getOpInfo", TaskContext_getOpInfo },
02440         { "hasOperation", TaskContext_hasOperation },
02441         { "provides", TaskContext_provides },
02442         { "getProviderNames", TaskContext_getProviderNames },
02443         { "connectServices", TaskContext_connectServices },
02444         { "getOperation", TaskContext_getOperation },
02445         { "delete", TaskContext_del },
02446         { NULL, NULL}
02447 };
02448 
02449 static const struct luaL_Reg TaskContext_m [] = {
02450         { "getName", TaskContext_getName },
02451         { "start", TaskContext_start },
02452         { "stop", TaskContext_stop },
02453         { "configure", TaskContext_configure },
02454         { "activate", TaskContext_activate },
02455         { "cleanup", TaskContext_cleanup },
02456         { "error", TaskContext_error },
02457         { "recover", TaskContext_recover },
02458         { "getState", TaskContext_getState },
02459         { "getPeers", TaskContext_getPeers },
02460         { "addPeer", TaskContext_addPeer },
02461         { "removePeer", TaskContext_removePeer },
02462         { "getPeer", TaskContext_getPeer },
02463         { "getPortNames", TaskContext_getPortNames },
02464         { "addPort", TaskContext_addPort },
02465         { "addEventPort", TaskContext_addEventPort },
02466         { "getPort", TaskContext_getPort },
02467         { "removePort", TaskContext_removePort },
02468         { "addProperty", TaskContext_addProperty },
02469         { "getProperty", TaskContext_getProperty },
02470         { "getProperties", TaskContext_getProperties },
02471         { "getPropertyNames", TaskContext_getPropertyNames },
02472         { "removeProperty", TaskContext_removeProperty },
02473         { "getOps", TaskContext_getOps },
02474         { "getOpInfo", TaskContext_getOpInfo },
02475         { "hasOperation", TaskContext_hasOperation },
02476         { "provides", TaskContext_provides },
02477         { "getProviderNames", TaskContext_getProviderNames },
02478         { "requires", TaskContext_requires },
02479         { "connectServices", TaskContext_connectServices },
02480         { "getOperation", TaskContext_getOperation },
02481         { "delete", TaskContext_del },
02482         // { "__index", TaskContext_index },
02483         /* we don't GC TaskContexts
02484          * { "__gc", GCMethod<TaskContext> }, */
02485         { NULL, NULL}
02486 };
02487 
02488 /*
02489  * Execution engine hook registration
02490  */
02491 
02492 /* executable IF */
02493 class EEHook : public base::ExecutableInterface
02494 {
02495 protected:
02496         std::string func;
02497         lua_State *L;
02498         TaskContext *tc; /* remember this to be able to print TC name
02499                             in error messages */
02500 public:
02501         EEHook(lua_State *_L, std::string _func) { L = _L; func = _func; tc = __getTC(L); }
02502         bool execute() { return call_func(L, func.c_str(), tc, 1, 1); }
02503 };
02504 
02505 static int EEHook_new(lua_State *L)
02506 {
02507         const char *func;
02508         func = luaL_checkstring(L, 1);
02509         luaM_pushobject(L, EEHook)(L, func);
02510         return 1;
02511 }
02512 
02513 static int EEHook_enable(lua_State *L)
02514 {
02515         EEHook *eeh = luaM_checkudata(L, 1, EEHook);
02516         TaskContext *tc = __getTC(L);
02517         lua_pushboolean(L, tc->engine()->runFunction(eeh));
02518         return 1;
02519 }
02520 
02521 static int EEHook_disable(lua_State *L)
02522 {       EEHook *eeh = luaM_checkudata(L, 1, EEHook);
02523         TaskContext *tc = __getTC(L);
02524         lua_pushboolean(L, tc->engine()->removeFunction(eeh));
02525         return 1;
02526 }
02527 
02528 #if 0
02529 static int EEHook_gc(lua_State *L)
02530 {
02531         EEHook_disable(L);
02532         lua_settop(L, 1);
02533         reinterpret_cast<EEHook*>(lua_touserdata(L, 1))->~EEHook();
02534         return 0;
02535 }
02536 #endif
02537 
02538 static const struct luaL_Reg EEHook_f [] = {
02539         { "new", EEHook_new },
02540         { "enable", EEHook_enable },
02541         { "disable", EEHook_disable },
02542 };
02543 
02544 
02545 static const struct luaL_Reg EEHook_m [] = {
02546         { "enable", EEHook_enable },
02547         { "disable", EEHook_disable },
02548         /* { "__gc", EEHook_gc }, */
02549 };
02550 
02551 
02552 /*
02553  * Logger and miscellaneous
02554  */
02555 static const char *const loglevels[] = {
02556         "Never", "Fatal", "Critical", "Error", "Warning", "Info", "Debug", "RealTime", NULL
02557 };
02558 
02559 static int Logger_setLogLevel(lua_State *L)
02560 {
02561         Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels);
02562         log().setLogLevel(ll);
02563         return 0;
02564 }
02565 
02566 static int Logger_getLogLevel(lua_State *L)
02567 {
02568         Logger::LogLevel ll = log().getLogLevel();
02569 
02570         switch(ll) {
02571         case Logger::Never:     lua_pushstring(L, "Never"); break;
02572         case Logger::Fatal:     lua_pushstring(L, "Fatal"); break;
02573         case Logger::Critical:  lua_pushstring(L, "Critical"); break;
02574         case Logger::Error:     lua_pushstring(L, "Error"); break;
02575         case Logger::Warning:   lua_pushstring(L, "Warning"); break;
02576         case Logger::Info:      lua_pushstring(L, "Info"); break;
02577         case Logger::Debug:     lua_pushstring(L, "Debug"); break;
02578         case Logger::RealTime:  lua_pushstring(L, "RealTime"); break;
02579         default:
02580                 lua_pushstring(L, "unknown");
02581         }
02582         return 1;
02583 }
02584 
02585 static int Logger_log(lua_State *L)
02586 {
02587         const char *mes;
02588         for(int i=1; i<=lua_gettop(L); i++) {
02589                 mes = luaL_checkstring(L, i);
02590                 Logger::log() << mes;
02591         }
02592         Logger::log() << endlog();
02593         return 0;
02594 }
02595 
02596 static int Logger_logl(lua_State *L)
02597 {
02598         const char *mes;
02599         Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels);
02600         for(int i=2; i<=lua_gettop(L); i++) {
02601                 mes = luaL_checkstring(L, i);
02602                 Logger::log(ll) << mes;
02603         }
02604         Logger::log(ll) << endlog();
02605         return 0;
02606 }
02607 
02608 /* misc stuff */
02609 
02610 static int getTime(lua_State *L)
02611 {
02612         unsigned long nsec, sec;
02613         RTT::os::TimeService::nsecs total_nsec = TimeService::Instance()->getNSecs();
02614         sec =  total_nsec / 1000000000;
02615         nsec = total_nsec % 1000000000;
02616         lua_pushinteger(L, sec);
02617         lua_pushinteger(L, nsec);
02618         return 2;
02619 }
02620 
02621 static int rtt_sleep(lua_State *L)
02622 {
02623         TIME_SPEC ts;
02624         ts.tv_sec = luaL_checknumber(L, 1);
02625         ts.tv_nsec = luaL_checknumber(L, 2);
02626         rtos_nanosleep(&ts, NULL);
02627         return 0;
02628 }
02629 
02630 static int getTC(lua_State *L)
02631 {
02632         lua_pushstring(L, "this_TC");
02633         lua_rawget(L, LUA_REGISTRYINDEX);
02634         return 1;
02635 }
02636 
02637 static TaskContext* __getTC(lua_State *L)
02638 {
02639         TaskContext *tc;
02640         getTC(L);
02641         tc = *(luaM_checkudata_bx(L, -1, TaskContext));
02642         lua_pop(L, 1);
02643         return tc;
02644 }
02645 
02646 /* access to the globals repository */
02647 static int globals_getNames(lua_State *L)
02648 {
02649         GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance();
02650         push_vect_str(L, gr->getAttributeNames() );
02651         return 1;
02652 }
02653 
02654 static int globals_get(lua_State *L)
02655 {
02656         const char *name;
02657         base::AttributeBase *ab;
02658         DataSourceBase::shared_ptr dsb;
02659 
02660         name = luaL_checkstring(L, 1);
02661         GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance();
02662 
02663         ab = gr->getAttribute(name);
02664 
02665         if (ab)
02666                 Variable_push_coerce(L, ab->getDataSource());
02667         else
02668                 lua_pushnil(L);
02669 
02670         return 1;
02671 }
02672 
02673 /* global service */
02674 static int provides_global(lua_State *L)
02675 {
02676         luaM_pushobject_mt(L, "Service", Service::shared_ptr)(GlobalService::Instance());
02677         lua_insert(L, 1);
02678         return Service_provides(L);
02679 }
02680 
02681 static int rtt_services(lua_State *L)
02682 {
02683         push_vect_str(L, PluginLoader::Instance()->listServices());
02684         return 1;
02685 }
02686 
02687 static int rtt_typekits(lua_State *L)
02688 {
02689         push_vect_str(L, PluginLoader::Instance()->listTypekits());
02690         return 1;
02691 }
02692 
02693 static int rtt_types(lua_State *L)
02694 {
02695         push_vect_str(L, TypeInfoRepository::Instance()->getTypes());
02696         return 1;
02697 }
02698 
02699 static const struct luaL_Reg rtt_f [] = {
02700         {"getTime", getTime },
02701         {"sleep", rtt_sleep },
02702         {"getTC", getTC },
02703         {"globals_getNames", globals_getNames },
02704         {"globals_get", globals_get },
02705         {"provides", provides_global },
02706         {"services", rtt_services },
02707         {"typekits", rtt_typekits },
02708         {"types", rtt_types },
02709         {"setLogLevel", Logger_setLogLevel },
02710         {"getLogLevel", Logger_getLogLevel },
02711         {"log", Logger_log },
02712         {"logl", Logger_logl },
02713         {NULL, NULL}
02714 };
02715 
02716 extern "C" int luaopen_rtt(lua_State *L);
02717 
02718 int luaopen_rtt(lua_State *L)
02719 {
02720         lua_newtable(L);
02721         lua_replace(L, LUA_ENVIRONINDEX);
02722 
02723         luaL_newmetatable(L, "__dead__");
02724 
02725         /* register MyObj
02726          * 1. line creates metatable MyObj and registers name in registry
02727          * 2. line duplicates metatable
02728          * 3. line sets metatable[__index]=metatable
02729          *    (more precisely: table at -2 [__index] = top_of_stack, pops top of stack)
02730          * 4. line register methods in metatable
02731          * 5. line registers free functions in global mystuff.MyObj table
02732          */
02733         luaL_newmetatable(L, "TaskContext");
02734         lua_pushvalue(L, -1); /* duplicates metatable */
02735         lua_setfield(L, -2, "__index");
02736         luaL_register(L, NULL, TaskContext_m);
02737         luaL_register(L, "rtt.TaskContext", TaskContext_f);
02738 
02739         luaL_newmetatable(L, "Operation");
02740         lua_pushvalue(L, -1);
02741         lua_setfield(L, -2, "__index");
02742         luaL_register(L, NULL, Operation_m);
02743         luaL_register(L, "rtt.Operation", Operation_f);
02744 
02745         luaL_newmetatable(L, "Service");
02746         lua_pushvalue(L, -1);
02747         lua_setfield(L, -2, "__index");
02748         luaL_register(L, NULL, Service_m);
02749         luaL_register(L, "rtt.Service", Service_f);
02750 
02751         luaL_newmetatable(L, "ServiceRequester");
02752         lua_pushvalue(L, -1);
02753         lua_setfield(L, -2, "__index");
02754         luaL_register(L, NULL, ServiceRequester_m);
02755         luaL_register(L, "rtt.ServiceRequester", ServiceRequester_f);
02756 
02757         luaL_newmetatable(L, "SendHandle");
02758         lua_pushvalue(L, -1); /* duplicates metatable */
02759         lua_setfield(L, -2, "__index");
02760         luaL_register(L, NULL, SendHandle_m);
02761         luaL_register(L, "rtt.SendHandle", SendHandle_f);
02762 
02763         luaL_newmetatable(L, "InputPort");
02764         lua_pushvalue(L, -1); /* duplicates metatable */
02765         lua_setfield(L, -2, "__index");
02766         luaL_register(L, NULL, InputPort_m);
02767         luaL_register(L, "rtt.InputPort", InputPort_f);
02768 
02769         luaL_newmetatable(L, "OutputPort");
02770         lua_pushvalue(L, -1); /* duplicates metatable */
02771         lua_setfield(L, -2, "__index");
02772         luaL_register(L, NULL, OutputPort_m);
02773         luaL_register(L, "rtt.OutputPort", OutputPort_f);
02774 
02775         luaL_newmetatable(L, "Variable");
02776         lua_pushvalue(L, -1); /* duplicates metatable */
02777         lua_setfield(L, -2, "__index");
02778         luaL_register(L, NULL, Variable_m);
02779         luaL_register(L, "rtt.Variable", Variable_f);
02780 
02781         luaL_newmetatable(L, "Property");
02782         lua_pushvalue(L, -1); /* duplicates metatable */
02783         lua_setfield(L, -2, "__index");
02784         luaL_register(L, NULL, Property_m);
02785         luaL_register(L, "rtt.Property", Property_f);
02786 
02787         luaL_newmetatable(L, "EEHook");
02788         lua_pushvalue(L, -1); /* duplicates metatable */
02789         lua_setfield(L, -2, "__index");
02790         luaL_register(L, NULL, EEHook_m);
02791         luaL_register(L, "rtt.EEHook", EEHook_f);
02792 
02793         /* misc toplevel functions */
02794         luaL_register(L, "rtt", rtt_f);
02795 
02796         return 1;
02797 }
02798 
02799 /* store the TC to be returned by getTC() in registry */
02800 int set_context_tc(TaskContext *tc, lua_State *L)
02801 {
02802         TaskContext **new_tc;
02803         lua_pushstring(L, "this_TC");
02804         new_tc = (TaskContext**) lua_newuserdata(L, sizeof(TaskContext*));
02805         *new_tc = (TaskContext*) tc;
02806         luaL_getmetatable(L, "TaskContext");
02807         lua_setmetatable(L, -2);
02808         lua_rawset(L, LUA_REGISTRYINDEX);
02809         return 0;
02810 }
02811 
02812 
02813 /* call a zero arity function with a boolean return value
02814  * used to call various hooks */
02815 bool call_func(lua_State *L, const char *fname, TaskContext *tc,
02816                int require_function, int require_result)
02817 {
02818         bool ret = true;
02819         int num_res = (require_result != 0) ? 1 : 0;
02820         lua_getglobal(L, fname);
02821 
02822         if(lua_isnil(L, -1)) {
02823                 lua_pop(L, 1);
02824                 if(require_function)
02825                         luaL_error(L, "%s: no (required) Lua function %s", tc->getName().c_str(), fname);
02826                 else
02827                         goto out;
02828         }
02829 
02830         if (lua_pcall(L, 0, num_res, 0) != 0) {
02831                 Logger::log(Logger::Error) << "LuaComponent '"<< tc->getName()  <<"': error calling function "
02832                                            << fname << ": " << lua_tostring(L, -1) << endlog();
02833                 ret = false;
02834                 goto out;
02835         }
02836 
02837         if(require_result) {
02838                 if (!lua_isboolean(L, -1)) {
02839                         Logger::log(Logger::Error) << "LuaComponent '" << tc->getName() << "': " << fname
02840                                                    << " must return a bool but returned a "
02841                                                    << lua_typename(L, lua_type(L, -1)) << endlog();
02842                         ret = false;
02843                         goto out;
02844                 }
02845                 ret = lua_toboolean(L, -1);
02846                 lua_pop(L, 1); /* pop result */
02847         }
02848  out:
02849         return ret;
02850 }


ocl
Author(s): OCL Development Team
autogenerated on Thu Jan 2 2014 11:38:08