OrocosComponentLibrary  2.8.3
rtt.cpp
1 /*
2  * Lua-RTT bindings
3  *
4  * (C) Copyright 2010 Markus Klotzbuecher
5  * markus.klotzbuecher@mech.kuleuven.be
6  * Department of Mechanical Engineering,
7  * Katholieke Universiteit Leuven, Belgium.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public
11  * License as published by the Free Software Foundation;
12  * version 2 of the License.
13  *
14  * As a special exception, you may use this file as part of a free
15  * software library without restriction. Specifically, if other files
16  * instantiate templates or use macros or inline functions from this
17  * file, or you compile this file and link it with other files to
18  * produce an executable, this file does not by itself cause the
19  * resulting executable to be covered by the GNU General Public
20  * License. This exception does not however invalidate any other
21  * reasons why the executable file might be covered by the GNU General
22  * Public License.
23  *
24  * This library is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27  * Lesser General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public
30  * License along with this library; if not, write to the Free Software
31  * Foundation, Inc., 59 Temple Place,
32  * Suite 330, Boston, MA 02111-1307 USA
33  */
34 
35 #include "rtt.hpp"
36 
37 using namespace std;
38 using namespace RTT;
39 using namespace RTT::detail;
40 using namespace RTT::base;
41 using namespace RTT::internal;
42 
43 static TaskContext* __getTC(lua_State*);
44 
45 #define DEBUG
46 
47 #ifdef MSVC
48 #ifdef DEBUG
49 # define _DBG(fmt, ...) printf("%s:%d\t" fmt "\n", __FUNCTION__, __LINE__, __VA_ARGS__)
50 #else
51 # define _DBG(fmt, ...) do { } while(0);
52 #endif
53 #else
54 #ifdef DEBUG
55 # define _DBG(fmt, args...) printf("%s:%d\t" fmt "\n", __FUNCTION__, __LINE__, ##args)
56 #else
57 # define _DBG(fmt, args...) do { } while(0);
58 #endif
59 #endif
60 
61 /*
62  * Inspired by tricks from here: http://lua-users.org/wiki/DoItYourselfCppBinding
63  */
64 
65 /* overloading new */
66 void* operator new(size_t size, lua_State* L, const char* mt)
67 {
68  void* ptr = lua_newuserdata(L, size);
69  luaL_getmetatable(L, mt);
70  /* assert(lua_istable(L, -1)) */ /* if you're paranoid */
71  lua_setmetatable(L, -2);
72  return ptr;
73 }
74 
75 /*
76  * luaM_pushobject_mt(L, "Port", InputPortInterface )(ctr_arg,...)
77  * expands to
78  * new(L, "Port") InputPortInterface(ctr_arg,...)
79  */
80 
81 #define luaM_pushobject(L, T) new(L, #T) T
82 #define luaM_pushobject_mt(L, MT, T) new(L, MT) T
83 
84 /* return udata ptr or fail if wrong metatable */
85 #define luaM_checkudata(L, pos, T) reinterpret_cast<T*>(luaL_checkudata((L), (pos), #T))
86 #define luaM_checkudata_mt(L, pos, MT, T) reinterpret_cast<T*>(luaL_checkudata((L), (pos), MT))
87 
88 /* return udata ptr or NULL if wrong metatable */
89 #define luaM_testudata(L, pos, T) (T*) (luaL_testudata((L), (pos), #T))
90 #define luaM_testudata_mt(L, pos, MT, T) (T*) (luaL_testudata((L), (pos), MT))
91 
92 /*
93  * boxed variants
94  */
95 
96 /* return boxed udata ptr or fail if wrong metatable */
97 #define luaM_checkudata_bx(L, pos, T) (T**) (luaL_checkudata((L), (pos), #T))
98 #define luaM_checkudata_mt_bx(L, pos, MT, T) (T**) (luaL_checkudata((L), (pos), MT))
99 
100 /* return udata ptr or NULL if wrong metatable */
101 #define luaM_testudata_bx(L, pos, T) (T**) (luaL_testudata((L), (pos), #T))
102 #define luaM_testudata_mt_bx(L, pos, MT, T) (T**) (luaL_testudata((L), (pos), MT))
103 
104 /* generate a function to push boxed pointers to lua */
105 #define gen_push_bxptr(name, MT, T) \
106 static void name(lua_State *L, T* ptr) \
107 { \
108  T** ptrptr = (T**) lua_newuserdata(L, sizeof(T*)); \
109  *ptrptr = ptr; \
110  luaL_getmetatable(L, MT); \
111  lua_setmetatable(L, -2); \
112 } \
113 
114 /* template for generating GC function */
115 template<typename T>
116 int GCMethod(lua_State* L)
117 {
118  reinterpret_cast<T*>(lua_touserdata(L, 1))->~T();
119  return 0;
120 }
121 
122 
123 /***************************************************************
124  * Some generic helpers
125  ***************************************************************/
126 
127 /* test if userdata on position ud has metatable tname */
128 void* luaL_testudata (lua_State *L, int ud, const char *tname)
129 {
130  void *p = lua_touserdata(L, ud);
131 
132  if (p == NULL)
133  goto out;
134 
135  if (!lua_getmetatable(L, ud)) {
136  p = NULL;
137  goto out;
138  }
139 
140  /* it has a MT, is it the right one? */
141  lua_pushstring(L, tname);
142  lua_rawget(L, LUA_REGISTRYINDEX);
143 
144  if (!lua_rawequal(L, -1, -2))
145  p = NULL;
146 
147  lua_pop(L, 2); /* remove both metatables */
148  out:
149  return p;
150 }
151 
152 
153 void push_vect_str(lua_State *L, const std::vector<std::string> &v)
154 {
155  int key = 1;
156  lua_createtable(L, v.size(), 0);
157 
158  for(vector<std::string>::const_iterator it = v.begin(); it != v.end(); ++it) {
159  lua_pushstring(L, it->c_str());
160  lua_rawseti(L, -2, key++);
161  }
162 }
163 
164 /* forw decl */
165 static void Variable_fromlua(lua_State *L, DataSourceBase::shared_ptr& dsb, int valind);
166 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const types::TypeInfo* ti, int valind);
167 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const char* type, int valind);
168 
169 /***************************************************************
170  * Variable (DataSourceBase)
171  ***************************************************************/
172 
173 static const TypeInfo* ti_lookup(lua_State *L, const char *name)
174 {
175 #ifndef TYPEINFO_CACHING
176  return types::TypeInfoRepository::Instance()->type(name);
177 #else
178 /* name-> TypeInfo* cache */
179  int top = lua_gettop(L);
180  const TypeInfo* ti;
181 
182  /* try lookup */
183  lua_pushstring(L, "typeinfo_cache");
184  lua_rawget(L, LUA_REGISTRYINDEX);
185 
186  if(lua_type(L, -1) == LUA_TTABLE)
187  goto table_on_top;
188 
189  /* first lookup, create table */
190  lua_pop(L, 1); /* pop nil */
191  lua_newtable(L); /* stays on top after the next three lines */
192  lua_pushstring(L, "typeinfo_cache"); /* key */
193  lua_pushvalue(L, -2); /* duplicates table */
194  lua_rawset(L, LUA_REGISTRYINDEX); /* REG['typeinfo_cache']={} */
195 
196  table_on_top:
197  /* try to lookup name in table */
198  lua_pushstring(L, name);
199  lua_rawget(L, -2);
200 
201  if(lua_type(L, -1) != LUA_TLIGHTUSERDATA)
202  goto cache_miss;
203 
204  ti = (const TypeInfo*) lua_touserdata(L, -1);
205  goto out;
206 
207  cache_miss:
208  lua_pop(L, 1); /* pop the nil */
209  ti = types::TypeInfoRepository::Instance()->type(name);
210  if (ti) { // only save if type exists !
211  lua_pushstring(L, name);
212  lua_pushlightuserdata(L, (void*) ti);
213  lua_rawset(L, -3);
214  }
215  out:
216  /* everyone happy! */
217  lua_settop(L, top);
218  return ti;
219 #endif /* TYPEINFO_CACHING */
220 }
221 
222 /* helper, check if a type name is an alias to the given TypeInfo */
223 static bool __typenames_cmp(lua_State *L, const types::TypeInfo *ti1, const char* type2)
224 {
225  const types::TypeInfo *ti2 = ti_lookup(L, type2);
226  return ti1 == ti2;
227 }
228 
229 /* helper, check if a dsb is of type type. Works also if dsb is known
230  under an alias of type */
231 static bool Variable_is_a(lua_State *L, const types::TypeInfo *ti1, const char* type)
232 {
233  const types::TypeInfo *ti2 = ti_lookup(L, type);
234  return ti1 == ti2;
235 }
236 
237 /* helper, check if a variable is basic, that is _tolua will succeed */
238 static bool __Variable_isbasic(lua_State *L, DataSourceBase::shared_ptr &dsb)
239 {
240  const types::TypeInfo *ti = dsb->getTypeInfo();
241 
242  if ( Variable_is_a(L, ti, "bool") ||
243  Variable_is_a(L, ti, "double") ||
244  Variable_is_a(L, ti, "float") ||
245  Variable_is_a(L, ti, "uint") ||
246  Variable_is_a(L, ti, "int") ||
247  Variable_is_a(L, ti, "long") ||
248  Variable_is_a(L, ti, "char") ||
249  Variable_is_a(L, ti, "uint8") || Variable_is_a(L, ti, "int8") ||
250  Variable_is_a(L, ti, "uint16") || Variable_is_a(L, ti, "int16") ||
251  Variable_is_a(L, ti, "uint32") || Variable_is_a(L, ti, "int32") ||
252  Variable_is_a(L, ti, "uint64") || Variable_is_a(L, ti, "int64") ||
253  Variable_is_a(L, ti, "string") ||
254  Variable_is_a(L, ti, "void"))
255  return true;
256  else
257  return false;
258 }
259 
260 static int Variable_isbasic(lua_State *L)
261 {
262  DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
263  lua_pushboolean(L, __Variable_isbasic(L, dsb));
264  return 1;
265 }
266 
267 
268 /*
269  * converts a DataSourceBase to the corresponding Lua value and pushes
270  * that on the stack.
271  */
272 static int __Variable_tolua(lua_State *L, DataSourceBase::shared_ptr dsb)
273 {
274  DataSourceBase *ds = dsb.get();
275  const types::TypeInfo* ti = dsb->getTypeInfo();
276  assert(ds);
277 
278  if(Variable_is_a(L, ti, "bool")) { // bool
279  DataSource<bool>* dsb = DataSource<bool>::narrow(ds);
280  if(dsb) lua_pushboolean(L, dsb->get());
281  else goto out_nodsb;
282  } else if (Variable_is_a(L, ti, "float")) { // float
283  DataSource<float>* dsb = DataSource<float>::narrow(ds);
284  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
285  else goto out_nodsb;
286  } else if (Variable_is_a(L, ti, "double")) { // double
287  DataSource<double>* dsb = DataSource<double>::narrow(ds);
288  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
289  else goto out_nodsb;
290  } else if (Variable_is_a(L, ti, "uint8")) { // uint8_t
291  DataSource<uint8_t>* dsb = DataSource<uint8_t>::narrow(ds);
292  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
293  else goto out_nodsb;
294  } else if (Variable_is_a(L, ti, "int8")) { // int8_t
295  DataSource<int8_t>* dsb = DataSource<int8_t>::narrow(ds);
296  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
297  else goto out_nodsb;
298  } else if (Variable_is_a(L, ti, "uint16")) { // uint16_t
299  DataSource<uint16_t>* dsb = DataSource<uint16_t>::narrow(ds);
300  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
301  else goto out_nodsb;
302  } else if (Variable_is_a(L, ti, "int16")) { // int16_t
303  DataSource<int16_t>* dsb = DataSource<int16_t>::narrow(ds);
304  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
305  else goto out_nodsb;
306  } else if (Variable_is_a(L, ti, "uint32")) { // uint32_t
307  DataSource<uint32_t>* dsb = DataSource<uint32_t>::narrow(ds);
308  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
309  else goto out_nodsb;
310  } else if (Variable_is_a(L, ti, "int32")) { // int32_t
311  DataSource<int32_t>* dsb = DataSource<int32_t>::narrow(ds);
312  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
313  else goto out_nodsb;
314  } else if (Variable_is_a(L, ti, "uint64")) { // uint64_t
315  DataSource<uint64_t>* dsb = DataSource<uint64_t>::narrow(ds);
316  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
317  else goto out_nodsb;
318  } else if (Variable_is_a(L, ti, "int64")) { // int64_t
319  DataSource<int64_t>* dsb = DataSource<int64_t>::narrow(ds);
320  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
321  else goto out_nodsb;
322  } else if (Variable_is_a(L, ti, "uint")) { // uint
323  DataSource<unsigned int>* dsb = DataSource<unsigned int>::narrow(ds);
324  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
325  else goto out_nodsb;
326  } else if (Variable_is_a(L, ti, "long")) { //long
327  DataSource<long>* dsb = DataSource<long>::narrow(ds);
328  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
329  else goto out_nodsb;
330  } else if (Variable_is_a(L, ti, "int")) { // int
331  DataSource<int>* dsb = DataSource<int>::narrow(ds);
332  if(dsb) lua_pushnumber(L, ((lua_Number) dsb->get()));
333  else goto out_nodsb;
334  } else if (Variable_is_a(L, ti, "char")) { // char
335  DataSource<char>* dsb = DataSource<char>::narrow(ds);
336  char c = dsb->get();
337  if(dsb) lua_pushlstring(L, &c, 1);
338  else goto out_nodsb;
339  } else if (Variable_is_a(L, ti, "string")) { //string
340  DataSource<std::string>* dsb = DataSource<std::string>::narrow(ds);
341  if(dsb) lua_pushlstring(L, dsb->get().c_str(), dsb->get().size());
342  else goto out_nodsb;
343  } else if (Variable_is_a(L, ti, "void")) {
344  DataSource<void>* dsb = DataSource<void>::narrow(ds);
345  if(dsb) lua_pushnil(L);
346  else goto out_nodsb;
347  } else {
348  goto out_conv_err;
349  }
350 
351  /* all ok */
352  return 1;
353 
354  out_conv_err:
355  luaL_error(L, "Variable.tolua: can't convert type %s", dsb->getTypeName().c_str());
356  return 0;
357 
358  out_nodsb:
359  luaL_error(L, "Variable.tolua: narrow failed for %s Variable", dsb->getTypeName().c_str());
360  return 0;
361 }
362 
363 static int Variable_tolua(lua_State *L)
364 {
365  DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
366  return __Variable_tolua(L, dsb);
367 }
368 
369 /* Function takes a DSB, that is also expected on the top of the
370  * stack. If the DSB is basic, it replaces the dsb with the
371  * corresponding Lua value. Otherwise it does nothing, leaving the DSB
372  * on the top of the stack.
373  */
374 static void Variable_coerce(lua_State *L, DataSourceBase::shared_ptr dsb)
375 {
376  if (__Variable_isbasic(L, dsb)) {
377  lua_pop(L, 1);
378  __Variable_tolua(L, dsb);
379  }
380 }
381 
382 /* this function takes a dsb and either pushes it as a Lua type if the
383  * dsb is basic or otherwise as at Variable
384  */
385 static void Variable_push_coerce(lua_State *L, DataSourceBase::shared_ptr dsb)
386 {
387  if (__Variable_isbasic(L, dsb))
388  __Variable_tolua(L, dsb);
389  else
390  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(dsb);
391 
392 }
393 
394 static int Variable_getTypes(lua_State *L)
395 {
396  push_vect_str(L, Types()->getTypes());
397  return 1;
398 }
399 
400 static int Variable_getMemberNames(lua_State *L)
401 {
402  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
403  push_vect_str(L, (*dsbp)->getMemberNames());
404  return 1;
405 }
406 
407 static int Variable_tolightuserdata(lua_State *L)
408 {
409  DataSourceBase::shared_ptr dsb = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
410  lua_pushlightuserdata(L, dsb->getRawPointer());
411  return 1;
412 }
413 
414 
415 /* caching of DSB members
416  * lookup of DSB using getMember and caches result.
417  * returns DSB (or nil if lookup fails) on top of stack.
418  */
419 static DataSourceBase::shared_ptr lookup_member(lua_State *L, DataSourceBase::shared_ptr parent, const char* mem)
420 {
421  DataSourceBase *varptr;
422  DataSourceBase::shared_ptr *dsbp;
423  DataSourceBase::shared_ptr memdsb;
424  int top = lua_gettop(L);
425 
426  varptr = parent.get();
427 
428  lua_pushlightuserdata(L, (void*) varptr);
429  lua_rawget(L, LUA_REGISTRYINDEX);
430 
431  if(lua_type(L, -1) == LUA_TNIL)
432  goto cache_miss;
433 
434  lua_pushstring(L, mem);
435  lua_rawget(L, -2);
436 
437  if ((dsbp = luaM_testudata_mt(L, -1, "Variable", DataSourceBase::shared_ptr)) != NULL) {
438  memdsb=*dsbp;
439  goto out;
440  }
441 
442  lua_pop(L, 1); /* pop nil from table lookup */
443 
444  cache_miss:
445  /* slowpath */
446  memdsb = parent->getMember(mem);
447 
448  if(memdsb == 0)
449  goto out;
450 
451  /* if nil is on top of stack, we have to create a new table */
452  if(lua_type(L, -1) == LUA_TNIL) {
453  lua_newtable(L); /* member lookup tab for this Variable */
454  lua_pushlightuserdata(L, (void*) varptr); /* index for REGISTRY */
455  lua_pushvalue(L, -2); /* duplicates table */
456  lua_rawset(L, LUA_REGISTRYINDEX); /* REG[varptr]=newtab */
457  }
458 
459  /* cache dsb in table */
460  lua_pushstring(L, mem);
461  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(memdsb);
462  lua_rawset(L, -3); /* newtab[mem]=memdsb, top is newtab */
463  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(memdsb);
464 
465  out:
466  lua_replace(L, top+1); // make new var top of stack
467  lua_settop(L, top+1);
468 
469  return memdsb;
470 }
471 
472 /* set reg[varptr] to nil so table will be garbage collected */
473 static void cache_clear(lua_State *L, DataSourceBase *varptr)
474 {
475  lua_pushlightuserdata(L, (void*) varptr);
476  lua_pushnil(L);
477  lua_rawset(L, LUA_REGISTRYINDEX);
478 }
479 
480 static int Variable_getMember(lua_State *L)
481 {
482  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
483  DataSourceBase::shared_ptr memdsb;
484  const char *mem = luaL_checkstring(L, 2);
485 
486  if ((memdsb = lookup_member(L, *dsbp, mem)) == 0)
487  luaL_error(L, "Variable.getMember: indexing failed, no member %s", mem);
488  else
489  Variable_coerce(L, memdsb);
490 
491  return 1;
492 }
493 
494 static int Variable_getMemberRaw(lua_State *L)
495 {
496  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
497  DataSourceBase::shared_ptr memdsb;
498  const char *mem = luaL_checkstring(L, 2);
499 
500  if ((memdsb = lookup_member(L, (*dsbp), mem)) == 0)
501  luaL_error(L, "Variable.getMemberRaw: indexing failed, no member %s", mem);
502 
503  /* else: Variable is already on top of stack */
504 
505  return 1;
506 }
507 
508 static int Variable_update(lua_State *L)
509 {
510  int ret;
511  DataSourceBase::shared_ptr dsb;
512  DataSourceBase::shared_ptr *dsbp;
513  DataSourceBase::shared_ptr self = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
514 
515  if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
516  dsb = *dsbp;
517  ret = self->update(dsb.get());
518  if (!ret) luaL_error(L, "Variable.assign: assignment failed");
519  } else {
520  Variable_fromlua(L, self, 2);
521  }
522 
523  return 0;
524 }
525 
526 /* create variable */
527 static int Variable_create(lua_State *L)
528 {
529  const char *type;
530  type = luaL_checkstring(L, 1);
531 
532  if(!strcmp(type, "void"))
533  luaL_error(L, "Variable.new: can't create void variable");
534 
535  TypeInfo* ti = Types()->type(type);
536 
537  if(ti==0)
538  luaL_error(L, "Variable.new: unknown type %s", type);
539 
540  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(ti->buildValue());
541  return 1;
542 }
543 
544 #define CONVERT_TO_NUMBER(CTGT) \
545  lua_Number x; \
546  if (luatype == LUA_TNUMBER) x = lua_tonumber(L, valind); \
547  else goto out_conv_err; \
548  AssignableDataSource<CTGT> *ads = ValueDataSource<CTGT>::narrow(dsb.get()); \
549  if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to %s.", #CTGT ); \
550  ads->set((CTGT) x)\
551 
552 /* Try to convert the Lua value on stack at valind to given DSB
553  * if it returns, evertthing is ok */
554 static void Variable_fromlua(lua_State *L, DataSourceBase::shared_ptr& dsb, int valind)
555 {
556  const types::TypeInfo* ti = dsb->getTypeInfo();
557 
558  luaL_checkany(L, valind);
559  int luatype = lua_type(L, valind); /* type of lua variable */
560 
561  if(__typenames_cmp(L, ti, "bool")) {
562  lua_Number x;
563  if(luatype == LUA_TBOOLEAN)
564  x = (lua_Number) lua_toboolean(L, valind);
565  else if (luatype == LUA_TNUMBER)
566  x = lua_tonumber(L, valind);
567  else
568  goto out_conv_err;
569 
570  AssignableDataSource<bool> *ads = ValueDataSource<bool>::narrow(dsb.get());
571  if (ads == NULL)
572  luaL_error(L, "Variable_fromlua: failed to narrow target dsb to bool");
573  ads->set((bool) x);
574  }
575  else if (__typenames_cmp(L, ti, "uint")) { CONVERT_TO_NUMBER(unsigned int); }
576  else if (__typenames_cmp(L, ti, "int")) { CONVERT_TO_NUMBER(int); }
577  else if (__typenames_cmp(L, ti, "double")) { CONVERT_TO_NUMBER(double); }
578  else if (__typenames_cmp(L, ti, "long")) { CONVERT_TO_NUMBER(double); }
579  else if (__typenames_cmp(L, ti, "uint8")) { CONVERT_TO_NUMBER(uint8_t); }
580  else if (__typenames_cmp(L, ti, "int8")) { CONVERT_TO_NUMBER(int8_t); }
581  else if (__typenames_cmp(L, ti, "uint16")) { CONVERT_TO_NUMBER(uint16_t); }
582  else if (__typenames_cmp(L, ti, "int16")) { CONVERT_TO_NUMBER(int16_t); }
583  else if (__typenames_cmp(L, ti, "uint32")) { CONVERT_TO_NUMBER(uint32_t); }
584  else if (__typenames_cmp(L, ti, "int32")) { CONVERT_TO_NUMBER(int32_t); }
585  else if (__typenames_cmp(L, ti, "uint64")) { CONVERT_TO_NUMBER(uint64_t); }
586  else if (__typenames_cmp(L, ti, "int64")) { CONVERT_TO_NUMBER(int64_t); }
587  else if (__typenames_cmp(L, ti, "float")) { CONVERT_TO_NUMBER(float); }
588 
589  else if (__typenames_cmp(L, ti, "char")) {
590  const char *x;
591  size_t l;
592  if (luatype == LUA_TSTRING) x = lua_tolstring(L, valind, &l);
593  else goto out_conv_err;
594  AssignableDataSource<char> *ads = ValueDataSource<char>::narrow(dsb.get());
595  if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to char");
596  ads->set((char) x[0]);
597 
598  } else if (__typenames_cmp(L, ti, "string")) {
599  const char *x;
600  if (luatype == LUA_TSTRING) x = lua_tostring(L, valind);
601  else goto out_conv_err;
602  AssignableDataSource<std::string> *ads = ValueDataSource<std::string>::narrow(dsb.get());
603  if (ads == NULL) luaL_error(L, "Variable_fromlua: failed to narrow target dsb to std::string");
604  ads->set((std::string) x);
605 
606  } else {
607  goto out_conv_err;
608  }
609 
610  /* everybody happy */
611  return;
612 
613  out_conv_err:
614  luaL_error(L, "__lua_todsb: can't convert lua %s to %s variable",
615  lua_typename(L, luatype), ti->getTypeName().c_str());
616  return;
617 }
618 
619 /* Create a DSB of RTT ti from the Lua value at stack[valind]
620  * This one will create a dsb - NRT!*/
621 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const types::TypeInfo *ti, int valind)
622 {
623  DataSourceBase::shared_ptr dsb = ti->buildValue();
624  Variable_fromlua(L, dsb, valind);
625  return dsb;
626 }
627 
628 /* Create a DSB of RTT type 'type' from the Lua value at stack[valind]
629  * This one will create a dsb - NRT!
630  * This one should be avoided, to reduce needless name-ti lookups.
631  * preferred variant is the one taking TypeInfo * as second arg */
632 static DataSourceBase::shared_ptr Variable_fromlua(lua_State *L, const char* type, int valind)
633 {
634  const types::TypeInfo* ti = ti_lookup(L, type);
635  if(!ti) luaL_error(L, "Variable_fromlua: %s is not a known type. Load typekit?", type);
636  return Variable_fromlua(L, ti, valind);
637 }
638 
639 
640 static int Variable_create_ival(lua_State *L, int typeind, int valind)
641 {
642  DataSourceBase::shared_ptr dsb;
643  luaL_checkany(L, valind);
644  const char* type = luaL_checkstring(L, typeind); /* target dsb type */
645  dsb = Variable_fromlua(L, type, valind);
646  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(dsb);
647  return 1;
648 }
649 
650 static int Variable_new(lua_State *L)
651 {
652  int argc = lua_gettop(L);
653  if(argc == 1)
654  return Variable_create(L);
655  else if(argc == 2)
656  return Variable_create_ival(L, 1, 2);
657  else
658  luaL_error(L, "Variable.new: invalid number of args");
659 
660  return 0;
661 }
662 
663 static int Variable_toString(lua_State *L)
664 {
665  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
666  lua_pushstring(L, ((*dsbp)->toString()).c_str());
667  return 1;
668 }
669 
670 static int Variable_getType(lua_State *L)
671 {
672  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
673  lua_pushstring(L, (*dsbp)->getType().c_str());
674  return 1;
675 }
676 
677 static int Variable_getTypeIdName(lua_State *L)
678 {
679  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
680  lua_pushstring(L, (*dsbp)->getTypeInfo()->getTypeIdName());
681  return 1;
682 }
683 
684 static int Variable_getTypeName(lua_State *L)
685 {
686  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
687  lua_pushstring(L, (*dsbp)->getTypeName().c_str());
688  return 1;
689 }
690 
691 static int Variable_resize(lua_State *L)
692 {
693  int size;
694  DataSourceBase::shared_ptr *dsbp = luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr);
695  size = luaL_checknumber(L, 2);
696  const TypeInfo *ti = (*dsbp)->getTypeInfo();
697  lua_pushboolean(L, ti->resize(*dsbp, size));
698  return 1;
699 }
700 
701 
702 /*
703  * Operators
704  */
705 static int Variable_unm(lua_State *L)
706 {
707  types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance();
708  DataSourceBase::shared_ptr arg = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
709  DataSourceBase::shared_ptr res = opreg->applyUnary("-", arg.get());
710  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res);
711  return 1;
712 }
713 
714 
715 /* don't try this at home */
716 #define gen_opmet(name, op) \
717 static int name(lua_State *L) \
718 { \
719  DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); \
720  DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)); \
721  types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); \
722  DataSourceBase *res = opreg->applyBinary(#op, arg1.get(), arg2.get()); \
723  if(res == 0) \
724  luaL_error(L , "%s (operator %s) failed", #name, #op); \
725  res->evaluate(); \
726  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res); \
727  return 1; \
728 } \
729 
730 gen_opmet(Variable_add, +)
731 gen_opmet(Variable_sub, -)
732 gen_opmet(Variable_mul, *)
733 gen_opmet(Variable_div, /)
734 gen_opmet(Variable_mod, %)
735 gen_opmet(Variable_pow, ^)
736 
737 /* these flavors convert the boolean return dsb to a lua bool */
738 #define gen_opmet_bool(name, op) \
739 static int name(lua_State *L) \
740 { \
741  DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr)); \
742  DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)); \
743  types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance(); \
744  DataSourceBase *res = opreg->applyBinary(#op, arg1.get(), arg2.get()); \
745  if(res == 0) \
746  luaL_error(L , "%s (operator %s) failed", #name, #op); \
747  res->evaluate(); \
748  return __Variable_tolua(L, res); \
749 } \
750 
751 gen_opmet_bool(Variable_eq, ==)
752 gen_opmet_bool(Variable_lt, <)
753 gen_opmet_bool(Variable_le, <=)
754 
755 static int Variable_opBinary(lua_State *L)
756 {
757  types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance();
758  const char *op = luaL_checkstring(L, 1);
759  DataSourceBase::shared_ptr arg1 = *(luaM_checkudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr));
760  DataSourceBase::shared_ptr arg2 = *(luaM_checkudata_mt(L, 3, "Variable", DataSourceBase::shared_ptr));
761  DataSourceBase *res;
762 
763  res = opreg->applyBinary(op, arg1.get(), arg2.get());
764  if(res == 0)
765  luaL_error(L , "Variable.opBinary '%s' not applicable to args", op);
766 
767  res->evaluate();
768 
769  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(res);
770  return 1;
771 }
772 
773 /*
774  * this is a dispatcher which checks if the key is a method, otherwise
775  * calls get for looking up the field. Inspired by
776  * http://lua-users.org/wiki/ObjectProperties
777  */
778 static int Variable_index(lua_State *L)
779 {
780  const char* key = luaL_checkstring(L, 2);
781 
782  lua_getmetatable(L, 1);
783  lua_getfield(L, -1, key);
784 
785  /* Either key is name of a method in the metatable */
786  if(!lua_isnil(L, -1))
787  return 1;
788 
789  /* ... or its a field access, so recall as self.get(self, value). */
790  lua_settop(L, 2);
791  return Variable_getMember(L);
792 }
793 
794 static int Variable_newindex(lua_State *L)
795 {
796  DataSourceBase::shared_ptr *newvalp;
797  DataSourceBase::shared_ptr newval;
798  DataSourceBase::shared_ptr parent = *(luaM_checkudata_mt(L, 1, "Variable", DataSourceBase::shared_ptr));
799  const char* mem = luaL_checkstring(L, 2);
800 
801  /* get dsb to be updated: we need its type before get-or-create'ing arg3 */
802  types::OperatorRepository::shared_ptr opreg = types::OperatorRepository::Instance();
803  DataSourceBase::shared_ptr curval;
804 
805  if ((curval = lookup_member(L, parent, mem)) == 0)
806  luaL_error(L, "Variable.newindex: indexing failed, no member %s", mem);
807 
808 
809  /* assigning a DSB */
810  if ((newvalp = luaM_testudata_mt(L, 3, "Variable", DataSourceBase::shared_ptr)) != NULL) {
811  newval = *newvalp;
812  if(!curval->update(newval.get())) {
813  luaL_error(L, "Variable.newindex: failed to assign %s to member %s of type %s",
814  newval->getType().c_str(), mem, curval->getType().c_str());
815  }
816  } else /* assigning basic type */
817  Variable_fromlua(L, curval, 3);
818  return 1;
819 }
820 
821 // Why doesn't the following work:
822 // static int Variable_gc(lua_State *L)
823 // {
824 // DataSourceBase::shared_ptr *dsbp = (DataSourceBase::shared_ptr*) lua_touserdata(L, 1);
825 // cache_clear(L, dsbp->get());
826 // dsbp->~DataSourceBase::shared_ptr();
827 // return 0;
828 // }
829 
830 template<typename T>
831 int VariableGC(lua_State* L)
832 {
833  T* dsbp = (T*) lua_touserdata(L, 1);
834  cache_clear(L, dsbp->get());
835  reinterpret_cast<T*>(dsbp)->~T();
836  return 0;
837 }
838 
839 
840 static const struct luaL_Reg Variable_f [] = {
841  { "new", Variable_new },
842  { "tolua", Variable_tolua },
843  { "isbasic", Variable_isbasic },
844  { "toString", Variable_toString },
845  { "getTypes", Variable_getTypes },
846  { "getType", Variable_getType },
847  { "getTypeName", Variable_getTypeName },
848  { "getTypeIdName", Variable_getTypeIdName },
849  { "getMemberNames", Variable_getMemberNames },
850  { "getMember", Variable_getMember },
851  { "getMemberRaw", Variable_getMemberRaw },
852  { "tolud", Variable_tolightuserdata },
853  { "resize", Variable_resize },
854  { "opBinary", Variable_opBinary },
855  { "assign", Variable_update }, /* assign seems a better name than update */
856  { "unm", Variable_unm },
857  { "add", Variable_add },
858  { "sub", Variable_sub },
859  { "mul", Variable_mul },
860  { "div", Variable_div },
861  { "mod", Variable_mod },
862  { "pow", Variable_pow },
863  { "eq", Variable_eq },
864  { "lt", Variable_lt },
865  { "le", Variable_le },
866  { NULL, NULL}
867 };
868 
869 static const struct luaL_Reg Variable_m [] = {
870  { "tolua", Variable_tolua },
871  { "isbasic", Variable_isbasic },
872  { "toString", Variable_toString },
873  { "getType", Variable_getType },
874  { "getTypeName", Variable_getTypeName },
875  { "getTypeIdName", Variable_getTypeIdName },
876  { "getMemberNames", Variable_getMemberNames },
877  { "getMember", Variable_getMember },
878  { "getMemberRaw", Variable_getMemberRaw },
879  { "tolud", Variable_tolightuserdata },
880  { "resize", Variable_resize },
881  { "opBinary", Variable_opBinary },
882  { "assign", Variable_update }, /* assign seems a better name than update */
883  { "__unm", Variable_unm },
884  { "__add", Variable_add },
885  { "__sub", Variable_sub },
886  { "__mul", Variable_mul },
887  { "__div", Variable_div },
888  { "__mod", Variable_mod },
889  { "__pow", Variable_pow },
890  { "__eq", Variable_eq },
891  { "__lt", Variable_lt },
892  { "__le", Variable_le },
893  { "__index", Variable_index },
894  { "__newindex", Variable_newindex },
895  // { "__gc", GCMethod<DataSourceBase::shared_ptr> },
896  // {"__gc", Variable_gc},
897  {"__gc", VariableGC<DataSourceBase::shared_ptr> },
898  { NULL, NULL}
899 };
900 
901 
902 /***************************************************************
903  * Property (boxed)
904  ***************************************************************/
905 
906 gen_push_bxptr(Property_push, "Property", PropertyBase)
907 
908 static int Property_new(lua_State *L)
909 {
910  const char *type, *name, *desc;
911  PropertyBase *pb;
912  int argc = lua_gettop(L);
913  type = luaL_checkstring(L, 1);
914 
915  /* name and description are optional */
916  name = (argc > 1) ? luaL_checkstring(L, 2) : "";
917  desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
918 
919  types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
920 
921  if(!ti)
922  luaL_error(L, "Property.new: unknown type %s", type);
923 
924  pb = ti->buildProperty(name, desc);
925  Property_push(L, pb);
926  return 1;
927 }
928 
929 static int Property_get(lua_State *L)
930 {
931  PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
932  Variable_push_coerce(L, pb->getDataSource());
933  return 1;
934 }
935 
936 static int Property_getRaw(lua_State *L)
937 {
938  PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
939  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(pb->getDataSource());
940  return 1;
941 }
942 
943 static int Property_set(lua_State *L)
944 {
945  DataSourceBase::shared_ptr newdsb;
946  DataSourceBase::shared_ptr *newdsbp;
947  DataSourceBase::shared_ptr propdsb;
948  PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
949  propdsb = pb->getDataSource();
950 
951  /* assigning a DSB */
952  if ((newdsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
953  newdsb = *newdsbp;
954  if(!propdsb->update(newdsb.get()))
955  luaL_error(L, "Property.set: failed to assign type %s to type %s",
956  newdsb->getType().c_str(), propdsb->getType().c_str());
957  } else { /* assigning a Lua value */
958  Variable_fromlua(L, propdsb, 2);
959  }
960  return 1;
961 }
962 
963 static int Property_info(lua_State *L)
964 {
965  PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
966  lua_newtable(L);
967  lua_pushstring(L, "name"); lua_pushstring(L, pb->getName().c_str()); lua_rawset(L, -3);
968  lua_pushstring(L, "desc"); lua_pushstring(L, pb->getDescription().c_str()); lua_rawset(L, -3);
969  lua_pushstring(L, "type"); lua_pushstring(L, pb->getType().c_str()); lua_rawset(L, -3);
970  return 1;
971 }
972 
973 #if NOT_USED_YET
974 /*
975  * Race condition if we collect properties: if we add this property to
976  * a TC and our life ends before that of the TC, the property will be
977  * deleted before the TaskContext.
978  */
979 static int Property_gc(lua_State *L)
980 {
981  PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
982  delete pb;
983  return 0;
984 }
985 #endif
986 
987 /* only explicit destruction allowed */
988 static int Property_del(lua_State *L)
989 {
990  PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Property", PropertyBase));
991  delete pb;
992 
993  /* this prevents calling rtt methods which would cause a crash */
994  luaL_getmetatable(L, "__dead__");
995  lua_setmetatable(L, -2);
996  return 0;
997 }
998 
999 /* indexability of properties */
1000 /*
1001  * this is a dispatcher which checks if the key is a method, otherwise
1002  * calls get for looking up the field. Inspired by
1003  * http://lua-users.org/wiki/ObjectProperties
1004  */
1005 static int Property_index(lua_State *L)
1006 {
1007  const char* key = luaL_checkstring(L, 2);
1008 
1009  lua_getmetatable(L, 1);
1010  lua_getfield(L, -1, key); /* this actually calls the method */
1011 
1012  /* Either key is name of a method in the metatable */
1013  if(!lua_isnil(L, -1))
1014  return 1;
1015 
1016  lua_settop(L, 2); /* reset stack */
1017  Property_get(L); /* pushes property var */
1018  lua_replace(L, 1); /* replace prop with var */
1019  return Variable_index(L);
1020 }
1021 
1022 static int Property_newindex(lua_State *L)
1023 {
1024  Property_get(L);
1025  lua_replace(L, 1);
1026  return Variable_newindex(L);
1027 }
1028 
1029 static const struct luaL_Reg Property_f [] = {
1030  {"new", Property_new },
1031  {"get", Property_get },
1032  {"getRaw", Property_getRaw },
1033  {"set", Property_set },
1034  {"info", Property_info },
1035  {"delete", Property_del },
1036  {NULL, NULL}
1037 };
1038 
1039 static const struct luaL_Reg Property_m [] = {
1040  {"get", Property_get },
1041  {"getRaw", Property_getRaw },
1042  {"set", Property_set },
1043  {"info", Property_info },
1044  // todo: shall we or not? s.o. {"__gc", Property_gc },
1045  {"delete", Property_del },
1046  {"__index", Property_index },
1047  {"__newindex", Property_newindex },
1048  {NULL, NULL}
1049 };
1050 
1051 /***************************************************************
1052  * Attribute (boxed)
1053  ***************************************************************/
1054 
1055 gen_push_bxptr(Attribute_push, "Attribute", AttributeBase)
1056 
1057 static int Attribute_new(lua_State *L)
1058 {
1059  const char *type, *name;
1060  AttributeBase *pb;
1061  int argc = lua_gettop(L);
1062  type = luaL_checkstring(L, 1);
1063 
1064  /* name and description are optional */
1065  name = (argc > 1) ? luaL_checkstring(L, 2) : "";
1066 
1067  types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
1068 
1069  if(!ti)
1070  luaL_error(L, "Attribute.new: unknown type %s", type);
1071 
1072  pb = ti->buildAttribute(name);
1073  Attribute_push(L, pb);
1074  return 1;
1075 }
1076 
1077 static int Attribute_get(lua_State *L)
1078 {
1079  AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
1080  Variable_push_coerce(L, pb->getDataSource());
1081  return 1;
1082 }
1083 
1084 static int Attribute_getRaw(lua_State *L)
1085 {
1086  AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
1087  luaM_pushobject_mt(L, "Variable", DataSourceBase::shared_ptr)(pb->getDataSource());
1088  return 1;
1089 }
1090 
1091 static int Attribute_set(lua_State *L)
1092 {
1093  DataSourceBase::shared_ptr newdsb;
1094  DataSourceBase::shared_ptr *newdsbp;
1095  DataSourceBase::shared_ptr propdsb;
1096  AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
1097  propdsb = pb->getDataSource();
1098 
1099  /* assigning a DSB */
1100  if ((newdsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
1101  newdsb = *newdsbp;
1102  if(!propdsb->update(newdsb.get()))
1103  luaL_error(L, "Attribute.set: failed to assign type %s to type %s",
1104  newdsb->getType().c_str(), propdsb->getType().c_str());
1105  } else { /* assigning a Lua value */
1106  Variable_fromlua(L, propdsb, 2);
1107  }
1108  return 1;
1109 }
1110 
1111 static int Attribute_info(lua_State *L)
1112 {
1113  AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
1114  lua_newtable(L);
1115  lua_pushstring(L, "name"); lua_pushstring(L, pb->getName().c_str()); lua_rawset(L, -3);
1116  lua_pushstring(L, "type"); lua_pushstring(L, pb->getDataSource()->getType().c_str()); lua_rawset(L, -3);
1117  return 1;
1118 }
1119 
1120 #if NOT_USED_YET
1121 /*
1122  * Race condition if we collect properties: if we add this attribute to
1123  * a TC and our life ends before that of the TC, the attribute will be
1124  * deleted before the TaskContext.
1125  */
1126 static int Attribute_gc(lua_State *L)
1127 {
1128  AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
1129  delete pb;
1130  return 0;
1131 }
1132 #endif
1133 
1134 
1135 /* only explicit destruction allowed */
1136 static int Attribute_del(lua_State *L)
1137 {
1138  AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 1, "Attribute", AttributeBase));
1139  delete pb;
1140 
1141  /* this prevents calling rtt methods which would cause a crash */
1142  luaL_getmetatable(L, "__dead__");
1143  lua_setmetatable(L, -2);
1144  return 0;
1145 }
1146 
1147 /* indexability of properties */
1148 /*
1149  * this is a dispatcher which checks if the key is a method, otherwise
1150  * calls get for looking up the field. Inspired by
1151  * http://lua-users.org/wiki/ObjectProperties
1152  */
1153 static int Attribute_index(lua_State *L)
1154 {
1155  const char* key = luaL_checkstring(L, 2);
1156 
1157  lua_getmetatable(L, 1);
1158  lua_getfield(L, -1, key); /* this actually calls the method */
1159 
1160  /* Either key is name of a method in the metatable */
1161  if(!lua_isnil(L, -1))
1162  return 1;
1163 
1164  lua_settop(L, 2); /* reset stack */
1165  Attribute_get(L); /* pushes attribute var */
1166  lua_replace(L, 1); /* replace prop with var */
1167  return Variable_index(L);
1168 }
1169 
1170 static int Attribute_newindex(lua_State *L)
1171 {
1172  Attribute_get(L);
1173  lua_replace(L, 1);
1174  return Variable_newindex(L);
1175 }
1176 
1177 static const struct luaL_Reg Attribute_f [] = {
1178  {"new", Attribute_new },
1179  {"get", Attribute_get },
1180  {"getRaw", Attribute_getRaw },
1181  {"set", Attribute_set },
1182  {"info", Attribute_info },
1183  {"delete", Attribute_del },
1184  {NULL, NULL}
1185 };
1186 
1187 static const struct luaL_Reg Attribute_m [] = {
1188  {"get", Attribute_get },
1189  {"getRaw", Attribute_getRaw },
1190  {"set", Attribute_set },
1191  {"info", Attribute_info },
1192  // todo: shall we or not? s.o. {"__gc", Attribute_gc },
1193  {"delete", Attribute_del },
1194  {"__index", Attribute_index },
1195  {"__newindex", Attribute_newindex },
1196  {NULL, NULL}
1197 };
1198 
1199 /***************************************************************
1200  * Ports (boxed)
1201  ***************************************************************/
1202 
1203 /* both input or output */
1204 static int Port_info(lua_State *L)
1205 {
1206  int arg_type;
1207  const char* port_type = NULL;
1208  PortInterface **pip;
1209  PortInterface *pi = NULL;
1210 
1211  if((pip = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
1212  pi = *pip;
1213  port_type = "in";
1214  } else if((pip = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
1215  pi = *pip;
1216  port_type = "out";
1217  }
1218  else {
1219  arg_type = lua_type(L, 1);
1220  luaL_error(L, "Port.info: invalid argument, expected Port, got %s",
1221  lua_typename(L, arg_type));
1222  }
1223 
1224  lua_newtable(L);
1225  lua_pushstring(L, "name"); lua_pushstring(L, pi->getName().c_str()); lua_rawset(L, -3);
1226  lua_pushstring(L, "desc"); lua_pushstring(L, pi->getDescription().c_str()); lua_rawset(L, -3);
1227  lua_pushstring(L, "connected"); lua_pushboolean(L, pi->connected()); lua_rawset(L, -3);
1228  lua_pushstring(L, "isLocal"); lua_pushboolean(L, pi->isLocal()); lua_rawset(L, -3);
1229  lua_pushstring(L, "type"); lua_pushstring(L, pi->getTypeInfo()->getTypeName().c_str()); lua_rawset(L, -3);
1230  lua_pushstring(L, "porttype"); lua_pushstring(L, port_type); lua_rawset(L, -3);
1231 
1232  return 1;
1233 }
1234 
1235 static int Port_connect(lua_State *L)
1236 {
1237  int arg_type, ret;
1238  PortInterface **pip1, **pip2;
1239  PortInterface *pi1 = NULL;
1240  PortInterface *pi2 = NULL;
1241  ConnPolicy **cpp;
1242  ConnPolicy *cp = NULL;
1243 
1244  if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
1245  pi1= *pip1;
1246  } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
1247  pi1= *pip1;
1248  }
1249  else {
1250  arg_type = lua_type(L, 1);
1251  luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s",
1252  lua_typename(L, arg_type));
1253  }
1254  if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) {
1255  pi2= *pip2;
1256  } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) {
1257  pi2= *pip2;
1258  }
1259  else {
1260  arg_type = lua_type(L, 2);
1261  luaL_error(L, "Port.connect: invalid argument 2, expected Port, got %s",
1262  lua_typename(L, arg_type));
1263  }
1264 
1265  if((cpp = (ConnPolicy**) luaL_testudata(L, 3, "ConnPolicy")) != NULL) {
1266  cp=*cpp;
1267  }
1268 
1269  if ( cp )
1270  ret = pi1->connectTo(pi2, *cp);
1271  else
1272  ret = pi1->connectTo(pi2);
1273 
1274  lua_pushboolean(L, ret);
1275 
1276  return 1;
1277 }
1278 
1279 static int Port_disconnect(lua_State *L)
1280 {
1281  int arg_type, ret;
1282  PortInterface **pip1, **pip2;
1283  PortInterface *pi1 = NULL;
1284  PortInterface *pi2 = NULL;
1285 
1286  if((pip1 = (PortInterface**) luaL_testudata(L, 1, "InputPort")) != NULL) {
1287  pi1= *pip1;
1288  } else if((pip1 = (PortInterface**) luaL_testudata(L, 1, "OutputPort")) != NULL) {
1289  pi1= *pip1;
1290  }
1291  else {
1292  arg_type = lua_type(L, 1);
1293  luaL_error(L, "Port.info: invalid argument 1, expected Port, got %s",
1294  lua_typename(L, arg_type));
1295  }
1296  if((pip2 = (PortInterface**) luaL_testudata(L, 2, "InputPort")) != NULL) {
1297  pi2= *pip2;
1298  } else if((pip2 = (PortInterface**) luaL_testudata(L, 2, "OutputPort")) != NULL) {
1299  pi2= *pip2;
1300  }
1301 
1302  if (pi2 != NULL)
1303  ret = pi1->disconnect(pi2);
1304  else{
1305  pi1->disconnect();
1306  ret = 1;
1307  }
1308  lua_pushboolean(L, ret);
1309 
1310  return 1;
1311 }
1312 
1313 
1314 
1315 /* InputPort (boxed) */
1316 
1317 gen_push_bxptr(InputPort_push, "InputPort", InputPortInterface)
1318 
1319 static int InputPort_new(lua_State *L)
1320 {
1321  const char *type, *name, *desc;
1322  InputPortInterface* ipi;
1323  int argc = lua_gettop(L);
1324 
1325  type = luaL_checkstring(L, 1);
1326 
1327  /* name and description are optional */
1328  name = (argc > 1) ? luaL_checkstring(L, 2) : "";
1329  desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
1330 
1331  types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
1332  if(ti==0)
1333  luaL_error(L, "InputPort.new: unknown type %s", type);
1334 
1335  ipi = ti->inputPort(name);
1336 
1337  if(!ipi)
1338  luaL_error(L, "InputPort.new: creating port of type %s failed", type);
1339 
1340  ipi->doc(desc);
1341  InputPort_push(L, ipi);
1342  return 1;
1343 }
1344 
1345 static int InputPort_read(lua_State *L)
1346 {
1347  int ret = 1;
1348  InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
1349  DataSourceBase::shared_ptr dsb;
1350  DataSourceBase::shared_ptr *dsbp;
1351  FlowStatus fs;
1352 
1353  /* if we get don't get a DS to store the result, create one */
1354  if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL)
1355  dsb = *dsbp;
1356  else {
1357  dsb = ip->getTypeInfo()->buildValue();
1358  ret = 2;
1359  }
1360 
1361  fs = ip->read(dsb);
1362 
1363  if(fs == NoData) lua_pushstring(L, "NoData");
1364  else if (fs == NewData) lua_pushstring(L, "NewData");
1365  else if (fs == OldData) lua_pushstring(L, "OldData");
1366  else luaL_error(L, "InputPort.read: unknown FlowStatus returned");
1367 
1368  if(ret>1)
1369  Variable_push_coerce(L, dsb);
1370 
1371  return ret;
1372 }
1373 
1374 #ifdef NOT_USED_YET
1375 static int InputPort_gc(lua_State *L)
1376 {
1377  InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
1378  delete ip;
1379  return 0;
1380 }
1381 #endif
1382 
1383 /* only explicit destruction allowed */
1384 static int InputPort_del(lua_State *L)
1385 {
1386  InputPortInterface *ip = *(luaM_checkudata_mt_bx(L, 1, "InputPort", InputPortInterface));
1387  delete ip;
1388 
1389  /* this prevents calling rtt methods which would cause a crash */
1390  luaL_getmetatable(L, "__dead__");
1391  lua_setmetatable(L, -2);
1392  return 0;
1393 }
1394 
1395 static const struct luaL_Reg InputPort_f [] = {
1396  {"new", InputPort_new },
1397  {"read", InputPort_read },
1398  {"info", Port_info },
1399  {"connect", Port_connect },
1400  {"disconnect", Port_disconnect },
1401  {"delete", InputPort_del },
1402  {NULL, NULL}
1403 };
1404 
1405 static const struct luaL_Reg InputPort_m [] = {
1406  {"read", InputPort_read },
1407  {"info", Port_info },
1408  {"delete", InputPort_del },
1409  {"connect", Port_connect },
1410  {"disconnect", Port_disconnect },
1411  /* {"__gc", InputPort_gc }, */
1412  {NULL, NULL}
1413 };
1414 
1415 /* OutputPort */
1416 
1417 gen_push_bxptr(OutputPort_push, "OutputPort", OutputPortInterface)
1418 
1419 
1420 static int OutputPort_new(lua_State *L)
1421 {
1422  const char *type, *name, *desc;
1423  OutputPortInterface* opi;
1424  int argc = lua_gettop(L);
1425 
1426  type = luaL_checkstring(L, 1);
1427 
1428  /* name and description are optional */
1429  name = (argc > 1) ? luaL_checkstring(L, 2) : "";
1430  desc = (argc > 2) ? luaL_checkstring(L, 3) : "";
1431 
1432  types::TypeInfo *ti = types::TypeInfoRepository::Instance()->type(type);
1433 
1434  if(ti==0)
1435  luaL_error(L, "OutputPort.new: unknown type %s", type);
1436 
1437  opi = ti->outputPort(name);
1438 
1439  if(!opi)
1440  luaL_error(L, "OutputPort.new: creating port of type %s failed", type);
1441 
1442  opi->doc(desc);
1443  OutputPort_push(L, opi);
1444  return 1;
1445 }
1446 
1447 static int OutputPort_write(lua_State *L)
1448 {
1449  DataSourceBase::shared_ptr dsb;
1450  DataSourceBase::shared_ptr *dsbp;
1451 
1452  OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
1453 
1454  /* fastpath: Variable argument */
1455  if ((dsbp = luaM_testudata_mt(L, 2, "Variable", DataSourceBase::shared_ptr)) != NULL) {
1456  dsb = *dsbp;
1457  } else {
1458  /* slowpath: convert lua value to dsb */
1459  dsb = Variable_fromlua(L, op->getTypeInfo(), 2);
1460  }
1461  op->write(dsb);
1462  return 0;
1463 }
1464 
1465 #ifdef NOT_USED_YET
1466 static int OutputPort_gc(lua_State *L)
1467 {
1468  OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
1469  delete op;
1470  return 0;
1471 }
1472 #endif
1473 
1474 /* only explicit destruction allowed */
1475 static int OutputPort_del(lua_State *L)
1476 {
1477  OutputPortInterface *op = *(luaM_checkudata_mt_bx(L, 1, "OutputPort", OutputPortInterface));
1478  delete op;
1479 
1480  /* this prevents calling rtt methods which would cause a crash */
1481  luaL_getmetatable(L, "__dead__");
1482  lua_setmetatable(L, -2);
1483  return 0;
1484 }
1485 
1486 static const struct luaL_Reg OutputPort_f [] = {
1487  {"new", OutputPort_new },
1488  {"write", OutputPort_write },
1489  {"info", Port_info },
1490  {"connect", Port_connect },
1491  {"disconnect", Port_disconnect },
1492  {"delete", OutputPort_del },
1493  {NULL, NULL}
1494 };
1495 
1496 static const struct luaL_Reg OutputPort_m [] = {
1497  {"write", OutputPort_write },
1498  {"info", Port_info },
1499  {"connect", Port_connect },
1500  {"disconnect", Port_disconnect },
1501  {"delete", OutputPort_del },
1502  /* {"__gc", OutputPort_gc }, */
1503  {NULL, NULL}
1504 };
1505 
1506 /***************************************************************
1507  * Operation
1508  ***************************************************************/
1509 
1511  OperationInterfacePart *oip;
1512  OperationCallerC *occ;
1513  unsigned int arity;
1514  bool is_void;
1515 
1516  /* we need to store references to the dsb which we created
1517  on-the-fly, because the ReferenceDSB does not hold a
1518  shared_ptr, and hence these DSN might get destructed
1519  before/during the call
1520  */
1521  std::vector<base::DataSourceBase::shared_ptr> dsb_store;
1522  std::vector<internal::Reference*> args;
1523  base::DataSourceBase::shared_ptr call_dsb;
1524  base::DataSourceBase::shared_ptr ret_dsb;
1525 };
1526 
1527 template<typename T>
1528 int OperationGC(lua_State* L)
1529 {
1530  T* oh = (T*) lua_touserdata(L, 1);
1531  delete oh->occ;
1532  reinterpret_cast<T*>(lua_touserdata(L, 1))->~T();
1533  return 0;
1534 }
1535 
1536 static int Operation_info(lua_State *L)
1537 {
1538  int i=1;
1539  std::vector<ArgumentDescription> args;
1540  OperationHandle *op = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
1541 
1542  lua_pushstring(L, op->oip->getName().c_str()); /* name */
1543  lua_pushstring(L, op->oip->description().c_str()); /* description */
1544  lua_pushstring(L, op->oip->resultType().c_str()); /* result type */
1545  lua_pushinteger(L, op->arity); /* arity */
1546 
1547  args = op->oip->getArgumentList();
1548 
1549  lua_newtable(L);
1550 
1551  for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) {
1552  lua_newtable(L);
1553  lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3);
1554  lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3);
1555  lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3);
1556  lua_rawseti(L, -2, i++);
1557  }
1558  return 5;
1559 }
1560 
1561 static int __Operation_call(lua_State *L)
1562 {
1563  bool ret;
1564  DataSourceBase::shared_ptr dsb, *dsbp;
1565 
1566  OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
1567  OperationInterfacePart *oip = oh->oip;
1568  unsigned int argc = lua_gettop(L);
1569 
1570  if(oh->arity != argc-1)
1571  luaL_error(L, "Operation.call: wrong number of args. expected %d, got %d", oh->arity, argc-1);
1572 
1573  /* update dsbs */
1574  for(unsigned int arg=2; arg<=argc; arg++) {
1575  /* fastpath: Variable argument */
1576  if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) {
1577  dsb = *dsbp;
1578  } else {
1579  /* slowpath: convert lua value to dsb */
1580  dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg);
1581  /* this dsb must outlive occ->call (see comment in
1582  OperationHandle def.): */
1583  oh->dsb_store.push_back(dsb);
1584  }
1585  if(!dsb->isAssignable())
1586  luaL_error(L, "Operation.call: argument %d is not assignable.", arg-1);
1587 
1588  ret = oh->args[arg-2]->setReference(dsb);
1589  if (!ret)
1590  luaL_error(L, "Operation_call: setReference failed, wrong type of argument?");
1591  }
1592 
1593  if(!oh->occ->call())
1594  luaL_error(L, "Operation.call: call failed.");
1595 
1596  oh->dsb_store.clear();
1597 
1598  if(!oh->is_void)
1599  Variable_push_coerce(L, oh->ret_dsb);
1600  else
1601  lua_pushnil(L);
1602  return 1;
1603 }
1604 
1605 static int __Operation_send(lua_State *L)
1606 {
1607  DataSourceBase::shared_ptr dsb, *dsbp;
1608 
1609  OperationHandle *oh = luaM_checkudata_mt(L, 1, "Operation", OperationHandle);
1610  OperationInterfacePart *oip = oh->oip;
1611  unsigned int argc = lua_gettop(L);
1612 
1613  if(oh->arity != argc-1)
1614  luaL_error(L, "Operation.send: wrong number of args. expected %d, got %d", oh->arity, argc-1);
1615 
1616  /* update dsbs */
1617  for(unsigned int arg=2; arg<=argc; arg++) {
1618  /* fastpath: Variable argument */
1619  if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL) {
1620  dsb = *dsbp;
1621  } else {
1622  /* slowpath: convert lua value to dsb */
1623  dsb = Variable_fromlua(L, oip->getArgumentType(arg-1), arg);
1624  /* this dsb must outlive occ->call (see comment in
1625  OperationHandle def.): */
1626  oh->dsb_store.push_back(dsb);
1627  }
1628  oh->args[arg-2]->setReference(dsb);
1629  }
1630 
1631  luaM_pushobject_mt(L, "SendHandle", SendHandleC)(oh->occ->send());
1632  return 1;
1633 }
1634 
1635 static int Operation_call(lua_State *L)
1636 {
1637  int ret;
1638  try {
1639  ret = __Operation_call(L);
1640  } catch(const std::exception &exc) {
1641  luaL_error(L, "Operation.call: caught exception '%s'", exc.what());
1642  } catch(...) {
1643  luaL_error(L, "Operation.call: caught unknown exception");
1644  }
1645  return ret;
1646 }
1647 
1648 static int Operation_send(lua_State *L)
1649 {
1650  int ret;
1651  try {
1652  ret = __Operation_send(L);
1653  } catch(const std::exception &exc) {
1654  luaL_error(L, "Operation.send: caught exception '%s'", exc.what());
1655  } catch(...) {
1656  luaL_error(L, "Operation.send: caught unknown exception");
1657  }
1658  return ret;
1659 }
1660 
1661 
1662 static const struct luaL_Reg Operation_f [] = {
1663  { "info", Operation_info },
1664  { "call", Operation_call },
1665  { "send", Operation_send },
1666  { NULL, NULL }
1667 
1668 };
1669 
1670 static const struct luaL_Reg Operation_m [] = {
1671  { "info", Operation_info },
1672  { "send", Operation_send },
1673  { "__call", Operation_call },
1674  { "__gc", OperationGC<OperationHandle> },
1675  { NULL, NULL }
1676 };
1677 
1678 /***************************************************************
1679  * Service (boxed)
1680  ***************************************************************/
1681 
1682 static int Service_getName(lua_State *L)
1683 {
1684  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1685  lua_pushstring(L, srv->getName().c_str());
1686  return 1;
1687 }
1688 
1689 static int Service_doc(lua_State *L)
1690 {
1691  int ret;
1692  const char* doc;
1693  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1694  if(lua_gettop(L) == 1) {
1695  lua_pushstring(L, srv->doc().c_str());
1696  ret = 1;
1697  } else {
1698  doc = luaL_checkstring(L, 2);
1699  srv->doc(doc);
1700  ret = 0;
1701  }
1702 
1703  return ret;
1704 }
1705 
1706 static int Service_getProviderNames(lua_State *L)
1707 {
1708  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1709  push_vect_str(L, srv->getProviderNames());
1710  return 1;
1711 }
1712 
1713 static int Service_getOperationNames(lua_State *L)
1714 {
1715  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1716  push_vect_str(L, srv->getOperationNames());
1717  return 1;
1718 }
1719 
1720 
1721 static int Service_hasOperation(lua_State *L)
1722 {
1723  int ret;
1724  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1725  const char* op = luaL_checkstring(L, 2);
1726  ret = srv->hasOperation(op);
1727  lua_pushboolean(L, ret);
1728  return 1;
1729 }
1730 
1731 static int Service_getPortNames(lua_State *L)
1732 {
1733  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1734  push_vect_str(L, srv->getPortNames());
1735  return 1;
1736 }
1737 
1738 static int Service_provides(lua_State *L)
1739 {
1740  int ret, i, argc;
1741  const char* subsrv_str;
1742  Service::shared_ptr srv, subsrv;
1743 
1744  srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1745  argc=lua_gettop(L);
1746 
1747  /* return "this" if no args given */
1748  if(argc == 1) {
1749  ret = 1;
1750  goto out;
1751  }
1752 
1753  for(i=2; i<=argc; i++) {
1754  subsrv_str = luaL_checkstring(L, i);
1755  subsrv = srv->getService(subsrv_str);
1756  if (subsrv == 0)
1757  luaL_error(L, "Service.provides: no subservice %s of service %s",
1758  subsrv_str, srv->getName().c_str() );
1759  else
1760  luaM_pushobject_mt(L, "Service", Service::shared_ptr)(subsrv);
1761  }
1762  ret = argc - 1;
1763 
1764  out:
1765  return ret;
1766 }
1767 
1768 static int Service_getOperation(lua_State *L)
1769 {
1770  const char *op_str;
1771  OperationInterfacePart *oip;
1772  Service::shared_ptr srv;
1773  DataSourceBase::shared_ptr dsb;
1774  const types::TypeInfo *ti;
1775  OperationHandle *oh;
1776  TaskContext *this_tc;
1777 
1778  srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1779  op_str = luaL_checkstring(L, 2);
1780  oip = srv->getOperation(op_str);
1781 
1782  if(!oip)
1783  luaL_error(L, "Service_getOperation: service %s has no operation %s",
1784  srv->getName().c_str(), op_str);
1785 
1786  oh = (OperationHandle*) luaM_pushobject_mt(L, "Operation", OperationHandle)();
1787  oh->oip = oip;
1788  oh->arity = oip->arity();
1789  oh->args.reserve(oh->arity);
1790  this_tc = __getTC(L);
1791 
1792  oh->occ = new OperationCallerC(oip, op_str, this_tc->engine());
1793 
1794  /* create args
1795  * getArgumentType(0) is return value
1796  */
1797  for(unsigned int arg=1; arg <= oh->arity; arg++) {
1798  std::string type = oip->getArgumentType(arg)->getTypeName();
1799  ti = types::TypeInfoRepository::Instance()->type(type);
1800  if(!ti)
1801  luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for arg %d of type '%s'",
1802  op_str, arg, type.c_str());
1803 
1804  dsb = ti->buildReference((void*) 0xdeadbeef);
1805  if(!dsb)
1806  luaL_error(L, "Operation.call: '%s', failed to build DSB for arg %d of type '%s'",
1807  op_str, arg, type.c_str());
1808 
1809  oh->args.push_back(dynamic_cast<internal::Reference*>(dsb.get()));
1810  oh->occ->arg(dsb);
1811  }
1812 
1813  /* return value */
1814  if(oip->resultType() != "void"){
1815  ti = oip->getArgumentType(0); // 0 == return type
1816  if(!ti)
1817  luaL_error(L, "Operation.call: '%s', failed to locate TypeInfo for return value of type '%s'",
1818  op_str, oip->resultType().c_str());
1819  oh->ret_dsb=ti->buildValue();
1820  if(!oh->ret_dsb)
1821  luaL_error(L, "Operation.call: '%s', failed to build DSB for return value of type '%s'",
1822  op_str, oip->resultType().c_str());
1823 
1824  oh->occ->ret(oh->ret_dsb);
1825  oh->is_void=false;
1826  } else {
1827  oh->is_void=true;
1828  }
1829 
1830  if(!oh->occ->ready())
1831  luaL_error(L, "Service.getOperation: OperationCallerC not ready!");
1832 
1833  return 1;
1834 }
1835 
1836 static int Service_getPort(lua_State *L)
1837 {
1838  const char* name;
1839  PortInterface *pi;
1840  InputPortInterface *ipi;
1841  OutputPortInterface *opi;
1842 
1843  Service::shared_ptr srv;
1844 
1845  srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1846  name = luaL_checkstring(L, 2);
1847 
1848  pi = srv->getPort(name);
1849  if(!pi)
1850  luaL_error(L, "Service.getPort: service %s has no port %",
1851  srv->getName().c_str(), name);
1852 
1853  /* input or output? */
1854  if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL)
1855  InputPort_push(L, ipi);
1856  else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL)
1857  OutputPort_push(L, opi);
1858  else
1859  luaL_error(L, "Service.getPort: unknown port type returned");
1860 
1861  return 1;
1862 }
1863 
1864 static int Service_getProperty(lua_State *L)
1865 {
1866  const char *name;
1867  PropertyBase *prop;
1868 
1869  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1870  name = luaL_checkstring(L, 2);
1871 
1872  prop = srv->getProperty(name);
1873 
1874  if(!prop)
1875  luaL_error(L, "%s failed. No such property", __FILE__);
1876 
1877  Property_push(L, prop);
1878  return 1;
1879 }
1880 
1881 static int Service_getPropertyNames(lua_State *L)
1882 {
1883  Service::shared_ptr srv;
1884  srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1885  std::vector<std::string> plist = srv->properties()->list();
1886  push_vect_str(L, plist);
1887  return 1;
1888 }
1889 
1890 static int Service_getProperties(lua_State *L)
1891 {
1892  Service::shared_ptr srv;
1893  srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1894  vector<PropertyBase*> props = srv->properties()->getProperties();
1895 
1896  int key = 1;
1897  lua_createtable(L, props.size(), 0);
1898  for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) {
1899  Property_push(L, *it);
1900  lua_rawseti(L, -2, key++);
1901  }
1902 
1903  return 1;
1904 }
1905 
1906 static int Service_getAttribute(lua_State *L)
1907 {
1908  const char *name;
1909  AttributeBase *prop;
1910 
1911  Service::shared_ptr srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1912  name = luaL_checkstring(L, 2);
1913 
1914  prop = srv->getAttribute(name);
1915 
1916  if(!prop)
1917  luaL_error(L, "%s failed. No such Attribute", __FILE__);
1918 
1919  Attribute_push(L, prop);
1920  return 1;
1921 }
1922 
1923 static int Service_getAttributeNames(lua_State *L)
1924 {
1925  Service::shared_ptr srv;
1926  srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1927  std::vector<std::string> plist = srv->getAttributeNames();
1928  push_vect_str(L, plist);
1929  return 1;
1930 }
1931 
1932 static int Service_getAttributes(lua_State *L)
1933 {
1934  Service::shared_ptr srv;
1935  srv = *(luaM_checkudata_mt(L, 1, "Service", Service::shared_ptr));
1936  vector<AttributeBase*> props = srv->getValues();
1937 
1938  int key = 1;
1939  lua_createtable(L, props.size(), 0);
1940  for(vector<AttributeBase*>::iterator it = props.begin(); it != props.end(); ++it) {
1941  Attribute_push(L, *it);
1942  lua_rawseti(L, -2, key++);
1943  }
1944 
1945  return 1;
1946 }
1947 
1948 static const struct luaL_Reg Service_f [] = {
1949  { "getName", Service_getName },
1950  { "doc", Service_doc },
1951  { "getProviderNames", Service_getProviderNames },
1952  { "getOperationNames", Service_getOperationNames },
1953  { "hasOperation", Service_hasOperation },
1954  { "getPortNames", Service_getPortNames },
1955  { "provides", Service_provides },
1956  { "getOperation", Service_getOperation },
1957  { "getPort", Service_getPort },
1958  { "getProperty", Service_getProperty },
1959  { "getProperties", Service_getProperties },
1960  { "getPropertyNames", Service_getPropertyNames },
1961  { "getAttribute", Service_getAttribute },
1962  { "getAttributes", Service_getAttributes },
1963  { "getAttributeNames", Service_getAttributeNames },
1964  { NULL, NULL }
1965 };
1966 
1967 static const struct luaL_Reg Service_m [] = {
1968  { "getName", Service_getName },
1969  { "doc", Service_doc },
1970  { "getProviderNames", Service_getProviderNames },
1971  { "getOperationNames", Service_getOperationNames },
1972  { "hasOperation", Service_hasOperation },
1973  { "getPortNames", Service_getPortNames },
1974  { "provides", Service_provides },
1975  { "getOperation", Service_getOperation },
1976  { "getPort", Service_getPort },
1977  { "getProperty", Service_getProperty },
1978  { "getProperties", Service_getProperties },
1979  { "getPropertyNames", Service_getPropertyNames },
1980  { "getAttribute", Service_getAttribute },
1981  { "getAttributes", Service_getAttributes },
1982  { "getAttributeNames", Service_getAttributeNames },
1983  { "__gc", GCMethod<Service::shared_ptr> },
1984  { NULL, NULL }
1985 };
1986 
1987 /***************************************************************
1988  * ServiceRequester
1989  ***************************************************************/
1990 
1991 gen_push_bxptr(ServiceRequester_push, "ServiceRequester", ServiceRequester)
1992 
1993 static int ServiceRequester_getRequestName(lua_State *L)
1994 {
1995  ServiceRequester *sr;
1996 
1997  sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
1998  lua_pushstring(L, sr->getRequestName().c_str());
1999  return 1;
2000 }
2001 
2002 static int ServiceRequester_getRequesterNames(lua_State *L)
2003 {
2004  ServiceRequester *sr;
2005  sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
2006  push_vect_str(L, sr->getRequesterNames());
2007  return 1;
2008 }
2009 
2010 static int ServiceRequester_ready(lua_State *L)
2011 {
2012  int ret;
2013  ServiceRequester *sr;
2014  sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
2015  ret = sr->ready();
2016  lua_pushboolean(L, ret);
2017  return 1;
2018 }
2019 
2020 static int ServiceRequester_disconnect(lua_State *L)
2021 {
2022  ServiceRequester *sr;
2023  sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
2024  sr->disconnect();
2025  return 0;
2026 }
2027 
2028 static int ServiceRequester_requires(lua_State *L)
2029 {
2030  int argc, ret, i;
2031  const char* subsr_str;
2032  ServiceRequester *sr;
2033  ServiceRequester::shared_ptr subsr;
2034 
2035  sr = *(luaM_checkudata_bx(L, 1, ServiceRequester));
2036  argc = lua_gettop(L);
2037 
2038  /* return "this" if no args given */
2039  if(argc == 1) {
2040  ret = 1;
2041  goto out;
2042  }
2043 
2044  for(i=2; i<=argc; i++) {
2045  subsr_str = luaL_checkstring(L, i);
2046  subsr = sr->requires(subsr_str);
2047  if (subsr == 0)
2048  luaL_error(L, "ServiceRequester: no required subservice %s of service %s",
2049  subsr_str, sr->getRequestName().c_str());
2050  else
2051  ServiceRequester_push(L, subsr.get());
2052  }
2053  ret = argc - 1;
2054 
2055  out:
2056  return ret;
2057 }
2058 
2059 static const struct luaL_Reg ServiceRequester_f [] = {
2060  { "getRequestName", ServiceRequester_getRequestName },
2061  { "getRequesterNames", ServiceRequester_getRequesterNames },
2062  { "ready", ServiceRequester_ready },
2063  { "disconnect", ServiceRequester_disconnect },
2064  { "requires", ServiceRequester_requires },
2065  { NULL, NULL }
2066 };
2067 
2068 static const struct luaL_Reg ServiceRequester_m [] = {
2069  { "getRequestName", ServiceRequester_getRequestName },
2070  { "getRequesterNames", ServiceRequester_getRequesterNames },
2071  { "ready", ServiceRequester_ready },
2072  { "disconnect", ServiceRequester_disconnect },
2073  { "requires", ServiceRequester_requires },
2074  { NULL, NULL }
2075 };
2076 
2077 
2078 /***************************************************************
2079  * TaskContext (boxed)
2080  ***************************************************************/
2081 
2082 gen_push_bxptr(TaskContext_push, "TaskContext", TaskContext)
2083 
2084 static int TaskContext_getName(lua_State *L)
2085 {
2086  const char *s;
2087  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2088  s = tc->getName().c_str();
2089  lua_pushstring(L, s);
2090  return 1;
2091 }
2092 
2093 static int TaskContext_start(lua_State *L)
2094 {
2095  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2096  bool b = tc->start();
2097  lua_pushboolean(L, b);
2098  return 1;
2099 }
2100 
2101 static int TaskContext_stop(lua_State *L)
2102 {
2103  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2104  bool b = tc->stop();
2105  lua_pushboolean(L, b);
2106  return 1;
2107 }
2108 
2109 static int TaskContext_configure(lua_State *L)
2110 {
2111  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2112  bool ret = tc->configure();
2113  lua_pushboolean(L, ret);
2114  return 1;
2115 }
2116 
2117 static int TaskContext_activate(lua_State *L)
2118 {
2119  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2120  bool ret = tc->activate();
2121  lua_pushboolean(L, ret);
2122  return 1;
2123 }
2124 
2125 static int TaskContext_cleanup(lua_State *L)
2126 {
2127  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2128  bool ret = tc->cleanup();
2129  lua_pushboolean(L, ret);
2130  return 1;
2131 }
2132 
2133 static int TaskContext_error(lua_State *L)
2134 {
2135  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2136  tc->error();
2137  return 0;
2138 }
2139 
2140 static int TaskContext_recover(lua_State *L)
2141 {
2142  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2143  bool ret = tc->recover();
2144  lua_pushboolean(L, ret);
2145  return 1;
2146 }
2147 
2148 static int TaskContext_getState(lua_State *L)
2149 {
2150  TaskCore::TaskState ts;
2151  TaskContext **tc = (TaskContext**) luaM_checkudata_bx(L, 1, TaskContext);
2152  ts = (*tc)->getTaskState();
2153 
2154  switch(ts) {
2155  case TaskCore::Init: lua_pushstring(L, "Init"); break;
2156  case TaskCore::PreOperational: lua_pushstring(L, "PreOperational"); break;
2157  case TaskCore::FatalError: lua_pushstring(L, "FatalError"); break;
2158  case TaskCore::Exception: lua_pushstring(L, "Exception"); break;
2159  case TaskCore::Stopped: lua_pushstring(L, "Stopped"); break;
2160  case TaskCore::Running: lua_pushstring(L, "Running"); break;
2161  case TaskCore::RunTimeError: lua_pushstring(L, "RunTimeError"); break;
2162  default: lua_pushstring(L, "unknown");
2163  }
2164  return 1;
2165 }
2166 
2167 /* string-table getPeers(TaskContext self)*/
2168 /* should better return array of TC's */
2169 static int TaskContext_getPeers(lua_State *L)
2170 {
2171  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2172  std::vector<std::string> plist = tc->getPeerList();
2173  push_vect_str(L, plist);
2174  return 1;
2175 }
2176 
2177 /* bool addPeer(TaskContext self, TaskContext peer)*/
2178 static int TaskContext_addPeer(lua_State *L)
2179 {
2180  bool ret;
2181  TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
2182  TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext));
2183  ret = self->addPeer(peer);
2184  lua_pushboolean(L, ret);
2185  return 1;
2186 }
2187 
2188 /* bool connectPeers(TaskContext self, TaskContext peer)*/
2189 static int TaskContext_connectPeers(lua_State *L)
2190 {
2191  bool ret;
2192  TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
2193  TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext));
2194  ret = self->connectPeers(peer);
2195  lua_pushboolean(L, ret);
2196  return 1;
2197 }
2198 
2199 /* void removePeer(TaskContext self, string peer)*/
2200 static int TaskContext_removePeer(lua_State *L)
2201 {
2202  std::string peer;
2203  TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
2204  peer = luaL_checkstring(L, 2);
2205  self->removePeer(peer);
2206  return 0;
2207 }
2208 
2209 /* TaskContext getPeer(string name) */
2210 static int TaskContext_getPeer(lua_State *L)
2211 {
2212  std::string strpeer;
2213  TaskContext *peer;
2214  TaskContext *self = *(luaM_checkudata_bx(L, 1, TaskContext));
2215  strpeer = luaL_checkstring(L, 2);
2216  peer = self->getPeer(strpeer);
2217 
2218  if(!peer) {
2219  luaL_error(L, "TaskContext.getPeer: no peer %s", strpeer.c_str());
2220  goto out;
2221  }
2222 
2223  TaskContext_push(L, peer);
2224  out:
2225  return 1;
2226 }
2227 
2228 static int TaskContext_getPortNames(lua_State *L)
2229 {
2230  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2231  std::vector<std::string> plist = tc->ports()->getPortNames();
2232  push_vect_str(L, plist);
2233  return 1;
2234 }
2235 
2236 static int TaskContext_addPort(lua_State *L)
2237 {
2238  const char* name, *desc;
2239  PortInterface **pi;
2240  int argc = lua_gettop(L);
2241  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2242 
2243  pi = (PortInterface**) luaL_testudata(L, 2, "InputPort");
2244  if(pi) goto check_name;
2245 
2246  pi = (PortInterface**) luaL_testudata(L, 2, "OutputPort");
2247  if(pi) goto check_name;
2248 
2249  return luaL_error(L, "addPort: invalid argument, not a Port");
2250 
2251  check_name:
2252  if(argc > 2) {
2253  name = luaL_checkstring(L, 3);
2254  (*pi)->setName(name);
2255  }
2256 
2257  if(argc > 3) {
2258  desc = luaL_checkstring(L, 4);
2259  (*pi)->doc(desc);
2260  }
2261 
2262  tc->ports()->addPort(**pi);
2263  return 0;
2264 }
2265 
2266 static int TaskContext_addEventPort(lua_State *L)
2267 {
2268  const char* name, *desc;
2269  InputPortInterface **ipi;
2270  int argc = lua_gettop(L);
2271  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2272 
2273  if((ipi = (InputPortInterface**) luaL_testudata(L, 2, "InputPort")) == NULL)
2274  return luaL_error(L, "addEventPort: invalid argument, not an InputPort");
2275 
2276  if(argc > 2) {
2277  name = luaL_checkstring(L, 3);
2278  (*ipi)->setName(name);
2279  }
2280 
2281  if(argc > 3) {
2282  desc = luaL_checkstring(L, 4);
2283  (*ipi)->doc(desc);
2284  }
2285 
2286  tc->ports()->addEventPort(**ipi);
2287  return 0;
2288 }
2289 
2290 static int TaskContext_getPort(lua_State *L)
2291 {
2292  const char* name;
2293  PortInterface *pi;
2294  InputPortInterface *ipi;
2295  OutputPortInterface *opi;
2296 
2297  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2298  name = luaL_checkstring(L, 2);
2299 
2300  pi = tc->getPort(name);
2301  if(!pi)
2302  luaL_error(L, "TaskContext.getPort: no port %s for taskcontext %s",
2303  name, tc->getName().c_str());
2304 
2305  /* input or output? */
2306  if ((ipi = dynamic_cast<InputPortInterface *> (pi)) != NULL)
2307  InputPort_push(L, ipi);
2308  else if ((opi = dynamic_cast<OutputPortInterface *> (pi)) != NULL)
2309  OutputPort_push(L, opi);
2310  else
2311  luaL_error(L, "TaskContext.getPort: unknown port returned");
2312 
2313  return 1;
2314 }
2315 
2316 static int TaskContext_removePort(lua_State *L)
2317 {
2318  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2319  const char *port = luaL_checkstring(L, 2);
2320  tc->ports()->removePort(port);
2321  return 0;
2322 }
2323 
2324 static int TaskContext_addProperty(lua_State *L)
2325 {
2326  const char *name, *desc;
2327  int argc = lua_gettop(L);
2328  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2329  PropertyBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Property", PropertyBase));
2330 
2331  if(argc > 2) {
2332  name = luaL_checkstring(L, 3);
2333  pb->setName(name);
2334  }
2335 
2336  if(argc > 3) {
2337  desc = luaL_checkstring(L, 4);
2338  pb->setDescription(desc);
2339  }
2340 
2341 
2342  if(!tc->addProperty(*pb))
2343  luaL_error(L, "TaskContext.addProperty: failed to add property %s.",
2344  pb->getName().c_str());
2345 
2346  return 0;
2347 }
2348 
2349 static int TaskContext_getProperty(lua_State *L)
2350 {
2351  const char *name;
2352  PropertyBase *prop;
2353 
2354  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2355  name = luaL_checkstring(L, 2);
2356 
2357  prop = tc->getProperty(name);
2358 
2359  if(!prop)
2360  luaL_error(L, "%s failed. No such property", __FILE__);
2361 
2362  Property_push(L, prop);
2363  return 1;
2364 }
2365 
2366 
2367 static int TaskContext_getPropertyNames(lua_State *L)
2368 {
2369  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2370  std::vector<std::string> plist = tc->properties()->list();
2371  push_vect_str(L, plist);
2372  return 1;
2373 }
2374 
2375 static int TaskContext_getProperties(lua_State *L)
2376 {
2377  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2378  vector<PropertyBase*> props = tc->properties()->getProperties();
2379 
2380  int key = 1;
2381  lua_createtable(L, props.size(), 0);
2382  for(vector<PropertyBase*>::iterator it = props.begin(); it != props.end(); ++it) {
2383  Property_push(L, *it);
2384  lua_rawseti(L, -2, key++);
2385  }
2386 
2387  return 1;
2388 }
2389 
2390 static int TaskContext_removeProperty(lua_State *L)
2391 {
2392  const char *name;
2393  PropertyBase *prop;
2394 
2395  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2396  name = luaL_checkstring(L, 2);
2397 
2398  prop = tc->getProperty(name);
2399 
2400  if(!prop)
2401  luaL_error(L, "%s failed. No such property", __FILE__);
2402 
2403  tc->properties()->remove(prop);
2404  return 0;
2405 }
2406 
2407 static int TaskContext_addAttribute(lua_State *L)
2408 {
2409  int argc = lua_gettop(L);
2410  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2411  AttributeBase *pb = *(luaM_checkudata_mt_bx(L, 2, "Attribute", AttributeBase));
2412 
2413  if(argc > 2) {
2414  const char *name = luaL_checkstring(L, 3);
2415  pb->setName(name);
2416  }
2417 
2418  if(!tc->addAttribute(*pb))
2419  luaL_error(L, "TaskContext.addAttribute: failed to add attribute %s.",
2420  pb->getName().c_str());
2421 
2422  return 0;
2423 }
2424 
2425 static int TaskContext_getAttribute(lua_State *L)
2426 {
2427  const char *name;
2428  AttributeBase *prop;
2429 
2430  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2431  name = luaL_checkstring(L, 2);
2432 
2433  prop = tc->getAttribute(name);
2434 
2435  if(!prop)
2436  luaL_error(L, "%s failed. No such Attribute", __FILE__);
2437 
2438  Attribute_push(L, prop);
2439  return 1;
2440 }
2441 
2442 
2443 static int TaskContext_getAttributeNames(lua_State *L)
2444 {
2445  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2446  std::vector<std::string> plist = tc->attributes()->getAttributeNames();
2447  push_vect_str(L, plist);
2448  return 1;
2449 }
2450 
2451 static int TaskContext_getAttributes(lua_State *L)
2452 {
2453  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2454  vector<AttributeBase*> props = tc->attributes()->getValues();
2455 
2456  int key = 1;
2457  lua_createtable(L, props.size(), 0);
2458  for(vector<AttributeBase*>::iterator it = props.begin(); it != props.end(); ++it) {
2459  Attribute_push(L, *it);
2460  lua_rawseti(L, -2, key++);
2461  }
2462 
2463  return 1;
2464 }
2465 
2466 static int TaskContext_removeAttribute(lua_State *L)
2467 {
2468  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2469  const char *name = luaL_checkstring(L, 2);
2470 
2471  if(!tc->attributes()->hasAttribute(name))
2472  luaL_error(L, "%s failed. No such attribute", __FILE__);
2473 
2474  tc->attributes()->removeAttribute(name);
2475 
2476  return 0;
2477 }
2478 
2479 static int TaskContext_getOps(lua_State *L)
2480 {
2481  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2482  std::vector<std::string> oplst = tc->operations()->getNames();
2483  push_vect_str(L, oplst);
2484  return 1;
2485 }
2486 
2487 /* returns restype, arity, table-of-arg-descr */
2488 static int TaskContext_getOpInfo(lua_State *L)
2489 {
2490  int i=1;
2491  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2492  const char *op = luaL_checkstring(L, 2);
2493  std::vector<ArgumentDescription> args;
2494 
2495  if(!tc->operations()->hasMember(op))
2496  luaL_error(L, "TaskContext.getOpInfo failed: no such operation");
2497 
2498  lua_pushstring(L, tc->operations()->getResultType(op).c_str()); /* result type */
2499  lua_pushinteger(L, tc->operations()->getArity(op)); /* arity */
2500  lua_pushstring(L, tc->operations()->getDescription(op).c_str()); /* description */
2501 
2502  args = tc->operations()->getArgumentList(op);
2503 
2504  lua_newtable(L);
2505 
2506  for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); it++) {
2507  lua_newtable(L);
2508  lua_pushstring(L, "name"); lua_pushstring(L, it->name.c_str()); lua_rawset(L, -3);
2509  lua_pushstring(L, "type"); lua_pushstring(L, it->type.c_str()); lua_rawset(L, -3);
2510  lua_pushstring(L, "desc"); lua_pushstring(L, it->description.c_str()); lua_rawset(L, -3);
2511  lua_rawseti(L, -2, i++);
2512  }
2513 
2514  return 4;
2515 }
2516 
2517 static int TaskContext_provides(lua_State *L)
2518 {
2519  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2520  Service::shared_ptr srv = tc->provides();
2521 
2522  if(srv == 0)
2523  luaL_error(L, "TaskContext.provides: no default service");
2524 
2525  /* forward to Serivce.provides */
2526  luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
2527  lua_replace(L, 1);
2528  return Service_provides(L);
2529 }
2530 
2531 static int TaskContext_getProviderNames(lua_State *L)
2532 {
2533  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2534  Service::shared_ptr srv = tc->provides();
2535  push_vect_str(L, srv->getProviderNames());
2536  return 1;
2537 }
2538 
2539 static int TaskContext_requires(lua_State *L)
2540 {
2541  ServiceRequester::shared_ptr sr;
2542  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2543  sr = tc->requires();
2544 
2545  if(!sr)
2546  luaL_error(L, "TaskContext.requires returned NULL");
2547 
2548  ServiceRequester_push(L, sr.get());
2549  lua_replace(L, 1);
2550  return ServiceRequester_requires(L);
2551 }
2552 
2553 static int TaskContext_connectServices(lua_State *L)
2554 {
2555  int ret;
2556  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2557  TaskContext *peer = *(luaM_checkudata_bx(L, 2, TaskContext));
2558  ret = tc->connectServices(peer);
2559  lua_pushboolean(L, ret);
2560  return 1;
2561 }
2562 
2563 static int TaskContext_hasOperation(lua_State *L)
2564 {
2565  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2566  Service::shared_ptr srv = tc->provides();
2567 
2568  if(srv == 0)
2569  luaL_error(L, "TaskContext.provides: no default service");
2570 
2571  /* forward to Serivce.hasOperation */
2572  luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
2573  lua_replace(L, 1);
2574  return Service_hasOperation(L);
2575 }
2576 
2577 
2578 static int TaskContext_getOperation(lua_State *L)
2579 {
2580  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2581  Service::shared_ptr srv = tc->provides();
2582 
2583  if(srv == 0)
2584  luaL_error(L, "TaskContext.getOperation: no default service");
2585 
2586  /* forward to Serivce.getOperation */
2587  luaM_pushobject_mt(L, "Service", Service::shared_ptr)(srv);
2588  lua_replace(L, 1);
2589  return Service_getOperation(L);
2590 }
2591 
2592 /*
2593  * SendHandle (required for send)
2594  */
2595 
2596 static void SendStatus_push(lua_State *L, SendStatus ss)
2597 {
2598  switch (ss) {
2599  case SendSuccess: lua_pushstring(L, "SendSuccess"); break;
2600  case SendNotReady: lua_pushstring(L, "SendNotReady"); break;
2601  case SendFailure: lua_pushstring(L, "SendFailure"); break;
2602  default: lua_pushstring(L, "unkown");
2603  }
2604 }
2605 
2606 static int __SendHandle_collect(lua_State *L, bool block)
2607 {
2608  unsigned int coll_argc;
2609  std::vector<DataSourceBase::shared_ptr> coll_args; /* temporarily store args */
2610  SendStatus ss;
2611  const types::TypeInfo *ti;
2612  OperationInterfacePart *oip;
2613  DataSourceBase::shared_ptr dsb, *dsbp;
2614 
2615  unsigned int argc = lua_gettop(L);
2616  SendHandleC *shc = luaM_checkudata_mt(L, 1, "SendHandle", SendHandleC);
2617 
2618  /* get orp pointer */
2619  oip = shc->getOrp();
2620  coll_argc = oip->collectArity();
2621 
2622  if(block && (argc == 1)) {
2623  // No args supplied, create them.
2624  for(unsigned int i=1; i<=coll_argc; i++) {
2625  ti = oip->getCollectType(i);
2626  dsb = ti->buildValue();
2627  coll_args.push_back(dsb);
2628  shc->arg(dsb);
2629  }
2630  } else if (argc-1 == coll_argc) {
2631  // args supplied, use them.
2632  if (!shc->ready()) {
2633  for(unsigned int arg=2; arg<=argc; arg++) {
2634  if ((dsbp = luaM_testudata_mt(L, arg, "Variable", DataSourceBase::shared_ptr)) != NULL)
2635  dsb = *dsbp;
2636  else
2637  luaL_error(L, "SendHandle.collect: expected Variable argument at position %d", arg-1);
2638  shc->arg(dsb);
2639  }
2640  }
2641  } else {
2642  if (block) {
2643  luaL_error(L, "SendHandle.collect: wrong number of args. expected either 0 or %d, got %d",
2644  coll_argc, argc-1);
2645  } else {
2646  luaL_error(L, "SendHandle.collectIfDone: wrong number of args. expected %d, got %d",
2647  coll_argc, argc-1);
2648  }
2649  }
2650 
2651  if(block) ss = shc->collect();
2652  else ss = shc->collectIfDone();
2653 
2654  SendStatus_push(L, ss);
2655 
2656  if(ss == SendSuccess) {
2657  for (unsigned int i=0; i<coll_args.size(); i++)
2658  Variable_push_coerce(L, coll_args[i]);
2659 
2660  /* SendStatus + collect args */
2661  return coll_args.size() + 1;
2662 
2663  } else {
2664  /* SendStatus only */
2665  return 1;
2666  }
2667 }
2668 
2669 static int SendHandle_collect(lua_State *L) { return __SendHandle_collect(L, true); }
2670 static int SendHandle_collectIfDone(lua_State *L) { return __SendHandle_collect(L, false); }
2671 
2672 static const struct luaL_Reg SendHandle_f [] = {
2673  { "collect", SendHandle_collect },
2674  { "collectIfDone", SendHandle_collectIfDone },
2675  { NULL, NULL }
2676 };
2677 
2678 static const struct luaL_Reg SendHandle_m [] = {
2679  { "collect", SendHandle_collect },
2680  { "collectIfDone", SendHandle_collectIfDone },
2681  { "__gc", GCMethod<SendHandleC> },
2682  { NULL, NULL }
2683 };
2684 
2685 /* only explicit destruction allowed */
2686 static int TaskContext_del(lua_State *L)
2687 {
2688  TaskContext *tc = *(luaM_checkudata_bx(L, 1, TaskContext));
2689  delete tc;
2690 
2691  /* this prevents calling rtt methods which would cause a crash */
2692  luaL_getmetatable(L, "__dead__");
2693  lua_setmetatable(L, -2);
2694  return 0;
2695 }
2696 
2697 static const struct luaL_Reg TaskContext_f [] = {
2698  { "getName", TaskContext_getName },
2699  { "start", TaskContext_start },
2700  { "stop", TaskContext_stop },
2701  { "configure", TaskContext_configure },
2702  { "activate", TaskContext_activate },
2703  { "cleanup", TaskContext_cleanup },
2704  { "error", TaskContext_error },
2705  { "recover", TaskContext_recover },
2706  { "getState", TaskContext_getState },
2707  { "getPeers", TaskContext_getPeers },
2708  { "addPeer", TaskContext_addPeer },
2709  { "removePeer", TaskContext_removePeer },
2710  { "getPeer", TaskContext_getPeer },
2711  { "getPortNames", TaskContext_getPortNames },
2712  { "addPort", TaskContext_addPort },
2713  { "addEventPort", TaskContext_addEventPort },
2714  { "getPort", TaskContext_getPort },
2715  { "removePort", TaskContext_removePort },
2716  { "addProperty", TaskContext_addProperty },
2717  { "getProperty", TaskContext_getProperty },
2718  { "getProperties", TaskContext_getProperties },
2719  { "getPropertyNames", TaskContext_getPropertyNames },
2720  { "removeProperty", TaskContext_removeProperty },
2721  { "addAttribute", TaskContext_addAttribute },
2722  { "getAttribute", TaskContext_getAttribute },
2723  { "getAttributes", TaskContext_getAttributes },
2724  { "getAttributeNames", TaskContext_getAttributeNames },
2725  { "removeAttribute", TaskContext_removeAttribute },
2726  { "getOps", TaskContext_getOps },
2727  { "getOpInfo", TaskContext_getOpInfo },
2728  { "hasOperation", TaskContext_hasOperation },
2729  { "provides", TaskContext_provides },
2730  { "getProviderNames", TaskContext_getProviderNames },
2731  { "connectServices", TaskContext_connectServices },
2732  { "getOperation", TaskContext_getOperation },
2733  { "delete", TaskContext_del },
2734  { NULL, NULL}
2735 };
2736 
2737 static const struct luaL_Reg TaskContext_m [] = {
2738  { "getName", TaskContext_getName },
2739  { "start", TaskContext_start },
2740  { "stop", TaskContext_stop },
2741  { "configure", TaskContext_configure },
2742  { "activate", TaskContext_activate },
2743  { "cleanup", TaskContext_cleanup },
2744  { "error", TaskContext_error },
2745  { "recover", TaskContext_recover },
2746  { "getState", TaskContext_getState },
2747  { "getPeers", TaskContext_getPeers },
2748  { "addPeer", TaskContext_addPeer },
2749  { "connectPeers", TaskContext_connectPeers },
2750  { "removePeer", TaskContext_removePeer },
2751  { "getPeer", TaskContext_getPeer },
2752  { "getPortNames", TaskContext_getPortNames },
2753  { "addPort", TaskContext_addPort },
2754  { "addEventPort", TaskContext_addEventPort },
2755  { "getPort", TaskContext_getPort },
2756  { "removePort", TaskContext_removePort },
2757  { "addProperty", TaskContext_addProperty },
2758  { "getProperty", TaskContext_getProperty },
2759  { "getProperties", TaskContext_getProperties },
2760  { "getPropertyNames", TaskContext_getPropertyNames },
2761  { "addAttribute", TaskContext_addAttribute },
2762  { "getAttribute", TaskContext_getAttribute },
2763  { "getAttributes", TaskContext_getAttributes },
2764  { "getAttributeNames", TaskContext_getAttributeNames },
2765  { "removeAttribute", TaskContext_removeAttribute },
2766  { "removeProperty", TaskContext_removeProperty },
2767  { "getOps", TaskContext_getOps },
2768  { "getOpInfo", TaskContext_getOpInfo },
2769  { "hasOperation", TaskContext_hasOperation },
2770  { "provides", TaskContext_provides },
2771  { "getProviderNames", TaskContext_getProviderNames },
2772  { "requires", TaskContext_requires },
2773  { "connectServices", TaskContext_connectServices },
2774  { "getOperation", TaskContext_getOperation },
2775  { "delete", TaskContext_del },
2776  // { "__index", TaskContext_index },
2777  /* we don't GC TaskContexts
2778  * { "__gc", GCMethod<TaskContext> }, */
2779  { NULL, NULL}
2780 };
2781 
2782 /*
2783  * Execution engine hook registration
2784  */
2785 
2786 /* executable IF */
2787 class EEHook : public base::ExecutableInterface
2788 {
2789 protected:
2790  std::string func;
2791  lua_State *L;
2792  TaskContext *tc; /* remember this to be able to print TC name
2793  in error messages */
2794 public:
2795  EEHook(lua_State *_L, std::string _func) { L = _L; func = _func; tc = __getTC(L); }
2796  bool execute() { return call_func(L, func.c_str(), tc, 1, 1); }
2797 };
2798 
2799 static int EEHook_new(lua_State *L)
2800 {
2801  const char *func;
2802  func = luaL_checkstring(L, 1);
2803  luaM_pushobject(L, EEHook)(L, func);
2804  return 1;
2805 }
2806 
2807 static int EEHook_enable(lua_State *L)
2808 {
2809  EEHook *eeh = luaM_checkudata(L, 1, EEHook);
2810  TaskContext *tc = __getTC(L);
2811  lua_pushboolean(L, tc->engine()->runFunction(eeh));
2812  return 1;
2813 }
2814 
2815 static int EEHook_disable(lua_State *L)
2816 { EEHook *eeh = luaM_checkudata(L, 1, EEHook);
2817  TaskContext *tc = __getTC(L);
2818  lua_pushboolean(L, tc->engine()->removeFunction(eeh));
2819  return 1;
2820 }
2821 
2822 #if 0
2823 static int EEHook_gc(lua_State *L)
2824 {
2825  EEHook_disable(L);
2826  lua_settop(L, 1);
2827  reinterpret_cast<EEHook*>(lua_touserdata(L, 1))->~EEHook();
2828  return 0;
2829 }
2830 #endif
2831 
2832 static const struct luaL_Reg EEHook_f [] = {
2833  { "new", EEHook_new },
2834  { "enable", EEHook_enable },
2835  { "disable", EEHook_disable },
2836 };
2837 
2838 
2839 static const struct luaL_Reg EEHook_m [] = {
2840  { "enable", EEHook_enable },
2841  { "disable", EEHook_disable },
2842  /* { "__gc", EEHook_gc }, */
2843 };
2844 
2845 
2846 /*
2847  * Logger and miscellaneous
2848  */
2849 static const char *const loglevels[] = {
2850  "Never", "Fatal", "Critical", "Error", "Warning", "Info", "Debug", "RealTime", NULL
2851 };
2852 
2853 static int Logger_setLogLevel(lua_State *L)
2854 {
2855  Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels);
2856  log().setLogLevel(ll);
2857  return 0;
2858 }
2859 
2860 static int Logger_getLogLevel(lua_State *L)
2861 {
2862  Logger::LogLevel ll = log().getLogLevel();
2863 
2864  switch(ll) {
2865  case Logger::Never: lua_pushstring(L, "Never"); break;
2866  case Logger::Fatal: lua_pushstring(L, "Fatal"); break;
2867  case Logger::Critical: lua_pushstring(L, "Critical"); break;
2868  case Logger::Error: lua_pushstring(L, "Error"); break;
2869  case Logger::Warning: lua_pushstring(L, "Warning"); break;
2870  case Logger::Info: lua_pushstring(L, "Info"); break;
2871  case Logger::Debug: lua_pushstring(L, "Debug"); break;
2872  case Logger::RealTime: lua_pushstring(L, "RealTime"); break;
2873  default:
2874  lua_pushstring(L, "unknown");
2875  }
2876  return 1;
2877 }
2878 
2879 static int Logger_log(lua_State *L)
2880 {
2881  const char *mes;
2882  for(int i=1; i<=lua_gettop(L); i++) {
2883  mes = luaL_checkstring(L, i);
2884  Logger::log() << mes;
2885  }
2886  Logger::log() << endlog();
2887  return 0;
2888 }
2889 
2890 static int Logger_logl(lua_State *L)
2891 {
2892  const char *mes;
2893  Logger::LogLevel ll = (Logger::LogLevel) luaL_checkoption(L, 1, NULL, loglevels);
2894  for(int i=2; i<=lua_gettop(L); i++) {
2895  mes = luaL_checkstring(L, i);
2896  Logger::log(ll) << mes;
2897  }
2898  Logger::log(ll) << endlog();
2899  return 0;
2900 }
2901 
2902 /* misc stuff */
2903 
2904 static int getTime(lua_State *L)
2905 {
2906  unsigned long nsec, sec;
2907  RTT::os::TimeService::nsecs total_nsec = TimeService::Instance()->getNSecs();
2908  sec = total_nsec / 1000000000;
2909  nsec = total_nsec % 1000000000;
2910  lua_pushinteger(L, sec);
2911  lua_pushinteger(L, nsec);
2912  return 2;
2913 }
2914 
2915 static int rtt_sleep(lua_State *L)
2916 {
2917  TIME_SPEC ts;
2918  ts.tv_sec = luaL_checknumber(L, 1);
2919  ts.tv_nsec = luaL_checknumber(L, 2);
2920  rtos_nanosleep(&ts, NULL);
2921  return 0;
2922 }
2923 
2924 static int getTC(lua_State *L)
2925 {
2926  lua_pushstring(L, "this_TC");
2927  lua_rawget(L, LUA_REGISTRYINDEX);
2928  return 1;
2929 }
2930 
2931 static TaskContext* __getTC(lua_State *L)
2932 {
2933  TaskContext *tc;
2934  getTC(L);
2935  tc = *(luaM_checkudata_bx(L, -1, TaskContext));
2936  lua_pop(L, 1);
2937  return tc;
2938 }
2939 
2940 /* access to the globals repository */
2941 static int globals_getNames(lua_State *L)
2942 {
2943  GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance();
2944  push_vect_str(L, gr->getAttributeNames() );
2945  return 1;
2946 }
2947 
2948 static int globals_get(lua_State *L)
2949 {
2950  const char *name;
2951  base::AttributeBase *ab;
2952  DataSourceBase::shared_ptr dsb;
2953 
2954  name = luaL_checkstring(L, 1);
2955  GlobalsRepository::shared_ptr gr = GlobalsRepository::Instance();
2956 
2957  ab = gr->getAttribute(name);
2958 
2959  if (ab)
2960  Variable_push_coerce(L, ab->getDataSource());
2961  else
2962  lua_pushnil(L);
2963 
2964  return 1;
2965 }
2966 
2967 /* global service */
2968 static int provides_global(lua_State *L)
2969 {
2970  luaM_pushobject_mt(L, "Service", Service::shared_ptr)(GlobalService::Instance());
2971  lua_insert(L, 1);
2972  return Service_provides(L);
2973 }
2974 
2975 static int rtt_services(lua_State *L)
2976 {
2977  push_vect_str(L, PluginLoader::Instance()->listServices());
2978  return 1;
2979 }
2980 
2981 static int rtt_typekits(lua_State *L)
2982 {
2983  push_vect_str(L, PluginLoader::Instance()->listTypekits());
2984  return 1;
2985 }
2986 
2987 static int rtt_types(lua_State *L)
2988 {
2989  push_vect_str(L, TypeInfoRepository::Instance()->getTypes());
2990  return 1;
2991 }
2992 
2993 static const struct luaL_Reg rtt_f [] = {
2994  {"getTime", getTime },
2995  {"sleep", rtt_sleep },
2996  {"getTC", getTC },
2997  {"globals_getNames", globals_getNames },
2998  {"globals_get", globals_get },
2999  {"provides", provides_global },
3000  {"services", rtt_services },
3001  {"typekits", rtt_typekits },
3002  {"types", rtt_types },
3003  {"setLogLevel", Logger_setLogLevel },
3004  {"getLogLevel", Logger_getLogLevel },
3005  {"log", Logger_log },
3006  {"logl", Logger_logl },
3007  {NULL, NULL}
3008 };
3009 
3010 extern "C" int luaopen_rtt(lua_State *L);
3011 
3012 int luaopen_rtt(lua_State *L)
3013 {
3014  lua_newtable(L);
3015  lua_replace(L, LUA_ENVIRONINDEX);
3016 
3017  luaL_newmetatable(L, "__dead__");
3018 
3019  /* register MyObj
3020  * 1. line creates metatable MyObj and registers name in registry
3021  * 2. line duplicates metatable
3022  * 3. line sets metatable[__index]=metatable
3023  * (more precisely: table at -2 [__index] = top_of_stack, pops top of stack)
3024  * 4. line register methods in metatable
3025  * 5. line registers free functions in global mystuff.MyObj table
3026  */
3027  luaL_newmetatable(L, "TaskContext");
3028  lua_pushvalue(L, -1); /* duplicates metatable */
3029  lua_setfield(L, -2, "__index");
3030  luaL_register(L, NULL, TaskContext_m);
3031  luaL_register(L, "rtt.TaskContext", TaskContext_f);
3032 
3033  luaL_newmetatable(L, "Operation");
3034  lua_pushvalue(L, -1);
3035  lua_setfield(L, -2, "__index");
3036  luaL_register(L, NULL, Operation_m);
3037  luaL_register(L, "rtt.Operation", Operation_f);
3038 
3039  luaL_newmetatable(L, "Service");
3040  lua_pushvalue(L, -1);
3041  lua_setfield(L, -2, "__index");
3042  luaL_register(L, NULL, Service_m);
3043  luaL_register(L, "rtt.Service", Service_f);
3044 
3045  luaL_newmetatable(L, "ServiceRequester");
3046  lua_pushvalue(L, -1);
3047  lua_setfield(L, -2, "__index");
3048  luaL_register(L, NULL, ServiceRequester_m);
3049  luaL_register(L, "rtt.ServiceRequester", ServiceRequester_f);
3050 
3051  luaL_newmetatable(L, "SendHandle");
3052  lua_pushvalue(L, -1); /* duplicates metatable */
3053  lua_setfield(L, -2, "__index");
3054  luaL_register(L, NULL, SendHandle_m);
3055  luaL_register(L, "rtt.SendHandle", SendHandle_f);
3056 
3057  luaL_newmetatable(L, "InputPort");
3058  lua_pushvalue(L, -1); /* duplicates metatable */
3059  lua_setfield(L, -2, "__index");
3060  luaL_register(L, NULL, InputPort_m);
3061  luaL_register(L, "rtt.InputPort", InputPort_f);
3062 
3063  luaL_newmetatable(L, "OutputPort");
3064  lua_pushvalue(L, -1); /* duplicates metatable */
3065  lua_setfield(L, -2, "__index");
3066  luaL_register(L, NULL, OutputPort_m);
3067  luaL_register(L, "rtt.OutputPort", OutputPort_f);
3068 
3069  luaL_newmetatable(L, "Variable");
3070  lua_pushvalue(L, -1); /* duplicates metatable */
3071  lua_setfield(L, -2, "__index");
3072  luaL_register(L, NULL, Variable_m);
3073  luaL_register(L, "rtt.Variable", Variable_f);
3074 
3075  luaL_newmetatable(L, "Property");
3076  lua_pushvalue(L, -1); /* duplicates metatable */
3077  lua_setfield(L, -2, "__index");
3078  luaL_register(L, NULL, Property_m);
3079  luaL_register(L, "rtt.Property", Property_f);
3080 
3081  luaL_newmetatable(L, "Attribute");
3082  lua_pushvalue(L, -1); /* duplicates metatable */
3083  lua_setfield(L, -2, "__index");
3084  luaL_register(L, NULL, Attribute_m);
3085  luaL_register(L, "rtt.Attribute", Attribute_f);
3086 
3087  luaL_newmetatable(L, "EEHook");
3088  lua_pushvalue(L, -1); /* duplicates metatable */
3089  lua_setfield(L, -2, "__index");
3090  luaL_register(L, NULL, EEHook_m);
3091  luaL_register(L, "rtt.EEHook", EEHook_f);
3092 
3093  /* misc toplevel functions */
3094  luaL_register(L, "rtt", rtt_f);
3095 
3096  return 1;
3097 }
3098 
3099 /* store the TC to be returned by getTC() in registry */
3100 int set_context_tc(TaskContext *tc, lua_State *L)
3101 {
3102  TaskContext **new_tc;
3103  lua_pushstring(L, "this_TC");
3104  new_tc = (TaskContext**) lua_newuserdata(L, sizeof(TaskContext*));
3105  *new_tc = (TaskContext*) tc;
3106  luaL_getmetatable(L, "TaskContext");
3107  lua_setmetatable(L, -2);
3108  lua_rawset(L, LUA_REGISTRYINDEX);
3109  return 0;
3110 }
3111 
3112 
3113 /* call a zero arity function with a boolean return value
3114  * used to call various hooks */
3115 bool call_func(lua_State *L, const char *fname, TaskContext *tc,
3116  int require_function, int require_result)
3117 {
3118  bool ret = true;
3119  int num_res = (require_result != 0) ? 1 : 0;
3120  lua_getglobal(L, fname);
3121 
3122  if(lua_isnil(L, -1)) {
3123  lua_pop(L, 1);
3124  if(require_function)
3125  luaL_error(L, "%s: no (required) Lua function %s", tc->getName().c_str(), fname);
3126  else
3127  goto out;
3128  }
3129 
3130  if (lua_pcall(L, 0, num_res, 0) != 0) {
3131  Logger::log(Logger::Error) << "LuaComponent '"<< tc->getName() <<"': error calling function "
3132  << fname << ": " << lua_tostring(L, -1) << endlog();
3133  lua_pop(L, 1);
3134  ret = false;
3135  goto out;
3136  }
3137 
3138  if(require_result) {
3139  if (!lua_isboolean(L, -1)) {
3140  Logger::log(Logger::Error) << "LuaComponent '" << tc->getName() << "': " << fname
3141  << " must return a bool but returned a "
3142  << lua_typename(L, lua_type(L, -1)) << endlog();
3143  lua_pop(L, 1);
3144  ret = false;
3145  goto out;
3146  }
3147  ret = lua_toboolean(L, -1);
3148  lua_pop(L, 1); /* pop result */
3149  }
3150  out:
3151  return ret;
3152 }
STL namespace.
Definition: Category.hpp:10
Definition: rtt.cpp:2787