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