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


ocl
Author(s): OCL Development Team
autogenerated on Sat Jun 8 2019 18:48:55