lbaselib.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:16k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /*
  2. ** $Id: lbaselib.c,v 1.189 2006/01/18 11:49:12 roberto Exp $
  3. ** Basic library
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <ctype.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #define lbaselib_c
  11. #define LUA_LIB
  12. #include "lua.h"
  13. #include "lauxlib.h"
  14. #include "lualib.h"
  15. /*
  16. ** If your system does not support `stdout', you can just remove this function.
  17. ** If you need, you can define your own `print' function, following this
  18. ** model but changing `fputs' to put the strings at a proper place
  19. ** (a console window or a log file, for instance).
  20. */
  21. static int luaB_print (lua_State *L) {
  22.   int n = lua_gettop(L);  /* number of arguments */
  23.   int i;
  24.   lua_getglobal(L, "tostring");
  25.   for (i=1; i<=n; i++) {
  26.     const char *s;
  27.     lua_pushvalue(L, -1);  /* function to be called */
  28.     lua_pushvalue(L, i);   /* value to print */
  29.     lua_call(L, 1, 1);
  30.     s = lua_tostring(L, -1);  /* get result */
  31.     if (s == NULL)
  32.       return luaL_error(L, LUA_QL("tostring") " must return a string to "
  33.                            LUA_QL("print"));
  34.     if (i>1) fputs("t", stdout);
  35.     fputs(s, stdout);
  36.     lua_pop(L, 1);  /* pop result */
  37.   }
  38.   fputs("n", stdout);
  39.   return 0;
  40. }
  41. static int luaB_tonumber (lua_State *L) {
  42.   int base = luaL_optint(L, 2, 10);
  43.   if (base == 10) {  /* standard conversion */
  44.     luaL_checkany(L, 1);
  45.     if (lua_isnumber(L, 1)) {
  46.       lua_pushnumber(L, lua_tonumber(L, 1));
  47.       return 1;
  48.     }
  49.   }
  50.   else {
  51.     const char *s1 = luaL_checkstring(L, 1);
  52.     char *s2;
  53.     unsigned long n;
  54.     luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
  55.     n = strtoul(s1, &s2, base);
  56.     if (s1 != s2) {  /* at least one valid digit? */
  57.       while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */
  58.       if (*s2 == '') {  /* no invalid trailing characters? */
  59.         lua_pushnumber(L, (lua_Number)n);
  60.         return 1;
  61.       }
  62.     }
  63.   }
  64.   lua_pushnil(L);  /* else not a number */
  65.   return 1;
  66. }
  67. static int luaB_error (lua_State *L) {
  68.   int level = luaL_optint(L, 2, 1);
  69.   lua_settop(L, 1);
  70.   if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */
  71.     luaL_where(L, level);
  72.     lua_pushvalue(L, 1);
  73.     lua_concat(L, 2);
  74.   }
  75.   return lua_error(L);
  76. }
  77. static int luaB_getmetatable (lua_State *L) {
  78.   luaL_checkany(L, 1);
  79.   if (!lua_getmetatable(L, 1)) {
  80.     lua_pushnil(L);
  81.     return 1;  /* no metatable */
  82.   }
  83.   luaL_getmetafield(L, 1, "__metatable");
  84.   return 1;  /* returns either __metatable field (if present) or metatable */
  85. }
  86. static int luaB_setmetatable (lua_State *L) {
  87.   int t = lua_type(L, 2);
  88.   luaL_checktype(L, 1, LUA_TTABLE);
  89.   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
  90.                     "nil or table expected");
  91.   if (luaL_getmetafield(L, 1, "__metatable"))
  92.     luaL_error(L, "cannot change a protected metatable");
  93.   lua_settop(L, 2);
  94.   lua_setmetatable(L, 1);
  95.   return 1;
  96. }
  97. static void getfunc (lua_State *L) {
  98.   if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);
  99.   else {
  100.     lua_Debug ar;
  101.     int level = luaL_optint(L, 1, 1);
  102.     luaL_argcheck(L, level >= 0, 1, "level must be non-negative");
  103.     if (lua_getstack(L, level, &ar) == 0)
  104.       luaL_argerror(L, 1, "invalid level");
  105.     lua_getinfo(L, "f", &ar);
  106.     if (lua_isnil(L, -1))
  107.       luaL_error(L, "no function environment for tail call at level %d",
  108.                     level);
  109.   }
  110. }
  111. static int luaB_getfenv (lua_State *L) {
  112.   getfunc(L);
  113.   if (lua_iscfunction(L, -1))  /* is a C function? */
  114.     lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */
  115.   else
  116.     lua_getfenv(L, -1);
  117.   return 1;
  118. }
  119. static int luaB_setfenv (lua_State *L) {
  120.   luaL_checktype(L, 2, LUA_TTABLE);
  121.   getfunc(L);
  122.   lua_pushvalue(L, 2);
  123.   if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {
  124.     /* change environment of current thread */
  125.     lua_pushthread(L);
  126.     lua_insert(L, -2);
  127.     lua_setfenv(L, -2);
  128.     return 0;
  129.   }
  130.   else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)
  131.     luaL_error(L,
  132.           LUA_QL("setfenv") " cannot change environment of given object");
  133.   return 1;
  134. }
  135. static int luaB_rawequal (lua_State *L) {
  136.   luaL_checkany(L, 1);
  137.   luaL_checkany(L, 2);
  138.   lua_pushboolean(L, lua_rawequal(L, 1, 2));
  139.   return 1;
  140. }
  141. static int luaB_rawget (lua_State *L) {
  142.   luaL_checktype(L, 1, LUA_TTABLE);
  143.   luaL_checkany(L, 2);
  144.   lua_settop(L, 2);
  145.   lua_rawget(L, 1);
  146.   return 1;
  147. }
  148. static int luaB_rawset (lua_State *L) {
  149.   luaL_checktype(L, 1, LUA_TTABLE);
  150.   luaL_checkany(L, 2);
  151.   luaL_checkany(L, 3);
  152.   lua_settop(L, 3);
  153.   lua_rawset(L, 1);
  154.   return 1;
  155. }
  156. static int luaB_gcinfo (lua_State *L) {
  157.   lua_pushinteger(L, lua_getgccount(L));
  158.   return 1;
  159. }
  160. static int luaB_collectgarbage (lua_State *L) {
  161.   static const char *const opts[] = {"stop", "restart", "collect",
  162.     "count", "step", "setpause", "setstepmul", NULL};
  163.   static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
  164.     LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};
  165.   int o = luaL_checkoption(L, 1, "collect", opts);
  166.   int ex = luaL_optint(L, 2, 0);
  167.   int res = lua_gc(L, optsnum[o], ex);
  168.   switch (optsnum[o]) {
  169.     case LUA_GCCOUNT: {
  170.       int b = lua_gc(L, LUA_GCCOUNTB, 0);
  171.       lua_pushnumber(L, res + ((lua_Number)b/1024));
  172.       return 1;
  173.     }
  174.     case LUA_GCSTEP: {
  175.       lua_pushboolean(L, res);
  176.       return 1;
  177.     }
  178.     default: {
  179.       lua_pushnumber(L, res);
  180.       return 1;
  181.     }
  182.   }
  183. }
  184. static int luaB_type (lua_State *L) {
  185.   luaL_checkany(L, 1);
  186.   lua_pushstring(L, luaL_typename(L, 1));
  187.   return 1;
  188. }
  189. static int luaB_next (lua_State *L) {
  190.   luaL_checktype(L, 1, LUA_TTABLE);
  191.   lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
  192.   if (lua_next(L, 1))
  193.     return 2;
  194.   else {
  195.     lua_pushnil(L);
  196.     return 1;
  197.   }
  198. }
  199. static int luaB_pairs (lua_State *L) {
  200.   luaL_checktype(L, 1, LUA_TTABLE);
  201.   lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
  202.   lua_pushvalue(L, 1);  /* state, */
  203.   lua_pushnil(L);  /* and initial value */
  204.   return 3;
  205. }
  206. static int ipairsaux (lua_State *L) {
  207.   int i = luaL_checkint(L, 2);
  208.   luaL_checktype(L, 1, LUA_TTABLE);
  209.   i++;  /* next value */
  210.   lua_pushinteger(L, i);
  211.   lua_rawgeti(L, 1, i);
  212.   return (lua_isnil(L, -1)) ? 0 : 2;
  213. }
  214. static int luaB_ipairs (lua_State *L) {
  215.   luaL_checktype(L, 1, LUA_TTABLE);
  216.   lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */
  217.   lua_pushvalue(L, 1);  /* state, */
  218.   lua_pushinteger(L, 0);  /* and initial value */
  219.   return 3;
  220. }
  221. static int load_aux (lua_State *L, int status) {
  222.   if (status == 0)  /* OK? */
  223.     return 1;
  224.   else {
  225.     lua_pushnil(L);
  226.     lua_insert(L, -2);  /* put before error message */
  227.     return 2;  /* return nil plus error message */
  228.   }
  229. }
  230. static int luaB_loadstring (lua_State *L) {
  231.   size_t l;
  232.   const char *s = luaL_checklstring(L, 1, &l);
  233.   const char *chunkname = luaL_optstring(L, 2, s);
  234.   return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));
  235. }
  236. static int luaB_loadfile (lua_State *L) {
  237.   const char *fname = luaL_optstring(L, 1, NULL);
  238.   return load_aux(L, luaL_loadfile(L, fname));
  239. }
  240. /*
  241. ** Reader for generic `load' function: `lua_load' uses the
  242. ** stack for internal stuff, so the reader cannot change the
  243. ** stack top. Instead, it keeps its resulting string in a
  244. ** reserved slot inside the stack.
  245. */
  246. static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
  247.   (void)ud;  /* to avoid warnings */
  248.   luaL_checkstack(L, 2, "too many nested functions");
  249.   lua_pushvalue(L, 1);  /* get function */
  250.   lua_call(L, 0, 1);  /* call it */
  251.   if (lua_isnil(L, -1)) {
  252.     *size = 0;
  253.     return NULL;
  254.   }
  255.   else if (lua_isstring(L, -1)) {
  256.     lua_replace(L, 3);  /* save string in a reserved stack slot */
  257.     return lua_tolstring(L, 3, size);
  258.   }
  259.   else luaL_error(L, "reader function must return a string");
  260.   return NULL;  /* to avoid warnings */
  261. }
  262. static int luaB_load (lua_State *L) {
  263.   int status;
  264.   const char *cname = luaL_optstring(L, 2, "=(load)");
  265.   luaL_checktype(L, 1, LUA_TFUNCTION);
  266.   lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */
  267.   status = lua_load(L, generic_reader, NULL, cname);
  268.   return load_aux(L, status);
  269. }
  270. static int luaB_dofile (lua_State *L) {
  271.   const char *fname = luaL_optstring(L, 1, NULL);
  272.   int n = lua_gettop(L);
  273.   if (luaL_loadfile(L, fname) != 0) lua_error(L);
  274.   lua_call(L, 0, LUA_MULTRET);
  275.   return lua_gettop(L) - n;
  276. }
  277. static int luaB_assert (lua_State *L) {
  278.   luaL_checkany(L, 1);
  279.   if (!lua_toboolean(L, 1))
  280.     return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
  281.   return lua_gettop(L);
  282. }
  283. static int luaB_unpack (lua_State *L) {
  284.   int i, e, n;
  285.   luaL_checktype(L, 1, LUA_TTABLE);
  286.   i = luaL_optint(L, 2, 1);
  287.   e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));
  288.   n = e - i + 1;  /* number of elements */
  289.   if (n <= 0) return 0;  /* empty range */
  290.   luaL_checkstack(L, n, "table too big to unpack");
  291.   for (; i<=e; i++)  /* push arg[i...e] */
  292.     lua_rawgeti(L, 1, i);
  293.   return n;
  294. }
  295. static int luaB_select (lua_State *L) {
  296.   int n = lua_gettop(L);
  297.   if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
  298.     lua_pushinteger(L, n-1);
  299.     return 1;
  300.   }
  301.   else {
  302.     int i = luaL_checkint(L, 1);
  303.     if (i < 0) i = n + i;
  304.     else if (i > n) i = n;
  305.     luaL_argcheck(L, 1 <= i, 1, "index out of range");
  306.     return n - i;
  307.   }
  308. }
  309. static int luaB_pcall (lua_State *L) {
  310.   int status;
  311.   luaL_checkany(L, 1);
  312.   status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);
  313.   lua_pushboolean(L, (status == 0));
  314.   lua_insert(L, 1);
  315.   return lua_gettop(L);  /* return status + all results */
  316. }
  317. static int luaB_xpcall (lua_State *L) {
  318.   int status;
  319.   luaL_checkany(L, 2);
  320.   lua_settop(L, 2);
  321.   lua_insert(L, 1);  /* put error function under function to be called */
  322.   status = lua_pcall(L, 0, LUA_MULTRET, 1);
  323.   lua_pushboolean(L, (status == 0));
  324.   lua_replace(L, 1);
  325.   return lua_gettop(L);  /* return status + all results */
  326. }
  327. static int luaB_tostring (lua_State *L) {
  328.   luaL_checkany(L, 1);
  329.   if (luaL_callmeta(L, 1, "__tostring"))  /* is there a metafield? */
  330.     return 1;  /* use its value */
  331.   switch (lua_type(L, 1)) {
  332.     case LUA_TNUMBER:
  333.       lua_pushstring(L, lua_tostring(L, 1));
  334.       break;
  335.     case LUA_TSTRING:
  336.       lua_pushvalue(L, 1);
  337.       break;
  338.     case LUA_TBOOLEAN:
  339.       lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false"));
  340.       break;
  341.     case LUA_TNIL:
  342.       lua_pushliteral(L, "nil");
  343.       break;
  344.     default:
  345.       lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1));
  346.       break;
  347.   }
  348.   return 1;
  349. }
  350. static int luaB_newproxy (lua_State *L) {
  351.   lua_settop(L, 1);
  352.   lua_newuserdata(L, 0);  /* create proxy */
  353.   if (lua_toboolean(L, 1) == 0)
  354.     return 1;  /* no metatable */
  355.   else if (lua_isboolean(L, 1)) {
  356.     lua_newtable(L);  /* create a new metatable `m' ... */
  357.     lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */
  358.     lua_pushboolean(L, 1);
  359.     lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */
  360.   }
  361.   else {
  362.     int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */
  363.     if (lua_getmetatable(L, 1)) {
  364.       lua_rawget(L, lua_upvalueindex(1));
  365.       validproxy = lua_toboolean(L, -1);
  366.       lua_pop(L, 1);  /* remove value */
  367.     }
  368.     luaL_argcheck(L, validproxy, 1, "boolean or proxy expected");
  369.     lua_getmetatable(L, 1);  /* metatable is valid; get it */
  370.   }
  371.   lua_setmetatable(L, 2);
  372.   return 1;
  373. }
  374. static const luaL_Reg base_funcs[] = {
  375.   {"assert", luaB_assert},
  376.   {"collectgarbage", luaB_collectgarbage},
  377.   {"dofile", luaB_dofile},
  378.   {"error", luaB_error},
  379.   {"gcinfo", luaB_gcinfo},
  380.   {"getfenv", luaB_getfenv},
  381.   {"getmetatable", luaB_getmetatable},
  382.   {"loadfile", luaB_loadfile},
  383.   {"load", luaB_load},
  384.   {"loadstring", luaB_loadstring},
  385.   {"next", luaB_next},
  386.   {"pcall", luaB_pcall},
  387.   {"print", luaB_print},
  388.   {"rawequal", luaB_rawequal},
  389.   {"rawget", luaB_rawget},
  390.   {"rawset", luaB_rawset},
  391.   {"select", luaB_select},
  392.   {"setfenv", luaB_setfenv},
  393.   {"setmetatable", luaB_setmetatable},
  394.   {"tonumber", luaB_tonumber},
  395.   {"tostring", luaB_tostring},
  396.   {"type", luaB_type},
  397.   {"unpack", luaB_unpack},
  398.   {"xpcall", luaB_xpcall},
  399.   {NULL, NULL}
  400. };
  401. /*
  402. ** {======================================================
  403. ** Coroutine library
  404. ** =======================================================
  405. */
  406. static int auxresume (lua_State *L, lua_State *co, int narg) {
  407.   int status;
  408.   if (!lua_checkstack(co, narg))
  409.     luaL_error(L, "too many arguments to resume");
  410.   if (lua_status(co) == 0 && lua_gettop(co) == 0) {
  411.     lua_pushliteral(L, "cannot resume dead coroutine");
  412.     return -1;  /* error flag */
  413.   }
  414.   lua_xmove(L, co, narg);
  415.   status = lua_resume(co, narg);
  416.   if (status == 0 || status == LUA_YIELD) {
  417.     int nres = lua_gettop(co);
  418.     if (!lua_checkstack(L, nres))
  419.       luaL_error(L, "too many results to resume");
  420.     lua_xmove(co, L, nres);  /* move yielded values */
  421.     return nres;
  422.   }
  423.   else {
  424.     lua_xmove(co, L, 1);  /* move error message */
  425.     return -1;  /* error flag */
  426.   }
  427. }
  428. static int luaB_coresume (lua_State *L) {
  429.   lua_State *co = lua_tothread(L, 1);
  430.   int r;
  431.   luaL_argcheck(L, co, 1, "coroutine expected");
  432.   r = auxresume(L, co, lua_gettop(L) - 1);
  433.   if (r < 0) {
  434.     lua_pushboolean(L, 0);
  435.     lua_insert(L, -2);
  436.     return 2;  /* return false + error message */
  437.   }
  438.   else {
  439.     lua_pushboolean(L, 1);
  440.     lua_insert(L, -(r + 1));
  441.     return r + 1;  /* return true + `resume' returns */
  442.   }
  443. }
  444. static int luaB_auxwrap (lua_State *L) {
  445.   lua_State *co = lua_tothread(L, lua_upvalueindex(1));
  446.   int r = auxresume(L, co, lua_gettop(L));
  447.   if (r < 0) {
  448.     if (lua_isstring(L, -1)) {  /* error object is a string? */
  449.       luaL_where(L, 1);  /* add extra info */
  450.       lua_insert(L, -2);
  451.       lua_concat(L, 2);
  452.     }
  453.     lua_error(L);  /* propagate error */
  454.   }
  455.   return r;
  456. }
  457. static int luaB_cocreate (lua_State *L) {
  458.   lua_State *NL = lua_newthread(L);
  459.   luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,
  460.     "Lua function expected");
  461.   lua_pushvalue(L, 1);  /* move function to top */
  462.   lua_xmove(L, NL, 1);  /* move function from L to NL */
  463.   return 1;
  464. }
  465. static int luaB_cowrap (lua_State *L) {
  466.   luaB_cocreate(L);
  467.   lua_pushcclosure(L, luaB_auxwrap, 1);
  468.   return 1;
  469. }
  470. static int luaB_yield (lua_State *L) {
  471.   return lua_yield(L, lua_gettop(L));
  472. }
  473. static int luaB_costatus (lua_State *L) {
  474.   lua_State *co = lua_tothread(L, 1);
  475.   luaL_argcheck(L, co, 1, "coroutine expected");
  476.   if (L == co) lua_pushliteral(L, "running");
  477.   else {
  478.     switch (lua_status(co)) {
  479.       case LUA_YIELD:
  480.         lua_pushliteral(L, "suspended");
  481.         break;
  482.       case 0: {
  483.         lua_Debug ar;
  484.         if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */
  485.           lua_pushliteral(L, "normal");  /* it is running */
  486.         else if (lua_gettop(co) == 0)
  487.             lua_pushliteral(L, "dead");
  488.         else
  489.           lua_pushliteral(L, "suspended");  /* initial state */
  490.         break;
  491.       }
  492.       default:  /* some error occured */
  493.         lua_pushliteral(L, "dead");
  494.         break;
  495.     }
  496.   }
  497.   return 1;
  498. }
  499. static int luaB_corunning (lua_State *L) {
  500.   if (lua_pushthread(L))
  501.     return 0;  /* main thread is not a coroutine */
  502.   else
  503.     return 1;
  504. }
  505. static const luaL_Reg co_funcs[] = {
  506.   {"create", luaB_cocreate},
  507.   {"resume", luaB_coresume},
  508.   {"running", luaB_corunning},
  509.   {"status", luaB_costatus},
  510.   {"wrap", luaB_cowrap},
  511.   {"yield", luaB_yield},
  512.   {NULL, NULL}
  513. };
  514. /* }====================================================== */
  515. static void auxopen (lua_State *L, const char *name,
  516.                      lua_CFunction f, lua_CFunction u) {
  517.   lua_pushcfunction(L, u);
  518.   lua_pushcclosure(L, f, 1);
  519.   lua_setfield(L, -2, name);
  520. }
  521. static void base_open (lua_State *L) {
  522.   /* set global _G */
  523.   lua_pushvalue(L, LUA_GLOBALSINDEX);
  524.   lua_setglobal(L, "_G");
  525.   /* open lib into global table */
  526.   luaL_register(L, "_G", base_funcs);
  527.   lua_pushliteral(L, LUA_VERSION);
  528.   lua_setglobal(L, "_VERSION");  /* set global _VERSION */
  529.   /* `ipairs' and `pairs' need auxliliary functions as upvalues */
  530.   auxopen(L, "ipairs", luaB_ipairs, ipairsaux);
  531.   auxopen(L, "pairs", luaB_pairs, luaB_next);
  532.   /* `newproxy' needs a weaktable as upvalue */
  533.   lua_createtable(L, 0, 1);  /* new table `w' */
  534.   lua_pushvalue(L, -1);  /* `w' will be its own metatable */
  535.   lua_setmetatable(L, -2);
  536.   lua_pushliteral(L, "kv");
  537.   lua_setfield(L, -2, "__mode");  /* metatable(w).__mode = "kv" */
  538.   lua_pushcclosure(L, luaB_newproxy, 1);
  539.   lua_setglobal(L, "newproxy");  /* set global `newproxy' */
  540. }
  541. LUALIB_API int luaopen_base (lua_State *L) {
  542.   base_open(L);
  543.   luaL_register(L, LUA_COLIBNAME, co_funcs);
  544.   return 2;
  545. }