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


ocl
Author(s): OCL Development Team
autogenerated on Mon Sep 14 2015 14:21:46