1280405Srpaulo/*
2344220Skevans** $Id: lapi.c,v 2.259.1.2 2017/12/06 18:35:12 roberto Exp $
3280405Srpaulo** Lua API
4280405Srpaulo** See Copyright Notice in lua.h
5280405Srpaulo*/
6280405Srpaulo
7280405Srpaulo#define lapi_c
8280405Srpaulo#define LUA_CORE
9280405Srpaulo
10280405Srpaulo#include "lprefix.h"
11280405Srpaulo
12280405Srpaulo
13280405Srpaulo#include <stdarg.h>
14280405Srpaulo#include <string.h>
15280405Srpaulo
16280405Srpaulo#include "lua.h"
17280405Srpaulo
18280405Srpaulo#include "lapi.h"
19280405Srpaulo#include "ldebug.h"
20280405Srpaulo#include "ldo.h"
21280405Srpaulo#include "lfunc.h"
22280405Srpaulo#include "lgc.h"
23280405Srpaulo#include "lmem.h"
24280405Srpaulo#include "lobject.h"
25280405Srpaulo#include "lstate.h"
26280405Srpaulo#include "lstring.h"
27280405Srpaulo#include "ltable.h"
28280405Srpaulo#include "ltm.h"
29280405Srpaulo#include "lundump.h"
30280405Srpaulo#include "lvm.h"
31280405Srpaulo
32280405Srpaulo
33280405Srpaulo
34280405Srpauloconst char lua_ident[] =
35280405Srpaulo  "$LuaVersion: " LUA_COPYRIGHT " $"
36280405Srpaulo  "$LuaAuthors: " LUA_AUTHORS " $";
37280405Srpaulo
38280405Srpaulo
39280405Srpaulo/* value at a non-valid index */
40280405Srpaulo#define NONVALIDVALUE		cast(TValue *, luaO_nilobject)
41280405Srpaulo
42280405Srpaulo/* corresponding test */
43280405Srpaulo#define isvalid(o)	((o) != luaO_nilobject)
44280405Srpaulo
45280405Srpaulo/* test for pseudo index */
46280405Srpaulo#define ispseudo(i)		((i) <= LUA_REGISTRYINDEX)
47280405Srpaulo
48280405Srpaulo/* test for upvalue */
49280405Srpaulo#define isupvalue(i)		((i) < LUA_REGISTRYINDEX)
50280405Srpaulo
51280405Srpaulo/* test for valid but not pseudo index */
52280405Srpaulo#define isstackindex(i, o)	(isvalid(o) && !ispseudo(i))
53280405Srpaulo
54326344Simp#define api_checkvalidindex(l,o)  api_check(l, isvalid(o), "invalid index")
55280405Srpaulo
56326344Simp#define api_checkstackindex(l, i, o)  \
57326344Simp	api_check(l, isstackindex(i, o), "index not in the stack")
58280405Srpaulo
59280405Srpaulo
60280405Srpaulostatic TValue *index2addr (lua_State *L, int idx) {
61280405Srpaulo  CallInfo *ci = L->ci;
62280405Srpaulo  if (idx > 0) {
63280405Srpaulo    TValue *o = ci->func + idx;
64326344Simp    api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index");
65280405Srpaulo    if (o >= L->top) return NONVALIDVALUE;
66280405Srpaulo    else return o;
67280405Srpaulo  }
68280405Srpaulo  else if (!ispseudo(idx)) {  /* negative index */
69326344Simp    api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index");
70280405Srpaulo    return L->top + idx;
71280405Srpaulo  }
72280405Srpaulo  else if (idx == LUA_REGISTRYINDEX)
73280405Srpaulo    return &G(L)->l_registry;
74280405Srpaulo  else {  /* upvalues */
75280405Srpaulo    idx = LUA_REGISTRYINDEX - idx;
76326344Simp    api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
77280405Srpaulo    if (ttislcf(ci->func))  /* light C function? */
78280405Srpaulo      return NONVALIDVALUE;  /* it has no upvalues */
79280405Srpaulo    else {
80280405Srpaulo      CClosure *func = clCvalue(ci->func);
81280405Srpaulo      return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE;
82280405Srpaulo    }
83280405Srpaulo  }
84280405Srpaulo}
85280405Srpaulo
86280405Srpaulo
87280405Srpaulo/*
88280405Srpaulo** to be called by 'lua_checkstack' in protected mode, to grow stack
89280405Srpaulo** capturing memory errors
90280405Srpaulo*/
91280405Srpaulostatic void growstack (lua_State *L, void *ud) {
92280405Srpaulo  int size = *(int *)ud;
93280405Srpaulo  luaD_growstack(L, size);
94280405Srpaulo}
95280405Srpaulo
96280405Srpaulo
97280405SrpauloLUA_API int lua_checkstack (lua_State *L, int n) {
98280405Srpaulo  int res;
99280405Srpaulo  CallInfo *ci = L->ci;
100280405Srpaulo  lua_lock(L);
101326344Simp  api_check(L, n >= 0, "negative 'n'");
102280405Srpaulo  if (L->stack_last - L->top > n)  /* stack large enough? */
103280405Srpaulo    res = 1;  /* yes; check is OK */
104280405Srpaulo  else {  /* no; need to grow stack */
105280405Srpaulo    int inuse = cast_int(L->top - L->stack) + EXTRA_STACK;
106280405Srpaulo    if (inuse > LUAI_MAXSTACK - n)  /* can grow without overflow? */
107280405Srpaulo      res = 0;  /* no */
108280405Srpaulo    else  /* try to grow stack */
109280405Srpaulo      res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK);
110280405Srpaulo  }
111280405Srpaulo  if (res && ci->top < L->top + n)
112280405Srpaulo    ci->top = L->top + n;  /* adjust frame top */
113280405Srpaulo  lua_unlock(L);
114280405Srpaulo  return res;
115280405Srpaulo}
116280405Srpaulo
117280405Srpaulo
118280405SrpauloLUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
119280405Srpaulo  int i;
120280405Srpaulo  if (from == to) return;
121280405Srpaulo  lua_lock(to);
122280405Srpaulo  api_checknelems(from, n);
123326344Simp  api_check(from, G(from) == G(to), "moving among independent states");
124326344Simp  api_check(from, to->ci->top - to->top >= n, "stack overflow");
125280405Srpaulo  from->top -= n;
126280405Srpaulo  for (i = 0; i < n; i++) {
127326344Simp    setobj2s(to, to->top, from->top + i);
128326344Simp    to->top++;  /* stack already checked by previous 'api_check' */
129280405Srpaulo  }
130280405Srpaulo  lua_unlock(to);
131280405Srpaulo}
132280405Srpaulo
133280405Srpaulo
134280405SrpauloLUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
135280405Srpaulo  lua_CFunction old;
136280405Srpaulo  lua_lock(L);
137280405Srpaulo  old = G(L)->panic;
138280405Srpaulo  G(L)->panic = panicf;
139280405Srpaulo  lua_unlock(L);
140280405Srpaulo  return old;
141280405Srpaulo}
142280405Srpaulo
143280405Srpaulo
144280405SrpauloLUA_API const lua_Number *lua_version (lua_State *L) {
145280405Srpaulo  static const lua_Number version = LUA_VERSION_NUM;
146280405Srpaulo  if (L == NULL) return &version;
147280405Srpaulo  else return G(L)->version;
148280405Srpaulo}
149280405Srpaulo
150280405Srpaulo
151280405Srpaulo
152280405Srpaulo/*
153280405Srpaulo** basic stack manipulation
154280405Srpaulo*/
155280405Srpaulo
156280405Srpaulo
157280405Srpaulo/*
158280405Srpaulo** convert an acceptable stack index into an absolute index
159280405Srpaulo*/
160280405SrpauloLUA_API int lua_absindex (lua_State *L, int idx) {
161280405Srpaulo  return (idx > 0 || ispseudo(idx))
162280405Srpaulo         ? idx
163326344Simp         : cast_int(L->top - L->ci->func) + idx;
164280405Srpaulo}
165280405Srpaulo
166280405Srpaulo
167280405SrpauloLUA_API int lua_gettop (lua_State *L) {
168280405Srpaulo  return cast_int(L->top - (L->ci->func + 1));
169280405Srpaulo}
170280405Srpaulo
171280405Srpaulo
172280405SrpauloLUA_API void lua_settop (lua_State *L, int idx) {
173280405Srpaulo  StkId func = L->ci->func;
174280405Srpaulo  lua_lock(L);
175280405Srpaulo  if (idx >= 0) {
176326344Simp    api_check(L, idx <= L->stack_last - (func + 1), "new top too large");
177280405Srpaulo    while (L->top < (func + 1) + idx)
178280405Srpaulo      setnilvalue(L->top++);
179280405Srpaulo    L->top = (func + 1) + idx;
180280405Srpaulo  }
181280405Srpaulo  else {
182326344Simp    api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top");
183280405Srpaulo    L->top += idx+1;  /* 'subtract' index (index is negative) */
184280405Srpaulo  }
185280405Srpaulo  lua_unlock(L);
186280405Srpaulo}
187280405Srpaulo
188280405Srpaulo
189280405Srpaulo/*
190280405Srpaulo** Reverse the stack segment from 'from' to 'to'
191280405Srpaulo** (auxiliary to 'lua_rotate')
192280405Srpaulo*/
193280405Srpaulostatic void reverse (lua_State *L, StkId from, StkId to) {
194280405Srpaulo  for (; from < to; from++, to--) {
195280405Srpaulo    TValue temp;
196280405Srpaulo    setobj(L, &temp, from);
197280405Srpaulo    setobjs2s(L, from, to);
198280405Srpaulo    setobj2s(L, to, &temp);
199280405Srpaulo  }
200280405Srpaulo}
201280405Srpaulo
202280405Srpaulo
203280405Srpaulo/*
204280405Srpaulo** Let x = AB, where A is a prefix of length 'n'. Then,
205280405Srpaulo** rotate x n == BA. But BA == (A^r . B^r)^r.
206280405Srpaulo*/
207280405SrpauloLUA_API void lua_rotate (lua_State *L, int idx, int n) {
208280405Srpaulo  StkId p, t, m;
209280405Srpaulo  lua_lock(L);
210280405Srpaulo  t = L->top - 1;  /* end of stack segment being rotated */
211280405Srpaulo  p = index2addr(L, idx);  /* start of segment */
212326344Simp  api_checkstackindex(L, idx, p);
213326344Simp  api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
214280405Srpaulo  m = (n >= 0 ? t - n : p - n - 1);  /* end of prefix */
215280405Srpaulo  reverse(L, p, m);  /* reverse the prefix with length 'n' */
216280405Srpaulo  reverse(L, m + 1, t);  /* reverse the suffix */
217280405Srpaulo  reverse(L, p, t);  /* reverse the entire segment */
218280405Srpaulo  lua_unlock(L);
219280405Srpaulo}
220280405Srpaulo
221280405Srpaulo
222280405SrpauloLUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
223280405Srpaulo  TValue *fr, *to;
224280405Srpaulo  lua_lock(L);
225280405Srpaulo  fr = index2addr(L, fromidx);
226280405Srpaulo  to = index2addr(L, toidx);
227326344Simp  api_checkvalidindex(L, to);
228280405Srpaulo  setobj(L, to, fr);
229280405Srpaulo  if (isupvalue(toidx))  /* function upvalue? */
230280405Srpaulo    luaC_barrier(L, clCvalue(L->ci->func), fr);
231280405Srpaulo  /* LUA_REGISTRYINDEX does not need gc barrier
232280405Srpaulo     (collector revisits it before finishing collection) */
233280405Srpaulo  lua_unlock(L);
234280405Srpaulo}
235280405Srpaulo
236280405Srpaulo
237280405SrpauloLUA_API void lua_pushvalue (lua_State *L, int idx) {
238280405Srpaulo  lua_lock(L);
239280405Srpaulo  setobj2s(L, L->top, index2addr(L, idx));
240280405Srpaulo  api_incr_top(L);
241280405Srpaulo  lua_unlock(L);
242280405Srpaulo}
243280405Srpaulo
244280405Srpaulo
245280405Srpaulo
246280405Srpaulo/*
247280405Srpaulo** access functions (stack -> C)
248280405Srpaulo*/
249280405Srpaulo
250280405Srpaulo
251280405SrpauloLUA_API int lua_type (lua_State *L, int idx) {
252280405Srpaulo  StkId o = index2addr(L, idx);
253280405Srpaulo  return (isvalid(o) ? ttnov(o) : LUA_TNONE);
254280405Srpaulo}
255280405Srpaulo
256280405Srpaulo
257280405SrpauloLUA_API const char *lua_typename (lua_State *L, int t) {
258280405Srpaulo  UNUSED(L);
259326344Simp  api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag");
260280405Srpaulo  return ttypename(t);
261280405Srpaulo}
262280405Srpaulo
263280405Srpaulo
264280405SrpauloLUA_API int lua_iscfunction (lua_State *L, int idx) {
265280405Srpaulo  StkId o = index2addr(L, idx);
266280405Srpaulo  return (ttislcf(o) || (ttisCclosure(o)));
267280405Srpaulo}
268280405Srpaulo
269280405Srpaulo
270280405SrpauloLUA_API int lua_isinteger (lua_State *L, int idx) {
271280405Srpaulo  StkId o = index2addr(L, idx);
272280405Srpaulo  return ttisinteger(o);
273280405Srpaulo}
274280405Srpaulo
275280405Srpaulo
276280405SrpauloLUA_API int lua_isnumber (lua_State *L, int idx) {
277280405Srpaulo  lua_Number n;
278280405Srpaulo  const TValue *o = index2addr(L, idx);
279280405Srpaulo  return tonumber(o, &n);
280280405Srpaulo}
281280405Srpaulo
282280405Srpaulo
283280405SrpauloLUA_API int lua_isstring (lua_State *L, int idx) {
284280405Srpaulo  const TValue *o = index2addr(L, idx);
285280405Srpaulo  return (ttisstring(o) || cvt2str(o));
286280405Srpaulo}
287280405Srpaulo
288280405Srpaulo
289280405SrpauloLUA_API int lua_isuserdata (lua_State *L, int idx) {
290280405Srpaulo  const TValue *o = index2addr(L, idx);
291280405Srpaulo  return (ttisfulluserdata(o) || ttislightuserdata(o));
292280405Srpaulo}
293280405Srpaulo
294280405Srpaulo
295280405SrpauloLUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
296280405Srpaulo  StkId o1 = index2addr(L, index1);
297280405Srpaulo  StkId o2 = index2addr(L, index2);
298280405Srpaulo  return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0;
299280405Srpaulo}
300280405Srpaulo
301280405Srpaulo
302280405SrpauloLUA_API void lua_arith (lua_State *L, int op) {
303280405Srpaulo  lua_lock(L);
304280405Srpaulo  if (op != LUA_OPUNM && op != LUA_OPBNOT)
305280405Srpaulo    api_checknelems(L, 2);  /* all other operations expect two operands */
306280405Srpaulo  else {  /* for unary operations, add fake 2nd operand */
307280405Srpaulo    api_checknelems(L, 1);
308280405Srpaulo    setobjs2s(L, L->top, L->top - 1);
309326344Simp    api_incr_top(L);
310280405Srpaulo  }
311280405Srpaulo  /* first operand at top - 2, second at top - 1; result go to top - 2 */
312280405Srpaulo  luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
313280405Srpaulo  L->top--;  /* remove second operand */
314280405Srpaulo  lua_unlock(L);
315280405Srpaulo}
316280405Srpaulo
317280405Srpaulo
318280405SrpauloLUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
319280405Srpaulo  StkId o1, o2;
320280405Srpaulo  int i = 0;
321280405Srpaulo  lua_lock(L);  /* may call tag method */
322280405Srpaulo  o1 = index2addr(L, index1);
323280405Srpaulo  o2 = index2addr(L, index2);
324280405Srpaulo  if (isvalid(o1) && isvalid(o2)) {
325280405Srpaulo    switch (op) {
326280405Srpaulo      case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
327280405Srpaulo      case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
328280405Srpaulo      case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
329326344Simp      default: api_check(L, 0, "invalid option");
330280405Srpaulo    }
331280405Srpaulo  }
332280405Srpaulo  lua_unlock(L);
333280405Srpaulo  return i;
334280405Srpaulo}
335280405Srpaulo
336280405Srpaulo
337280405SrpauloLUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {
338280405Srpaulo  size_t sz = luaO_str2num(s, L->top);
339280405Srpaulo  if (sz != 0)
340280405Srpaulo    api_incr_top(L);
341280405Srpaulo  return sz;
342280405Srpaulo}
343280405Srpaulo
344280405Srpaulo
345280405SrpauloLUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {
346280405Srpaulo  lua_Number n;
347280405Srpaulo  const TValue *o = index2addr(L, idx);
348280405Srpaulo  int isnum = tonumber(o, &n);
349280405Srpaulo  if (!isnum)
350280405Srpaulo    n = 0;  /* call to 'tonumber' may change 'n' even if it fails */
351280405Srpaulo  if (pisnum) *pisnum = isnum;
352280405Srpaulo  return n;
353280405Srpaulo}
354280405Srpaulo
355280405Srpaulo
356280405SrpauloLUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {
357280405Srpaulo  lua_Integer res;
358280405Srpaulo  const TValue *o = index2addr(L, idx);
359280405Srpaulo  int isnum = tointeger(o, &res);
360280405Srpaulo  if (!isnum)
361280405Srpaulo    res = 0;  /* call to 'tointeger' may change 'n' even if it fails */
362280405Srpaulo  if (pisnum) *pisnum = isnum;
363280405Srpaulo  return res;
364280405Srpaulo}
365280405Srpaulo
366280405Srpaulo
367280405SrpauloLUA_API int lua_toboolean (lua_State *L, int idx) {
368280405Srpaulo  const TValue *o = index2addr(L, idx);
369280405Srpaulo  return !l_isfalse(o);
370280405Srpaulo}
371280405Srpaulo
372280405Srpaulo
373280405SrpauloLUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
374280405Srpaulo  StkId o = index2addr(L, idx);
375280405Srpaulo  if (!ttisstring(o)) {
376280405Srpaulo    if (!cvt2str(o)) {  /* not convertible? */
377280405Srpaulo      if (len != NULL) *len = 0;
378280405Srpaulo      return NULL;
379280405Srpaulo    }
380280405Srpaulo    lua_lock(L);  /* 'luaO_tostring' may create a new string */
381326344Simp    luaO_tostring(L, o);
382280405Srpaulo    luaC_checkGC(L);
383280405Srpaulo    o = index2addr(L, idx);  /* previous call may reallocate the stack */
384280405Srpaulo    lua_unlock(L);
385280405Srpaulo  }
386326344Simp  if (len != NULL)
387326344Simp    *len = vslen(o);
388280405Srpaulo  return svalue(o);
389280405Srpaulo}
390280405Srpaulo
391280405Srpaulo
392280405SrpauloLUA_API size_t lua_rawlen (lua_State *L, int idx) {
393280405Srpaulo  StkId o = index2addr(L, idx);
394326344Simp  switch (ttype(o)) {
395326344Simp    case LUA_TSHRSTR: return tsvalue(o)->shrlen;
396326344Simp    case LUA_TLNGSTR: return tsvalue(o)->u.lnglen;
397280405Srpaulo    case LUA_TUSERDATA: return uvalue(o)->len;
398280405Srpaulo    case LUA_TTABLE: return luaH_getn(hvalue(o));
399280405Srpaulo    default: return 0;
400280405Srpaulo  }
401280405Srpaulo}
402280405Srpaulo
403280405Srpaulo
404280405SrpauloLUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
405280405Srpaulo  StkId o = index2addr(L, idx);
406280405Srpaulo  if (ttislcf(o)) return fvalue(o);
407280405Srpaulo  else if (ttisCclosure(o))
408280405Srpaulo    return clCvalue(o)->f;
409280405Srpaulo  else return NULL;  /* not a C function */
410280405Srpaulo}
411280405Srpaulo
412280405Srpaulo
413280405SrpauloLUA_API void *lua_touserdata (lua_State *L, int idx) {
414280405Srpaulo  StkId o = index2addr(L, idx);
415280405Srpaulo  switch (ttnov(o)) {
416280405Srpaulo    case LUA_TUSERDATA: return getudatamem(uvalue(o));
417280405Srpaulo    case LUA_TLIGHTUSERDATA: return pvalue(o);
418280405Srpaulo    default: return NULL;
419280405Srpaulo  }
420280405Srpaulo}
421280405Srpaulo
422280405Srpaulo
423280405SrpauloLUA_API lua_State *lua_tothread (lua_State *L, int idx) {
424280405Srpaulo  StkId o = index2addr(L, idx);
425280405Srpaulo  return (!ttisthread(o)) ? NULL : thvalue(o);
426280405Srpaulo}
427280405Srpaulo
428280405Srpaulo
429280405SrpauloLUA_API const void *lua_topointer (lua_State *L, int idx) {
430280405Srpaulo  StkId o = index2addr(L, idx);
431280405Srpaulo  switch (ttype(o)) {
432280405Srpaulo    case LUA_TTABLE: return hvalue(o);
433280405Srpaulo    case LUA_TLCL: return clLvalue(o);
434280405Srpaulo    case LUA_TCCL: return clCvalue(o);
435280405Srpaulo    case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o)));
436280405Srpaulo    case LUA_TTHREAD: return thvalue(o);
437326344Simp    case LUA_TUSERDATA: return getudatamem(uvalue(o));
438326344Simp    case LUA_TLIGHTUSERDATA: return pvalue(o);
439280405Srpaulo    default: return NULL;
440280405Srpaulo  }
441280405Srpaulo}
442280405Srpaulo
443280405Srpaulo
444280405Srpaulo
445280405Srpaulo/*
446280405Srpaulo** push functions (C -> stack)
447280405Srpaulo*/
448280405Srpaulo
449280405Srpaulo
450280405SrpauloLUA_API void lua_pushnil (lua_State *L) {
451280405Srpaulo  lua_lock(L);
452280405Srpaulo  setnilvalue(L->top);
453280405Srpaulo  api_incr_top(L);
454280405Srpaulo  lua_unlock(L);
455280405Srpaulo}
456280405Srpaulo
457280405Srpaulo
458280405SrpauloLUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
459280405Srpaulo  lua_lock(L);
460280405Srpaulo  setfltvalue(L->top, n);
461280405Srpaulo  api_incr_top(L);
462280405Srpaulo  lua_unlock(L);
463280405Srpaulo}
464280405Srpaulo
465280405Srpaulo
466280405SrpauloLUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
467280405Srpaulo  lua_lock(L);
468280405Srpaulo  setivalue(L->top, n);
469280405Srpaulo  api_incr_top(L);
470280405Srpaulo  lua_unlock(L);
471280405Srpaulo}
472280405Srpaulo
473280405Srpaulo
474326344Simp/*
475326344Simp** Pushes on the stack a string with given length. Avoid using 's' when
476326344Simp** 'len' == 0 (as 's' can be NULL in that case), due to later use of
477326344Simp** 'memcmp' and 'memcpy'.
478326344Simp*/
479280405SrpauloLUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
480280405Srpaulo  TString *ts;
481280405Srpaulo  lua_lock(L);
482326344Simp  ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
483280405Srpaulo  setsvalue2s(L, L->top, ts);
484280405Srpaulo  api_incr_top(L);
485326344Simp  luaC_checkGC(L);
486280405Srpaulo  lua_unlock(L);
487280405Srpaulo  return getstr(ts);
488280405Srpaulo}
489280405Srpaulo
490280405Srpaulo
491280405SrpauloLUA_API const char *lua_pushstring (lua_State *L, const char *s) {
492326344Simp  lua_lock(L);
493326344Simp  if (s == NULL)
494326344Simp    setnilvalue(L->top);
495280405Srpaulo  else {
496280405Srpaulo    TString *ts;
497280405Srpaulo    ts = luaS_new(L, s);
498280405Srpaulo    setsvalue2s(L, L->top, ts);
499326344Simp    s = getstr(ts);  /* internal copy's address */
500280405Srpaulo  }
501326344Simp  api_incr_top(L);
502326344Simp  luaC_checkGC(L);
503326344Simp  lua_unlock(L);
504326344Simp  return s;
505280405Srpaulo}
506280405Srpaulo
507280405Srpaulo
508280405SrpauloLUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
509280405Srpaulo                                      va_list argp) {
510280405Srpaulo  const char *ret;
511280405Srpaulo  lua_lock(L);
512326344Simp  ret = luaO_pushvfstring(L, fmt, argp);
513280405Srpaulo  luaC_checkGC(L);
514280405Srpaulo  lua_unlock(L);
515280405Srpaulo  return ret;
516280405Srpaulo}
517280405Srpaulo
518280405Srpaulo
519280405SrpauloLUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
520280405Srpaulo  const char *ret;
521280405Srpaulo  va_list argp;
522280405Srpaulo  lua_lock(L);
523280405Srpaulo  va_start(argp, fmt);
524280405Srpaulo  ret = luaO_pushvfstring(L, fmt, argp);
525280405Srpaulo  va_end(argp);
526326344Simp  luaC_checkGC(L);
527280405Srpaulo  lua_unlock(L);
528280405Srpaulo  return ret;
529280405Srpaulo}
530280405Srpaulo
531280405Srpaulo
532280405SrpauloLUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
533280405Srpaulo  lua_lock(L);
534280405Srpaulo  if (n == 0) {
535280405Srpaulo    setfvalue(L->top, fn);
536344220Skevans    api_incr_top(L);
537280405Srpaulo  }
538280405Srpaulo  else {
539280405Srpaulo    CClosure *cl;
540280405Srpaulo    api_checknelems(L, n);
541326344Simp    api_check(L, n <= MAXUPVAL, "upvalue index too large");
542280405Srpaulo    cl = luaF_newCclosure(L, n);
543280405Srpaulo    cl->f = fn;
544280405Srpaulo    L->top -= n;
545280405Srpaulo    while (n--) {
546280405Srpaulo      setobj2n(L, &cl->upvalue[n], L->top + n);
547280405Srpaulo      /* does not need barrier because closure is white */
548280405Srpaulo    }
549280405Srpaulo    setclCvalue(L, L->top, cl);
550344220Skevans    api_incr_top(L);
551344220Skevans    luaC_checkGC(L);
552280405Srpaulo  }
553280405Srpaulo  lua_unlock(L);
554280405Srpaulo}
555280405Srpaulo
556280405Srpaulo
557280405SrpauloLUA_API void lua_pushboolean (lua_State *L, int b) {
558280405Srpaulo  lua_lock(L);
559280405Srpaulo  setbvalue(L->top, (b != 0));  /* ensure that true is 1 */
560280405Srpaulo  api_incr_top(L);
561280405Srpaulo  lua_unlock(L);
562280405Srpaulo}
563280405Srpaulo
564280405Srpaulo
565280405SrpauloLUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
566280405Srpaulo  lua_lock(L);
567280405Srpaulo  setpvalue(L->top, p);
568280405Srpaulo  api_incr_top(L);
569280405Srpaulo  lua_unlock(L);
570280405Srpaulo}
571280405Srpaulo
572280405Srpaulo
573280405SrpauloLUA_API int lua_pushthread (lua_State *L) {
574280405Srpaulo  lua_lock(L);
575280405Srpaulo  setthvalue(L, L->top, L);
576280405Srpaulo  api_incr_top(L);
577280405Srpaulo  lua_unlock(L);
578280405Srpaulo  return (G(L)->mainthread == L);
579280405Srpaulo}
580280405Srpaulo
581280405Srpaulo
582280405Srpaulo
583280405Srpaulo/*
584280405Srpaulo** get functions (Lua -> stack)
585280405Srpaulo*/
586280405Srpaulo
587280405Srpaulo
588326344Simpstatic int auxgetstr (lua_State *L, const TValue *t, const char *k) {
589326344Simp  const TValue *slot;
590326344Simp  TString *str = luaS_new(L, k);
591326344Simp  if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
592326344Simp    setobj2s(L, L->top, slot);
593326344Simp    api_incr_top(L);
594326344Simp  }
595326344Simp  else {
596326344Simp    setsvalue2s(L, L->top, str);
597326344Simp    api_incr_top(L);
598326344Simp    luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
599326344Simp  }
600326344Simp  lua_unlock(L);
601326344Simp  return ttnov(L->top - 1);
602326344Simp}
603326344Simp
604326344Simp
605280405SrpauloLUA_API int lua_getglobal (lua_State *L, const char *name) {
606280405Srpaulo  Table *reg = hvalue(&G(L)->l_registry);
607280405Srpaulo  lua_lock(L);
608326344Simp  return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
609280405Srpaulo}
610280405Srpaulo
611280405Srpaulo
612280405SrpauloLUA_API int lua_gettable (lua_State *L, int idx) {
613280405Srpaulo  StkId t;
614280405Srpaulo  lua_lock(L);
615280405Srpaulo  t = index2addr(L, idx);
616280405Srpaulo  luaV_gettable(L, t, L->top - 1, L->top - 1);
617280405Srpaulo  lua_unlock(L);
618280405Srpaulo  return ttnov(L->top - 1);
619280405Srpaulo}
620280405Srpaulo
621280405Srpaulo
622280405SrpauloLUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
623280405Srpaulo  lua_lock(L);
624326344Simp  return auxgetstr(L, index2addr(L, idx), k);
625280405Srpaulo}
626280405Srpaulo
627280405Srpaulo
628280405SrpauloLUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
629280405Srpaulo  StkId t;
630326344Simp  const TValue *slot;
631280405Srpaulo  lua_lock(L);
632280405Srpaulo  t = index2addr(L, idx);
633326344Simp  if (luaV_fastget(L, t, n, slot, luaH_getint)) {
634326344Simp    setobj2s(L, L->top, slot);
635326344Simp    api_incr_top(L);
636326344Simp  }
637326344Simp  else {
638326344Simp    setivalue(L->top, n);
639326344Simp    api_incr_top(L);
640326344Simp    luaV_finishget(L, t, L->top - 1, L->top - 1, slot);
641326344Simp  }
642280405Srpaulo  lua_unlock(L);
643280405Srpaulo  return ttnov(L->top - 1);
644280405Srpaulo}
645280405Srpaulo
646280405Srpaulo
647280405SrpauloLUA_API int lua_rawget (lua_State *L, int idx) {
648280405Srpaulo  StkId t;
649280405Srpaulo  lua_lock(L);
650280405Srpaulo  t = index2addr(L, idx);
651326344Simp  api_check(L, ttistable(t), "table expected");
652280405Srpaulo  setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
653280405Srpaulo  lua_unlock(L);
654280405Srpaulo  return ttnov(L->top - 1);
655280405Srpaulo}
656280405Srpaulo
657280405Srpaulo
658280405SrpauloLUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
659280405Srpaulo  StkId t;
660280405Srpaulo  lua_lock(L);
661280405Srpaulo  t = index2addr(L, idx);
662326344Simp  api_check(L, ttistable(t), "table expected");
663280405Srpaulo  setobj2s(L, L->top, luaH_getint(hvalue(t), n));
664280405Srpaulo  api_incr_top(L);
665280405Srpaulo  lua_unlock(L);
666280405Srpaulo  return ttnov(L->top - 1);
667280405Srpaulo}
668280405Srpaulo
669280405Srpaulo
670280405SrpauloLUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
671280405Srpaulo  StkId t;
672280405Srpaulo  TValue k;
673280405Srpaulo  lua_lock(L);
674280405Srpaulo  t = index2addr(L, idx);
675326344Simp  api_check(L, ttistable(t), "table expected");
676280405Srpaulo  setpvalue(&k, cast(void *, p));
677280405Srpaulo  setobj2s(L, L->top, luaH_get(hvalue(t), &k));
678280405Srpaulo  api_incr_top(L);
679280405Srpaulo  lua_unlock(L);
680280405Srpaulo  return ttnov(L->top - 1);
681280405Srpaulo}
682280405Srpaulo
683280405Srpaulo
684280405SrpauloLUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
685280405Srpaulo  Table *t;
686280405Srpaulo  lua_lock(L);
687280405Srpaulo  t = luaH_new(L);
688280405Srpaulo  sethvalue(L, L->top, t);
689280405Srpaulo  api_incr_top(L);
690280405Srpaulo  if (narray > 0 || nrec > 0)
691280405Srpaulo    luaH_resize(L, t, narray, nrec);
692326344Simp  luaC_checkGC(L);
693280405Srpaulo  lua_unlock(L);
694280405Srpaulo}
695280405Srpaulo
696280405Srpaulo
697280405SrpauloLUA_API int lua_getmetatable (lua_State *L, int objindex) {
698280405Srpaulo  const TValue *obj;
699280405Srpaulo  Table *mt;
700280405Srpaulo  int res = 0;
701280405Srpaulo  lua_lock(L);
702280405Srpaulo  obj = index2addr(L, objindex);
703280405Srpaulo  switch (ttnov(obj)) {
704280405Srpaulo    case LUA_TTABLE:
705280405Srpaulo      mt = hvalue(obj)->metatable;
706280405Srpaulo      break;
707280405Srpaulo    case LUA_TUSERDATA:
708280405Srpaulo      mt = uvalue(obj)->metatable;
709280405Srpaulo      break;
710280405Srpaulo    default:
711280405Srpaulo      mt = G(L)->mt[ttnov(obj)];
712280405Srpaulo      break;
713280405Srpaulo  }
714280405Srpaulo  if (mt != NULL) {
715280405Srpaulo    sethvalue(L, L->top, mt);
716280405Srpaulo    api_incr_top(L);
717280405Srpaulo    res = 1;
718280405Srpaulo  }
719280405Srpaulo  lua_unlock(L);
720280405Srpaulo  return res;
721280405Srpaulo}
722280405Srpaulo
723280405Srpaulo
724280405SrpauloLUA_API int lua_getuservalue (lua_State *L, int idx) {
725280405Srpaulo  StkId o;
726280405Srpaulo  lua_lock(L);
727280405Srpaulo  o = index2addr(L, idx);
728326344Simp  api_check(L, ttisfulluserdata(o), "full userdata expected");
729280405Srpaulo  getuservalue(L, uvalue(o), L->top);
730280405Srpaulo  api_incr_top(L);
731280405Srpaulo  lua_unlock(L);
732280405Srpaulo  return ttnov(L->top - 1);
733280405Srpaulo}
734280405Srpaulo
735280405Srpaulo
736280405Srpaulo/*
737280405Srpaulo** set functions (stack -> Lua)
738280405Srpaulo*/
739280405Srpaulo
740326344Simp/*
741326344Simp** t[k] = value at the top of the stack (where 'k' is a string)
742326344Simp*/
743326344Simpstatic void auxsetstr (lua_State *L, const TValue *t, const char *k) {
744326344Simp  const TValue *slot;
745326344Simp  TString *str = luaS_new(L, k);
746326344Simp  api_checknelems(L, 1);
747326344Simp  if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1))
748326344Simp    L->top--;  /* pop value */
749326344Simp  else {
750326344Simp    setsvalue2s(L, L->top, str);  /* push 'str' (to make it a TValue) */
751326344Simp    api_incr_top(L);
752326344Simp    luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
753326344Simp    L->top -= 2;  /* pop value and key */
754326344Simp  }
755326344Simp  lua_unlock(L);  /* lock done by caller */
756326344Simp}
757280405Srpaulo
758326344Simp
759280405SrpauloLUA_API void lua_setglobal (lua_State *L, const char *name) {
760280405Srpaulo  Table *reg = hvalue(&G(L)->l_registry);
761326344Simp  lua_lock(L);  /* unlock done in 'auxsetstr' */
762326344Simp  auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
763280405Srpaulo}
764280405Srpaulo
765280405Srpaulo
766280405SrpauloLUA_API void lua_settable (lua_State *L, int idx) {
767280405Srpaulo  StkId t;
768280405Srpaulo  lua_lock(L);
769280405Srpaulo  api_checknelems(L, 2);
770280405Srpaulo  t = index2addr(L, idx);
771280405Srpaulo  luaV_settable(L, t, L->top - 2, L->top - 1);
772280405Srpaulo  L->top -= 2;  /* pop index and value */
773280405Srpaulo  lua_unlock(L);
774280405Srpaulo}
775280405Srpaulo
776280405Srpaulo
777280405SrpauloLUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
778326344Simp  lua_lock(L);  /* unlock done in 'auxsetstr' */
779326344Simp  auxsetstr(L, index2addr(L, idx), k);
780280405Srpaulo}
781280405Srpaulo
782280405Srpaulo
783280405SrpauloLUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
784280405Srpaulo  StkId t;
785326344Simp  const TValue *slot;
786280405Srpaulo  lua_lock(L);
787280405Srpaulo  api_checknelems(L, 1);
788280405Srpaulo  t = index2addr(L, idx);
789326344Simp  if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1))
790326344Simp    L->top--;  /* pop value */
791326344Simp  else {
792326344Simp    setivalue(L->top, n);
793326344Simp    api_incr_top(L);
794326344Simp    luaV_finishset(L, t, L->top - 1, L->top - 2, slot);
795326344Simp    L->top -= 2;  /* pop value and key */
796326344Simp  }
797280405Srpaulo  lua_unlock(L);
798280405Srpaulo}
799280405Srpaulo
800280405Srpaulo
801280405SrpauloLUA_API void lua_rawset (lua_State *L, int idx) {
802280405Srpaulo  StkId o;
803326344Simp  TValue *slot;
804280405Srpaulo  lua_lock(L);
805280405Srpaulo  api_checknelems(L, 2);
806280405Srpaulo  o = index2addr(L, idx);
807326344Simp  api_check(L, ttistable(o), "table expected");
808326344Simp  slot = luaH_set(L, hvalue(o), L->top - 2);
809326344Simp  setobj2t(L, slot, L->top - 1);
810326344Simp  invalidateTMcache(hvalue(o));
811326344Simp  luaC_barrierback(L, hvalue(o), L->top-1);
812280405Srpaulo  L->top -= 2;
813280405Srpaulo  lua_unlock(L);
814280405Srpaulo}
815280405Srpaulo
816280405Srpaulo
817280405SrpauloLUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
818280405Srpaulo  StkId o;
819280405Srpaulo  lua_lock(L);
820280405Srpaulo  api_checknelems(L, 1);
821280405Srpaulo  o = index2addr(L, idx);
822326344Simp  api_check(L, ttistable(o), "table expected");
823326344Simp  luaH_setint(L, hvalue(o), n, L->top - 1);
824326344Simp  luaC_barrierback(L, hvalue(o), L->top-1);
825280405Srpaulo  L->top--;
826280405Srpaulo  lua_unlock(L);
827280405Srpaulo}
828280405Srpaulo
829280405Srpaulo
830280405SrpauloLUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
831280405Srpaulo  StkId o;
832326344Simp  TValue k, *slot;
833280405Srpaulo  lua_lock(L);
834280405Srpaulo  api_checknelems(L, 1);
835280405Srpaulo  o = index2addr(L, idx);
836326344Simp  api_check(L, ttistable(o), "table expected");
837280405Srpaulo  setpvalue(&k, cast(void *, p));
838326344Simp  slot = luaH_set(L, hvalue(o), &k);
839326344Simp  setobj2t(L, slot, L->top - 1);
840326344Simp  luaC_barrierback(L, hvalue(o), L->top - 1);
841280405Srpaulo  L->top--;
842280405Srpaulo  lua_unlock(L);
843280405Srpaulo}
844280405Srpaulo
845280405Srpaulo
846280405SrpauloLUA_API int lua_setmetatable (lua_State *L, int objindex) {
847280405Srpaulo  TValue *obj;
848280405Srpaulo  Table *mt;
849280405Srpaulo  lua_lock(L);
850280405Srpaulo  api_checknelems(L, 1);
851280405Srpaulo  obj = index2addr(L, objindex);
852280405Srpaulo  if (ttisnil(L->top - 1))
853280405Srpaulo    mt = NULL;
854280405Srpaulo  else {
855326344Simp    api_check(L, ttistable(L->top - 1), "table expected");
856280405Srpaulo    mt = hvalue(L->top - 1);
857280405Srpaulo  }
858280405Srpaulo  switch (ttnov(obj)) {
859280405Srpaulo    case LUA_TTABLE: {
860280405Srpaulo      hvalue(obj)->metatable = mt;
861280405Srpaulo      if (mt) {
862280405Srpaulo        luaC_objbarrier(L, gcvalue(obj), mt);
863280405Srpaulo        luaC_checkfinalizer(L, gcvalue(obj), mt);
864280405Srpaulo      }
865280405Srpaulo      break;
866280405Srpaulo    }
867280405Srpaulo    case LUA_TUSERDATA: {
868280405Srpaulo      uvalue(obj)->metatable = mt;
869280405Srpaulo      if (mt) {
870280405Srpaulo        luaC_objbarrier(L, uvalue(obj), mt);
871280405Srpaulo        luaC_checkfinalizer(L, gcvalue(obj), mt);
872280405Srpaulo      }
873280405Srpaulo      break;
874280405Srpaulo    }
875280405Srpaulo    default: {
876280405Srpaulo      G(L)->mt[ttnov(obj)] = mt;
877280405Srpaulo      break;
878280405Srpaulo    }
879280405Srpaulo  }
880280405Srpaulo  L->top--;
881280405Srpaulo  lua_unlock(L);
882280405Srpaulo  return 1;
883280405Srpaulo}
884280405Srpaulo
885280405Srpaulo
886280405SrpauloLUA_API void lua_setuservalue (lua_State *L, int idx) {
887280405Srpaulo  StkId o;
888280405Srpaulo  lua_lock(L);
889280405Srpaulo  api_checknelems(L, 1);
890280405Srpaulo  o = index2addr(L, idx);
891326344Simp  api_check(L, ttisfulluserdata(o), "full userdata expected");
892280405Srpaulo  setuservalue(L, uvalue(o), L->top - 1);
893280405Srpaulo  luaC_barrier(L, gcvalue(o), L->top - 1);
894280405Srpaulo  L->top--;
895280405Srpaulo  lua_unlock(L);
896280405Srpaulo}
897280405Srpaulo
898280405Srpaulo
899280405Srpaulo/*
900280405Srpaulo** 'load' and 'call' functions (run Lua code)
901280405Srpaulo*/
902280405Srpaulo
903280405Srpaulo
904280405Srpaulo#define checkresults(L,na,nr) \
905326344Simp     api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \
906280405Srpaulo	"results from function overflow current stack size")
907280405Srpaulo
908280405Srpaulo
909280405SrpauloLUA_API void lua_callk (lua_State *L, int nargs, int nresults,
910280405Srpaulo                        lua_KContext ctx, lua_KFunction k) {
911280405Srpaulo  StkId func;
912280405Srpaulo  lua_lock(L);
913326344Simp  api_check(L, k == NULL || !isLua(L->ci),
914280405Srpaulo    "cannot use continuations inside hooks");
915280405Srpaulo  api_checknelems(L, nargs+1);
916326344Simp  api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
917280405Srpaulo  checkresults(L, nargs, nresults);
918280405Srpaulo  func = L->top - (nargs+1);
919280405Srpaulo  if (k != NULL && L->nny == 0) {  /* need to prepare continuation? */
920280405Srpaulo    L->ci->u.c.k = k;  /* save continuation */
921280405Srpaulo    L->ci->u.c.ctx = ctx;  /* save context */
922326344Simp    luaD_call(L, func, nresults);  /* do the call */
923280405Srpaulo  }
924280405Srpaulo  else  /* no continuation or no yieldable */
925326344Simp    luaD_callnoyield(L, func, nresults);  /* just do the call */
926280405Srpaulo  adjustresults(L, nresults);
927280405Srpaulo  lua_unlock(L);
928280405Srpaulo}
929280405Srpaulo
930280405Srpaulo
931280405Srpaulo
932280405Srpaulo/*
933280405Srpaulo** Execute a protected call.
934280405Srpaulo*/
935280405Srpaulostruct CallS {  /* data to 'f_call' */
936280405Srpaulo  StkId func;
937280405Srpaulo  int nresults;
938280405Srpaulo};
939280405Srpaulo
940280405Srpaulo
941280405Srpaulostatic void f_call (lua_State *L, void *ud) {
942280405Srpaulo  struct CallS *c = cast(struct CallS *, ud);
943326344Simp  luaD_callnoyield(L, c->func, c->nresults);
944280405Srpaulo}
945280405Srpaulo
946280405Srpaulo
947280405Srpaulo
948280405SrpauloLUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
949280405Srpaulo                        lua_KContext ctx, lua_KFunction k) {
950280405Srpaulo  struct CallS c;
951280405Srpaulo  int status;
952280405Srpaulo  ptrdiff_t func;
953280405Srpaulo  lua_lock(L);
954326344Simp  api_check(L, k == NULL || !isLua(L->ci),
955280405Srpaulo    "cannot use continuations inside hooks");
956280405Srpaulo  api_checknelems(L, nargs+1);
957326344Simp  api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
958280405Srpaulo  checkresults(L, nargs, nresults);
959280405Srpaulo  if (errfunc == 0)
960280405Srpaulo    func = 0;
961280405Srpaulo  else {
962280405Srpaulo    StkId o = index2addr(L, errfunc);
963326344Simp    api_checkstackindex(L, errfunc, o);
964280405Srpaulo    func = savestack(L, o);
965280405Srpaulo  }
966280405Srpaulo  c.func = L->top - (nargs+1);  /* function to be called */
967280405Srpaulo  if (k == NULL || L->nny > 0) {  /* no continuation or no yieldable? */
968280405Srpaulo    c.nresults = nresults;  /* do a 'conventional' protected call */
969280405Srpaulo    status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
970280405Srpaulo  }
971280405Srpaulo  else {  /* prepare continuation (call is already protected by 'resume') */
972280405Srpaulo    CallInfo *ci = L->ci;
973280405Srpaulo    ci->u.c.k = k;  /* save continuation */
974280405Srpaulo    ci->u.c.ctx = ctx;  /* save context */
975280405Srpaulo    /* save information for error recovery */
976280405Srpaulo    ci->extra = savestack(L, c.func);
977280405Srpaulo    ci->u.c.old_errfunc = L->errfunc;
978280405Srpaulo    L->errfunc = func;
979280405Srpaulo    setoah(ci->callstatus, L->allowhook);  /* save value of 'allowhook' */
980280405Srpaulo    ci->callstatus |= CIST_YPCALL;  /* function can do error recovery */
981326344Simp    luaD_call(L, c.func, nresults);  /* do the call */
982280405Srpaulo    ci->callstatus &= ~CIST_YPCALL;
983280405Srpaulo    L->errfunc = ci->u.c.old_errfunc;
984280405Srpaulo    status = LUA_OK;  /* if it is here, there were no errors */
985280405Srpaulo  }
986280405Srpaulo  adjustresults(L, nresults);
987280405Srpaulo  lua_unlock(L);
988280405Srpaulo  return status;
989280405Srpaulo}
990280405Srpaulo
991280405Srpaulo
992280405SrpauloLUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
993280405Srpaulo                      const char *chunkname, const char *mode) {
994280405Srpaulo  ZIO z;
995280405Srpaulo  int status;
996280405Srpaulo  lua_lock(L);
997280405Srpaulo  if (!chunkname) chunkname = "?";
998280405Srpaulo  luaZ_init(L, &z, reader, data);
999280405Srpaulo  status = luaD_protectedparser(L, &z, chunkname, mode);
1000280405Srpaulo  if (status == LUA_OK) {  /* no errors? */
1001280405Srpaulo    LClosure *f = clLvalue(L->top - 1);  /* get newly created function */
1002280405Srpaulo    if (f->nupvalues >= 1) {  /* does it have an upvalue? */
1003280405Srpaulo      /* get global table from registry */
1004280405Srpaulo      Table *reg = hvalue(&G(L)->l_registry);
1005280405Srpaulo      const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
1006280405Srpaulo      /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
1007280405Srpaulo      setobj(L, f->upvals[0]->v, gt);
1008280405Srpaulo      luaC_upvalbarrier(L, f->upvals[0]);
1009280405Srpaulo    }
1010280405Srpaulo  }
1011280405Srpaulo  lua_unlock(L);
1012280405Srpaulo  return status;
1013280405Srpaulo}
1014280405Srpaulo
1015280405Srpaulo
1016280405SrpauloLUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
1017280405Srpaulo  int status;
1018280405Srpaulo  TValue *o;
1019280405Srpaulo  lua_lock(L);
1020280405Srpaulo  api_checknelems(L, 1);
1021280405Srpaulo  o = L->top - 1;
1022280405Srpaulo  if (isLfunction(o))
1023280405Srpaulo    status = luaU_dump(L, getproto(o), writer, data, strip);
1024280405Srpaulo  else
1025280405Srpaulo    status = 1;
1026280405Srpaulo  lua_unlock(L);
1027280405Srpaulo  return status;
1028280405Srpaulo}
1029280405Srpaulo
1030280405Srpaulo
1031280405SrpauloLUA_API int lua_status (lua_State *L) {
1032280405Srpaulo  return L->status;
1033280405Srpaulo}
1034280405Srpaulo
1035280405Srpaulo
1036280405Srpaulo/*
1037280405Srpaulo** Garbage-collection function
1038280405Srpaulo*/
1039280405Srpaulo
1040280405SrpauloLUA_API int lua_gc (lua_State *L, int what, int data) {
1041280405Srpaulo  int res = 0;
1042280405Srpaulo  global_State *g;
1043280405Srpaulo  lua_lock(L);
1044280405Srpaulo  g = G(L);
1045280405Srpaulo  switch (what) {
1046280405Srpaulo    case LUA_GCSTOP: {
1047280405Srpaulo      g->gcrunning = 0;
1048280405Srpaulo      break;
1049280405Srpaulo    }
1050280405Srpaulo    case LUA_GCRESTART: {
1051280405Srpaulo      luaE_setdebt(g, 0);
1052280405Srpaulo      g->gcrunning = 1;
1053280405Srpaulo      break;
1054280405Srpaulo    }
1055280405Srpaulo    case LUA_GCCOLLECT: {
1056280405Srpaulo      luaC_fullgc(L, 0);
1057280405Srpaulo      break;
1058280405Srpaulo    }
1059280405Srpaulo    case LUA_GCCOUNT: {
1060280405Srpaulo      /* GC values are expressed in Kbytes: #bytes/2^10 */
1061280405Srpaulo      res = cast_int(gettotalbytes(g) >> 10);
1062280405Srpaulo      break;
1063280405Srpaulo    }
1064280405Srpaulo    case LUA_GCCOUNTB: {
1065280405Srpaulo      res = cast_int(gettotalbytes(g) & 0x3ff);
1066280405Srpaulo      break;
1067280405Srpaulo    }
1068280405Srpaulo    case LUA_GCSTEP: {
1069280405Srpaulo      l_mem debt = 1;  /* =1 to signal that it did an actual step */
1070326344Simp      lu_byte oldrunning = g->gcrunning;
1071280405Srpaulo      g->gcrunning = 1;  /* allow GC to run */
1072280405Srpaulo      if (data == 0) {
1073280405Srpaulo        luaE_setdebt(g, -GCSTEPSIZE);  /* to do a "small" step */
1074280405Srpaulo        luaC_step(L);
1075280405Srpaulo      }
1076280405Srpaulo      else {  /* add 'data' to total debt */
1077280405Srpaulo        debt = cast(l_mem, data) * 1024 + g->GCdebt;
1078280405Srpaulo        luaE_setdebt(g, debt);
1079280405Srpaulo        luaC_checkGC(L);
1080280405Srpaulo      }
1081280405Srpaulo      g->gcrunning = oldrunning;  /* restore previous state */
1082280405Srpaulo      if (debt > 0 && g->gcstate == GCSpause)  /* end of cycle? */
1083280405Srpaulo        res = 1;  /* signal it */
1084280405Srpaulo      break;
1085280405Srpaulo    }
1086280405Srpaulo    case LUA_GCSETPAUSE: {
1087280405Srpaulo      res = g->gcpause;
1088280405Srpaulo      g->gcpause = data;
1089280405Srpaulo      break;
1090280405Srpaulo    }
1091280405Srpaulo    case LUA_GCSETSTEPMUL: {
1092280405Srpaulo      res = g->gcstepmul;
1093280405Srpaulo      if (data < 40) data = 40;  /* avoid ridiculous low values (and 0) */
1094280405Srpaulo      g->gcstepmul = data;
1095280405Srpaulo      break;
1096280405Srpaulo    }
1097280405Srpaulo    case LUA_GCISRUNNING: {
1098280405Srpaulo      res = g->gcrunning;
1099280405Srpaulo      break;
1100280405Srpaulo    }
1101280405Srpaulo    default: res = -1;  /* invalid option */
1102280405Srpaulo  }
1103280405Srpaulo  lua_unlock(L);
1104280405Srpaulo  return res;
1105280405Srpaulo}
1106280405Srpaulo
1107280405Srpaulo
1108280405Srpaulo
1109280405Srpaulo/*
1110280405Srpaulo** miscellaneous functions
1111280405Srpaulo*/
1112280405Srpaulo
1113280405Srpaulo
1114280405SrpauloLUA_API int lua_error (lua_State *L) {
1115280405Srpaulo  lua_lock(L);
1116280405Srpaulo  api_checknelems(L, 1);
1117280405Srpaulo  luaG_errormsg(L);
1118280405Srpaulo  /* code unreachable; will unlock when control actually leaves the kernel */
1119280405Srpaulo  return 0;  /* to avoid warnings */
1120280405Srpaulo}
1121280405Srpaulo
1122280405Srpaulo
1123280405SrpauloLUA_API int lua_next (lua_State *L, int idx) {
1124280405Srpaulo  StkId t;
1125280405Srpaulo  int more;
1126280405Srpaulo  lua_lock(L);
1127280405Srpaulo  t = index2addr(L, idx);
1128326344Simp  api_check(L, ttistable(t), "table expected");
1129280405Srpaulo  more = luaH_next(L, hvalue(t), L->top - 1);
1130280405Srpaulo  if (more) {
1131280405Srpaulo    api_incr_top(L);
1132280405Srpaulo  }
1133280405Srpaulo  else  /* no more elements */
1134280405Srpaulo    L->top -= 1;  /* remove key */
1135280405Srpaulo  lua_unlock(L);
1136280405Srpaulo  return more;
1137280405Srpaulo}
1138280405Srpaulo
1139280405Srpaulo
1140280405SrpauloLUA_API void lua_concat (lua_State *L, int n) {
1141280405Srpaulo  lua_lock(L);
1142280405Srpaulo  api_checknelems(L, n);
1143280405Srpaulo  if (n >= 2) {
1144280405Srpaulo    luaV_concat(L, n);
1145280405Srpaulo  }
1146280405Srpaulo  else if (n == 0) {  /* push empty string */
1147280405Srpaulo    setsvalue2s(L, L->top, luaS_newlstr(L, "", 0));
1148280405Srpaulo    api_incr_top(L);
1149280405Srpaulo  }
1150280405Srpaulo  /* else n == 1; nothing to do */
1151326344Simp  luaC_checkGC(L);
1152280405Srpaulo  lua_unlock(L);
1153280405Srpaulo}
1154280405Srpaulo
1155280405Srpaulo
1156280405SrpauloLUA_API void lua_len (lua_State *L, int idx) {
1157280405Srpaulo  StkId t;
1158280405Srpaulo  lua_lock(L);
1159280405Srpaulo  t = index2addr(L, idx);
1160280405Srpaulo  luaV_objlen(L, L->top, t);
1161280405Srpaulo  api_incr_top(L);
1162280405Srpaulo  lua_unlock(L);
1163280405Srpaulo}
1164280405Srpaulo
1165280405Srpaulo
1166280405SrpauloLUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
1167280405Srpaulo  lua_Alloc f;
1168280405Srpaulo  lua_lock(L);
1169280405Srpaulo  if (ud) *ud = G(L)->ud;
1170280405Srpaulo  f = G(L)->frealloc;
1171280405Srpaulo  lua_unlock(L);
1172280405Srpaulo  return f;
1173280405Srpaulo}
1174280405Srpaulo
1175280405Srpaulo
1176280405SrpauloLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
1177280405Srpaulo  lua_lock(L);
1178280405Srpaulo  G(L)->ud = ud;
1179280405Srpaulo  G(L)->frealloc = f;
1180280405Srpaulo  lua_unlock(L);
1181280405Srpaulo}
1182280405Srpaulo
1183280405Srpaulo
1184280405SrpauloLUA_API void *lua_newuserdata (lua_State *L, size_t size) {
1185280405Srpaulo  Udata *u;
1186280405Srpaulo  lua_lock(L);
1187280405Srpaulo  u = luaS_newudata(L, size);
1188280405Srpaulo  setuvalue(L, L->top, u);
1189280405Srpaulo  api_incr_top(L);
1190326344Simp  luaC_checkGC(L);
1191280405Srpaulo  lua_unlock(L);
1192280405Srpaulo  return getudatamem(u);
1193280405Srpaulo}
1194280405Srpaulo
1195280405Srpaulo
1196280405Srpaulo
1197280405Srpaulostatic const char *aux_upvalue (StkId fi, int n, TValue **val,
1198280405Srpaulo                                CClosure **owner, UpVal **uv) {
1199280405Srpaulo  switch (ttype(fi)) {
1200280405Srpaulo    case LUA_TCCL: {  /* C closure */
1201280405Srpaulo      CClosure *f = clCvalue(fi);
1202280405Srpaulo      if (!(1 <= n && n <= f->nupvalues)) return NULL;
1203280405Srpaulo      *val = &f->upvalue[n-1];
1204280405Srpaulo      if (owner) *owner = f;
1205280405Srpaulo      return "";
1206280405Srpaulo    }
1207280405Srpaulo    case LUA_TLCL: {  /* Lua closure */
1208280405Srpaulo      LClosure *f = clLvalue(fi);
1209280405Srpaulo      TString *name;
1210280405Srpaulo      Proto *p = f->p;
1211280405Srpaulo      if (!(1 <= n && n <= p->sizeupvalues)) return NULL;
1212280405Srpaulo      *val = f->upvals[n-1]->v;
1213280405Srpaulo      if (uv) *uv = f->upvals[n - 1];
1214280405Srpaulo      name = p->upvalues[n-1].name;
1215280405Srpaulo      return (name == NULL) ? "(*no name)" : getstr(name);
1216280405Srpaulo    }
1217280405Srpaulo    default: return NULL;  /* not a closure */
1218280405Srpaulo  }
1219280405Srpaulo}
1220280405Srpaulo
1221280405Srpaulo
1222280405SrpauloLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
1223280405Srpaulo  const char *name;
1224280405Srpaulo  TValue *val = NULL;  /* to avoid warnings */
1225280405Srpaulo  lua_lock(L);
1226280405Srpaulo  name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL);
1227280405Srpaulo  if (name) {
1228280405Srpaulo    setobj2s(L, L->top, val);
1229280405Srpaulo    api_incr_top(L);
1230280405Srpaulo  }
1231280405Srpaulo  lua_unlock(L);
1232280405Srpaulo  return name;
1233280405Srpaulo}
1234280405Srpaulo
1235280405Srpaulo
1236280405SrpauloLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
1237280405Srpaulo  const char *name;
1238280405Srpaulo  TValue *val = NULL;  /* to avoid warnings */
1239280405Srpaulo  CClosure *owner = NULL;
1240280405Srpaulo  UpVal *uv = NULL;
1241280405Srpaulo  StkId fi;
1242280405Srpaulo  lua_lock(L);
1243280405Srpaulo  fi = index2addr(L, funcindex);
1244280405Srpaulo  api_checknelems(L, 1);
1245280405Srpaulo  name = aux_upvalue(fi, n, &val, &owner, &uv);
1246280405Srpaulo  if (name) {
1247280405Srpaulo    L->top--;
1248280405Srpaulo    setobj(L, val, L->top);
1249280405Srpaulo    if (owner) { luaC_barrier(L, owner, L->top); }
1250280405Srpaulo    else if (uv) { luaC_upvalbarrier(L, uv); }
1251280405Srpaulo  }
1252280405Srpaulo  lua_unlock(L);
1253280405Srpaulo  return name;
1254280405Srpaulo}
1255280405Srpaulo
1256280405Srpaulo
1257280405Srpaulostatic UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
1258280405Srpaulo  LClosure *f;
1259280405Srpaulo  StkId fi = index2addr(L, fidx);
1260326344Simp  api_check(L, ttisLclosure(fi), "Lua function expected");
1261280405Srpaulo  f = clLvalue(fi);
1262326344Simp  api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index");
1263280405Srpaulo  if (pf) *pf = f;
1264280405Srpaulo  return &f->upvals[n - 1];  /* get its upvalue pointer */
1265280405Srpaulo}
1266280405Srpaulo
1267280405Srpaulo
1268280405SrpauloLUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
1269280405Srpaulo  StkId fi = index2addr(L, fidx);
1270280405Srpaulo  switch (ttype(fi)) {
1271280405Srpaulo    case LUA_TLCL: {  /* lua closure */
1272280405Srpaulo      return *getupvalref(L, fidx, n, NULL);
1273280405Srpaulo    }
1274280405Srpaulo    case LUA_TCCL: {  /* C closure */
1275280405Srpaulo      CClosure *f = clCvalue(fi);
1276326344Simp      api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index");
1277280405Srpaulo      return &f->upvalue[n - 1];
1278280405Srpaulo    }
1279280405Srpaulo    default: {
1280326344Simp      api_check(L, 0, "closure expected");
1281280405Srpaulo      return NULL;
1282280405Srpaulo    }
1283280405Srpaulo  }
1284280405Srpaulo}
1285280405Srpaulo
1286280405Srpaulo
1287280405SrpauloLUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
1288280405Srpaulo                                            int fidx2, int n2) {
1289280405Srpaulo  LClosure *f1;
1290280405Srpaulo  UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
1291280405Srpaulo  UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
1292280405Srpaulo  luaC_upvdeccount(L, *up1);
1293280405Srpaulo  *up1 = *up2;
1294280405Srpaulo  (*up1)->refcount++;
1295280405Srpaulo  if (upisopen(*up1)) (*up1)->u.open.touched = 1;
1296280405Srpaulo  luaC_upvalbarrier(L, *up1);
1297280405Srpaulo}
1298280405Srpaulo
1299280405Srpaulo
1300