2024-07-17 12:39:44 +01:00
|
|
|
package internal
|
|
|
|
|
|
|
|
/*
|
2024-07-17 16:44:41 +01:00
|
|
|
#cgo CFLAGS: -Iluau/VM/include -I/usr/lib/gcc/x86_64-pc-linux-gnu/14.1.1/include
|
2024-07-18 13:15:33 +01:00
|
|
|
// #cgo LDFLAGS: -L${SRCDIR}/luau/cmake -lLuau.VM -lm -lstdc++
|
2024-07-17 12:39:44 +01:00
|
|
|
#include <lua.h>
|
|
|
|
#include <lualib.h>
|
|
|
|
#include <stdlib.h>
|
2024-07-17 16:44:41 +01:00
|
|
|
#include "clua.h"
|
2024-07-17 12:39:44 +01:00
|
|
|
|
|
|
|
// From https://golang-nuts.narkive.com/UsNENgyt/cgo-how-to-pass-string-to-char-array
|
|
|
|
static char** makeCharArray(int size) {
|
|
|
|
return calloc(sizeof(char*), size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setArrayString(char** a, char* s, int n) {
|
|
|
|
a[n] = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void freeCharArray(char** a, int size) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < size; i++)
|
|
|
|
free(a[i]);
|
|
|
|
free(a);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
import "C"
|
|
|
|
import "unsafe"
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
type LuaLReg C.luaL_Reg
|
2024-07-17 12:39:44 +01:00
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LRegister(L *LuaState, libname string, l *LuaLReg) {
|
2024-07-17 12:39:44 +01:00
|
|
|
clibname := C.CString(libname)
|
|
|
|
defer C.free(unsafe.Pointer(clibname))
|
|
|
|
|
|
|
|
C.luaL_register(L, clibname, (*C.luaL_Reg)(l))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LGetMetaField(L *LuaState, obj int32, e string) int32 {
|
2024-07-17 12:39:44 +01:00
|
|
|
ce := C.CString(e)
|
|
|
|
defer C.free(unsafe.Pointer(ce))
|
|
|
|
|
|
|
|
return int32(C.luaL_getmetafield(L, C.int(obj), ce))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCallMeta(L *LuaState, obj int32, e string) int32 {
|
2024-07-17 12:39:44 +01:00
|
|
|
ce := C.CString(e)
|
|
|
|
defer C.free(unsafe.Pointer(ce))
|
|
|
|
|
|
|
|
return int32(C.luaL_callmeta(L, C.int(obj), ce))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LTypeError(L *LuaState, narg int32, tname string) {
|
2024-07-17 12:39:44 +01:00
|
|
|
ctname := C.CString(tname)
|
|
|
|
defer C.free(unsafe.Pointer(ctname))
|
|
|
|
|
|
|
|
C.luaL_typeerrorL(L, C.int(narg), ctname)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LArgError(L *LuaState, narg int32, extramsg string) {
|
2024-07-17 12:39:44 +01:00
|
|
|
cextramsg := C.CString(extramsg)
|
|
|
|
defer C.free(unsafe.Pointer(cextramsg))
|
|
|
|
|
|
|
|
C.luaL_argerrorL(L, C.int(narg), cextramsg)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckLString(L *LuaState, narg int32, l *uint64) string {
|
2024-07-17 12:39:44 +01:00
|
|
|
p := C.luaL_checklstring(L, C.int(narg), (*C.size_t)(l))
|
|
|
|
defer C.free(unsafe.Pointer(p))
|
|
|
|
|
|
|
|
return C.GoString(p)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LOptLString(L *LuaState, narg int32, def string, l *uint64) string {
|
2024-07-17 12:39:44 +01:00
|
|
|
cdef := C.CString(def)
|
|
|
|
defer C.free(unsafe.Pointer(cdef))
|
|
|
|
|
|
|
|
p := C.luaL_optlstring(L, C.int(narg), cdef, (*C.ulong)(l))
|
|
|
|
defer C.free(unsafe.Pointer(p))
|
|
|
|
|
|
|
|
return C.GoString(p)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckNumber(L *LuaState, narg int32) LuaNumber {
|
|
|
|
return LuaNumber(C.luaL_checknumber(L, C.int(narg)))
|
2024-07-17 12:39:44 +01:00
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LOptNumber(L *LuaState, narg int32, def LuaNumber) LuaNumber {
|
|
|
|
return LuaNumber(C.luaL_optnumber(L, C.int(narg), C.lua_Number(def)))
|
2024-07-17 12:39:44 +01:00
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckBoolean(L *LuaState, narg int32) bool {
|
2024-07-17 12:39:44 +01:00
|
|
|
return C.luaL_checkboolean(L, C.int(narg)) != 0
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LOptBoolean(L *LuaState, narg int32, def bool) bool {
|
2024-07-17 12:39:44 +01:00
|
|
|
cdef := C.int(0)
|
|
|
|
if def {
|
|
|
|
cdef = C.int(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
return C.luaL_optboolean(L, C.int(narg), cdef) != 0
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckInteger(L *LuaState, narg int32) LuaInteger {
|
|
|
|
return LuaInteger(C.luaL_checkinteger(L, C.int(narg)))
|
2024-07-17 12:39:44 +01:00
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LOptInteger(L *LuaState, narg int32, def LuaInteger) LuaInteger {
|
|
|
|
return LuaInteger(C.luaL_optinteger(L, C.int(narg), C.lua_Integer(def)))
|
2024-07-17 12:39:44 +01:00
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckUnsigned(L *LuaState, narg int32) LuaUnsigned {
|
|
|
|
return LuaUnsigned(C.luaL_checkunsigned(L, C.int(narg)))
|
2024-07-17 12:39:44 +01:00
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LOptUnsigned(L *LuaState, narg int32, def LuaUnsigned) LuaUnsigned {
|
|
|
|
return LuaUnsigned(C.luaL_optunsigned(L, C.int(narg), C.lua_Unsigned(def)))
|
2024-07-17 12:39:44 +01:00
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckVector(L *LuaState, narg int32) *float32 {
|
2024-07-17 12:39:44 +01:00
|
|
|
return (*float32)(C.luaL_checkvector(L, C.int(narg)))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LOptVector(L *LuaState, narg int32, def *float32) *float32 {
|
2024-07-17 12:39:44 +01:00
|
|
|
return (*float32)(C.luaL_optvector(L, C.int(narg), (*C.float)(def)))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckStack(L *LuaState, sz int32, msg string) {
|
2024-07-17 12:39:44 +01:00
|
|
|
cmsg := C.CString(msg)
|
|
|
|
defer C.free(unsafe.Pointer(cmsg))
|
|
|
|
|
|
|
|
C.luaL_checkstack(L, C.int(sz), cmsg)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckType(L *LuaState, narg int32, t int32) {
|
2024-07-17 12:39:44 +01:00
|
|
|
C.luaL_checktype(L, C.int(narg), C.int(t))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckAny(L *LuaState, narg int32) {
|
2024-07-17 12:39:44 +01:00
|
|
|
C.luaL_checkany(L, C.int(narg))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LNewMetatable(L *LuaState, tname string) bool {
|
2024-07-17 12:39:44 +01:00
|
|
|
ctname := C.CString(tname)
|
|
|
|
defer C.free(unsafe.Pointer(ctname))
|
|
|
|
|
|
|
|
return C.luaL_newmetatable(L, ctname) != 0
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckUdata(L *LuaState, ud int32, tname string) unsafe.Pointer {
|
2024-07-17 12:39:44 +01:00
|
|
|
ctname := C.CString(tname)
|
|
|
|
defer C.free(unsafe.Pointer(ctname))
|
|
|
|
|
|
|
|
return C.luaL_checkudata(L, C.int(ud), ctname)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckBuffer(L *LuaState, narg int32, len *uint64) unsafe.Pointer {
|
2024-07-17 12:39:44 +01:00
|
|
|
return C.luaL_checkbuffer(L, C.int(narg), (*C.size_t)(len))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LWhere(L *LuaState, lvl int32) {
|
2024-07-17 12:39:44 +01:00
|
|
|
C.luaL_where(L, C.int(lvl))
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: It's not possible to pass varargs from Go->C via cgo, so instead we
|
|
|
|
// expect the user to format the message and hand it over to us, which we
|
|
|
|
// pass to luaL_errorL. This is an inconsistency with the actual C API, but
|
|
|
|
// there isn't really anything we can do.
|
2024-07-18 14:30:39 +01:00
|
|
|
func LErrorL(L *LuaState, msg string) {
|
2024-07-17 12:39:44 +01:00
|
|
|
cmsg := C.CString(msg)
|
|
|
|
defer C.free(unsafe.Pointer(cmsg))
|
|
|
|
|
|
|
|
C.cluaL_errorL(L, cmsg)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckOption(L *LuaState, narg int32, def string, lst []string) int32 {
|
2024-07-17 12:39:44 +01:00
|
|
|
cdef := C.CString(def)
|
|
|
|
defer C.free(unsafe.Pointer(cdef))
|
|
|
|
|
|
|
|
clst := C.makeCharArray(C.int(len(lst)))
|
|
|
|
defer C.freeCharArray(clst, C.int(len(lst)))
|
|
|
|
for i, s := range lst {
|
|
|
|
C.setArrayString(clst, C.CString(s), C.int(i))
|
|
|
|
}
|
|
|
|
|
|
|
|
return int32(C.luaL_checkoption(L, C.int(narg), cdef, clst))
|
|
|
|
}
|
2024-07-17 16:44:41 +01:00
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LToLString(L *LuaState, idx int32, len *uint64) string {
|
2024-07-17 16:44:41 +01:00
|
|
|
p := C.luaL_tolstring(L, C.int(idx), (*C.size_t)(len))
|
|
|
|
defer C.free(unsafe.Pointer(p))
|
|
|
|
|
|
|
|
return C.GoString(p)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LNewState() *LuaState {
|
2024-07-17 16:44:41 +01:00
|
|
|
return C.luaL_newstate()
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LTypeName(L *LuaState, idx int32) string {
|
2024-07-17 16:44:41 +01:00
|
|
|
return C.GoString(C.luaL_typename(L, C.int(idx)))
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LSandbox(L *LuaState) {
|
2024-07-17 16:44:41 +01:00
|
|
|
C.luaL_sandbox(L)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LSandboxThread(L *LuaState) {
|
2024-07-17 16:44:41 +01:00
|
|
|
C.luaL_sandboxthread(L)
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Some useful macros
|
|
|
|
//
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LArgCheck(L *LuaState, cond bool, arg int32, extramsg string) {
|
2024-07-17 16:44:41 +01:00
|
|
|
if cond {
|
|
|
|
LArgError(L, arg, extramsg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LArgExpected(L *LuaState, cond bool, arg int32, tname string) {
|
2024-07-17 16:44:41 +01:00
|
|
|
if cond {
|
|
|
|
LTypeError(L, arg, tname)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LCheckString(L *LuaState, n int32) string {
|
2024-07-17 16:44:41 +01:00
|
|
|
return LCheckLString(L, n, nil)
|
|
|
|
}
|
|
|
|
|
2024-07-18 14:30:39 +01:00
|
|
|
func LOptString(L *LuaState, n int32, d string) string {
|
2024-07-17 16:44:41 +01:00
|
|
|
return LOptLString(L, n, d, nil)
|
|
|
|
}
|
|
|
|
|
2024-07-21 08:11:38 +01:00
|
|
|
const (
|
|
|
|
LUA_COLIBNAME = "coroutine"
|
|
|
|
LUA_TABLIBNAME = "table"
|
|
|
|
LUA_OSLIBNAME = "os"
|
|
|
|
LUA_STRLIBNAME = "string"
|
|
|
|
LUA_BITLIBNAME = "bit32"
|
|
|
|
LUA_BUFFERLIBNAME = "buffer"
|
|
|
|
LUA_UTF8LIBNAME = "utf8"
|
|
|
|
LUA_MATHLIBNAME = "math"
|
|
|
|
LUA_DBLIBNAME = "debug"
|
|
|
|
)
|
|
|
|
|
|
|
|
func OpenBase(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_base(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenCoroutine(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_coroutine(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenTable(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_table(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenOS(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_os(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenString(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_string(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenBit32(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_bit32(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenBuffer(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_buffer(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenUtf8(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_utf8(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenMath(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_math(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenDebug(L *LuaState) int32 {
|
|
|
|
return int32(C.luaopen_debug(L))
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenLibs(L *LuaState) {
|
|
|
|
C.luaL_openlibs(L)
|
|
|
|
}
|
|
|
|
|
2024-07-17 16:44:41 +01:00
|
|
|
// TODO: More utility functions, buffer bindings
|