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