1 /* BEGIN CSTYLED */ 2 /* 3 ** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $ 4 ** Coroutine Library 5 ** See Copyright Notice in lua.h 6 */ 7 8 9 #define lcorolib_c 10 #define LUA_LIB 11 12 #include <sys/lua/lua.h> 13 14 #include <sys/lua/lauxlib.h> 15 #include <sys/lua/lualib.h> 16 17 18 static int auxresume (lua_State *L, lua_State *co, int narg) { 19 int status; 20 if (!lua_checkstack(co, narg)) { 21 lua_pushliteral(L, "too many arguments to resume"); 22 return -1; /* error flag */ 23 } 24 if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { 25 lua_pushliteral(L, "cannot resume dead coroutine"); 26 return -1; /* error flag */ 27 } 28 lua_xmove(L, co, narg); 29 status = lua_resume(co, L, narg); 30 if (status == LUA_OK || status == LUA_YIELD) { 31 int nres = lua_gettop(co); 32 if (!lua_checkstack(L, nres + 1)) { 33 lua_pop(co, nres); /* remove results anyway */ 34 lua_pushliteral(L, "too many results to resume"); 35 return -1; /* error flag */ 36 } 37 lua_xmove(co, L, nres); /* move yielded values */ 38 return nres; 39 } 40 else { 41 lua_xmove(co, L, 1); /* move error message */ 42 return -1; /* error flag */ 43 } 44 } 45 46 47 static int luaB_coresume (lua_State *L) { 48 lua_State *co = lua_tothread(L, 1); 49 int r; 50 luaL_argcheck(L, co, 1, "coroutine expected"); 51 r = auxresume(L, co, lua_gettop(L) - 1); 52 if (r < 0) { 53 lua_pushboolean(L, 0); 54 lua_insert(L, -2); 55 return 2; /* return false + error message */ 56 } 57 else { 58 lua_pushboolean(L, 1); 59 lua_insert(L, -(r + 1)); 60 return r + 1; /* return true + 'resume' returns */ 61 } 62 } 63 64 65 static int luaB_auxwrap (lua_State *L) { 66 lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 67 int r = auxresume(L, co, lua_gettop(L)); 68 if (r < 0) { 69 if (lua_isstring(L, -1)) { /* error object is a string? */ 70 luaL_where(L, 1); /* add extra info */ 71 lua_insert(L, -2); 72 lua_concat(L, 2); 73 } 74 return lua_error(L); /* propagate error */ 75 } 76 return r; 77 } 78 79 80 static int luaB_cocreate (lua_State *L) { 81 lua_State *NL; 82 luaL_checktype(L, 1, LUA_TFUNCTION); 83 NL = lua_newthread(L); 84 lua_pushvalue(L, 1); /* move function to top */ 85 lua_xmove(L, NL, 1); /* move function from L to NL */ 86 return 1; 87 } 88 89 90 static int luaB_cowrap (lua_State *L) { 91 luaB_cocreate(L); 92 lua_pushcclosure(L, luaB_auxwrap, 1); 93 return 1; 94 } 95 96 97 static int luaB_yield (lua_State *L) { 98 return lua_yield(L, lua_gettop(L)); 99 } 100 101 102 static int luaB_costatus (lua_State *L) { 103 lua_State *co = lua_tothread(L, 1); 104 luaL_argcheck(L, co, 1, "coroutine expected"); 105 if (L == co) lua_pushliteral(L, "running"); 106 else { 107 switch (lua_status(co)) { 108 case LUA_YIELD: 109 lua_pushliteral(L, "suspended"); 110 break; 111 case LUA_OK: { 112 lua_Debug ar; 113 if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ 114 lua_pushliteral(L, "normal"); /* it is running */ 115 else if (lua_gettop(co) == 0) 116 lua_pushliteral(L, "dead"); 117 else 118 lua_pushliteral(L, "suspended"); /* initial state */ 119 break; 120 } 121 default: /* some error occurred */ 122 lua_pushliteral(L, "dead"); 123 break; 124 } 125 } 126 return 1; 127 } 128 129 130 static int luaB_corunning (lua_State *L) { 131 int ismain = lua_pushthread(L); 132 lua_pushboolean(L, ismain); 133 return 2; 134 } 135 136 137 static const luaL_Reg co_funcs[] = { 138 {"create", luaB_cocreate}, 139 {"resume", luaB_coresume}, 140 {"running", luaB_corunning}, 141 {"status", luaB_costatus}, 142 {"wrap", luaB_cowrap}, 143 {"yield", luaB_yield}, 144 {NULL, NULL} 145 }; 146 147 148 149 LUAMOD_API int luaopen_coroutine (lua_State *L) { 150 luaL_newlib(L, co_funcs); 151 return 1; 152 } 153 154 #if defined(_KERNEL) 155 156 EXPORT_SYMBOL(luaopen_coroutine); 157 158 #endif 159 /* END CSTYLED */ 160