xref: /freebsd/contrib/lua/src/lapi.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
1 /*
2 ** $Id: lapi.c $
3 ** Lua API
4 ** See Copyright Notice in lua.h
5 */
6 
7 #define lapi_c
8 #define LUA_CORE
9 
10 #include "lprefix.h"
11 
12 
13 #include <limits.h>
14 #include <stdarg.h>
15 #include <string.h>
16 
17 #include "lua.h"
18 
19 #include "lapi.h"
20 #include "ldebug.h"
21 #include "ldo.h"
22 #include "lfunc.h"
23 #include "lgc.h"
24 #include "lmem.h"
25 #include "lobject.h"
26 #include "lstate.h"
27 #include "lstring.h"
28 #include "ltable.h"
29 #include "ltm.h"
30 #include "lundump.h"
31 #include "lvm.h"
32 
33 
34 
35 const char lua_ident[] =
36   "$LuaVersion: " LUA_COPYRIGHT " $"
37   "$LuaAuthors: " LUA_AUTHORS " $";
38 
39 
40 
41 /*
42 ** Test for a valid index (one that is not the 'nilvalue').
43 ** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed.
44 ** However, it covers the most common cases in a faster way.
45 */
46 #define isvalid(L, o)	(!ttisnil(o) || o != &G(L)->nilvalue)
47 
48 
49 /* test for pseudo index */
50 #define ispseudo(i)		((i) <= LUA_REGISTRYINDEX)
51 
52 /* test for upvalue */
53 #define isupvalue(i)		((i) < LUA_REGISTRYINDEX)
54 
55 
56 /*
57 ** Convert an acceptable index to a pointer to its respective value.
58 ** Non-valid indices return the special nil value 'G(L)->nilvalue'.
59 */
60 static TValue *index2value (lua_State *L, int idx) {
61   CallInfo *ci = L->ci;
62   if (idx > 0) {
63     StkId o = ci->func.p + idx;
64     api_check(L, idx <= ci->top.p - (ci->func.p + 1), "unacceptable index");
65     if (o >= L->top.p) return &G(L)->nilvalue;
66     else return s2v(o);
67   }
68   else if (!ispseudo(idx)) {  /* negative index */
69     api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1),
70                  "invalid index");
71     return s2v(L->top.p + idx);
72   }
73   else if (idx == LUA_REGISTRYINDEX)
74     return &G(L)->l_registry;
75   else {  /* upvalues */
76     idx = LUA_REGISTRYINDEX - idx;
77     api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
78     if (ttisCclosure(s2v(ci->func.p))) {  /* C closure? */
79       CClosure *func = clCvalue(s2v(ci->func.p));
80       return (idx <= func->nupvalues) ? &func->upvalue[idx-1]
81                                       : &G(L)->nilvalue;
82     }
83     else {  /* light C function or Lua function (through a hook)?) */
84       api_check(L, ttislcf(s2v(ci->func.p)), "caller not a C function");
85       return &G(L)->nilvalue;  /* no upvalues */
86     }
87   }
88 }
89 
90 
91 
92 /*
93 ** Convert a valid actual index (not a pseudo-index) to its address.
94 */
95 l_sinline StkId index2stack (lua_State *L, int idx) {
96   CallInfo *ci = L->ci;
97   if (idx > 0) {
98     StkId o = ci->func.p + idx;
99     api_check(L, o < L->top.p, "invalid index");
100     return o;
101   }
102   else {    /* non-positive index */
103     api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1),
104                  "invalid index");
105     api_check(L, !ispseudo(idx), "invalid index");
106     return L->top.p + idx;
107   }
108 }
109 
110 
111 LUA_API int lua_checkstack (lua_State *L, int n) {
112   int res;
113   CallInfo *ci;
114   lua_lock(L);
115   ci = L->ci;
116   api_check(L, n >= 0, "negative 'n'");
117   if (L->stack_last.p - L->top.p > n)  /* stack large enough? */
118     res = 1;  /* yes; check is OK */
119   else  /* need to grow stack */
120     res = luaD_growstack(L, n, 0);
121   if (res && ci->top.p < L->top.p + n)
122     ci->top.p = L->top.p + n;  /* adjust frame top */
123   lua_unlock(L);
124   return res;
125 }
126 
127 
128 LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {
129   int i;
130   if (from == to) return;
131   lua_lock(to);
132   api_checknelems(from, n);
133   api_check(from, G(from) == G(to), "moving among independent states");
134   api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow");
135   from->top.p -= n;
136   for (i = 0; i < n; i++) {
137     setobjs2s(to, to->top.p, from->top.p + i);
138     to->top.p++;  /* stack already checked by previous 'api_check' */
139   }
140   lua_unlock(to);
141 }
142 
143 
144 LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {
145   lua_CFunction old;
146   lua_lock(L);
147   old = G(L)->panic;
148   G(L)->panic = panicf;
149   lua_unlock(L);
150   return old;
151 }
152 
153 
154 LUA_API lua_Number lua_version (lua_State *L) {
155   UNUSED(L);
156   return LUA_VERSION_NUM;
157 }
158 
159 
160 
161 /*
162 ** basic stack manipulation
163 */
164 
165 
166 /*
167 ** convert an acceptable stack index into an absolute index
168 */
169 LUA_API int lua_absindex (lua_State *L, int idx) {
170   return (idx > 0 || ispseudo(idx))
171          ? idx
172          : cast_int(L->top.p - L->ci->func.p) + idx;
173 }
174 
175 
176 LUA_API int lua_gettop (lua_State *L) {
177   return cast_int(L->top.p - (L->ci->func.p + 1));
178 }
179 
180 
181 LUA_API void lua_settop (lua_State *L, int idx) {
182   CallInfo *ci;
183   StkId func, newtop;
184   ptrdiff_t diff;  /* difference for new top */
185   lua_lock(L);
186   ci = L->ci;
187   func = ci->func.p;
188   if (idx >= 0) {
189     api_check(L, idx <= ci->top.p - (func + 1), "new top too large");
190     diff = ((func + 1) + idx) - L->top.p;
191     for (; diff > 0; diff--)
192       setnilvalue(s2v(L->top.p++));  /* clear new slots */
193   }
194   else {
195     api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top");
196     diff = idx + 1;  /* will "subtract" index (as it is negative) */
197   }
198   api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot");
199   newtop = L->top.p + diff;
200   if (diff < 0 && L->tbclist.p >= newtop) {
201     lua_assert(hastocloseCfunc(ci->nresults));
202     newtop = luaF_close(L, newtop, CLOSEKTOP, 0);
203   }
204   L->top.p = newtop;  /* correct top only after closing any upvalue */
205   lua_unlock(L);
206 }
207 
208 
209 LUA_API void lua_closeslot (lua_State *L, int idx) {
210   StkId level;
211   lua_lock(L);
212   level = index2stack(L, idx);
213   api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist.p == level,
214      "no variable to close at given level");
215   level = luaF_close(L, level, CLOSEKTOP, 0);
216   setnilvalue(s2v(level));
217   lua_unlock(L);
218 }
219 
220 
221 /*
222 ** Reverse the stack segment from 'from' to 'to'
223 ** (auxiliary to 'lua_rotate')
224 ** Note that we move(copy) only the value inside the stack.
225 ** (We do not move additional fields that may exist.)
226 */
227 l_sinline void reverse (lua_State *L, StkId from, StkId to) {
228   for (; from < to; from++, to--) {
229     TValue temp;
230     setobj(L, &temp, s2v(from));
231     setobjs2s(L, from, to);
232     setobj2s(L, to, &temp);
233   }
234 }
235 
236 
237 /*
238 ** Let x = AB, where A is a prefix of length 'n'. Then,
239 ** rotate x n == BA. But BA == (A^r . B^r)^r.
240 */
241 LUA_API void lua_rotate (lua_State *L, int idx, int n) {
242   StkId p, t, m;
243   lua_lock(L);
244   t = L->top.p - 1;  /* end of stack segment being rotated */
245   p = index2stack(L, idx);  /* start of segment */
246   api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'");
247   m = (n >= 0 ? t - n : p - n - 1);  /* end of prefix */
248   reverse(L, p, m);  /* reverse the prefix with length 'n' */
249   reverse(L, m + 1, t);  /* reverse the suffix */
250   reverse(L, p, t);  /* reverse the entire segment */
251   lua_unlock(L);
252 }
253 
254 
255 LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
256   TValue *fr, *to;
257   lua_lock(L);
258   fr = index2value(L, fromidx);
259   to = index2value(L, toidx);
260   api_check(L, isvalid(L, to), "invalid index");
261   setobj(L, to, fr);
262   if (isupvalue(toidx))  /* function upvalue? */
263     luaC_barrier(L, clCvalue(s2v(L->ci->func.p)), fr);
264   /* LUA_REGISTRYINDEX does not need gc barrier
265      (collector revisits it before finishing collection) */
266   lua_unlock(L);
267 }
268 
269 
270 LUA_API void lua_pushvalue (lua_State *L, int idx) {
271   lua_lock(L);
272   setobj2s(L, L->top.p, index2value(L, idx));
273   api_incr_top(L);
274   lua_unlock(L);
275 }
276 
277 
278 
279 /*
280 ** access functions (stack -> C)
281 */
282 
283 
284 LUA_API int lua_type (lua_State *L, int idx) {
285   const TValue *o = index2value(L, idx);
286   return (isvalid(L, o) ? ttype(o) : LUA_TNONE);
287 }
288 
289 
290 LUA_API const char *lua_typename (lua_State *L, int t) {
291   UNUSED(L);
292   api_check(L, LUA_TNONE <= t && t < LUA_NUMTYPES, "invalid type");
293   return ttypename(t);
294 }
295 
296 
297 LUA_API int lua_iscfunction (lua_State *L, int idx) {
298   const TValue *o = index2value(L, idx);
299   return (ttislcf(o) || (ttisCclosure(o)));
300 }
301 
302 
303 LUA_API int lua_isinteger (lua_State *L, int idx) {
304   const TValue *o = index2value(L, idx);
305   return ttisinteger(o);
306 }
307 
308 
309 LUA_API int lua_isnumber (lua_State *L, int idx) {
310   lua_Number n;
311   const TValue *o = index2value(L, idx);
312   return tonumber(o, &n);
313 }
314 
315 
316 LUA_API int lua_isstring (lua_State *L, int idx) {
317   const TValue *o = index2value(L, idx);
318   return (ttisstring(o) || cvt2str(o));
319 }
320 
321 
322 LUA_API int lua_isuserdata (lua_State *L, int idx) {
323   const TValue *o = index2value(L, idx);
324   return (ttisfulluserdata(o) || ttislightuserdata(o));
325 }
326 
327 
328 LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
329   const TValue *o1 = index2value(L, index1);
330   const TValue *o2 = index2value(L, index2);
331   return (isvalid(L, o1) && isvalid(L, o2)) ? luaV_rawequalobj(o1, o2) : 0;
332 }
333 
334 
335 LUA_API void lua_arith (lua_State *L, int op) {
336   lua_lock(L);
337   if (op != LUA_OPUNM && op != LUA_OPBNOT)
338     api_checknelems(L, 2);  /* all other operations expect two operands */
339   else {  /* for unary operations, add fake 2nd operand */
340     api_checknelems(L, 1);
341     setobjs2s(L, L->top.p, L->top.p - 1);
342     api_incr_top(L);
343   }
344   /* first operand at top - 2, second at top - 1; result go to top - 2 */
345   luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2);
346   L->top.p--;  /* remove second operand */
347   lua_unlock(L);
348 }
349 
350 
351 LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) {
352   const TValue *o1;
353   const TValue *o2;
354   int i = 0;
355   lua_lock(L);  /* may call tag method */
356   o1 = index2value(L, index1);
357   o2 = index2value(L, index2);
358   if (isvalid(L, o1) && isvalid(L, o2)) {
359     switch (op) {
360       case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
361       case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;
362       case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break;
363       default: api_check(L, 0, "invalid option");
364     }
365   }
366   lua_unlock(L);
367   return i;
368 }
369 
370 
371 LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) {
372   size_t sz = luaO_str2num(s, s2v(L->top.p));
373   if (sz != 0)
374     api_incr_top(L);
375   return sz;
376 }
377 
378 
379 LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) {
380   lua_Number n = 0;
381   const TValue *o = index2value(L, idx);
382   int isnum = tonumber(o, &n);
383   if (pisnum)
384     *pisnum = isnum;
385   return n;
386 }
387 
388 
389 LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) {
390   lua_Integer res = 0;
391   const TValue *o = index2value(L, idx);
392   int isnum = tointeger(o, &res);
393   if (pisnum)
394     *pisnum = isnum;
395   return res;
396 }
397 
398 
399 LUA_API int lua_toboolean (lua_State *L, int idx) {
400   const TValue *o = index2value(L, idx);
401   return !l_isfalse(o);
402 }
403 
404 
405 LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
406   TValue *o;
407   lua_lock(L);
408   o = index2value(L, idx);
409   if (!ttisstring(o)) {
410     if (!cvt2str(o)) {  /* not convertible? */
411       if (len != NULL) *len = 0;
412       lua_unlock(L);
413       return NULL;
414     }
415     luaO_tostring(L, o);
416     luaC_checkGC(L);
417     o = index2value(L, idx);  /* previous call may reallocate the stack */
418   }
419   if (len != NULL)
420     *len = vslen(o);
421   lua_unlock(L);
422   return svalue(o);
423 }
424 
425 
426 LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) {
427   const TValue *o = index2value(L, idx);
428   switch (ttypetag(o)) {
429     case LUA_VSHRSTR: return tsvalue(o)->shrlen;
430     case LUA_VLNGSTR: return tsvalue(o)->u.lnglen;
431     case LUA_VUSERDATA: return uvalue(o)->len;
432     case LUA_VTABLE: return luaH_getn(hvalue(o));
433     default: return 0;
434   }
435 }
436 
437 
438 LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
439   const TValue *o = index2value(L, idx);
440   if (ttislcf(o)) return fvalue(o);
441   else if (ttisCclosure(o))
442     return clCvalue(o)->f;
443   else return NULL;  /* not a C function */
444 }
445 
446 
447 l_sinline void *touserdata (const TValue *o) {
448   switch (ttype(o)) {
449     case LUA_TUSERDATA: return getudatamem(uvalue(o));
450     case LUA_TLIGHTUSERDATA: return pvalue(o);
451     default: return NULL;
452   }
453 }
454 
455 
456 LUA_API void *lua_touserdata (lua_State *L, int idx) {
457   const TValue *o = index2value(L, idx);
458   return touserdata(o);
459 }
460 
461 
462 LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
463   const TValue *o = index2value(L, idx);
464   return (!ttisthread(o)) ? NULL : thvalue(o);
465 }
466 
467 
468 /*
469 ** Returns a pointer to the internal representation of an object.
470 ** Note that ANSI C does not allow the conversion of a pointer to
471 ** function to a 'void*', so the conversion here goes through
472 ** a 'size_t'. (As the returned pointer is only informative, this
473 ** conversion should not be a problem.)
474 */
475 LUA_API const void *lua_topointer (lua_State *L, int idx) {
476   const TValue *o = index2value(L, idx);
477   switch (ttypetag(o)) {
478     case LUA_VLCF: return cast_voidp(cast_sizet(fvalue(o)));
479     case LUA_VUSERDATA: case LUA_VLIGHTUSERDATA:
480       return touserdata(o);
481     default: {
482       if (iscollectable(o))
483         return gcvalue(o);
484       else
485         return NULL;
486     }
487   }
488 }
489 
490 
491 
492 /*
493 ** push functions (C -> stack)
494 */
495 
496 
497 LUA_API void lua_pushnil (lua_State *L) {
498   lua_lock(L);
499   setnilvalue(s2v(L->top.p));
500   api_incr_top(L);
501   lua_unlock(L);
502 }
503 
504 
505 LUA_API void lua_pushnumber (lua_State *L, lua_Number n) {
506   lua_lock(L);
507   setfltvalue(s2v(L->top.p), n);
508   api_incr_top(L);
509   lua_unlock(L);
510 }
511 
512 
513 LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {
514   lua_lock(L);
515   setivalue(s2v(L->top.p), n);
516   api_incr_top(L);
517   lua_unlock(L);
518 }
519 
520 
521 /*
522 ** Pushes on the stack a string with given length. Avoid using 's' when
523 ** 'len' == 0 (as 's' can be NULL in that case), due to later use of
524 ** 'memcmp' and 'memcpy'.
525 */
526 LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) {
527   TString *ts;
528   lua_lock(L);
529   ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len);
530   setsvalue2s(L, L->top.p, ts);
531   api_incr_top(L);
532   luaC_checkGC(L);
533   lua_unlock(L);
534   return getstr(ts);
535 }
536 
537 
538 LUA_API const char *lua_pushstring (lua_State *L, const char *s) {
539   lua_lock(L);
540   if (s == NULL)
541     setnilvalue(s2v(L->top.p));
542   else {
543     TString *ts;
544     ts = luaS_new(L, s);
545     setsvalue2s(L, L->top.p, ts);
546     s = getstr(ts);  /* internal copy's address */
547   }
548   api_incr_top(L);
549   luaC_checkGC(L);
550   lua_unlock(L);
551   return s;
552 }
553 
554 
555 LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,
556                                       va_list argp) {
557   const char *ret;
558   lua_lock(L);
559   ret = luaO_pushvfstring(L, fmt, argp);
560   luaC_checkGC(L);
561   lua_unlock(L);
562   return ret;
563 }
564 
565 
566 LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {
567   const char *ret;
568   va_list argp;
569   lua_lock(L);
570   va_start(argp, fmt);
571   ret = luaO_pushvfstring(L, fmt, argp);
572   va_end(argp);
573   luaC_checkGC(L);
574   lua_unlock(L);
575   return ret;
576 }
577 
578 
579 LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
580   lua_lock(L);
581   if (n == 0) {
582     setfvalue(s2v(L->top.p), fn);
583     api_incr_top(L);
584   }
585   else {
586     CClosure *cl;
587     api_checknelems(L, n);
588     api_check(L, n <= MAXUPVAL, "upvalue index too large");
589     cl = luaF_newCclosure(L, n);
590     cl->f = fn;
591     L->top.p -= n;
592     while (n--) {
593       setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n));
594       /* does not need barrier because closure is white */
595       lua_assert(iswhite(cl));
596     }
597     setclCvalue(L, s2v(L->top.p), cl);
598     api_incr_top(L);
599     luaC_checkGC(L);
600   }
601   lua_unlock(L);
602 }
603 
604 
605 LUA_API void lua_pushboolean (lua_State *L, int b) {
606   lua_lock(L);
607   if (b)
608     setbtvalue(s2v(L->top.p));
609   else
610     setbfvalue(s2v(L->top.p));
611   api_incr_top(L);
612   lua_unlock(L);
613 }
614 
615 
616 LUA_API void lua_pushlightuserdata (lua_State *L, void *p) {
617   lua_lock(L);
618   setpvalue(s2v(L->top.p), p);
619   api_incr_top(L);
620   lua_unlock(L);
621 }
622 
623 
624 LUA_API int lua_pushthread (lua_State *L) {
625   lua_lock(L);
626   setthvalue(L, s2v(L->top.p), L);
627   api_incr_top(L);
628   lua_unlock(L);
629   return (G(L)->mainthread == L);
630 }
631 
632 
633 
634 /*
635 ** get functions (Lua -> stack)
636 */
637 
638 
639 l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) {
640   const TValue *slot;
641   TString *str = luaS_new(L, k);
642   if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
643     setobj2s(L, L->top.p, slot);
644     api_incr_top(L);
645   }
646   else {
647     setsvalue2s(L, L->top.p, str);
648     api_incr_top(L);
649     luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot);
650   }
651   lua_unlock(L);
652   return ttype(s2v(L->top.p - 1));
653 }
654 
655 
656 /*
657 ** Get the global table in the registry. Since all predefined
658 ** indices in the registry were inserted right when the registry
659 ** was created and never removed, they must always be in the array
660 ** part of the registry.
661 */
662 #define getGtable(L)  \
663 	(&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1])
664 
665 
666 LUA_API int lua_getglobal (lua_State *L, const char *name) {
667   const TValue *G;
668   lua_lock(L);
669   G = getGtable(L);
670   return auxgetstr(L, G, name);
671 }
672 
673 
674 LUA_API int lua_gettable (lua_State *L, int idx) {
675   const TValue *slot;
676   TValue *t;
677   lua_lock(L);
678   t = index2value(L, idx);
679   if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) {
680     setobj2s(L, L->top.p - 1, slot);
681   }
682   else
683     luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot);
684   lua_unlock(L);
685   return ttype(s2v(L->top.p - 1));
686 }
687 
688 
689 LUA_API int lua_getfield (lua_State *L, int idx, const char *k) {
690   lua_lock(L);
691   return auxgetstr(L, index2value(L, idx), k);
692 }
693 
694 
695 LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) {
696   TValue *t;
697   const TValue *slot;
698   lua_lock(L);
699   t = index2value(L, idx);
700   if (luaV_fastgeti(L, t, n, slot)) {
701     setobj2s(L, L->top.p, slot);
702   }
703   else {
704     TValue aux;
705     setivalue(&aux, n);
706     luaV_finishget(L, t, &aux, L->top.p, slot);
707   }
708   api_incr_top(L);
709   lua_unlock(L);
710   return ttype(s2v(L->top.p - 1));
711 }
712 
713 
714 l_sinline int finishrawget (lua_State *L, const TValue *val) {
715   if (isempty(val))  /* avoid copying empty items to the stack */
716     setnilvalue(s2v(L->top.p));
717   else
718     setobj2s(L, L->top.p, val);
719   api_incr_top(L);
720   lua_unlock(L);
721   return ttype(s2v(L->top.p - 1));
722 }
723 
724 
725 static Table *gettable (lua_State *L, int idx) {
726   TValue *t = index2value(L, idx);
727   api_check(L, ttistable(t), "table expected");
728   return hvalue(t);
729 }
730 
731 
732 LUA_API int lua_rawget (lua_State *L, int idx) {
733   Table *t;
734   const TValue *val;
735   lua_lock(L);
736   api_checknelems(L, 1);
737   t = gettable(L, idx);
738   val = luaH_get(t, s2v(L->top.p - 1));
739   L->top.p--;  /* remove key */
740   return finishrawget(L, val);
741 }
742 
743 
744 LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) {
745   Table *t;
746   lua_lock(L);
747   t = gettable(L, idx);
748   return finishrawget(L, luaH_getint(t, n));
749 }
750 
751 
752 LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
753   Table *t;
754   TValue k;
755   lua_lock(L);
756   t = gettable(L, idx);
757   setpvalue(&k, cast_voidp(p));
758   return finishrawget(L, luaH_get(t, &k));
759 }
760 
761 
762 LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
763   Table *t;
764   lua_lock(L);
765   t = luaH_new(L);
766   sethvalue2s(L, L->top.p, t);
767   api_incr_top(L);
768   if (narray > 0 || nrec > 0)
769     luaH_resize(L, t, narray, nrec);
770   luaC_checkGC(L);
771   lua_unlock(L);
772 }
773 
774 
775 LUA_API int lua_getmetatable (lua_State *L, int objindex) {
776   const TValue *obj;
777   Table *mt;
778   int res = 0;
779   lua_lock(L);
780   obj = index2value(L, objindex);
781   switch (ttype(obj)) {
782     case LUA_TTABLE:
783       mt = hvalue(obj)->metatable;
784       break;
785     case LUA_TUSERDATA:
786       mt = uvalue(obj)->metatable;
787       break;
788     default:
789       mt = G(L)->mt[ttype(obj)];
790       break;
791   }
792   if (mt != NULL) {
793     sethvalue2s(L, L->top.p, mt);
794     api_incr_top(L);
795     res = 1;
796   }
797   lua_unlock(L);
798   return res;
799 }
800 
801 
802 LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) {
803   TValue *o;
804   int t;
805   lua_lock(L);
806   o = index2value(L, idx);
807   api_check(L, ttisfulluserdata(o), "full userdata expected");
808   if (n <= 0 || n > uvalue(o)->nuvalue) {
809     setnilvalue(s2v(L->top.p));
810     t = LUA_TNONE;
811   }
812   else {
813     setobj2s(L, L->top.p, &uvalue(o)->uv[n - 1].uv);
814     t = ttype(s2v(L->top.p));
815   }
816   api_incr_top(L);
817   lua_unlock(L);
818   return t;
819 }
820 
821 
822 /*
823 ** set functions (stack -> Lua)
824 */
825 
826 /*
827 ** t[k] = value at the top of the stack (where 'k' is a string)
828 */
829 static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
830   const TValue *slot;
831   TString *str = luaS_new(L, k);
832   api_checknelems(L, 1);
833   if (luaV_fastget(L, t, str, slot, luaH_getstr)) {
834     luaV_finishfastset(L, t, slot, s2v(L->top.p - 1));
835     L->top.p--;  /* pop value */
836   }
837   else {
838     setsvalue2s(L, L->top.p, str);  /* push 'str' (to make it a TValue) */
839     api_incr_top(L);
840     luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot);
841     L->top.p -= 2;  /* pop value and key */
842   }
843   lua_unlock(L);  /* lock done by caller */
844 }
845 
846 
847 LUA_API void lua_setglobal (lua_State *L, const char *name) {
848   const TValue *G;
849   lua_lock(L);  /* unlock done in 'auxsetstr' */
850   G = getGtable(L);
851   auxsetstr(L, G, name);
852 }
853 
854 
855 LUA_API void lua_settable (lua_State *L, int idx) {
856   TValue *t;
857   const TValue *slot;
858   lua_lock(L);
859   api_checknelems(L, 2);
860   t = index2value(L, idx);
861   if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) {
862     luaV_finishfastset(L, t, slot, s2v(L->top.p - 1));
863   }
864   else
865     luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot);
866   L->top.p -= 2;  /* pop index and value */
867   lua_unlock(L);
868 }
869 
870 
871 LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
872   lua_lock(L);  /* unlock done in 'auxsetstr' */
873   auxsetstr(L, index2value(L, idx), k);
874 }
875 
876 
877 LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
878   TValue *t;
879   const TValue *slot;
880   lua_lock(L);
881   api_checknelems(L, 1);
882   t = index2value(L, idx);
883   if (luaV_fastgeti(L, t, n, slot)) {
884     luaV_finishfastset(L, t, slot, s2v(L->top.p - 1));
885   }
886   else {
887     TValue aux;
888     setivalue(&aux, n);
889     luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot);
890   }
891   L->top.p--;  /* pop value */
892   lua_unlock(L);
893 }
894 
895 
896 static void aux_rawset (lua_State *L, int idx, TValue *key, int n) {
897   Table *t;
898   lua_lock(L);
899   api_checknelems(L, n);
900   t = gettable(L, idx);
901   luaH_set(L, t, key, s2v(L->top.p - 1));
902   invalidateTMcache(t);
903   luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1));
904   L->top.p -= n;
905   lua_unlock(L);
906 }
907 
908 
909 LUA_API void lua_rawset (lua_State *L, int idx) {
910   aux_rawset(L, idx, s2v(L->top.p - 2), 2);
911 }
912 
913 
914 LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) {
915   TValue k;
916   setpvalue(&k, cast_voidp(p));
917   aux_rawset(L, idx, &k, 1);
918 }
919 
920 
921 LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) {
922   Table *t;
923   lua_lock(L);
924   api_checknelems(L, 1);
925   t = gettable(L, idx);
926   luaH_setint(L, t, n, s2v(L->top.p - 1));
927   luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1));
928   L->top.p--;
929   lua_unlock(L);
930 }
931 
932 
933 LUA_API int lua_setmetatable (lua_State *L, int objindex) {
934   TValue *obj;
935   Table *mt;
936   lua_lock(L);
937   api_checknelems(L, 1);
938   obj = index2value(L, objindex);
939   if (ttisnil(s2v(L->top.p - 1)))
940     mt = NULL;
941   else {
942     api_check(L, ttistable(s2v(L->top.p - 1)), "table expected");
943     mt = hvalue(s2v(L->top.p - 1));
944   }
945   switch (ttype(obj)) {
946     case LUA_TTABLE: {
947       hvalue(obj)->metatable = mt;
948       if (mt) {
949         luaC_objbarrier(L, gcvalue(obj), mt);
950         luaC_checkfinalizer(L, gcvalue(obj), mt);
951       }
952       break;
953     }
954     case LUA_TUSERDATA: {
955       uvalue(obj)->metatable = mt;
956       if (mt) {
957         luaC_objbarrier(L, uvalue(obj), mt);
958         luaC_checkfinalizer(L, gcvalue(obj), mt);
959       }
960       break;
961     }
962     default: {
963       G(L)->mt[ttype(obj)] = mt;
964       break;
965     }
966   }
967   L->top.p--;
968   lua_unlock(L);
969   return 1;
970 }
971 
972 
973 LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) {
974   TValue *o;
975   int res;
976   lua_lock(L);
977   api_checknelems(L, 1);
978   o = index2value(L, idx);
979   api_check(L, ttisfulluserdata(o), "full userdata expected");
980   if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue)))
981     res = 0;  /* 'n' not in [1, uvalue(o)->nuvalue] */
982   else {
983     setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top.p - 1));
984     luaC_barrierback(L, gcvalue(o), s2v(L->top.p - 1));
985     res = 1;
986   }
987   L->top.p--;
988   lua_unlock(L);
989   return res;
990 }
991 
992 
993 /*
994 ** 'load' and 'call' functions (run Lua code)
995 */
996 
997 
998 #define checkresults(L,na,nr) \
999      api_check(L, (nr) == LUA_MULTRET \
1000                || (L->ci->top.p - L->top.p >= (nr) - (na)), \
1001 	"results from function overflow current stack size")
1002 
1003 
1004 LUA_API void lua_callk (lua_State *L, int nargs, int nresults,
1005                         lua_KContext ctx, lua_KFunction k) {
1006   StkId func;
1007   lua_lock(L);
1008   api_check(L, k == NULL || !isLua(L->ci),
1009     "cannot use continuations inside hooks");
1010   api_checknelems(L, nargs+1);
1011   api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
1012   checkresults(L, nargs, nresults);
1013   func = L->top.p - (nargs+1);
1014   if (k != NULL && yieldable(L)) {  /* need to prepare continuation? */
1015     L->ci->u.c.k = k;  /* save continuation */
1016     L->ci->u.c.ctx = ctx;  /* save context */
1017     luaD_call(L, func, nresults);  /* do the call */
1018   }
1019   else  /* no continuation or no yieldable */
1020     luaD_callnoyield(L, func, nresults);  /* just do the call */
1021   adjustresults(L, nresults);
1022   lua_unlock(L);
1023 }
1024 
1025 
1026 
1027 /*
1028 ** Execute a protected call.
1029 */
1030 struct CallS {  /* data to 'f_call' */
1031   StkId func;
1032   int nresults;
1033 };
1034 
1035 
1036 static void f_call (lua_State *L, void *ud) {
1037   struct CallS *c = cast(struct CallS *, ud);
1038   luaD_callnoyield(L, c->func, c->nresults);
1039 }
1040 
1041 
1042 
1043 LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
1044                         lua_KContext ctx, lua_KFunction k) {
1045   struct CallS c;
1046   int status;
1047   ptrdiff_t func;
1048   lua_lock(L);
1049   api_check(L, k == NULL || !isLua(L->ci),
1050     "cannot use continuations inside hooks");
1051   api_checknelems(L, nargs+1);
1052   api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
1053   checkresults(L, nargs, nresults);
1054   if (errfunc == 0)
1055     func = 0;
1056   else {
1057     StkId o = index2stack(L, errfunc);
1058     api_check(L, ttisfunction(s2v(o)), "error handler must be a function");
1059     func = savestack(L, o);
1060   }
1061   c.func = L->top.p - (nargs+1);  /* function to be called */
1062   if (k == NULL || !yieldable(L)) {  /* no continuation or no yieldable? */
1063     c.nresults = nresults;  /* do a 'conventional' protected call */
1064     status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
1065   }
1066   else {  /* prepare continuation (call is already protected by 'resume') */
1067     CallInfo *ci = L->ci;
1068     ci->u.c.k = k;  /* save continuation */
1069     ci->u.c.ctx = ctx;  /* save context */
1070     /* save information for error recovery */
1071     ci->u2.funcidx = cast_int(savestack(L, c.func));
1072     ci->u.c.old_errfunc = L->errfunc;
1073     L->errfunc = func;
1074     setoah(ci->callstatus, L->allowhook);  /* save value of 'allowhook' */
1075     ci->callstatus |= CIST_YPCALL;  /* function can do error recovery */
1076     luaD_call(L, c.func, nresults);  /* do the call */
1077     ci->callstatus &= ~CIST_YPCALL;
1078     L->errfunc = ci->u.c.old_errfunc;
1079     status = LUA_OK;  /* if it is here, there were no errors */
1080   }
1081   adjustresults(L, nresults);
1082   lua_unlock(L);
1083   return status;
1084 }
1085 
1086 
1087 LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
1088                       const char *chunkname, const char *mode) {
1089   ZIO z;
1090   int status;
1091   lua_lock(L);
1092   if (!chunkname) chunkname = "?";
1093   luaZ_init(L, &z, reader, data);
1094   status = luaD_protectedparser(L, &z, chunkname, mode);
1095   if (status == LUA_OK) {  /* no errors? */
1096     LClosure *f = clLvalue(s2v(L->top.p - 1));  /* get new function */
1097     if (f->nupvalues >= 1) {  /* does it have an upvalue? */
1098       /* get global table from registry */
1099       const TValue *gt = getGtable(L);
1100       /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
1101       setobj(L, f->upvals[0]->v.p, gt);
1102       luaC_barrier(L, f->upvals[0], gt);
1103     }
1104   }
1105   lua_unlock(L);
1106   return status;
1107 }
1108 
1109 
1110 LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
1111   int status;
1112   TValue *o;
1113   lua_lock(L);
1114   api_checknelems(L, 1);
1115   o = s2v(L->top.p - 1);
1116   if (isLfunction(o))
1117     status = luaU_dump(L, getproto(o), writer, data, strip);
1118   else
1119     status = 1;
1120   lua_unlock(L);
1121   return status;
1122 }
1123 
1124 
1125 LUA_API int lua_status (lua_State *L) {
1126   return L->status;
1127 }
1128 
1129 
1130 /*
1131 ** Garbage-collection function
1132 */
1133 LUA_API int lua_gc (lua_State *L, int what, ...) {
1134   va_list argp;
1135   int res = 0;
1136   global_State *g = G(L);
1137   if (g->gcstp & GCSTPGC)  /* internal stop? */
1138     return -1;  /* all options are invalid when stopped */
1139   lua_lock(L);
1140   va_start(argp, what);
1141   switch (what) {
1142     case LUA_GCSTOP: {
1143       g->gcstp = GCSTPUSR;  /* stopped by the user */
1144       break;
1145     }
1146     case LUA_GCRESTART: {
1147       luaE_setdebt(g, 0);
1148       g->gcstp = 0;  /* (GCSTPGC must be already zero here) */
1149       break;
1150     }
1151     case LUA_GCCOLLECT: {
1152       luaC_fullgc(L, 0);
1153       break;
1154     }
1155     case LUA_GCCOUNT: {
1156       /* GC values are expressed in Kbytes: #bytes/2^10 */
1157       res = cast_int(gettotalbytes(g) >> 10);
1158       break;
1159     }
1160     case LUA_GCCOUNTB: {
1161       res = cast_int(gettotalbytes(g) & 0x3ff);
1162       break;
1163     }
1164     case LUA_GCSTEP: {
1165       int data = va_arg(argp, int);
1166       l_mem debt = 1;  /* =1 to signal that it did an actual step */
1167       lu_byte oldstp = g->gcstp;
1168       g->gcstp = 0;  /* allow GC to run (GCSTPGC must be zero here) */
1169       if (data == 0) {
1170         luaE_setdebt(g, 0);  /* do a basic step */
1171         luaC_step(L);
1172       }
1173       else {  /* add 'data' to total debt */
1174         debt = cast(l_mem, data) * 1024 + g->GCdebt;
1175         luaE_setdebt(g, debt);
1176         luaC_checkGC(L);
1177       }
1178       g->gcstp = oldstp;  /* restore previous state */
1179       if (debt > 0 && g->gcstate == GCSpause)  /* end of cycle? */
1180         res = 1;  /* signal it */
1181       break;
1182     }
1183     case LUA_GCSETPAUSE: {
1184       int data = va_arg(argp, int);
1185       res = getgcparam(g->gcpause);
1186       setgcparam(g->gcpause, data);
1187       break;
1188     }
1189     case LUA_GCSETSTEPMUL: {
1190       int data = va_arg(argp, int);
1191       res = getgcparam(g->gcstepmul);
1192       setgcparam(g->gcstepmul, data);
1193       break;
1194     }
1195     case LUA_GCISRUNNING: {
1196       res = gcrunning(g);
1197       break;
1198     }
1199     case LUA_GCGEN: {
1200       int minormul = va_arg(argp, int);
1201       int majormul = va_arg(argp, int);
1202       res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC;
1203       if (minormul != 0)
1204         g->genminormul = minormul;
1205       if (majormul != 0)
1206         setgcparam(g->genmajormul, majormul);
1207       luaC_changemode(L, KGC_GEN);
1208       break;
1209     }
1210     case LUA_GCINC: {
1211       int pause = va_arg(argp, int);
1212       int stepmul = va_arg(argp, int);
1213       int stepsize = va_arg(argp, int);
1214       res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC;
1215       if (pause != 0)
1216         setgcparam(g->gcpause, pause);
1217       if (stepmul != 0)
1218         setgcparam(g->gcstepmul, stepmul);
1219       if (stepsize != 0)
1220         g->gcstepsize = stepsize;
1221       luaC_changemode(L, KGC_INC);
1222       break;
1223     }
1224     default: res = -1;  /* invalid option */
1225   }
1226   va_end(argp);
1227   lua_unlock(L);
1228   return res;
1229 }
1230 
1231 
1232 
1233 /*
1234 ** miscellaneous functions
1235 */
1236 
1237 
1238 LUA_API int lua_error (lua_State *L) {
1239   TValue *errobj;
1240   lua_lock(L);
1241   errobj = s2v(L->top.p - 1);
1242   api_checknelems(L, 1);
1243   /* error object is the memory error message? */
1244   if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg))
1245     luaM_error(L);  /* raise a memory error */
1246   else
1247     luaG_errormsg(L);  /* raise a regular error */
1248   /* code unreachable; will unlock when control actually leaves the kernel */
1249   return 0;  /* to avoid warnings */
1250 }
1251 
1252 
1253 LUA_API int lua_next (lua_State *L, int idx) {
1254   Table *t;
1255   int more;
1256   lua_lock(L);
1257   api_checknelems(L, 1);
1258   t = gettable(L, idx);
1259   more = luaH_next(L, t, L->top.p - 1);
1260   if (more) {
1261     api_incr_top(L);
1262   }
1263   else  /* no more elements */
1264     L->top.p -= 1;  /* remove key */
1265   lua_unlock(L);
1266   return more;
1267 }
1268 
1269 
1270 LUA_API void lua_toclose (lua_State *L, int idx) {
1271   int nresults;
1272   StkId o;
1273   lua_lock(L);
1274   o = index2stack(L, idx);
1275   nresults = L->ci->nresults;
1276   api_check(L, L->tbclist.p < o, "given index below or equal a marked one");
1277   luaF_newtbcupval(L, o);  /* create new to-be-closed upvalue */
1278   if (!hastocloseCfunc(nresults))  /* function not marked yet? */
1279     L->ci->nresults = codeNresults(nresults);  /* mark it */
1280   lua_assert(hastocloseCfunc(L->ci->nresults));
1281   lua_unlock(L);
1282 }
1283 
1284 
1285 LUA_API void lua_concat (lua_State *L, int n) {
1286   lua_lock(L);
1287   api_checknelems(L, n);
1288   if (n > 0)
1289     luaV_concat(L, n);
1290   else {  /* nothing to concatenate */
1291     setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0));  /* push empty string */
1292     api_incr_top(L);
1293   }
1294   luaC_checkGC(L);
1295   lua_unlock(L);
1296 }
1297 
1298 
1299 LUA_API void lua_len (lua_State *L, int idx) {
1300   TValue *t;
1301   lua_lock(L);
1302   t = index2value(L, idx);
1303   luaV_objlen(L, L->top.p, t);
1304   api_incr_top(L);
1305   lua_unlock(L);
1306 }
1307 
1308 
1309 LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {
1310   lua_Alloc f;
1311   lua_lock(L);
1312   if (ud) *ud = G(L)->ud;
1313   f = G(L)->frealloc;
1314   lua_unlock(L);
1315   return f;
1316 }
1317 
1318 
1319 LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {
1320   lua_lock(L);
1321   G(L)->ud = ud;
1322   G(L)->frealloc = f;
1323   lua_unlock(L);
1324 }
1325 
1326 
1327 void lua_setwarnf (lua_State *L, lua_WarnFunction f, void *ud) {
1328   lua_lock(L);
1329   G(L)->ud_warn = ud;
1330   G(L)->warnf = f;
1331   lua_unlock(L);
1332 }
1333 
1334 
1335 void lua_warning (lua_State *L, const char *msg, int tocont) {
1336   lua_lock(L);
1337   luaE_warning(L, msg, tocont);
1338   lua_unlock(L);
1339 }
1340 
1341 
1342 
1343 LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) {
1344   Udata *u;
1345   lua_lock(L);
1346   api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value");
1347   u = luaS_newudata(L, size, nuvalue);
1348   setuvalue(L, s2v(L->top.p), u);
1349   api_incr_top(L);
1350   luaC_checkGC(L);
1351   lua_unlock(L);
1352   return getudatamem(u);
1353 }
1354 
1355 
1356 
1357 static const char *aux_upvalue (TValue *fi, int n, TValue **val,
1358                                 GCObject **owner) {
1359   switch (ttypetag(fi)) {
1360     case LUA_VCCL: {  /* C closure */
1361       CClosure *f = clCvalue(fi);
1362       if (!(cast_uint(n) - 1u < cast_uint(f->nupvalues)))
1363         return NULL;  /* 'n' not in [1, f->nupvalues] */
1364       *val = &f->upvalue[n-1];
1365       if (owner) *owner = obj2gco(f);
1366       return "";
1367     }
1368     case LUA_VLCL: {  /* Lua closure */
1369       LClosure *f = clLvalue(fi);
1370       TString *name;
1371       Proto *p = f->p;
1372       if (!(cast_uint(n) - 1u  < cast_uint(p->sizeupvalues)))
1373         return NULL;  /* 'n' not in [1, p->sizeupvalues] */
1374       *val = f->upvals[n-1]->v.p;
1375       if (owner) *owner = obj2gco(f->upvals[n - 1]);
1376       name = p->upvalues[n-1].name;
1377       return (name == NULL) ? "(no name)" : getstr(name);
1378     }
1379     default: return NULL;  /* not a closure */
1380   }
1381 }
1382 
1383 
1384 LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {
1385   const char *name;
1386   TValue *val = NULL;  /* to avoid warnings */
1387   lua_lock(L);
1388   name = aux_upvalue(index2value(L, funcindex), n, &val, NULL);
1389   if (name) {
1390     setobj2s(L, L->top.p, val);
1391     api_incr_top(L);
1392   }
1393   lua_unlock(L);
1394   return name;
1395 }
1396 
1397 
1398 LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {
1399   const char *name;
1400   TValue *val = NULL;  /* to avoid warnings */
1401   GCObject *owner = NULL;  /* to avoid warnings */
1402   TValue *fi;
1403   lua_lock(L);
1404   fi = index2value(L, funcindex);
1405   api_checknelems(L, 1);
1406   name = aux_upvalue(fi, n, &val, &owner);
1407   if (name) {
1408     L->top.p--;
1409     setobj(L, val, s2v(L->top.p));
1410     luaC_barrier(L, owner, val);
1411   }
1412   lua_unlock(L);
1413   return name;
1414 }
1415 
1416 
1417 static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) {
1418   static const UpVal *const nullup = NULL;
1419   LClosure *f;
1420   TValue *fi = index2value(L, fidx);
1421   api_check(L, ttisLclosure(fi), "Lua function expected");
1422   f = clLvalue(fi);
1423   if (pf) *pf = f;
1424   if (1 <= n && n <= f->p->sizeupvalues)
1425     return &f->upvals[n - 1];  /* get its upvalue pointer */
1426   else
1427     return (UpVal**)&nullup;
1428 }
1429 
1430 
1431 LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) {
1432   TValue *fi = index2value(L, fidx);
1433   switch (ttypetag(fi)) {
1434     case LUA_VLCL: {  /* lua closure */
1435       return *getupvalref(L, fidx, n, NULL);
1436     }
1437     case LUA_VCCL: {  /* C closure */
1438       CClosure *f = clCvalue(fi);
1439       if (1 <= n && n <= f->nupvalues)
1440         return &f->upvalue[n - 1];
1441       /* else */
1442     }  /* FALLTHROUGH */
1443     case LUA_VLCF:
1444       return NULL;  /* light C functions have no upvalues */
1445     default: {
1446       api_check(L, 0, "function expected");
1447       return NULL;
1448     }
1449   }
1450 }
1451 
1452 
1453 LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
1454                                             int fidx2, int n2) {
1455   LClosure *f1;
1456   UpVal **up1 = getupvalref(L, fidx1, n1, &f1);
1457   UpVal **up2 = getupvalref(L, fidx2, n2, NULL);
1458   api_check(L, *up1 != NULL && *up2 != NULL, "invalid upvalue index");
1459   *up1 = *up2;
1460   luaC_objbarrier(L, f1, *up1);
1461 }
1462 
1463 
1464