1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21#include "config.h"
22#include "runtime.h"
23
24// LOVE
25#include "Module.h"
26#include "Object.h"
27#include "Reference.h"
28#include "StringMap.h"
29
30// C++
31#include <algorithm>
32#include <iostream>
33#include <cstdint>
34#include <cstdio>
35#include <cstddef>
36#include <cmath>
37#include <sstream>
38
39// VS2013 doesn't support alignof
40#if defined(_MSC_VER) && _MSC_VER <= 1800
41#define LOVE_ALIGNOF(x) __alignof(x)
42#else
43#define LOVE_ALIGNOF(x) alignof(x)
44#endif
45
46namespace love
47{
48
49/**
50 * Called when an object is collected. The object is released
51 * once in this function, possibly deleting it.
52 **/
53static int w__gc(lua_State *L)
54{
55 Proxy *p = (Proxy *) lua_touserdata(L, 1);
56 if (p->object != nullptr)
57 {
58 p->object->release();
59 p->object = nullptr;
60 }
61 return 0;
62}
63
64static int w__tostring(lua_State *L)
65{
66 Proxy *p = (Proxy *) lua_touserdata(L, 1);
67 const char *typname = lua_tostring(L, lua_upvalueindex(1));
68 lua_pushfstring(L, "%s: %p", typname, p->object);
69 return 1;
70}
71
72static int w__type(lua_State *L)
73{
74 lua_pushvalue(L, lua_upvalueindex(1));
75 return 1;
76}
77
78static int w__typeOf(lua_State *L)
79{
80 Proxy *p = (Proxy *)lua_touserdata(L, 1);
81 Type *t = luax_type(L, 2);
82 if (!t)
83 luax_pushboolean(L, false);
84 else
85 luax_pushboolean(L, p->type->isa(*t));
86 return 1;
87}
88
89static int w__eq(lua_State *L)
90{
91 Proxy *p1 = (Proxy *)lua_touserdata(L, 1);
92 Proxy *p2 = (Proxy *)lua_touserdata(L, 2);
93 luax_pushboolean(L, p1->object == p2->object && p1->object != nullptr);
94 return 1;
95}
96
97typedef uint64 ObjectKey;
98
99static bool luax_isfulllightuserdatasupported(lua_State *L)
100{
101 // LuaJIT prior to commit e9af1abec542e6f9851ff2368e7f196b6382a44c doesn't
102 // support lightuserdata > 48 bits. This is not a problem with Android,
103 // Windows, macOS, and iOS as they'll use updated LuaJIT or won't use
104 // pointers > 48 bits, but this is not the case for Linux. So check for
105 // this capability first!
106 static bool checked = false;
107 static bool supported = false;
108
109 if (sizeof(void*) == 4)
110 // 32-bit platforms always supports full-lightuserdata.
111 return true;
112
113 if (!checked)
114 {
115 lua_pushcclosure(L, [](lua_State *L) -> int
116 {
117 // Try to push pointer with all bits set.
118 lua_pushlightuserdata(L, (void *) (~((size_t) 0)));
119 return 1;
120 }, 0);
121
122 supported = lua_pcall(L, 0, 1, 0) == 0;
123 checked = true;
124
125 lua_pop(L, 1);
126 }
127
128 return supported;
129}
130
131// For use with the love object pointer -> Proxy pointer registry.
132// Using the pointer directly via lightuserdata would be ideal, but LuaJIT
133// (before a commit to 2.1 in 2020) cannot use lightuserdata with more than 47
134// bits whereas some newer arm64 architectures allow pointers which use more
135// than that.
136static ObjectKey luax_computeloveobjectkey(lua_State *L, love::Object *object)
137{
138 // love objects should be allocated on the heap, and thus are subject
139 // to the alignment rules of operator new / malloc. Lua numbers (doubles)
140 // can store all possible integers up to 2^53. We can store pointers that
141 // use more than 53 bits if their alignment is guaranteed to be more than 1.
142 // For example an alignment requirement of 8 means we can shift the
143 // pointer's bits by 3. However, this is not always reliable on 32-bit platforms
144 // as can be seen in this bug report: https://github.com/love2d/love/issues/1916.
145 // It appears to be ABI violation. However it seems there's no reliable way to
146 // get the correct alignment pre-C++17. Consider that 32-bit pointer still fits
147 // in 2^53 range, it's perfectly fine to assume alignment of 1 there.
148 const size_t minalign = sizeof(void*) == 8 ? LOVE_ALIGNOF(std::max_align_t) : 1;
149 uintptr_t key = (uintptr_t) object;
150
151 if ((key & (minalign - 1)) != 0)
152 {
153 luaL_error(L, "Cannot push love object to Lua: unexpected alignment "
154 "(pointer is %p but alignment should be %d)", object, (int) minalign);
155 }
156
157 static const size_t shift = (size_t) log2(minalign);
158
159 key >>= shift;
160
161 return (ObjectKey) key;
162}
163
164static void luax_pushloveobjectkey(lua_State *L, ObjectKey key)
165{
166 // If full 64-bit lightuserdata is supported, always use that. Otherwise,
167 // if the key is smaller than 2^53 (which is integer precision for double
168 // datatype), then push number. Otherwise, throw error.
169 if (luax_isfulllightuserdatasupported(L))
170 lua_pushlightuserdata(L, (void *) key);
171 else if (key > 0x20000000000000ULL) // 2^53
172 luaL_error(L, "Cannot push love object to Lua: pointer value %p is too large", key);
173 else
174 lua_pushnumber(L, (lua_Number) key);
175}
176
177static int w__release(lua_State *L)
178{
179 Proxy *p = (Proxy *) lua_touserdata(L, 1);
180 Object *object = p->object;
181
182 if (object != nullptr)
183 {
184 p->object = nullptr;
185 object->release();
186
187 // Fetch the registry table of instantiated objects.
188 luax_getregistry(L, REGISTRY_OBJECTS);
189
190 if (lua_istable(L, -1))
191 {
192 // loveobjects[object] = nil
193 ObjectKey objectkey = luax_computeloveobjectkey(L, object);
194 luax_pushloveobjectkey(L, objectkey);
195 lua_pushnil(L);
196 lua_settable(L, -3);
197 }
198
199 lua_pop(L, 1);
200 }
201
202 luax_pushboolean(L, object != nullptr);
203 return 1;
204}
205
206Reference *luax_refif(lua_State *L, int type)
207{
208 Reference *r = nullptr;
209
210 // Create a reference only if the test succeeds.
211 if (lua_type(L, -1) == type)
212 r = new Reference(L);
213 else // Pop the value manually if it fails (done by Reference if it succeeds).
214 lua_pop(L, 1);
215
216 return r;
217}
218
219void luax_printstack(lua_State *L)
220{
221 for (int i = 1; i <= lua_gettop(L); i++)
222 std::cout << i << " - " << luaL_typename(L, i) << std::endl;
223}
224
225int luax_traceback(lua_State *L)
226{
227 if (!lua_isstring(L, 1)) // 'message' not a string?
228 return 1; // keep it intact
229
230 lua_getglobal(L, "debug");
231 if (!lua_istable(L, -1))
232 {
233 lua_pop(L, 1);
234 return 1;
235 }
236
237 lua_getfield(L, -1, "traceback");
238 if (!lua_isfunction(L, -1))
239 {
240 lua_pop(L, 2);
241 return 1;
242 }
243
244 lua_pushvalue(L, 1); // pass error message
245 lua_pushinteger(L, 2); // skip this function and traceback
246 lua_call(L, 2, 1); // call debug.traceback
247 return 1;
248}
249
250bool luax_isarrayoftables(lua_State *L, int idx)
251{
252 if (!lua_istable(L, idx))
253 return false;
254
255 lua_rawgeti(L, idx, 1);
256 bool tableoftables = lua_istable(L, -1);
257 lua_pop(L, 1);
258 return tableoftables;
259}
260
261bool luax_toboolean(lua_State *L, int idx)
262{
263 return (lua_toboolean(L, idx) != 0);
264}
265
266bool luax_checkboolean(lua_State *L, int idx)
267{
268 luaL_checktype(L, idx, LUA_TBOOLEAN);
269 return luax_toboolean(L, idx);
270}
271
272void luax_pushboolean(lua_State *L, bool b)
273{
274 lua_pushboolean(L, b ? 1 : 0);
275}
276
277bool luax_optboolean(lua_State *L, int idx, bool b)
278{
279 if (lua_isboolean(L, idx) == 1)
280 return (lua_toboolean(L, idx) == 1 ? true : false);
281 return b;
282}
283
284std::string luax_tostring(lua_State *L, int idx)
285{
286 size_t len;
287 const char *str = lua_tolstring(L, idx, &len);
288 return std::string(str, len);
289}
290
291std::string luax_checkstring(lua_State *L, int idx)
292{
293 size_t len;
294 const char *str = luaL_checklstring(L, idx, &len);
295 return std::string(str, len);
296}
297
298void luax_pushstring(lua_State *L, const std::string &str)
299{
300 lua_pushlstring(L, str.data(), str.size());
301}
302
303void luax_pushpointerasstring(lua_State *L, const void *pointer)
304{
305 char str[sizeof(void *)];
306 memcpy(str, &pointer, sizeof(void *));
307 lua_pushlstring(L, str, sizeof(void *));
308}
309
310bool luax_boolflag(lua_State *L, int table_index, const char *key, bool defaultValue)
311{
312 lua_getfield(L, table_index, key);
313
314 bool retval;
315 if (lua_isnoneornil(L, -1))
316 retval = defaultValue;
317 else
318 retval = lua_toboolean(L, -1) != 0;
319
320 lua_pop(L, 1);
321 return retval;
322}
323
324int luax_intflag(lua_State *L, int table_index, const char *key, int defaultValue)
325{
326 lua_getfield(L, table_index, key);
327
328 int retval;
329 if (!lua_isnumber(L, -1))
330 retval = defaultValue;
331 else
332 retval = (int) lua_tointeger(L, -1);
333
334 lua_pop(L, 1);
335 return retval;
336}
337
338double luax_numberflag(lua_State *L, int table_index, const char *key, double defaultValue)
339{
340 lua_getfield(L, table_index, key);
341
342 double retval;
343 if (!lua_isnumber(L, -1))
344 retval = defaultValue;
345 else
346 retval = lua_tonumber(L, -1);
347
348 lua_pop(L, 1);
349 return retval;
350}
351
352int luax_checkintflag(lua_State *L, int table_index, const char *key)
353{
354 lua_getfield(L, table_index, key);
355
356 int retval;
357 if (!lua_isnumber(L, -1))
358 {
359 std::string err = "expected integer field " + std::string(key) + " in table";
360 return luaL_argerror(L, table_index, err.c_str());
361 }
362 else
363 retval = (int) luaL_checkinteger(L, -1);
364 lua_pop(L, 1);
365
366 return retval;
367}
368
369int luax_assert_argc(lua_State *L, int min)
370{
371 int argc = lua_gettop(L);
372 if (argc < min)
373 return luaL_error(L, "Incorrect number of arguments. Got [%d], expected at least [%d]", argc, min);
374 return 0;
375}
376
377int luax_assert_argc(lua_State *L, int min, int max)
378{
379 int argc = lua_gettop(L);
380 if (argc < min || argc > max)
381 return luaL_error(L, "Incorrect number of arguments. Got [%d], expected [%d-%d]", argc, min, max);
382 return 0;
383}
384
385int luax_assert_function(lua_State *L, int idx)
386{
387 if (!lua_isfunction(L, idx))
388 return luaL_error(L, "Argument must be of type \"function\".");
389 return 0;
390}
391
392int luax_assert_nilerror(lua_State *L, int idx)
393{
394 if (lua_isnoneornil(L, idx))
395 {
396 if (lua_isstring(L, idx + 1))
397 return luaL_error(L, lua_tostring(L, idx + 1));
398 else
399 return luaL_error(L, "assertion failed!");
400 }
401 return 0;
402}
403
404void luax_setfuncs(lua_State *L, const luaL_Reg *l)
405{
406 if (l == nullptr)
407 return;
408
409 for (; l->name != nullptr; l++)
410 {
411 lua_pushcfunction(L, l->func);
412 lua_setfield(L, -2, l->name);
413 }
414}
415
416int luax_require(lua_State *L, const char *name)
417{
418 lua_getglobal(L, "require");
419 lua_pushstring(L, name);
420 lua_call(L, 1, 1);
421 return 1;
422}
423
424int luax_register_module(lua_State *L, const WrappedModule &m)
425{
426 m.type->init();
427
428 // Put a reference to the C++ module in Lua.
429 luax_insistregistry(L, REGISTRY_MODULES);
430
431 Proxy *p = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
432 p->object = m.module;
433 p->type = m.type;
434
435 luaL_newmetatable(L, m.module->getName());
436 lua_pushvalue(L, -1);
437 lua_setfield(L, -2, "__index");
438 lua_pushcfunction(L, w__gc);
439 lua_setfield(L, -2, "__gc");
440
441 lua_setmetatable(L, -2);
442 lua_setfield(L, -2, m.name); // _modules[name] = proxy
443 lua_pop(L, 1);
444
445 // Gets the love table.
446 luax_insistglobal(L, "love");
447
448 // Create new table for module.
449 lua_newtable(L);
450
451 // Register all the functions.
452 if (m.functions != nullptr)
453 luax_setfuncs(L, m.functions);
454
455 // Register types.
456 if (m.types != nullptr)
457 {
458 for (const lua_CFunction *t = m.types; *t != nullptr; t++)
459 (*t)(L);
460 }
461
462 lua_pushvalue(L, -1);
463 lua_setfield(L, -3, m.name); // love.graphics = table
464 lua_remove(L, -2); // love
465
466 // Register module instance
467 Module::registerInstance(m.module);
468
469 return 1;
470}
471
472int luax_preload(lua_State *L, lua_CFunction f, const char *name)
473{
474 lua_getglobal(L, "package");
475 lua_getfield(L, -1, "preload");
476 lua_pushcfunction(L, f);
477 lua_setfield(L, -2, name);
478 lua_pop(L, 2);
479 return 0;
480}
481
482int luax_register_type(lua_State *L, love::Type *type, ...)
483{
484 type->init();
485
486 // Get the place for storing and re-using instantiated love types.
487 luax_getregistry(L, REGISTRY_OBJECTS);
488
489 // Create registry._loveobjects if it doesn't exist yet.
490 if (!lua_istable(L, -1))
491 {
492 lua_newtable(L);
493 lua_replace(L, -2);
494
495 // Create a metatable.
496 lua_newtable(L);
497
498 // metatable.__mode = "v". Weak userdata values.
499 lua_pushliteral(L, "v");
500 lua_setfield(L, -2, "__mode");
501
502 // setmetatable(newtable, metatable)
503 lua_setmetatable(L, -2);
504
505 // registry._loveobjects = newtable
506 lua_setfield(L, LUA_REGISTRYINDEX, "_loveobjects");
507 }
508 else
509 lua_pop(L, 1);
510
511 luaL_newmetatable(L, type->getName());
512
513 // m.__index = m
514 lua_pushvalue(L, -1);
515 lua_setfield(L, -2, "__index");
516
517 // setup gc
518 lua_pushcfunction(L, w__gc);
519 lua_setfield(L, -2, "__gc");
520
521 // Add equality
522 lua_pushcfunction(L, w__eq);
523 lua_setfield(L, -2, "__eq");
524
525 // Add tostring function.
526 lua_pushstring(L, type->getName());
527 lua_pushcclosure(L, w__tostring, 1);
528 lua_setfield(L, -2, "__tostring");
529
530 // Add type
531 lua_pushstring(L, type->getName());
532 lua_pushcclosure(L, w__type, 1);
533 lua_setfield(L, -2, "type");
534
535 // Add typeOf
536 lua_pushcfunction(L, w__typeOf);
537 lua_setfield(L, -2, "typeOf");
538
539 // Add release
540 lua_pushcfunction(L, w__release);
541 lua_setfield(L, -2, "release");
542
543 va_list fs;
544 va_start(fs, type);
545 for (const luaL_Reg *f = va_arg(fs, const luaL_Reg *); f; f = va_arg(fs, const luaL_Reg *))
546 luax_setfuncs(L, f);
547 va_end(fs);
548
549 lua_pop(L, 1); // Pops metatable.
550 return 0;
551}
552
553void luax_gettypemetatable(lua_State *L, const love::Type &type)
554{
555 const char *name = type.getName();
556 lua_getfield(L, LUA_REGISTRYINDEX, name);
557}
558
559int luax_table_insert(lua_State *L, int tindex, int vindex, int pos)
560{
561 if (tindex < 0)
562 tindex = lua_gettop(L)+1+tindex;
563 if (vindex < 0)
564 vindex = lua_gettop(L)+1+vindex;
565
566 if (pos == -1)
567 {
568 lua_pushvalue(L, vindex);
569 lua_rawseti(L, tindex, (int) luax_objlen(L, tindex)+1);
570 return 0;
571 }
572 else if (pos < 0)
573 pos = (int) luax_objlen(L, tindex)+1+pos;
574
575 for (int i = (int) luax_objlen(L, tindex)+1; i > pos; i--)
576 {
577 lua_rawgeti(L, tindex, i-1);
578 lua_rawseti(L, tindex, i);
579 }
580
581 lua_pushvalue(L, vindex);
582 lua_rawseti(L, tindex, pos);
583 return 0;
584}
585
586int luax_register_searcher(lua_State *L, lua_CFunction f, int pos)
587{
588 // Add the package loader to the package.loaders table.
589 lua_getglobal(L, "package");
590
591 if (lua_isnil(L, -1))
592 return luaL_error(L, "Can't register searcher: package table does not exist.");
593
594 lua_getfield(L, -1, "loaders");
595
596 // Lua 5.2 renamed package.loaders to package.searchers.
597 if (lua_isnil(L, -1))
598 {
599 lua_pop(L, 1);
600 lua_getfield(L, -1, "searchers");
601 }
602
603 if (lua_isnil(L, -1))
604 return luaL_error(L, "Can't register searcher: package.loaders table does not exist.");
605
606 lua_pushcfunction(L, f);
607 luax_table_insert(L, -2, -1, pos);
608 lua_pop(L, 3);
609 return 0;
610}
611
612void luax_rawnewtype(lua_State *L, love::Type &type, love::Object *object)
613{
614 Proxy *u = (Proxy *)lua_newuserdata(L, sizeof(Proxy));
615
616 object->retain();
617
618 u->object = object;
619 u->type = &type;
620
621 const char *name = type.getName();
622 luaL_newmetatable(L, name);
623
624 lua_getfield(L, -1, "__gc");
625 bool has_gc = !lua_isnoneornil(L, -1);
626 lua_pop(L, 1);
627
628 // Make sure mt.__gc exists, so Lua states which don't have the object's
629 // module loaded will still clean the object up when it's collected.
630 if (!has_gc)
631 {
632 lua_pushcfunction(L, w__gc);
633 lua_setfield(L, -2, "__gc");
634 }
635
636 lua_setmetatable(L, -2);
637}
638
639void luax_pushtype(lua_State *L, love::Type &type, love::Object *object)
640{
641 if (object == nullptr)
642 {
643 lua_pushnil(L);
644 return;
645 }
646
647 // Fetch the registry table of instantiated objects.
648 luax_getregistry(L, REGISTRY_OBJECTS);
649
650 // The table might not exist - it should be insisted in luax_register_type.
651 if (lua_isnoneornil(L, -1))
652 {
653 lua_pop(L, 1);
654 return luax_rawnewtype(L, type, object);
655 }
656
657 ObjectKey objectkey = luax_computeloveobjectkey(L, object);
658
659 // Get the value of loveobjects[object] on the stack.
660 luax_pushloveobjectkey(L, objectkey);
661 lua_gettable(L, -2);
662
663 // If the Proxy userdata isn't in the instantiated types table yet, add it.
664 if (lua_type(L, -1) != LUA_TUSERDATA)
665 {
666 lua_pop(L, 1);
667
668 luax_rawnewtype(L, type, object);
669
670 luax_pushloveobjectkey(L, objectkey);
671 lua_pushvalue(L, -2);
672
673 // loveobjects[object] = Proxy.
674 lua_settable(L, -4);
675 }
676
677 // Remove the loveobjects table from the stack.
678 lua_remove(L, -2);
679
680 // Keep the Proxy userdata on the stack.
681}
682
683bool luax_istype(lua_State *L, int idx, love::Type &type)
684{
685 if (lua_type(L, idx) != LUA_TUSERDATA)
686 return false;
687
688 Proxy *p = (Proxy *) lua_touserdata(L, idx);
689
690 if (p->type != nullptr)
691 return p->type->isa(type);
692 else
693 return false;
694}
695
696int luax_getfunction(lua_State *L, const char *mod, const char *fn)
697{
698 lua_getglobal(L, "love");
699 if (lua_isnil(L, -1)) return luaL_error(L, "Could not find global love!");
700 lua_getfield(L, -1, mod);
701 if (lua_isnil(L, -1)) return luaL_error(L, "Could not find love.%s!", mod);
702 lua_getfield(L, -1, fn);
703 if (lua_isnil(L, -1)) return luaL_error(L, "Could not find love.%s.%s!", mod, fn);
704
705 lua_remove(L, -2); // remove mod
706 lua_remove(L, -2); // remove fn
707 return 0;
708}
709
710int luax_convobj(lua_State *L, int idx, const char *mod, const char *fn)
711{
712 // Convert to absolute index if necessary.
713 if (idx < 0 && idx > LUA_REGISTRYINDEX)
714 idx += lua_gettop(L) + 1;
715
716 // Convert string to a file.
717 luax_getfunction(L, mod, fn);
718 lua_pushvalue(L, idx); // The initial argument.
719 lua_call(L, 1, 2); // Call the function, one arg, one return value (plus optional errstring.)
720 luax_assert_nilerror(L, -2); // Make sure the function returned something.
721 lua_pop(L, 1); // Pop the second return value now that we don't need it.
722 lua_replace(L, idx); // Replace the initial argument with the new object.
723 return 0;
724}
725
726int luax_convobj(lua_State *L, const int idxs[], int n, const char *mod, const char *fn)
727{
728 luax_getfunction(L, mod, fn);
729 for (int i = 0; i < n; i++)
730 {
731 lua_pushvalue(L, idxs[i]); // The arguments.
732 }
733 lua_call(L, n, 2); // Call the function, n args, one return value (plus optional errstring.)
734 luax_assert_nilerror(L, -2); // Make sure the function returned something.
735 lua_pop(L, 1); // Pop the second return value now that we don't need it.
736 if (n > 0)
737 lua_replace(L, idxs[0]); // Replace the initial argument with the new object.
738 return 0;
739}
740
741int luax_convobj(lua_State *L, const std::vector<int>& idxs, const char *module, const char *function)
742{
743 const int *idxPtr = idxs.size() > 0 ? &idxs[0] : nullptr;
744 return luax_convobj(L, idxPtr, (int) idxs.size(), module, function);
745}
746
747int luax_pconvobj(lua_State *L, int idx, const char *mod, const char *fn)
748{
749 // Convert string to a file.
750 luax_getfunction(L, mod, fn);
751 lua_pushvalue(L, idx); // The initial argument.
752 int ret = lua_pcall(L, 1, 1, 0); // Call the function, one arg, one return value.
753 if (ret == 0)
754 lua_replace(L, idx); // Replace the initial argument with the new object.
755 return ret;
756}
757
758int luax_pconvobj(lua_State *L, const int idxs[], int n, const char *mod, const char *fn)
759{
760 luax_getfunction(L, mod, fn);
761 for (int i = 0; i < n; i++)
762 {
763 lua_pushvalue(L, idxs[i]); // The arguments.
764 }
765 int ret = lua_pcall(L, n, 1, 0); // Call the function, n args, one return value.
766 if (ret == 0)
767 lua_replace(L, idxs[0]); // Replace the initial argument with the new object.
768 return ret;
769}
770
771int luax_pconvobj(lua_State *L, const std::vector<int>& idxs, const char *module, const char *function)
772{
773 const int *idxPtr = idxs.size() > 0 ? &idxs[0] : nullptr;
774 return luax_pconvobj(L, idxPtr, (int) idxs.size(), module, function);
775}
776
777int luax_insist(lua_State *L, int idx, const char *k)
778{
779 // Convert to absolute index if necessary.
780 if (idx < 0 && idx > LUA_REGISTRYINDEX)
781 idx += lua_gettop(L) + 1;
782
783 lua_getfield(L, idx, k);
784
785 // Create if necessary.
786 if (!lua_istable(L, -1))
787 {
788 lua_pop(L, 1); // Pop the non-table.
789 lua_newtable(L);
790 lua_pushvalue(L, -1); // Duplicate the table to leave on top.
791 lua_setfield(L, idx, k); // lua_stack[idx][k] = lua_stack[-1] (table)
792 }
793
794 return 1;
795}
796
797int luax_insistglobal(lua_State *L, const char *k)
798{
799 lua_getglobal(L, k);
800
801 if (!lua_istable(L, -1))
802 {
803 lua_pop(L, 1); // Pop the non-table.
804 lua_newtable(L);
805 lua_pushvalue(L, -1);
806 lua_setglobal(L, k);
807 }
808
809 return 1;
810}
811
812int luax_c_insistglobal(lua_State *L, const char *k)
813{
814 return luax_insistglobal(L, k);
815}
816
817int luax_insistlove(lua_State *L, const char *k)
818{
819 luax_insistglobal(L, "love");
820 luax_insist(L, -1, k);
821
822 // The love table should be replaced with the top stack
823 // item. Only the reqested table should remain on the stack.
824 lua_replace(L, -2);
825
826 return 1;
827}
828
829int luax_getlove(lua_State *L, const char *k)
830{
831 lua_getglobal(L, "love");
832
833 if (!lua_isnil(L, -1))
834 {
835 lua_getfield(L, -1, k);
836 lua_replace(L, -2);
837 }
838
839 return 1;
840}
841
842int luax_insistregistry(lua_State *L, Registry r)
843{
844 switch (r)
845 {
846 case REGISTRY_MODULES:
847 return luax_insistlove(L, "_modules");
848 case REGISTRY_OBJECTS:
849 return luax_insist(L, LUA_REGISTRYINDEX, "_loveobjects");
850 default:
851 return luaL_error(L, "Attempted to use invalid registry.");
852 }
853}
854
855int luax_getregistry(lua_State *L, Registry r)
856{
857 switch (r)
858 {
859 case REGISTRY_MODULES:
860 return luax_getlove(L, "_modules");
861 case REGISTRY_OBJECTS:
862 lua_getfield(L, LUA_REGISTRYINDEX, "_loveobjects");
863 return 1;
864 default:
865 return luaL_error(L, "Attempted to use invalid registry.");
866 }
867}
868
869static const char *MAIN_THREAD_KEY = "_love_mainthread";
870
871lua_State *luax_insistpinnedthread(lua_State *L)
872{
873 lua_getfield(L, LUA_REGISTRYINDEX, MAIN_THREAD_KEY);
874
875 if (lua_isnoneornil(L, -1))
876 {
877 lua_pop(L, 1);
878
879 // lua_pushthread returns 1 if it's actually the main thread, but we
880 // can't actually get the real main thread if lua_pushthread doesn't
881 // return it (in Lua 5.1 at least), so we ignore that for now...
882 // We do store a strong reference to the current thread/coroutine in
883 // the registry, however.
884 lua_pushthread(L);
885 lua_pushvalue(L, -1);
886 lua_setfield(L, LUA_REGISTRYINDEX, MAIN_THREAD_KEY);
887 }
888
889 lua_State *thread = lua_tothread(L, -1);
890 lua_pop(L, 1);
891 return thread;
892}
893
894lua_State *luax_getpinnedthread(lua_State *L)
895{
896 lua_getfield(L, LUA_REGISTRYINDEX, MAIN_THREAD_KEY);
897 lua_State *thread = lua_tothread(L, -1);
898 lua_pop(L, 1);
899 return thread;
900}
901
902void luax_markdeprecated(lua_State *L, const char *name, APIType api)
903{
904 luax_markdeprecated(L, name, api, DEPRECATED_NO_REPLACEMENT, nullptr);
905}
906
907void luax_markdeprecated(lua_State *L, const char *name, APIType api, DeprecationType type, const char *replacement)
908{
909 MarkDeprecated deprecated(name, api, type, replacement);
910
911 if (deprecated.info != nullptr && deprecated.info->uses == 1)
912 {
913 luaL_where(L, 1);
914 const char *where = lua_tostring(L, -1);
915 if (where != nullptr)
916 deprecated.info->where = where;
917 lua_pop(L, 1);
918 }
919}
920
921extern "C" int luax_typerror(lua_State *L, int narg, const char *tname)
922{
923 int argtype = lua_type(L, narg);
924 const char *argtname = nullptr;
925
926 // We want to use the love type name for userdata, if possible.
927 if (argtype == LUA_TUSERDATA && luaL_getmetafield(L, narg, "type") != 0)
928 {
929 lua_pushvalue(L, narg);
930 if (lua_pcall(L, 1, 1, 0) == 0 && lua_type(L, -1) == LUA_TSTRING)
931 {
932 argtname = lua_tostring(L, -1);
933
934 // Non-love userdata might have a type metamethod which doesn't
935 // describe its type properly, so we only use it for love types.
936 if (!Type::byName(argtname))
937 argtname = nullptr;
938 }
939 }
940
941 if (argtname == nullptr)
942 argtname = lua_typename(L, argtype);
943
944 const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, argtname);
945 return luaL_argerror(L, narg, msg);
946}
947
948int luax_enumerror(lua_State *L, const char *enumName, const char *value)
949{
950 return luaL_error(L, "Invalid %s: %s", enumName, value);
951}
952
953int luax_enumerror(lua_State *L, const char *enumName, const std::vector<std::string> &values, const char *value)
954{
955 std::stringstream valueStream;
956 bool first = true;
957 for (auto value : values)
958 {
959 valueStream << (first ? "'" : ", '") << value << "'";
960 first = false;
961 }
962
963 std::string valueString = valueStream.str();
964 return luaL_error(L, "Invalid %s '%s', expected one of: %s", enumName, value, valueString.c_str());
965}
966
967size_t luax_objlen(lua_State *L, int ndx)
968{
969#if LUA_VERSION_NUM == 501
970 return lua_objlen(L, ndx);
971#else
972 return lua_rawlen(L, ndx);
973#endif
974}
975
976void luax_register(lua_State *L, const char *name, const luaL_Reg *l)
977{
978 if (name)
979 lua_newtable(L);
980
981 luax_setfuncs(L, l);
982 if (name)
983 {
984 lua_pushvalue(L, -1);
985 lua_setglobal(L, name);
986 }
987}
988
989void luax_runwrapper(lua_State *L, const char *filedata, size_t datalen, const char *filename, const love::Type &type, void *ffifuncs)
990{
991 luax_gettypemetatable(L, type);
992
993 // Load and execute the given Lua file, sending the metatable and the ffi
994 // functions struct pointer as arguments.
995 if (lua_istable(L, -1))
996 {
997 std::string chunkname = std::string("=[love \"") + std::string(filename) + std::string("\"]");
998
999 luaL_loadbuffer(L, filedata, datalen, chunkname.c_str());
1000 lua_pushvalue(L, -2);
1001 if (ffifuncs != nullptr)
1002 luax_pushpointerasstring(L, ffifuncs);
1003 else
1004 lua_pushnil(L);
1005 lua_call(L, 2, 0);
1006 }
1007
1008 // Pop the metatable.
1009 lua_pop(L, 1);
1010}
1011
1012Type *luax_type(lua_State *L, int idx)
1013{
1014 return Type::byName(luaL_checkstring(L, idx));
1015}
1016
1017int luax_resume(lua_State *L, int nargs, int* nres)
1018{
1019#if LUA_VERSION_NUM >= 504
1020 return lua_resume(L, nullptr, nargs, nres);
1021#elif LUA_VERSION_NUM >= 502
1022 LOVE_UNUSED(nres);
1023 return lua_resume(L, nullptr, nargs);
1024#else
1025 LOVE_UNUSED(nres);
1026 return lua_resume(L, nargs);
1027#endif
1028}
1029
1030} // love
1031