2 ** Rings: Multiple Lua States
3 ** $Id: rings.c,v 1.7 2007/06/11 23:36:37 carregal Exp $
4 ** See Copyright Notice in license.html
14 #define RINGS_TABLENAME "rings"
15 #define RINGS_CACHE "rings cache"
16 #define STATE_METATABLE "state metatable"
24 LUALIB_API int luaopen_rings (lua_State *L);
28 ** Get a State object from the first call stack position.
30 static state_data *getstate (lua_State *L) {
31 state_data *s = (state_data *)luaL_checkudata (L, 1, STATE_METATABLE);
32 luaL_argcheck (L, s != NULL, 1, "not a Lua State");
33 luaL_argcheck (L, s->L, 1, "already closed state");
41 static int state_tostring (lua_State *L) {
42 state_data *s = (state_data *)luaL_checkudata (L, 1, STATE_METATABLE);
43 lua_pushfstring (L, "Lua State (%p)", s);
49 ** Copies values from State src to State dst.
51 static void copy_values (lua_State *dst, lua_State *src, int i, int top) {
52 for (; i <= top; i++) {
53 switch (lua_type (src, i)) {
55 lua_pushnumber (dst, lua_tonumber (src, i));
58 lua_pushboolean (dst, lua_toboolean (src, i));
61 const char *string = lua_tostring (src, i);
62 size_t length = lua_strlen (src, i);
63 lua_pushlstring (dst, string, length);
67 case LUA_TLIGHTUSERDATA: {
68 lua_pushlightuserdata (dst, lua_touserdata (src, i));
81 ** Obtains a function which is the compiled string in the given state.
82 ** It also caches the resulting function to optimize future uses.
83 ** Leaves the compiled function on top of the stack or the error message
84 ** produced by luaL_loadbuffer.
86 static int compile_string (lua_State *L, const char *str) {
87 lua_pushliteral (L, RINGS_CACHE);
88 lua_gettable (L, LUA_REGISTRYINDEX); /* push cache table */
89 lua_pushstring (L, str);
90 lua_gettable (L, -2); /* cache[str] */
91 if (!lua_isfunction (L, -1)) {
93 lua_pop (L, 1); /* remove cache[str] (= nil) from top of the stack */
94 status = luaL_loadbuffer (L, str, strlen(str), str); /* Compile */
95 if (status != 0) { /* error? */
96 lua_remove (L, -2); /* removes cache table; leaves the error message */
99 /* Stores the produced function at cache[str] */
100 lua_pushstring (L, str);
101 lua_pushvalue (L, -2);
102 lua_settable (L, -4); /* cache[str] = func */
104 lua_remove (L, -2); /* removes cache table; leaves the function */
110 ** Executes a string of code from State src into State dst.
111 ** idx is the index of the string of code.
113 static int dostring (lua_State *dst, lua_State *src, int idx) {
114 const char *str = luaL_checkstring (src, idx);
115 int base = lua_gettop (dst);
116 idx++; /* ignore first argument (string of code) */
117 if (compile_string (dst, str) == 0) { /* Compile OK? => push function */
118 int arg_top = lua_gettop (src);
119 copy_values (dst, src, idx, arg_top); /* Push arguments to dst stack */
120 if (lua_pcall (dst, arg_top-idx+1, LUA_MULTRET, 0) == 0) { /* run OK? */
121 int ret_top = lua_gettop (dst);
122 lua_pushboolean (src, 1); /* Push status = OK */
123 copy_values (src, dst, base+1, ret_top); /* Return values to src */
124 lua_pop (dst, ret_top-base);
125 return 1+(ret_top-base); /* Return true (success) plus return values */
128 lua_pushboolean (src, 0); /* Push status = ERR */
129 lua_pushstring (src, lua_tostring (dst, -1));
130 lua_pop (dst, 1); /* pops result from dst state */
136 ** Executes a string of Lua code in the master state.
138 static int master_dostring (lua_State *S) {
139 lua_State *M = (lua_State *)lua_touserdata (S, lua_upvalueindex (1));
140 return dostring (M, S, 1);
145 ** Executes a string of Lua code in a given slave state.
147 static int slave_dostring (lua_State *M) {
148 state_data *s = getstate (M); /* S == s->L */
149 return dostring (s->L, M, 2);
154 ** Creates a weak table in the registry.
156 static void create_cache (lua_State *L) {
157 lua_pushliteral (L, RINGS_CACHE);
159 lua_newtable (L); /* cache metatable */
160 lua_pushliteral (L, "__mode");
161 lua_pushliteral (L, "kv");
162 lua_settable (L, -3); /* metatable.__mode = "kv" */
163 lua_setmetatable (L, -2);
164 lua_settable (L, LUA_REGISTRYINDEX);
169 ** Creates a new Lua State and returns an userdata that represents it.
171 static int state_new (lua_State *L) {
172 state_data *s = (state_data *)lua_newuserdata (L, sizeof (state_data));
174 luaL_getmetatable (L, STATE_METATABLE);
175 lua_setmetatable (L, -2);
178 /* load base libraries */
181 /* define dostring function (which runs strings on the master state) */
182 lua_pushliteral (s->L, "remotedostring");
183 lua_pushlightuserdata (s->L, L);
184 lua_pushcclosure (s->L, master_dostring, 1);
185 lua_settable (s->L, LUA_GLOBALSINDEX);
194 ** Closes a Lua State.
195 ** Returns `true' in case of success; `nil' when the state was already closed.
197 static int slave_close (lua_State *L) {
198 state_data *s = (state_data *)luaL_checkudata (L, 1, STATE_METATABLE);
199 luaL_argcheck (L, s != NULL, 1, "not a Lua State");
204 lua_pushboolean (L, 1);
210 ** Creates the metatable for the state on top of the stack.
212 static int state_createmetatable (lua_State *L) {
214 struct luaL_reg methods[] = {
215 {"close", slave_close},
216 {"dostring", slave_dostring},
219 /* State metatable */
220 if (!luaL_newmetatable (L, STATE_METATABLE)) {
224 luaL_openlib (L, NULL, methods, 0);
225 /* define metamethods */
226 lua_pushliteral (L, "__gc");
227 lua_pushcfunction (L, slave_close);
228 lua_settable (L, -3);
230 lua_pushliteral (L, "__index");
231 lua_pushvalue (L, -2);
232 lua_settable (L, -3);
234 lua_pushliteral (L, "__tostring");
235 lua_pushcfunction (L, state_tostring);
236 lua_settable (L, -3);
238 lua_pushliteral (L, "__metatable");
239 lua_pushliteral (L, "You're not allowed to get the metatable of a Lua State");
240 lua_settable (L, -3);
248 static void set_info (lua_State *L) {
249 lua_pushliteral (L, "_COPYRIGHT");
250 lua_pushliteral (L, "Copyright (C) 2006-2007 Kepler Project");
251 lua_settable (L, -3);
252 lua_pushliteral (L, "_DESCRIPTION");
253 lua_pushliteral (L, "Rings: Multiple Lua States");
254 lua_settable (L, -3); lua_pushliteral (L, "_VERSION");
255 lua_pushliteral (L, "Rings 1.1.0");
256 lua_settable (L, -3);
263 LUALIB_API int luaopen_rings (lua_State *L) {
264 /* Library functions */
265 struct luaL_reg rings[] = {
269 if (!state_createmetatable (L))
272 /* define library functions */
273 luaL_openlib (L, RINGS_TABLENAME, rings, 0);