lapi.c
上传用户:jxpjxmjjw
上传日期:2009-12-07
资源大小:5877k
文件大小:19k
源码类别:

模拟服务器

开发平台:

Visual C++

  1. /*
  2. ** $Id: lapi.c,v 1.1 2004/08/20 02:26:56 JH Exp $
  3. ** Lua API
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <assert.h>
  7. #include <string.h>
  8. #define lapi_c
  9. #include "lua.h"
  10. #include "lapi.h"
  11. #include "ldebug.h"
  12. #include "ldo.h"
  13. #include "lfunc.h"
  14. #include "lgc.h"
  15. #include "lmem.h"
  16. #include "lobject.h"
  17. #include "lstate.h"
  18. #include "lstring.h"
  19. #include "ltable.h"
  20. #include "ltm.h"
  21. #include "lundump.h"
  22. #include "lvm.h"
  23. const char lua_ident[] =
  24.   "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $n"
  25.   "$Authors: " LUA_AUTHORS " $n"
  26.   "$URL: www.lua.org $n";
  27. #ifndef api_check
  28. #define api_check(L, o) /*{ assert(o); }*/
  29. #endif
  30. #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base))
  31. #define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}
  32. static TObject *negindex (lua_State *L, int idx) {
  33.   if (idx > LUA_REGISTRYINDEX) {
  34.     api_check(L, idx != 0 && -idx <= L->top - L->base);
  35.     return L->top+idx;
  36.   }
  37.   else switch (idx) {  /* pseudo-indices */
  38.     case LUA_REGISTRYINDEX: return registry(L);
  39.     case LUA_GLOBALSINDEX: return gt(L);
  40.     default: {
  41.       TObject *func = (L->base - 1);
  42.       idx = LUA_GLOBALSINDEX - idx;
  43.       lua_assert(iscfunction(func));
  44.       return (idx <= clvalue(func)->c.nupvalues)
  45.                 ? &clvalue(func)->c.upvalue[idx-1]
  46.                 : NULL;
  47.     }
  48.   }
  49. }
  50. static TObject *luaA_index (lua_State *L, int idx) {
  51.   if (idx > 0) {
  52.     api_check(L, idx <= L->top - L->base);
  53.     return L->base + idx - 1;
  54.   }
  55.   else {
  56.     TObject *o = negindex(L, idx);
  57.     api_check(L, o != NULL);
  58.     return o;
  59.   }
  60. }
  61. static TObject *luaA_indexAcceptable (lua_State *L, int idx) {
  62.   if (idx > 0) {
  63.     TObject *o = L->base+(idx-1);
  64.     api_check(L, idx <= L->stack_last - L->base);
  65.     if (o >= L->top) return NULL;
  66.     else return o;
  67.   }
  68.   else
  69.     return negindex(L, idx);
  70. }
  71. void luaA_pushobject (lua_State *L, const TObject *o) {
  72.   setobj2s(L->top, o);
  73.   incr_top(L);
  74. }
  75. LUA_API int lua_checkstack (lua_State *L, int size) {
  76.   int res;
  77.   lua_lock(L);
  78.   if ((L->top - L->base + size) > LUA_MAXCSTACK)
  79.     res = 0;  /* stack overflow */
  80.   else {
  81.     luaD_checkstack(L, size);
  82.     if (L->ci->top < L->top + size)
  83.       L->ci->top = L->top + size;
  84.     res = 1;
  85.   }
  86.   lua_unlock(L);
  87.   return res;
  88. }
  89. LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
  90.   int i;
  91.   lua_lock(to);
  92.   api_checknelems(from, n);
  93.   from->top -= n;
  94.   for (i = 0; i < n; i++) {
  95.     setobj2s(to->top, from->top + i);
  96.     api_incr_top(to);
  97.   }
  98.   lua_unlock(to);
  99. }
  100. LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
  101.   lua_CFunction old;
  102.   lua_lock(L);
  103.   old = G(L)->panic;
  104.   G(L)->panic = panicf;
  105.   lua_unlock(L);
  106.   return old;
  107. }
  108. LUA_API lua_State *lua_newthread (lua_State *L) {
  109.   lua_State *L1;
  110.   lua_lock(L);
  111.   luaC_checkGC(L);
  112.   L1 = luaE_newthread(L);
  113.   setthvalue(L->top, L1);
  114.   api_incr_top(L);
  115.   lua_unlock(L);
  116.   lua_userstateopen(L1);
  117.   return L1;
  118. }
  119. /*
  120. ** basic stack manipulation
  121. */
  122. LUA_API int lua_gettop (lua_State *L) {
  123.   return (L->top - L->base);
  124. }
  125. LUA_API void lua_settop (lua_State *L, int idx) {
  126.   lua_lock(L);
  127.   if (idx >= 0) {
  128.     api_check(L, idx <= L->stack_last - L->base);
  129.     while (L->top < L->base + idx)
  130.       setnilvalue(L->top++);
  131.     L->top = L->base + idx;
  132.   }
  133.   else {
  134.     api_check(L, -(idx+1) <= (L->top - L->base));
  135.     L->top += idx+1;  /* `subtract' index (index is negative) */
  136.   }
  137.   lua_unlock(L);
  138. }
  139. LUA_API void lua_remove (lua_State *L, int idx) {
  140.   StkId p;
  141.   lua_lock(L);
  142.   p = luaA_index(L, idx);
  143.   while (++p < L->top) setobjs2s(p-1, p);
  144.   L->top--;
  145.   lua_unlock(L);
  146. }
  147. LUA_API void lua_insert (lua_State *L, int idx) {
  148.   StkId p;
  149.   StkId q;
  150.   lua_lock(L);
  151.   p = luaA_index(L, idx);
  152.   for (q = L->top; q>p; q--) setobjs2s(q, q-1);
  153.   setobjs2s(p, L->top);
  154.   lua_unlock(L);
  155. }
  156. LUA_API void lua_replace (lua_State *L, int idx) {
  157.   lua_lock(L);
  158.   api_checknelems(L, 1);
  159.   setobj(luaA_index(L, idx), L->top - 1);  /* write barrier */
  160.   L->top--;
  161.   lua_unlock(L);
  162. }
  163. LUA_API void lua_pushvalue (lua_State *L, int idx) {
  164.   lua_lock(L);
  165.   setobj2s(L->top, luaA_index(L, idx));
  166.   api_incr_top(L);
  167.   lua_unlock(L);
  168. }
  169. /*
  170. ** access functions (stack -> C)
  171. */
  172. LUA_API int lua_type (lua_State *L, int idx) {
  173.   StkId o = luaA_indexAcceptable(L, idx);
  174.   return (o == NULL) ? LUA_TNONE : ttype(o);
  175. }
  176. LUA_API const char *lua_typename (lua_State *L, int t) {
  177.   UNUSED(L);
  178.   return (t == LUA_TNONE) ? "no value" : luaT_typenames[t];
  179. }
  180. LUA_API int lua_iscfunction (lua_State *L, int idx) {
  181.   StkId o = luaA_indexAcceptable(L, idx);
  182.   return (o == NULL) ? 0 : iscfunction(o);
  183. }
  184. LUA_API int lua_isnumber (lua_State *L, int idx) {
  185.   TObject n;
  186.   const TObject *o = luaA_indexAcceptable(L, idx);
  187.   return (o != NULL && tonumber(o, &n));
  188. }
  189. LUA_API int lua_isstring (lua_State *L, int idx) {
  190.   int t = lua_type(L, idx);
  191.   return (t == LUA_TSTRING || t == LUA_TNUMBER);
  192. }
  193. LUA_API int lua_isuserdata (lua_State *L, int idx) {
  194.   const TObject *o = luaA_indexAcceptable(L, idx);
  195.   return (o != NULL && (ttisuserdata(o) || ttislightuserdata(o)));
  196. }
  197. LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
  198.   StkId o1 = luaA_indexAcceptable(L, index1);
  199.   StkId o2 = luaA_indexAcceptable(L, index2);
  200.   return (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
  201.                                     : luaO_rawequalObj(o1, o2);
  202. }
  203. LUA_API int lua_equal (lua_State *L, int index1, int index2) {
  204.   StkId o1, o2;
  205.   int i;
  206.   lua_lock(L);  /* may call tag method */
  207.   o1 = luaA_indexAcceptable(L, index1);
  208.   o2 = luaA_indexAcceptable(L, index2);
  209.   i = (o1 == NULL || o2 == NULL) ? 0  /* index out of range */
  210.                                  : equalobj(L, o1, o2);
  211.   lua_unlock(L);
  212.   return i;
  213. }
  214. LUA_API int lua_lessthan (lua_State *L, int index1, int index2) {
  215.   StkId o1, o2;
  216.   int i;
  217.   lua_lock(L);  /* may call tag method */
  218.   o1 = luaA_indexAcceptable(L, index1);
  219.   o2 = luaA_indexAcceptable(L, index2);
  220.   i = (o1 == NULL || o2 == NULL) ? 0  /* index out-of-range */
  221.                                  : luaV_lessthan(L, o1, o2);
  222.   lua_unlock(L);
  223.   return i;
  224. }
  225. LUA_API lua_Number lua_tonumber (lua_State *L, int idx) {
  226.   TObject n;
  227.   const TObject *o = luaA_indexAcceptable(L, idx);
  228.   if (o != NULL && tonumber(o, &n))
  229.     return nvalue(o);
  230.   else
  231.     return 0;
  232. }
  233. LUA_API int lua_toboolean (lua_State *L, int idx) {
  234.   const TObject *o = luaA_indexAcceptable(L, idx);
  235.   return (o != NULL) && !l_isfalse(o);
  236. }
  237. LUA_API const char *lua_tostring (lua_State *L, int idx) {
  238.   StkId o = luaA_indexAcceptable(L, idx);
  239.   if (o == NULL)
  240.     return NULL;
  241.   else if (ttisstring(o))
  242.     return svalue(o);
  243.   else {
  244.     const char *s;
  245.     lua_lock(L);  /* `luaV_tostring' may create a new string */
  246.     s = (luaV_tostring(L, o) ? svalue(o) : NULL);
  247.     luaC_checkGC(L);
  248.     lua_unlock(L);
  249.     return s;
  250.   }
  251. }
  252. LUA_API size_t lua_strlen (lua_State *L, int idx) {
  253.   StkId o = luaA_indexAcceptable(L, idx);
  254.   if (o == NULL)
  255.     return 0;
  256.   else if (ttisstring(o))
  257.     return tsvalue(o)->tsv.len;
  258.   else {
  259.     size_t l;
  260.     lua_lock(L);  /* `luaV_tostring' may create a new string */
  261.     l = (luaV_tostring(L, o) ? tsvalue(o)->tsv.len : 0);
  262.     lua_unlock(L);
  263.     return l;
  264.   }
  265. }
  266. LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
  267.   StkId o = luaA_indexAcceptable(L, idx);
  268.   return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->c.f;
  269. }
  270. LUA_API void *lua_touserdata (lua_State *L, int idx) {
  271.   StkId o = luaA_indexAcceptable(L, idx);
  272.   if (o == NULL) return NULL;
  273.   switch (ttype(o)) {
  274.     case LUA_TUSERDATA: return (uvalue(o) + 1);
  275.     case LUA_TLIGHTUSERDATA: return pvalue(o);
  276.     default: return NULL;
  277.   }
  278. }
  279. LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
  280.   StkId o = luaA_indexAcceptable(L, idx);
  281.   return (o == NULL || !ttisthread(o)) ? NULL : thvalue(o);
  282. }
  283. LUA_API const void *lua_topointer (lua_State *L, int idx) {
  284.   StkId o = luaA_indexAcceptable(L, idx);
  285.   if (o == NULL) return NULL;
  286.   else {
  287.     switch (ttype(o)) {
  288.       case LUA_TTABLE: return hvalue(o);
  289.       case LUA_TFUNCTION: return clvalue(o);
  290.       case LUA_TTHREAD: return thvalue(o);
  291.       case LUA_TUSERDATA:
  292.       case LUA_TLIGHTUSERDATA:
  293.         return lua_touserdata(L, idx);
  294.       default: return NULL;
  295.     }
  296.   }
  297. }
  298. /*
  299. ** push functions (C -> stack)
  300. */
  301. LUA_API void lua_pushnil (lua_State *L) {
  302.   lua_lock(L);
  303.   setnilvalue(L->top);
  304.   api_incr_top(L);
  305.   lua_unlock(L);
  306. }
  307. LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
  308.   lua_lock(L);
  309.   setnvalue(L->top, n);
  310.   api_incr_top(L);
  311.   lua_unlock(L);
  312. }
  313. LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {
  314.   lua_lock(L);
  315.   luaC_checkGC(L);
  316.   setsvalue2s(L->top, luaS_newlstr(L, s, len));
  317.   api_incr_top(L);
  318.   lua_unlock(L);
  319. }
  320. LUA_API void lua_pushstring (lua_State *L, const char *s) {
  321.   if (s == NULL)
  322.     lua_pushnil(L);
  323.   else
  324.     lua_pushlstring(L, s, strlen(s));
  325. }
  326. LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
  327.                                       va_list argp) {
  328.   const char *ret;
  329.   lua_lock(L);
  330.   luaC_checkGC(L);
  331.   ret = luaO_pushvfstring(L, fmt, argp);
  332.   lua_unlock(L);
  333.   return ret;
  334. }
  335. LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
  336.   const char *ret;
  337.   va_list argp;
  338.   lua_lock(L);
  339.   luaC_checkGC(L);
  340.   va_start(argp, fmt);
  341.   ret = luaO_pushvfstring(L, fmt, argp);
  342.   va_end(argp);
  343.   lua_unlock(L);
  344.   return ret;
  345. }
  346. LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
  347.   Closure *cl;
  348.   lua_lock(L);
  349.   luaC_checkGC(L);
  350.   api_checknelems(L, n);
  351.   cl = luaF_newCclosure(L, n);
  352.   cl->c.f = fn;
  353.   L->top -= n;
  354.   while (n--)
  355.     setobj2n(&cl->c.upvalue[n], L->top+n);
  356.   setclvalue(L->top, cl);
  357.   api_incr_top(L);
  358.   lua_unlock(L);
  359. }
  360. LUA_API void lua_pushboolean (lua_State *L, int b) {
  361.   lua_lock(L);
  362.   setbvalue(L->top, (b != 0));  /* ensure that true is 1 */
  363.   api_incr_top(L);
  364.   lua_unlock(L);
  365. }
  366. LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
  367.   lua_lock(L);
  368.   setpvalue(L->top, p);
  369.   api_incr_top(L);
  370.   lua_unlock(L);
  371. }
  372. /*
  373. ** get functions (Lua -> stack)
  374. */
  375. LUA_API void lua_gettable (lua_State *L, int idx) {
  376.   StkId t;
  377.   lua_lock(L);
  378.   t = luaA_index(L, idx);
  379.   setobj2s(L->top - 1, luaV_gettable(L, t, L->top - 1, 0));
  380.   lua_unlock(L);
  381. }
  382. LUA_API void lua_rawget (lua_State *L, int idx) {
  383.   StkId t;
  384.   lua_lock(L);
  385.   t = luaA_index(L, idx);
  386.   api_check(L, ttistable(t));
  387.   setobj2s(L->top - 1, luaH_get(hvalue(t), L->top - 1));
  388.   lua_unlock(L);
  389. }
  390. LUA_API void lua_rawgeti (lua_State *L, int idx, int n) {
  391.   StkId o;
  392.   lua_lock(L);
  393.   o = luaA_index(L, idx);
  394.   api_check(L, ttistable(o));
  395.   setobj2s(L->top, luaH_getnum(hvalue(o), n));
  396.   api_incr_top(L);
  397.   lua_unlock(L);
  398. }
  399. LUA_API void lua_newtable (lua_State *L) {
  400.   lua_lock(L);
  401.   luaC_checkGC(L);
  402.   sethvalue(L->top, luaH_new(L, 0, 0));
  403.   api_incr_top(L);
  404.   lua_unlock(L);
  405. }
  406. LUA_API int lua_getmetatable (lua_State *L, int objindex) {
  407.   const TObject *obj;
  408.   Table *mt = NULL;
  409.   int res;
  410.   lua_lock(L);
  411.   obj = luaA_indexAcceptable(L, objindex);
  412.   if (obj != NULL) {
  413.     switch (ttype(obj)) {
  414.       case LUA_TTABLE:
  415.         mt = hvalue(obj)->metatable;
  416.         break;
  417.       case LUA_TUSERDATA:
  418.         mt = uvalue(obj)->uv.metatable;
  419.         break;
  420.     }
  421.   }
  422.   if (mt == NULL || mt == hvalue(defaultmeta(L)))
  423.     res = 0;
  424.   else {
  425.     sethvalue(L->top, mt);
  426.     api_incr_top(L);
  427.     res = 1;
  428.   }
  429.   lua_unlock(L);
  430.   return res;
  431. }
  432. LUA_API void lua_getfenv (lua_State *L, int idx) {
  433.   StkId o;
  434.   lua_lock(L);
  435.   o = luaA_index(L, idx);
  436.   setobj2s(L->top, isLfunction(o) ? &clvalue(o)->l.g : gt(L));
  437.   api_incr_top(L);
  438.   lua_unlock(L);
  439. }
  440. /*
  441. ** set functions (stack -> Lua)
  442. */
  443. LUA_API void lua_settable (lua_State *L, int idx) {
  444.   StkId t;
  445.   lua_lock(L);
  446.   api_checknelems(L, 2);
  447.   t = luaA_index(L, idx);
  448.   luaV_settable(L, t, L->top - 2, L->top - 1);
  449.   L->top -= 2;  /* pop index and value */
  450.   lua_unlock(L);
  451. }
  452. LUA_API void lua_rawset (lua_State *L, int idx) {
  453.   StkId t;
  454.   lua_lock(L);
  455.   api_checknelems(L, 2);
  456.   t = luaA_index(L, idx);
  457.   api_check(L, ttistable(t));
  458.   setobj2t(luaH_set(L, hvalue(t), L->top-2), L->top-1);  /* write barrier */
  459.   L->top -= 2;
  460.   lua_unlock(L);
  461. }
  462. LUA_API void lua_rawseti (lua_State *L, int idx, int n) {
  463.   StkId o;
  464.   lua_lock(L);
  465.   api_checknelems(L, 1);
  466.   o = luaA_index(L, idx);
  467.   api_check(L, ttistable(o));
  468.   setobj2t(luaH_setnum(L, hvalue(o), n), L->top-1);  /* write barrier */
  469.   L->top--;
  470.   lua_unlock(L);
  471. }
  472. LUA_API int lua_setmetatable (lua_State *L, int objindex) {
  473.   TObject *obj, *mt;
  474.   int res = 1;
  475.   lua_lock(L);
  476.   api_checknelems(L, 1);
  477.   obj = luaA_index(L, objindex);
  478.   mt = (!ttisnil(L->top - 1)) ? L->top - 1 : defaultmeta(L);
  479.   api_check(L, ttistable(mt));
  480.   switch (ttype(obj)) {
  481.     case LUA_TTABLE: {
  482.       hvalue(obj)->metatable = hvalue(mt);  /* write barrier */
  483.       break;
  484.     }
  485.     case LUA_TUSERDATA: {
  486.       uvalue(obj)->uv.metatable = hvalue(mt);  /* write barrier */
  487.       break;
  488.     }
  489.     default: {
  490.       res = 0;  /* cannot set */
  491.       break;
  492.     }
  493.   }
  494.   L->top--;
  495.   lua_unlock(L);
  496.   return res;
  497. }
  498. LUA_API int lua_setfenv (lua_State *L, int idx) {
  499.   StkId o;
  500.   int res = 0;
  501.   lua_lock(L);
  502.   api_checknelems(L, 1);
  503.   o = luaA_index(L, idx);
  504.   L->top--;
  505.   api_check(L, ttistable(L->top));
  506.   if (isLfunction(o)) {
  507.     res = 1;
  508.     clvalue(o)->l.g = *(L->top);
  509.   }
  510.   lua_unlock(L);
  511.   return res;
  512. }
  513. /*
  514. ** `load' and `call' functions (run Lua code)
  515. */
  516. LUA_API void lua_call (lua_State *L, int nargs, int nresults) {
  517.   StkId func;
  518.   lua_lock(L);
  519.   api_checknelems(L, nargs+1);
  520.   func = L->top - (nargs+1);
  521.   luaD_call(L, func, nresults);
  522.   lua_unlock(L);
  523. }
  524. /*
  525. ** Execute a protected call.
  526. */
  527. struct CallS {  /* data to `f_call' */
  528.   StkId func;
  529.   int nresults;
  530. };
  531. static void f_call (lua_State *L, void *ud) {
  532.   struct CallS *c = cast(struct CallS *, ud);
  533.   luaD_call(L, c->func, c->nresults);
  534. }
  535. LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {
  536.   struct CallS c;
  537.   int status;
  538.   ptrdiff_t func;
  539.   lua_lock(L);
  540.   func = (errfunc == 0) ? 0 : savestack(L, luaA_index(L, errfunc));
  541.   c.func = L->top - (nargs+1);  /* function to be called */
  542.   c.nresults = nresults;
  543.   status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
  544.   lua_unlock(L);
  545.   return status;
  546. }
  547. /*
  548. ** Execute a protected C call.
  549. */
  550. struct CCallS {  /* data to `f_Ccall' */
  551.   lua_CFunction func;
  552.   void *ud;
  553. };
  554. static void f_Ccall (lua_State *L, void *ud) {
  555.   struct CCallS *c = cast(struct CCallS *, ud);
  556.   Closure *cl;
  557.   cl = luaF_newCclosure(L, 0);
  558.   cl->c.f = c->func;
  559.   setclvalue(L->top, cl);  /* push function */
  560.   incr_top(L);
  561.   setpvalue(L->top, c->ud);  /* push only argument */
  562.   incr_top(L);
  563.   luaD_call(L, L->top - 2, 0);
  564. }
  565. LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {
  566.   struct CCallS c;
  567.   int status;
  568.   lua_lock(L);
  569.   c.func = func;
  570.   c.ud = ud;
  571.   status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);
  572.   lua_unlock(L);
  573.   return status;
  574. }
  575. LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data,
  576.                       const char *chunkname) {
  577.   ZIO z;
  578.   int status;
  579.   int c;
  580.   lua_lock(L);
  581.   if (!chunkname) chunkname = "?";
  582.   luaZ_init(&z, reader, data, chunkname);
  583.   c = luaZ_lookahead(&z);
  584.   status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0]));
  585.   lua_unlock(L);
  586.   return status;
  587. }
  588. LUA_API int lua_dump (lua_State *L, lua_Chunkwriter writer, void *data) {
  589.   int status;
  590.   TObject *o;
  591.   lua_lock(L);
  592.   api_checknelems(L, 1);
  593.   o = L->top - 1;
  594.   if (isLfunction(o) && clvalue(o)->l.nupvalues == 0) {
  595.     luaU_dump(L, clvalue(o)->l.p, writer, data);
  596.     status = 1;
  597.   }
  598.   else
  599.     status = 0;
  600.   lua_unlock(L);
  601.   return status;
  602. }
  603. /*
  604. ** Garbage-collection functions
  605. */
  606. /* GC values are expressed in Kbytes: #bytes/2^10 */
  607. #define GCscalel(x) ((x)>>10)
  608. #define GCscale(x) (cast(int, GCscalel(x)))
  609. #define GCunscale(x) (cast(lu_mem, x)<<10)
  610. LUA_API int lua_getgcthreshold (lua_State *L) {
  611.   int threshold;
  612.   lua_lock(L);
  613.   threshold = GCscale(G(L)->GCthreshold);
  614.   lua_unlock(L);
  615.   return threshold;
  616. }
  617. LUA_API int lua_getgccount (lua_State *L) {
  618.   int count;
  619.   lua_lock(L);
  620.   count = GCscale(G(L)->nblocks);
  621.   lua_unlock(L);
  622.   return count;
  623. }
  624. LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) {
  625.   lua_lock(L);
  626.   if (cast(lu_mem, newthreshold) > GCscalel(MAX_LUMEM))
  627.     G(L)->GCthreshold = MAX_LUMEM;
  628.   else
  629.     G(L)->GCthreshold = GCunscale(newthreshold);
  630.   luaC_checkGC(L);
  631.   lua_unlock(L);
  632. }
  633. /*
  634. ** miscellaneous functions
  635. */
  636. LUA_API const char *lua_version (void) {
  637.   return LUA_VERSION;
  638. }
  639. LUA_API int lua_error (lua_State *L) {
  640.   lua_lock(L);
  641.   api_checknelems(L, 1);
  642.   luaG_errormsg(L);
  643.   lua_unlock(L);
  644.   return 0;  /* to avoid warnings */
  645. }
  646. LUA_API int lua_next (lua_State *L, int idx) {
  647.   StkId t;
  648.   int more;
  649.   lua_lock(L);
  650.   t = luaA_index(L, idx);
  651.   api_check(L, ttistable(t));
  652.   more = luaH_next(L, hvalue(t), L->top - 1);
  653.   if (more) {
  654.     api_incr_top(L);
  655.   }
  656.   else  /* no more elements */
  657.     L->top -= 1;  /* remove key */
  658.   lua_unlock(L);
  659.   return more;
  660. }
  661. LUA_API void lua_concat (lua_State *L, int n) {
  662.   lua_lock(L);
  663.   luaC_checkGC(L);
  664.   api_checknelems(L, n);
  665.   if (n >= 2) {
  666.     luaV_concat(L, n, L->top - L->base - 1);
  667.     L->top -= (n-1);
  668.   }
  669.   else if (n == 0) {  /* push empty string */
  670.     setsvalue2s(L->top, luaS_newlstr(L, NULL, 0));
  671.     api_incr_top(L);
  672.   }
  673.   /* else n == 1; nothing to do */
  674.   lua_unlock(L);
  675. }
  676. LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
  677.   Udata *u;
  678.   lua_lock(L);
  679.   luaC_checkGC(L);
  680.   u = luaS_newudata(L, size);
  681.   setuvalue(L->top, u);
  682.   api_incr_top(L);
  683.   lua_unlock(L);
  684.   return u + 1;
  685. }
  686. LUA_API int lua_pushupvalues (lua_State *L) {
  687.   Closure *func;
  688.   int n, i;
  689.   lua_lock(L);
  690.   api_check(L, iscfunction(L->base - 1));
  691.   func = clvalue(L->base - 1);
  692.   n = func->c.nupvalues;
  693.   luaD_checkstack(L, n + LUA_MINSTACK);
  694.   for (i=0; i<n; i++) {
  695.     setobj2s(L->top, &func->c.upvalue[i]);
  696.     L->top++;
  697.   }
  698.   lua_unlock(L);
  699.   return n;
  700. }
  701. static const char *aux_upvalue (lua_State *L, int funcindex, int n,
  702.                                 TObject **val) {
  703.   Closure *f;
  704.   StkId fi = luaA_index(L, funcindex);
  705.   if (!ttisfunction(fi)) return NULL;
  706.   f = clvalue(fi);
  707.   if (f->c.isC) {
  708.     if (n > f->c.nupvalues) return NULL;
  709.     *val = &f->c.upvalue[n-1];
  710.     return "";
  711.   }
  712.   else {
  713.     Proto *p = f->l.p;
  714.     if (n > p->sizeupvalues) return NULL;
  715.     *val = f->l.upvals[n-1]->v;
  716.     return getstr(p->upvalues[n-1]);
  717.   }
  718. }
  719. LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
  720.   const char *name;
  721.   TObject *val;
  722.   lua_lock(L);
  723.   name = aux_upvalue(L, funcindex, n, &val);
  724.   if (name) {
  725.     setobj2s(L->top, val);
  726.     api_incr_top(L);
  727.   }
  728.   lua_unlock(L);
  729.   return name;
  730. }
  731. LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
  732.   const char *name;
  733.   TObject *val;
  734.   lua_lock(L);
  735.   api_checknelems(L, 1);
  736.   name = aux_upvalue(L, funcindex, n, &val);
  737.   if (name) {
  738.     L->top--;
  739.     setobj(val, L->top);  /* write barrier */
  740.   }
  741.   lua_unlock(L);
  742.   return name;
  743. }