diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lua/lcorolib.c (renamed from src/lua-5.3/lcorolib.c) | 84 |
1 files changed, 61 insertions, 23 deletions
diff --git a/src/lua-5.3/lcorolib.c b/src/lua/lcorolib.c index 0b17af9..7d6e585 100644 --- a/src/lua-5.3/lcorolib.c +++ b/src/lua/lcorolib.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcorolib.c,v 1.10.1.1 2017/04/19 17:20:42 roberto Exp $ | 2 | ** $Id: lcorolib.c $ |
| 3 | ** Coroutine Library | 3 | ** Coroutine Library |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -20,25 +20,24 @@ | |||
| 20 | 20 | ||
| 21 | static lua_State *getco (lua_State *L) { | 21 | static lua_State *getco (lua_State *L) { |
| 22 | lua_State *co = lua_tothread(L, 1); | 22 | lua_State *co = lua_tothread(L, 1); |
| 23 | luaL_argcheck(L, co, 1, "thread expected"); | 23 | luaL_argexpected(L, co, 1, "thread"); |
| 24 | return co; | 24 | return co; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | /* | ||
| 29 | ** Resumes a coroutine. Returns the number of results for non-error | ||
| 30 | ** cases or -1 for errors. | ||
| 31 | */ | ||
| 28 | static int auxresume (lua_State *L, lua_State *co, int narg) { | 32 | static int auxresume (lua_State *L, lua_State *co, int narg) { |
| 29 | int status; | 33 | int status, nres; |
| 30 | if (!lua_checkstack(co, narg)) { | 34 | if (!lua_checkstack(co, narg)) { |
| 31 | lua_pushliteral(L, "too many arguments to resume"); | 35 | lua_pushliteral(L, "too many arguments to resume"); |
| 32 | return -1; /* error flag */ | 36 | return -1; /* error flag */ |
| 33 | } | 37 | } |
| 34 | if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { | ||
| 35 | lua_pushliteral(L, "cannot resume dead coroutine"); | ||
| 36 | return -1; /* error flag */ | ||
| 37 | } | ||
| 38 | lua_xmove(L, co, narg); | 38 | lua_xmove(L, co, narg); |
| 39 | status = lua_resume(co, L, narg); | 39 | status = lua_resume(co, L, narg, &nres); |
| 40 | if (status == LUA_OK || status == LUA_YIELD) { | 40 | if (status == LUA_OK || status == LUA_YIELD) { |
| 41 | int nres = lua_gettop(co); | ||
| 42 | if (!lua_checkstack(L, nres + 1)) { | 41 | if (!lua_checkstack(L, nres + 1)) { |
| 43 | lua_pop(co, nres); /* remove results anyway */ | 42 | lua_pop(co, nres); /* remove results anyway */ |
| 44 | lua_pushliteral(L, "too many results to resume"); | 43 | lua_pushliteral(L, "too many results to resume"); |
| @@ -75,8 +74,11 @@ static int luaB_auxwrap (lua_State *L) { | |||
| 75 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); | 74 | lua_State *co = lua_tothread(L, lua_upvalueindex(1)); |
| 76 | int r = auxresume(L, co, lua_gettop(L)); | 75 | int r = auxresume(L, co, lua_gettop(L)); |
| 77 | if (r < 0) { | 76 | if (r < 0) { |
| 77 | int stat = lua_status(co); | ||
| 78 | if (stat != LUA_OK && stat != LUA_YIELD) | ||
| 79 | lua_resetthread(co); /* close variables in case of errors */ | ||
| 78 | if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ | 80 | if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ |
| 79 | luaL_where(L, 1); /* add extra info */ | 81 | luaL_where(L, 1); /* add extra info, if available */ |
| 80 | lua_insert(L, -2); | 82 | lua_insert(L, -2); |
| 81 | lua_concat(L, 2); | 83 | lua_concat(L, 2); |
| 82 | } | 84 | } |
| @@ -108,35 +110,48 @@ static int luaB_yield (lua_State *L) { | |||
| 108 | } | 110 | } |
| 109 | 111 | ||
| 110 | 112 | ||
| 111 | static int luaB_costatus (lua_State *L) { | 113 | #define COS_RUN 0 |
| 112 | lua_State *co = getco(L); | 114 | #define COS_DEAD 1 |
| 113 | if (L == co) lua_pushliteral(L, "running"); | 115 | #define COS_YIELD 2 |
| 116 | #define COS_NORM 3 | ||
| 117 | |||
| 118 | |||
| 119 | static const char *const statname[] = | ||
| 120 | {"running", "dead", "suspended", "normal"}; | ||
| 121 | |||
| 122 | |||
| 123 | static int auxstatus (lua_State *L, lua_State *co) { | ||
| 124 | if (L == co) return COS_RUN; | ||
| 114 | else { | 125 | else { |
| 115 | switch (lua_status(co)) { | 126 | switch (lua_status(co)) { |
| 116 | case LUA_YIELD: | 127 | case LUA_YIELD: |
| 117 | lua_pushliteral(L, "suspended"); | 128 | return COS_YIELD; |
| 118 | break; | ||
| 119 | case LUA_OK: { | 129 | case LUA_OK: { |
| 120 | lua_Debug ar; | 130 | lua_Debug ar; |
| 121 | if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ | 131 | if (lua_getstack(co, 0, &ar)) /* does it have frames? */ |
| 122 | lua_pushliteral(L, "normal"); /* it is running */ | 132 | return COS_NORM; /* it is running */ |
| 123 | else if (lua_gettop(co) == 0) | 133 | else if (lua_gettop(co) == 0) |
| 124 | lua_pushliteral(L, "dead"); | 134 | return COS_DEAD; |
| 125 | else | 135 | else |
| 126 | lua_pushliteral(L, "suspended"); /* initial state */ | 136 | return COS_YIELD; /* initial state */ |
| 127 | break; | ||
| 128 | } | 137 | } |
| 129 | default: /* some error occurred */ | 138 | default: /* some error occurred */ |
| 130 | lua_pushliteral(L, "dead"); | 139 | return COS_DEAD; |
| 131 | break; | ||
| 132 | } | 140 | } |
| 133 | } | 141 | } |
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | static int luaB_costatus (lua_State *L) { | ||
| 146 | lua_State *co = getco(L); | ||
| 147 | lua_pushstring(L, statname[auxstatus(L, co)]); | ||
| 134 | return 1; | 148 | return 1; |
| 135 | } | 149 | } |
| 136 | 150 | ||
| 137 | 151 | ||
| 138 | static int luaB_yieldable (lua_State *L) { | 152 | static int luaB_yieldable (lua_State *L) { |
| 139 | lua_pushboolean(L, lua_isyieldable(L)); | 153 | lua_State *co = lua_isnone(L, 1) ? L : getco(L); |
| 154 | lua_pushboolean(L, lua_isyieldable(co)); | ||
| 140 | return 1; | 155 | return 1; |
| 141 | } | 156 | } |
| 142 | 157 | ||
| @@ -148,6 +163,28 @@ static int luaB_corunning (lua_State *L) { | |||
| 148 | } | 163 | } |
| 149 | 164 | ||
| 150 | 165 | ||
| 166 | static int luaB_close (lua_State *L) { | ||
| 167 | lua_State *co = getco(L); | ||
| 168 | int status = auxstatus(L, co); | ||
| 169 | switch (status) { | ||
| 170 | case COS_DEAD: case COS_YIELD: { | ||
| 171 | status = lua_resetthread(co); | ||
| 172 | if (status == LUA_OK) { | ||
| 173 | lua_pushboolean(L, 1); | ||
| 174 | return 1; | ||
| 175 | } | ||
| 176 | else { | ||
| 177 | lua_pushboolean(L, 0); | ||
| 178 | lua_xmove(co, L, 1); /* copy error message */ | ||
| 179 | return 2; | ||
| 180 | } | ||
| 181 | } | ||
| 182 | default: /* normal or running coroutine */ | ||
| 183 | return luaL_error(L, "cannot close a %s coroutine", statname[status]); | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | |||
| 151 | static const luaL_Reg co_funcs[] = { | 188 | static const luaL_Reg co_funcs[] = { |
| 152 | {"create", luaB_cocreate}, | 189 | {"create", luaB_cocreate}, |
| 153 | {"resume", luaB_coresume}, | 190 | {"resume", luaB_coresume}, |
| @@ -156,6 +193,7 @@ static const luaL_Reg co_funcs[] = { | |||
| 156 | {"wrap", luaB_cowrap}, | 193 | {"wrap", luaB_cowrap}, |
| 157 | {"yield", luaB_yield}, | 194 | {"yield", luaB_yield}, |
| 158 | {"isyieldable", luaB_yieldable}, | 195 | {"isyieldable", luaB_yieldable}, |
| 196 | {"close", luaB_close}, | ||
| 159 | {NULL, NULL} | 197 | {NULL, NULL} |
| 160 | }; | 198 | }; |
| 161 | 199 | ||
