Mercurial > vba-clojure
diff src/lua/lbaselib.c @ 11:27763b933818
raise lua sources up one level
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:07:39 -0600 |
parents | src/lua/src/lbaselib.c@f9f4f1b99eed |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/lua/lbaselib.c Sat Mar 03 11:07:39 2012 -0600 1.3 @@ -0,0 +1,653 @@ 1.4 +/* 1.5 +** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ 1.6 +** Basic library 1.7 +** See Copyright Notice in lua.h 1.8 +*/ 1.9 + 1.10 + 1.11 + 1.12 +#include <ctype.h> 1.13 +#include <stdio.h> 1.14 +#include <stdlib.h> 1.15 +#include <string.h> 1.16 + 1.17 +#define lbaselib_c 1.18 +#define LUA_LIB 1.19 + 1.20 +#include "lua.h" 1.21 + 1.22 +#include "lauxlib.h" 1.23 +#include "lualib.h" 1.24 + 1.25 + 1.26 + 1.27 + 1.28 +/* 1.29 +** If your system does not support `stdout', you can just remove this function. 1.30 +** If you need, you can define your own `print' function, following this 1.31 +** model but changing `fputs' to put the strings at a proper place 1.32 +** (a console window or a log file, for instance). 1.33 +*/ 1.34 +static int luaB_print (lua_State *L) { 1.35 + int n = lua_gettop(L); /* number of arguments */ 1.36 + int i; 1.37 + lua_getglobal(L, "tostring"); 1.38 + for (i=1; i<=n; i++) { 1.39 + const char *s; 1.40 + lua_pushvalue(L, -1); /* function to be called */ 1.41 + lua_pushvalue(L, i); /* value to print */ 1.42 + lua_call(L, 1, 1); 1.43 + s = lua_tostring(L, -1); /* get result */ 1.44 + if (s == NULL) 1.45 + return luaL_error(L, LUA_QL("tostring") " must return a string to " 1.46 + LUA_QL("print")); 1.47 + if (i>1) fputs("\t", stdout); 1.48 + fputs(s, stdout); 1.49 + lua_pop(L, 1); /* pop result */ 1.50 + } 1.51 + fputs("\n", stdout); 1.52 + return 0; 1.53 +} 1.54 + 1.55 + 1.56 +static int luaB_tonumber (lua_State *L) { 1.57 + int base = luaL_optint(L, 2, 10); 1.58 + if (base == 10) { /* standard conversion */ 1.59 + luaL_checkany(L, 1); 1.60 + if (lua_isnumber(L, 1)) { 1.61 + lua_pushnumber(L, lua_tonumber(L, 1)); 1.62 + return 1; 1.63 + } 1.64 + } 1.65 + else { 1.66 + const char *s1 = luaL_checkstring(L, 1); 1.67 + char *s2; 1.68 + unsigned long n; 1.69 + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); 1.70 + n = strtoul(s1, &s2, base); 1.71 + if (s1 != s2) { /* at least one valid digit? */ 1.72 + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ 1.73 + if (*s2 == '\0') { /* no invalid trailing characters? */ 1.74 + lua_pushnumber(L, (lua_Number)n); 1.75 + return 1; 1.76 + } 1.77 + } 1.78 + } 1.79 + lua_pushnil(L); /* else not a number */ 1.80 + return 1; 1.81 +} 1.82 + 1.83 + 1.84 +static int luaB_error (lua_State *L) { 1.85 + int level = luaL_optint(L, 2, 1); 1.86 + lua_settop(L, 1); 1.87 + if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ 1.88 + luaL_where(L, level); 1.89 + lua_pushvalue(L, 1); 1.90 + lua_concat(L, 2); 1.91 + } 1.92 + return lua_error(L); 1.93 +} 1.94 + 1.95 + 1.96 +static int luaB_getmetatable (lua_State *L) { 1.97 + luaL_checkany(L, 1); 1.98 + if (!lua_getmetatable(L, 1)) { 1.99 + lua_pushnil(L); 1.100 + return 1; /* no metatable */ 1.101 + } 1.102 + luaL_getmetafield(L, 1, "__metatable"); 1.103 + return 1; /* returns either __metatable field (if present) or metatable */ 1.104 +} 1.105 + 1.106 + 1.107 +static int luaB_setmetatable (lua_State *L) { 1.108 + int t = lua_type(L, 2); 1.109 + luaL_checktype(L, 1, LUA_TTABLE); 1.110 + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, 1.111 + "nil or table expected"); 1.112 + if (luaL_getmetafield(L, 1, "__metatable")) 1.113 + luaL_error(L, "cannot change a protected metatable"); 1.114 + lua_settop(L, 2); 1.115 + lua_setmetatable(L, 1); 1.116 + return 1; 1.117 +} 1.118 + 1.119 + 1.120 +static void getfunc (lua_State *L, int opt) { 1.121 + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); 1.122 + else { 1.123 + lua_Debug ar; 1.124 + int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); 1.125 + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); 1.126 + if (lua_getstack(L, level, &ar) == 0) 1.127 + luaL_argerror(L, 1, "invalid level"); 1.128 + lua_getinfo(L, "f", &ar); 1.129 + if (lua_isnil(L, -1)) 1.130 + luaL_error(L, "no function environment for tail call at level %d", 1.131 + level); 1.132 + } 1.133 +} 1.134 + 1.135 + 1.136 +static int luaB_getfenv (lua_State *L) { 1.137 + getfunc(L, 1); 1.138 + if (lua_iscfunction(L, -1)) /* is a C function? */ 1.139 + lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ 1.140 + else 1.141 + lua_getfenv(L, -1); 1.142 + return 1; 1.143 +} 1.144 + 1.145 + 1.146 +static int luaB_setfenv (lua_State *L) { 1.147 + luaL_checktype(L, 2, LUA_TTABLE); 1.148 + getfunc(L, 0); 1.149 + lua_pushvalue(L, 2); 1.150 + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { 1.151 + /* change environment of current thread */ 1.152 + lua_pushthread(L); 1.153 + lua_insert(L, -2); 1.154 + lua_setfenv(L, -2); 1.155 + return 0; 1.156 + } 1.157 + else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) 1.158 + luaL_error(L, 1.159 + LUA_QL("setfenv") " cannot change environment of given object"); 1.160 + return 1; 1.161 +} 1.162 + 1.163 + 1.164 +static int luaB_rawequal (lua_State *L) { 1.165 + luaL_checkany(L, 1); 1.166 + luaL_checkany(L, 2); 1.167 + lua_pushboolean(L, lua_rawequal(L, 1, 2)); 1.168 + return 1; 1.169 +} 1.170 + 1.171 + 1.172 +static int luaB_rawget (lua_State *L) { 1.173 + luaL_checktype(L, 1, LUA_TTABLE); 1.174 + luaL_checkany(L, 2); 1.175 + lua_settop(L, 2); 1.176 + lua_rawget(L, 1); 1.177 + return 1; 1.178 +} 1.179 + 1.180 +static int luaB_rawset (lua_State *L) { 1.181 + luaL_checktype(L, 1, LUA_TTABLE); 1.182 + luaL_checkany(L, 2); 1.183 + luaL_checkany(L, 3); 1.184 + lua_settop(L, 3); 1.185 + lua_rawset(L, 1); 1.186 + return 1; 1.187 +} 1.188 + 1.189 + 1.190 +static int luaB_gcinfo (lua_State *L) { 1.191 + lua_pushinteger(L, lua_getgccount(L)); 1.192 + return 1; 1.193 +} 1.194 + 1.195 + 1.196 +static int luaB_collectgarbage (lua_State *L) { 1.197 + static const char *const opts[] = {"stop", "restart", "collect", 1.198 + "count", "step", "setpause", "setstepmul", NULL}; 1.199 + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, 1.200 + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; 1.201 + int o = luaL_checkoption(L, 1, "collect", opts); 1.202 + int ex = luaL_optint(L, 2, 0); 1.203 + int res = lua_gc(L, optsnum[o], ex); 1.204 + switch (optsnum[o]) { 1.205 + case LUA_GCCOUNT: { 1.206 + int b = lua_gc(L, LUA_GCCOUNTB, 0); 1.207 + lua_pushnumber(L, res + ((lua_Number)b/1024)); 1.208 + return 1; 1.209 + } 1.210 + case LUA_GCSTEP: { 1.211 + lua_pushboolean(L, res); 1.212 + return 1; 1.213 + } 1.214 + default: { 1.215 + lua_pushnumber(L, res); 1.216 + return 1; 1.217 + } 1.218 + } 1.219 +} 1.220 + 1.221 + 1.222 +static int luaB_type (lua_State *L) { 1.223 + luaL_checkany(L, 1); 1.224 + lua_pushstring(L, luaL_typename(L, 1)); 1.225 + return 1; 1.226 +} 1.227 + 1.228 + 1.229 +static int luaB_next (lua_State *L) { 1.230 + luaL_checktype(L, 1, LUA_TTABLE); 1.231 + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ 1.232 + if (lua_next(L, 1)) 1.233 + return 2; 1.234 + else { 1.235 + lua_pushnil(L); 1.236 + return 1; 1.237 + } 1.238 +} 1.239 + 1.240 + 1.241 +static int luaB_pairs (lua_State *L) { 1.242 + luaL_checktype(L, 1, LUA_TTABLE); 1.243 + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ 1.244 + lua_pushvalue(L, 1); /* state, */ 1.245 + lua_pushnil(L); /* and initial value */ 1.246 + return 3; 1.247 +} 1.248 + 1.249 + 1.250 +static int ipairsaux (lua_State *L) { 1.251 + int i = luaL_checkint(L, 2); 1.252 + luaL_checktype(L, 1, LUA_TTABLE); 1.253 + i++; /* next value */ 1.254 + lua_pushinteger(L, i); 1.255 + lua_rawgeti(L, 1, i); 1.256 + return (lua_isnil(L, -1)) ? 0 : 2; 1.257 +} 1.258 + 1.259 + 1.260 +static int luaB_ipairs (lua_State *L) { 1.261 + luaL_checktype(L, 1, LUA_TTABLE); 1.262 + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ 1.263 + lua_pushvalue(L, 1); /* state, */ 1.264 + lua_pushinteger(L, 0); /* and initial value */ 1.265 + return 3; 1.266 +} 1.267 + 1.268 + 1.269 +static int load_aux (lua_State *L, int status) { 1.270 + if (status == 0) /* OK? */ 1.271 + return 1; 1.272 + else { 1.273 + lua_pushnil(L); 1.274 + lua_insert(L, -2); /* put before error message */ 1.275 + return 2; /* return nil plus error message */ 1.276 + } 1.277 +} 1.278 + 1.279 + 1.280 +static int luaB_loadstring (lua_State *L) { 1.281 + size_t l; 1.282 + const char *s = luaL_checklstring(L, 1, &l); 1.283 + const char *chunkname = luaL_optstring(L, 2, s); 1.284 + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); 1.285 +} 1.286 + 1.287 + 1.288 +static int luaB_loadfile (lua_State *L) { 1.289 + const char *fname = luaL_optstring(L, 1, NULL); 1.290 + return load_aux(L, luaL_loadfile(L, fname)); 1.291 +} 1.292 + 1.293 + 1.294 +/* 1.295 +** Reader for generic `load' function: `lua_load' uses the 1.296 +** stack for internal stuff, so the reader cannot change the 1.297 +** stack top. Instead, it keeps its resulting string in a 1.298 +** reserved slot inside the stack. 1.299 +*/ 1.300 +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { 1.301 + (void)ud; /* to avoid warnings */ 1.302 + luaL_checkstack(L, 2, "too many nested functions"); 1.303 + lua_pushvalue(L, 1); /* get function */ 1.304 + lua_call(L, 0, 1); /* call it */ 1.305 + if (lua_isnil(L, -1)) { 1.306 + *size = 0; 1.307 + return NULL; 1.308 + } 1.309 + else if (lua_isstring(L, -1)) { 1.310 + lua_replace(L, 3); /* save string in a reserved stack slot */ 1.311 + return lua_tolstring(L, 3, size); 1.312 + } 1.313 + else luaL_error(L, "reader function must return a string"); 1.314 + return NULL; /* to avoid warnings */ 1.315 +} 1.316 + 1.317 + 1.318 +static int luaB_load (lua_State *L) { 1.319 + int status; 1.320 + const char *cname = luaL_optstring(L, 2, "=(load)"); 1.321 + luaL_checktype(L, 1, LUA_TFUNCTION); 1.322 + lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ 1.323 + status = lua_load(L, generic_reader, NULL, cname); 1.324 + return load_aux(L, status); 1.325 +} 1.326 + 1.327 + 1.328 +static int luaB_dofile (lua_State *L) { 1.329 + const char *fname = luaL_optstring(L, 1, NULL); 1.330 + int n = lua_gettop(L); 1.331 + if (luaL_loadfile(L, fname) != 0) lua_error(L); 1.332 + lua_call(L, 0, LUA_MULTRET); 1.333 + return lua_gettop(L) - n; 1.334 +} 1.335 + 1.336 + 1.337 +static int luaB_assert (lua_State *L) { 1.338 + luaL_checkany(L, 1); 1.339 + if (!lua_toboolean(L, 1)) 1.340 + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); 1.341 + return lua_gettop(L); 1.342 +} 1.343 + 1.344 + 1.345 +static int luaB_unpack (lua_State *L) { 1.346 + int i, e, n; 1.347 + luaL_checktype(L, 1, LUA_TTABLE); 1.348 + i = luaL_optint(L, 2, 1); 1.349 + e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); 1.350 + if (i > e) return 0; /* empty range */ 1.351 + n = e - i + 1; /* number of elements */ 1.352 + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ 1.353 + return luaL_error(L, "too many results to unpack"); 1.354 + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ 1.355 + while (i++ < e) /* push arg[i + 1...e] */ 1.356 + lua_rawgeti(L, 1, i); 1.357 + return n; 1.358 +} 1.359 + 1.360 + 1.361 +static int luaB_select (lua_State *L) { 1.362 + int n = lua_gettop(L); 1.363 + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { 1.364 + lua_pushinteger(L, n-1); 1.365 + return 1; 1.366 + } 1.367 + else { 1.368 + int i = luaL_checkint(L, 1); 1.369 + if (i < 0) i = n + i; 1.370 + else if (i > n) i = n; 1.371 + luaL_argcheck(L, 1 <= i, 1, "index out of range"); 1.372 + return n - i; 1.373 + } 1.374 +} 1.375 + 1.376 + 1.377 +static int luaB_pcall (lua_State *L) { 1.378 + int status; 1.379 + luaL_checkany(L, 1); 1.380 + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); 1.381 + lua_pushboolean(L, (status == 0)); 1.382 + lua_insert(L, 1); 1.383 + return lua_gettop(L); /* return status + all results */ 1.384 +} 1.385 + 1.386 + 1.387 +static int luaB_xpcall (lua_State *L) { 1.388 + int status; 1.389 + luaL_checkany(L, 2); 1.390 + lua_settop(L, 2); 1.391 + lua_insert(L, 1); /* put error function under function to be called */ 1.392 + status = lua_pcall(L, 0, LUA_MULTRET, 1); 1.393 + lua_pushboolean(L, (status == 0)); 1.394 + lua_replace(L, 1); 1.395 + return lua_gettop(L); /* return status + all results */ 1.396 +} 1.397 + 1.398 + 1.399 +static int luaB_tostring (lua_State *L) { 1.400 + luaL_checkany(L, 1); 1.401 + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ 1.402 + return 1; /* use its value */ 1.403 + switch (lua_type(L, 1)) { 1.404 + case LUA_TNUMBER: 1.405 + lua_pushstring(L, lua_tostring(L, 1)); 1.406 + break; 1.407 + case LUA_TSTRING: 1.408 + lua_pushvalue(L, 1); 1.409 + break; 1.410 + case LUA_TBOOLEAN: 1.411 + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); 1.412 + break; 1.413 + case LUA_TNIL: 1.414 + lua_pushliteral(L, "nil"); 1.415 + break; 1.416 + default: 1.417 + lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); 1.418 + break; 1.419 + } 1.420 + return 1; 1.421 +} 1.422 + 1.423 + 1.424 +static int luaB_newproxy (lua_State *L) { 1.425 + lua_settop(L, 1); 1.426 + lua_newuserdata(L, 0); /* create proxy */ 1.427 + if (lua_toboolean(L, 1) == 0) 1.428 + return 1; /* no metatable */ 1.429 + else if (lua_isboolean(L, 1)) { 1.430 + lua_newtable(L); /* create a new metatable `m' ... */ 1.431 + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ 1.432 + lua_pushboolean(L, 1); 1.433 + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ 1.434 + } 1.435 + else { 1.436 + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ 1.437 + if (lua_getmetatable(L, 1)) { 1.438 + lua_rawget(L, lua_upvalueindex(1)); 1.439 + validproxy = lua_toboolean(L, -1); 1.440 + lua_pop(L, 1); /* remove value */ 1.441 + } 1.442 + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); 1.443 + lua_getmetatable(L, 1); /* metatable is valid; get it */ 1.444 + } 1.445 + lua_setmetatable(L, 2); 1.446 + return 1; 1.447 +} 1.448 + 1.449 + 1.450 +static const luaL_Reg base_funcs[] = { 1.451 + {"assert", luaB_assert}, 1.452 + {"collectgarbage", luaB_collectgarbage}, 1.453 + {"dofile", luaB_dofile}, 1.454 + {"error", luaB_error}, 1.455 + {"gcinfo", luaB_gcinfo}, 1.456 + {"getfenv", luaB_getfenv}, 1.457 + {"getmetatable", luaB_getmetatable}, 1.458 + {"loadfile", luaB_loadfile}, 1.459 + {"load", luaB_load}, 1.460 + {"loadstring", luaB_loadstring}, 1.461 + {"next", luaB_next}, 1.462 + {"pcall", luaB_pcall}, 1.463 + {"print", luaB_print}, 1.464 + {"rawequal", luaB_rawequal}, 1.465 + {"rawget", luaB_rawget}, 1.466 + {"rawset", luaB_rawset}, 1.467 + {"select", luaB_select}, 1.468 + {"setfenv", luaB_setfenv}, 1.469 + {"setmetatable", luaB_setmetatable}, 1.470 + {"tonumber", luaB_tonumber}, 1.471 + {"tostring", luaB_tostring}, 1.472 + {"type", luaB_type}, 1.473 + {"unpack", luaB_unpack}, 1.474 + {"xpcall", luaB_xpcall}, 1.475 + {NULL, NULL} 1.476 +}; 1.477 + 1.478 + 1.479 +/* 1.480 +** {====================================================== 1.481 +** Coroutine library 1.482 +** ======================================================= 1.483 +*/ 1.484 + 1.485 +#define CO_RUN 0 /* running */ 1.486 +#define CO_SUS 1 /* suspended */ 1.487 +#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ 1.488 +#define CO_DEAD 3 1.489 + 1.490 +static const char *const statnames[] = 1.491 + {"running", "suspended", "normal", "dead"}; 1.492 + 1.493 +static int costatus (lua_State *L, lua_State *co) { 1.494 + if (L == co) return CO_RUN; 1.495 + switch (lua_status(co)) { 1.496 + case LUA_YIELD: 1.497 + return CO_SUS; 1.498 + case 0: { 1.499 + lua_Debug ar; 1.500 + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ 1.501 + return CO_NOR; /* it is running */ 1.502 + else if (lua_gettop(co) == 0) 1.503 + return CO_DEAD; 1.504 + else 1.505 + return CO_SUS; /* initial state */ 1.506 + } 1.507 + default: /* some error occured */ 1.508 + return CO_DEAD; 1.509 + } 1.510 +} 1.511 + 1.512 + 1.513 +static int luaB_costatus (lua_State *L) { 1.514 + lua_State *co = lua_tothread(L, 1); 1.515 + luaL_argcheck(L, co, 1, "coroutine expected"); 1.516 + lua_pushstring(L, statnames[costatus(L, co)]); 1.517 + return 1; 1.518 +} 1.519 + 1.520 + 1.521 +static int auxresume (lua_State *L, lua_State *co, int narg) { 1.522 + int status = costatus(L, co); 1.523 + if (!lua_checkstack(co, narg)) 1.524 + luaL_error(L, "too many arguments to resume"); 1.525 + if (status != CO_SUS) { 1.526 + lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); 1.527 + return -1; /* error flag */ 1.528 + } 1.529 + lua_xmove(L, co, narg); 1.530 + lua_setlevel(L, co); 1.531 + status = lua_resume(co, narg); 1.532 + if (status == 0 || status == LUA_YIELD) { 1.533 + int nres = lua_gettop(co); 1.534 + if (!lua_checkstack(L, nres + 1)) 1.535 + luaL_error(L, "too many results to resume"); 1.536 + lua_xmove(co, L, nres); /* move yielded values */ 1.537 + return nres; 1.538 + } 1.539 + else { 1.540 + lua_xmove(co, L, 1); /* move error message */ 1.541 + return -1; /* error flag */ 1.542 + } 1.543 +} 1.544 + 1.545 + 1.546 +static int luaB_coresume (lua_State *L) { 1.547 + lua_State *co = lua_tothread(L, 1); 1.548 + int r; 1.549 + luaL_argcheck(L, co, 1, "coroutine expected"); 1.550 + r = auxresume(L, co, lua_gettop(L) - 1); 1.551 + if (r < 0) { 1.552 + lua_pushboolean(L, 0); 1.553 + lua_insert(L, -2); 1.554 + return 2; /* return false + error message */ 1.555 + } 1.556 + else { 1.557 + lua_pushboolean(L, 1); 1.558 + lua_insert(L, -(r + 1)); 1.559 + return r + 1; /* return true + `resume' returns */ 1.560 + } 1.561 +} 1.562 + 1.563 + 1.564 +static int luaB_auxwrap (lua_State *L) { 1.565 + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); 1.566 + int r = auxresume(L, co, lua_gettop(L)); 1.567 + if (r < 0) { 1.568 + if (lua_isstring(L, -1)) { /* error object is a string? */ 1.569 + luaL_where(L, 1); /* add extra info */ 1.570 + lua_insert(L, -2); 1.571 + lua_concat(L, 2); 1.572 + } 1.573 + lua_error(L); /* propagate error */ 1.574 + } 1.575 + return r; 1.576 +} 1.577 + 1.578 + 1.579 +static int luaB_cocreate (lua_State *L) { 1.580 + lua_State *NL = lua_newthread(L); 1.581 + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, 1.582 + "Lua function expected"); 1.583 + lua_pushvalue(L, 1); /* move function to top */ 1.584 + lua_xmove(L, NL, 1); /* move function from L to NL */ 1.585 + return 1; 1.586 +} 1.587 + 1.588 + 1.589 +static int luaB_cowrap (lua_State *L) { 1.590 + luaB_cocreate(L); 1.591 + lua_pushcclosure(L, luaB_auxwrap, 1); 1.592 + return 1; 1.593 +} 1.594 + 1.595 + 1.596 +static int luaB_yield (lua_State *L) { 1.597 + return lua_yield(L, lua_gettop(L)); 1.598 +} 1.599 + 1.600 + 1.601 +static int luaB_corunning (lua_State *L) { 1.602 + if (lua_pushthread(L)) 1.603 + lua_pushnil(L); /* main thread is not a coroutine */ 1.604 + return 1; 1.605 +} 1.606 + 1.607 + 1.608 +static const luaL_Reg co_funcs[] = { 1.609 + {"create", luaB_cocreate}, 1.610 + {"resume", luaB_coresume}, 1.611 + {"running", luaB_corunning}, 1.612 + {"status", luaB_costatus}, 1.613 + {"wrap", luaB_cowrap}, 1.614 + {"yield", luaB_yield}, 1.615 + {NULL, NULL} 1.616 +}; 1.617 + 1.618 +/* }====================================================== */ 1.619 + 1.620 + 1.621 +static void auxopen (lua_State *L, const char *name, 1.622 + lua_CFunction f, lua_CFunction u) { 1.623 + lua_pushcfunction(L, u); 1.624 + lua_pushcclosure(L, f, 1); 1.625 + lua_setfield(L, -2, name); 1.626 +} 1.627 + 1.628 + 1.629 +static void base_open (lua_State *L) { 1.630 + /* set global _G */ 1.631 + lua_pushvalue(L, LUA_GLOBALSINDEX); 1.632 + lua_setglobal(L, "_G"); 1.633 + /* open lib into global table */ 1.634 + luaL_register(L, "_G", base_funcs); 1.635 + lua_pushliteral(L, LUA_VERSION); 1.636 + lua_setglobal(L, "_VERSION"); /* set global _VERSION */ 1.637 + /* `ipairs' and `pairs' need auxliliary functions as upvalues */ 1.638 + auxopen(L, "ipairs", luaB_ipairs, ipairsaux); 1.639 + auxopen(L, "pairs", luaB_pairs, luaB_next); 1.640 + /* `newproxy' needs a weaktable as upvalue */ 1.641 + lua_createtable(L, 0, 1); /* new table `w' */ 1.642 + lua_pushvalue(L, -1); /* `w' will be its own metatable */ 1.643 + lua_setmetatable(L, -2); 1.644 + lua_pushliteral(L, "kv"); 1.645 + lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ 1.646 + lua_pushcclosure(L, luaB_newproxy, 1); 1.647 + lua_setglobal(L, "newproxy"); /* set global `newproxy' */ 1.648 +} 1.649 + 1.650 + 1.651 +LUALIB_API int luaopen_base (lua_State *L) { 1.652 + base_open(L); 1.653 + luaL_register(L, LUA_COLIBNAME, co_funcs); 1.654 + return 2; 1.655 +} 1.656 +