00001
00002
00003
00004
00005
00006
00007 #include <common/Logger.h>
00008
00009 #include <ctype.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013
00014 #define lbaselib_c
00015 #define LUA_LIB
00016
00017 #include "lua.h"
00018
00019 #include "lauxlib.h"
00020 #include "lualib.h"
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 static int luaB_print (lua_State *L) {
00032
00033 std::string result;
00034
00035 int n = lua_gettop(L);
00036 int i;
00037 lua_getglobal(L, "tostring");
00038 for (i=1; i<=n; i++) {
00039 const char *s;
00040 lua_pushvalue(L, -1);
00041 lua_pushvalue(L, i);
00042 lua_call(L, 1, 1);
00043 s = lua_tostring(L, -1);
00044 if (s == NULL)
00045 return luaL_error(L, LUA_QL("tostring") " must return a string to "
00046 LUA_QL("print"));
00047 if (i>1) result.append("\t");
00048 result.append(s);
00049 lua_pop(L, 1);
00050 }
00051 result.append("\n");
00052 Logger::log(result.c_str());
00053 return 0;
00054 }
00055
00056
00057 static int luaB_tonumber (lua_State *L) {
00058 int base = luaL_optint(L, 2, 10);
00059 if (base == 10) {
00060 luaL_checkany(L, 1);
00061 if (lua_isnumber(L, 1)) {
00062 lua_pushnumber(L, lua_tonumber(L, 1));
00063 return 1;
00064 }
00065 }
00066 else {
00067 const char *s1 = luaL_checkstring(L, 1);
00068 char *s2;
00069 unsigned long n;
00070 luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
00071 n = strtoul(s1, &s2, base);
00072 if (s1 != s2) {
00073 while (isspace((unsigned char)(*s2))) s2++;
00074 if (*s2 == '\0') {
00075 lua_pushnumber(L, (lua_Number)n);
00076 return 1;
00077 }
00078 }
00079 }
00080 lua_pushnil(L);
00081 return 1;
00082 }
00083
00084
00085 static int luaB_error (lua_State *L) {
00086 int level = luaL_optint(L, 2, 1);
00087 lua_settop(L, 1);
00088 if (lua_isstring(L, 1) && level > 0) {
00089 luaL_where(L, level);
00090 lua_pushvalue(L, 1);
00091 lua_concat(L, 2);
00092 }
00093 return lua_error(L);
00094 }
00095
00096
00097 static int luaB_getmetatable (lua_State *L) {
00098 luaL_checkany(L, 1);
00099 if (!lua_getmetatable(L, 1)) {
00100 lua_pushnil(L);
00101 return 1;
00102 }
00103 luaL_getmetafield(L, 1, "__metatable");
00104 return 1;
00105 }
00106
00107
00108 static int luaB_setmetatable (lua_State *L) {
00109 int t = lua_type(L, 2);
00110 luaL_checktype(L, 1, LUA_TTABLE);
00111 luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
00112 "nil or table expected");
00113 if (luaL_getmetafield(L, 1, "__metatable"))
00114 luaL_error(L, "cannot change a protected metatable");
00115 lua_settop(L, 2);
00116 lua_setmetatable(L, 1);
00117 return 1;
00118 }
00119
00120
00121 static void getfunc (lua_State *L, int opt) {
00122 if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
00123 else {
00124 lua_Debug ar;
00125 int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);
00126 luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
00127 if (lua_getstack(L, level, &ar) == 0)
00128 luaL_argerror(L, 1, "invalid level");
00129 lua_getinfo(L, "f", &ar);
00130 if (lua_isnil(L, -1))
00131 luaL_error(L, "no function environment for tail call at level %d",
00132 level);
00133 }
00134 }
00135
00136
00137 static int luaB_getfenv (lua_State *L) {
00138 getfunc(L, 1);
00139 if (lua_iscfunction(L, -1))
00140 lua_pushvalue(L, LUA_GLOBALSINDEX);
00141 else
00142 lua_getfenv(L, -1);
00143 return 1;
00144 }
00145
00146
00147 static int luaB_setfenv (lua_State *L) {
00148 luaL_checktype(L, 2, LUA_TTABLE);
00149 getfunc(L, 0);
00150 lua_pushvalue(L, 2);
00151 if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
00152
00153 lua_pushthread(L);
00154 lua_insert(L, -2);
00155 lua_setfenv(L, -2);
00156 return 0;
00157 }
00158 else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
00159 luaL_error(L,
00160 LUA_QL("setfenv") " cannot change environment of given object");
00161 return 1;
00162 }
00163
00164
00165 static int luaB_rawequal (lua_State *L) {
00166 luaL_checkany(L, 1);
00167 luaL_checkany(L, 2);
00168 lua_pushboolean(L, lua_rawequal(L, 1, 2));
00169 return 1;
00170 }
00171
00172
00173 static int luaB_rawget (lua_State *L) {
00174 luaL_checktype(L, 1, LUA_TTABLE);
00175 luaL_checkany(L, 2);
00176 lua_settop(L, 2);
00177 lua_rawget(L, 1);
00178 return 1;
00179 }
00180
00181 static int luaB_rawset (lua_State *L) {
00182 luaL_checktype(L, 1, LUA_TTABLE);
00183 luaL_checkany(L, 2);
00184 luaL_checkany(L, 3);
00185 lua_settop(L, 3);
00186 lua_rawset(L, 1);
00187 return 1;
00188 }
00189
00190
00191 static int luaB_gcinfo (lua_State *L) {
00192 lua_pushinteger(L, lua_getgccount(L));
00193 return 1;
00194 }
00195
00196
00197 static int luaB_collectgarbage (lua_State *L) {
00198 static const char *const opts[] = {"stop", "restart", "collect",
00199 "count", "step", "setpause", "setstepmul", NULL};
00200 static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
00201 LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
00202 int o = luaL_checkoption(L, 1, "collect", opts);
00203 int ex = luaL_optint(L, 2, 0);
00204 int res = lua_gc(L, optsnum[o], ex);
00205 switch (optsnum[o]) {
00206 case LUA_GCCOUNT: {
00207 int b = lua_gc(L, LUA_GCCOUNTB, 0);
00208 lua_pushnumber(L, res + ((lua_Number)b/1024));
00209 return 1;
00210 }
00211 case LUA_GCSTEP: {
00212 lua_pushboolean(L, res);
00213 return 1;
00214 }
00215 default: {
00216 lua_pushnumber(L, res);
00217 return 1;
00218 }
00219 }
00220 }
00221
00222
00223 static int luaB_type (lua_State *L) {
00224 luaL_checkany(L, 1);
00225 lua_pushstring(L, luaL_typename(L, 1));
00226 return 1;
00227 }
00228
00229
00230 static int luaB_next (lua_State *L) {
00231 luaL_checktype(L, 1, LUA_TTABLE);
00232 lua_settop(L, 2);
00233 if (lua_next(L, 1))
00234 return 2;
00235 else {
00236 lua_pushnil(L);
00237 return 1;
00238 }
00239 }
00240
00241
00242 static int luaB_pairs (lua_State *L) {
00243 luaL_checktype(L, 1, LUA_TTABLE);
00244 lua_pushvalue(L, lua_upvalueindex(1));
00245 lua_pushvalue(L, 1);
00246 lua_pushnil(L);
00247 return 3;
00248 }
00249
00250
00251 static int ipairsaux (lua_State *L) {
00252 int i = luaL_checkint(L, 2);
00253 luaL_checktype(L, 1, LUA_TTABLE);
00254 i++;
00255 lua_pushinteger(L, i);
00256 lua_rawgeti(L, 1, i);
00257 return (lua_isnil(L, -1)) ? 0 : 2;
00258 }
00259
00260
00261 static int luaB_ipairs (lua_State *L) {
00262 luaL_checktype(L, 1, LUA_TTABLE);
00263 lua_pushvalue(L, lua_upvalueindex(1));
00264 lua_pushvalue(L, 1);
00265 lua_pushinteger(L, 0);
00266 return 3;
00267 }
00268
00269
00270 static int load_aux (lua_State *L, int status) {
00271 if (status == 0)
00272 return 1;
00273 else {
00274 lua_pushnil(L);
00275 lua_insert(L, -2);
00276 return 2;
00277 }
00278 }
00279
00280
00281 static int luaB_loadstring (lua_State *L) {
00282 size_t l;
00283 const char *s = luaL_checklstring(L, 1, &l);
00284 const char *chunkname = luaL_optstring(L, 2, s);
00285 return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
00286 }
00287
00288
00289 static int luaB_loadfile (lua_State *L) {
00290 const char *fname = luaL_optstring(L, 1, NULL);
00291 return load_aux(L, luaL_loadfile(L, fname));
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301 static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
00302 (void)ud;
00303 luaL_checkstack(L, 2, "too many nested functions");
00304 lua_pushvalue(L, 1);
00305 lua_call(L, 0, 1);
00306 if (lua_isnil(L, -1)) {
00307 *size = 0;
00308 return NULL;
00309 }
00310 else if (lua_isstring(L, -1)) {
00311 lua_replace(L, 3);
00312 return lua_tolstring(L, 3, size);
00313 }
00314 else luaL_error(L, "reader function must return a string");
00315 return NULL;
00316 }
00317
00318
00319 static int luaB_load (lua_State *L) {
00320 int status;
00321 const char *cname = luaL_optstring(L, 2, "=(load)");
00322 luaL_checktype(L, 1, LUA_TFUNCTION);
00323 lua_settop(L, 3);
00324 status = lua_load(L, generic_reader, NULL, cname);
00325 return load_aux(L, status);
00326 }
00327
00328
00329 static int luaB_dofile (lua_State *L) {
00330 const char *fname = luaL_optstring(L, 1, NULL);
00331 int n = lua_gettop(L);
00332 if (luaL_loadfile(L, fname) != 0) lua_error(L);
00333 lua_call(L, 0, LUA_MULTRET);
00334 return lua_gettop(L) - n;
00335 }
00336
00337
00338 static int luaB_assert (lua_State *L) {
00339 luaL_checkany(L, 1);
00340 if (!lua_toboolean(L, 1))
00341 return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
00342 return lua_gettop(L);
00343 }
00344
00345
00346 static int luaB_unpack (lua_State *L) {
00347 int i, e, n;
00348 luaL_checktype(L, 1, LUA_TTABLE);
00349 i = luaL_optint(L, 2, 1);
00350 e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
00351 n = e - i + 1;
00352 if (n <= 0) return 0;
00353 luaL_checkstack(L, n, "table too big to unpack");
00354 for (; i<=e; i++)
00355 lua_rawgeti(L, 1, i);
00356 return n;
00357 }
00358
00359
00360 static int luaB_select (lua_State *L) {
00361 int n = lua_gettop(L);
00362 if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
00363 lua_pushinteger(L, n-1);
00364 return 1;
00365 }
00366 else {
00367 int i = luaL_checkint(L, 1);
00368 if (i < 0) i = n + i;
00369 else if (i > n) i = n;
00370 luaL_argcheck(L, 1 <= i, 1, "index out of range");
00371 return n - i;
00372 }
00373 }
00374
00375
00376 static int luaB_pcall (lua_State *L) {
00377 int status;
00378 luaL_checkany(L, 1);
00379 status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
00380 lua_pushboolean(L, (status == 0));
00381 lua_insert(L, 1);
00382 return lua_gettop(L);
00383 }
00384
00385
00386 static int luaB_xpcall (lua_State *L) {
00387 int status;
00388 luaL_checkany(L, 2);
00389 lua_settop(L, 2);
00390 lua_insert(L, 1);
00391 status = lua_pcall(L, 0, LUA_MULTRET, 1);
00392 lua_pushboolean(L, (status == 0));
00393 lua_replace(L, 1);
00394 return lua_gettop(L);
00395 }
00396
00397
00398 static int luaB_tostring (lua_State *L) {
00399 luaL_checkany(L, 1);
00400 if (luaL_callmeta(L, 1, "__tostring"))
00401 return 1;
00402 switch (lua_type(L, 1)) {
00403 case LUA_TNUMBER:
00404 lua_pushstring(L, lua_tostring(L, 1));
00405 break;
00406 case LUA_TSTRING:
00407 lua_pushvalue(L, 1);
00408 break;
00409 case LUA_TBOOLEAN:
00410 lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
00411 break;
00412 case LUA_TNIL:
00413 lua_pushliteral(L, "nil");
00414 break;
00415 default:
00416 lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
00417 break;
00418 }
00419 return 1;
00420 }
00421
00422
00423 static int luaB_newproxy (lua_State *L) {
00424 lua_settop(L, 1);
00425 lua_newuserdata(L, 0);
00426 if (lua_toboolean(L, 1) == 0)
00427 return 1;
00428 else if (lua_isboolean(L, 1)) {
00429 lua_newtable(L);
00430 lua_pushvalue(L, -1);
00431 lua_pushboolean(L, 1);
00432 lua_rawset(L, lua_upvalueindex(1));
00433 }
00434 else {
00435 int validproxy = 0;
00436 if (lua_getmetatable(L, 1)) {
00437 lua_rawget(L, lua_upvalueindex(1));
00438 validproxy = lua_toboolean(L, -1);
00439 lua_pop(L, 1);
00440 }
00441 luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
00442 lua_getmetatable(L, 1);
00443 }
00444 lua_setmetatable(L, 2);
00445 return 1;
00446 }
00447
00448
00449 static const luaL_Reg base_funcs[] = {
00450 {"assert", luaB_assert},
00451 {"collectgarbage", luaB_collectgarbage},
00452 {"dofile", luaB_dofile},
00453 {"error", luaB_error},
00454 {"gcinfo", luaB_gcinfo},
00455 {"getfenv", luaB_getfenv},
00456 {"getmetatable", luaB_getmetatable},
00457 {"loadfile", luaB_loadfile},
00458 {"load", luaB_load},
00459 {"loadstring", luaB_loadstring},
00460 {"next", luaB_next},
00461 {"pcall", luaB_pcall},
00462 {"print", luaB_print},
00463 {"log", luaB_print},
00464 {"rawequal", luaB_rawequal},
00465 {"rawget", luaB_rawget},
00466 {"rawset", luaB_rawset},
00467 {"select", luaB_select},
00468 {"setfenv", luaB_setfenv},
00469 {"setmetatable", luaB_setmetatable},
00470 {"tonumber", luaB_tonumber},
00471 {"tostring", luaB_tostring},
00472 {"type", luaB_type},
00473 {"unpack", luaB_unpack},
00474 {"xpcall", luaB_xpcall},
00475 {NULL, NULL}
00476 };
00477
00478
00479
00480
00481
00482
00483
00484
00485 static int auxresume (lua_State *L, lua_State *co, int narg) {
00486 int status;
00487 if (!lua_checkstack(co, narg))
00488 luaL_error(L, "too many arguments to resume");
00489 if (lua_status(co) == 0 && lua_gettop(co) == 0) {
00490 lua_pushliteral(L, "cannot resume dead coroutine");
00491 return -1;
00492 }
00493 lua_xmove(L, co, narg);
00494 status = lua_resume(co, narg);
00495 if (status == 0 || status == LUA_YIELD) {
00496 int nres = lua_gettop(co);
00497 if (!lua_checkstack(L, nres))
00498 luaL_error(L, "too many results to resume");
00499 lua_xmove(co, L, nres);
00500 return nres;
00501 }
00502 else {
00503 lua_xmove(co, L, 1);
00504 return -1;
00505 }
00506 }
00507
00508
00509 static int luaB_coresume (lua_State *L) {
00510 lua_State *co = lua_tothread(L, 1);
00511 int r;
00512 luaL_argcheck(L, co, 1, "coroutine expected");
00513 r = auxresume(L, co, lua_gettop(L) - 1);
00514 if (r < 0) {
00515 lua_pushboolean(L, 0);
00516 lua_insert(L, -2);
00517 return 2;
00518 }
00519 else {
00520 lua_pushboolean(L, 1);
00521 lua_insert(L, -(r + 1));
00522 return r + 1;
00523 }
00524 }
00525
00526
00527 static int luaB_auxwrap (lua_State *L) {
00528 lua_State *co = lua_tothread(L, lua_upvalueindex(1));
00529 int r = auxresume(L, co, lua_gettop(L));
00530 if (r < 0) {
00531 if (lua_isstring(L, -1)) {
00532 luaL_where(L, 1);
00533 lua_insert(L, -2);
00534 lua_concat(L, 2);
00535 }
00536 lua_error(L);
00537 }
00538 return r;
00539 }
00540
00541
00542 static int luaB_cocreate (lua_State *L) {
00543 lua_State *NL = lua_newthread(L);
00544 luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
00545 "Lua function expected");
00546 lua_pushvalue(L, 1);
00547 lua_xmove(L, NL, 1);
00548 return 1;
00549 }
00550
00551
00552 static int luaB_cowrap (lua_State *L) {
00553 luaB_cocreate(L);
00554 lua_pushcclosure(L, luaB_auxwrap, 1);
00555 return 1;
00556 }
00557
00558
00559 static int luaB_yield (lua_State *L) {
00560 return lua_yield(L, lua_gettop(L));
00561 }
00562
00563
00564 static int luaB_costatus (lua_State *L) {
00565 lua_State *co = lua_tothread(L, 1);
00566 luaL_argcheck(L, co, 1, "coroutine expected");
00567 if (L == co) lua_pushliteral(L, "running");
00568 else {
00569 switch (lua_status(co)) {
00570 case LUA_YIELD:
00571 lua_pushliteral(L, "suspended");
00572 break;
00573 case 0: {
00574 lua_Debug ar;
00575 if (lua_getstack(co, 0, &ar) > 0)
00576 lua_pushliteral(L, "normal");
00577 else if (lua_gettop(co) == 0)
00578 lua_pushliteral(L, "dead");
00579 else
00580 lua_pushliteral(L, "suspended");
00581 break;
00582 }
00583 default:
00584 lua_pushliteral(L, "dead");
00585 break;
00586 }
00587 }
00588 return 1;
00589 }
00590
00591
00592 static int luaB_corunning (lua_State *L) {
00593 if (lua_pushthread(L))
00594 return 0;
00595 else
00596 return 1;
00597 }
00598
00599
00600 static const luaL_Reg co_funcs[] = {
00601 {"create", luaB_cocreate},
00602 {"resume", luaB_coresume},
00603 {"running", luaB_corunning},
00604 {"status", luaB_costatus},
00605 {"wrap", luaB_cowrap},
00606 {"yield", luaB_yield},
00607 {NULL, NULL}
00608 };
00609
00610
00611
00612
00613 static void auxopen (lua_State *L, const char *name,
00614 lua_CFunction f, lua_CFunction u) {
00615 lua_pushcfunction(L, u);
00616 lua_pushcclosure(L, f, 1);
00617 lua_setfield(L, -2, name);
00618 }
00619
00620
00621 static void base_open (lua_State *L) {
00622
00623 lua_pushvalue(L, LUA_GLOBALSINDEX);
00624 lua_setglobal(L, "_G");
00625
00626 luaL_register(L, "_G", base_funcs);
00627 lua_pushliteral(L, LUA_VERSION);
00628 lua_setglobal(L, "_VERSION");
00629
00630 auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
00631 auxopen(L, "pairs", luaB_pairs, luaB_next);
00632
00633 lua_createtable(L, 0, 1);
00634 lua_pushvalue(L, -1);
00635 lua_setmetatable(L, -2);
00636 lua_pushliteral(L, "kv");
00637 lua_setfield(L, -2, "__mode");
00638 lua_pushcclosure(L, luaB_newproxy, 1);
00639 lua_setglobal(L, "newproxy");
00640 }
00641
00642
00643 LUALIB_API int luaopen_base (lua_State *L) {
00644 base_open(L);
00645 luaL_register(L, LUA_COLIBNAME, co_funcs);
00646 return 2;
00647 }
00648