/* ** $Id: lbaselib.c,v 1.116 2002/12/20 09:55:56 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ #include #include #include #include #define lbaselib_c #include "lua.h" #include "lauxlib.h" #include "lualib.h" /* ** If your system does not support `stdout', you can just remove this function. ** If you need, you can define your own `print' function, following this ** model but changing `fputs' to put the strings at a proper place ** (a console window or a log file, for instance). */ static int luaB_print (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ int i; lua_getglobal(L, "tostring"); for (i=1; i<=n; i++) { const char *s; lua_pushvalue(L, -1); /* function to be called */ lua_pushvalue(L, i); /* value to print */ lua_call(L, 1, 1); s = lua_tostring(L, -1); /* get result */ if (s == NULL) return luaL_error(L, "`tostring' must return a string to `print'"); if (i>1) fputs("\t", stdout); fputs(s, stdout); lua_pop(L, 1); /* pop result */ } fputs("\n", stdout); return 0; } static int luaB_tonumber (lua_State *L) { int base = luaL_optint(L, 2, 10); if (base == 10) { /* standard conversion */ luaL_checkany(L, 1); if (lua_isnumber(L, 1)) { lua_pushnumber(L, lua_tonumber(L, 1)); return 1; } } else { const char *s1 = luaL_checkstring(L, 1); char *s2; unsigned long n; luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); n = strtoul(s1, &s2, base); if (s1 != s2) { /* at least one valid digit? */ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ if (*s2 == '\0') { /* no invalid trailing characters? */ lua_pushnumber(L, n); return 1; } } } lua_pushnil(L); /* else not a number */ return 1; } static int luaB_error (lua_State *L) { int level = luaL_optint(L, 2, 1); luaL_checkany(L, 1); if (!lua_isstring(L, 1) || level == 0) lua_pushvalue(L, 1); /* propagate error message without changes */ else { /* add extra information */ luaL_where(L, level); lua_pushvalue(L, 1); lua_concat(L, 2); } return lua_error(L); } static int luaB_getmetatable (lua_State *L) { luaL_checkany(L, 1); if (!lua_getmetatable(L, 1)) { lua_pushnil(L); return 1; /* no metatable */ } luaL_getmetafield(L, 1, "__metatable"); return 1; /* returns either __metatable field (if present) or metatable */ } static int luaB_setmetatable (lua_State *L) { int t = lua_type(L, 2); luaL_checktype(L, 1, LUA_TTABLE); luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table expected"); if (luaL_getmetafield(L, 1, "__metatable")) luaL_error(L, "cannot change a protected metatable"); lua_settop(L, 2); lua_setmetatable(L, 1); return 1; } static void getfunc (lua_State *L) { if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); else { lua_Debug ar; int level = luaL_optint(L, 1, 1); luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); if (lua_getstack(L, level, &ar) == 0) luaL_argerror(L, 1, "invalid level"); lua_getinfo(L, "f", &ar); } } static int aux_getglobals (lua_State *L) { lua_getglobals(L, -1); lua_pushliteral(L, "__globals"); lua_rawget(L, -2); return !lua_isnil(L, -1); } static int luaB_getglobals (lua_State *L) { getfunc(L); if (!aux_getglobals(L)) /* __globals not defined? */ lua_pop(L, 1); /* remove it, to return real globals */ return 1; } static int luaB_setglobals (lua_State *L) { luaL_checktype(L, 2, LUA_TTABLE); getfunc(L); if (aux_getglobals(L)) /* __globals defined? */ luaL_error(L, "cannot change a protected global table"); else lua_pop(L, 2); /* remove __globals and real global table */ lua_pushvalue(L, 2); if (lua_setglobals(L, -2) == 0) luaL_error(L, "cannot change global table of given function"); return 0; } static int luaB_rawequal (lua_State *L) { luaL_checkany(L, 1); luaL_checkany(L, 2); lua_pushboolean(L, lua_rawequal(L, 1, 2)); return 1; } static int luaB_rawget (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checkany(L, 2); lua_rawget(L, 1); return 1; } static int luaB_rawset (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checkany(L, 2); luaL_checkany(L, 3); lua_rawset(L, 1); return 1; } static int luaB_gcinfo (lua_State *L) { lua_pushnumber(L, lua_getgccount(L)); lua_pushnumber(L, lua_getgcthreshold(L)); return 2; } static int luaB_collectgarbage (lua_State *L) { lua_setgcthreshold(L, luaL_optint(L, 1, 0)); return 0; } static int luaB_type (lua_State *L) { luaL_checkany(L, 1); lua_pushstring(L, lua_typename(L, lua_type(L, 1))); return 1; } static int luaB_next (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 2); /* create a 2nd argument if there isn't one */ if (lua_next(L, 1)) return 2; else { lua_pushnil(L); return 1; } } static int luaB_pairs (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_pushliteral(L, "next"); lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ lua_pushvalue(L, 1); /* state, */ lua_pushnil(L); /* and initial value */ return 3; } static int luaB_ipairs (lua_State *L) { lua_Number i = lua_tonumber(L, 2); luaL_checktype(L, 1, LUA_TTABLE); if (i == 0 && lua_isnone(L, 2)) { /* `for' start? */ lua_pushliteral(L, "ipairs"); lua_rawget(L, LUA_GLOBALSINDEX); /* return generator, */ lua_pushvalue(L, 1); /* state, */ lua_pushnumber(L, 0); /* and initial value */ return 3; } else { /* `for' step */ i++; /* next value */ lua_pushnumber(L, i); lua_rawgeti(L, 1, (int)i); return (lua_isnil(L, -1)) ? 0 : 2; } } static int load_aux (lua_State *L, int status) { if (status == 0) { /* OK? */ lua_Debug ar; lua_getstack(L, 1, &ar); lua_getinfo(L, "f", &ar); /* get calling function */ lua_getglobals(L, -1); /* get its global table */ lua_setglobals(L, -3); /* set it as the global table of the new chunk */ lua_pop(L, 1); /* remove calling function */ return 1; } else { lua_pushnil(L); lua_insert(L, -2); return 2; } } static int luaB_loadstring (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); const char *chunkname = luaL_optstring(L, 2, s); return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); } static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); return load_aux(L, luaL_loadfile(L, fname)); } static int luaB_dofile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); int status = luaL_loadfile(L, fname); if (status != 0) lua_error(L); lua_call(L, 0, LUA_MULTRET); return lua_gettop(L) - 1; } static int luaB_assert (lua_State *L) { luaL_checkany(L, 1); if (!lua_toboolean(L, 1)) return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); lua_settop(L, 1); return 1; } static int luaB_unpack (lua_State *L) { int n, i; luaL_checktype(L, 1, LUA_TTABLE); lua_pushliteral(L, "n"); lua_rawget(L, 1); n = (lua_isnumber(L, -1)) ? (int)lua_tonumber(L, -1) : -1; for (i=0; i