Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Trying to make userdata work
[simgrid.git] / src / bindings / lua / simgrid_lua.c
1 /* SimGrid Lua bindings                                                     */
2
3 /* Copyright (c) 2010. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8 #include "simgrid_lua.h"
9 #include <string.h> // memcpy
10
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(lua, bindings, "Lua Bindings");
12
13 static lua_State *lua_maestro_state;
14
15 #define TASK_MODULE_NAME "simgrid.Task"
16 #define HOST_MODULE_NAME "simgrid.Host"
17 // Surf (bypass XML)
18 #define LINK_MODULE_NAME "simgrid.Link"
19 #define ROUTE_MODULE_NAME "simgrid.Route"
20 #define AS_MODULE_NAME "simgrid.AS"
21 #define TRACE_MODULE_NAME "simgrid.Trace"
22
23 /**
24  * @brief A chunk of memory.
25  *
26  * TODO replace this by a dynar
27  */
28 typedef struct s_buffer {
29   char* data;
30   size_t size;
31   size_t capacity;
32 } s_buffer_t, *buffer_t;
33
34 static const char* value_tostring(lua_State* L, int index);
35 static const char* keyvalue_tostring(lua_State* L, int key_index, int value_index);
36 static void stack_dump(const char *msg, lua_State* L);
37 static int writer(lua_State* L, const void* source, size_t size, void* userdata);
38 static lua_State* get_father(lua_State* L);
39 static void move_value(lua_State* src, lua_State* dst);
40 static void move_value_impl(lua_State* src, lua_State* dst, const char* name);
41 static int l_get_from_father(lua_State* L);
42 static lua_State *clone_lua_state(lua_State* L);
43 static m_task_t check_task(lua_State *L, int index);
44 static void register_c_functions(lua_State *L);
45
46 /* ********************************************************************************* */
47 /*                            helper functions                                       */
48 /* ********************************************************************************* */
49
50 /**
51  * @brief Returns a string representation of a value in the Lua stack.
52  *
53  * This function is for debugging purposes.
54  * It always returns the same pointer.
55  *
56  * @param L the Lua state
57  * @param index index in the stack
58  * @return a string representation of the value at this index
59  */
60 static const char* value_tostring(lua_State* L, int index) {
61
62   static char buff[64];
63
64   switch (lua_type(L, index)) {
65
66     case LUA_TNIL:
67       sprintf(buff, "nil");
68       break;
69
70     case LUA_TNUMBER:
71       sprintf(buff, "%.3f", lua_tonumber(L, index));
72       break;
73
74     case LUA_TBOOLEAN:
75       sprintf(buff, "%s", lua_toboolean(L, index) ? "true" : "false");
76       break;
77
78     case LUA_TSTRING:
79       snprintf(buff, 63, "'%s'", lua_tostring(L, index));
80       break;
81
82     case LUA_TFUNCTION:
83       if (lua_iscfunction(L, index)) {
84         sprintf(buff, "C-function");
85       }
86       else {
87         sprintf(buff, "function");
88       }
89       break;
90
91     case LUA_TTABLE:
92       sprintf(buff, "table(%p)", lua_topointer(L, index));
93       break;
94
95     case LUA_TLIGHTUSERDATA:
96     case LUA_TUSERDATA:
97       sprintf(buff, "userdata(%p)", lua_touserdata(L, index));
98       break;
99
100     case LUA_TTHREAD:
101       sprintf(buff, "thread");
102       break;
103   }
104   return buff;
105 }
106
107 /**
108  * @brief Returns a string representation of a key-value pair.
109  *
110  * This function is for debugging purposes.
111  * It always returns the same pointer.
112  *
113  * @param L the Lua state
114  * @param key_index index of the key
115  * @param value_index index of the value
116  * @return a string representation of the key-value pair
117  */
118 static const char* keyvalue_tostring(lua_State* L, int key_index, int value_index) {
119
120   static char buff[64];
121   /* value_tostring also always returns the same pointer */
122   int len = snprintf(buff, 63, "[%s] -> ", value_tostring(L, key_index));
123   snprintf(buff + len, 63 - len, "%s", value_tostring(L, value_index));
124   return buff;
125 }
126
127 /**
128  * @brief Returns a string composed of the specified number of spaces.
129  *
130  * This function is for debugging purposes.
131  * It always returns the same pointer.
132  *
133  * @param length length of the string
134  * @return a string of this length with only spaces
135  */
136 static const char* get_spaces(int length) {
137
138   static char spaces[128];
139
140   xbt_assert(length < 128);
141   memset(spaces, ' ', length);
142   spaces[length] = '\0';
143   return spaces;
144 }
145
146 /**
147  * @brief Dumps the Lua stack if debug logs are enabled.
148  * @param msg a message to print
149  * @param L a Lua state
150  */
151 static void stack_dump(const char* msg, lua_State* L)
152 {
153   if (XBT_LOG_ISENABLED(lua, xbt_log_priority_debug)) {
154     char buff[2048];
155     char* p = buff;
156     int i;
157     int top = lua_gettop(L);
158
159     //if (1) return;
160
161     fflush(stdout);
162
163     p[0] = '\0';
164     for (i = 1; i <= top; i++) {  /* repeat for each level */
165
166       p += sprintf(p, "%s", value_tostring(L, i));
167       p += sprintf(p, " ");       /* put a separator */
168     }
169     XBT_DEBUG("%s%s", msg, buff);
170   }
171 }
172
173 /**
174  * @brief Writes the specified data into a memory buffer.
175  *
176  * This function is a valid lua_Writer that writes into a memory buffer passed
177  * as userdata.
178  *
179  * @param L a lua state
180  * @param source some data
181  * @param sz number of bytes of data
182  * @param user_data the memory buffer to write
183  */
184 static int writer(lua_State* L, const void* source, size_t size, void* userdata) {
185
186   buffer_t buffer = (buffer_t) userdata;
187   while (buffer->capacity < buffer->size + size) {
188     buffer->capacity *= 2;
189     buffer->data = xbt_realloc(buffer->data, buffer->capacity);
190   }
191   memcpy(buffer->data + buffer->size, source, size);
192   buffer->size += size;
193
194   return 0;
195 }
196
197 /**
198  * @brief Returns the father of a state.
199  * @param L a Lua state
200  * @return its father
201  */
202 static lua_State* get_father(lua_State* L) {
203
204                                   /* ... */
205   lua_pushstring(L, "simgrid.father");
206                                   /* ... "simgrid.father" */
207   lua_rawget(L, LUA_REGISTRYINDEX);
208                                   /* ... father */
209   lua_State* father = lua_touserdata(L, -1);
210   lua_pop(L, 1);
211                                   /* ... */
212   return father;
213 }
214
215 /**
216  * @brief Pops a value from a state and pushes it onto the stack of another
217  * state.
218  *
219  * @param src the source state
220  * @param dst the destination state
221  */
222 static void move_value(lua_State* src, lua_State* dst) {
223
224   if (src != dst) {
225
226     /* get the list of visited tables from father at index 1 of dst */
227                                   /* src: ... value
228                                      dst: ... */
229     lua_getfield(dst, LUA_REGISTRYINDEX, "simgrid.father_visited_tables");
230                                   /* dst: ... visited */
231     lua_insert(dst, 1);
232                                   /* dst: visited ... */
233
234     move_value_impl(src, dst, value_tostring(src, -1));
235                                   /* src: ...
236                                      dst: visited ... value */
237     lua_remove(dst, 1);
238                                   /* dst: ... value */
239     stack_dump("src after xmove: ", src);
240     stack_dump("dst after xmove: ", dst);
241   }
242 }
243
244 /**
245  * @brief Pops a value from the stack of a source state and pushes it on the
246  * stack of another state.
247  *
248  * If the value is a table, its content is copied recursively. To avoid cycles,
249  * a table of previously visited tables must be present at index 1 of dst.
250  * Its keys are pointers to visited tables in src and its values are the tables
251  * already built.
252  *
253  * TODO: add support of closures
254  *
255  * @param src the source state
256  * @param dst the destination state, with a list of visited tables at index 1
257  * @param name a name describing the value
258  */
259 static void move_value_impl(lua_State* src, lua_State *dst, const char* name) {
260
261   luaL_checkany(src, -1);                  /* check the value to copy */
262   luaL_checktype(dst, 1, LUA_TTABLE);      /* check the presence of a table of
263                                               previously visited tables */
264
265   int indent = (lua_gettop(dst) - 1) * 6;
266   XBT_DEBUG("%sCopying data %s", get_spaces(indent), name);
267   indent += 2;
268
269   stack_dump("src before copying a value (should be ... value): ", src);
270   stack_dump("dst before copying a value (should be visited ...): ", dst);
271
272   switch (lua_type(src, -1)) {
273
274     case LUA_TNIL:
275       lua_pushnil(dst);
276       break;
277
278     case LUA_TNUMBER:
279       lua_pushnumber(dst, lua_tonumber(src, -1));
280       break;
281
282     case LUA_TBOOLEAN:
283       lua_pushboolean(dst, lua_toboolean(src, -1));
284       break;
285
286     case LUA_TSTRING:
287       /* no worries about memory: lua_pushstring makes a copy */
288       lua_pushstring(dst, lua_tostring(src, -1));
289       break;
290
291     case LUA_TFUNCTION:
292       /* it's a function that does not exist yet in L2 */
293
294       if (lua_iscfunction(src, -1)) {
295         /* it's a C function: just copy the pointer */
296         lua_CFunction f = lua_tocfunction(src, -1);
297         lua_pushcfunction(dst, f);
298       }
299       else {
300         /* it's a Lua function: dump it from src */
301         XBT_DEBUG("%sDumping Lua function '%s'", get_spaces(indent), name);
302
303         s_buffer_t buffer;
304         buffer.capacity = 64;
305         buffer.size = 0;
306         buffer.data = xbt_new(char, buffer.capacity);
307
308         /* copy the binary chunk from src into a buffer */
309         int error = lua_dump(src, writer, &buffer);
310         xbt_assert(!error, "Failed to dump function '%s' from the source state: error %d",
311               name, error);
312
313         /* load the chunk into dst */
314         error = luaL_loadbuffer(dst, buffer.data, buffer.size, name);
315         xbt_assert(!error, "Failed to load function '%s' into the destination state: %s",
316             name, lua_tostring(dst, -1));
317         XBT_DEBUG("%sFunction '%s' successfully loaded", get_spaces(indent), name);
318       }
319       break;
320
321     case LUA_TTABLE:
322
323       /* first register the table in the source state itself */
324       lua_getfield(src, LUA_REGISTRYINDEX, "simgrid.visited_tables");
325                                   /* src: ... table visited */
326       lua_pushlightuserdata(src, (void*) lua_topointer(src, -1));
327                                   /* src: ... table visited psrctable */
328       lua_pushvalue(src, -3);
329                                   /* src: ... table visited psrctable table */
330       lua_settable(src, -3);
331                                   /* src: ... table visited */
332       lua_pop(src, 1);
333                                   /* src: ... table */
334
335       /* see if this table was already known by dst */
336       lua_pushlightuserdata(dst, (void*) lua_topointer(src, -1));
337                                   /* dst: visited ... psrctable */
338       lua_gettable(dst, 1);
339                                   /* dst: visited ... table/nil */
340       if (lua_istable(dst, -1)) {
341         XBT_DEBUG("%sNothing to do: table already visited (%p)",
342             get_spaces(indent), lua_topointer(src, -1));
343                                   /* dst: visited ... table */
344       }
345       else {
346         XBT_DEBUG("%sFirst visit of this table (%p)", get_spaces(indent),
347             lua_topointer(src, -1));
348                                   /* dst: visited ... nil */
349         lua_pop(dst, 1);
350                                   /* dst: visited ... */
351
352         /* first visit: create the new table in dst */
353         lua_newtable(dst);
354                                   /* dst: visited ... table */
355
356         /* mark the table as visited to avoid infinite recursion */
357         lua_pushlightuserdata(dst, (void*) lua_topointer(src, -1));
358                                   /* dst: visited ... table psrctable */
359         lua_pushvalue(dst, -2);
360                                   /* dst: visited ... table psrctable table */
361         lua_settable(dst, 1);
362                                   /* dst: visited ... table */
363         XBT_DEBUG("%sTable marked as visited", get_spaces(indent));
364
365         stack_dump("dst after marking the table as visited (should be visited ... table): ", dst);
366
367         /* copy the metatable if any */
368         int has_meta_table = lua_getmetatable(src, -1);
369                                   /* src: ... table mt? */
370         if (has_meta_table) {
371           XBT_DEBUG("%sCopying metatable", get_spaces(indent));
372                                   /* src: ... table mt */
373           move_value_impl(src, dst, "metatable");
374                                   /* src: ... table
375                                      dst: visited ... table mt */
376           lua_setmetatable(dst, -2);
377                                   /* dst: visited ... table */
378         }
379         else {
380           XBT_DEBUG("%sNo metatable", get_spaces(indent));
381         }
382
383         stack_dump("src before traversing the table (should be ... table): ", src);
384         stack_dump("dst before traversing the table (should be visited ... table): ", dst);
385
386         /* traverse the table of src and copy each element */
387         lua_pushnil(src);
388                                   /* src: ... table nil */
389         while (lua_next(src, -2) != 0) {
390                                   /* src: ... table key value */
391
392           XBT_DEBUG("%sCopying table element %s", get_spaces(indent), keyvalue_tostring(src, -2, -1));
393
394           stack_dump("src before copying table element (should be ... table key value): ", src);
395           stack_dump("dst before copying table element (should be visited ... table): ", dst);
396
397           /* copy the key */
398           lua_pushvalue(src, -2);
399                                   /* src: ... table key value key */
400           indent += 2;
401           XBT_DEBUG("%sCopying the key part of the table element", get_spaces(indent));
402           move_value_impl(src, dst, value_tostring(src, -1));
403                                   /* src: ... table key value
404                                      dst: visited ... table key */
405           XBT_DEBUG("%sCopied the key part of the table element", get_spaces(indent));
406
407           /* copy the value */
408           XBT_DEBUG("%sCopying the value part of the table element", get_spaces(indent));
409           move_value_impl(src, dst, value_tostring(src, -1));
410                                   /* src: ... table key
411                                      dst: visited ... table key value */
412           XBT_DEBUG("%sCopied the value part of the table element", get_spaces(indent));
413           indent -= 2;
414
415           /* set the table element */
416           lua_settable(dst, -3);
417                                   /* dst: visited ... table */
418
419           /* the key stays on top of src for next iteration */
420           stack_dump("src before next iteration (should be ... table key): ", src);
421           stack_dump("dst before next iteration (should be visited ... table): ", dst);
422
423           XBT_DEBUG("%sTable element copied", get_spaces(indent));
424         }
425         XBT_DEBUG("%sFinished traversing the table", get_spaces(indent));
426       }
427       break;
428
429     case LUA_TLIGHTUSERDATA:
430       lua_pushlightuserdata(dst, lua_touserdata(src, -1));
431       break;
432
433     case LUA_TUSERDATA:
434     {
435       /* copy the data */
436                                   /* src: ... udata
437                                      dst: visited ... */
438       size_t size = lua_objlen(src, -1);
439       void* src_block = lua_touserdata(src, -1);
440       void* dst_block = lua_newuserdata(dst, size);
441                                   /* dst: visited ... udata */
442       memcpy(dst_block, src_block, size);
443
444       /* copy the metatable if any */
445       int has_meta_table = lua_getmetatable(src, -1);
446                                   /* src: ... udata mt? */
447       if (has_meta_table) {
448         XBT_DEBUG("%sCopying metatable of userdata (%p)", get_spaces(indent),
449             lua_topointer(src, -1));
450                                   /* src: ... udata mt */
451         lua_State* father = get_father(dst);
452
453         if (father != NULL) {
454           XBT_DEBUG("%sGet the metatable from my father", get_spaces(indent));
455           /* find the same metatable in the father state */
456           /* TODO find in visited_tables of src the pointer to the same
457            * metatable in the father world, then copy the metatable from the
458            * father world into dst
459            */
460           lua_pushstring(father, "simgrid.visited_tables");
461                                   /* father: ... "simgrid.visited_tables" */
462           lua_rawget(father, LUA_REGISTRYINDEX);
463                                   /* father: ... visited */
464           lua_pushlightuserdata(father, (void*) lua_topointer(src, -1));
465                                   /* father: ... visited pfathermt */
466           lua_gettable(father, -2);
467                                   /* father: ... visited mt */
468           move_value_impl(father, dst, "(father metatable)");
469                                   /* father: ... visited
470                                      dst: visited ... udata mt */
471           lua_pop(father, 1);
472                                   /* father: ... */
473         }
474         else {
475           XBT_DEBUG("%sI have no father", get_spaces(indent));
476           move_value_impl(src, dst, "metatable");
477                                   /* src: ... udata
478                                      dst: visited ... udata mt */
479         }
480         lua_setmetatable(dst, -2);
481                                   /* dst: visited ... udata */
482
483         XBT_DEBUG("%sMetatable of userdata copied", get_spaces(indent));
484       }
485       else {
486         XBT_DEBUG("%sNo metatable for this userdata", get_spaces(indent));
487                                   /* src: ... udata */
488       }
489     }
490     break;
491
492     case LUA_TTHREAD:
493       XBT_WARN("Cannot copy a thread from the source state.");
494       lua_pushnil(dst);
495       break;
496   }
497
498   /* pop the value from src */
499   lua_pop(src, 1);
500
501   indent -= 2;
502   XBT_DEBUG("%sData copied", get_spaces(indent));
503
504   stack_dump("src after copying a value (should be ...): ", src);
505   stack_dump("dst after copying a value (should be visited ... value): ", dst);
506 }
507
508 /**
509  * @brief Copies a global value or a registry value from the father state.
510  *
511  * The state L must have a father, i.e. it should have been created by
512  * clone_lua_state().
513  * This function is meant to be an __index metamethod.
514  * Consequently, it assumes that the stack has two elements:
515  * a table (either the environment or the registry of L) and the string key of
516  * a value that does not exist yet in this table. It copies the corresponding
517  * value from the father state and pushes it on the stack of L.
518  * If the value does not exist in the father state either, nil is pushed.
519  *
520  * TODO: make this function thread safe. If the simulation runs in parallel,
521  * several simulated processes may trigger this __index metamethod at the same
522  * time and get globals from maestro.
523  *
524  * @param L the current state
525  * @return number of return values pushed (always 1)
526  */
527 static int l_get_from_father(lua_State *L) {
528
529   /* check the arguments */
530   luaL_checktype(L, 1, LUA_TTABLE);
531   const char* key = luaL_checkstring(L, 2);
532                                                /* L:      table key */
533   XBT_DEBUG("__index of '%s' begins", key);
534
535   /* want a global or a registry value? */
536   int pseudo_index;
537   if (lua_equal(L, 1, LUA_REGISTRYINDEX)) {
538     /* registry */
539     pseudo_index = LUA_REGISTRYINDEX;
540     XBT_DEBUG("Will get the value from the registry of the father");
541   }
542   else {
543     /* global */
544     pseudo_index = LUA_GLOBALSINDEX;
545     XBT_DEBUG("Will get the value from the globals of the father");
546   }
547
548   /* get the father */
549   lua_State* father = get_father(L);
550
551   if (father == NULL) {
552     XBT_WARN("This state has no father");
553     lua_pop(L, 3);
554     lua_pushnil(L);
555     return 1;
556   }
557                                                /* L:      table key */
558
559   /* get the list of visited tables */
560   lua_pushstring(L, "simgrid.father_visited_tables");
561                                                /* L:      table key "simgrid.father_visited_tables" */
562   lua_rawget(L, LUA_REGISTRYINDEX);
563                                                /* L:      table key visited */
564   lua_insert(L, 1);
565                                                /* L:      visited table key */
566
567   /* get the value from the father */
568   lua_getfield(father, pseudo_index, key);
569                                                /* father: ... value */
570
571   /* push the value onto the stack of L */
572   move_value_impl(father, L, key);
573                                                /* father: ...
574                                                   L:      visited table key value */
575   lua_remove(L, 1);
576                                                /* L:      table key value */
577
578   /* prepare the return value of __index */
579   lua_pushvalue(L, -1);
580                                                /* L:      table key value value */
581   lua_insert(L, 1);
582                                                /* L:      value table key value */
583
584   /* save the copied value in the table for subsequent accesses */
585   lua_settable(L, -3);
586                                                /* L:      value table */
587   lua_settop(L, 1);
588                                                /* L:      value */
589
590   XBT_DEBUG("__index of '%s' returns %s", key, value_tostring(L, -1));
591
592   return 1;
593 }
594
595 /**
596  * @brief Creates a new Lua state and get its environment from an existing state.
597  *
598  * The state created is independent from the existing one and has its own
599  * copies of global variables and functions.
600  * However, the global variables and functions are not copied right now from
601  * the original state; they are copied only the first time they are accessed.
602  * This behavior saves time and memory, and is okay for Simgrid's needs.
603  *
604  * @param father an existing state
605  * @return the state created
606  */
607 static lua_State* clone_lua_state(lua_State *father) {
608
609   /* create the new state */
610   lua_State *L = luaL_newstate();
611
612   /* set its environment and its registry:
613    * - create a table newenv
614    * - create a metatable mt
615    * - set mt.__index = a function that copies the global from the father state
616    * - set mt as the metatable of the registry
617    * - set mt as the metatable of newenv
618    * - set newenv as the environment of the new state
619    */
620   lua_pushthread(L);                        /* thread */
621   lua_newtable(L);                          /* thread newenv */
622   lua_newtable(L);                          /* thread newenv mt */
623   lua_pushvalue(L, LUA_REGISTRYINDEX);      /* thread newenv mt reg */
624   lua_pushcfunction(L, l_get_from_father);  /* thread newenv mt reg f */
625   lua_setfield(L, -3, "__index");           /* thread newenv mt reg */
626   lua_pushvalue(L, -2);                     /* thread newenv mt reg mt */
627   lua_setmetatable(L, -2);                  /* thread newenv mt reg */
628   lua_pop(L, 1);                            /* thread newenv mt */
629   lua_setmetatable(L, -2);                  /* thread newenv */
630   lua_setfenv(L, -2);                       /* thread */
631   lua_pop(L, 1);                            /* -- */
632
633   /* set a pointer to the father */
634   lua_pushstring(L, "simgrid.father");      /* "simgrid.father" */
635   lua_pushlightuserdata(L, father);         /* "simgrid.father" father */
636   lua_rawset(L, LUA_REGISTRYINDEX);
637                                             /* -- */
638
639   /* create the table of visited tables from the father */
640   lua_pushstring(L, "simgrid.father_visited_tables");
641                                             /* "simgrid.father_visited_tables" */
642   lua_newtable(L);                          /* "simgrid.father_visited_tables" visited */
643   lua_rawset(L, LUA_REGISTRYINDEX);
644                                             /* -- */
645
646   /* create the table of my own visited tables */
647   /* TODO simgrid.father_visited_tables probably becomes useless */
648   lua_pushstring(L, "simgrid.visited_tables");
649                                             /* "simgrid.visited_tables" */
650   lua_newtable(L);                          /* "simgrid.visited_tables" visited */
651   lua_rawset(L, LUA_REGISTRYINDEX);
652                                             /* -- */
653
654   /* open the standard libs (theoretically, this is not necessary as they can
655    * be inherited like any global values, but without a proper support of
656    * closures, iterators like ipairs don't work). */
657   XBT_DEBUG("Metatable of globals and registry set, opening standard libraries now");
658   luaL_openlibs(L);
659
660   XBT_DEBUG("New state created");
661
662   return L;
663 }
664
665 /*
666 static void *my_checkudata (lua_State *L, int ud, const char *tname) {
667   void *p = lua_touserdata(L, ud);
668   lua_getfield(L, LUA_REGISTRYINDEX, tname);
669   const void* correct_mt = lua_topointer(L, -1);
670
671   int has_mt = lua_getmetatable(L, ud);
672   const void* actual_mt = NULL;
673   if (has_mt) { actual_mt = lua_topointer(L, -1); lua_pop(L, 1); }
674   XBT_DEBUG("Checking the task's metatable: expected %p, found %p", correct_mt, actual_mt);
675   stack_dump("my_checkudata: ", L);
676
677   if (p == NULL || !lua_getmetatable(L, ud) || !lua_rawequal(L, -1, -2))
678     luaL_typerror(L, ud, tname);
679   lua_pop(L, 2);
680   return p;
681 }
682 */
683
684 /**
685  * @brief Ensures that a userdata on the stack is a task
686  * and returns the pointer inside the userdata.
687  * @param L a Lua state
688  * @param index an index in the Lua stack
689  * @return the task at this index
690  */
691 static m_task_t checkTask(lua_State * L, int index)
692 {
693   m_task_t *pi, tk;
694   luaL_checktype(L, index, LUA_TTABLE);
695   lua_getfield(L, index, "__simgrid_task");
696
697   pi = (m_task_t *) luaL_checkudata(L, lua_gettop(L), TASK_MODULE_NAME);
698
699   if (pi == NULL)
700     luaL_typerror(L, index, TASK_MODULE_NAME);
701   tk = *pi;
702   if (!tk)
703     luaL_error(L, "null Task");
704   lua_pop(L, 1);
705   return tk;
706 }
707
708 /* ********************************************************************************* */
709 /*                           wrapper functions                                       */
710 /* ********************************************************************************* */
711
712 /**
713  * A task is either something to compute somewhere, or something to exchange between two hosts (or both).
714  * It is defined by a computing amount and a message size.
715  *
716  */
717
718 /* *              * *
719  * * Constructors * *
720  * *              * */
721
722 /**
723  * @brief Constructs a new task with the specified processing amount and amount
724  * of data needed.
725  *
726  * @param name  Task's name
727  *
728  * @param computeDuration       A value of the processing amount (in flop) needed to process the task.
729  *                              If 0, then it cannot be executed with the execute() method.
730  *                              This value has to be >= 0.
731  *
732  * @param messageSize           A value of amount of data (in bytes) needed to transfert this task.
733  *                              If 0, then it cannot be transfered with the get() and put() methods.
734  *                              This value has to be >= 0.
735  */
736 static int Task_new(lua_State * L)
737 {
738   XBT_DEBUG("Task new...");
739   const char *name = luaL_checkstring(L, 1);
740   int comp_size = luaL_checkint(L, 2);
741   int msg_size = luaL_checkint(L, 3);
742   m_task_t msg_task = MSG_task_create(name, comp_size, msg_size, NULL);
743   lua_newtable(L);              /* create a table, put the userdata on top of it */
744   m_task_t *lua_task = (m_task_t *) lua_newuserdata(L, sizeof(m_task_t));
745   *lua_task = msg_task;
746   luaL_getmetatable(L, TASK_MODULE_NAME);
747   lua_setmetatable(L, -2);
748   lua_setfield(L, -2, "__simgrid_task");        /* put the userdata as field of the table */
749   /* remove the args from the stack */
750   lua_remove(L, 1);
751   lua_remove(L, 1);
752   lua_remove(L, 1);
753   return 1;
754 }
755
756 static int Task_get_name(lua_State * L)
757 {
758   m_task_t tk = checkTask(L, -1);
759   lua_pushstring(L, MSG_task_get_name(tk));
760   return 1;
761 }
762
763 static int Task_computation_duration(lua_State * L)
764 {
765   m_task_t tk = checkTask(L, -1);
766   lua_pushnumber(L, MSG_task_get_compute_duration(tk));
767   return 1;
768 }
769
770 static int Task_execute(lua_State * L)
771 {
772   m_task_t tk = checkTask(L, -1);
773   int res = MSG_task_execute(tk);
774   lua_pushnumber(L, res);
775   return 1;
776 }
777
778 static int Task_destroy(lua_State * L)
779 {
780   m_task_t tk = checkTask(L, -1);
781   int res = MSG_task_destroy(tk);
782   lua_pushnumber(L, res);
783   return 1;
784 }
785
786 static int Task_send(lua_State * L)
787 {
788   //stack_dump("send ", L);
789   m_task_t tk = checkTask(L, 1);
790   const char *mailbox = luaL_checkstring(L, 2);
791   lua_pop(L, 1);                // remove the string so that the task is on top of it
792   MSG_task_set_data(tk, L);     // Copy my stack into the task, so that the receiver can copy the lua task directly
793   MSG_error_t res = MSG_task_send(tk, mailbox);
794   while (MSG_task_get_data(tk) != NULL) // Don't mess up with my stack: the receiver didn't copy the data yet
795     MSG_process_sleep(0);       // yield
796
797   if (res != MSG_OK)
798     switch (res) {
799     case MSG_TIMEOUT:
800       XBT_DEBUG("MSG_task_send failed : Timeout");
801       break;
802     case MSG_TRANSFER_FAILURE:
803       XBT_DEBUG("MSG_task_send failed : Transfer Failure");
804       break;
805     case MSG_HOST_FAILURE:
806       XBT_DEBUG("MSG_task_send failed : Host Failure ");
807       break;
808     default:
809       XBT_ERROR
810           ("MSG_task_send failed : Unexpected error , please report this bug");
811       break;
812     }
813   return 0;
814 }
815
816 static int Task_recv_with_timeout(lua_State *L)
817 {
818   m_task_t tk = NULL;
819   const char *mailbox = luaL_checkstring(L, -2);
820   int timeout = luaL_checknumber(L, -1);
821   MSG_error_t res = MSG_task_receive_with_timeout(&tk, mailbox, timeout);
822
823   if (res == MSG_OK) {
824     lua_State *sender_stack = MSG_task_get_data(tk);
825
826     stack_dump("sender before moving data: ", sender_stack);
827     stack_dump("receiver before moving data: ", L);
828
829     move_value(sender_stack, L);        // copy the data directly from sender's stack
830
831     stack_dump("sender after moving data: ", sender_stack);
832     stack_dump("receiver after moving data: ", L);
833
834     MSG_task_set_data(tk, NULL);
835   }
836   else {
837     switch (res) {
838     case MSG_TIMEOUT:
839       XBT_DEBUG("MSG_task_receive failed : Timeout");
840       break;
841     case MSG_TRANSFER_FAILURE:
842       XBT_DEBUG("MSG_task_receive failed : Transfer Failure");
843       break;
844     case MSG_HOST_FAILURE:
845       XBT_DEBUG("MSG_task_receive failed : Host Failure ");
846       break;
847     default:
848       XBT_ERROR("MSG_task_receive failed : Unexpected error , please report this bug");
849       break;
850     }
851     lua_pushnil(L);
852   }
853   return 1;
854 }
855
856 static int Task_recv(lua_State * L)
857 {
858   lua_pushnumber(L, -1.0);
859   return Task_recv_with_timeout(L);
860 }
861
862 static const luaL_reg Task_methods[] = {
863   {"new", Task_new},
864   {"name", Task_get_name},
865   {"computation_duration", Task_computation_duration},
866   {"execute", Task_execute},
867   {"destroy", Task_destroy},
868   {"send", Task_send},
869   {"recv", Task_recv},
870   {"recv_timeout", Task_recv_with_timeout},
871   {NULL, NULL}
872 };
873
874 static int Task_gc(lua_State * L)
875 {
876   m_task_t tk = checkTask(L, -1);
877   if (tk)
878     MSG_task_destroy(tk);
879   return 0;
880 }
881
882 static int Task_tostring(lua_State * L)
883 {
884   lua_pushfstring(L, "Task :%p", lua_touserdata(L, 1));
885   return 1;
886 }
887
888 static const luaL_reg Task_meta[] = {
889   {"__gc", Task_gc},
890   {"__tostring", Task_tostring},
891   {NULL, NULL}
892 };
893
894 /**
895  * Host
896  */
897 static m_host_t checkHost(lua_State * L, int index)
898 {
899   m_host_t *pi, ht;
900   luaL_checktype(L, index, LUA_TTABLE);
901   lua_getfield(L, index, "__simgrid_host");
902   pi = (m_host_t *) luaL_checkudata(L, lua_gettop(L), HOST_MODULE_NAME);
903   if (pi == NULL)
904     luaL_typerror(L, index, HOST_MODULE_NAME);
905   ht = *pi;
906   if (!ht)
907     luaL_error(L, "null Host");
908   lua_pop(L, 1);
909   return ht;
910 }
911
912 static int Host_get_by_name(lua_State * L)
913 {
914   const char *name = luaL_checkstring(L, 1);
915   XBT_DEBUG("Getting Host from name...");
916   m_host_t msg_host = MSG_get_host_by_name(name);
917   if (!msg_host) {
918     luaL_error(L, "null Host : MSG_get_host_by_name failed");
919   }
920   lua_newtable(L);              /* create a table, put the userdata on top of it */
921   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
922   *lua_host = msg_host;
923   luaL_getmetatable(L, HOST_MODULE_NAME);
924   lua_setmetatable(L, -2);
925   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
926   /* remove the args from the stack */
927   lua_remove(L, 1);
928   return 1;
929 }
930
931 static int Host_get_name(lua_State * L)
932 {
933   m_host_t ht = checkHost(L, -1);
934   lua_pushstring(L, MSG_host_get_name(ht));
935   return 1;
936 }
937
938 static int Host_number(lua_State * L)
939 {
940   lua_pushnumber(L, MSG_get_host_number());
941   return 1;
942 }
943
944 static int Host_at(lua_State * L)
945 {
946   int index = luaL_checkinteger(L, 1);
947   m_host_t host = MSG_get_host_table()[index - 1];      // lua indexing start by 1 (lua[1] <=> C[0])
948   lua_newtable(L);              /* create a table, put the userdata on top of it */
949   m_host_t *lua_host = (m_host_t *) lua_newuserdata(L, sizeof(m_host_t));
950   *lua_host = host;
951   luaL_getmetatable(L, HOST_MODULE_NAME);
952   lua_setmetatable(L, -2);
953   lua_setfield(L, -2, "__simgrid_host");        /* put the userdata as field of the table */
954   return 1;
955
956 }
957
958 static int Host_self(lua_State * L)
959 {
960   m_host_t host = MSG_host_self();
961   lua_newtable(L);
962   m_host_t *lua_host =(m_host_t *)lua_newuserdata(L,sizeof(m_host_t));
963   *lua_host = host;
964   luaL_getmetatable(L, HOST_MODULE_NAME);
965   lua_setmetatable(L, -2);
966   lua_setfield(L, -2, "__simgrid_host");
967   return 1;
968 }
969
970 static int Host_get_property_value(lua_State * L)
971 {
972   m_host_t ht = checkHost(L, -2);
973   const char *prop = luaL_checkstring(L, -1);
974   lua_pushstring(L,MSG_host_get_property_value(ht,prop));
975   return 1;
976 }
977
978 static int Host_sleep(lua_State *L)
979 {
980   int time = luaL_checknumber(L, -1);
981   MSG_process_sleep(time);
982   return 1;
983 }
984
985 static int Host_destroy(lua_State *L)
986 {
987   m_host_t ht = checkHost(L, -1);
988   __MSG_host_destroy(ht);
989   return 1;
990 }
991
992 /* ********************************************************************************* */
993 /*                           lua_stub_generator functions                            */
994 /* ********************************************************************************* */
995
996 xbt_dict_t process_function_set;
997 xbt_dynar_t process_list;
998 xbt_dict_t machine_set;
999 static s_process_t process;
1000
1001 void s_process_free(void *process)
1002 {
1003   s_process_t *p = (s_process_t *) process;
1004   int i;
1005   for (i = 0; i < p->argc; i++)
1006     free(p->argv[i]);
1007   free(p->argv);
1008   free(p->host);
1009 }
1010
1011 static int gras_add_process_function(lua_State * L)
1012 {
1013   const char *arg;
1014   const char *process_host = luaL_checkstring(L, 1);
1015   const char *process_function = luaL_checkstring(L, 2);
1016
1017   if (xbt_dict_is_empty(machine_set)
1018       || xbt_dict_is_empty(process_function_set)
1019       || xbt_dynar_is_empty(process_list)) {
1020     process_function_set = xbt_dict_new();
1021     process_list = xbt_dynar_new(sizeof(s_process_t), s_process_free);
1022     machine_set = xbt_dict_new();
1023   }
1024
1025   xbt_dict_set(machine_set, process_host, NULL, NULL);
1026   xbt_dict_set(process_function_set, process_function, NULL, NULL);
1027
1028   process.argc = 1;
1029   process.argv = xbt_new(char *, 1);
1030   process.argv[0] = xbt_strdup(process_function);
1031   process.host = strdup(process_host);
1032
1033   lua_pushnil(L);
1034   while (lua_next(L, 3) != 0) {
1035     arg = lua_tostring(L, -1);
1036     process.argc++;
1037     process.argv =
1038         xbt_realloc(process.argv, (process.argc) * sizeof(char *));
1039     process.argv[(process.argc) - 1] = xbt_strdup(arg);
1040
1041     XBT_DEBUG("index = %f , arg = %s \n", lua_tonumber(L, -2),
1042            lua_tostring(L, -1));
1043     lua_pop(L, 1);
1044   }
1045   lua_pop(L, 1);
1046   //add to the process list
1047   xbt_dynar_push(process_list, &process);
1048   return 0;
1049 }
1050
1051
1052 static int gras_generate(lua_State * L)
1053 {
1054   const char *project_name = luaL_checkstring(L, 1);
1055   generate_sim(project_name);
1056   generate_rl(project_name);
1057   generate_makefile_local(project_name);
1058   return 0;
1059 }
1060
1061 /***********************************
1062  *      Tracing
1063  **********************************/
1064 static int trace_start(lua_State *L)
1065 {
1066 #ifdef HAVE_TRACING
1067   TRACE_start();
1068 #endif
1069   return 1;
1070 }
1071
1072 static int trace_category(lua_State * L)
1073 {
1074 #ifdef HAVE_TRACING
1075   TRACE_category(luaL_checkstring(L, 1));
1076 #endif
1077   return 1;
1078 }
1079
1080 static int trace_set_task_category(lua_State *L)
1081 {
1082 #ifdef HAVE_TRACING
1083   TRACE_msg_set_task_category(checkTask(L, -2), luaL_checkstring(L, -1));
1084 #endif
1085   return 1;
1086 }
1087
1088 static int trace_end(lua_State *L)
1089 {
1090 #ifdef HAVE_TRACING
1091   TRACE_end();
1092 #endif
1093   return 1;
1094 }
1095
1096 // *********** Register Methods ******************************************* //
1097
1098 /*
1099  * Host Methods
1100  */
1101 static const luaL_reg Host_methods[] = {
1102   {"getByName", Host_get_by_name},
1103   {"name", Host_get_name},
1104   {"number", Host_number},
1105   {"at", Host_at},
1106   {"self", Host_self},
1107   {"getPropValue", Host_get_property_value},
1108   {"sleep", Host_sleep},
1109   {"destroy", Host_destroy},
1110   // Bypass XML Methods
1111   {"setFunction", console_set_function},
1112   {"setProperty", console_host_set_property},
1113   {NULL, NULL}
1114 };
1115
1116 static int Host_gc(lua_State * L)
1117 {
1118   m_host_t ht = checkHost(L, -1);
1119   if (ht)
1120     ht = NULL;
1121   return 0;
1122 }
1123
1124 static int Host_tostring(lua_State * L)
1125 {
1126   lua_pushfstring(L, "Host :%p", lua_touserdata(L, 1));
1127   return 1;
1128 }
1129
1130 static const luaL_reg Host_meta[] = {
1131   {"__gc", Host_gc},
1132   {"__tostring", Host_tostring},
1133   {0, 0}
1134 };
1135
1136 /*
1137  * AS Methods
1138  */
1139 static const luaL_reg AS_methods[] = {
1140   {"new", console_add_AS},
1141   {"addHost", console_add_host},
1142   {"addLink", console_add_link},
1143   {"addRoute", console_add_route},
1144   {NULL, NULL}
1145 };
1146
1147 /**
1148  * Tracing Functions
1149  */
1150 static const luaL_reg Trace_methods[] = {
1151   {"start", trace_start},
1152   {"category", trace_category},
1153   {"setTaskCategory", trace_set_task_category},
1154   {"finish", trace_end},
1155   {NULL, NULL}
1156 };
1157
1158 /*
1159  * Environment related
1160  */
1161
1162 /**
1163  * @brief Runs a Lua function as a new simulated process.
1164  * @param argc number of arguments of the function
1165  * @param argv name of the Lua function and array of its arguments
1166  * @return result of the function
1167  */
1168 static int run_lua_code(int argc, char **argv)
1169 {
1170   XBT_DEBUG("Run lua code %s", argv[0]);
1171
1172   lua_State *L = clone_lua_state(lua_maestro_state);
1173   int res = 1;
1174
1175   /* start the function */
1176   lua_getglobal(L, argv[0]);
1177   xbt_assert(lua_isfunction(L, -1),
1178               "The lua function %s does not seem to exist", argv[0]);
1179
1180   /* push arguments onto the stack */
1181   int i;
1182   for (i = 1; i < argc; i++)
1183     lua_pushstring(L, argv[i]);
1184
1185   /* call the function */
1186   int err;
1187   err = lua_pcall(L, argc - 1, 1, 0);
1188   xbt_assert(err == 0, "error running function `%s': %s", argv[0],
1189               lua_tostring(L, -1));
1190
1191   /* retrieve result */
1192   if (lua_isnumber(L, -1)) {
1193     res = lua_tonumber(L, -1);
1194     lua_pop(L, 1);              /* pop returned value */
1195   }
1196
1197   XBT_DEBUG("Execution of Lua code %s is over", (argv ? argv[0] : "(null)"));
1198
1199   return res;
1200 }
1201
1202 static int launch_application(lua_State * L)
1203 {
1204   const char *file = luaL_checkstring(L, 1);
1205   MSG_function_register_default(run_lua_code);
1206   MSG_launch_application(file);
1207   return 0;
1208 }
1209
1210 static int create_environment(lua_State * L)
1211 {
1212   const char *file = luaL_checkstring(L, 1);
1213   XBT_DEBUG("Loading environment file %s", file);
1214   MSG_create_environment(file);
1215   return 0;
1216 }
1217
1218 static int debug(lua_State * L)
1219 {
1220   const char *str = luaL_checkstring(L, 1);
1221   XBT_DEBUG("%s", str);
1222   return 0;
1223 }
1224
1225 static int info(lua_State * L)
1226 {
1227   const char *str = luaL_checkstring(L, 1);
1228   XBT_INFO("%s", str);
1229   return 0;
1230 }
1231
1232 static int run(lua_State * L)
1233 {
1234   MSG_main();
1235   return 0;
1236 }
1237
1238 static int clean(lua_State * L)
1239 {
1240   MSG_clean();
1241   return 0;
1242 }
1243
1244 /*
1245  * Bypass XML Parser (lua console)
1246  */
1247
1248 /*
1249  * Register platform for MSG
1250  */
1251 static int msg_register_platform(lua_State * L)
1252 {
1253   /* Tell Simgrid we dont wanna use its parser */
1254   surf_parse = console_parse_platform;
1255   surf_parse_reset_callbacks();
1256   surf_config_models_setup(NULL);
1257   MSG_create_environment(NULL);
1258   return 0;
1259 }
1260
1261 /*
1262  * Register platform for Simdag
1263  */
1264
1265 static int sd_register_platform(lua_State * L)
1266 {
1267   surf_parse = console_parse_platform_wsL07;
1268   surf_parse_reset_callbacks();
1269   surf_config_models_setup(NULL);
1270   SD_create_environment(NULL);
1271   return 0;
1272 }
1273
1274 /*
1275  * Register platform for gras
1276  */
1277 static int gras_register_platform(lua_State * L)
1278 {
1279   /* Tell Simgrid we dont wanna use surf parser */
1280   surf_parse = console_parse_platform;
1281   surf_parse_reset_callbacks();
1282   surf_config_models_setup(NULL);
1283   gras_create_environment(NULL);
1284   return 0;
1285 }
1286
1287 /**
1288  * Register applicaiton for MSG
1289  */
1290 static int msg_register_application(lua_State * L)
1291 {
1292   MSG_function_register_default(run_lua_code);
1293   surf_parse = console_parse_application;
1294   MSG_launch_application(NULL);
1295   return 0;
1296 }
1297
1298 /*
1299  * Register application for gras
1300  */
1301 static int gras_register_application(lua_State * L)
1302 {
1303   gras_function_register_default(run_lua_code);
1304   surf_parse = console_parse_application;
1305   gras_launch_application(NULL);
1306   return 0;
1307 }
1308
1309 static const luaL_Reg simgrid_funcs[] = {
1310   {"create_environment", create_environment},
1311   {"launch_application", launch_application},
1312   {"debug", debug},
1313   {"info", info},
1314   {"run", run},
1315   {"clean", clean},
1316   /* short names */
1317   {"platform", create_environment},
1318   {"application", launch_application},
1319   /* methods to bypass XML parser */
1320   {"msg_register_platform", msg_register_platform},
1321   {"sd_register_platform", sd_register_platform},
1322   {"msg_register_application", msg_register_application},
1323   {"gras_register_platform", gras_register_platform},
1324   {"gras_register_application", gras_register_application},
1325   /* gras sub generator method */
1326   {"gras_set_process_function", gras_add_process_function},
1327   {"gras_generate", gras_generate},
1328   {NULL, NULL}
1329 };
1330
1331 /* ********************************************************************************* */
1332 /*                       module management functions                                 */
1333 /* ********************************************************************************* */
1334
1335 #define LUA_MAX_ARGS_COUNT 10   /* maximum amount of arguments we can get from lua on command line */
1336
1337 int luaopen_simgrid(lua_State *L);     // Fuck gcc: we don't need that prototype
1338
1339 /**
1340  * This function is called automatically by the Lua interpreter when some Lua code requires
1341  * the "simgrid" module.
1342  * @param L the Lua state
1343  */
1344 int luaopen_simgrid(lua_State *L)
1345 {
1346   XBT_DEBUG("luaopen_simgrid *****");
1347
1348   /* Get the command line arguments from the lua interpreter */
1349   char **argv = malloc(sizeof(char *) * LUA_MAX_ARGS_COUNT);
1350   int argc = 1;
1351   argv[0] = (char *) "/usr/bin/lua";    /* Lie on the argv[0] so that the stack dumping facilities find the right binary. FIXME: what if lua is not in that location? */
1352
1353   lua_getglobal(L, "arg");
1354   /* if arg is a null value, it means we use lua only as a script to init platform
1355    * else it should be a table and then take arg in consideration
1356    */
1357   if (lua_istable(L, -1)) {
1358     int done = 0;
1359     while (!done) {
1360       argc++;
1361       lua_pushinteger(L, argc - 2);
1362       lua_gettable(L, -2);
1363       if (lua_isnil(L, -1)) {
1364         done = 1;
1365       } else {
1366         xbt_assert(lua_isstring(L, -1),
1367                     "argv[%d] got from lua is no string", argc - 1);
1368         xbt_assert(argc < LUA_MAX_ARGS_COUNT,
1369                     "Too many arguments, please increase LUA_MAX_ARGS_COUNT in %s before recompiling SimGrid if you insist on having more than %d args on command line",
1370                     __FILE__, LUA_MAX_ARGS_COUNT - 1);
1371         argv[argc - 1] = (char *) luaL_checkstring(L, -1);
1372         lua_pop(L, 1);
1373         XBT_DEBUG("Got command line argument %s from lua", argv[argc - 1]);
1374       }
1375     }
1376     argv[argc--] = NULL;
1377
1378     /* Initialize the MSG core */
1379     MSG_global_init(&argc, argv);
1380     XBT_DEBUG("Still %d arguments on command line", argc); // FIXME: update the lua's arg table to reflect the changes from SimGrid
1381   }
1382
1383   /* Keep the context mechanism informed of our lua world today */
1384   lua_maestro_state = L;
1385
1386   /* initialize access to my tables by children Lua states */
1387   lua_newtable(L);
1388   lua_setfield(L, LUA_REGISTRYINDEX, "simgrid.visited_tables");
1389
1390   register_c_functions(L);
1391
1392   return 1;
1393 }
1394
1395 /**
1396  * Makes the appropriate Simgrid functions available to the Lua world.
1397  * @param L a Lua world
1398  */
1399 void register_c_functions(lua_State *L) {
1400
1401   /* register the core C functions to lua */
1402   luaL_register(L, "simgrid", simgrid_funcs);
1403
1404   /* register the task methods to lua */
1405   luaL_openlib(L, TASK_MODULE_NAME, Task_methods, 0);   // create methods table, add it to the globals
1406   luaL_newmetatable(L, TASK_MODULE_NAME);       // create metatable for Task, add it to the Lua registry
1407   luaL_openlib(L, 0, Task_meta, 0);     // fill metatable
1408   lua_pushliteral(L, "__index");
1409   lua_pushvalue(L, -3);         // dup methods table
1410   lua_rawset(L, -3);            // matatable.__index = methods
1411   lua_pushliteral(L, "__metatable");
1412   lua_pushvalue(L, -3);         // dup methods table
1413   lua_rawset(L, -3);            // hide metatable:metatable.__metatable = methods
1414   lua_pop(L, 1);                // drop metatable
1415
1416   /* register the hosts methods to lua */
1417   luaL_openlib(L, HOST_MODULE_NAME, Host_methods, 0);
1418   luaL_newmetatable(L, HOST_MODULE_NAME);
1419   luaL_openlib(L, 0, Host_meta, 0);
1420   lua_pushliteral(L, "__index");
1421   lua_pushvalue(L, -3);
1422   lua_rawset(L, -3);
1423   lua_pushliteral(L, "__metatable");
1424   lua_pushvalue(L, -3);
1425   lua_rawset(L, -3);
1426   lua_pop(L, 1);
1427
1428   /* register the links methods to lua */
1429   luaL_openlib(L, AS_MODULE_NAME, AS_methods, 0);
1430   luaL_newmetatable(L, AS_MODULE_NAME);
1431   lua_pop(L, 1);
1432
1433   /* register the Tracing functions to lua */
1434   luaL_openlib(L, TRACE_MODULE_NAME, Trace_methods, 0);
1435   luaL_newmetatable(L, TRACE_MODULE_NAME);
1436   lua_pop(L, 1);
1437 }