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