From 01659158a423dc292ff818369685329173bc394d Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Sun, 20 Mar 2011 11:46:27 +0100 Subject: [PATCH 001/100] setting an execution limit to lua code in terms of number of instructions executed --- lua51/golua.c | 11 +++++++++++ lua51/golua.h | 3 +-- lua51/lua.go | 5 ++++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/lua51/golua.c b/lua51/golua.c index c8ad53e3..46f68568 100644 --- a/lua51/golua.c +++ b/lua51/golua.c @@ -220,3 +220,14 @@ void clua_openos(lua_State* L){ lua_pushstring(L,"os"); lua_call(L, 1, 0); } + +void clua_hook_function(lua_State *L, lua_Debug *ar) { + lua_checkstack(L, 2); + lua_pushstring(L, "Lua execution quantum exceeded"); + lua_error(L); +} + +void clua_setexecutionlimit(lua_State* L, int n) { + lua_sethook(L, &clua_hook_function, LUA_MASKCOUNT, n); +} + diff --git a/lua51/golua.h b/lua51/golua.h index ec60e836..d5616137 100644 --- a/lua51/golua.h +++ b/lua51/golua.h @@ -22,5 +22,4 @@ void clua_openpackage(lua_State* L); void clua_openstring(lua_State* L); void clua_opentable(lua_State* L); void clua_openos(lua_State* L); - - +void clua_setexecutionlimit(lua_State* L, int n); diff --git a/lua51/lua.go b/lua51/lua.go index 9cb9e647..edb04866 100644 --- a/lua51/lua.go +++ b/lua51/lua.go @@ -184,7 +184,6 @@ func (L *State) AtPanic(panicf GoFunction) (oldpanicf GoFunction) { return nil; } - func (L *State) Call(nargs int, nresults int) { C.lua_call(L.s,C.int(nargs),C.int(nresults)); } @@ -518,3 +517,7 @@ func (L *State) OpenTable() { func (L *State) OpenOS() { C.clua_openos(L.s); } + +func (L *State) SetExecutionLimit(instrNumber int) { + C.clua_setexecutionlimit(L.s, C.int(instrNumber)); +} From c0e50eaacbb4ebe8468541e77575213ce096f214 Mon Sep 17 00:00:00 2001 From: ddzuk Date: Thu, 8 Sep 2011 15:37:01 +0200 Subject: [PATCH 002/100] updated to compile on last go release (r60, 20110908) --- lua51/golua.c | 8 +++---- lua51/lua.go | 8 +++---- lua51/lua_defs.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 lua51/lua_defs.go diff --git a/lua51/golua.c b/lua51/golua.c index 46f68568..f4869850 100644 --- a/lua51/golua.c +++ b/lua51/golua.c @@ -123,7 +123,7 @@ int callback_panicf(lua_State* L) unsigned int fid = lua_tointeger(L,-1); lua_pop(L,1); GoInterface* gi = clua_getgostate(L); - return golua_callpanicfunction(*gi,fid); + return callpanicfunction(*gi,fid); } @@ -150,12 +150,12 @@ GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id) //make a GoInterface with a wrapped C panicf or the original go panicf if(pf == &callback_panicf) { - return golua_idtointerface(old_id); + return idtointerface(old_id); } else { //TODO: technically UB, function ptr -> non function ptr - return golua_cfunctiontointerface((int*)pf); + return cfunctiontointerface((int*)pf); } } @@ -166,7 +166,7 @@ int clua_callluacfunc(lua_State* L, lua_CFunction f) void* allocwrapper(void* ud, void *ptr, size_t osize, size_t nsize) { - return (void*)golua_callallocf((uintptr)ud,(uintptr)ptr,osize,nsize); + return (void*)callAllocf((uintptr)ud,(uintptr)ptr,osize,nsize); } lua_State* clua_newstate(void* goallocf) diff --git a/lua51/lua.go b/lua51/lua.go index edb04866..a6e90c63 100644 --- a/lua51/lua.go +++ b/lua51/lua.go @@ -105,19 +105,19 @@ func golua_gchook(L interface{}, id uint) int { return 0; } -//export golua_callpanicfunction +//export callpanicfunction func callpanicfunction(L interface{}, id uint) int { L1 := L.(*State); f := L1.registry[id].(GoFunction); return f(L1); } -//export golua_idtointerface +//export idtointerface func idtointerface(id uint) interface{} { return id; } -//export golua_cfunctiontointerface +//export cfunctiontointerface func cfunctiontointerface(f *uintptr) interface{} { return f; } @@ -156,7 +156,7 @@ func (L *State) NewUserdata(size uintptr) unsafe.Pointer { type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer; -//export golua_callallocf +//export callAllocf func callAllocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr),osize,nsize)); diff --git a/lua51/lua_defs.go b/lua51/lua_defs.go new file mode 100644 index 00000000..0985fb2d --- /dev/null +++ b/lua51/lua_defs.go @@ -0,0 +1,59 @@ +package lua51; +//#include + //#include + //#include + import "C" +const LUA_VERSION = C.LUA_VERSION +const LUA_RELEASE = C.LUA_RELEASE +const LUA_VERSION_NUM = C.LUA_VERSION_NUM +const LUA_COPYRIGHT = C.LUA_COPYRIGHT +const LUA_AUTHORS = C.LUA_AUTHORS +const LUA_MULTRET = C.LUA_MULTRET +const LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX +const LUA_ENVIRONINDEX = C.LUA_ENVIRONINDEX +const LUA_GLOBALSINDEX = C.LUA_GLOBALSINDEX +const LUA_YIELD = C.LUA_YIELD +const LUA_ERRRUN = C.LUA_ERRRUN +const LUA_ERRSYNTAX = C.LUA_ERRSYNTAX +const LUA_ERRMEM = C.LUA_ERRMEM +const LUA_ERRERR = C.LUA_ERRERR +const LUA_TNONE = C.LUA_TNONE +const LUA_TNIL = C.LUA_TNIL +const LUA_TBOOLEAN = C.LUA_TBOOLEAN +const LUA_TLIGHTUSERDATA = C.LUA_TLIGHTUSERDATA +const LUA_TNUMBER = C.LUA_TNUMBER +const LUA_TSTRING = C.LUA_TSTRING +const LUA_TTABLE = C.LUA_TTABLE +const LUA_TFUNCTION = C.LUA_TFUNCTION +const LUA_TUSERDATA = C.LUA_TUSERDATA +const LUA_TTHREAD = C.LUA_TTHREAD +const LUA_MINSTACK = C.LUA_MINSTACK +const LUA_GCSTOP = C.LUA_GCSTOP +const LUA_GCRESTART = C.LUA_GCRESTART +const LUA_GCCOLLECT = C.LUA_GCCOLLECT +const LUA_GCCOUNT = C.LUA_GCCOUNT +const LUA_GCCOUNTB = C.LUA_GCCOUNTB +const LUA_GCSTEP = C.LUA_GCSTEP +const LUA_GCSETPAUSE = C.LUA_GCSETPAUSE +const LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL +const LUA_HOOKCALL = C.LUA_HOOKCALL +const LUA_HOOKRET = C.LUA_HOOKRET +const LUA_HOOKLINE = C.LUA_HOOKLINE +const LUA_HOOKCOUNT = C.LUA_HOOKCOUNT +const LUA_HOOKTAILRET = C.LUA_HOOKTAILRET +const LUA_MASKCALL = C.LUA_MASKCALL +const LUA_MASKRET = C.LUA_MASKRET +const LUA_MASKLINE = C.LUA_MASKLINE +const LUA_MASKCOUNT = C.LUA_MASKCOUNT +const LUA_ERRFILE = C.LUA_ERRFILE +const LUA_NOREF = C.LUA_NOREF +const LUA_REFNIL = C.LUA_REFNIL +const LUA_FILEHANDLE = C.LUA_FILEHANDLE +const LUA_COLIBNAME = C.LUA_COLIBNAME +const LUA_TABLIBNAME = C.LUA_TABLIBNAME +const LUA_IOLIBNAME = C.LUA_IOLIBNAME +const LUA_OSLIBNAME = C.LUA_OSLIBNAME +const LUA_STRLIBNAME = C.LUA_STRLIBNAME +const LUA_MATHLIBNAME = C.LUA_MATHLIBNAME +const LUA_DBLIBNAME = C.LUA_DBLIBNAME +const LUA_LOADLIBNAME = C.LUA_LOADLIBNAME From 4ae26385f4d2d37addaebb31ba235137c39f25ff Mon Sep 17 00:00:00 2001 From: ddzuk Date: Fri, 30 Sep 2011 11:52:38 +0200 Subject: [PATCH 003/100] better way to make this compile with release (thanks to vase / v.tolstov@selfip.ru) --- lua51/golua.c | 8 ++++---- lua51/lua.go | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lua51/golua.c b/lua51/golua.c index f4869850..46f68568 100644 --- a/lua51/golua.c +++ b/lua51/golua.c @@ -123,7 +123,7 @@ int callback_panicf(lua_State* L) unsigned int fid = lua_tointeger(L,-1); lua_pop(L,1); GoInterface* gi = clua_getgostate(L); - return callpanicfunction(*gi,fid); + return golua_callpanicfunction(*gi,fid); } @@ -150,12 +150,12 @@ GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id) //make a GoInterface with a wrapped C panicf or the original go panicf if(pf == &callback_panicf) { - return idtointerface(old_id); + return golua_idtointerface(old_id); } else { //TODO: technically UB, function ptr -> non function ptr - return cfunctiontointerface((int*)pf); + return golua_cfunctiontointerface((int*)pf); } } @@ -166,7 +166,7 @@ int clua_callluacfunc(lua_State* L, lua_CFunction f) void* allocwrapper(void* ud, void *ptr, size_t osize, size_t nsize) { - return (void*)callAllocf((uintptr)ud,(uintptr)ptr,osize,nsize); + return (void*)golua_callallocf((uintptr)ud,(uintptr)ptr,osize,nsize); } lua_State* clua_newstate(void* goallocf) diff --git a/lua51/lua.go b/lua51/lua.go index a6e90c63..416c3119 100644 --- a/lua51/lua.go +++ b/lua51/lua.go @@ -105,20 +105,20 @@ func golua_gchook(L interface{}, id uint) int { return 0; } -//export callpanicfunction -func callpanicfunction(L interface{}, id uint) int { +//export golua_callpanicfunction +func golua_callpanicfunction(L interface{}, id uint) int { L1 := L.(*State); f := L1.registry[id].(GoFunction); return f(L1); } -//export idtointerface -func idtointerface(id uint) interface{} { +//export golua_idtointerface +func golua_idtointerface(id uint) interface{} { return id; } -//export cfunctiontointerface -func cfunctiontointerface(f *uintptr) interface{} { +//export golua_cfunctiontointerface +func golua_cfunctiontointerface(f *uintptr) interface{} { return f; } @@ -156,8 +156,8 @@ func (L *State) NewUserdata(size uintptr) unsafe.Pointer { type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer; -//export callAllocf -func callAllocf(fp uintptr, ptr uintptr, +//export golua_callallocf +func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr),osize,nsize)); } From c8b077a7f44a15386759d094588ef30e3019fd50 Mon Sep 17 00:00:00 2001 From: ddzuk Date: Fri, 30 Sep 2011 12:06:36 +0200 Subject: [PATCH 004/100] Vasily (v.tolstov@selfip.ru) patch to Makefile --- lua51/Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lua51/Makefile b/lua51/Makefile index 8b95a45d..9480796d 100644 --- a/lua51/Makefile +++ b/lua51/Makefile @@ -7,7 +7,7 @@ include $(GOROOT)/src/Make.inc CGO_OFILES+=golua.o ifndef LUA51_LIBNAME -LUA51_LIBNAME=lua5.1 +LUA51_LIBNAME=$(shell pkg-config --print-provides lua | cut -d ' ' -f1) endif ifndef LUA51_INCLUDE_DIR @@ -34,7 +34,7 @@ CLEANFILES+=lua_defs.go LUA_HEADERS=lua.h lauxlib.h lualib.h LUA_HEADER_FILES:=$(patsubst %,$(LUA51_INCLUDE_DIR)/%,$(LUA_HEADERS)) -LUA_INCLUDE_DIRECTIVES:=$(patsubst %,//\#include <%>\n, $(LUA_HEADERS)) +LUA_INCLUDE_DIRECTIVES:=$(patsubst %,\#include <%>\n, $(LUA_HEADERS)) include $(GOROOT)/src/Make.pkg @@ -48,7 +48,8 @@ golua.o: golua.c lua_defs.go: echo "package lua51;" > lua_defs.go - echo "$(LUA_INCLUDE_DIRECTIVES)" "import \"C\"" >> lua_defs.go -# echo "import \"C\"" >> lua_defs.go + echo "/*" >> lua_defs.go + echo -e "$(LUA_INCLUDE_DIRECTIVES)" >> lua_defs.go + echo "*/" >> lua_defs.go + echo "import \"C\"" >> lua_defs.go cat $(LUA_HEADER_FILES) | grep '#define LUA' | sed 's/#define/const/' | sed 's/\([A-Z_][A-Z_]*\)[\t ].*/\1 = C.\1/' >> lua_defs.go - From 47aebd092abfb9ec71e0f9d4835520e768d7d6e8 Mon Sep 17 00:00:00 2001 From: ddzuk Date: Fri, 30 Sep 2011 12:09:23 +0200 Subject: [PATCH 005/100] changes to make the previous patch work on my system: - whatever echo make invoked automatically didn't have the -e flag (forced it to use GNU's echo at /bin/echo) - falling back to lua5.1 for LUA51_LIBNAME when pkg-config doesn't return anything for "--print-provides lua" --- lua51/Makefile | 4 ++-- lua51/lua_defs.go | 11 +++++++---- luaver.sh | 9 +++++++++ 3 files changed, 18 insertions(+), 6 deletions(-) create mode 100755 luaver.sh diff --git a/lua51/Makefile b/lua51/Makefile index 9480796d..9107032a 100644 --- a/lua51/Makefile +++ b/lua51/Makefile @@ -7,7 +7,7 @@ include $(GOROOT)/src/Make.inc CGO_OFILES+=golua.o ifndef LUA51_LIBNAME -LUA51_LIBNAME=$(shell pkg-config --print-provides lua | cut -d ' ' -f1) +LUA51_LIBNAME=$(shell ../luaver.sh) endif ifndef LUA51_INCLUDE_DIR @@ -49,7 +49,7 @@ golua.o: golua.c lua_defs.go: echo "package lua51;" > lua_defs.go echo "/*" >> lua_defs.go - echo -e "$(LUA_INCLUDE_DIRECTIVES)" >> lua_defs.go + /bin/echo -e "$(LUA_INCLUDE_DIRECTIVES)" >> lua_defs.go echo "*/" >> lua_defs.go echo "import \"C\"" >> lua_defs.go cat $(LUA_HEADER_FILES) | grep '#define LUA' | sed 's/#define/const/' | sed 's/\([A-Z_][A-Z_]*\)[\t ].*/\1 = C.\1/' >> lua_defs.go diff --git a/lua51/lua_defs.go b/lua51/lua_defs.go index 0985fb2d..de677158 100644 --- a/lua51/lua_defs.go +++ b/lua51/lua_defs.go @@ -1,8 +1,11 @@ package lua51; -//#include - //#include - //#include - import "C" +/* +#include + #include + #include + +*/ +import "C" const LUA_VERSION = C.LUA_VERSION const LUA_RELEASE = C.LUA_RELEASE const LUA_VERSION_NUM = C.LUA_VERSION_NUM diff --git a/luaver.sh b/luaver.sh new file mode 100755 index 00000000..cfc4b250 --- /dev/null +++ b/luaver.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +LUAVER=$(pkg-config --print-provides lua | cut -d ' ' -f1) + +if test "$LUAVER" = ""; then + LUAVER=lua5.1 +fi + +echo $LUAVER From cc9f0084fe179e82418490c0a831fdbd93f4fc65 Mon Sep 17 00:00:00 2001 From: "James D. Nurmi" Date: Wed, 6 Jul 2011 09:52:40 -0700 Subject: [PATCH 006/100] Clean up some memory leaks in initialization. --- lua51/golua.c | 2 +- lua51/lauxlib.go | 58 +++++++++++++++++++++++++++++++++++++----------- lua51/lua.go | 20 +++++++++++------ 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/lua51/golua.c b/lua51/golua.c index 46f68568..b2b1dc14 100644 --- a/lua51/golua.c +++ b/lua51/golua.c @@ -46,7 +46,7 @@ int gchook_wrapper(lua_State* L) GoInterface* gi = clua_getgostate(L); if(fid != NULL) return golua_gchook(*gi,*fid); - + printf("GCHook failed\n"); //TODO: try udata or whatever, after impl return 0; diff --git a/lua51/lauxlib.go b/lua51/lauxlib.go index 2503fdb7..85e66986 100644 --- a/lua51/lauxlib.go +++ b/lua51/lauxlib.go @@ -3,6 +3,7 @@ package lua51 //#include //#include //#include +//#include //#include "golua.h" import "C" import "unsafe" @@ -14,12 +15,16 @@ import "unsafe" func ArgCheck(L *State, cond bool, narg int, extramsg string) { if cond { - C.luaL_argerror(L.s, C.int(narg), C.CString(extramsg)); + Cextramsg := C.CString(extramsg) + defer C.free(unsafe.Pointer(Cextramsg)) + C.luaL_argerror(L.s, C.int(narg), Cextramsg) } } func ArgError(L *State, narg int, extramsg string) int { - return int(C.luaL_argerror(L.s,C.int(narg),C.CString(extramsg))); + Cextramsg := C.CString(extramsg) + defer C.free(unsafe.Pointer(Cextramsg)) + return int(C.luaL_argerror(L.s,C.int(narg),Cextramsg)); } //type luaL_Buffer @@ -27,7 +32,9 @@ func ArgError(L *State, narg int, extramsg string) int { //luaL_buffinit func CallMeta(L *State, obj int, e string) int { - return int(C.luaL_callmeta(L.s,C.int(obj),C.CString(e))); + Ce := C.CString(e) + defer C.free(unsafe.Pointer(Ce)) + return int(C.luaL_callmeta(L.s,C.int(obj),Ce)) } func CheckAny(L *State, narg int) { @@ -55,8 +62,11 @@ func CheckOption(L *State, narg int, def string, lst []string) int { func CheckType(L *State, narg int, t int) { C.luaL_checktype(L.s,C.int(narg),C.int(t)); } + func CheckUdata(L *State, narg int, tname string) unsafe.Pointer { - return unsafe.Pointer(C.luaL_checkudata(L.s,C.int(narg),C.CString(tname))); + Ctname := C.CString(tname) + defer C.free(unsafe.Pointer(Ctname)) + return unsafe.Pointer(C.luaL_checkudata(L.s,C.int(narg),Ctname)) } //true if no errors, false otherwise @@ -83,33 +93,51 @@ func FmtError(L *State, fmt string, args...interface{}) int { //returns false if no such metatable or no such field func GetMetaField(L *State, obj int, e string) bool { - return C.luaL_getmetafield(L.s,C.int(obj),C.CString(e)) != 0; + Ce := C.CString(e) + defer C.free(unsafe.Pointer(Ce)) + return C.luaL_getmetafield(L.s,C.int(obj),Ce) != 0; } //TODO: rename better... clashes with lua_getmetatable func LGetMetaTable(L *State, tname string) { - //C.luaL_getmetatable(L.s,C.CString(tname)); - C.lua_getfield(L.s,LUA_REGISTRYINDEX,C.CString(tname)); + Ctname := C.CString(tname) + defer C.free(unsafe.Pointer(Ctname)) + C.lua_getfield(L.s,LUA_REGISTRYINDEX,Ctname); } func GSub(L *State, s string, p string, r string) string { - return C.GoString(C.luaL_gsub(L.s, C.CString(s), C.CString(p), C.CString(r))); + Cs := C.CString(s) + Cp := C.CString(p) + Cr := C.CString(r) + defer func(){ + C.free(unsafe.Pointer(Cs)) + C.free(unsafe.Pointer(Cp)) + C.free(unsafe.Pointer(Cr)) + }() + + return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) } //TODO: luaL_loadbuffer func (L *State) LoadFile(filename string) int { - return int(C.luaL_loadfile(L.s,C.CString(filename))); + Cfilename := C.CString(filename) + defer C.free(unsafe.Pointer(Cfilename)) + return int(C.luaL_loadfile(L.s,Cfilename)); } func (L *State) LoadString(s string) int { - return int(C.luaL_loadstring(L.s,C.CString(s))); + Cs := C.CString(s) + defer C.free(unsafe.Pointer(Cs)) + return int(C.luaL_loadstring(L.s,Cs)) } //returns false if registry already contains key tname func (L *State) NewMetaTable(tname string) bool { - return C.luaL_newmetatable(L.s, C.CString(tname)) != 0; + Ctname := C.CString(tname) + defer C.free(unsafe.Pointer(Ctname)) + return C.luaL_newmetatable(L.s, Ctname) != 0; } func NewState() *State { @@ -132,7 +160,9 @@ func (L *State) OptNumber(narg int, d float64) float64 { func (L *State) OptString(narg int, d string) string { var length C.size_t; - return C.GoString(C.luaL_optlstring(L.s,C.int(narg),C.CString(d),&length)); + Cd := C.CString(d) + defer C.free(unsafe.Pointer(Cd)) + return C.GoString(C.luaL_optlstring(L.s,C.int(narg),Cd,&length)); } //luaL_prepbuffer @@ -150,7 +180,9 @@ func LTypename(L *State, index int) string { //TODO: decide if we actually want this renamed func TypeError(L *State, narg int, tname string) int { - return int(C.luaL_typerror(L.s,C.int(narg),C.CString(tname))); + Ctname := C.CString(tname) + defer C.free(unsafe.Pointer(Ctname)) + return int(C.luaL_typerror(L.s,C.int(narg),Ctname)) } func Unref(L *State, t int, ref int) { diff --git a/lua51/lua.go b/lua51/lua.go index 416c3119..fbadac01 100644 --- a/lua51/lua.go +++ b/lua51/lua.go @@ -2,11 +2,10 @@ package lua51 //#include //#include "golua.h" +//#include import "C" import "unsafe" -//TODO: remove -import "fmt" @@ -101,7 +100,6 @@ func golua_callgofunction(L interface{}, fid uint) int { func golua_gchook(L interface{}, id uint) int { L1 := L.(*State); L1.unregister(id); - fmt.Printf("GC id: %d\n",id); return 0; } @@ -227,7 +225,9 @@ func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } func (L *State) GetField(index int, k string) { - C.lua_getfield(L.s, C.int(index), C.CString(k)) + Ck := C.CString(k) + defer C.free(unsafe.Pointer(Ck)) + C.lua_getfield(L.s, C.int(index), Ck) } func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } @@ -340,7 +340,9 @@ func (L *State) PushBoolean(b bool) { } func (L *State) PushString(str string) { - C.lua_pushstring(L.s,C.CString(str)); + Cstr := C.CString(str) + defer C.free(unsafe.Pointer(Cstr)) + C.lua_pushstring(L.s,Cstr) } func (L *State) PushInteger(n int) { @@ -409,11 +411,15 @@ func (L *State) SetfEnv(index int) { } func (L *State) SetField(index int, k string) { - C.lua_setfield(L.s, C.int(index), C.CString(k)); + Ck := C.CString(k) + defer C.free(unsafe.Pointer(Ck)) + C.lua_setfield(L.s, C.int(index), Ck) } func (L *State) SetGlobal(name string) { - C.lua_setfield(L.s, C.int(LUA_GLOBALSINDEX), C.CString(name)) + Cname := C.CString(name) + defer C.free(unsafe.Pointer(Cname)) + C.lua_setfield(L.s, C.int(LUA_GLOBALSINDEX), Cname) } func (L *State) SetMetaTable(index int) { From 7dda61b799bbb53041774cd10f7ae1dc6e443d44 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 31 Mar 2012 19:08:25 +0200 Subject: [PATCH 007/100] Compiles with go1 (barely tested) --- example/Makefile | 31 -------------- example/alloc.go | 2 +- example/basic.go | 16 +++---- example/panic.go | 10 +++-- example/userdata.go | 2 +- lua51/golua.c => lua/c-golua.c | 17 ++++---- lua/golua.go | 60 ++++++++++++++++++++++++++ {lua51 => lua}/golua.h | 3 +- {lua51 => lua}/lauxlib.go | 40 +++++++++--------- {lua51 => lua}/lua.go | 77 +++++++--------------------------- {lua51 => lua}/lua_defs.go | 2 +- lua51/Makefile | 55 ------------------------ luaver.sh | 9 ---- 13 files changed, 123 insertions(+), 201 deletions(-) delete mode 100644 example/Makefile rename lua51/golua.c => lua/c-golua.c (94%) create mode 100644 lua/golua.go rename {lua51 => lua}/golua.h (92%) rename {lua51 => lua}/lauxlib.go (87%) rename {lua51 => lua}/lua.go (88%) rename {lua51 => lua}/lua_defs.go (99%) delete mode 100644 lua51/Makefile delete mode 100755 luaver.sh diff --git a/example/Makefile b/example/Makefile deleted file mode 100644 index be4278fa..00000000 --- a/example/Makefile +++ /dev/null @@ -1,31 +0,0 @@ - -include $(GOROOT)/src/Make.inc - -all: basic panic userdata alloc - -basic: basic.8 - $(LD) -o basic basic.8 - -basic.8: basic.go - $(GC) -o basic.8 basic.go - -panic: panic.8 - $(LD) -o panic panic.8 - -panic.8: panic.go - $(GC) -o panic.8 panic.go - -userdata: userdata.8 - $(LD) -o userdata userdata.8 - -userdata.8: userdata.go - $(GC) -o userdata.8 userdata.go - -alloc: alloc.8 - $(LD) -o alloc alloc.8 - -alloc.8: alloc.go - $(GC) -o alloc.8 alloc.go - -clean: - -rm -f basic panic alloc userdata *.8 diff --git a/example/alloc.go b/example/alloc.go index 212665c1..fe6b80fb 100644 --- a/example/alloc.go +++ b/example/alloc.go @@ -1,6 +1,6 @@ package main -import lua "lua51" +import lua "golua/lua" import "unsafe" import "fmt" diff --git a/example/basic.go b/example/basic.go index 2276822b..bc3685f9 100644 --- a/example/basic.go +++ b/example/basic.go @@ -1,16 +1,16 @@ package main -import "lua51" +import "golua/lua" import "fmt" -func test(L *lua51.State) int { +func test(L *lua.State) int { fmt.Println("hello world! from go!"); return 0; } -func test2(L *lua51.State) int { - arg := lua51.CheckInteger(L,-1); - argfrombottom := lua51.CheckInteger(L,1); +func test2(L *lua.State) int { + arg := lua.CheckInteger(L,-1); + argfrombottom := lua.CheckInteger(L,1); fmt.Print("test2 arg: "); fmt.Println(arg); fmt.Print("from bottom: "); @@ -19,12 +19,12 @@ func test2(L *lua51.State) int { } func main() { - var L *lua51.State; + var L *lua.State; - L = lua51.NewState(); + L = lua.NewState(); L.OpenLibs(); - L.GetField(lua51.LUA_GLOBALSINDEX, "print"); + L.GetField(lua.LUA_GLOBALSINDEX, "print"); L.PushString("Hello World!"); L.Call(1,0); diff --git a/example/panic.go b/example/panic.go index 15cc50c7..4f0480dc 100644 --- a/example/panic.go +++ b/example/panic.go @@ -1,6 +1,6 @@ package main -import lua "lua51" +import lua "golua/lua" import "fmt" func test(L *lua.State) int { @@ -19,8 +19,12 @@ func main() { currentPanicf := L.AtPanic(nil); currentPanicf = L.AtPanic(currentPanicf); newPanic := func(L1 *lua.State) int { - fmt.Println("I AM PANICKING!!!"); - return currentPanicf(L1); + fmt.Println("I AM PANICKING!!! %v", currentPanicf); + if currentPanicf != nil { + return currentPanicf(L1); + } + + return 1; } L.AtPanic(newPanic); diff --git a/example/userdata.go b/example/userdata.go index 620803f2..75db68d9 100644 --- a/example/userdata.go +++ b/example/userdata.go @@ -1,6 +1,6 @@ package main -import lua "lua51" +import lua "golua/lua" import "unsafe" import "fmt" diff --git a/lua51/golua.c b/lua/c-golua.c similarity index 94% rename from lua51/golua.c rename to lua/c-golua.c index b2b1dc14..655db907 100644 --- a/lua51/golua.c +++ b/lua/c-golua.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "_cgo_export.h" //metatables to register: // GoLua.GoInterface @@ -25,7 +26,7 @@ GoInterface* clua_getgostate(lua_State* L) lua_gettable(L, LUA_REGISTRYINDEX); GoInterface* gip = lua_touserdata(L,-1); lua_pop(L,1); - return gip; + return gip; } @@ -40,7 +41,7 @@ int callback_function(lua_State* L) } //wrapper for gchook -int gchook_wrapper(lua_State* L) +int gchook_wrapper(lua_State* L) { unsigned int* fid = clua_checkgofunction(L,-1); //TODO: this will error GoInterface* gi = clua_getgostate(L); @@ -65,14 +66,14 @@ void clua_pushgofunction(lua_State* L, unsigned int fid) lua_setmetatable(L, -2); } -void clua_pushlightinteger(lua_State* L, unsigned int n) +void clua_pushlightinteger(lua_State* L, int n) { - lua_pushlightuserdata(L, (void*)n); + lua_pushlightuserdata(L, (void*)(uintptr_t)n); } -int clua_tolightinteger(lua_State *L, unsigned int index) +uintptr_t clua_tolightinteger(lua_State *L, unsigned int index) { - return (int)lua_touserdata(L, index); + return (uintptr_t)lua_touserdata(L, index); } void clua_setgostate(lua_State* L, GoInterface gi) @@ -84,7 +85,7 @@ void clua_setgostate(lua_State* L, GoInterface gi) gip->t = gi.t; //set into registry table lua_settable(L,LUA_REGISTRYINDEX); - + } @@ -155,7 +156,7 @@ GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id) else { //TODO: technically UB, function ptr -> non function ptr - return golua_cfunctiontointerface((int*)pf); + return golua_cfunctiontointerface((uintptr *)pf); } } diff --git a/lua/golua.go b/lua/golua.go new file mode 100644 index 00000000..ea68c62f --- /dev/null +++ b/lua/golua.go @@ -0,0 +1,60 @@ +package lua + +/* +#cgo pkg-config: lua5.1 + +#include +#include +*/ +import "C" + +import "unsafe" + +type GoFunction func(*State) int; +type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer; + +//wrapper to keep cgo from complaining about incomplete ptr type +//export State +type State struct { + s *C.lua_State; + //funcs []GoFunction; + registry []interface{}; + //freelist for funcs indices, to allow for freeing + freeIndices []uint; +} + +//export golua_callgofunction +func golua_callgofunction(L interface{}, fid uint) int { + L1 := L.(*State); + f := L1.registry[fid].(GoFunction); + return f(L1); +} + +//export golua_gchook +func golua_gchook(L interface{}, id uint) int { + L1 := L.(*State); + L1.unregister(id); + return 0; +} + +//export golua_callpanicfunction +func golua_callpanicfunction(L interface{}, id uint) int { + L1 := L.(*State); + f := L1.registry[id].(GoFunction); + return f(L1); +} + +//export golua_idtointerface +func golua_idtointerface(id uint) interface{} { + return id; +} + +//export golua_cfunctiontointerface +func golua_cfunctiontointerface(f *uintptr) interface{} { + return f; +} + +//export golua_callallocf +func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { + return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr),osize,nsize)); +} diff --git a/lua51/golua.h b/lua/golua.h similarity index 92% rename from lua51/golua.h rename to lua/golua.h index d5616137..faddb603 100644 --- a/lua51/golua.h +++ b/lua/golua.h @@ -1,3 +1,4 @@ +#include typedef struct { void *t; void *v; } GoInterface; @@ -7,7 +8,7 @@ void clua_initstate(lua_State* L); unsigned int clua_togofunction(lua_State* L, int index); void clua_pushgofunction(lua_State* L, unsigned int fid); void clua_pushlightinteger(lua_State* L, int n); -int clua_tolightinteger(lua_State* L, int index); +uintptr_t clua_tolightinteger(lua_State* L, int index); void clua_setgostate(lua_State* L, GoInterface gostate); GoInterface* clua_getgostate(lua_State* L); GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id); diff --git a/lua51/lauxlib.go b/lua/lauxlib.go similarity index 87% rename from lua51/lauxlib.go rename to lua/lauxlib.go index 85e66986..8910c5ab 100644 --- a/lua51/lauxlib.go +++ b/lua/lauxlib.go @@ -1,4 +1,4 @@ -package lua51 +package lua //#include //#include @@ -15,14 +15,14 @@ import "unsafe" func ArgCheck(L *State, cond bool, narg int, extramsg string) { if cond { - Cextramsg := C.CString(extramsg) + Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) C.luaL_argerror(L.s, C.int(narg), Cextramsg) } } func ArgError(L *State, narg int, extramsg string) int { - Cextramsg := C.CString(extramsg) + Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) return int(C.luaL_argerror(L.s,C.int(narg),Cextramsg)); } @@ -32,7 +32,7 @@ func ArgError(L *State, narg int, extramsg string) int { //luaL_buffinit func CallMeta(L *State, obj int, e string) int { - Ce := C.CString(e) + Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) return int(C.luaL_callmeta(L.s,C.int(obj),Ce)) } @@ -64,8 +64,8 @@ func CheckType(L *State, narg int, t int) { } func CheckUdata(L *State, narg int, tname string) unsafe.Pointer { - Ctname := C.CString(tname) - defer C.free(unsafe.Pointer(Ctname)) + Ctname := C.CString(tname) + defer C.free(unsafe.Pointer(Ctname)) return unsafe.Pointer(C.luaL_checkudata(L.s,C.int(narg),Ctname)) } @@ -93,50 +93,50 @@ func FmtError(L *State, fmt string, args...interface{}) int { //returns false if no such metatable or no such field func GetMetaField(L *State, obj int, e string) bool { - Ce := C.CString(e) - defer C.free(unsafe.Pointer(Ce)) + Ce := C.CString(e) + defer C.free(unsafe.Pointer(Ce)) return C.luaL_getmetafield(L.s,C.int(obj),Ce) != 0; } //TODO: rename better... clashes with lua_getmetatable func LGetMetaTable(L *State, tname string) { - Ctname := C.CString(tname) - defer C.free(unsafe.Pointer(Ctname)) + Ctname := C.CString(tname) + defer C.free(unsafe.Pointer(Ctname)) C.lua_getfield(L.s,LUA_REGISTRYINDEX,Ctname); } func GSub(L *State, s string, p string, r string) string { - Cs := C.CString(s) - Cp := C.CString(p) - Cr := C.CString(r) + Cs := C.CString(s) + Cp := C.CString(p) + Cr := C.CString(r) defer func(){ C.free(unsafe.Pointer(Cs)) C.free(unsafe.Pointer(Cp)) C.free(unsafe.Pointer(Cr)) }() - return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) + return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) } //TODO: luaL_loadbuffer func (L *State) LoadFile(filename string) int { - Cfilename := C.CString(filename) - defer C.free(unsafe.Pointer(Cfilename)) + Cfilename := C.CString(filename) + defer C.free(unsafe.Pointer(Cfilename)) return int(C.luaL_loadfile(L.s,Cfilename)); } func (L *State) LoadString(s string) int { - Cs := C.CString(s) - defer C.free(unsafe.Pointer(Cs)) + Cs := C.CString(s) + defer C.free(unsafe.Pointer(Cs)) return int(C.luaL_loadstring(L.s,Cs)) } //returns false if registry already contains key tname func (L *State) NewMetaTable(tname string) bool { - Ctname := C.CString(tname) - defer C.free(unsafe.Pointer(Ctname)) + Ctname := C.CString(tname) + defer C.free(unsafe.Pointer(Ctname)) return C.luaL_newmetatable(L.s, Ctname) != 0; } diff --git a/lua51/lua.go b/lua/lua.go similarity index 88% rename from lua51/lua.go rename to lua/lua.go index fbadac01..016f7a54 100644 --- a/lua51/lua.go +++ b/lua/lua.go @@ -1,31 +1,24 @@ -package lua51 +package lua -//#include -//#include "golua.h" -//#include -import "C" +/* +#cgo pkg-config: lua5.1 -import "unsafe" +#include +#include +#include "golua.h" +*/ +import "C" +import "unsafe" //like lua_Writer, but as p will contain capacity, not needed as separate param type Writer func(L *State, p []byte, ud interface{}); -//like lua reader, but the return slice has the size, so does +//like lua reader, but the return slice has the size, so does // we do not need it to be an out param type Reader func(L *State, data interface{}) []byte; -//wrapper to keep cgo from complaining about incomplete ptr type -//export State -type State struct { - s *C.lua_State; - //funcs []GoFunction; - registry []interface{}; - //freelist for funcs indices, to allow for freeing - freeIndices []uint; -} - func newState(L *C.lua_State) *State { var newstatei interface{} newstate := &State{L, make([]interface{},0,8), make([]uint,0,8)}; @@ -87,40 +80,6 @@ func (L *State) unregister(fid uint) { } } -type GoFunction func(*State) int; - -//export golua_callgofunction -func golua_callgofunction(L interface{}, fid uint) int { - L1 := L.(*State); - f := L1.registry[fid].(GoFunction); - return f(L1); -} - -//export golua_gchook -func golua_gchook(L interface{}, id uint) int { - L1 := L.(*State); - L1.unregister(id); - return 0; -} - -//export golua_callpanicfunction -func golua_callpanicfunction(L interface{}, id uint) int { - L1 := L.(*State); - f := L1.registry[id].(GoFunction); - return f(L1); -} - -//export golua_idtointerface -func golua_idtointerface(id uint) interface{} { - return id; -} - -//export golua_cfunctiontointerface -func golua_cfunctiontointerface(f *uintptr) interface{} { - return f; -} - - func (L *State) PushGoFunction(f GoFunction) { fid := L.register(f); C.clua_pushgofunction(L.s,C.uint(fid)); @@ -140,7 +99,7 @@ func (L *State) PushLightUserdata(ud *interface{}) { } /* //TODO: -//push pointer as full userdata - mem is go owned, but we +//push pointer as full userdata - mem is go owned, but we //make a guarantee that lifetime will outlast lua lifetime func PushUserdata(L *State, ud interface{}) { @@ -152,14 +111,6 @@ func (L *State) NewUserdata(size uintptr) unsafe.Pointer { return unsafe.Pointer(C.lua_newuserdata(L.s, C.size_t(size))); } - -type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer; -//export golua_callallocf -func golua_callallocf(fp uintptr, ptr uintptr, - osize uint, nsize uint) uintptr { - return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr),osize,nsize)); -} - func (L *State) AtPanic(panicf GoFunction) (oldpanicf GoFunction) { fid := uint(0); if panicf != nil { @@ -178,7 +129,7 @@ func (L *State) AtPanic(panicf GoFunction) (oldpanicf GoFunction) { } } //generally we only get here if the panicf got set to something like nil - //potentially dangerous because we may silently fail + //potentially dangerous because we may silently fail return nil; } @@ -208,7 +159,7 @@ func (L *State) GoPCall(fun GoFunction, ud interface{}) int { return 0; } -//TODO: data be a slice? +//TODO: data be a slice? func (L *State) Dump( writer Writer, data interface{}) int { //TODO: return 0; @@ -247,7 +198,7 @@ func (L *State) IsBoolean(index int) bool { } func (L *State) IsGoFunction(index int) bool { - //TODO:go function is now a userdatum, not a c function, so this will not work + //TODO:go function is now a userdatum, not a c function, so this will not work return C.lua_iscfunction(L.s, C.int(index)) == 1 } diff --git a/lua51/lua_defs.go b/lua/lua_defs.go similarity index 99% rename from lua51/lua_defs.go rename to lua/lua_defs.go index de677158..89576d7f 100644 --- a/lua51/lua_defs.go +++ b/lua/lua_defs.go @@ -1,4 +1,4 @@ -package lua51; +package lua /* #include #include diff --git a/lua51/Makefile b/lua51/Makefile deleted file mode 100644 index 9107032a..00000000 --- a/lua51/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright 2009 The Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -CGO_OFILES+=golua.o - -ifndef LUA51_LIBNAME -LUA51_LIBNAME=$(shell ../luaver.sh) -endif - -ifndef LUA51_INCLUDE_DIR -CGO_CFLAGS+=`pkg-config --cflags $(LUA51_LIBNAME)` -LUA51_INCLUDE_DIR:=$(shell pkg-config --cflags-only-I $(LUA51_LIBNAME) | sed 's/-I//' | sed 's/[ ]*$$//') -else -CGO_CFLAGS+=-I$(LUA51_INCLUDE_DIR) -endif - -ifndef LUA51_LIB_DIR -CGO_LDFLAGS+=`pkg-config --libs $(LUA51_LIBNAME)` -else -CGO_LDFLAGS+=-L$(LUA51_LIB_DIR) -l$(LUA51_LIBNAME) -endif - -TARG=lua51 - -CGOFILES=\ - lua.go \ - lauxlib.go \ - lua_defs.go - -CLEANFILES+=lua_defs.go - -LUA_HEADERS=lua.h lauxlib.h lualib.h -LUA_HEADER_FILES:=$(patsubst %,$(LUA51_INCLUDE_DIR)/%,$(LUA_HEADERS)) -LUA_INCLUDE_DIRECTIVES:=$(patsubst %,\#include <%>\n, $(LUA_HEADERS)) - - -include $(GOROOT)/src/Make.pkg - -%: install %.go - $(QUOTED_GOBIN)/$(GC) $*.go - $(QUOTED_GOBIN)/$(LD) -o $@ $*.$O - -golua.o: golua.c - gcc $(CGO_CFLAGS) $(_CGO_CFLAGS_$(GOARCH)) -fPIC $(CFLAGS) -c golua.c -o golua.o - -lua_defs.go: - echo "package lua51;" > lua_defs.go - echo "/*" >> lua_defs.go - /bin/echo -e "$(LUA_INCLUDE_DIRECTIVES)" >> lua_defs.go - echo "*/" >> lua_defs.go - echo "import \"C\"" >> lua_defs.go - cat $(LUA_HEADER_FILES) | grep '#define LUA' | sed 's/#define/const/' | sed 's/\([A-Z_][A-Z_]*\)[\t ].*/\1 = C.\1/' >> lua_defs.go diff --git a/luaver.sh b/luaver.sh deleted file mode 100755 index cfc4b250..00000000 --- a/luaver.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -LUAVER=$(pkg-config --print-provides lua | cut -d ' ' -f1) - -if test "$LUAVER" = ""; then - LUAVER=lua5.1 -fi - -echo $LUAVER From bc4e72f6caefc906d6b7b2d0f8f405e41b7c1692 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 31 Mar 2012 19:11:21 +0200 Subject: [PATCH 008/100] readme update --- README | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/README b/README index 7a68e52d..9b64139c 100644 --- a/README +++ b/README @@ -2,24 +2,9 @@ Go Bindings for the lua C API Simplest way to install: -#goinstall -u github.com/afitz/golua -#cd $GOROOT/src/pkg/github.com/afitz/golua -#make install +#go get -u github.com/aarzilli/golua - -Configuration Variables ------------------------ -LUA51_LIBNAME -default: lua5.1 -used if LUA51_LIB_DIR is defined - -LUA51_INCLUDE_DIR -default: undefined -defining this overrides the pkg-config mechanism to find the lua cflags - -LUA51_LIB_DIR -default: undefined -defining this overrides the pkg-config mechanism to create the LD_FLAGS +Will work as long as pkg-config knows about lua Licensing ------------------------- From e62ba98a4f17552e11c69c094988dadf13039667 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 31 Mar 2012 19:20:30 +0200 Subject: [PATCH 009/100] Import path fixes for examples and more explanations in README --- Makefile | 18 ------------------ README | 12 ++++++++++-- example/alloc.go | 2 +- example/basic.go | 2 +- example/panic.go | 4 ++-- example/userdata.go | 2 +- 6 files changed, 15 insertions(+), 25 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index adf77e67..00000000 --- a/Makefile +++ /dev/null @@ -1,18 +0,0 @@ - -LUA51_DIR=lua51 - -all: $(LUA51_DIR)/_obj/lua51.a examples - -$(LUA51_DIR)/_obj/lua51.a: - cd $(LUA51_DIR) && make - -examples: install - cd example && make - -clean: - cd example && make clean - cd $(LUA51_DIR) && make clean - -install: - cd $(LUA51_DIR) && make install - diff --git a/README b/README index 9b64139c..e92d9bf3 100644 --- a/README +++ b/README @@ -2,9 +2,17 @@ Go Bindings for the lua C API Simplest way to install: -#go get -u github.com/aarzilli/golua +#go get -u github.com/aarzilli/golua/lua -Will work as long as pkg-config knows about lua +Will work as long as pkg-config knows about lua. + +You can then try to run the examples: + +$cd /usr/local/go/src/pkg/github.com/aarzilli/golua/example/ +$go run basic.go +$go run alloc.go +$go run panic.go +$go run userdata.go Licensing ------------------------- diff --git a/example/alloc.go b/example/alloc.go index fe6b80fb..075acb1b 100644 --- a/example/alloc.go +++ b/example/alloc.go @@ -1,6 +1,6 @@ package main -import lua "golua/lua" +import "github.com/aarzilli/golua/lua" import "unsafe" import "fmt" diff --git a/example/basic.go b/example/basic.go index bc3685f9..71082eb9 100644 --- a/example/basic.go +++ b/example/basic.go @@ -1,6 +1,6 @@ package main -import "golua/lua" +import "github.com/aarzilli/golua/lua" import "fmt" func test(L *lua.State) int { diff --git a/example/panic.go b/example/panic.go index 4f0480dc..0216ce79 100644 --- a/example/panic.go +++ b/example/panic.go @@ -1,6 +1,6 @@ package main -import lua "golua/lua" +import "github.com/aarzilli/golua/lua" import "fmt" func test(L *lua.State) int { @@ -23,7 +23,7 @@ func main() { if currentPanicf != nil { return currentPanicf(L1); } - + return 1; } diff --git a/example/userdata.go b/example/userdata.go index 75db68d9..1abb9219 100644 --- a/example/userdata.go +++ b/example/userdata.go @@ -1,6 +1,6 @@ package main -import lua "golua/lua" +import "github.com/aarzilli/golua/lua" import "unsafe" import "fmt" From 4a2a3754bdf43138d38d15a7447d45cdaa7d8940 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sun, 24 Jun 2012 15:21:14 +0200 Subject: [PATCH 010/100] Merging https://github.com/aarzilli/golua/pull/1 from ruitao (thanks) --- lua/c-golua.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index 655db907..99e43e20 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -68,12 +68,12 @@ void clua_pushgofunction(lua_State* L, unsigned int fid) void clua_pushlightinteger(lua_State* L, int n) { - lua_pushlightuserdata(L, (void*)(uintptr_t)n); + lua_pushlightuserdata(L, (void*)(GoUintptr)n); } -uintptr_t clua_tolightinteger(lua_State *L, unsigned int index) +GoUintptr clua_tolightinteger(lua_State *L, unsigned int index) { - return (uintptr_t)lua_touserdata(L, index); + return (GoUintptr)lua_touserdata(L, index); } void clua_setgostate(lua_State* L, GoInterface gi) @@ -156,7 +156,7 @@ GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id) else { //TODO: technically UB, function ptr -> non function ptr - return golua_cfunctiontointerface((uintptr *)pf); + return golua_cfunctiontointerface((GoUintptr *)pf); } } @@ -167,7 +167,7 @@ int clua_callluacfunc(lua_State* L, lua_CFunction f) void* allocwrapper(void* ud, void *ptr, size_t osize, size_t nsize) { - return (void*)golua_callallocf((uintptr)ud,(uintptr)ptr,osize,nsize); + return (void*)golua_callallocf((GoUintptr)ud,(GoUintptr)ptr,osize,nsize); } lua_State* clua_newstate(void* goallocf) From e44d144d88f109a8a9252ed6eab9a93102d6d5f7 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Tue, 26 Jun 2012 20:00:27 +0200 Subject: [PATCH 011/100] changed examples to make them easier to run locally --- example/alloc.go | 2 +- example/basic.go | 2 +- example/panic.go | 2 +- example/userdata.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/alloc.go b/example/alloc.go index 075acb1b..c8719780 100644 --- a/example/alloc.go +++ b/example/alloc.go @@ -1,6 +1,6 @@ package main -import "github.com/aarzilli/golua/lua" +import "../lua" import "unsafe" import "fmt" diff --git a/example/basic.go b/example/basic.go index 71082eb9..fed7f824 100644 --- a/example/basic.go +++ b/example/basic.go @@ -1,6 +1,6 @@ package main -import "github.com/aarzilli/golua/lua" +import "../lua" import "fmt" func test(L *lua.State) int { diff --git a/example/panic.go b/example/panic.go index 0216ce79..7cedfe95 100644 --- a/example/panic.go +++ b/example/panic.go @@ -1,6 +1,6 @@ package main -import "github.com/aarzilli/golua/lua" +import "../lua" import "fmt" func test(L *lua.State) int { diff --git a/example/userdata.go b/example/userdata.go index 1abb9219..30c0e8a0 100644 --- a/example/userdata.go +++ b/example/userdata.go @@ -1,6 +1,6 @@ package main -import "github.com/aarzilli/golua/lua" +import "../lua" import "unsafe" import "fmt" From 097c56b52bb84ec757d06ca99c973370ed8f087a Mon Sep 17 00:00:00 2001 From: aarzilli Date: Thu, 28 Jun 2012 13:26:03 +0200 Subject: [PATCH 012/100] pushing go interfaces to lua like we do with functions, changed name of GoFunctoin type, fixed IsGoFunction --- example/userdata.go | 43 ++++++++++++++++++--- lua/c-golua.c | 92 ++++++++++++++++++++++++++++++--------------- lua/golua.go | 9 +++-- lua/golua.h | 3 ++ lua/lauxlib.go | 6 +-- lua/lua.go | 33 ++++++++-------- 6 files changed, 127 insertions(+), 59 deletions(-) diff --git a/example/userdata.go b/example/userdata.go index 30c0e8a0..b565a3eb 100644 --- a/example/userdata.go +++ b/example/userdata.go @@ -8,11 +8,7 @@ type Userdata struct { a,b int } -func main() { - var L *lua.State; - L = lua.NewState(); - L.OpenLibs(); - +func userDataProper(L *lua.State) { rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{}))); var ptr *Userdata; ptr = (*Userdata)(rawptr); @@ -26,3 +22,40 @@ func main() { fmt.Println(ptr2); } + +func example_function(L *lua.State) int { + fmt.Println("Heeeeelllllooooooooooo nuuurse!!!!"); + return 0 +} + +func goDefinedFunctions(L *lua.State) { + /* example_function is registered inside Lua VM */ + L.Register("example_function", example_function) + + /* This code demonstrates checking that a value on the stack is a go function */ + L.CheckStack(1) + L.GetGlobal("example_function") + if !L.IsGoFunction(-1) { + panic("Not go function") + } + L.Pop(1) + + /* We call example_function from inside Lua VM */ + L.DoString("example_function()") +} + +func main() { + var L *lua.State; + L = lua.NewState(); + L.OpenLibs(); + + /* + This function stores a go object inside Lua VM + */ + userDataProper(L) + + /* + This function demonstrates exposing a function implemented in go to interpreted Lua code + */ + goDefinedFunctions(L); +} diff --git a/lua/c-golua.c b/lua/c-golua.c index 99e43e20..36fed320 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -8,15 +8,25 @@ // GoLua.GoFunction // +#define MT_GOFUNCTION "GoLua.GoFunction" +#define MT_GOINTERFACE "GoLua.GoInterface" + static const char GoStateRegistryKey = 'k'; //golua registry key static const char PanicFIDRegistryKey = 'k'; -unsigned int* clua_checkgofunction(lua_State* L, int index) +unsigned int* clua_checkgosomething(lua_State* L, int index, const char *desired_metatable) { - unsigned int* fid = (unsigned int*)luaL_checkudata(L,index,"GoLua.GoFunction"); - luaL_argcheck(L, fid != NULL, index, "'GoFunction' expected"); - return fid; + if (desired_metatable != NULL) { + unsigned int* fid = (unsigned int*)luaL_checkudata(L,index, desired_metatable); + luaL_argcheck(L, fid != NULL, index, "Metatable not what expected"); + return fid; + } else { + unsigned int *sid = (unsigned int *)luaL_checkudata(L, index, MT_GOFUNCTION); + if (sid == NULL) sid = (unsigned int *)luaL_checkudata(L, index, MT_GOINTERFACE); + luaL_argcheck(L, sid != NULL, index, "Metatable not what expected"); + return sid; + } } GoInterface* clua_getgostate(lua_State* L) @@ -33,7 +43,7 @@ GoInterface* clua_getgostate(lua_State* L) //wrapper for callgofunction int callback_function(lua_State* L) { - unsigned int *fid = clua_checkgofunction(L,1); + unsigned int *fid = clua_checkgosomething(L, 1, MT_GOFUNCTION); GoInterface* gi = clua_getgostate(L); //remove the go function from the stack (to present same behavior as lua_CFunctions) lua_remove(L,1); @@ -43,7 +53,7 @@ int callback_function(lua_State* L) //wrapper for gchook int gchook_wrapper(lua_State* L) { - unsigned int* fid = clua_checkgofunction(L,-1); //TODO: this will error + unsigned int* fid = clua_checkgosomething(L, -1, NULL); //TODO: this will error GoInterface* gi = clua_getgostate(L); if(fid != NULL) return golua_gchook(*gi,*fid); @@ -55,25 +65,28 @@ int gchook_wrapper(lua_State* L) unsigned int clua_togofunction(lua_State* L, int index) { - return *(clua_checkgofunction(L,index)); + return *(clua_checkgosomething(L, index, MT_GOFUNCTION)); } -void clua_pushgofunction(lua_State* L, unsigned int fid) +unsigned int clua_togointerface(lua_State *L, int index) { - unsigned int* fidptr = (unsigned int*)lua_newuserdata(L, sizeof(unsigned int)); - *fidptr = fid; - luaL_getmetatable(L, "GoLua.GoFunction"); - lua_setmetatable(L, -2); + return *(clua_checkgosomething(L, index, MT_GOINTERFACE)); } -void clua_pushlightinteger(lua_State* L, int n) +void clua_pushgofunction(lua_State* L, unsigned int fid) { - lua_pushlightuserdata(L, (void*)(GoUintptr)n); + unsigned int* fidptr = (unsigned int *)lua_newuserdata(L, sizeof(unsigned int)); + *fidptr = fid; + luaL_getmetatable(L, MT_GOFUNCTION); + lua_setmetatable(L, -2); } -GoUintptr clua_tolightinteger(lua_State *L, unsigned int index) +void clua_pushgointerface(lua_State* L, unsigned int iid) { - return (GoUintptr)lua_touserdata(L, index); + unsigned int* iidptr = (unsigned int *)lua_newuserdata(L, sizeof(unsigned int)); + *iidptr = iid; + luaL_getmetatable(L, MT_GOINTERFACE); + lua_setmetatable(L,-2); } void clua_setgostate(lua_State* L, GoInterface gi) @@ -89,31 +102,30 @@ void clua_setgostate(lua_State* L, GoInterface gi) } -void clua_pushgointerface(lua_State* L, GoInterface gi) -{ - GoInterface* iptr = (GoInterface*)lua_newuserdata(L, sizeof(GoInterface)); - iptr->v = gi.v; - iptr->t = gi.t; - luaL_getmetatable(L, "GoLua.GoInterface"); - lua_setmetatable(L,-2); -} - void clua_initstate(lua_State* L) { /* create the GoLua.GoFunction metatable */ - luaL_newmetatable(L,"GoLua.GoFunction"); - //pushkey + luaL_newmetatable(L,MT_GOFUNCTION); + + // gofunction_metatable[__call] = &callback_function lua_pushliteral(L,"__call"); - //push value lua_pushcfunction(L,&callback_function); - //t[__call] = &callback_function lua_settable(L,-3); - //push key + + // gofunction_metatable[__gc] = &gchook_wrapper lua_pushliteral(L,"__gc"); - //pushvalue lua_pushcfunction(L,&gchook_wrapper); lua_settable(L,-3); lua_pop(L,1); + + luaL_newmetatable(L, MT_GOINTERFACE); + + // gointerface_metatable[__gc] = &gchook_wrapper + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, &gchook_wrapper); + lua_settable(L, -3); + + lua_pop(L, 1); } @@ -232,3 +244,21 @@ void clua_setexecutionlimit(lua_State* L, int n) { lua_sethook(L, &clua_hook_function, LUA_MASKCOUNT, n); } +/* taken from lua5.2 source */ +void *testudata(lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ +} + +int clua_isgofunction(lua_State *L, int n) { + return testudata(L, n, MT_GOFUNCTION) != NULL; +} diff --git a/lua/golua.go b/lua/golua.go index ea68c62f..7ae5f988 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -10,14 +10,15 @@ import "C" import "unsafe" -type GoFunction func(*State) int; type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer; +// this is the type of go function that can be registered as lua functions +type LuaGoFunction func(L *State) int; + //wrapper to keep cgo from complaining about incomplete ptr type //export State type State struct { s *C.lua_State; - //funcs []GoFunction; registry []interface{}; //freelist for funcs indices, to allow for freeing freeIndices []uint; @@ -26,7 +27,7 @@ type State struct { //export golua_callgofunction func golua_callgofunction(L interface{}, fid uint) int { L1 := L.(*State); - f := L1.registry[fid].(GoFunction); + f := L1.registry[fid].(LuaGoFunction); return f(L1); } @@ -40,7 +41,7 @@ func golua_gchook(L interface{}, id uint) int { //export golua_callpanicfunction func golua_callpanicfunction(L interface{}, id uint) int { L1 := L.(*State); - f := L1.registry[id].(GoFunction); + f := L1.registry[id].(LuaGoFunction); return f(L1); } diff --git a/lua/golua.h b/lua/golua.h index faddb603..a7a47a9b 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -7,6 +7,7 @@ void clua_initstate(lua_State* L); unsigned int clua_togofunction(lua_State* L, int index); void clua_pushgofunction(lua_State* L, unsigned int fid); +void clua_pushgointerface(lua_State *L, unsigned int fid); void clua_pushlightinteger(lua_State* L, int n); uintptr_t clua_tolightinteger(lua_State* L, int index); void clua_setgostate(lua_State* L, GoInterface gostate); @@ -24,3 +25,5 @@ void clua_openstring(lua_State* L); void clua_opentable(lua_State* L); void clua_openos(lua_State* L); void clua_setexecutionlimit(lua_State* L, int n); + +int clua_isgofunction(lua_State *L, int n); \ No newline at end of file diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 8910c5ab..178fcc5c 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -160,8 +160,8 @@ func (L *State) OptNumber(narg int, d float64) float64 { func (L *State) OptString(narg int, d string) string { var length C.size_t; - Cd := C.CString(d) - defer C.free(unsafe.Pointer(Cd)) + Cd := C.CString(d) + defer C.free(unsafe.Pointer(Cd)) return C.GoString(C.luaL_optlstring(L.s,C.int(narg),Cd,&length)); } @@ -180,7 +180,7 @@ func LTypename(L *State, index int) string { //TODO: decide if we actually want this renamed func TypeError(L *State, narg int, tname string) int { - Ctname := C.CString(tname) + Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) return int(C.luaL_typerror(L.s,C.int(narg),Ctname)) } diff --git a/lua/lua.go b/lua/lua.go index 016f7a54..a45bdc9f 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -80,23 +80,27 @@ func (L *State) unregister(fid uint) { } } -func (L *State) PushGoFunction(f GoFunction) { +func (L *State) PushGoFunction(f LuaGoFunction) { fid := L.register(f); C.clua_pushgofunction(L.s,C.uint(fid)); } +func (L *State) PushGoInterface(iface interface{}) { + iid := L.register(iface); + C.clua_pushgointerface(L.s, C.uint(iid)); +} -func (L *State) PushLightInteger(n int) { +/*func (L *State) PushLightInteger(n int) { C.clua_pushlightinteger(L.s, C.int(n)) -} +}*/ //push pointer by value, as a value - we don't impact lifetime func (L *State) PushLightUserdata(ud *interface{}) { //push C.lua_pushlightuserdata(L.s,unsafe.Pointer(ud)); - } + /* //TODO: //push pointer as full userdata - mem is go owned, but we @@ -111,7 +115,7 @@ func (L *State) NewUserdata(size uintptr) unsafe.Pointer { return unsafe.Pointer(C.lua_newuserdata(L.s, C.size_t(size))); } -func (L *State) AtPanic(panicf GoFunction) (oldpanicf GoFunction) { +func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { fid := uint(0); if panicf != nil { fid = L.register(panicf); @@ -119,7 +123,7 @@ func (L *State) AtPanic(panicf GoFunction) (oldpanicf GoFunction) { oldres := interface{}(C.clua_atpanic(L.s,C.uint(fid))); switch i := oldres.(type) { case C.uint: - f := L.registry[uint(i)].(GoFunction); + f := L.registry[uint(i)].(LuaGoFunction); //free registry entry L.unregister(uint(i)); return f; @@ -154,7 +158,7 @@ func (L *State) CreateTable(narr int, nrec int) { } //CPcall replacement -func (L *State) GoPCall(fun GoFunction, ud interface{}) int { +func (L *State) GoPCall(fun LuaGoFunction, ud interface{}) int { //TODO: need to emulate by pushing a c closure as in pushgofunction return 0; } @@ -198,12 +202,9 @@ func (L *State) IsBoolean(index int) bool { } func (L *State) IsGoFunction(index int) bool { - //TODO:go function is now a userdatum, not a c function, so this will not work - return C.lua_iscfunction(L.s, C.int(index)) == 1 + return C.clua_isgofunction(L.s, C.int(index)) != 0 } -//TODO: add iscfunction - func (L *State) IsFunction(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TFUNCTION } @@ -336,7 +337,7 @@ func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)); } -func (L *State) Register(name string, f GoFunction) { +func (L *State) Register(name string, f LuaGoFunction) { L.PushGoFunction(f); L.SetGlobal(name); } @@ -393,9 +394,9 @@ func (L *State) ToBoolean(index int) bool { return C.lua_toboolean(L.s, C.int(index)) != 0; } -func (L *State) ToGoFunction(index int) (f GoFunction) { +func (L *State) ToGoFunction(index int) (f LuaGoFunction) { fid := C.clua_togofunction(L.s,C.int(index)) - return L.registry[fid].(GoFunction); + return L.registry[fid].(LuaGoFunction); } func (L *State) ToString(index int) string { @@ -425,9 +426,9 @@ func (L *State) ToUserdata(index int) unsafe.Pointer { return unsafe.Pointer(C.lua_touserdata(L.s,C.int(index))); } -func (L *State) ToLightInteger(index int) int { +/*func (L *State) ToLightInteger(index int) int { return int(C.clua_tolightinteger(L.s, C.int(index))) -} +}*/ func (L *State) Type(index int) int { return int(C.lua_type(L.s, C.int(index))); From e21000926097a951fbfdf0dd41551d1d3a7182a2 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Thu, 28 Jun 2012 13:26:51 +0200 Subject: [PATCH 013/100] clua_isgointerface --- lua/c-golua.c | 4 ++++ lua/golua.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index 36fed320..fb192cc3 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -262,3 +262,7 @@ void *testudata(lua_State *L, int ud, const char *tname) { int clua_isgofunction(lua_State *L, int n) { return testudata(L, n, MT_GOFUNCTION) != NULL; } + +int clua_isgointerface(lua_State *L, int n) { + return testudata(L, n, MT_GOINTERFACE) != NULL; +} diff --git a/lua/golua.h b/lua/golua.h index a7a47a9b..75df5867 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -26,4 +26,5 @@ void clua_opentable(lua_State* L); void clua_openos(lua_State* L); void clua_setexecutionlimit(lua_State* L, int n); -int clua_isgofunction(lua_State *L, int n); \ No newline at end of file +int clua_isgofunction(lua_State *L, int n); +int clua_isgointerface(lua_State *L, int n); \ No newline at end of file From b3a1fd14f7a940920af7311312aa7a4b7e95255d Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 18 Jul 2012 16:12:35 +0200 Subject: [PATCH 014/100] PushGoStruct -- with reflection to access and set plain data fields --- example/userdata.go | 30 ++++++++++- lua/c-golua.c | 75 ++++++++++++++++++++++++-- lua/golua.go | 129 +++++++++++++++++++++++++++++++++++++++++++- lua/golua.h | 4 +- lua/lauxlib.go | 25 +++++++-- lua/lua.go | 10 ++-- 6 files changed, 258 insertions(+), 15 deletions(-) diff --git a/example/userdata.go b/example/userdata.go index b565a3eb..18bd399b 100644 --- a/example/userdata.go +++ b/example/userdata.go @@ -36,12 +36,36 @@ func goDefinedFunctions(L *lua.State) { L.CheckStack(1) L.GetGlobal("example_function") if !L.IsGoFunction(-1) { - panic("Not go function") + panic("Not a go function") } L.Pop(1) /* We call example_function from inside Lua VM */ - L.DoString("example_function()") + L.MustDoString("example_function()") +} + +type TestObject struct { + AField int +} + +func goDefinedObjects(L *lua.State) { + t := &TestObject{42}; + + L.PushGoStruct(t) + L.SetGlobal("t"); + + /* This code demonstrates checking that a value on the stack is a go object */ + L.CheckStack(1) + L.GetGlobal("t") + if !L.IsGoStruct(-1) { + panic("Not a go struct") + } + L.Pop(1) + + /* This code demonstrates access and assignment to a field of a go object */ + L.MustDoString("print('AField of t is: ' .. t.AField .. ' before assignment');") + L.MustDoString("t.AField = 10;"); + L.MustDoString("print('AField of t is: ' .. t.AField .. ' after assignment');"); } func main() { @@ -58,4 +82,6 @@ func main() { This function demonstrates exposing a function implemented in go to interpreted Lua code */ goDefinedFunctions(L); + + goDefinedObjects(L); } diff --git a/lua/c-golua.c b/lua/c-golua.c index fb192cc3..2114ea24 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -68,7 +68,7 @@ unsigned int clua_togofunction(lua_State* L, int index) return *(clua_checkgosomething(L, index, MT_GOFUNCTION)); } -unsigned int clua_togointerface(lua_State *L, int index) +unsigned int clua_togostruct(lua_State *L, int index) { return *(clua_checkgosomething(L, index, MT_GOINTERFACE)); } @@ -81,7 +81,7 @@ void clua_pushgofunction(lua_State* L, unsigned int fid) lua_setmetatable(L, -2); } -void clua_pushgointerface(lua_State* L, unsigned int iid) +void clua_pushgostruct(lua_State* L, unsigned int iid) { unsigned int* iidptr = (unsigned int *)lua_newuserdata(L, sizeof(unsigned int)); *iidptr = iid; @@ -98,9 +98,68 @@ void clua_setgostate(lua_State* L, GoInterface gi) gip->t = gi.t; //set into registry table lua_settable(L,LUA_REGISTRYINDEX); +} + +/* called when lua code attempts to access a field of a published go object */ +int interface_index_callback(lua_State *L) +{ + unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); + if (iid == NULL) { + lua_pushnil(L); + return 1; + } + + char *field_name = (char *)lua_tostring(L, 2); + if (field_name == NULL) { + lua_pushnil(L); + return 1; + } + GoInterface* gi = clua_getgostate(L); + + int r = golua_interface_index_callback(*gi, *iid, field_name); + + lua_remove(L, 2); + lua_remove(L, 1); + + if (r < 0) { + lua_error(L); + return 0; + } else { + return r; + } } +/* called when lua code attempts to set a field of a published go object */ +int interface_newindex_callback(lua_State *L) +{ + unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); + if (iid == NULL) { + lua_pushnil(L); + return 1; + } + + char *field_name = (char *)lua_tostring(L, 2); + if (field_name == NULL) { + lua_pushnil(L); + return 1; + } + + GoInterface* gi = clua_getgostate(L); + + int r = golua_interface_newindex_callback(*gi, *iid, field_name); + + lua_remove(L, 3); + lua_remove(L, 2); + lua_remove(L, 1); + + if (r < 0) { + lua_error(L); + return 0; + } else { + return r; + } +} void clua_initstate(lua_State* L) { @@ -125,6 +184,16 @@ void clua_initstate(lua_State* L) lua_pushcfunction(L, &gchook_wrapper); lua_settable(L, -3); + // gointerface_metatable[__index] = &interface_index_callback + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, &interface_index_callback); + lua_settable(L, -3); + + // gointerface_metatable[__newindex] = &interface_newindex_callback + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, &interface_newindex_callback); + lua_settable(L, -3); + lua_pop(L, 1); } @@ -263,6 +332,6 @@ int clua_isgofunction(lua_State *L, int n) { return testudata(L, n, MT_GOFUNCTION) != NULL; } -int clua_isgointerface(lua_State *L, int n) { +int clua_isgostruct(lua_State *L, int n) { return testudata(L, n, MT_GOINTERFACE) != NULL; } diff --git a/lua/golua.go b/lua/golua.go index 7ae5f988..52092006 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -4,11 +4,15 @@ package lua #cgo pkg-config: lua5.1 #include +#include #include */ import "C" -import "unsafe" +import ( + "unsafe" + "reflect" +) type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer; @@ -31,6 +35,129 @@ func golua_callgofunction(L interface{}, fid uint) int { return f(L1); } +//export golua_interface_newindex_callback +func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr *C.char) int { + L := Li.(*State) + iface := L.registry[iid] + ifacevalue := reflect.ValueOf(iface).Elem() + + field_name := C.GoString(field_name_cstr) + + fval := ifacevalue.FieldByName(field_name) + + if fval.Kind() == reflect.Ptr { + fval = fval.Elem() + } + + luatype := C.lua_type(L.s, 3) + + switch fval.Kind() { + case reflect.Bool: + if luatype == LUA_TBOOLEAN { + fval.SetBool(int(C.lua_toboolean(L.s, 3)) != 0) + return 1 + } else { + C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + return -1 + } + + case reflect.Int: fallthrough + case reflect.Int8: fallthrough + case reflect.Int16: fallthrough + case reflect.Int32: fallthrough + case reflect.Int64: + if luatype == LUA_TNUMBER { + fval.SetInt(int64(C.lua_tointeger(L.s, 3))) + return 1 + } else { + C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + return -1 + } + + case reflect.Uint: fallthrough + case reflect.Uint8: fallthrough + case reflect.Uint16: fallthrough + case reflect.Uint32: fallthrough + case reflect.Uint64: + if luatype == LUA_TNUMBER { + fval.SetUint(uint64(C.lua_tointeger(L.s, 3))) + return 1 + } else { + C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + return -1 + } + + case reflect.String: + if luatype == LUA_TSTRING { + fval.SetString(C.GoString(C.lua_tolstring(L.s, 3, nil))) + return 1 + } else { + C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + return -1 + } + + case reflect.Float32: fallthrough + case reflect.Float64: + if luatype == LUA_TNUMBER { + fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) + return 1 + } else { + C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + return -1 + } + } + + C.lua_pushstring(L.s, C.CString("Unsupported type of field " + field_name + ": " + fval.Type().String())) + return -1; +} + +//export golua_interface_index_callback +func golua_interface_index_callback(Li interface{}, iid uint, field_name *C.char) int { + L := Li.(*State) + iface := L.registry[iid] + ifacevalue := reflect.ValueOf(iface).Elem() + + fval := ifacevalue.FieldByName(C.GoString(field_name)) + + if fval.Kind() == reflect.Ptr { + fval = fval.Elem() + } + + switch fval.Kind() { + case reflect.Bool: + L.PushBoolean(fval.Bool()) + return 1 + + case reflect.Int: fallthrough + case reflect.Int8: fallthrough + case reflect.Int16: fallthrough + case reflect.Int32: fallthrough + case reflect.Int64: + L.PushInteger(fval.Int()) + return 1 + + case reflect.Uint: fallthrough + case reflect.Uint8: fallthrough + case reflect.Uint16: fallthrough + case reflect.Uint32: fallthrough + case reflect.Uint64: + L.PushInteger(int64(fval.Uint())) + return 1 + + case reflect.String: + L.PushString(fval.String()) + return 1 + + case reflect.Float32: fallthrough + case reflect.Float64: + L.PushNumber(fval.Float()) + return 1 + } + + C.lua_pushstring(L.s, C.CString("Unsupported type of field: " + fval.Type().String())) + return -1; +} + //export golua_gchook func golua_gchook(L interface{}, id uint) int { L1 := L.(*State); diff --git a/lua/golua.h b/lua/golua.h index 75df5867..acd79211 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -7,7 +7,7 @@ void clua_initstate(lua_State* L); unsigned int clua_togofunction(lua_State* L, int index); void clua_pushgofunction(lua_State* L, unsigned int fid); -void clua_pushgointerface(lua_State *L, unsigned int fid); +void clua_pushgostruct(lua_State *L, unsigned int fid); void clua_pushlightinteger(lua_State* L, int n); uintptr_t clua_tolightinteger(lua_State* L, int index); void clua_setgostate(lua_State* L, GoInterface gostate); @@ -27,4 +27,4 @@ void clua_openos(lua_State* L); void clua_setexecutionlimit(lua_State* L, int n); int clua_isgofunction(lua_State *L, int n); -int clua_isgointerface(lua_State *L, int n); \ No newline at end of file +int clua_isgostruct(lua_State *L, int n); \ No newline at end of file diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 178fcc5c..d7059855 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -13,6 +13,14 @@ import "unsafe" //luaL_addstring //luaL_addvalue +type LuaError struct { + message string +} + +func (err *LuaError) Error() string { + return err.message +} + func ArgCheck(L *State, cond bool, narg int, extramsg string) { if cond { Cextramsg := C.CString(extramsg) @@ -77,12 +85,21 @@ func (L *State) DoFile(filename string) bool { return false; } -//true if no errors, false otherwise -func (L *State) DoString(str string) bool { +//nil if no errors, an error otherwise +func (L *State) DoString(str string) error { if L.LoadString(str) == 0 { - return L.PCall(0,LUA_MULTRET,0) == 0; + if L.PCall(0,LUA_MULTRET,0) == 0 { + return nil + } + } + return &LuaError{L.ToString(-1)} +} + +// evaluates argument like DoString, panics if execution failed +func (L *State) MustDoString(str string) { + if err := L.DoString(str); err != nil { + panic(err) } - return false; } //luaL_error becomes FmtError because of lua_error diff --git a/lua/lua.go b/lua/lua.go index a45bdc9f..8f548f1b 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -85,9 +85,9 @@ func (L *State) PushGoFunction(f LuaGoFunction) { C.clua_pushgofunction(L.s,C.uint(fid)); } -func (L *State) PushGoInterface(iface interface{}) { +func (L *State) PushGoStruct(iface interface{}) { iid := L.register(iface); - C.clua_pushgointerface(L.s, C.uint(iid)); + C.clua_pushgostruct(L.s, C.uint(iid)); } /*func (L *State) PushLightInteger(n int) { @@ -205,6 +205,10 @@ func (L *State) IsGoFunction(index int) bool { return C.clua_isgofunction(L.s, C.int(index)) != 0 } +func (L *State) IsGoStruct(index int) bool { + return C.clua_isgostruct(L.s, C.int(index)) != 0 +} + func (L *State) IsFunction(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TFUNCTION } @@ -297,7 +301,7 @@ func (L *State) PushString(str string) { C.lua_pushstring(L.s,Cstr) } -func (L *State) PushInteger(n int) { +func (L *State) PushInteger(n int64) { C.lua_pushinteger(L.s,C.lua_Integer(n)); } From 4b79a924c3db32fccd43fc605b5c4fa9f4d16ab5 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 18 Jul 2012 16:21:38 +0200 Subject: [PATCH 015/100] go fmt run (and consistent formatting in c-golua.c) --- lua/c-golua.c | 196 +++++++++++++++++++++----------------- lua/golua.go | 122 ++++++++++++++---------- lua/lauxlib.go | 102 ++++++++++---------- lua/lua.go | 245 ++++++++++++++++++++++++------------------------ lua/lua_defs.go | 2 + 5 files changed, 354 insertions(+), 313 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index 2114ea24..adcd1bae 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -3,10 +3,6 @@ #include #include #include "_cgo_export.h" -//metatables to register: -// GoLua.GoInterface -// GoLua.GoFunction -// #define MT_GOFUNCTION "GoLua.GoFunction" #define MT_GOINTERFACE "GoLua.GoInterface" @@ -14,14 +10,16 @@ static const char GoStateRegistryKey = 'k'; //golua registry key static const char PanicFIDRegistryKey = 'k'; - unsigned int* clua_checkgosomething(lua_State* L, int index, const char *desired_metatable) { - if (desired_metatable != NULL) { + if (desired_metatable != NULL) + { unsigned int* fid = (unsigned int*)luaL_checkudata(L,index, desired_metatable); luaL_argcheck(L, fid != NULL, index, "Metatable not what expected"); return fid; - } else { + } + else + { unsigned int *sid = (unsigned int *)luaL_checkudata(L, index, MT_GOFUNCTION); if (sid == NULL) sid = (unsigned int *)luaL_checkudata(L, index, MT_GOINTERFACE); luaL_argcheck(L, sid != NULL, index, "Metatable not what expected"); @@ -103,62 +101,72 @@ void clua_setgostate(lua_State* L, GoInterface gi) /* called when lua code attempts to access a field of a published go object */ int interface_index_callback(lua_State *L) { - unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); - if (iid == NULL) { - lua_pushnil(L); - return 1; - } - - char *field_name = (char *)lua_tostring(L, 2); - if (field_name == NULL) { - lua_pushnil(L); - return 1; - } - - GoInterface* gi = clua_getgostate(L); - - int r = golua_interface_index_callback(*gi, *iid, field_name); - - lua_remove(L, 2); - lua_remove(L, 1); - - if (r < 0) { - lua_error(L); - return 0; - } else { - return r; - } + unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); + if (iid == NULL) + { + lua_pushnil(L); + return 1; + } + + char *field_name = (char *)lua_tostring(L, 2); + if (field_name == NULL) + { + lua_pushnil(L); + return 1; + } + + GoInterface* gi = clua_getgostate(L); + + int r = golua_interface_index_callback(*gi, *iid, field_name); + + lua_remove(L, 2); + lua_remove(L, 1); + + if (r < 0) + { + lua_error(L); + return 0; + } + else + { + return r; + } } /* called when lua code attempts to set a field of a published go object */ int interface_newindex_callback(lua_State *L) { - unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); - if (iid == NULL) { - lua_pushnil(L); - return 1; - } - - char *field_name = (char *)lua_tostring(L, 2); - if (field_name == NULL) { - lua_pushnil(L); - return 1; - } - - GoInterface* gi = clua_getgostate(L); - - int r = golua_interface_newindex_callback(*gi, *iid, field_name); - - lua_remove(L, 3); - lua_remove(L, 2); - lua_remove(L, 1); - - if (r < 0) { - lua_error(L); - return 0; - } else { - return r; - } + unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); + if (iid == NULL) + { + lua_pushnil(L); + return 1; + } + + char *field_name = (char *)lua_tostring(L, 2); + if (field_name == NULL) + { + lua_pushnil(L); + return 1; + } + + GoInterface* gi = clua_getgostate(L); + + int r = golua_interface_newindex_callback(*gi, *iid, field_name); + + lua_remove(L, 3); + lua_remove(L, 2); + lua_remove(L, 1); + + if (r < 0) + { + lua_error(L); + return 0; + } + else + { + return r; + } } void clua_initstate(lua_State* L) @@ -261,77 +269,91 @@ void clua_setallocf(lua_State* L, void* goallocf) lua_setallocf(L,&allocwrapper,goallocf); } -void clua_openbase(lua_State* L){ +void clua_openbase(lua_State* L) +{ lua_pushcfunction(L,&luaopen_base); lua_pushstring(L,""); lua_call(L, 1, 0); } -void clua_openio(lua_State* L){ +void clua_openio(lua_State* L) +{ lua_pushcfunction(L,&luaopen_io); lua_pushstring(L,"io"); lua_call(L, 1, 0); } -void clua_openmath(lua_State* L){ +void clua_openmath(lua_State* L) +{ lua_pushcfunction(L,&luaopen_math); lua_pushstring(L,"math"); lua_call(L, 1, 0); } -void clua_openpackage(lua_State* L){ +void clua_openpackage(lua_State* L) +{ lua_pushcfunction(L,&luaopen_package); lua_pushstring(L,"package"); lua_call(L, 1, 0); } -void clua_openstring(lua_State* L){ +void clua_openstring(lua_State* L) +{ lua_pushcfunction(L,&luaopen_string); lua_pushstring(L,"string"); lua_call(L, 1, 0); } -void clua_opentable(lua_State* L){ +void clua_opentable(lua_State* L) +{ lua_pushcfunction(L,&luaopen_table); lua_pushstring(L,"table"); lua_call(L, 1, 0); } -void clua_openos(lua_State* L){ +void clua_openos(lua_State* L) +{ lua_pushcfunction(L,&luaopen_os); lua_pushstring(L,"os"); lua_call(L, 1, 0); } -void clua_hook_function(lua_State *L, lua_Debug *ar) { - lua_checkstack(L, 2); - lua_pushstring(L, "Lua execution quantum exceeded"); - lua_error(L); +void clua_hook_function(lua_State *L, lua_Debug *ar) +{ + lua_checkstack(L, 2); + lua_pushstring(L, "Lua execution quantum exceeded"); + lua_error(L); } -void clua_setexecutionlimit(lua_State* L, int n) { - lua_sethook(L, &clua_hook_function, LUA_MASKCOUNT, n); +void clua_setexecutionlimit(lua_State* L, int n) +{ + lua_sethook(L, &clua_hook_function, LUA_MASKCOUNT, n); } /* taken from lua5.2 source */ -void *testudata(lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ +void *testudata(lua_State *L, int ud, const char *tname) +{ + void *p = lua_touserdata(L, ud); + if (p != NULL) + { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) + { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ } -int clua_isgofunction(lua_State *L, int n) { - return testudata(L, n, MT_GOFUNCTION) != NULL; +int clua_isgofunction(lua_State *L, int n) +{ + return testudata(L, n, MT_GOFUNCTION) != NULL; } -int clua_isgostruct(lua_State *L, int n) { - return testudata(L, n, MT_GOINTERFACE) != NULL; +int clua_isgostruct(lua_State *L, int n) +{ + return testudata(L, n, MT_GOINTERFACE) != NULL; } diff --git a/lua/golua.go b/lua/golua.go index 52092006..1ff48354 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -10,29 +10,29 @@ package lua import "C" import ( - "unsafe" "reflect" + "unsafe" ) -type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer; +type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer // this is the type of go function that can be registered as lua functions -type LuaGoFunction func(L *State) int; +type LuaGoFunction func(L *State) int //wrapper to keep cgo from complaining about incomplete ptr type //export State type State struct { - s *C.lua_State; - registry []interface{}; + s *C.lua_State + registry []interface{} //freelist for funcs indices, to allow for freeing - freeIndices []uint; + freeIndices []uint } //export golua_callgofunction func golua_callgofunction(L interface{}, fid uint) int { - L1 := L.(*State); - f := L1.registry[fid].(LuaGoFunction); - return f(L1); + L1 := L.(*State) + f := L1.registry[fid].(LuaGoFunction) + return f(L1) } //export golua_interface_newindex_callback @@ -57,33 +57,41 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval.SetBool(int(C.lua_toboolean(L.s, 3)) != 0) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) return -1 } - case reflect.Int: fallthrough - case reflect.Int8: fallthrough - case reflect.Int16: fallthrough - case reflect.Int32: fallthrough + case reflect.Int: + fallthrough + case reflect.Int8: + fallthrough + case reflect.Int16: + fallthrough + case reflect.Int32: + fallthrough case reflect.Int64: if luatype == LUA_TNUMBER { fval.SetInt(int64(C.lua_tointeger(L.s, 3))) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) return -1 } - case reflect.Uint: fallthrough - case reflect.Uint8: fallthrough - case reflect.Uint16: fallthrough - case reflect.Uint32: fallthrough + case reflect.Uint: + fallthrough + case reflect.Uint8: + fallthrough + case reflect.Uint16: + fallthrough + case reflect.Uint32: + fallthrough case reflect.Uint64: if luatype == LUA_TNUMBER { fval.SetUint(uint64(C.lua_tointeger(L.s, 3))) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) return -1 } @@ -92,23 +100,24 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval.SetString(C.GoString(C.lua_tolstring(L.s, 3, nil))) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) + C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) return -1 } - case reflect.Float32: fallthrough - case reflect.Float64: - if luatype == LUA_TNUMBER { - fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) + case reflect.Float32: + fallthrough + case reflect.Float64: + if luatype == LUA_TNUMBER { + fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) return 1 - } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field " + field_name)) - return -1 - } + } else { + C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) + return -1 + } } - C.lua_pushstring(L.s, C.CString("Unsupported type of field " + field_name + ": " + fval.Type().String())) - return -1; + C.lua_pushstring(L.s, C.CString("Unsupported type of field "+field_name+": "+fval.Type().String())) + return -1 } //export golua_interface_index_callback @@ -128,18 +137,26 @@ func golua_interface_index_callback(Li interface{}, iid uint, field_name *C.char L.PushBoolean(fval.Bool()) return 1 - case reflect.Int: fallthrough - case reflect.Int8: fallthrough - case reflect.Int16: fallthrough - case reflect.Int32: fallthrough + case reflect.Int: + fallthrough + case reflect.Int8: + fallthrough + case reflect.Int16: + fallthrough + case reflect.Int32: + fallthrough case reflect.Int64: L.PushInteger(fval.Int()) return 1 - case reflect.Uint: fallthrough - case reflect.Uint8: fallthrough - case reflect.Uint16: fallthrough - case reflect.Uint32: fallthrough + case reflect.Uint: + fallthrough + case reflect.Uint8: + fallthrough + case reflect.Uint16: + fallthrough + case reflect.Uint32: + fallthrough case reflect.Uint64: L.PushInteger(int64(fval.Uint())) return 1 @@ -148,41 +165,42 @@ func golua_interface_index_callback(Li interface{}, iid uint, field_name *C.char L.PushString(fval.String()) return 1 - case reflect.Float32: fallthrough - case reflect.Float64: + case reflect.Float32: + fallthrough + case reflect.Float64: L.PushNumber(fval.Float()) return 1 } - C.lua_pushstring(L.s, C.CString("Unsupported type of field: " + fval.Type().String())) - return -1; + C.lua_pushstring(L.s, C.CString("Unsupported type of field: "+fval.Type().String())) + return -1 } //export golua_gchook func golua_gchook(L interface{}, id uint) int { - L1 := L.(*State); - L1.unregister(id); - return 0; + L1 := L.(*State) + L1.unregister(id) + return 0 } //export golua_callpanicfunction func golua_callpanicfunction(L interface{}, id uint) int { - L1 := L.(*State); - f := L1.registry[id].(LuaGoFunction); - return f(L1); + L1 := L.(*State) + f := L1.registry[id].(LuaGoFunction) + return f(L1) } //export golua_idtointerface func golua_idtointerface(id uint) interface{} { - return id; + return id } //export golua_cfunctiontointerface func golua_cfunctiontointerface(f *uintptr) interface{} { - return f; + return f } //export golua_callallocf func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { - return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr),osize,nsize)); + return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr), osize, nsize)) } diff --git a/lua/lauxlib.go b/lua/lauxlib.go index d7059855..a7487a86 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -7,6 +7,7 @@ package lua //#include "golua.h" import "C" import "unsafe" + //luaL_addchar //luaL_addlstring //luaL_addsize @@ -23,16 +24,16 @@ func (err *LuaError) Error() string { func ArgCheck(L *State, cond bool, narg int, extramsg string) { if cond { - Cextramsg := C.CString(extramsg) + Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) C.luaL_argerror(L.s, C.int(narg), Cextramsg) } } func ArgError(L *State, narg int, extramsg string) int { - Cextramsg := C.CString(extramsg) + Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) - return int(C.luaL_argerror(L.s,C.int(narg),Cextramsg)); + return int(C.luaL_argerror(L.s, C.int(narg), Cextramsg)) } //type luaL_Buffer @@ -40,55 +41,55 @@ func ArgError(L *State, narg int, extramsg string) int { //luaL_buffinit func CallMeta(L *State, obj int, e string) int { - Ce := C.CString(e) + Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) - return int(C.luaL_callmeta(L.s,C.int(obj),Ce)) + return int(C.luaL_callmeta(L.s, C.int(obj), Ce)) } func CheckAny(L *State, narg int) { - C.luaL_checkany(L.s,C.int(narg)); + C.luaL_checkany(L.s, C.int(narg)) } func CheckInteger(L *State, narg int) int { - return int(C.luaL_checkinteger(L.s,C.int(narg))); + return int(C.luaL_checkinteger(L.s, C.int(narg))) } func CheckNumber(L *State, narg int) float64 { - return float64(C.luaL_checknumber(L.s,C.int(narg))); + return float64(C.luaL_checknumber(L.s, C.int(narg))) } func CheckString(L *State, narg int) string { - var length C.size_t; - return C.GoString( C.luaL_checklstring(L.s,C.int(narg),&length) ); + var length C.size_t + return C.GoString(C.luaL_checklstring(L.s, C.int(narg), &length)) } func CheckOption(L *State, narg int, def string, lst []string) int { //TODO: complication: lst conversion to const char* lst[] from string slice - return 0; + return 0 } func CheckType(L *State, narg int, t int) { - C.luaL_checktype(L.s,C.int(narg),C.int(t)); + C.luaL_checktype(L.s, C.int(narg), C.int(t)) } func CheckUdata(L *State, narg int, tname string) unsafe.Pointer { - Ctname := C.CString(tname) + Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) - return unsafe.Pointer(C.luaL_checkudata(L.s,C.int(narg),Ctname)) + return unsafe.Pointer(C.luaL_checkudata(L.s, C.int(narg), Ctname)) } //true if no errors, false otherwise func (L *State) DoFile(filename string) bool { if L.LoadFile(filename) == 0 { - return L.PCall(0,LUA_MULTRET,0) == 0; + return L.PCall(0, LUA_MULTRET, 0) == 0 } - return false; + return false } //nil if no errors, an error otherwise func (L *State) DoString(str string) error { if L.LoadString(str) == 0 { - if L.PCall(0,LUA_MULTRET,0) == 0 { + if L.PCall(0, LUA_MULTRET, 0) == 0 { return nil } } @@ -103,33 +104,33 @@ func (L *State) MustDoString(str string) { } //luaL_error becomes FmtError because of lua_error -func FmtError(L *State, fmt string, args...interface{}) int { +func FmtError(L *State, fmt string, args ...interface{}) int { //TODO: complication: pass varargs - return 0; + return 0 } //returns false if no such metatable or no such field func GetMetaField(L *State, obj int, e string) bool { - Ce := C.CString(e) + Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) - return C.luaL_getmetafield(L.s,C.int(obj),Ce) != 0; + return C.luaL_getmetafield(L.s, C.int(obj), Ce) != 0 } //TODO: rename better... clashes with lua_getmetatable func LGetMetaTable(L *State, tname string) { - Ctname := C.CString(tname) + Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) - C.lua_getfield(L.s,LUA_REGISTRYINDEX,Ctname); + C.lua_getfield(L.s, LUA_REGISTRYINDEX, Ctname) } func GSub(L *State, s string, p string, r string) string { - Cs := C.CString(s) - Cp := C.CString(p) - Cr := C.CString(r) - defer func(){ - C.free(unsafe.Pointer(Cs)) - C.free(unsafe.Pointer(Cp)) - C.free(unsafe.Pointer(Cr)) + Cs := C.CString(s) + Cp := C.CString(p) + Cr := C.CString(r) + defer func() { + C.free(unsafe.Pointer(Cs)) + C.free(unsafe.Pointer(Cp)) + C.free(unsafe.Pointer(Cr)) }() return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) @@ -137,75 +138,74 @@ func GSub(L *State, s string, p string, r string) string { //TODO: luaL_loadbuffer - func (L *State) LoadFile(filename string) int { - Cfilename := C.CString(filename) + Cfilename := C.CString(filename) defer C.free(unsafe.Pointer(Cfilename)) - return int(C.luaL_loadfile(L.s,Cfilename)); + return int(C.luaL_loadfile(L.s, Cfilename)) } func (L *State) LoadString(s string) int { - Cs := C.CString(s) + Cs := C.CString(s) defer C.free(unsafe.Pointer(Cs)) - return int(C.luaL_loadstring(L.s,Cs)) + return int(C.luaL_loadstring(L.s, Cs)) } //returns false if registry already contains key tname func (L *State) NewMetaTable(tname string) bool { - Ctname := C.CString(tname) + Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) - return C.luaL_newmetatable(L.s, Ctname) != 0; + return C.luaL_newmetatable(L.s, Ctname) != 0 } func NewState() *State { - ls := (C.luaL_newstate()); - L := newState(ls); - return L; + ls := (C.luaL_newstate()) + L := newState(ls) + return L } func (L *State) OpenLibs() { - C.luaL_openlibs(L.s); + C.luaL_openlibs(L.s) } func (L *State) OptInteger(narg int, d int) int { - return int(C.luaL_optinteger(L.s,C.int(narg),C.lua_Integer(d))); + return int(C.luaL_optinteger(L.s, C.int(narg), C.lua_Integer(d))) } func (L *State) OptNumber(narg int, d float64) float64 { - return float64(C.luaL_optnumber(L.s,C.int(narg),C.lua_Number(d))); + return float64(C.luaL_optnumber(L.s, C.int(narg), C.lua_Number(d))) } func (L *State) OptString(narg int, d string) string { - var length C.size_t; + var length C.size_t Cd := C.CString(d) defer C.free(unsafe.Pointer(Cd)) - return C.GoString(C.luaL_optlstring(L.s,C.int(narg),Cd,&length)); + return C.GoString(C.luaL_optlstring(L.s, C.int(narg), Cd, &length)) } //luaL_prepbuffer func (L *State) Ref(t int) int { - return int(C.luaL_ref(L.s,C.int(t))); + return int(C.luaL_ref(L.s, C.int(t))) } //TODO: register - definately doable //TODO: rename better func LTypename(L *State, index int) string { - return C.GoString(C.lua_typename(L.s,C.lua_type(L.s,C.int(index)))); + return C.GoString(C.lua_typename(L.s, C.lua_type(L.s, C.int(index)))) } //TODO: decide if we actually want this renamed func TypeError(L *State, narg int, tname string) int { - Ctname := C.CString(tname) + Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) - return int(C.luaL_typerror(L.s,C.int(narg),Ctname)) + return int(C.luaL_typerror(L.s, C.int(narg), Ctname)) } func Unref(L *State, t int, ref int) { - C.luaL_unref(L.s,C.int(t),C.int(ref)); + C.luaL_unref(L.s, C.int(t), C.int(ref)) } func Where(L *State, lvl int) { - C.luaL_where(L.s,C.int(lvl)); + C.luaL_where(L.s, C.int(lvl)) } diff --git a/lua/lua.go b/lua/lua.go index 8f548f1b..0e46eecb 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -14,91 +14,91 @@ import "C" import "unsafe" //like lua_Writer, but as p will contain capacity, not needed as separate param -type Writer func(L *State, p []byte, ud interface{}); +type Writer func(L *State, p []byte, ud interface{}) + //like lua reader, but the return slice has the size, so does // we do not need it to be an out param -type Reader func(L *State, data interface{}) []byte; +type Reader func(L *State, data interface{}) []byte func newState(L *C.lua_State) *State { var newstatei interface{} - newstate := &State{L, make([]interface{},0,8), make([]uint,0,8)}; - newstatei = newstate; - ns1 := unsafe.Pointer(&newstatei); - ns2 := (*C.GoInterface)(ns1); - C.clua_setgostate(L,*ns2); //hacky.... + newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8)} + newstatei = newstate + ns1 := unsafe.Pointer(&newstatei) + ns2 := (*C.GoInterface)(ns1) + C.clua_setgostate(L, *ns2) //hacky.... C.clua_initstate(L) - return newstate; + return newstate } func (L *State) addFreeIndex(i uint) { freelen := len(L.freeIndices) //reallocate if necessary if freelen+1 > cap(L.freeIndices) { - newSlice := make([]uint, freelen, cap(L.freeIndices)*2); - copy(newSlice, L.freeIndices); - L.freeIndices = newSlice; + newSlice := make([]uint, freelen, cap(L.freeIndices)*2) + copy(newSlice, L.freeIndices) + L.freeIndices = newSlice } //reslice - L.freeIndices = L.freeIndices[0:freelen+1]; - L.freeIndices[freelen] = i; + L.freeIndices = L.freeIndices[0 : freelen+1] + L.freeIndices[freelen] = i } func (L *State) getFreeIndex() (index uint, ok bool) { - freelen := len(L.freeIndices); + freelen := len(L.freeIndices) //if there exist entries in the freelist if freelen > 0 { - i := L.freeIndices[freelen - 1]; //get index - L.freeIndices = L.freeIndices[0:i]; //'pop' index from list - return i, true; + i := L.freeIndices[freelen-1] //get index + L.freeIndices = L.freeIndices[0:i] //'pop' index from list + return i, true } - return 0,false; + return 0, false } //returns the registered function id func (L *State) register(f interface{}) uint { - index,ok := L.getFreeIndex(); + index, ok := L.getFreeIndex() //if not ok, then we need to add new index by extending the slice if !ok { - index = uint(len(L.registry)); + index = uint(len(L.registry)) //reallocate backing array if necessary if index+1 > uint(cap(L.registry)) { - newSlice := make([]interface{},index,cap(L.registry)*2); - copy(newSlice, L.registry); - L.registry = newSlice; + newSlice := make([]interface{}, index, cap(L.registry)*2) + copy(newSlice, L.registry) + L.registry = newSlice } //reslice - L.registry = L.registry[0:index+1] + L.registry = L.registry[0 : index+1] } - L.registry[index] = f; - return index; + L.registry[index] = f + return index } func (L *State) unregister(fid uint) { if (fid < uint(len(L.registry))) && (L.registry[fid] != nil) { - L.registry[fid] = nil; - L.addFreeIndex(fid); + L.registry[fid] = nil + L.addFreeIndex(fid) } } func (L *State) PushGoFunction(f LuaGoFunction) { - fid := L.register(f); - C.clua_pushgofunction(L.s,C.uint(fid)); + fid := L.register(f) + C.clua_pushgofunction(L.s, C.uint(fid)) } func (L *State) PushGoStruct(iface interface{}) { - iid := L.register(iface); - C.clua_pushgostruct(L.s, C.uint(iid)); + iid := L.register(iface) + C.clua_pushgostruct(L.s, C.uint(iid)) } /*func (L *State) PushLightInteger(n int) { C.clua_pushlightinteger(L.s, C.int(n)) }*/ - //push pointer by value, as a value - we don't impact lifetime func (L *State) PushLightUserdata(ud *interface{}) { //push - C.lua_pushlightuserdata(L.s,unsafe.Pointer(ud)); + C.lua_pushlightuserdata(L.s, unsafe.Pointer(ud)) } /* @@ -112,72 +112,72 @@ func PushUserdata(L *State, ud interface{}) { //old style func (L *State) NewUserdata(size uintptr) unsafe.Pointer { - return unsafe.Pointer(C.lua_newuserdata(L.s, C.size_t(size))); + return unsafe.Pointer(C.lua_newuserdata(L.s, C.size_t(size))) } func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { - fid := uint(0); + fid := uint(0) if panicf != nil { - fid = L.register(panicf); + fid = L.register(panicf) } - oldres := interface{}(C.clua_atpanic(L.s,C.uint(fid))); + oldres := interface{}(C.clua_atpanic(L.s, C.uint(fid))) switch i := oldres.(type) { case C.uint: - f := L.registry[uint(i)].(LuaGoFunction); + f := L.registry[uint(i)].(LuaGoFunction) //free registry entry - L.unregister(uint(i)); - return f; + L.unregister(uint(i)) + return f case C.lua_CFunction: return func(L1 *State) int { - return int(C.clua_callluacfunc(L1.s,i)); + return int(C.clua_callluacfunc(L1.s, i)) } } //generally we only get here if the panicf got set to something like nil //potentially dangerous because we may silently fail - return nil; + return nil } func (L *State) Call(nargs int, nresults int) { - C.lua_call(L.s,C.int(nargs),C.int(nresults)); + C.lua_call(L.s, C.int(nargs), C.int(nresults)) } func (L *State) CheckStack(extra int) bool { - return C.lua_checkstack(L.s, C.int(extra)) != 0; + return C.lua_checkstack(L.s, C.int(extra)) != 0 } func (L *State) Close() { - C.lua_close(L.s); + C.lua_close(L.s) } func (L *State) Concat(n int) { - C.lua_concat(L.s,C.int(n)); + C.lua_concat(L.s, C.int(n)) } func (L *State) CreateTable(narr int, nrec int) { - C.lua_createtable(L.s, C.int(narr), C.int(nrec)); + C.lua_createtable(L.s, C.int(narr), C.int(nrec)) } //CPcall replacement func (L *State) GoPCall(fun LuaGoFunction, ud interface{}) int { //TODO: need to emulate by pushing a c closure as in pushgofunction - return 0; + return 0 } //TODO: data be a slice? -func (L *State) Dump( writer Writer, data interface{}) int { +func (L *State) Dump(writer Writer, data interface{}) int { //TODO: - return 0; + return 0 } func (L *State) Equal(index1, index2 int) bool { return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 } -func (L *State) Error() int { return int(C.lua_error(L.s)) } +func (L *State) Error() int { return int(C.lua_error(L.s)) } -func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } +func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } -func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } +func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } func (L *State) GetField(index int, k string) { Ck := C.CString(k) @@ -185,17 +185,17 @@ func (L *State) GetField(index int, k string) { C.lua_getfield(L.s, C.int(index), Ck) } -func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } +func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } func (L *State) GetMetaTable(index int) bool { return C.lua_getmetatable(L.s, C.int(index)) != 0 } -func (L *State) GetTable(index int) { C.lua_gettable(L.s, C.int(index)) } +func (L *State) GetTable(index int) { C.lua_gettable(L.s, C.int(index)) } -func (L *State) GetTop() int { return int(C.lua_gettop(L.s)) } +func (L *State) GetTop() int { return int(C.lua_gettop(L.s)) } -func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } +func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } func (L *State) IsBoolean(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TBOOLEAN @@ -217,23 +217,23 @@ func (L *State) IsLightUserdata(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TLIGHTUSERDATA } -func (L *State) IsNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNIL } +func (L *State) IsNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNIL } -func (L *State) IsNone(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNONE } +func (L *State) IsNone(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNONE } -func (L *State) IsNoneOrNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) <= 0 } +func (L *State) IsNoneOrNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) <= 0 } -func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(index)) == 1 } +func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(index)) == 1 } -func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } +func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } -func (L *State) IsTable(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } +func (L *State) IsTable(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } func (L *State) IsThread(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TTHREAD } -func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int(index)) == 1 } +func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int(index)) == 1 } func (L *State) LessThan(index1, index2 int) bool { return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 @@ -241,7 +241,7 @@ func (L *State) LessThan(index1, index2 int) bool { func (L *State) Load(reader Reader, data interface{}, chunkname string) int { //TODO: - return 0; + return 0 } //NOTE: lua_newstate becomes NewStateAlloc whereas @@ -250,120 +250,119 @@ func NewStateAlloc(f Alloc) *State { //TODO: implement a newState function which will initialize a State // call with result from C.lua_newstate for the s initializer //ls := lua_newstate( - ls := C.clua_newstate(unsafe.Pointer(&f)); + ls := C.clua_newstate(unsafe.Pointer(&f)) //ls := clua_newstate( - return newState(ls); + return newState(ls) } func (L *State) NewTable() { - C.lua_createtable(L.s,0,0); + C.lua_createtable(L.s, 0, 0) } - func (L *State) NewThread() *State { //TODO: call newState with result from C.lua_newthread and return it //TODO: should have same lists as parent // but may complicate gc - s := C.lua_newthread(L.s); - return &State{s,nil,nil}; + s := C.lua_newthread(L.s) + return &State{s, nil, nil} } func (L *State) Next(index int) int { - return int(C.lua_next(L.s,C.int(index))); + return int(C.lua_next(L.s, C.int(index))) } func (L *State) ObjLen(index int) uint { - return uint(C.lua_objlen(L.s,C.int(index))); + return uint(C.lua_objlen(L.s, C.int(index))) } func (L *State) PCall(nargs int, nresults int, errfunc int) int { - return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))); + return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) } func (L *State) Pop(n int) { //C.lua_pop(L.s, C.int(n)); - C.lua_settop(L.s, C.int(-n-1)); + C.lua_settop(L.s, C.int(-n-1)) } func (L *State) PushBoolean(b bool) { - var bint int; + var bint int if b { - bint = 1; + bint = 1 } else { - bint = 0; + bint = 0 } - C.lua_pushboolean(L.s, C.int(bint)); + C.lua_pushboolean(L.s, C.int(bint)) } func (L *State) PushString(str string) { Cstr := C.CString(str) defer C.free(unsafe.Pointer(Cstr)) - C.lua_pushstring(L.s,Cstr) + C.lua_pushstring(L.s, Cstr) } func (L *State) PushInteger(n int64) { - C.lua_pushinteger(L.s,C.lua_Integer(n)); + C.lua_pushinteger(L.s, C.lua_Integer(n)) } func (L *State) PushNil() { - C.lua_pushnil(L.s); + C.lua_pushnil(L.s) } func (L *State) PushNumber(n float64) { - C.lua_pushnumber(L.s, C.lua_Number(n)); + C.lua_pushnumber(L.s, C.lua_Number(n)) } func (L *State) PushThread() (isMain bool) { - return C.lua_pushthread(L.s) != 0; + return C.lua_pushthread(L.s) != 0 } func (L *State) PushValue(index int) { - C.lua_pushvalue(L.s, C.int(index)); + C.lua_pushvalue(L.s, C.int(index)) } func (L *State) RawEqual(index1 int, index2 int) bool { - return C.lua_rawequal(L.s, C.int(index1), C.int(index2)) != 0; + return C.lua_rawequal(L.s, C.int(index1), C.int(index2)) != 0 } func (L *State) RawGet(index int) { - C.lua_rawget(L.s, C.int(index)); + C.lua_rawget(L.s, C.int(index)) } func (L *State) RawGeti(index int, n int) { - C.lua_rawgeti(L.s, C.int(index), C.int(n)); + C.lua_rawgeti(L.s, C.int(index), C.int(n)) } func (L *State) RawSet(index int) { - C.lua_rawset(L.s, C.int(index)); + C.lua_rawset(L.s, C.int(index)) } func (L *State) RawSeti(index int, n int) { - C.lua_rawseti(L.s, C.int(index), C.int(n)); + C.lua_rawseti(L.s, C.int(index), C.int(n)) } func (L *State) Register(name string, f LuaGoFunction) { - L.PushGoFunction(f); - L.SetGlobal(name); + L.PushGoFunction(f) + L.SetGlobal(name) } func (L *State) Remove(index int) { - C.lua_remove(L.s, C.int(index)); + C.lua_remove(L.s, C.int(index)) } func (L *State) Replace(index int) { - C.lua_replace(L.s, C.int(index)); + C.lua_replace(L.s, C.int(index)) } func (L *State) Resume(narg int) int { - return int(C.lua_resume(L.s, C.int(narg))); + return int(C.lua_resume(L.s, C.int(narg))) } func (L *State) SetAllocf(f Alloc) { - C.clua_setallocf(L.s,unsafe.Pointer(&f)); + C.clua_setallocf(L.s, unsafe.Pointer(&f)) } func (L *State) SetfEnv(index int) { - C.lua_setfenv(L.s, C.int(index)); + C.lua_setfenv(L.s, C.int(index)) } func (L *State) SetField(index int, k string) { @@ -379,46 +378,46 @@ func (L *State) SetGlobal(name string) { } func (L *State) SetMetaTable(index int) { - C.lua_setmetatable(L.s, C.int(index)); + C.lua_setmetatable(L.s, C.int(index)) } func (L *State) SetTable(index int) { - C.lua_settable(L.s, C.int(index)); + C.lua_settable(L.s, C.int(index)) } func (L *State) SetTop(index int) { - C.lua_settop(L.s, C.int(index)); + C.lua_settop(L.s, C.int(index)) } func (L *State) Status() int { - return int(C.lua_status(L.s)); + return int(C.lua_status(L.s)) } func (L *State) ToBoolean(index int) bool { - return C.lua_toboolean(L.s, C.int(index)) != 0; + return C.lua_toboolean(L.s, C.int(index)) != 0 } func (L *State) ToGoFunction(index int) (f LuaGoFunction) { - fid := C.clua_togofunction(L.s,C.int(index)) - return L.registry[fid].(LuaGoFunction); + fid := C.clua_togofunction(L.s, C.int(index)) + return L.registry[fid].(LuaGoFunction) } func (L *State) ToString(index int) string { - var size C.size_t; + var size C.size_t //C.GoString(C.lua_tolstring(L.s, C.int(index), &size)); - return C.GoString(C.lua_tolstring(L.s,C.int(index),&size)); + return C.GoString(C.lua_tolstring(L.s, C.int(index), &size)) } func (L *State) ToInteger(index int) int { - return int(C.lua_tointeger(L.s, C.int(index))); + return int(C.lua_tointeger(L.s, C.int(index))) } func (L *State) ToNumber(index int) float64 { - return float64(C.lua_tonumber(L.s, C.int(index))); + return float64(C.lua_tonumber(L.s, C.int(index))) } func (L *State) ToPointer(index int) uintptr { - return uintptr(C.lua_topointer(L.s, C.int(index))); + return uintptr(C.lua_topointer(L.s, C.int(index))) } func (L *State) ToThread(index int) *State { @@ -427,7 +426,7 @@ func (L *State) ToThread(index int) *State { } func (L *State) ToUserdata(index int) unsafe.Pointer { - return unsafe.Pointer(C.lua_touserdata(L.s,C.int(index))); + return unsafe.Pointer(C.lua_touserdata(L.s, C.int(index))) } /*func (L *State) ToLightInteger(index int) int { @@ -435,51 +434,51 @@ func (L *State) ToUserdata(index int) unsafe.Pointer { }*/ func (L *State) Type(index int) int { - return int(C.lua_type(L.s, C.int(index))); + return int(C.lua_type(L.s, C.int(index))) } func (L *State) Typename(tp int) string { - return C.GoString(C.lua_typename(L.s, C.int(tp))); + return C.GoString(C.lua_typename(L.s, C.int(tp))) } func XMove(from *State, to *State, n int) { - C.lua_xmove(from.s, to.s, C.int(n)); + C.lua_xmove(from.s, to.s, C.int(n)) } func (L *State) Yield(nresults int) int { - return int(C.lua_yield(L.s, C.int(nresults))); + return int(C.lua_yield(L.s, C.int(nresults))) } // Restricted library opens func (L *State) OpenBase() { - C.clua_openbase(L.s); + C.clua_openbase(L.s) } func (L *State) OpenIO() { - C.clua_openio(L.s); + C.clua_openio(L.s) } func (L *State) OpenMath() { - C.clua_openmath(L.s); + C.clua_openmath(L.s) } func (L *State) OpenPackage() { - C.clua_openpackage(L.s); + C.clua_openpackage(L.s) } func (L *State) OpenString() { - C.clua_openstring(L.s); + C.clua_openstring(L.s) } func (L *State) OpenTable() { - C.clua_opentable(L.s); + C.clua_opentable(L.s) } func (L *State) OpenOS() { - C.clua_openos(L.s); + C.clua_openos(L.s) } func (L *State) SetExecutionLimit(instrNumber int) { - C.clua_setexecutionlimit(L.s, C.int(instrNumber)); + C.clua_setexecutionlimit(L.s, C.int(instrNumber)) } diff --git a/lua/lua_defs.go b/lua/lua_defs.go index 89576d7f..96409ee5 100644 --- a/lua/lua_defs.go +++ b/lua/lua_defs.go @@ -1,4 +1,5 @@ package lua + /* #include #include @@ -6,6 +7,7 @@ package lua */ import "C" + const LUA_VERSION = C.LUA_VERSION const LUA_RELEASE = C.LUA_RELEASE const LUA_VERSION_NUM = C.LUA_VERSION_NUM From e36b6d303a8ba56168f1b0551cc7010643ad01f6 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 18 Jul 2012 17:14:12 +0200 Subject: [PATCH 016/100] removed some garbage, collected TODO items, made lauxlib functions into methods --- TODO | 6 ++++++ lua/c-golua.c | 15 ++++++-------- lua/golua.go | 16 +++++++-------- lua/golua.h | 3 +-- lua/lauxlib.go | 56 +++++++++++++++++++------------------------------- lua/lua.go | 45 ++++++++++------------------------------ 6 files changed, 53 insertions(+), 88 deletions(-) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 00000000..64ffd07a --- /dev/null +++ b/TODO @@ -0,0 +1,6 @@ +- documentation +- lua.go:Dump +- lua.go:Load +- AtPanic slightly broken when nil is passed, if we think passing nil has value to extract the current atpanic function we should also make sure it doesn't break everything +- threads implementation is probably fucked completely should look into it +- lauxlib.go:CheckOption is not implemented \ No newline at end of file diff --git a/lua/c-golua.c b/lua/c-golua.c index adcd1bae..46d140e7 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -51,13 +51,10 @@ int callback_function(lua_State* L) //wrapper for gchook int gchook_wrapper(lua_State* L) { - unsigned int* fid = clua_checkgosomething(L, -1, NULL); //TODO: this will error + unsigned int* fid = clua_checkgosomething(L, -1, NULL); GoInterface* gi = clua_getgostate(L); if(fid != NULL) return golua_gchook(*gi,*fid); - printf("GCHook failed\n"); - //TODO: try udata or whatever, after impl - return 0; } @@ -224,16 +221,16 @@ GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id) unsigned int old_id; lua_pushlightuserdata(L, (void*)&PanicFIDRegistryKey); lua_gettable(L,LUA_REGISTRYINDEX); - if(lua_isnil(L,-1) == 0) + if(lua_isnil(L, -1) == 0) old_id = lua_tointeger(L,-1); - lua_pop(L,1); + lua_pop(L, 1); //set registry key for function id of go panic function - lua_pushlightuserdata(L,(void*)&PanicFIDRegistryKey); + lua_pushlightuserdata(L, (void*)&PanicFIDRegistryKey); //push id value - lua_pushinteger(L,panicf_id); + lua_pushinteger(L, panicf_id); //set into registry table - lua_settable(L,LUA_REGISTRYINDEX); + lua_settable(L, LUA_REGISTRYINDEX); //now set the panic function lua_CFunction pf = lua_atpanic(L,&callback_panicf); diff --git a/lua/golua.go b/lua/golua.go index 1ff48354..028f2ea0 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -22,7 +22,7 @@ type LuaGoFunction func(L *State) int //wrapper to keep cgo from complaining about incomplete ptr type //export State type State struct { - s *C.lua_State + s *C.lua_State registry []interface{} //freelist for funcs indices, to allow for freeing freeIndices []uint @@ -57,7 +57,7 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval.SetBool(int(C.lua_toboolean(L.s, 3)) != 0) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) + L.PushString("Wrong assignment to field "+field_name) return -1 } @@ -74,7 +74,7 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval.SetInt(int64(C.lua_tointeger(L.s, 3))) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) + L.PushString("Wrong assignment to field "+field_name) return -1 } @@ -91,7 +91,7 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval.SetUint(uint64(C.lua_tointeger(L.s, 3))) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) + L.PushString("Wrong assignment to field "+field_name) return -1 } @@ -100,7 +100,7 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval.SetString(C.GoString(C.lua_tolstring(L.s, 3, nil))) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) + L.PushString("Wrong assignment to field "+field_name) return -1 } @@ -111,12 +111,12 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) return 1 } else { - C.lua_pushstring(L.s, C.CString("Wrong assignment to field "+field_name)) + L.PushString("Wrong assignment to field "+field_name) return -1 } } - C.lua_pushstring(L.s, C.CString("Unsupported type of field "+field_name+": "+fval.Type().String())) + L.PushString("Unsupported type of field "+field_name+": "+fval.Type().String()) return -1 } @@ -172,7 +172,7 @@ func golua_interface_index_callback(Li interface{}, iid uint, field_name *C.char return 1 } - C.lua_pushstring(L.s, C.CString("Unsupported type of field: "+fval.Type().String())) + L.PushString("Unsupported type of field: "+fval.Type().String()) return -1 } diff --git a/lua/golua.h b/lua/golua.h index acd79211..a15b1893 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -6,10 +6,9 @@ typedef struct { void *t; void *v; } GoInterface; void clua_initstate(lua_State* L); unsigned int clua_togofunction(lua_State* L, int index); +unsigned int clua_togostruct(lua_State *L, int index); void clua_pushgofunction(lua_State* L, unsigned int fid); void clua_pushgostruct(lua_State *L, unsigned int fid); -void clua_pushlightinteger(lua_State* L, int n); -uintptr_t clua_tolightinteger(lua_State* L, int index); void clua_setgostate(lua_State* L, GoInterface gostate); GoInterface* clua_getgostate(lua_State* L); GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id); diff --git a/lua/lauxlib.go b/lua/lauxlib.go index a7487a86..0baafe54 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -22,7 +22,7 @@ func (err *LuaError) Error() string { return err.message } -func ArgCheck(L *State, cond bool, narg int, extramsg string) { +func (L *State) ArgCheck(cond bool, narg int, extramsg string) { if cond { Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) @@ -30,7 +30,7 @@ func ArgCheck(L *State, cond bool, narg int, extramsg string) { } } -func ArgError(L *State, narg int, extramsg string) int { +func (L *State) ArgError(narg int, extramsg string) int { Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) return int(C.luaL_argerror(L.s, C.int(narg), Cextramsg)) @@ -40,39 +40,39 @@ func ArgError(L *State, narg int, extramsg string) int { //luaL_buffinit -func CallMeta(L *State, obj int, e string) int { +func (L *State) CallMeta(obj int, e string) int { Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) return int(C.luaL_callmeta(L.s, C.int(obj), Ce)) } -func CheckAny(L *State, narg int) { +func (L *State) CheckAny(narg int) { C.luaL_checkany(L.s, C.int(narg)) } -func CheckInteger(L *State, narg int) int { +func (L *State) CheckInteger(narg int) int { return int(C.luaL_checkinteger(L.s, C.int(narg))) } -func CheckNumber(L *State, narg int) float64 { +func (L *State) CheckNumber(narg int) float64 { return float64(C.luaL_checknumber(L.s, C.int(narg))) } -func CheckString(L *State, narg int) string { +func (L *State) CheckString(narg int) string { var length C.size_t return C.GoString(C.luaL_checklstring(L.s, C.int(narg), &length)) } -func CheckOption(L *State, narg int, def string, lst []string) int { +func (L *State) CheckOption(narg int, def string, lst []string) int { //TODO: complication: lst conversion to const char* lst[] from string slice return 0 } -func CheckType(L *State, narg int, t int) { +func (L *State) CheckType(narg int, t int) { C.luaL_checktype(L.s, C.int(narg), C.int(t)) } -func CheckUdata(L *State, narg int, tname string) unsafe.Pointer { +func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) return unsafe.Pointer(C.luaL_checkudata(L.s, C.int(narg), Ctname)) @@ -103,27 +103,21 @@ func (L *State) MustDoString(str string) { } } -//luaL_error becomes FmtError because of lua_error -func FmtError(L *State, fmt string, args ...interface{}) int { - //TODO: complication: pass varargs - return 0 -} - //returns false if no such metatable or no such field -func GetMetaField(L *State, obj int, e string) bool { +func (L *State) GetMetaField(obj int, e string) bool { Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) return C.luaL_getmetafield(L.s, C.int(obj), Ce) != 0 } //TODO: rename better... clashes with lua_getmetatable -func LGetMetaTable(L *State, tname string) { +func (L *State) LGetMetaTable(tname string) { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) C.lua_getfield(L.s, LUA_REGISTRYINDEX, Ctname) } -func GSub(L *State, s string, p string, r string) string { +func (L *State) GSub(s string, p string, r string) string { Cs := C.CString(s) Cp := C.CString(p) Cr := C.CString(r) @@ -136,8 +130,6 @@ func GSub(L *State, s string, p string, r string) string { return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) } -//TODO: luaL_loadbuffer - func (L *State) LoadFile(filename string) int { Cfilename := C.CString(filename) defer C.free(unsafe.Pointer(Cfilename)) @@ -182,30 +174,24 @@ func (L *State) OptString(narg int, d string) string { return C.GoString(C.luaL_optlstring(L.s, C.int(narg), Cd, &length)) } -//luaL_prepbuffer +func (L *State) ErrorWithMessage(errorMessage string) int { + L.PushString(errorMessage) + return L.Error() +} func (L *State) Ref(t int) int { return int(C.luaL_ref(L.s, C.int(t))) } -//TODO: register - definately doable - -//TODO: rename better -func LTypename(L *State, index int) string { +func (L *State) LTypename(index int) string { return C.GoString(C.lua_typename(L.s, C.lua_type(L.s, C.int(index)))) } -//TODO: decide if we actually want this renamed -func TypeError(L *State, narg int, tname string) int { - Ctname := C.CString(tname) - defer C.free(unsafe.Pointer(Ctname)) - return int(C.luaL_typerror(L.s, C.int(narg), Ctname)) -} - -func Unref(L *State, t int, ref int) { +func (L *State) Unref(t int, ref int) { C.luaL_unref(L.s, C.int(t), C.int(ref)) } -func Where(L *State, lvl int) { +func (L *State) Where(lvl int) { C.luaL_where(L.s, C.int(lvl)) } + diff --git a/lua/lua.go b/lua/lua.go index 0e46eecb..47f95b58 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -91,25 +91,12 @@ func (L *State) PushGoStruct(iface interface{}) { C.clua_pushgostruct(L.s, C.uint(iid)) } -/*func (L *State) PushLightInteger(n int) { - C.clua_pushlightinteger(L.s, C.int(n)) -}*/ - //push pointer by value, as a value - we don't impact lifetime func (L *State) PushLightUserdata(ud *interface{}) { //push C.lua_pushlightuserdata(L.s, unsafe.Pointer(ud)) } -/* -//TODO: -//push pointer as full userdata - mem is go owned, but we -//make a guarantee that lifetime will outlast lua lifetime -func PushUserdata(L *State, ud interface{}) { - -} -*/ - //old style func (L *State) NewUserdata(size uintptr) unsafe.Pointer { return unsafe.Pointer(C.lua_newuserdata(L.s, C.size_t(size))) @@ -157,15 +144,14 @@ func (L *State) CreateTable(narr int, nrec int) { C.lua_createtable(L.s, C.int(narr), C.int(nrec)) } -//CPcall replacement -func (L *State) GoPCall(fun LuaGoFunction, ud interface{}) int { - //TODO: need to emulate by pushing a c closure as in pushgofunction +//TODO: data be a slice? +func (L *State) Dump(writer Writer, data interface{}) int { + //TODO: Implement Dump return 0 } -//TODO: data be a slice? -func (L *State) Dump(writer Writer, data interface{}) int { - //TODO: +func (L *State) Load(reader Reader, data interface{}, chunkname string) int { + //TODO: Implement Load return 0 } @@ -239,19 +225,8 @@ func (L *State) LessThan(index1, index2 int) bool { return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 } -func (L *State) Load(reader Reader, data interface{}, chunkname string) int { - //TODO: - return 0 -} - -//NOTE: lua_newstate becomes NewStateAlloc whereas -// luaL_newstate becomes NewState func NewStateAlloc(f Alloc) *State { - //TODO: implement a newState function which will initialize a State - // call with result from C.lua_newstate for the s initializer - //ls := lua_newstate( ls := C.clua_newstate(unsafe.Pointer(&f)) - //ls := clua_newstate( return newState(ls) } @@ -280,6 +255,7 @@ func (L *State) PCall(nargs int, nresults int, errfunc int) int { } func (L *State) Pop(n int) { + //Why is this implemented this way? I don't get it... //C.lua_pop(L.s, C.int(n)); C.lua_settop(L.s, C.int(-n-1)) } @@ -402,6 +378,11 @@ func (L *State) ToGoFunction(index int) (f LuaGoFunction) { return L.registry[fid].(LuaGoFunction) } +func (L *State) ToGoStruct(index int) (f interface{}) { + fid := C.clua_togostruct(L.s, C.int(index)) + return L.registry[fid] +} + func (L *State) ToString(index int) string { var size C.size_t //C.GoString(C.lua_tolstring(L.s, C.int(index), &size)); @@ -429,10 +410,6 @@ func (L *State) ToUserdata(index int) unsafe.Pointer { return unsafe.Pointer(C.lua_touserdata(L.s, C.int(index))) } -/*func (L *State) ToLightInteger(index int) int { - return int(C.clua_tolightinteger(L.s, C.int(index))) -}*/ - func (L *State) Type(index int) int { return int(C.lua_type(L.s, C.int(index))) } From 40b8d1a1c464459197d6b365610b7ba963731d50 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 20 Jul 2012 15:45:20 +0200 Subject: [PATCH 017/100] documentation --- TODO | 7 +-- lua/golua.go | 5 ++- lua/lauxlib.go | 55 +++++++++++++++-------- lua/lua.go | 117 ++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 140 insertions(+), 44 deletions(-) diff --git a/TODO b/TODO index 64ffd07a..a26ffcc3 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,7 @@ -- documentation -- lua.go:Dump -- lua.go:Load +- ToGoFunction / ToGoStruct error checking (what happens to the other To* and Check* functions when called on the wrong type?) +- testing (DoFile, DoString on error) +- lua.go: Dump implementing lua_dump +- lua.go: Load implementing lua_load - AtPanic slightly broken when nil is passed, if we think passing nil has value to extract the current atpanic function we should also make sure it doesn't break everything - threads implementation is probably fucked completely should look into it - lauxlib.go:CheckOption is not implemented \ No newline at end of file diff --git a/lua/golua.go b/lua/golua.go index 028f2ea0..4fb1c3a8 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -14,12 +14,13 @@ import ( "unsafe" ) +// Type of allocation functions to use with NewStateAlloc type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer -// this is the type of go function that can be registered as lua functions +// This is the type of go function that can be registered as lua functions type LuaGoFunction func(L *State) int -//wrapper to keep cgo from complaining about incomplete ptr type +// Wrapper to keep cgo from complaining about incomplete ptr type //export State type State struct { s *C.lua_State diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 0baafe54..f1c19c48 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -8,12 +8,6 @@ package lua import "C" import "unsafe" -//luaL_addchar -//luaL_addlstring -//luaL_addsize -//luaL_addstring -//luaL_addvalue - type LuaError struct { message string } @@ -22,6 +16,7 @@ func (err *LuaError) Error() string { return err.message } +// luaL_argcheck func (L *State) ArgCheck(cond bool, narg int, extramsg string) { if cond { Cextramsg := C.CString(extramsg) @@ -30,63 +25,72 @@ func (L *State) ArgCheck(cond bool, narg int, extramsg string) { } } +// luaL_argerror func (L *State) ArgError(narg int, extramsg string) int { Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) return int(C.luaL_argerror(L.s, C.int(narg), Cextramsg)) } -//type luaL_Buffer - -//luaL_buffinit - +// luaL_callmeta func (L *State) CallMeta(obj int, e string) int { Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) return int(C.luaL_callmeta(L.s, C.int(obj), Ce)) } +// luaL_checkany func (L *State) CheckAny(narg int) { C.luaL_checkany(L.s, C.int(narg)) } +// luaL_checkinteger func (L *State) CheckInteger(narg int) int { return int(C.luaL_checkinteger(L.s, C.int(narg))) } +// luaL_checknumber func (L *State) CheckNumber(narg int) float64 { return float64(C.luaL_checknumber(L.s, C.int(narg))) } +// luaL_checkstring func (L *State) CheckString(narg int) string { var length C.size_t return C.GoString(C.luaL_checklstring(L.s, C.int(narg), &length)) } +// luaL_checkoption +// +// BUG(everyone_involved): not implemented func (L *State) CheckOption(narg int, def string, lst []string) int { //TODO: complication: lst conversion to const char* lst[] from string slice return 0 } +// luaL_checktype func (L *State) CheckType(narg int, t int) { C.luaL_checktype(L.s, C.int(narg), C.int(t)) } +// luaL_checkudata func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) return unsafe.Pointer(C.luaL_checkudata(L.s, C.int(narg), Ctname)) } -//true if no errors, false otherwise -func (L *State) DoFile(filename string) bool { +// Executes file, returns nil for no errors or the lua error string on failure +func (L *State) DoFile(filename string) error { if L.LoadFile(filename) == 0 { - return L.PCall(0, LUA_MULTRET, 0) == 0 + if L.PCall(0, LUA_MULTRET, 0) == 0 { + return nil + } } - return false + return &LuaError{L.ToString(-1)} } -//nil if no errors, an error otherwise +// Executes the string, returns nil for no errors or the lua error string on failure func (L *State) DoString(str string) error { if L.LoadString(str) == 0 { if L.PCall(0, LUA_MULTRET, 0) == 0 { @@ -96,27 +100,28 @@ func (L *State) DoString(str string) error { return &LuaError{L.ToString(-1)} } -// evaluates argument like DoString, panics if execution failed +// Like DoString but panics on error func (L *State) MustDoString(str string) { if err := L.DoString(str); err != nil { panic(err) } } -//returns false if no such metatable or no such field +// luaL_getmetafield func (L *State) GetMetaField(obj int, e string) bool { Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) return C.luaL_getmetafield(L.s, C.int(obj), Ce) != 0 } -//TODO: rename better... clashes with lua_getmetatable +// luaL_getmetatable func (L *State) LGetMetaTable(tname string) { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) C.lua_getfield(L.s, LUA_REGISTRYINDEX, Ctname) } +// luaL_gsub func (L *State) GSub(s string, p string, r string) string { Cs := C.CString(s) Cp := C.CString(p) @@ -130,43 +135,50 @@ func (L *State) GSub(s string, p string, r string) string { return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) } +// luaL_loadfile func (L *State) LoadFile(filename string) int { Cfilename := C.CString(filename) defer C.free(unsafe.Pointer(Cfilename)) return int(C.luaL_loadfile(L.s, Cfilename)) } +// luaL_loadstring func (L *State) LoadString(s string) int { Cs := C.CString(s) defer C.free(unsafe.Pointer(Cs)) return int(C.luaL_loadstring(L.s, Cs)) } -//returns false if registry already contains key tname +// luaL_newmetatable func (L *State) NewMetaTable(tname string) bool { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) return C.luaL_newmetatable(L.s, Ctname) != 0 } +// luaL_newstate func NewState() *State { ls := (C.luaL_newstate()) L := newState(ls) return L } +// luaL_openlibs func (L *State) OpenLibs() { C.luaL_openlibs(L.s) } +// luaL_optinteger func (L *State) OptInteger(narg int, d int) int { return int(C.luaL_optinteger(L.s, C.int(narg), C.lua_Integer(d))) } +// luaL_optnumber func (L *State) OptNumber(narg int, d float64) float64 { return float64(C.luaL_optnumber(L.s, C.int(narg), C.lua_Number(d))) } +// luaL_optstring func (L *State) OptString(narg int, d string) string { var length C.size_t Cd := C.CString(d) @@ -174,23 +186,28 @@ func (L *State) OptString(narg int, d string) string { return C.GoString(C.luaL_optlstring(L.s, C.int(narg), Cd, &length)) } +// Raises error with given message, equivalent to PushString followed by Error func (L *State) ErrorWithMessage(errorMessage string) int { L.PushString(errorMessage) return L.Error() } +// luaL_ref func (L *State) Ref(t int) int { return int(C.luaL_ref(L.s, C.int(t))) } +// luaL_typename func (L *State) LTypename(index int) string { return C.GoString(C.lua_typename(L.s, C.lua_type(L.s, C.int(index)))) } +// luaL_unref func (L *State) Unref(t int, ref int) { C.luaL_unref(L.s, C.int(t), C.int(ref)) } +// luaL_where func (L *State) Where(lvl int) { C.luaL_where(L.s, C.int(lvl)) } diff --git a/lua/lua.go b/lua/lua.go index 47f95b58..a43c21fb 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -1,3 +1,8 @@ +// This package provides access to the excellent lua language interpreter from go code. +// +// Access to most of the functions in lua.h and lauxlib.h is provided as well as additional convenience functions to publish Go objects and functions to lua code. +// +// The documentation of this package is no substitute for the official lua documentation and in many instances methods are described only with the name of their C equivalent package lua /* @@ -13,13 +18,6 @@ import "C" import "unsafe" -//like lua_Writer, but as p will contain capacity, not needed as separate param -type Writer func(L *State, p []byte, ud interface{}) - -//like lua reader, but the return slice has the size, so does -// we do not need it to be an out param -type Reader func(L *State, data interface{}) []byte - func newState(L *C.lua_State) *State { var newstatei interface{} newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8)} @@ -81,27 +79,36 @@ func (L *State) unregister(fid uint) { } } +// Like lua_pushcfunction pushes onto the stack a go function as user data func (L *State) PushGoFunction(f LuaGoFunction) { fid := L.register(f) C.clua_pushgofunction(L.s, C.uint(fid)) } +// Pushes a Go struct onto the stack as user data. +// +// The user data will be rigged so that lua code can access and change to public members of simple types directly func (L *State) PushGoStruct(iface interface{}) { iid := L.register(iface) C.clua_pushgostruct(L.s, C.uint(iid)) } -//push pointer by value, as a value - we don't impact lifetime +// Push a pointer onto the stack as user data. +// +// This function doesn't save a reference to the interface, it is the responsibility of the caller of this function to insure that the interface outlasts the lifetime of the lua object that this function creates. func (L *State) PushLightUserdata(ud *interface{}) { //push C.lua_pushlightuserdata(L.s, unsafe.Pointer(ud)) } -//old style +// Creates a new user data object of specified size and returns it func (L *State) NewUserdata(size uintptr) unsafe.Pointer { return unsafe.Pointer(C.lua_newuserdata(L.s, C.size_t(size))) } +// Sets the AtPanic function, returns the old one +// +// BUG(everyone_involved): passing nil causes serious problems func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { fid := uint(0) if panicf != nil { @@ -124,116 +131,137 @@ func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { return nil } +// lua_call func (L *State) Call(nargs int, nresults int) { C.lua_call(L.s, C.int(nargs), C.int(nresults)) } +// lua_checkstack func (L *State) CheckStack(extra int) bool { return C.lua_checkstack(L.s, C.int(extra)) != 0 } +// lua_close func (L *State) Close() { C.lua_close(L.s) } +// lua_concat func (L *State) Concat(n int) { C.lua_concat(L.s, C.int(n)) } +// lua_createtable func (L *State) CreateTable(narr int, nrec int) { C.lua_createtable(L.s, C.int(narr), C.int(nrec)) } -//TODO: data be a slice? -func (L *State) Dump(writer Writer, data interface{}) int { - //TODO: Implement Dump - return 0 -} - -func (L *State) Load(reader Reader, data interface{}, chunkname string) int { - //TODO: Implement Load - return 0 -} - +// lua_equal func (L *State) Equal(index1, index2 int) bool { return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 } +// lua_error func (L *State) Error() int { return int(C.lua_error(L.s)) } +// lua_gc func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } +// lua_getfenv func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } +// lua_getfield func (L *State) GetField(index int, k string) { Ck := C.CString(k) defer C.free(unsafe.Pointer(Ck)) C.lua_getfield(L.s, C.int(index), Ck) } +// Pushes on the stack the value of a global variable (lua_getglobal) func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } +// lua_getmetatable func (L *State) GetMetaTable(index int) bool { return C.lua_getmetatable(L.s, C.int(index)) != 0 } +// lua_gettable func (L *State) GetTable(index int) { C.lua_gettable(L.s, C.int(index)) } +// lua_gettop func (L *State) GetTop() int { return int(C.lua_gettop(L.s)) } +// lua_insert func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } +// Returns true if lua_type == LUA_TBOOLEAN func (L *State) IsBoolean(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TBOOLEAN } +// Returns true if the value at index is a LuaGoFunction func (L *State) IsGoFunction(index int) bool { return C.clua_isgofunction(L.s, C.int(index)) != 0 } +// Returns true if the value at index is user data pushed with PushGoStruct func (L *State) IsGoStruct(index int) bool { return C.clua_isgostruct(L.s, C.int(index)) != 0 } +// Returns true if the value at index is user data pushed with PushGoFunction func (L *State) IsFunction(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TFUNCTION } +// Returns true if the value at index is light user data func (L *State) IsLightUserdata(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TLIGHTUSERDATA } +// lua_isnil func (L *State) IsNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNIL } +// lua_isnone func (L *State) IsNone(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNONE } +// lua_isnoneornil func (L *State) IsNoneOrNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) <= 0 } +// lua_isnumber func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(index)) == 1 } +// lua_isstring func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } +// lua_istable func (L *State) IsTable(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } +// lua_isthread func (L *State) IsThread(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TTHREAD } +// lua_isuserdata func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int(index)) == 1 } +// lua_lessthan func (L *State) LessThan(index1, index2 int) bool { return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 } +// Creates a new lua interpreter state with the given allocation function func NewStateAlloc(f Alloc) *State { ls := C.clua_newstate(unsafe.Pointer(&f)) return newState(ls) } +// lua_newtable func (L *State) NewTable() { C.lua_createtable(L.s, 0, 0) } +// lua_newthread func (L *State) NewThread() *State { //TODO: call newState with result from C.lua_newthread and return it //TODO: should have same lists as parent @@ -242,24 +270,29 @@ func (L *State) NewThread() *State { return &State{s, nil, nil} } +// lua_next func (L *State) Next(index int) int { return int(C.lua_next(L.s, C.int(index))) } +// lua_objlen func (L *State) ObjLen(index int) uint { return uint(C.lua_objlen(L.s, C.int(index))) } +// lua_pcall func (L *State) PCall(nargs int, nresults int, errfunc int) int { return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) } +// lua_pop func (L *State) Pop(n int) { //Why is this implemented this way? I don't get it... //C.lua_pop(L.s, C.int(n)); C.lua_settop(L.s, C.int(-n-1)) } +// lua_pushboolean func (L *State) PushBoolean(b bool) { var bint int if b { @@ -270,192 +303,236 @@ func (L *State) PushBoolean(b bool) { C.lua_pushboolean(L.s, C.int(bint)) } +// lua_pushstring func (L *State) PushString(str string) { Cstr := C.CString(str) defer C.free(unsafe.Pointer(Cstr)) C.lua_pushstring(L.s, Cstr) } +// lua_pushinteger func (L *State) PushInteger(n int64) { C.lua_pushinteger(L.s, C.lua_Integer(n)) } +// lua_pushnil func (L *State) PushNil() { C.lua_pushnil(L.s) } +// lua_pushnumber func (L *State) PushNumber(n float64) { C.lua_pushnumber(L.s, C.lua_Number(n)) } +// lua_pushthread func (L *State) PushThread() (isMain bool) { return C.lua_pushthread(L.s) != 0 } +// lua_pushvalue func (L *State) PushValue(index int) { C.lua_pushvalue(L.s, C.int(index)) } +// lua_rawequal func (L *State) RawEqual(index1 int, index2 int) bool { return C.lua_rawequal(L.s, C.int(index1), C.int(index2)) != 0 } +// lua_rawget func (L *State) RawGet(index int) { C.lua_rawget(L.s, C.int(index)) } +// lua_rawgeti func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.int(n)) } +// lua_rawset func (L *State) RawSet(index int) { C.lua_rawset(L.s, C.int(index)) } +// lua_rawseti func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)) } +// Registers a Go function as a global variable func (L *State) Register(name string, f LuaGoFunction) { L.PushGoFunction(f) L.SetGlobal(name) } +// lua_remove func (L *State) Remove(index int) { C.lua_remove(L.s, C.int(index)) } +// lua_replace func (L *State) Replace(index int) { C.lua_replace(L.s, C.int(index)) } +// lua_resume func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, C.int(narg))) } +// lua_setallocf func (L *State) SetAllocf(f Alloc) { C.clua_setallocf(L.s, unsafe.Pointer(&f)) } +// lua_setfenv func (L *State) SetfEnv(index int) { C.lua_setfenv(L.s, C.int(index)) } +// lua_setfield func (L *State) SetField(index int, k string) { Ck := C.CString(k) defer C.free(unsafe.Pointer(Ck)) C.lua_setfield(L.s, C.int(index), Ck) } +// lua_setglobal func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) C.lua_setfield(L.s, C.int(LUA_GLOBALSINDEX), Cname) } +// lua_setmetatable func (L *State) SetMetaTable(index int) { C.lua_setmetatable(L.s, C.int(index)) } +// lua_settable func (L *State) SetTable(index int) { C.lua_settable(L.s, C.int(index)) } +// lua_settop func (L *State) SetTop(index int) { C.lua_settop(L.s, C.int(index)) } +// lua_status func (L *State) Status() int { return int(C.lua_status(L.s)) } +// lua_toboolean func (L *State) ToBoolean(index int) bool { return C.lua_toboolean(L.s, C.int(index)) != 0 } +// Returns the value at index as a Go function (it must be something pushed with PushGoFunction) func (L *State) ToGoFunction(index int) (f LuaGoFunction) { fid := C.clua_togofunction(L.s, C.int(index)) return L.registry[fid].(LuaGoFunction) } +// Returns the value at index as a Go Struct (it must be something pushed with PushGoStruct) func (L *State) ToGoStruct(index int) (f interface{}) { fid := C.clua_togostruct(L.s, C.int(index)) return L.registry[fid] } +// lua_tostring func (L *State) ToString(index int) string { var size C.size_t //C.GoString(C.lua_tolstring(L.s, C.int(index), &size)); return C.GoString(C.lua_tolstring(L.s, C.int(index), &size)) } +// lua_tointeger func (L *State) ToInteger(index int) int { return int(C.lua_tointeger(L.s, C.int(index))) } +// lua_tonumber func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumber(L.s, C.int(index))) } +// lua_topointer func (L *State) ToPointer(index int) uintptr { return uintptr(C.lua_topointer(L.s, C.int(index))) } +// lua_tothread func (L *State) ToThread(index int) *State { //TODO: find a way to link lua_State* to existing *State, return that return &State{} } +// lua_touserdata func (L *State) ToUserdata(index int) unsafe.Pointer { return unsafe.Pointer(C.lua_touserdata(L.s, C.int(index))) } +// lua_type func (L *State) Type(index int) int { return int(C.lua_type(L.s, C.int(index))) } +// lua_typename func (L *State) Typename(tp int) string { return C.GoString(C.lua_typename(L.s, C.int(tp))) } +// lua_xmove func XMove(from *State, to *State, n int) { C.lua_xmove(from.s, to.s, C.int(n)) } +// lua_yield func (L *State) Yield(nresults int) int { return int(C.lua_yield(L.s, C.int(nresults))) } // Restricted library opens +// Calls luaopen_base func (L *State) OpenBase() { C.clua_openbase(L.s) } +// Calls luaopen_io func (L *State) OpenIO() { C.clua_openio(L.s) } +// Calls luaopen_math func (L *State) OpenMath() { C.clua_openmath(L.s) } +// Calls luaopen_package func (L *State) OpenPackage() { C.clua_openpackage(L.s) } +// Calls luaopen_string func (L *State) OpenString() { C.clua_openstring(L.s) } +// Calls luaopen_table func (L *State) OpenTable() { C.clua_opentable(L.s) } +// Calls luaopen_os func (L *State) OpenOS() { C.clua_openos(L.s) } +// Sets the maximum number of operations to execute at instrNumber, after this the execution ends func (L *State) SetExecutionLimit(instrNumber int) { C.clua_setexecutionlimit(L.s, C.int(instrNumber)) } From 2e01ce2dd6eaa9468d14ab0cb7c0ce330d825927 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 17 Oct 2012 09:57:17 +0200 Subject: [PATCH 018/100] some testing --- lua/lua_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 lua/lua_test.go diff --git a/lua/lua_test.go b/lua/lua_test.go new file mode 100644 index 00000000..5dcadf40 --- /dev/null +++ b/lua/lua_test.go @@ -0,0 +1,45 @@ +package lua + +import ( + "testing" +) + +type TestStruct struct { + IntField int + StringField string + FloatField float64 +} + +func TestGoStruct(t *testing.T) { + L := NewState() + L.OpenLibs() + defer L.Close() + + ts := &TestStruct{10, "test", 2.3 } + + L.CheckStack(1) + + L.PushGoStruct(ts) + L.SetGlobal("t") + + L.GetGlobal("t") + if !L.IsGoStruct(-1) { t.Fatal("Not go struct") } + + tsr := L.ToGoStruct(-1).(*TestStruct) + if tsr != ts { t.Fatal("Retrieved something different from what we inserted") } + + L.Pop(1) + + L.PushString("This is not a struct") + if L.ToGoStruct(-1) != nil { + t.Fatal("Non-GoStruct value attempted to convert into GoStruct should result in nil") + } + + L.Pop(1) +} + +// TODO: +// - function test +// - struct field getting and setting test +// - DoFile / DoString tests (including errors + From ad8ad2e23703fab81cc93b7236e66a5ef130a34e Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 17 Oct 2012 09:58:13 +0200 Subject: [PATCH 019/100] returning nil in ToGoStruct/ToGoFunction --- TODO | 1 - example/userdata.go | 7 +++---- lua/c-golua.c | 7 ------- lua/lua.go | 2 ++ 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/TODO b/TODO index a26ffcc3..c0e56799 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -- ToGoFunction / ToGoStruct error checking (what happens to the other To* and Check* functions when called on the wrong type?) - testing (DoFile, DoString on error) - lua.go: Dump implementing lua_dump - lua.go: Load implementing lua_load diff --git a/example/userdata.go b/example/userdata.go index 18bd399b..96f90049 100644 --- a/example/userdata.go +++ b/example/userdata.go @@ -49,10 +49,10 @@ type TestObject struct { } func goDefinedObjects(L *lua.State) { - t := &TestObject{42}; + t := &TestObject{42} L.PushGoStruct(t) - L.SetGlobal("t"); + L.SetGlobal("t") /* This code demonstrates checking that a value on the stack is a go object */ L.CheckStack(1) @@ -69,8 +69,7 @@ func goDefinedObjects(L *lua.State) { } func main() { - var L *lua.State; - L = lua.NewState(); + L := lua.NewState() L.OpenLibs(); /* diff --git a/lua/c-golua.c b/lua/c-golua.c index 46d140e7..8ea852bd 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -116,9 +116,6 @@ int interface_index_callback(lua_State *L) int r = golua_interface_index_callback(*gi, *iid, field_name); - lua_remove(L, 2); - lua_remove(L, 1); - if (r < 0) { lua_error(L); @@ -151,10 +148,6 @@ int interface_newindex_callback(lua_State *L) int r = golua_interface_newindex_callback(*gi, *iid, field_name); - lua_remove(L, 3); - lua_remove(L, 2); - lua_remove(L, 1); - if (r < 0) { lua_error(L); diff --git a/lua/lua.go b/lua/lua.go index a43c21fb..6a1eca81 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -432,12 +432,14 @@ func (L *State) ToBoolean(index int) bool { // Returns the value at index as a Go function (it must be something pushed with PushGoFunction) func (L *State) ToGoFunction(index int) (f LuaGoFunction) { + if !L.IsGoFunction(index) { return nil } fid := C.clua_togofunction(L.s, C.int(index)) return L.registry[fid].(LuaGoFunction) } // Returns the value at index as a Go Struct (it must be something pushed with PushGoStruct) func (L *State) ToGoStruct(index int) (f interface{}) { + if !L.IsGoStruct(index) { return nil } fid := C.clua_togostruct(L.s, C.int(index)) return L.registry[fid] } From 11e5a399e48bb1c4a477d7004e45cde49f0c8d18 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 27 Oct 2012 11:31:33 +0200 Subject: [PATCH 020/100] Fixed example/basic.go --- example/basic.go | 4 ++-- example/panic.go | 4 +++- lua/lua_test.go | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/example/basic.go b/example/basic.go index fed7f824..3d9e603a 100644 --- a/example/basic.go +++ b/example/basic.go @@ -9,8 +9,8 @@ func test(L *lua.State) int { } func test2(L *lua.State) int { - arg := lua.CheckInteger(L,-1); - argfrombottom := lua.CheckInteger(L,1); + arg := L.CheckInteger(-1); + argfrombottom := L.CheckInteger(1); fmt.Print("test2 arg: "); fmt.Println(arg); fmt.Print("from bottom: "); diff --git a/example/panic.go b/example/panic.go index 7cedfe95..1fc3f209 100644 --- a/example/panic.go +++ b/example/panic.go @@ -19,7 +19,7 @@ func main() { currentPanicf := L.AtPanic(nil); currentPanicf = L.AtPanic(currentPanicf); newPanic := func(L1 *lua.State) int { - fmt.Println("I AM PANICKING!!! %v", currentPanicf); + fmt.Println("I AM PANICKING!!!", currentPanicf); if currentPanicf != nil { return currentPanicf(L1); } @@ -32,4 +32,6 @@ func main() { //force a panic L.PushNil(); L.Call(0,0); + + fmt.Println("End") } diff --git a/lua/lua_test.go b/lua/lua_test.go index 5dcadf40..e21d4bb3 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -38,6 +38,7 @@ func TestGoStruct(t *testing.T) { L.Pop(1) } + // TODO: // - function test // - struct field getting and setting test From dd5cb7a08dde959337b83765a82011620f561df8 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 27 Oct 2012 12:40:32 +0200 Subject: [PATCH 021/100] lua.State.Error never worked or was broken by some go update at some point, use panic instead lua_error will longjump out of the calling c function, this seems to mess up cgocall state. I do not think there is a way to make this work and therefore I have removed lua.State.Error and lua.State.ErrorWithMessage from the interface DoString and DoFile will instead catch panics and return them as errors --- TODO | 1 - example/error.go | 38 ++++++++++++++++++++++++++++++++++++++ lua/lauxlib.go | 40 ++++++++++++++++++++++++---------------- lua/lua.go | 4 ---- 4 files changed, 62 insertions(+), 21 deletions(-) create mode 100644 example/error.go diff --git a/TODO b/TODO index c0e56799..c9d4f374 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -- testing (DoFile, DoString on error) - lua.go: Dump implementing lua_dump - lua.go: Load implementing lua_load - AtPanic slightly broken when nil is passed, if we think passing nil has value to extract the current atpanic function we should also make sure it doesn't break everything diff --git a/example/error.go b/example/error.go new file mode 100644 index 00000000..113520c0 --- /dev/null +++ b/example/error.go @@ -0,0 +1,38 @@ +package main + +import "../lua" +import "fmt" +import "errors" +import "os" + +func testDefault(L *lua.State) { + err := L.DoString("print(\"Unknown variable\" .. x)") + fmt.Printf("Error is: %v\n", err) + if err == nil { + fmt.Printf("Error shouldn't have been nil\n") + os.Exit(1) + } +} + +func faultyfunc(L *lua.State) int { + panic(errors.New("An error")) +} + +func testRegistered(L *lua.State) { + L.Register("faultyfunc", faultyfunc) + err := L.DoString("faultyfunc()") + fmt.Printf("Error is %v\n", err) + if err == nil { + fmt.Printf("Error shouldn't have been nil\n") + os.Exit(1) + } +} + +func main() { + L := lua.NewState() + defer L.Close() + L.OpenLibs() + + testDefault(L) + testRegistered(L) +} diff --git a/lua/lauxlib.go b/lua/lauxlib.go index f1c19c48..795d8b8b 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -80,24 +80,38 @@ func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { return unsafe.Pointer(C.luaL_checkudata(L.s, C.int(narg), Ctname)) } +func (L *State) pcallAndCatchErrors() (err error) { + defer func() { + if err2 := recover(); err2 != nil { + if _, ok := err2.(error); ok { + err = err2.(error) + } + return; + } + }() + err = nil + + if L.PCall(0, LUA_MULTRET, 0) != 0 { + err = &LuaError{L.ToString(-1)} + } + + return +} + // Executes file, returns nil for no errors or the lua error string on failure func (L *State) DoFile(filename string) error { - if L.LoadFile(filename) == 0 { - if L.PCall(0, LUA_MULTRET, 0) == 0 { - return nil - } + if L.LoadFile(filename) != 0 { + return &LuaError{L.ToString(-1)} } - return &LuaError{L.ToString(-1)} + return L.pcallAndCatchErrors() } // Executes the string, returns nil for no errors or the lua error string on failure func (L *State) DoString(str string) error { - if L.LoadString(str) == 0 { - if L.PCall(0, LUA_MULTRET, 0) == 0 { - return nil - } + if L.LoadString(str) != 0 { + return &LuaError{L.ToString(-1)} } - return &LuaError{L.ToString(-1)} + return L.pcallAndCatchErrors() } // Like DoString but panics on error @@ -186,12 +200,6 @@ func (L *State) OptString(narg int, d string) string { return C.GoString(C.luaL_optlstring(L.s, C.int(narg), Cd, &length)) } -// Raises error with given message, equivalent to PushString followed by Error -func (L *State) ErrorWithMessage(errorMessage string) int { - L.PushString(errorMessage) - return L.Error() -} - // luaL_ref func (L *State) Ref(t int) int { return int(C.luaL_ref(L.s, C.int(t))) diff --git a/lua/lua.go b/lua/lua.go index 6a1eca81..6e86ac7e 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -15,7 +15,6 @@ package lua */ import "C" - import "unsafe" func newState(L *C.lua_State) *State { @@ -161,9 +160,6 @@ func (L *State) Equal(index1, index2 int) bool { return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 } -// lua_error -func (L *State) Error() int { return int(C.lua_error(L.s)) } - // lua_gc func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } From bf83d11664d1a286bc9e83e5cd898034b336cf8a Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 27 Oct 2012 19:50:28 +0200 Subject: [PATCH 022/100] bugfixes: more longjump madness plus a bug in the garbage collection of pushed user data --- lua/c-golua.c | 76 ++++++++++++++++++++++++++------------------------- lua/golua.go | 1 + lua/lua.go | 11 +++++++- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index 8ea852bd..e65ef3f6 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -10,20 +10,45 @@ static const char GoStateRegistryKey = 'k'; //golua registry key static const char PanicFIDRegistryKey = 'k'; +/* taken from lua5.2 source */ +void *testudata(lua_State *L, int ud, const char *tname) +{ + void *p = lua_touserdata(L, ud); + if (p != NULL) + { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) + { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ +} + +int clua_isgofunction(lua_State *L, int n) +{ + return testudata(L, n, MT_GOFUNCTION) != NULL; +} + +int clua_isgostruct(lua_State *L, int n) +{ + return testudata(L, n, MT_GOINTERFACE) != NULL; +} + unsigned int* clua_checkgosomething(lua_State* L, int index, const char *desired_metatable) { if (desired_metatable != NULL) { - unsigned int* fid = (unsigned int*)luaL_checkudata(L,index, desired_metatable); - luaL_argcheck(L, fid != NULL, index, "Metatable not what expected"); - return fid; + return testudata(L, index, desired_metatable); } else { - unsigned int *sid = (unsigned int *)luaL_checkudata(L, index, MT_GOFUNCTION); - if (sid == NULL) sid = (unsigned int *)luaL_checkudata(L, index, MT_GOINTERFACE); - luaL_argcheck(L, sid != NULL, index, "Metatable not what expected"); - return sid; + unsigned int *sid = testudata(L, index, MT_GOFUNCTION); + if (sid != NULL) return sid; + return testudata(L, index, MT_GOINTERFACE); } } @@ -45,27 +70,30 @@ int callback_function(lua_State* L) GoInterface* gi = clua_getgostate(L); //remove the go function from the stack (to present same behavior as lua_CFunctions) lua_remove(L,1); - return golua_callgofunction(*gi,*fid); + return golua_callgofunction(*gi,fid!=NULL ? *fid : -1); } //wrapper for gchook int gchook_wrapper(lua_State* L) { + //printf("Garbage collection wrapper\n"); unsigned int* fid = clua_checkgosomething(L, -1, NULL); GoInterface* gi = clua_getgostate(L); - if(fid != NULL) + if (fid != NULL) return golua_gchook(*gi,*fid); return 0; } unsigned int clua_togofunction(lua_State* L, int index) { - return *(clua_checkgosomething(L, index, MT_GOFUNCTION)); + int *r = clua_checkgosomething(L, index, MT_GOFUNCTION); + return (r != NULL) ? *r : -1; } unsigned int clua_togostruct(lua_State *L, int index) { - return *(clua_checkgosomething(L, index, MT_GOINTERFACE)); + int *r = clua_checkgosomething(L, index, MT_GOINTERFACE); + return (r != NULL) ? *r : -1; } void clua_pushgofunction(lua_State* L, unsigned int fid) @@ -320,30 +348,4 @@ void clua_setexecutionlimit(lua_State* L, int n) lua_sethook(L, &clua_hook_function, LUA_MASKCOUNT, n); } -/* taken from lua5.2 source */ -void *testudata(lua_State *L, int ud, const char *tname) -{ - void *p = lua_touserdata(L, ud); - if (p != NULL) - { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) - { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ -} -int clua_isgofunction(lua_State *L, int n) -{ - return testudata(L, n, MT_GOFUNCTION) != NULL; -} - -int clua_isgostruct(lua_State *L, int n) -{ - return testudata(L, n, MT_GOINTERFACE) != NULL; -} diff --git a/lua/golua.go b/lua/golua.go index 4fb1c3a8..7b59a28f 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -31,6 +31,7 @@ type State struct { //export golua_callgofunction func golua_callgofunction(L interface{}, fid uint) int { + if fid < 0 { panic(&LuaError{"Requested execution of an unknown function"}) } L1 := L.(*State) f := L1.registry[fid].(LuaGoFunction) return f(L1) diff --git a/lua/lua.go b/lua/lua.go index 6e86ac7e..74fbccb7 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -16,6 +16,7 @@ package lua */ import "C" import "unsafe" +import "fmt" func newState(L *C.lua_State) *State { var newstatei interface{} @@ -46,7 +47,9 @@ func (L *State) getFreeIndex() (index uint, ok bool) { //if there exist entries in the freelist if freelen > 0 { i := L.freeIndices[freelen-1] //get index - L.freeIndices = L.freeIndices[0:i] //'pop' index from list + //fmt.Printf("Free indices before: %v\n", L.freeIndices) + L.freeIndices = L.freeIndices[0:freelen-1] //'pop' index from list + //fmt.Printf("Free indices after: %v\n", L.freeIndices) return i, true } return 0, false @@ -54,7 +57,9 @@ func (L *State) getFreeIndex() (index uint, ok bool) { //returns the registered function id func (L *State) register(f interface{}) uint { + //fmt.Printf("Registering %v\n") index, ok := L.getFreeIndex() + //fmt.Printf("\tfreeindex: index = %v, ok = %v\n", index, ok) //if not ok, then we need to add new index by extending the slice if !ok { index = uint(len(L.registry)) @@ -67,11 +72,13 @@ func (L *State) register(f interface{}) uint { //reslice L.registry = L.registry[0 : index+1] } + //fmt.Printf("\tregistering %d %v\n", index, f) L.registry[index] = f return index } func (L *State) unregister(fid uint) { + //fmt.Printf("Unregistering %d (len: %d, value: %v)\n", fid, len(L.registry), L.registry[fid]) if (fid < uint(len(L.registry))) && (L.registry[fid] != nil) { L.registry[fid] = nil L.addFreeIndex(fid) @@ -430,6 +437,7 @@ func (L *State) ToBoolean(index int) bool { func (L *State) ToGoFunction(index int) (f LuaGoFunction) { if !L.IsGoFunction(index) { return nil } fid := C.clua_togofunction(L.s, C.int(index)) + if fid < 0 { return nil } return L.registry[fid].(LuaGoFunction) } @@ -437,6 +445,7 @@ func (L *State) ToGoFunction(index int) (f LuaGoFunction) { func (L *State) ToGoStruct(index int) (f interface{}) { if !L.IsGoStruct(index) { return nil } fid := C.clua_togostruct(L.s, C.int(index)) + if fid < 0 { return nil } return L.registry[fid] } From 4c44a0e39427b1bfd78bb14ef81540cdca5b31ea Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 27 Oct 2012 19:57:41 +0200 Subject: [PATCH 023/100] damn you go!!!! --- lua/lua.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lua.go b/lua/lua.go index 74fbccb7..60ab9d86 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -16,7 +16,7 @@ package lua */ import "C" import "unsafe" -import "fmt" +//import "fmt" func newState(L *C.lua_State) *State { var newstatei interface{} From 829ce7a1df1267b8b2b769878cc8160f0081e825 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 27 Oct 2012 21:17:57 +0200 Subject: [PATCH 024/100] new todo item --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index c9d4f374..28493956 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,4 @@ +- find all calls to lua api that can result in lua_error calls and rework them (for example checkarg stuff) - lua.go: Dump implementing lua_dump - lua.go: Load implementing lua_load - AtPanic slightly broken when nil is passed, if we think passing nil has value to extract the current atpanic function we should also make sure it doesn't break everything From 69c75da5b07bfa2912f05fafbb58e724d9deff99 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Tue, 30 Oct 2012 11:37:27 +0100 Subject: [PATCH 025/100] quick start guide --- README | 25 -------------- README.md | 77 +++++++++++++++++++++++++++++++++++++++++++ example/basic.go | 53 ++++++++++++++--------------- example/quickstart.go | 23 +++++++++++++ 4 files changed, 127 insertions(+), 51 deletions(-) delete mode 100644 README create mode 100644 README.md create mode 100644 example/quickstart.go diff --git a/README b/README deleted file mode 100644 index e92d9bf3..00000000 --- a/README +++ /dev/null @@ -1,25 +0,0 @@ -Go Bindings for the lua C API - -Simplest way to install: - -#go get -u github.com/aarzilli/golua/lua - -Will work as long as pkg-config knows about lua. - -You can then try to run the examples: - -$cd /usr/local/go/src/pkg/github.com/aarzilli/golua/example/ -$go run basic.go -$go run alloc.go -$go run panic.go -$go run userdata.go - -Licensing -------------------------- -GoLua is released under the MIT license. -Please see the LICENSE file for more information. - -Lua is Copyright (c) Lua.org, PUC-Rio. All rights reserved. - - - diff --git a/README.md b/README.md new file mode 100644 index 00000000..cdb200e1 --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +Go Bindings for the lua C API +========================= + +Simplest way to install: + + # go get -u github.com/aarzilli/golua/lua + +Will work as long as `pkg-config` knows about lua. + +You can then try to run the examples: + + $ cd /usr/local/go/src/pkg/github.com/aarzilli/golua/example/ + $ go run basic.go + $ go run alloc.go + $ go run panic.go + $ go run userdata.go + +QUICK START +--------------------- + +Create a new Virtual Machine with: + +```go +L := lua.newState() +L.OpenLibs() +defer L.Close() +``` + +Lua's Virtual Machine is stack based, you can call lua functions like this: + +```go +// push "print" function on the stack +L.GetField(lua.LUA_GLOBALSINDEX, "print") +// push the string "Hello World!" on the stack +L.PushString("Hello World!") +// call print with one argument, expecting no results +L.Call(1, 0) +``` + +Of course this isn't very useful, more useful is executing lua code from a file or from a string: + +```go +// executes a string of lua code +err := L.DoString("...") +// executes a file +err = L.DoFile(filename) +``` + +You will also probably want to publish go functions to the virtual machine, you can do it by: + +```go +func adder(L *lua.State) int { + a := L.ToInteger(1) + b := L.ToInteger(2) + L.PushInteger(a + b) + return 1 // number of return values +} + +func main() { + L := lua.NewState() + defer L.Close() + L.OpenLibs() + + L.Register("adder", adder) + L.DoString("print(adder(2, 2))") +} +``` + +Licensing +------------- +GoLua is released under the MIT license. +Please see the LICENSE file for more information. + +Lua is Copyright (c) Lua.org, PUC-Rio. All rights reserved. + + + diff --git a/example/basic.go b/example/basic.go index 3d9e603a..86c9f3d2 100644 --- a/example/basic.go +++ b/example/basic.go @@ -4,43 +4,44 @@ import "../lua" import "fmt" func test(L *lua.State) int { - fmt.Println("hello world! from go!"); - return 0; + fmt.Println("hello world! from go!") + return 0 } func test2(L *lua.State) int { - arg := L.CheckInteger(-1); - argfrombottom := L.CheckInteger(1); - fmt.Print("test2 arg: "); - fmt.Println(arg); - fmt.Print("from bottom: "); - fmt.Println(argfrombottom); - return 0; + arg := L.CheckInteger(-1) + argfrombottom := L.CheckInteger(1) + fmt.Print("test2 arg: ") + fmt.Println(arg) + fmt.Print("from bottom: ") + fmt.Println(argfrombottom) + return 0 } func main() { - var L *lua.State; + L := lua.NewState() + defer L.Close() + L.OpenLibs() - L = lua.NewState(); - L.OpenLibs(); + L.GetField(lua.LUA_GLOBALSINDEX, "print") + L.PushString("Hello World!") + L.Call(1,0) - L.GetField(lua.LUA_GLOBALSINDEX, "print"); - L.PushString("Hello World!"); - L.Call(1,0); + L.PushGoFunction(test) + L.PushGoFunction(test) + L.PushGoFunction(test) + L.PushGoFunction(test) - L.PushGoFunction(test); - L.PushGoFunction(test); - L.PushGoFunction(test); - L.PushGoFunction(test); + L.PushGoFunction(test2) + L.PushInteger(42) + L.Call(1,0) - L.PushGoFunction(test2); - L.PushInteger(42); - L.Call(1,0); + L.Call(0,0) + L.Call(0,0) + L.Call(0,0) - L.Call(0,0); - L.Call(0,0); - L.Call(0,0); + err := L.DoString("test2(42)") - L.Close(); + fmt.Printf("Ciao %v\n", err) } diff --git a/example/quickstart.go b/example/quickstart.go new file mode 100644 index 00000000..bb9afd96 --- /dev/null +++ b/example/quickstart.go @@ -0,0 +1,23 @@ +package main + +import "../lua" + +func adder(L *lua.State) int { + a := L.ToInteger(1) + b := L.ToInteger(2) + L.PushInteger(int64(a + b)) + return 1 +} + +func main() { + L := lua.NewState() + defer L.Close() + L.OpenLibs() + + L.GetField(lua.LUA_GLOBALSINDEX, "print") + L.PushString("Hello World!") + L.Call(1, 0) + + L.Register("adder", adder) + L.DoString("print(adder(2, 2))") +} From 487c090b4839a10fc334c517c267eec7cd4c0620 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Thu, 22 Nov 2012 09:14:31 +0800 Subject: [PATCH 026/100] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cdb200e1..1bbb23bc 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ QUICK START Create a new Virtual Machine with: ```go -L := lua.newState() +L := lua.NewState() L.OpenLibs() defer L.Close() ``` From 4a78253af3957a28ec0049fa34f1436817bc78ae Mon Sep 17 00:00:00 2001 From: Harley Laue Date: Tue, 11 Dec 2012 10:34:54 -0600 Subject: [PATCH 027/100] clua_pushcallback has been added to allow definining metamethods with Go functions --- lua/c-golua.c | 12 ++++++++++++ lua/golua.h | 3 ++- lua/lua.go | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index e65ef3f6..2d8bed91 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -104,6 +104,18 @@ void clua_pushgofunction(lua_State* L, unsigned int fid) lua_setmetatable(L, -2); } +static int callback_c (lua_State* L) +{ + int fid = clua_togofunction(L,lua_upvalueindex(1)); + GoInterface *gi = clua_getgostate(L); + return golua_callgofunction(*gi,fid); +} + +void clua_pushcallback(lua_State* L) +{ + lua_pushcclosure(L,callback_c,1); +} + void clua_pushgostruct(lua_State* L, unsigned int iid) { unsigned int* iidptr = (unsigned int *)lua_newuserdata(L, sizeof(unsigned int)); diff --git a/lua/golua.h b/lua/golua.h index a15b1893..604d168e 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -7,6 +7,7 @@ void clua_initstate(lua_State* L); unsigned int clua_togofunction(lua_State* L, int index); unsigned int clua_togostruct(lua_State *L, int index); +void clua_pushcallback(lua_State* L); void clua_pushgofunction(lua_State* L, unsigned int fid); void clua_pushgostruct(lua_State *L, unsigned int fid); void clua_setgostate(lua_State* L, GoInterface gostate); @@ -26,4 +27,4 @@ void clua_openos(lua_State* L); void clua_setexecutionlimit(lua_State* L, int n); int clua_isgofunction(lua_State *L, int n); -int clua_isgostruct(lua_State *L, int n); \ No newline at end of file +int clua_isgostruct(lua_State *L, int n); diff --git a/lua/lua.go b/lua/lua.go index 60ab9d86..ff23964d 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -91,6 +91,12 @@ func (L *State) PushGoFunction(f LuaGoFunction) { C.clua_pushgofunction(L.s, C.uint(fid)) } +// Like lua_pushcclosure pushes a new Go closure onto the stack +func (L *State) PushGoCallback(f LuaGoFunction) { + L.PushGoFunction(f) // leaves Go function userdata on stack + C.clua_pushcallback(L.s) +} + // Pushes a Go struct onto the stack as user data. // // The user data will be rigged so that lua code can access and change to public members of simple types directly From a3f4feb19b7c40c4309800efd0d2ff1df08aea1d Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 15 Dec 2012 07:47:39 +0100 Subject: [PATCH 028/100] Changed PushCallback into SetMetaMethod --- lua/lua.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lua/lua.go b/lua/lua.go index ff23964d..fe4f2704 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -91,10 +91,24 @@ func (L *State) PushGoFunction(f LuaGoFunction) { C.clua_pushgofunction(L.s, C.uint(fid)) } -// Like lua_pushcclosure pushes a new Go closure onto the stack -func (L *State) PushGoCallback(f LuaGoFunction) { +// Sets a metamethod to execute a go function +// +// The code: +// +// L.LGetMetaTable(tableName) +// L.SetMetaMethod(methodName, function) +// +// is the logical equivalent of: +// +// L.LGetMetaTable(tableName) +// L.PushGoFunction(function) +// L.SetField(-2, methodName) +// +// except this wouldn't work because pushing a go function results in user data not a cfunction +func (L *State) SetMetaMethod(methodName string, f LuaGoFunction) { L.PushGoFunction(f) // leaves Go function userdata on stack - C.clua_pushcallback(L.s) + C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function + L.SetField(-2, methodName) } // Pushes a Go struct onto the stack as user data. From bd064a4224226154a5fc29428744b8ac9dd29f62 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 21 Dec 2012 21:49:19 +0100 Subject: [PATCH 029/100] restored lua.State.Error function to existence with a hack --- example/basic.go | 1 + example/error.go | 17 +++++++++++++++++ lua/c-golua.c | 7 ++++++- lua/golua.go | 18 ++++++++++++++++-- lua/lua.go | 12 ++++++++++-- 5 files changed, 50 insertions(+), 5 deletions(-) diff --git a/example/basic.go b/example/basic.go index 86c9f3d2..42581cc3 100644 --- a/example/basic.go +++ b/example/basic.go @@ -41,6 +41,7 @@ func main() { L.Call(0,0) L.Call(0,0) + // this will fail as we didn't register test2 function err := L.DoString("test2(42)") fmt.Printf("Ciao %v\n", err) diff --git a/example/error.go b/example/error.go index 113520c0..32e9ee20 100644 --- a/example/error.go +++ b/example/error.go @@ -18,6 +18,12 @@ func faultyfunc(L *lua.State) int { panic(errors.New("An error")) } +func faultyfunc2(L *lua.State) int { + L.PushString("Some error") + L.Error() + return 1 +} + func testRegistered(L *lua.State) { L.Register("faultyfunc", faultyfunc) err := L.DoString("faultyfunc()") @@ -28,6 +34,16 @@ func testRegistered(L *lua.State) { } } +func testRegistered2(L *lua.State) { + L.Register("faultyfunc2", faultyfunc2) + err := L.DoString("faultyfunc2()") + fmt.Printf("Error is %v\n", err) + if err == nil { + fmt.Printf("Error shouldn't have been nil\n") + os.Exit(1) + } +} + func main() { L := lua.NewState() defer L.Close() @@ -35,4 +51,5 @@ func main() { testDefault(L) testRegistered(L) + testRegistered2(L) } diff --git a/lua/c-golua.c b/lua/c-golua.c index 2d8bed91..fbf3389d 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -66,11 +66,16 @@ GoInterface* clua_getgostate(lua_State* L) //wrapper for callgofunction int callback_function(lua_State* L) { + int r; unsigned int *fid = clua_checkgosomething(L, 1, MT_GOFUNCTION); GoInterface* gi = clua_getgostate(L); //remove the go function from the stack (to present same behavior as lua_CFunctions) lua_remove(L,1); - return golua_callgofunction(*gi,fid!=NULL ? *fid : -1); + r = golua_callgofunction(*gi, fid!=NULL ? *fid : -1); + if (golua_error_requested(*gi)) { + lua_error(L); + } + return r; } //wrapper for gchook diff --git a/lua/golua.go b/lua/golua.go index 7b59a28f..ba37c92d 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -23,20 +23,34 @@ type LuaGoFunction func(L *State) int // Wrapper to keep cgo from complaining about incomplete ptr type //export State type State struct { + // Wrapped lua_State object s *C.lua_State + + // Registry of go object that have been pushed to Lua VM registry []interface{} - //freelist for funcs indices, to allow for freeing + + // Freelist for funcs indices, to allow for freeing freeIndices []uint + + // Go functions can set this to true to have their C wrapper call lua_error (they can't call it directly) + errorRequested bool } //export golua_callgofunction func golua_callgofunction(L interface{}, fid uint) int { - if fid < 0 { panic(&LuaError{"Requested execution of an unknown function"}) } + if fid < 0 { panic(&LuaError{"Requested execution of an unknown function"}) } L1 := L.(*State) + L1.errorRequested = false f := L1.registry[fid].(LuaGoFunction) return f(L1) } +//export golua_error_requested +func golua_error_requested(L interface{}) bool { + L1 := L.(*State) + return L1.errorRequested +} + //export golua_interface_newindex_callback func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr *C.char) int { L := Li.(*State) diff --git a/lua/lua.go b/lua/lua.go index fe4f2704..d23a07a0 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -20,7 +20,7 @@ import "unsafe" func newState(L *C.lua_State) *State { var newstatei interface{} - newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8)} + newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8), false} newstatei = newstate ns1 := unsafe.Pointer(&newstatei) ns2 := (*C.GoInterface)(ns1) @@ -290,7 +290,7 @@ func (L *State) NewThread() *State { //TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) - return &State{s, nil, nil} + return &State{s, nil, nil, false} } // lua_next @@ -563,3 +563,11 @@ func (L *State) OpenOS() { func (L *State) SetExecutionLimit(instrNumber int) { C.clua_setexecutionlimit(L.s, C.int(instrNumber)) } + +// Calls lua_error. +// The call to lua error will be delayed until control returns to Lua VM: +// follow a call to this function with a return and make sure you leave a string describing the error on the stack +func (L *State) Error() { + L.errorRequested = true +} + From 1ef48b4775de20bc91b36c3ea71480da143d3105 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 22 Dec 2012 13:32:43 +0100 Subject: [PATCH 030/100] added Lua 5.1 headers (cherry picked Steve Donovan commit) --- lua/lua/lauxlib.h | 174 +++++++++++ lua/lua/lua.h | 388 +++++++++++++++++++++++ lua/lua/luaconf.h | 767 ++++++++++++++++++++++++++++++++++++++++++++++ lua/lua/lualib.h | 53 ++++ 4 files changed, 1382 insertions(+) create mode 100644 lua/lua/lauxlib.h create mode 100644 lua/lua/lua.h create mode 100644 lua/lua/luaconf.h create mode 100644 lua/lua/lualib.h diff --git a/lua/lua/lauxlib.h b/lua/lua/lauxlib.h new file mode 100644 index 00000000..34258235 --- /dev/null +++ b/lua/lua/lauxlib.h @@ -0,0 +1,174 @@ +/* +** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#if defined(LUA_COMPAT_GETN) +LUALIB_API int (luaL_getn) (lua_State *L, int t); +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); +#else +#define luaL_getn(L,i) ((int)lua_objlen(L, i)) +#define luaL_setn(L,i,j) ((void)0) /* no op! */ +#endif + +#if defined(LUA_COMPAT_OPENLIB) +#define luaI_openlib luaL_openlib +#endif + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + + +LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l); +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); +LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, + const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, + const char *fname, int szhint); + + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); + + +/* }====================================================== */ + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) + +#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) + +#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) + + +#define luaL_reg luaL_Reg + +#endif + + diff --git a/lua/lua/lua.h b/lua/lua/lua.h new file mode 100644 index 00000000..e4bdfd3b --- /dev/null +++ b/lua/lua/lua.h @@ -0,0 +1,388 @@ +/* +** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.4" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +/* mark for precompiled code (`Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* thread status; 0 is OK */ +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getfenv) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setfenv) (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_strlen(L,i) lua_objlen(L, (i)) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** compatibility macros and functions +*/ + +#define lua_open() luaL_newstate() + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) + +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) + +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer + + +/* hack */ +LUA_API void lua_setlevel (lua_State *from, lua_State *to); + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); + +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/lua/lua/luaconf.h b/lua/lua/luaconf.h new file mode 100644 index 00000000..3a099cee --- /dev/null +++ b/lua/lua/luaconf.h @@ -0,0 +1,767 @@ +/* +** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef lconfig_h +#define lconfig_h + +#include +#include + + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) +#define LUA_WIN +#endif + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_DL_DYLD /* does not need extra library */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionallity listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#endif + + +/* +@@ LUA_PATH and LUA_CPATH are the names of the environment variables that +@* Lua check to set its paths. +@@ LUA_INIT is the name of the environment variable that Lua +@* checks for initialization code. +** CHANGE them if you want different names. +*/ +#define LUA_PATH "LUA_PATH" +#define LUA_CPATH "LUA_CPATH" +#define LUA_INIT "LUA_INIT" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + +#else +#define LUA_ROOT "/usr/local/" +#define LUA_ROOT2 "/usr/" +#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +#define LUA_LDIR2 LUA_ROOT2 "share/lua/5.1/" +#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" +#define LUA_CDIR2 LUA_ROOT2 "lib/lua/5.1/" +#define LUA_PATH_DEFAULT \ + "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + LUA_LDIR2"?.lua;" LUA_LDIR2"?/init.lua" +#define LUA_CPATH_DEFAULT \ + "./?.so;" LUA_CDIR"?.so;" LUA_CDIR2"?.so;" LUA_CDIR"loadall.so" +#endif + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + + +/* +@@ LUA_PATHSEP is the character that separates templates in a path. +@@ LUA_PATH_MARK is the string that marks the substitution points in a +@* template. +@@ LUA_EXECDIR in a Windows path is replaced by the executable's +@* directory. +@@ LUA_IGMARK is a mark to ignore all before it when bulding the +@* luaopen_ function name. +** CHANGE them if for some reason your system cannot use those +** characters. (E.g., if one of those characters is a common character +** in file/directory names.) Probably you do not need to change them. +*/ +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ +#define LUA_INTEGER ptrdiff_t + + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all standard library functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) + +#if defined(LUA_CORE) || defined(LUA_LIB) +#define LUA_API __declspec(dllexport) +#else +#define LUA_API __declspec(dllimport) +#endif + +#else + +#define LUA_API extern + +#endif + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DATA is a mark for all extern (const) variables that are not to +@* be exported to outside modules. +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. +*/ +#if defined(luaall_c) +#define LUAI_FUNC static +#define LUAI_DATA /* empty */ + +#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DATA LUAI_FUNC + +#else +#define LUAI_FUNC extern +#define LUAI_DATA extern +#endif + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +** {================================================================== +** Stand-alone configuration +** =================================================================== +*/ + +#if defined(lua_c) || defined(luaall_c) + +/* +@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that +@* is, whether we're running lua interactively). +** CHANGE it if you have a better definition for non-POSIX/non-Windows +** systems. +*/ +#if defined(LUA_USE_ISATTY) +#include +#define lua_stdin_is_tty() isatty(0) +#elif defined(LUA_WIN) +#include +#include +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#else +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#endif + + +/* +@@ LUA_PROMPT is the default prompt used by stand-alone Lua. +@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. +** CHANGE them if you want different prompts. (You can also change the +** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) +*/ +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " + + +/* +@@ LUA_PROGNAME is the default name for the stand-alone Lua program. +** CHANGE it if your stand-alone interpreter has a different name and +** your system is not able to detect that name automatically. +*/ +#define LUA_PROGNAME "lua" + + +/* +@@ LUA_MAXINPUT is the maximum length for an input line in the +@* stand-alone interpreter. +** CHANGE it if you need longer lines. +*/ +#define LUA_MAXINPUT 512 + + +/* +@@ lua_readline defines how to show a prompt and then read a line from +@* the standard input. +@@ lua_saveline defines how to "save" a read line in a "history". +@@ lua_freeline defines how to free a line read by lua_readline. +** CHANGE them if you want to improve this functionality (e.g., by using +** GNU readline and history facilities). +*/ +#if defined(LUA_USE_READLINE) +#include +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,idx) \ + if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ + add_history(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L,b) ((void)L, free(b)) +#else +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } +#endif + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles +@* as a percentage. +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. +*/ +#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ + + +/* +@@ LUAI_GCMUL defines the default speed of garbage collection relative to +@* memory allocation as a percentage. +** CHANGE it if you want to change the granularity of the garbage +** collection. (Higher values mean coarser collections. 0 represents +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. +*/ +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ + + + +/* +@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. +** CHANGE it (define it) if you want exact compatibility with the +** behavior of setn/getn in Lua 5.0. +*/ +#undef LUA_COMPAT_GETN + +/* +@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. +** CHANGE it to undefined as soon as you do not need a global 'loadlib' +** function (the function is still available as 'package.loadlib'). +*/ +#undef LUA_COMPAT_LOADLIB + +/* +@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. +** CHANGE it to undefined as soon as your programs use only '...' to +** access vararg parameters (instead of the old 'arg' table). +*/ +#define LUA_COMPAT_VARARG + +/* +@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. +** CHANGE it to undefined as soon as your programs use 'math.fmod' or +** the new '%' operator instead of 'math.mod'. +*/ +#define LUA_COMPAT_MOD + +/* +@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting +@* facility. +** CHANGE it to 2 if you want the old behaviour, or undefine it to turn +** off the advisory error when nesting [[...]]. +*/ +#define LUA_COMPAT_LSTR 1 + +/* +@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. +** CHANGE it to undefined as soon as you rename 'string.gfind' to +** 'string.gmatch'. +*/ +#define LUA_COMPAT_GFIND + +/* +@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' +@* behavior. +** CHANGE it to undefined as soon as you replace to 'luaL_register' +** your uses of 'luaL_openlib' +*/ +#define LUA_COMPAT_OPENLIB + + + +/* +@@ luai_apicheck is the assert macro used by the Lua-C API. +** CHANGE luai_apicheck if you want Lua to perform some checks in the +** parameters it gets from API calls. This may slow down the interpreter +** a bit, but may be quite useful when debugging C code that interfaces +** with Lua. A useful redefinition is to use assert.h. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(L,o) { (void)L; assert(o); } +#else +#define luai_apicheck(L,o) { (void)L; } +#endif + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L +/* int has at least 32 bits */ +#define LUAI_BITSINT 32 +#else +#error "you must define LUA_BITSINT with number of bits in an integer" +#endif + + +/* +@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. +@@ LUAI_INT32 is an signed integer with at least 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. (The definitions in the 'else' +** part always works, but may waste space on machines with 64-bit +** longs.) Probably you do not need to change this. +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_UINT32 unsigned int +#define LUAI_INT32 int +#define LUAI_MAXINT32 INT_MAX +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else +/* 16-bit ints */ +#define LUAI_UINT32 unsigned long +#define LUAI_INT32 long +#define LUAI_MAXINT32 LONG_MAX +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif + + +/* +@@ LUAI_MAXCALLS limits the number of nested calls. +** CHANGE it if you need really deep recursive calls. This limit is +** arbitrary; its only purpose is to stop infinite recursion before +** exhausting memory. +*/ +#define LUAI_MAXCALLS 20000 + + +/* +@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function +@* can use. +** CHANGE it if you need lots of (Lua) stack space for your C +** functions. This limit is arbitrary; its only purpose is to stop C +** functions to consume unlimited stack space. (must be smaller than +** -LUA_REGISTRYINDEX) +*/ +#define LUAI_MAXCSTACK 8000 + + + +/* +** {================================================================== +** CHANGE (to smaller values) the following definitions if your system +** has a small C stack. (Or you may want to change them to larger +** values if your system has a large C stack and these limits are +** too rigid for you.) Some of these constants control the size of +** stack-allocated arrays used by the compiler or the interpreter, while +** others limit the maximum number of recursive calls that the compiler +** or the interpreter can perform. Values too large may cause a C stack +** overflow for some forms of deep constructs. +** =================================================================== +*/ + + +/* +@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and +@* syntactical nested non-terminals in a program. +*/ +#define LUAI_MAXCCALLS 200 + + +/* +@@ LUAI_MAXVARS is the maximum number of local variables per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXVARS 200 + + +/* +@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXUPVALUES 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE BUFSIZ + +/* }================================================================== */ + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double + +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +#define LUAI_UACNUMBER double + + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +@@ lua_str2number converts a string to a number. +*/ +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#define lua_str2number(s,p) strtod((s), (p)) + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ +#if defined(LUA_CORE) +#include +#define luai_numadd(a,b) ((a)+(b)) +#define luai_numsub(a,b) ((a)-(b)) +#define luai_nummul(a,b) ((a)*(b)) +#define luai_numdiv(a,b) ((a)/(b)) +#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(a,b) (pow(a,b)) +#define luai_numunm(a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + +/* +@@ lua_number2int is a macro to convert lua_Number to int. +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +** CHANGE them if you know a faster way to convert a lua_Number to +** int (with any rounding method and without throwing errors) in your +** system. In Pentium machines, a naive typecast from double to int +** in C is extremely slow, so any alternative is worth trying. +*/ + +/* On a Pentium, resort to a trick */ +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ + (defined(__i386) || defined (_M_IX86) || defined(__i386__)) + +/* On a Microsoft compiler, use assembler */ +#if defined(_MSC_VER) + +#define lua_number2int(i,d) __asm fld d __asm fistp i +#define lua_number2integer(i,n) lua_number2int(i, n) + +/* the next trick should work on any Pentium, but sometimes clashes + with a DirectX idiosyncrasy */ +#else + +union luai_Cast { double l_d; long l_l; }; +#define lua_number2int(i,d) \ + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +#define lua_number2integer(i,n) lua_number2int(i, n) + +#endif + + +/* this option always works, but may be slow */ +#else +#define lua_number2int(i,d) ((i)=(int)(d)) +#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. +** CHANGE it if your system requires alignments larger than double. (For +** instance, if your system supports long doubles and they must be +** aligned in 16-byte boundaries, then you should add long double in the +** union.) Probably you do not need to change this. +*/ +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } + + +/* +@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. +** CHANGE them if you prefer to use longjmp/setjmp even with C++ +** or if want/don't to use _longjmp/_setjmp instead of regular +** longjmp/setjmp. By default, Lua handles errors with exceptions when +** compiling as C++ code, with _longjmp/_setjmp when asked to use them, +** and with longjmp/setjmp otherwise. +*/ +#if defined(__cplusplus) +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) try { a } catch(...) \ + { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_ULONGJMP) +/* in Unix, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else +/* default handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif + + +/* +@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern +@* can do during pattern-matching. +** CHANGE it if you need more captures. This limit is arbitrary. +*/ +#define LUA_MAXCAPTURES 32 + + +/* +@@ lua_tmpnam is the function that the OS library uses to create a +@* temporary name. +@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. +** CHANGE them if you have an alternative to tmpnam (which is considered +** insecure) or if you want the original tmpnam anyway. By default, Lua +** uses tmpnam except when POSIX is available, where it uses mkstemp. +*/ +#if defined(loslib_c) || defined(luaall_c) + +#if defined(LUA_USE_MKSTEMP) +#include +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +#endif + +#endif + + +/* +@@ lua_popen spawns a new process connected to the current one through +@* the file streams. +** CHANGE it if you have a way to implement it in your system. +*/ +#if defined(LUA_USE_POPEN) + +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) + +#elif defined(LUA_WIN) + +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) + +#else + +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), 0) + +#endif + +/* +@@ LUA_DL_* define which dynamic-library system Lua should use. +** CHANGE here if Lua has problems choosing the appropriate +** dynamic-library system for your platform (either Windows' DLL, Mac's +** dyld, or Unix's dlopen). If your system is some kind of Unix, there +** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for +** it. To use dlopen you also need to adapt the src/Makefile (probably +** adding -ldl to the linker options), so Lua does not select it +** automatically. (When you change the makefile to add -ldl, you must +** also add -DLUA_USE_DLOPEN.) +** If you do not want any kind of dynamic library, undefine all these +** options. +** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. +*/ +#if defined(LUA_USE_DLOPEN) +#define LUA_DL_DLOPEN +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#endif + + +/* +@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State +@* (the data goes just *before* the lua_State pointer). +** CHANGE (define) this if you really need that. This value must be +** a multiple of the maximum alignment required for your machine. +*/ +#define LUAI_EXTRASPACE 0 + + +/* +@@ luai_userstate* allow user-specific actions on threads. +** CHANGE them if you defined LUAI_EXTRASPACE and need to do something +** extra when a thread is created/deleted/resumed/yielded. +*/ +#define luai_userstateopen(L) ((void)L) +#define luai_userstateclose(L) ((void)L) +#define luai_userstatethread(L,L1) ((void)L) +#define luai_userstatefree(L) ((void)L) +#define luai_userstateresume(L,n) ((void)L) +#define luai_userstateyield(L,n) ((void)L) + + +/* +@@ LUA_INTFRMLEN is the length modifier for integer conversions +@* in 'string.format'. +@@ LUA_INTFRM_T is the integer type correspoding to the previous length +@* modifier. +** CHANGE them if your system supports long long or does not support long. +*/ + +#if defined(LUA_USELONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/lua/lua/lualib.h b/lua/lua/lualib.h new file mode 100644 index 00000000..469417f6 --- /dev/null +++ b/lua/lua/lualib.h @@ -0,0 +1,53 @@ +/* +** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* Key to file-handle type */ +#define LUA_FILEHANDLE "FILE*" + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int (luaopen_base) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUALIB_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUALIB_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int (luaopen_string) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUALIB_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#ifndef lua_assert +#define lua_assert(x) ((void)0) +#endif + + +#endif From 9b14eb251b6f87c3ad2c1aca695b6d450ec45a7c Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 22 Dec 2012 13:51:05 +0100 Subject: [PATCH 031/100] (cherry picked from Steve Donovan fork) configuring cgo directly isntead of using pkg-config (let's see if it works better) --- lua/golua.go | 2 +- lua/lua.go | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lua/golua.go b/lua/golua.go index ba37c92d..746055c5 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -1,7 +1,7 @@ package lua /* -#cgo pkg-config: lua5.1 +#cgo CFLAGS: -Ilua #include #include diff --git a/lua/lua.go b/lua/lua.go index d23a07a0..8501f1fc 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -6,7 +6,11 @@ package lua /* -#cgo pkg-config: lua5.1 +#cgo CFLAGS: -Ilua +#cgo llua LDFLAGS: -llua +#cgo linux,!llua LDFLAGS: -llua5.1 +#cgo darwin LDFLAGS: -llua +#cgo freebsd LDFLAGS: -llua #include #include From a8bb2405af44c47a149b0a9e7cbdb9ee8cc85d70 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Tue, 1 Jan 2013 10:53:09 +0100 Subject: [PATCH 032/100] updated README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1bbb23bc..e6c8883a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Simplest way to install: # go get -u github.com/aarzilli/golua/lua -Will work as long as `pkg-config` knows about lua. +Will work as long as your compiler can find a shared object called lua5.1 on linux, or lua anywhere else (use the build tag llua if you have linux but your lua isn't called "lua5.1"). You can then try to run the examples: @@ -65,6 +65,10 @@ func main() { L.DoString("print(adder(2, 2))") } ``` +SEE ALSO +--------------------- + +[Luar](https://github.com/stevedonovan/luar/) is a reflection layer on top of golua API providing a simplified way to publish go functions to a Lua VM. Licensing ------------- @@ -72,6 +76,3 @@ GoLua is released under the MIT license. Please see the LICENSE file for more information. Lua is Copyright (c) Lua.org, PUC-Rio. All rights reserved. - - - From d8e5c9edda313e31cb7b7e23f3b503a296dfc335 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sun, 31 Mar 2013 15:34:24 +0200 Subject: [PATCH 033/100] Fixes issue #4 (or at least I hope it does) --- README.md | 29 +++++ example/error.go | 13 +- example/userdata.go | 5 +- lua/c-golua.c | 30 ++++- lua/golua.go | 20 ++- lua/golua.h | 4 + lua/lauxlib.go | 23 +--- lua/lua.go | 52 +++++--- lua/lua_test.go | 290 +++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 395 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index e6c8883a..59d84d7c 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,35 @@ func main() { L.DoString("print(adder(2, 2))") } ``` + +ON ERROR HANDLING +--------------------- + +Lua's exceptions are incompatible with Go, golua works around this incompatibility by setting up protected execution environments in `lua.State.DoString`, `lua.State.DoFile` and lua.State.Call and turning every exception into a Go panic. + +This means that: +1. In general you can't do any exception handling from Lua, `pcall` and `xpcall` are renamed to `unsafe_pcall` and `unsafe_xpcall`. They are only safe to be called from Lua code that never calls back to Go. Use at your own risk. +2. The call to lua.State.Error, present in previous versions of this library, has been removed as it is nonsensical +3. Method calls on a newly created `lua.State` happen in an unprotected environment, if Lua throws an exception as a result your program will be terminated. If this is undesirable perform your initialization like this: + +```go +func LuaStateInit(L *lua.State) int { + … initialization goes here… + return 0 +} + +… +L.PushGoFunction(LuaStateInit) +err := L.Call(0, 0) +… +``` + +ON THREADS AND COROUTINES +--------------------- + +'lua.State' is not thread safe, but the library itself is. Lua's coroutines exist but (to my knowledge) have never been tested and are likely to encounter the same problems that errors have, use at your own peril. + + SEE ALSO --------------------- diff --git a/example/error.go b/example/error.go index 32e9ee20..778d9425 100644 --- a/example/error.go +++ b/example/error.go @@ -18,12 +18,6 @@ func faultyfunc(L *lua.State) int { panic(errors.New("An error")) } -func faultyfunc2(L *lua.State) int { - L.PushString("Some error") - L.Error() - return 1 -} - func testRegistered(L *lua.State) { L.Register("faultyfunc", faultyfunc) err := L.DoString("faultyfunc()") @@ -34,9 +28,8 @@ func testRegistered(L *lua.State) { } } -func testRegistered2(L *lua.State) { - L.Register("faultyfunc2", faultyfunc2) - err := L.DoString("faultyfunc2()") +func test2(L *lua.State) { + err := L.DoString("error(\"Some error\")") fmt.Printf("Error is %v\n", err) if err == nil { fmt.Printf("Error shouldn't have been nil\n") @@ -51,5 +44,5 @@ func main() { testDefault(L) testRegistered(L) - testRegistered2(L) + test2(L) } diff --git a/example/userdata.go b/example/userdata.go index 96f90049..eb6ac3bd 100644 --- a/example/userdata.go +++ b/example/userdata.go @@ -70,6 +70,7 @@ func goDefinedObjects(L *lua.State) { func main() { L := lua.NewState() + defer L.Close() L.OpenLibs(); /* @@ -80,7 +81,7 @@ func main() { /* This function demonstrates exposing a function implemented in go to interpreted Lua code */ - goDefinedFunctions(L); + goDefinedFunctions(L) - goDefinedObjects(L); + goDefinedObjects(L) } diff --git a/lua/c-golua.c b/lua/c-golua.c index fbf3389d..9a5518e1 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -7,6 +7,8 @@ #define MT_GOFUNCTION "GoLua.GoFunction" #define MT_GOINTERFACE "GoLua.GoInterface" +#define GOLUA_DEFAULT_MSGHANDLER "golua_default_msghandler" + static const char GoStateRegistryKey = 'k'; //golua registry key static const char PanicFIDRegistryKey = 'k'; @@ -71,11 +73,7 @@ int callback_function(lua_State* L) GoInterface* gi = clua_getgostate(L); //remove the go function from the stack (to present same behavior as lua_CFunctions) lua_remove(L,1); - r = golua_callgofunction(*gi, fid!=NULL ? *fid : -1); - if (golua_error_requested(*gi)) { - lua_error(L); - } - return r; + return golua_callgofunction(*gi, fid!=NULL ? *fid : -1); } //wrapper for gchook @@ -204,10 +202,28 @@ int interface_newindex_callback(lua_State *L) } } +int panic_msghandler(lua_State *L) +{ + go_panic_msghandler((char *)lua_tolstring(L, -1, NULL)); +} + +void clua_hide_pcall(lua_State *L) +{ + lua_getglobal(L, "pcall"); + lua_setglobal(L, "unsafe_pcall"); + lua_pushnil(L); + lua_setglobal(L, "pcall"); + + lua_getglobal(L, "xpcall"); + lua_setglobal(L, "unsafe_xpcall"); + lua_pushnil(L); + lua_setglobal(L, "xpcall"); +} + void clua_initstate(lua_State* L) { /* create the GoLua.GoFunction metatable */ - luaL_newmetatable(L,MT_GOFUNCTION); + luaL_newmetatable(L, MT_GOFUNCTION); // gofunction_metatable[__call] = &callback_function lua_pushliteral(L,"__call"); @@ -237,6 +253,7 @@ void clua_initstate(lua_State* L) lua_pushcfunction(L, &interface_newindex_callback); lua_settable(L, -3); + lua_register(L, GOLUA_DEFAULT_MSGHANDLER, &panic_msghandler); lua_pop(L, 1); } @@ -309,6 +326,7 @@ void clua_openbase(lua_State* L) lua_pushcfunction(L,&luaopen_base); lua_pushstring(L,""); lua_call(L, 1, 0); + clua_hide_pcall(L); } void clua_openio(lua_State* L) diff --git a/lua/golua.go b/lua/golua.go index 746055c5..da22d75d 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -31,26 +31,18 @@ type State struct { // Freelist for funcs indices, to allow for freeing freeIndices []uint - - // Go functions can set this to true to have their C wrapper call lua_error (they can't call it directly) - errorRequested bool } //export golua_callgofunction func golua_callgofunction(L interface{}, fid uint) int { - if fid < 0 { panic(&LuaError{"Requested execution of an unknown function"}) } + if fid < 0 { + panic(&LuaError{"Requested execution of an unknown function"}) + } L1 := L.(*State) - L1.errorRequested = false f := L1.registry[fid].(LuaGoFunction) return f(L1) } -//export golua_error_requested -func golua_error_requested(L interface{}) bool { - L1 := L.(*State) - return L1.errorRequested -} - //export golua_interface_newindex_callback func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr *C.char) int { L := Li.(*State) @@ -220,3 +212,9 @@ func golua_cfunctiontointerface(f *uintptr) interface{} { func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr), osize, nsize)) } + +//export go_panic_msghandler +func go_panic_msghandler(z *C.char) { + s := C.GoString(z) + panic(&LuaError{s}) +} \ No newline at end of file diff --git a/lua/golua.h b/lua/golua.h index 604d168e..5f8e8125 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -2,8 +2,11 @@ typedef struct { void *t; void *v; } GoInterface; +#define GOLUA_DEFAULT_MSGHANDLER "golua_default_msghandler" + /* function to setup metatables, etc */ void clua_initstate(lua_State* L); +void clua_hide_pcall(lua_State *L); unsigned int clua_togofunction(lua_State* L, int index); unsigned int clua_togostruct(lua_State *L, int index); @@ -28,3 +31,4 @@ void clua_setexecutionlimit(lua_State* L, int n); int clua_isgofunction(lua_State *L, int n); int clua_isgostruct(lua_State *L, int n); + diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 795d8b8b..dc8260cd 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -80,30 +80,12 @@ func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { return unsafe.Pointer(C.luaL_checkudata(L.s, C.int(narg), Ctname)) } -func (L *State) pcallAndCatchErrors() (err error) { - defer func() { - if err2 := recover(); err2 != nil { - if _, ok := err2.(error); ok { - err = err2.(error) - } - return; - } - }() - err = nil - - if L.PCall(0, LUA_MULTRET, 0) != 0 { - err = &LuaError{L.ToString(-1)} - } - - return -} - // Executes file, returns nil for no errors or the lua error string on failure func (L *State) DoFile(filename string) error { if L.LoadFile(filename) != 0 { return &LuaError{L.ToString(-1)} } - return L.pcallAndCatchErrors() + return L.Call(0, LUA_MULTRET); } // Executes the string, returns nil for no errors or the lua error string on failure @@ -111,7 +93,7 @@ func (L *State) DoString(str string) error { if L.LoadString(str) != 0 { return &LuaError{L.ToString(-1)} } - return L.pcallAndCatchErrors() + return L.Call(0, LUA_MULTRET) } // Like DoString but panics on error @@ -180,6 +162,7 @@ func NewState() *State { // luaL_openlibs func (L *State) OpenLibs() { C.luaL_openlibs(L.s) + C.clua_hide_pcall(L.s) } // luaL_optinteger diff --git a/lua/lua.go b/lua/lua.go index 8501f1fc..ccbfb57e 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -20,11 +20,10 @@ package lua */ import "C" import "unsafe" -//import "fmt" func newState(L *C.lua_State) *State { var newstatei interface{} - newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8), false} + newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8)} newstatei = newstate ns1 := unsafe.Pointer(&newstatei) ns2 := (*C.GoInterface)(ns1) @@ -161,9 +160,39 @@ func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { return nil } +func (L *State) pcall(nargs, nresults, errfunc int) int { + return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) +} + +func (L *State) pcallAndCatchErrors(nargs, nresults, erridx int) (err error) { + defer func() { + if err2 := recover(); err2 != nil { + if _, ok := err2.(error); ok { + err = err2.(error) + } + return; + } + }() + err = nil + + if L.pcall(nargs, nresults, erridx) != 0 { + err = &LuaError{L.ToString(-1)} + } + + return +} + // lua_call -func (L *State) Call(nargs int, nresults int) { - C.lua_call(L.s, C.int(nargs), C.int(nresults)) +func (L *State) Call(nargs int, nresults int) error { + L.GetGlobal(C.GOLUA_DEFAULT_MSGHANDLER) + // We must record where we put the error handler in the stack otherwise it will be impossible to remove after the pcall when nresults == LUA_MULTRET + erridx := L.GetTop()-nargs-1 + L.Insert(erridx) + r := L.pcallAndCatchErrors(nargs, nresults, L.GetTop()-nargs-1) + if r == nil { + L.Remove(erridx) + } + return r } // lua_checkstack @@ -294,7 +323,7 @@ func (L *State) NewThread() *State { //TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) - return &State{s, nil, nil, false} + return &State{s, nil, nil} } // lua_next @@ -307,11 +336,6 @@ func (L *State) ObjLen(index int) uint { return uint(C.lua_objlen(L.s, C.int(index))) } -// lua_pcall -func (L *State) PCall(nargs int, nresults int, errfunc int) int { - return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) -} - // lua_pop func (L *State) Pop(n int) { //Why is this implemented this way? I don't get it... @@ -567,11 +591,3 @@ func (L *State) OpenOS() { func (L *State) SetExecutionLimit(instrNumber int) { C.clua_setexecutionlimit(L.s, C.int(instrNumber)) } - -// Calls lua_error. -// The call to lua error will be delayed until control returns to Lua VM: -// follow a call to this function with a return and make sure you leave a string describing the error on the stack -func (L *State) Error() { - L.errorRequested = true -} - diff --git a/lua/lua_test.go b/lua/lua_test.go index e21d4bb3..f82c0e29 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -2,6 +2,7 @@ package lua import ( "testing" + "unsafe" ) type TestStruct struct { @@ -38,9 +39,290 @@ func TestGoStruct(t *testing.T) { L.Pop(1) } +func TestCheckStringSuccess(t *testing.T) { + L := NewState() + L.OpenLibs() + defer L.Close() + + Test := func(L *State) int { + L.PushString("this is a test") + L.CheckString(-1) + return 0 + } + + L.Register("test", Test) + err := L.DoString("test()") + if err != nil { + t.Fatalf("DoString did return an error: %v\n", err.Error()) + } +} + +func TestCheckStringFail(t *testing.T) { + L := NewState() + L.OpenLibs() + defer L.Close() + + Test := func(L *State) int { + L.CheckString(-1) + return 0 + } + + L.Register("test", Test) + err := L.DoString("test();") + if err == nil { + t.Fatal("DoString did not return an error\n") + } +} + +func TestPCallHidden(t *testing.T) { + L := NewState() + L.OpenLibs() + defer L.Close() + + err := L.DoString("pcall(print, \"ciao\")") + if err == nil { + t.Fatal("Can use pcall\n") + } + + err = L.DoString("unsafe_pcall(print, \"ciao\")") + if err != nil { + t.Fatal("Can not use unsafe_pcall\n") + } +} + +func TestCall(t *testing.T) { + L := NewState() + L.OpenLibs() + defer L.Close() + + test := func (L *State) int { + arg1 := L.ToString(1) + arg2 := L.ToString(2) + arg3 := L.ToString(3) + + if arg1 != "Argument1" { + t.Fatal("Got wrong argument (1)") + } + + if arg2 != "Argument2" { + t.Fatal("Got wrong argument (2)") + } + + if arg3 != "Argument3" { + t.Fatal("Got wrong argument (3)") + } + + L.PushString("Return1") + L.PushString("Return2") + + return 2 + } + + L.Register("test", test) + + L.PushString("Dummy") + L.GetGlobal("test") + L.PushString("Argument1") + L.PushString("Argument2") + L.PushString("Argument3") + err := L.Call(3, 2) + + if err != nil { + t.Fatalf("Error executing call: %v\n", err) + } + + dummy := L.ToString(1) + ret1 := L.ToString(2) + ret2 := L.ToString(3) + + if dummy != "Dummy" { + t.Fatal("The stack was disturbed") + } + + if ret1 != "Return1" { + t.Fatalf("Wrong return value (1) got: <%s>", ret1) + } + + if ret2 != "Return2" { + t.Fatalf("Wrong return value (2) got: <%s>", ret2) + } +} + +// equivalent to basic.go +func TestLikeBasic(t *testing.T) { + L := NewState() + defer L.Close() + L.OpenLibs() -// TODO: -// - function test -// - struct field getting and setting test -// - DoFile / DoString tests (including errors + testCalled := 0 + test := func(L *State) int { + testCalled++ + return 0 + } + + test2Arg := -1 + test2Argfrombottom := -1 + test2 := func(L *State) int { + test2Arg = L.CheckInteger(-1) + test2Argfrombottom = L.CheckInteger(1) + return 0 + } + + L.GetField(LUA_GLOBALSINDEX, "print") + L.PushString("Hello World!") + if err := L.Call(1,0); err != nil { + t.Fatalf("Call to print returned error") + } + + L.PushGoFunction(test) + L.PushGoFunction(test) + L.PushGoFunction(test) + L.PushGoFunction(test2) + L.PushInteger(42) + if err := L.Call(1,0); err != nil { + t.Fatalf("Call to print returned error") + } + if (test2Arg != 42) || (test2Argfrombottom != 42) { + t.Fatalf("Call to test2 didn't work") + } + + if err := L.Call(0,0); err != nil { + t.Fatalf("Call to print returned error") + } + if err := L.Call(0,0); err != nil { + t.Fatalf("Call to print returned error") + } + if err := L.Call(0,0); err != nil { + t.Fatalf("Call to print returned error") + } + if testCalled != 3 { + t.Fatalf("Test function not called the correct number of times: %d\n", testCalled); + } + + // this will fail as we didn't register test2 function + if err := L.DoString("test2(42)"); err == nil { + t.Fatal("No error when calling unregistered function") + } +} + +// equivalent to quickstart.go +func TestLikeQuickstart(t *testing.T) { + adder := func(L *State) int { + a := L.ToInteger(1) + b := L.ToInteger(2) + L.PushInteger(int64(a + b)) + return 1 + } + + L := NewState() + defer L.Close() + L.OpenLibs() + + L.Register("adder", adder) + + if err := L.DoString("return adder(2, 2)"); err != nil { + t.Fatalf("Error during call to adder: %v\n", err) + } + if r := L.ToInteger(1); r != 4 { + t.Fatalf("Wrong return value from adder (was: %d)\n", r) + } +} + +// equivalent to userdata.go +func TestLikeUserdata(t *testing.T) { + type Userdata struct { + a,b int + } + + userDataProper := func(L *State) { + rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{}))); + var ptr *Userdata; + ptr = (*Userdata)(rawptr); + ptr.a = 2; + ptr.b = 3; + + rawptr2 := L.ToUserdata(-1); + ptr2 := (*Userdata)(rawptr2); + + if ptr != ptr2 { + t.Fatalf("Failed to create userdata\n") + } + } + + testCalled := 0 + test := func(L *State) int { + testCalled++ + return 0 + } + + goDefinedFunctions := func(L *State) { + /* example_function is registered inside Lua VM */ + L.Register("test", test) + + /* This code demonstrates checking that a value on the stack is a go function */ + L.CheckStack(1) + L.GetGlobal("test") + if !L.IsGoFunction(-1) { + t.Fatalf("IsGoFunction failed to recognize a Go function object") + } + L.Pop(1) + + /* We call example_function from inside Lua VM */ + testCalled = 0 + if err := L.DoString("test()"); err != nil { + t.Fatalf("Error executing test function: %v\n", err) + } + if testCalled != 1 { + t.Fatalf("It appears the test function wasn't actually called\n"); + } + } + + type TestObject struct { + AField int + } + + goDefinedObjects := func(L *State) { + z := &TestObject{42} + + L.PushGoStruct(z) + L.SetGlobal("z") + + /* This code demonstrates checking that a value on the stack is a go object */ + L.CheckStack(1) + L.GetGlobal("z") + if !L.IsGoStruct(-1) { + t.Fatal("IsGoStruct failed to recognize a Go struct\n") + } + L.Pop(1) + + /* This code demonstrates access and assignment to a field of a go object */ + if err := L.DoString("return z.AField"); err != nil { + t.Fatal("Couldn't execute code") + } + before := L.ToInteger(-1) + L.Pop(1) + if before != 42 { + t.Fatalf("Wrong value of z.AField before change (%d)\n", before) + } + if err := L.DoString("z.AField = 10;"); err != nil { + t.Fatal("Couldn't execute code") + } + if err := L.DoString("return z.AField"); err != nil { + t.Fatal("Couldn't execute code") + } + after := L.ToInteger(-1) + L.Pop(1) + if after != 10 { + t.Fatalf("Wrong value of z.AField after change (%d)\n", after) + } + } + + L := NewState() + defer L.Close() + L.OpenLibs() + + userDataProper(L) + goDefinedFunctions(L) + goDefinedObjects(L) +} From cb419472bd9d483a78fd8198f811b082e51f36cc Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sun, 31 Mar 2013 16:53:48 +0200 Subject: [PATCH 034/100] collect all consts under a single const statement --- lua/lua_defs.go | 110 ++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 54 deletions(-) diff --git a/lua/lua_defs.go b/lua/lua_defs.go index 96409ee5..2ad9b68a 100644 --- a/lua/lua_defs.go +++ b/lua/lua_defs.go @@ -8,57 +8,59 @@ package lua */ import "C" -const LUA_VERSION = C.LUA_VERSION -const LUA_RELEASE = C.LUA_RELEASE -const LUA_VERSION_NUM = C.LUA_VERSION_NUM -const LUA_COPYRIGHT = C.LUA_COPYRIGHT -const LUA_AUTHORS = C.LUA_AUTHORS -const LUA_MULTRET = C.LUA_MULTRET -const LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX -const LUA_ENVIRONINDEX = C.LUA_ENVIRONINDEX -const LUA_GLOBALSINDEX = C.LUA_GLOBALSINDEX -const LUA_YIELD = C.LUA_YIELD -const LUA_ERRRUN = C.LUA_ERRRUN -const LUA_ERRSYNTAX = C.LUA_ERRSYNTAX -const LUA_ERRMEM = C.LUA_ERRMEM -const LUA_ERRERR = C.LUA_ERRERR -const LUA_TNONE = C.LUA_TNONE -const LUA_TNIL = C.LUA_TNIL -const LUA_TBOOLEAN = C.LUA_TBOOLEAN -const LUA_TLIGHTUSERDATA = C.LUA_TLIGHTUSERDATA -const LUA_TNUMBER = C.LUA_TNUMBER -const LUA_TSTRING = C.LUA_TSTRING -const LUA_TTABLE = C.LUA_TTABLE -const LUA_TFUNCTION = C.LUA_TFUNCTION -const LUA_TUSERDATA = C.LUA_TUSERDATA -const LUA_TTHREAD = C.LUA_TTHREAD -const LUA_MINSTACK = C.LUA_MINSTACK -const LUA_GCSTOP = C.LUA_GCSTOP -const LUA_GCRESTART = C.LUA_GCRESTART -const LUA_GCCOLLECT = C.LUA_GCCOLLECT -const LUA_GCCOUNT = C.LUA_GCCOUNT -const LUA_GCCOUNTB = C.LUA_GCCOUNTB -const LUA_GCSTEP = C.LUA_GCSTEP -const LUA_GCSETPAUSE = C.LUA_GCSETPAUSE -const LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL -const LUA_HOOKCALL = C.LUA_HOOKCALL -const LUA_HOOKRET = C.LUA_HOOKRET -const LUA_HOOKLINE = C.LUA_HOOKLINE -const LUA_HOOKCOUNT = C.LUA_HOOKCOUNT -const LUA_HOOKTAILRET = C.LUA_HOOKTAILRET -const LUA_MASKCALL = C.LUA_MASKCALL -const LUA_MASKRET = C.LUA_MASKRET -const LUA_MASKLINE = C.LUA_MASKLINE -const LUA_MASKCOUNT = C.LUA_MASKCOUNT -const LUA_ERRFILE = C.LUA_ERRFILE -const LUA_NOREF = C.LUA_NOREF -const LUA_REFNIL = C.LUA_REFNIL -const LUA_FILEHANDLE = C.LUA_FILEHANDLE -const LUA_COLIBNAME = C.LUA_COLIBNAME -const LUA_TABLIBNAME = C.LUA_TABLIBNAME -const LUA_IOLIBNAME = C.LUA_IOLIBNAME -const LUA_OSLIBNAME = C.LUA_OSLIBNAME -const LUA_STRLIBNAME = C.LUA_STRLIBNAME -const LUA_MATHLIBNAME = C.LUA_MATHLIBNAME -const LUA_DBLIBNAME = C.LUA_DBLIBNAME -const LUA_LOADLIBNAME = C.LUA_LOADLIBNAME +const ( + LUA_VERSION = C.LUA_VERSION + LUA_RELEASE = C.LUA_RELEASE + LUA_VERSION_NUM = C.LUA_VERSION_NUM + LUA_COPYRIGHT = C.LUA_COPYRIGHT + LUA_AUTHORS = C.LUA_AUTHORS + LUA_MULTRET = C.LUA_MULTRET + LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX + LUA_ENVIRONINDEX = C.LUA_ENVIRONINDEX + LUA_GLOBALSINDEX = C.LUA_GLOBALSINDEX + LUA_YIELD = C.LUA_YIELD + LUA_ERRRUN = C.LUA_ERRRUN + LUA_ERRSYNTAX = C.LUA_ERRSYNTAX + LUA_ERRMEM = C.LUA_ERRMEM + LUA_ERRERR = C.LUA_ERRERR + LUA_TNONE = C.LUA_TNONE + LUA_TNIL = C.LUA_TNIL + LUA_TBOOLEAN = C.LUA_TBOOLEAN + LUA_TLIGHTUSERDATA = C.LUA_TLIGHTUSERDATA + LUA_TNUMBER = C.LUA_TNUMBER + LUA_TSTRING = C.LUA_TSTRING + LUA_TTABLE = C.LUA_TTABLE + LUA_TFUNCTION = C.LUA_TFUNCTION + LUA_TUSERDATA = C.LUA_TUSERDATA + LUA_TTHREAD = C.LUA_TTHREAD + LUA_MINSTACK = C.LUA_MINSTACK + LUA_GCSTOP = C.LUA_GCSTOP + LUA_GCRESTART = C.LUA_GCRESTART + LUA_GCCOLLECT = C.LUA_GCCOLLECT + LUA_GCCOUNT = C.LUA_GCCOUNT + LUA_GCCOUNTB = C.LUA_GCCOUNTB + LUA_GCSTEP = C.LUA_GCSTEP + LUA_GCSETPAUSE = C.LUA_GCSETPAUSE + LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL + LUA_HOOKCALL = C.LUA_HOOKCALL + LUA_HOOKRET = C.LUA_HOOKRET + LUA_HOOKLINE = C.LUA_HOOKLINE + LUA_HOOKCOUNT = C.LUA_HOOKCOUNT + LUA_HOOKTAILRET = C.LUA_HOOKTAILRET + LUA_MASKCALL = C.LUA_MASKCALL + LUA_MASKRET = C.LUA_MASKRET + LUA_MASKLINE = C.LUA_MASKLINE + LUA_MASKCOUNT = C.LUA_MASKCOUNT + LUA_ERRFILE = C.LUA_ERRFILE + LUA_NOREF = C.LUA_NOREF + LUA_REFNIL = C.LUA_REFNIL + LUA_FILEHANDLE = C.LUA_FILEHANDLE + LUA_COLIBNAME = C.LUA_COLIBNAME + LUA_TABLIBNAME = C.LUA_TABLIBNAME + LUA_IOLIBNAME = C.LUA_IOLIBNAME + LUA_OSLIBNAME = C.LUA_OSLIBNAME + LUA_STRLIBNAME = C.LUA_STRLIBNAME + LUA_MATHLIBNAME = C.LUA_MATHLIBNAME + LUA_DBLIBNAME = C.LUA_DBLIBNAME + LUA_LOADLIBNAME = C.LUA_LOADLIBNAME +) \ No newline at end of file From 67ae247c6963a90de6b50eaf7e66341bb7268af1 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sun, 31 Mar 2013 17:02:43 +0200 Subject: [PATCH 035/100] Added list of contributors to README.md If you contributed and I didn't include you complain. --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 59d84d7c..98637af6 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,16 @@ ON THREADS AND COROUTINES 'lua.State' is not thread safe, but the library itself is. Lua's coroutines exist but (to my knowledge) have never been tested and are likely to encounter the same problems that errors have, use at your own peril. +CONTRIBUTORS +--------------------- + +Adam Fitzgerald (original author) +Alessandro Arzilli +Steve Donovan +Harley Laue +James Nurmi +Ruitao +Xushiwei SEE ALSO --------------------- From 54de8197815d45cf963d5db240351894f8e39315 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 1 Apr 2013 11:09:57 +0200 Subject: [PATCH 036/100] Saving lua return code inside LuaError --- lua/golua.go | 6 +++--- lua/lauxlib.go | 13 +++++++++---- lua/lua.go | 48 +++++++++++++++++++++++++++--------------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/lua/golua.go b/lua/golua.go index da22d75d..fee0f168 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -36,7 +36,7 @@ type State struct { //export golua_callgofunction func golua_callgofunction(L interface{}, fid uint) int { if fid < 0 { - panic(&LuaError{"Requested execution of an unknown function"}) + panic(&LuaError{0, "Requested execution of an unknown function"}) } L1 := L.(*State) f := L1.registry[fid].(LuaGoFunction) @@ -216,5 +216,5 @@ func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { //export go_panic_msghandler func go_panic_msghandler(z *C.char) { s := C.GoString(z) - panic(&LuaError{s}) -} \ No newline at end of file + panic(&LuaError{0, s}) +} diff --git a/lua/lauxlib.go b/lua/lauxlib.go index dc8260cd..53bf3370 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -9,6 +9,7 @@ import "C" import "unsafe" type LuaError struct { + code int message string } @@ -16,6 +17,10 @@ func (err *LuaError) Error() string { return err.message } +func (err *LuaError) Code() int { + return err.code +} + // luaL_argcheck func (L *State) ArgCheck(cond bool, narg int, extramsg string) { if cond { @@ -82,16 +87,16 @@ func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { // Executes file, returns nil for no errors or the lua error string on failure func (L *State) DoFile(filename string) error { - if L.LoadFile(filename) != 0 { - return &LuaError{L.ToString(-1)} + if r := L.LoadFile(filename); r != 0 { + return &LuaError{r, L.ToString(-1)} } return L.Call(0, LUA_MULTRET); } // Executes the string, returns nil for no errors or the lua error string on failure func (L *State) DoString(str string) error { - if L.LoadString(str) != 0 { - return &LuaError{L.ToString(-1)} + if r := L.LoadString(str); r != 0 { + return &LuaError{r, L.ToString(-1)} } return L.Call(0, LUA_MULTRET) } diff --git a/lua/lua.go b/lua/lua.go index ccbfb57e..84b56b56 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -164,35 +164,41 @@ func (L *State) pcall(nargs, nresults, errfunc int) int { return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) } -func (L *State) pcallAndCatchErrors(nargs, nresults, erridx int) (err error) { - defer func() { - if err2 := recover(); err2 != nil { - if _, ok := err2.(error); ok { - err = err2.(error) +func (L *State) callEx(nargs, nresults int, catch bool) (err error) { + if (catch) { + defer func() { + if err2 := recover(); err2 != nil { + if _, ok := err2.(error); ok { + err = err2.(error) + } + return; } - return; - } - }() - err = nil - - if L.pcall(nargs, nresults, erridx) != 0 { - err = &LuaError{L.ToString(-1)} + }() } - return -} - -// lua_call -func (L *State) Call(nargs int, nresults int) error { L.GetGlobal(C.GOLUA_DEFAULT_MSGHANDLER) // We must record where we put the error handler in the stack otherwise it will be impossible to remove after the pcall when nresults == LUA_MULTRET erridx := L.GetTop()-nargs-1 L.Insert(erridx) - r := L.pcallAndCatchErrors(nargs, nresults, L.GetTop()-nargs-1) - if r == nil { - L.Remove(erridx) + r := L.pcall(nargs, nresults, erridx) + L.Remove(erridx) + if r != 0 { + err = &LuaError{r, L.ToString(-1)} + if !catch { + panic(err) + } } - return r + return +} + +// lua_call +func (L *State) Call(nargs, nresults int) (err error) { + return L.callEx(nargs, nresults, true) +} + +// Like lua_call but panics on errors +func (L *State) MustCall(nargs, nresults int) { + L.callEx(nargs, nresults, false) } // lua_checkstack From e23213093530c3a7f6941bcc829bd84234ceb897 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 1 Apr 2013 12:10:52 +0200 Subject: [PATCH 037/100] saving lua stack trace --- example/calls.lua | 19 +++++++++++++++++++ lua/c-golua.c | 3 ++- lua/golua.go | 10 ++++++---- lua/lauxlib.go | 9 +++++++-- lua/lua.go | 34 +++++++++++++++++++++++++++++++++- lua/lua_test.go | 31 ++++++++++++++++++++++++++----- 6 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 example/calls.lua diff --git a/example/calls.lua b/example/calls.lua new file mode 100644 index 00000000..454109ac --- /dev/null +++ b/example/calls.lua @@ -0,0 +1,19 @@ +-- The only point of this file is to generate an interesting stack trace + +function call3(n) + if n == 3 then + error("Some error") + end +end + +function call2() + for i = 1, 4, 1 do + call3(i) + end +end + +function call1() + call2() +end + +call1() diff --git a/lua/c-golua.c b/lua/c-golua.c index 9a5518e1..ca5bdf4a 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -204,7 +204,8 @@ int interface_newindex_callback(lua_State *L) int panic_msghandler(lua_State *L) { - go_panic_msghandler((char *)lua_tolstring(L, -1, NULL)); + GoInterface* gi = clua_getgostate(L); + go_panic_msghandler(*gi, (char *)lua_tolstring(L, -1, NULL)); } void clua_hide_pcall(lua_State *L) diff --git a/lua/golua.go b/lua/golua.go index fee0f168..c9ad1c39 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -35,10 +35,10 @@ type State struct { //export golua_callgofunction func golua_callgofunction(L interface{}, fid uint) int { + L1 := L.(*State) if fid < 0 { - panic(&LuaError{0, "Requested execution of an unknown function"}) + panic(&LuaError{0, "Requested execution of an unknown function", L1.StackTrace()}) } - L1 := L.(*State) f := L1.registry[fid].(LuaGoFunction) return f(L1) } @@ -214,7 +214,9 @@ func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { } //export go_panic_msghandler -func go_panic_msghandler(z *C.char) { +func go_panic_msghandler(Li interface{}, z *C.char) { + L := Li.(*State) s := C.GoString(z) - panic(&LuaError{0, s}) + + panic(&LuaError{LUA_ERRERR, s, L.StackTrace()}) } diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 53bf3370..4d8b7e8e 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -11,6 +11,7 @@ import "unsafe" type LuaError struct { code int message string + stackTrace []LuaStackEntry } func (err *LuaError) Error() string { @@ -21,6 +22,10 @@ func (err *LuaError) Code() int { return err.code } +func (err *LuaError) StackTrace() []LuaStackEntry { + return err.stackTrace +} + // luaL_argcheck func (L *State) ArgCheck(cond bool, narg int, extramsg string) { if cond { @@ -88,7 +93,7 @@ func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { // Executes file, returns nil for no errors or the lua error string on failure func (L *State) DoFile(filename string) error { if r := L.LoadFile(filename); r != 0 { - return &LuaError{r, L.ToString(-1)} + return &LuaError{r, L.ToString(-1), L.StackTrace()} } return L.Call(0, LUA_MULTRET); } @@ -96,7 +101,7 @@ func (L *State) DoFile(filename string) error { // Executes the string, returns nil for no errors or the lua error string on failure func (L *State) DoString(str string) error { if r := L.LoadString(str); r != 0 { - return &LuaError{r, L.ToString(-1)} + return &LuaError{r, L.ToString(-1), L.StackTrace()} } return L.Call(0, LUA_MULTRET) } diff --git a/lua/lua.go b/lua/lua.go index 84b56b56..68eb53fc 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -21,6 +21,13 @@ package lua import "C" import "unsafe" +type LuaStackEntry struct { + Name string + Source string + ShortSource string + CurrentLine int +} + func newState(L *C.lua_State) *State { var newstatei interface{} newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8)} @@ -183,7 +190,7 @@ func (L *State) callEx(nargs, nresults int, catch bool) (err error) { r := L.pcall(nargs, nresults, erridx) L.Remove(erridx) if r != 0 { - err = &LuaError{r, L.ToString(-1)} + err = &LuaError{r, L.ToString(-1), L.StackTrace()} if !catch { panic(err) } @@ -597,3 +604,28 @@ func (L *State) OpenOS() { func (L *State) SetExecutionLimit(instrNumber int) { C.clua_setexecutionlimit(L.s, C.int(instrNumber)) } + +// Returns the current stack trace +func (L *State) StackTrace() []LuaStackEntry { + r := []LuaStackEntry{} + var d C.lua_Debug + Sln := C.CString("Sln") + defer C.free(unsafe.Pointer(Sln)) + + for depth := 0; C.lua_getstack(L.s, C.int(depth), &d) > 0; depth++ { + C.lua_getinfo(L.s, Sln, &d) + ssb := make([]byte, C.LUA_IDSIZE) + for i := 0; i < C.LUA_IDSIZE; i++ { + ssb[i] = byte(d.short_src[i]) + if ssb[i] == 0 { + ssb = ssb[:i] + break + } + } + ss := string(ssb) + + r = append(r, LuaStackEntry{ C.GoString(d.name), C.GoString(d.source), ss, int(d.currentline) }) + } + + return r +} diff --git a/lua/lua_test.go b/lua/lua_test.go index f82c0e29..4a62b054 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -257,10 +257,10 @@ func TestLikeUserdata(t *testing.T) { } goDefinedFunctions := func(L *State) { - /* example_function is registered inside Lua VM */ + // example_function is registered inside Lua VM L.Register("test", test) - /* This code demonstrates checking that a value on the stack is a go function */ + // This code demonstrates checking that a value on the stack is a go function L.CheckStack(1) L.GetGlobal("test") if !L.IsGoFunction(-1) { @@ -268,7 +268,7 @@ func TestLikeUserdata(t *testing.T) { } L.Pop(1) - /* We call example_function from inside Lua VM */ + // We call example_function from inside Lua VM testCalled = 0 if err := L.DoString("test()"); err != nil { t.Fatalf("Error executing test function: %v\n", err) @@ -288,7 +288,7 @@ func TestLikeUserdata(t *testing.T) { L.PushGoStruct(z) L.SetGlobal("z") - /* This code demonstrates checking that a value on the stack is a go object */ + // This code demonstrates checking that a value on the stack is a go object L.CheckStack(1) L.GetGlobal("z") if !L.IsGoStruct(-1) { @@ -296,7 +296,7 @@ func TestLikeUserdata(t *testing.T) { } L.Pop(1) - /* This code demonstrates access and assignment to a field of a go object */ + // This code demonstrates access and assignment to a field of a go object if err := L.DoString("return z.AField"); err != nil { t.Fatal("Couldn't execute code") } @@ -326,3 +326,24 @@ func TestLikeUserdata(t *testing.T) { goDefinedFunctions(L) goDefinedObjects(L) } + +func TestStackTrace(t *testing.T) { + L := NewState() + defer L.Close() + L.OpenLibs() + + err := L.DoFile("../example/calls.lua") + if err == nil { + t.Fatal("No error returned from the execution of calls.lua") + } + + le := err.(*LuaError) + + if le.Code() != LUA_ERRERR { + t.Fatalf("Wrong kind of error encountered running calls.lua: %v (%d %d)\n", le, le.Code(), LUA_ERRERR) + } + + if len(le.StackTrace()) != 6 { + t.Fatalf("Wrong size of stack trace (%v)\n", le.StackTrace()) + } +} From aaa092a6d846823c3d8263e48243ce909f1bea8c Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sat, 4 May 2013 13:55:23 +0200 Subject: [PATCH 038/100] Clarification about using the llua build tag on linux --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 98637af6..0aec0b6f 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,11 @@ Simplest way to install: # go get -u github.com/aarzilli/golua/lua -Will work as long as your compiler can find a shared object called lua5.1 on linux, or lua anywhere else (use the build tag llua if you have linux but your lua isn't called "lua5.1"). +Will work as long as your compiler can find a shared object called lua5.1 on linux, or lua anywhere else. +If your linux system uses "lua" as the shared object name for lua (for example, Fedora Core does this) you can install using: + + # go get -u -tags llua github.com/aarzilli/golua/lua + You can then try to run the examples: From d81fa4ec21a8c242b204e2552a0be6a9b5a4a238 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 17 Jun 2013 14:50:15 +0200 Subject: [PATCH 039/100] Exposing method to create LuaError objects (fixes Issue 7) --- lua/lua.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lua/lua.go b/lua/lua.go index 68eb53fc..54fa58db 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -21,6 +21,8 @@ package lua import "C" import "unsafe" +import "fmt" + type LuaStackEntry struct { Name string Source string @@ -629,3 +631,16 @@ func (L *State) StackTrace() []LuaStackEntry { return r } + +func (L *State) RaiseError(msg string) { + st := L.StackTrace() + prefix := "" + if len(st) >= 1 { + prefix = fmt.Sprintf("%s:%d: ", st[1].ShortSource, st[1].CurrentLine) + } + panic(&LuaError{ 0, prefix + msg, st }) +} + +func (L *State) NewError(msg string) *LuaError { + return &LuaError{ 0, msg, L.StackTrace() } +} From 6836c92f77d928ddcf9db84f30bb802513d1c8a9 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Tue, 6 Aug 2013 14:16:32 +0200 Subject: [PATCH 040/100] replaced example allocator in example/alloc.go with one that isn't broken --- example/alloc.go | 22 ++++++++++++++-------- lua/c-golua.c | 11 ++++++++++- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/example/alloc.go b/example/alloc.go index c8719780..41731604 100644 --- a/example/alloc.go +++ b/example/alloc.go @@ -4,7 +4,7 @@ import "../lua" import "unsafe" import "fmt" -var refHolder [][]byte; +var refHolder = map[unsafe.Pointer][]byte{} //a terrible allocator! @@ -12,15 +12,21 @@ var refHolder [][]byte; //not usable as an actual implementation func AllocatorF(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { if(nsize == 0) { - //TODO: remove from reference holder + if _, ok := refHolder[ptr]; ok { + delete(refHolder, ptr) + } + ptr = unsafe.Pointer(nil) } else if(osize != nsize) { - //TODO: remove old ptr from list if its in there slice := make([]byte,nsize); + + if oldslice, ok := refHolder[ptr]; ok { + copy(slice, oldslice) + _ = oldslice + delete(refHolder, ptr) + } + ptr = unsafe.Pointer(&(slice[0])); - //TODO: add slice to holder - l := len(refHolder); - refHolder = refHolder[0:l+1]; - refHolder[l] = slice; + refHolder[ptr] = slice } //fmt.Println("in allocf"); return ptr; @@ -33,7 +39,7 @@ func A2(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { func main() { - refHolder = make([][]byte,0,500); + //refHolder = make([][]byte,0,500); L := lua.NewStateAlloc(AllocatorF); defer L.Close() diff --git a/lua/c-golua.c b/lua/c-golua.c index ca5bdf4a..a08c510d 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "_cgo_export.h" #define MT_GOFUNCTION "GoLua.GoFunction" @@ -127,15 +128,23 @@ void clua_pushgostruct(lua_State* L, unsigned int iid) lua_setmetatable(L,-2); } +int default_panicf(lua_State *L) +{ + const char *s = lua_tostring(L, -1); + printf("Lua unprotected panic: %s\n", s); + abort(); +} + void clua_setgostate(lua_State* L, GoInterface gi) { + lua_atpanic(L, default_panicf); lua_pushlightuserdata(L,(void*)&GoStateRegistryKey); GoInterface* gip = (GoInterface*)lua_newuserdata(L,sizeof(GoInterface)); //copy interface value to userdata gip->v = gi.v; gip->t = gi.t; //set into registry table - lua_settable(L,LUA_REGISTRYINDEX); + lua_settable(L, LUA_REGISTRYINDEX); } /* called when lua code attempts to access a field of a published go object */ From 82d28bfc6bd54af7782ace90dd6eab34a7f9b1f6 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 23 Aug 2013 19:39:16 +0200 Subject: [PATCH 041/100] changed PushString and ToString to work correctly when their argument contains NUL bytes --- lua/golua.go | 2 +- lua/lua.go | 24 ++++++++++++------------ lua/lua_defs.go | 23 ++++++++++++++--------- lua/lua_test.go | 31 +++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 22 deletions(-) diff --git a/lua/golua.go b/lua/golua.go index c9ad1c39..fb5dece4 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -57,7 +57,7 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr fval = fval.Elem() } - luatype := C.lua_type(L.s, 3) + luatype := LuaValType(C.lua_type(L.s, 3)) switch fval.Kind() { case reflect.Bool: diff --git a/lua/lua.go b/lua/lua.go index 54fa58db..3704e137 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -267,7 +267,7 @@ func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } // Returns true if lua_type == LUA_TBOOLEAN func (L *State) IsBoolean(index int) bool { - return int(C.lua_type(L.s, C.int(index))) == LUA_TBOOLEAN + return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TBOOLEAN } // Returns true if the value at index is a LuaGoFunction @@ -282,19 +282,19 @@ func (L *State) IsGoStruct(index int) bool { // Returns true if the value at index is user data pushed with PushGoFunction func (L *State) IsFunction(index int) bool { - return int(C.lua_type(L.s, C.int(index))) == LUA_TFUNCTION + return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TFUNCTION } // Returns true if the value at index is light user data func (L *State) IsLightUserdata(index int) bool { - return int(C.lua_type(L.s, C.int(index))) == LUA_TLIGHTUSERDATA + return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TLIGHTUSERDATA } // lua_isnil -func (L *State) IsNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNIL } +func (L *State) IsNil(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNIL } // lua_isnone -func (L *State) IsNone(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TNONE } +func (L *State) IsNone(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNONE } // lua_isnoneornil func (L *State) IsNoneOrNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) <= 0 } @@ -306,11 +306,11 @@ func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(inde func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } // lua_istable -func (L *State) IsTable(index int) bool { return int(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } +func (L *State) IsTable(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } // lua_isthread func (L *State) IsThread(index int) bool { - return int(C.lua_type(L.s, C.int(index))) == LUA_TTHREAD + return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTHREAD } // lua_isuserdata @@ -373,7 +373,7 @@ func (L *State) PushBoolean(b bool) { func (L *State) PushString(str string) { Cstr := C.CString(str) defer C.free(unsafe.Pointer(Cstr)) - C.lua_pushstring(L.s, Cstr) + C.lua_pushlstring(L.s, Cstr, C.size_t(len(str))) } // lua_pushinteger @@ -515,8 +515,8 @@ func (L *State) ToGoStruct(index int) (f interface{}) { // lua_tostring func (L *State) ToString(index int) string { var size C.size_t - //C.GoString(C.lua_tolstring(L.s, C.int(index), &size)); - return C.GoString(C.lua_tolstring(L.s, C.int(index), &size)) + r := C.lua_tolstring(L.s, C.int(index), &size) + return C.GoStringN(r, C.int(size)) } // lua_tointeger @@ -546,8 +546,8 @@ func (L *State) ToUserdata(index int) unsafe.Pointer { } // lua_type -func (L *State) Type(index int) int { - return int(C.lua_type(L.s, C.int(index))) +func (L *State) Type(index int) LuaValType { + return LuaValType(C.lua_type(L.s, C.int(index))) } // lua_typename diff --git a/lua/lua_defs.go b/lua/lua_defs.go index 2ad9b68a..3c438a5c 100644 --- a/lua/lua_defs.go +++ b/lua/lua_defs.go @@ -8,6 +8,20 @@ package lua */ import "C" +type LuaValType int + +const ( + LUA_TNIL = LuaValType(C.LUA_TNIL) + LUA_TNUMBER = LuaValType(C.LUA_TNUMBER) + LUA_TBOOLEAN = LuaValType(C.LUA_TBOOLEAN) + LUA_TSTRING = LuaValType(C.LUA_TSTRING) + LUA_TTABLE = LuaValType(C.LUA_TTABLE) + LUA_TFUNCTION = LuaValType(C.LUA_TFUNCTION) + LUA_TUSERDATA = LuaValType(C.LUA_TUSERDATA) + LUA_TTHREAD = LuaValType(C.LUA_TTHREAD) + LUA_TLIGHTUSERDATA = LuaValType(C.LUA_TLIGHTUSERDATA) +) + const ( LUA_VERSION = C.LUA_VERSION LUA_RELEASE = C.LUA_RELEASE @@ -24,15 +38,6 @@ const ( LUA_ERRMEM = C.LUA_ERRMEM LUA_ERRERR = C.LUA_ERRERR LUA_TNONE = C.LUA_TNONE - LUA_TNIL = C.LUA_TNIL - LUA_TBOOLEAN = C.LUA_TBOOLEAN - LUA_TLIGHTUSERDATA = C.LUA_TLIGHTUSERDATA - LUA_TNUMBER = C.LUA_TNUMBER - LUA_TSTRING = C.LUA_TSTRING - LUA_TTABLE = C.LUA_TTABLE - LUA_TFUNCTION = C.LUA_TFUNCTION - LUA_TUSERDATA = C.LUA_TUSERDATA - LUA_TTHREAD = C.LUA_TTHREAD LUA_MINSTACK = C.LUA_MINSTACK LUA_GCSTOP = C.LUA_GCSTOP LUA_GCRESTART = C.LUA_GCRESTART diff --git a/lua/lua_test.go b/lua/lua_test.go index 4a62b054..9106b2d3 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -347,3 +347,34 @@ func TestStackTrace(t *testing.T) { t.Fatalf("Wrong size of stack trace (%v)\n", le.StackTrace()) } } + +func TestConv(t *testing.T) { + L := NewState() + defer L.Close() + L.OpenLibs() + + L.PushString("10") + n := L.ToNumber(-1) + if n != 10 { + t.Fatalf("Wrong conversion (str -> int)") + } + if L.Type(-1) != LUA_TSTRING { + t.Fatalf("Wrong type (str)") + } + + L.Pop(1) + + L.PushInteger(10) + s := L.ToString(-1) + if s != "10" { + t.Fatalf("Wrong conversion (int -> str)") + } + + L.Pop(1) + + L.PushString("a\000test") + s = L.ToString(-1) + if s != "a\000test" { + t.Fatalf("Wrong conversion (str -> str): <%s>", s) + } +} From aaa0b86e11b6594e0af1d2efeec49c3a8836fffe Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 23 Aug 2013 19:43:48 +0200 Subject: [PATCH 042/100] better formatting for contributors list + new contributor --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0aec0b6f..c78c86da 100644 --- a/README.md +++ b/README.md @@ -100,13 +100,14 @@ ON THREADS AND COROUTINES CONTRIBUTORS --------------------- -Adam Fitzgerald (original author) -Alessandro Arzilli -Steve Donovan -Harley Laue -James Nurmi -Ruitao -Xushiwei +* Adam Fitzgerald (original author) +* Alessandro Arzilli +* Steve Donovan +* Harley Laue +* James Nurmi +* Ruitao +* Xushiwei +* Isaint SEE ALSO --------------------- From 01ee1fee29901909e73ca2bec07dd5c0a4b5cd6c Mon Sep 17 00:00:00 2001 From: hirochachacha Date: Fri, 30 Aug 2013 19:27:33 +0900 Subject: [PATCH 043/100] fix README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c78c86da..d6011996 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,11 @@ ON ERROR HANDLING Lua's exceptions are incompatible with Go, golua works around this incompatibility by setting up protected execution environments in `lua.State.DoString`, `lua.State.DoFile` and lua.State.Call and turning every exception into a Go panic. This means that: + 1. In general you can't do any exception handling from Lua, `pcall` and `xpcall` are renamed to `unsafe_pcall` and `unsafe_xpcall`. They are only safe to be called from Lua code that never calls back to Go. Use at your own risk. + 2. The call to lua.State.Error, present in previous versions of this library, has been removed as it is nonsensical + 3. Method calls on a newly created `lua.State` happen in an unprotected environment, if Lua throws an exception as a result your program will be terminated. If this is undesirable perform your initialization like this: ```go From fc1ef177ce263ab6238257c591a9917991ba6bd6 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 18 Sep 2013 10:31:38 +0200 Subject: [PATCH 044/100] pointer to lua 5.2 support --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index c78c86da..7153f418 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,11 @@ ON THREADS AND COROUTINES 'lua.State' is not thread safe, but the library itself is. Lua's coroutines exist but (to my knowledge) have never been tested and are likely to encounter the same problems that errors have, use at your own peril. +LUA 5.2 SUPPORT +--------------------- + +Support for lua 5.2 is in the lua5.2 branch, this branch only supports lua5.1. + CONTRIBUTORS --------------------- From d2aab3166b5ea1bd306d0a7e5b6204f69a7463ed Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 20 Dec 2013 09:32:22 +0100 Subject: [PATCH 045/100] target to link with liblua.a --- lua/lua.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lua/lua.go b/lua/lua.go index 3704e137..22e498ff 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -8,9 +8,10 @@ package lua /* #cgo CFLAGS: -Ilua #cgo llua LDFLAGS: -llua -#cgo linux,!llua LDFLAGS: -llua5.1 -#cgo darwin LDFLAGS: -llua -#cgo freebsd LDFLAGS: -llua +#cgo luaa LDFLAGS: -llua -lm -ldl +#cgo linux,!llua,!luaa LDFLAGS: -llua5.1 +#cgo darwin,!luaa LDFLAGS: -llua +#cgo freebsd,!luaa LDFLAGS: -llua #include #include From fb28da3802a72545ff5c17392548c5fb0637e935 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 20 Dec 2013 16:17:58 +0100 Subject: [PATCH 046/100] Added note for liblua.a in README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 371213f4..5b063f8c 100644 --- a/README.md +++ b/README.md @@ -100,10 +100,11 @@ ON THREADS AND COROUTINES 'lua.State' is not thread safe, but the library itself is. Lua's coroutines exist but (to my knowledge) have never been tested and are likely to encounter the same problems that errors have, use at your own peril. -LUA 5.2 SUPPORT +ODDS AND ENDS --------------------- -Support for lua 5.2 is in the lua5.2 branch, this branch only supports lua5.1. +* Support for lua 5.2 is in the lua5.2 branch, this branch only supports lua5.1. +* Compiling from source yields only a static link library (liblua.a), you can either produce the dynamic link library on your own or use the `luaa` build tag. CONTRIBUTORS --------------------- @@ -116,6 +117,7 @@ CONTRIBUTORS * Ruitao * Xushiwei * Isaint +* hsinhoyeh SEE ALSO --------------------- From 1c344269a2a8202c1d57d2f52e406fb08e615159 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 17 Jan 2014 08:31:09 +0100 Subject: [PATCH 047/100] fix issue #22 --- lua/c-golua.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index a08c510d..bd47c678 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -90,13 +90,13 @@ int gchook_wrapper(lua_State* L) unsigned int clua_togofunction(lua_State* L, int index) { - int *r = clua_checkgosomething(L, index, MT_GOFUNCTION); + unsigned int *r = clua_checkgosomething(L, index, MT_GOFUNCTION); return (r != NULL) ? *r : -1; } unsigned int clua_togostruct(lua_State *L, int index) { - int *r = clua_checkgosomething(L, index, MT_GOINTERFACE); + unsigned int *r = clua_checkgosomething(L, index, MT_GOINTERFACE); return (r != NULL) ? *r : -1; } @@ -215,6 +215,7 @@ int panic_msghandler(lua_State *L) { GoInterface* gi = clua_getgostate(L); go_panic_msghandler(*gi, (char *)lua_tolstring(L, -1, NULL)); + return 0; } void clua_hide_pcall(lua_State *L) From 5c5d9af6c14c7be1752085c58718fae93b460d26 Mon Sep 17 00:00:00 2001 From: Viktor Palmkvist Date: Wed, 20 Aug 2014 13:06:43 +0200 Subject: [PATCH 048/100] Fix #26 Changes the type of the second argument to CheckType to be the more correct LuaValType, for consistency with the rest of the library. --- lua/lauxlib.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 4d8b7e8e..e444d21d 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -79,7 +79,7 @@ func (L *State) CheckOption(narg int, def string, lst []string) int { } // luaL_checktype -func (L *State) CheckType(narg int, t int) { +func (L *State) CheckType(narg int, t LuaValType) { C.luaL_checktype(L.s, C.int(narg), C.int(t)) } From baea951c38c89e5bf7c2a101e56315a3afcfce9e Mon Sep 17 00:00:00 2001 From: aarzilli Date: Wed, 20 Aug 2014 17:38:57 +0200 Subject: [PATCH 049/100] Added contributor for Fix #27 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5b063f8c..b99336d5 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ CONTRIBUTORS * Xushiwei * Isaint * hsinhoyeh +* Viktor Palmkvist SEE ALSO --------------------- From 3bbbc0cbc3b625690631053bf4d60d0b76951f84 Mon Sep 17 00:00:00 2001 From: hongzhen Date: Tue, 2 Dec 2014 03:23:47 +0800 Subject: [PATCH 050/100] Fix build ldflags for freebsd --- lua/lua.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lua.go b/lua/lua.go index 22e498ff..eb452944 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -11,7 +11,7 @@ package lua #cgo luaa LDFLAGS: -llua -lm -ldl #cgo linux,!llua,!luaa LDFLAGS: -llua5.1 #cgo darwin,!luaa LDFLAGS: -llua -#cgo freebsd,!luaa LDFLAGS: -llua +#cgo freebsd,!luaa LDFLAGS: -llua-5.1 #include #include From 8db26f9e99168070a0fd50c28cc4324bb8d3cb7a Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Tue, 9 Dec 2014 15:13:44 +0100 Subject: [PATCH 051/100] Added hongzhen to contributors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b99336d5..d28c4a56 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ CONTRIBUTORS * Isaint * hsinhoyeh * Viktor Palmkvist +* HongZhen Peng SEE ALSO --------------------- From 3f64d28312a8880f42d4e95a7fbdd5481a8b4956 Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Wed, 17 Jun 2015 15:18:35 +0800 Subject: [PATCH 052/100] link with luajit --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index d28c4a56..ec6c71ea 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,17 @@ ODDS AND ENDS * Support for lua 5.2 is in the lua5.2 branch, this branch only supports lua5.1. * Compiling from source yields only a static link library (liblua.a), you can either produce the dynamic link library on your own or use the `luaa` build tag. +LUAJIT +--------------------- + +To link with [luajit-2.0.x](http://luajit.org/luajit.html), you can use CGO_CFLAGS and CGO_LDFLAGS environment variables + +``` +$ CGO_CFLAGS=`pkg-config luajit --cflags` +$ CGO_LDFLAGS=`pkg-config luajit --libs` +$ go get -f -u github.com/aarzilli/golua/lua +``` + CONTRIBUTORS --------------------- From e56d4f2ca0f7046b63244a7153c0c3b0d2328cf0 Mon Sep 17 00:00:00 2001 From: admin36 Date: Wed, 29 Jul 2015 19:59:34 -0400 Subject: [PATCH 053/100] Add lua.PushGoClosure() method - fixes issue aarzilli/golua#36 --- README.md | 1 + lua/lua.go | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/README.md b/README.md index ec6c71ea..66d22430 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ CONTRIBUTORS * hsinhoyeh * Viktor Palmkvist * HongZhen Peng +* Admin36 SEE ALSO --------------------- diff --git a/lua/lua.go b/lua/lua.go index eb452944..ac05a004 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -104,6 +104,14 @@ func (L *State) PushGoFunction(f LuaGoFunction) { C.clua_pushgofunction(L.s, C.uint(fid)) } +// PushGoClosure pushes a lua.LuaGoFunction to the stack wrapped in a Closure. +// this permits the go function to reflect lua type 'function' when checking with type() +// this implements behaviour akin to lua_pushcfunction() in lua C API. +func (L *State) PushGoClosure(f LuaGoFunction) { + L.PushGoFunction(f) // leaves Go function userdata on stack + C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function +} + // Sets a metamethod to execute a go function // // The code: From fa753832e7c66fbb824291fa6f112bba656abf4e Mon Sep 17 00:00:00 2001 From: Gabriel Cziprusz Date: Tue, 29 Sep 2015 12:36:22 -0500 Subject: [PATCH 054/100] update build flags for osx --- lua/lua.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/lua.go b/lua/lua.go index ac05a004..f171d152 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -6,11 +6,12 @@ package lua /* +#cgo pkg-config: lua5.1 #cgo CFLAGS: -Ilua #cgo llua LDFLAGS: -llua #cgo luaa LDFLAGS: -llua -lm -ldl #cgo linux,!llua,!luaa LDFLAGS: -llua5.1 -#cgo darwin,!luaa LDFLAGS: -llua +#cgo darwin,!luaa pkg-config: lua5.1 #cgo freebsd,!luaa LDFLAGS: -llua-5.1 #include From b30b2c62c6712c6683a9d22ff0abfa54c8267863 Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Mon, 30 Nov 2015 11:17:47 +1100 Subject: [PATCH 055/100] luaL_argcheck: Raise an error when condition is _not_ true See http://www.lua.org/manual/5.1/manual.html#luaL_argcheck. --- lua/lauxlib.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/lauxlib.go b/lua/lauxlib.go index e444d21d..fef39b01 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -28,7 +28,7 @@ func (err *LuaError) StackTrace() []LuaStackEntry { // luaL_argcheck func (L *State) ArgCheck(cond bool, narg int, extramsg string) { - if cond { + if !cond { Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) C.luaL_argerror(L.s, C.int(narg), Cextramsg) From fb8ef8637bcfec77aa44150b9272a728870e9c13 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Tue, 1 Dec 2015 08:49:36 +0100 Subject: [PATCH 056/100] Insured that code that uses the old version of ArgCheck does not compile Added Pierre Neidhardt to contributors --- README.md | 1 + lua/lauxlib.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 66d22430..10dd87de 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,7 @@ CONTRIBUTORS * Viktor Palmkvist * HongZhen Peng * Admin36 +* Pierre Neidhardt (@Ambrevar) SEE ALSO --------------------- diff --git a/lua/lauxlib.go b/lua/lauxlib.go index fef39b01..d2c5cd02 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -27,7 +27,8 @@ func (err *LuaError) StackTrace() []LuaStackEntry { } // luaL_argcheck -func (L *State) ArgCheck(cond bool, narg int, extramsg string) { +// WARNING: before b30b2c62c6712c6683a9d22ff0abfa54c8267863 the function ArgCheck had the opposite behaviour +func (L *State) Argcheck(cond bool, narg int, extramsg string) { if !cond { Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) From 1074bd50a84be62f322d7b2cf8109e1f1801bfeb Mon Sep 17 00:00:00 2001 From: aarzilli Date: Thu, 24 Dec 2015 09:52:58 +0100 Subject: [PATCH 057/100] Go 1.6 beta 1 compatibility Note: each new state leaks 4 bytes. Closes #41 --- lua/c-golua.c | 42 +++++++++++++++++++-------------------- lua/golua.go | 54 +++++++++++++++++++++++++++++++++++++++------------ lua/golua.h | 2 +- lua/lua.go | 12 +++++------- 4 files changed, 68 insertions(+), 42 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index bd47c678..7ca79d51 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -55,14 +55,15 @@ unsigned int* clua_checkgosomething(lua_State* L, int index, const char *desired } } -GoInterface* clua_getgostate(lua_State* L) +int clua_getgostate(lua_State* L) { + int gostateindex; //get gostate from registry entry lua_pushlightuserdata(L,(void*)&GoStateRegistryKey); lua_gettable(L, LUA_REGISTRYINDEX); - GoInterface* gip = lua_touserdata(L,-1); + gostateindex = lua_tointeger(L,-1); lua_pop(L,1); - return gip; + return gostateindex; } @@ -71,10 +72,10 @@ int callback_function(lua_State* L) { int r; unsigned int *fid = clua_checkgosomething(L, 1, MT_GOFUNCTION); - GoInterface* gi = clua_getgostate(L); + int gostateindex = clua_getgostate(L); //remove the go function from the stack (to present same behavior as lua_CFunctions) lua_remove(L,1); - return golua_callgofunction(*gi, fid!=NULL ? *fid : -1); + return golua_callgofunction(gostateindex, fid!=NULL ? *fid : -1); } //wrapper for gchook @@ -82,9 +83,9 @@ int gchook_wrapper(lua_State* L) { //printf("Garbage collection wrapper\n"); unsigned int* fid = clua_checkgosomething(L, -1, NULL); - GoInterface* gi = clua_getgostate(L); + int gostateindex = clua_getgostate(L); if (fid != NULL) - return golua_gchook(*gi,*fid); + return golua_gchook(gostateindex,*fid); return 0; } @@ -111,8 +112,8 @@ void clua_pushgofunction(lua_State* L, unsigned int fid) static int callback_c (lua_State* L) { int fid = clua_togofunction(L,lua_upvalueindex(1)); - GoInterface *gi = clua_getgostate(L); - return golua_callgofunction(*gi,fid); + int gostateindex = clua_getgostate(L); + return golua_callgofunction(gostateindex,fid); } void clua_pushcallback(lua_State* L) @@ -135,14 +136,11 @@ int default_panicf(lua_State *L) abort(); } -void clua_setgostate(lua_State* L, GoInterface gi) +void clua_setgostate(lua_State* L, int gostateindex) { lua_atpanic(L, default_panicf); lua_pushlightuserdata(L,(void*)&GoStateRegistryKey); - GoInterface* gip = (GoInterface*)lua_newuserdata(L,sizeof(GoInterface)); - //copy interface value to userdata - gip->v = gi.v; - gip->t = gi.t; + lua_pushinteger(L, gostateindex); //set into registry table lua_settable(L, LUA_REGISTRYINDEX); } @@ -164,9 +162,9 @@ int interface_index_callback(lua_State *L) return 1; } - GoInterface* gi = clua_getgostate(L); + int gostateindex = clua_getgostate(L); - int r = golua_interface_index_callback(*gi, *iid, field_name); + int r = golua_interface_index_callback(gostateindex, *iid, field_name); if (r < 0) { @@ -196,9 +194,9 @@ int interface_newindex_callback(lua_State *L) return 1; } - GoInterface* gi = clua_getgostate(L); + int gostateindex = clua_getgostate(L); - int r = golua_interface_newindex_callback(*gi, *iid, field_name); + int r = golua_interface_newindex_callback(gostateindex, *iid, field_name); if (r < 0) { @@ -213,8 +211,8 @@ int interface_newindex_callback(lua_State *L) int panic_msghandler(lua_State *L) { - GoInterface* gi = clua_getgostate(L); - go_panic_msghandler(*gi, (char *)lua_tolstring(L, -1, NULL)); + int gostateindex = clua_getgostate(L); + go_panic_msghandler(gostateindex, (char *)lua_tolstring(L, -1, NULL)); return 0; } @@ -275,8 +273,8 @@ int callback_panicf(lua_State* L) lua_gettable(L,LUA_REGISTRYINDEX); unsigned int fid = lua_tointeger(L,-1); lua_pop(L,1); - GoInterface* gi = clua_getgostate(L); - return golua_callpanicfunction(*gi,fid); + int gostateindex = clua_getgostate(L); + return golua_callpanicfunction(gostateindex,fid); } diff --git a/lua/golua.go b/lua/golua.go index fb5dece4..c79cc117 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -11,6 +11,7 @@ import "C" import ( "reflect" + "sync" "unsafe" ) @@ -26,6 +27,9 @@ type State struct { // Wrapped lua_State object s *C.lua_State + // index of this object inside the goStates array + Index int + // Registry of go object that have been pushed to Lua VM registry []interface{} @@ -33,9 +37,35 @@ type State struct { freeIndices []uint } +var goStates []*State +var goStatesMutex sync.Mutex + +func init() { + goStates = make([]*State, 0, 16) +} + +func registerGoState(L *State) { + goStatesMutex.Lock() + defer goStatesMutex.Unlock() + L.Index = len(goStates) + goStates = append(goStates, L) +} + +func unregisterGoState(L *State) { + goStatesMutex.Lock() + defer goStatesMutex.Unlock() + goStates[L.Index] = nil +} + +func getGoState(gostateindex int) *State { + goStatesMutex.Lock() + defer goStatesMutex.Unlock() + return goStates[gostateindex] +} + //export golua_callgofunction -func golua_callgofunction(L interface{}, fid uint) int { - L1 := L.(*State) +func golua_callgofunction(gostateindex int, fid uint) int { + L1 := getGoState(gostateindex) if fid < 0 { panic(&LuaError{0, "Requested execution of an unknown function", L1.StackTrace()}) } @@ -44,8 +74,8 @@ func golua_callgofunction(L interface{}, fid uint) int { } //export golua_interface_newindex_callback -func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr *C.char) int { - L := Li.(*State) +func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cstr *C.char) int { + L := getGoState(gostateindex) iface := L.registry[iid] ifacevalue := reflect.ValueOf(iface).Elem() @@ -129,8 +159,8 @@ func golua_interface_newindex_callback(Li interface{}, iid uint, field_name_cstr } //export golua_interface_index_callback -func golua_interface_index_callback(Li interface{}, iid uint, field_name *C.char) int { - L := Li.(*State) +func golua_interface_index_callback(gostateindex int, iid uint, field_name *C.char) int { + L := getGoState(gostateindex) iface := L.registry[iid] ifacevalue := reflect.ValueOf(iface).Elem() @@ -185,15 +215,15 @@ func golua_interface_index_callback(Li interface{}, iid uint, field_name *C.char } //export golua_gchook -func golua_gchook(L interface{}, id uint) int { - L1 := L.(*State) +func golua_gchook(gostateindex int, id uint) int { + L1 := getGoState(gostateindex) L1.unregister(id) return 0 } //export golua_callpanicfunction -func golua_callpanicfunction(L interface{}, id uint) int { - L1 := L.(*State) +func golua_callpanicfunction(gostateindex int, id uint) int { + L1 := getGoState(gostateindex) f := L1.registry[id].(LuaGoFunction) return f(L1) } @@ -214,8 +244,8 @@ func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { } //export go_panic_msghandler -func go_panic_msghandler(Li interface{}, z *C.char) { - L := Li.(*State) +func go_panic_msghandler(gostateindex int, z *C.char) { + L := getGoState(gostateindex) s := C.GoString(z) panic(&LuaError{LUA_ERRERR, s, L.StackTrace()}) diff --git a/lua/golua.h b/lua/golua.h index 5f8e8125..e6f66a37 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -13,7 +13,7 @@ unsigned int clua_togostruct(lua_State *L, int index); void clua_pushcallback(lua_State* L); void clua_pushgofunction(lua_State* L, unsigned int fid); void clua_pushgostruct(lua_State *L, unsigned int fid); -void clua_setgostate(lua_State* L, GoInterface gostate); +void clua_setgostate(lua_State* L, int gostateindex); GoInterface* clua_getgostate(lua_State* L); GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id); int clua_callluacfunc(lua_State* L, lua_CFunction f); diff --git a/lua/lua.go b/lua/lua.go index f171d152..3b48b1ea 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -33,12 +33,9 @@ type LuaStackEntry struct { } func newState(L *C.lua_State) *State { - var newstatei interface{} - newstate := &State{L, make([]interface{}, 0, 8), make([]uint, 0, 8)} - newstatei = newstate - ns1 := unsafe.Pointer(&newstatei) - ns2 := (*C.GoInterface)(ns1) - C.clua_setgostate(L, *ns2) //hacky.... + newstate := &State{L, -1, make([]interface{}, 0, 8), make([]uint, 0, 8)} + registerGoState(newstate) + C.clua_setgostate(L, C.int(newstate.Index)) C.clua_initstate(L) return newstate } @@ -228,6 +225,7 @@ func (L *State) CheckStack(extra int) bool { // lua_close func (L *State) Close() { C.lua_close(L.s) + unregisterGoState(L) } // lua_concat @@ -348,7 +346,7 @@ func (L *State) NewThread() *State { //TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) - return &State{s, nil, nil} + return &State{s, -1, nil, nil} } // lua_next From c15567389b0759638405cfe9f34ca306705ef28d Mon Sep 17 00:00:00 2001 From: aarzilli Date: Thu, 24 Dec 2015 09:53:31 +0100 Subject: [PATCH 058/100] go fmt --- lua/golua.go | 14 +++---- lua/lauxlib.go | 7 ++-- lua/lua.go | 44 ++++++++++++-------- lua/lua_defs.go | 106 ++++++++++++++++++++++++------------------------ lua/lua_test.go | 46 +++++++++++---------- 5 files changed, 115 insertions(+), 102 deletions(-) diff --git a/lua/golua.go b/lua/golua.go index c79cc117..4580dde7 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -95,7 +95,7 @@ func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cs fval.SetBool(int(C.lua_toboolean(L.s, 3)) != 0) return 1 } else { - L.PushString("Wrong assignment to field "+field_name) + L.PushString("Wrong assignment to field " + field_name) return -1 } @@ -112,7 +112,7 @@ func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cs fval.SetInt(int64(C.lua_tointeger(L.s, 3))) return 1 } else { - L.PushString("Wrong assignment to field "+field_name) + L.PushString("Wrong assignment to field " + field_name) return -1 } @@ -129,7 +129,7 @@ func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cs fval.SetUint(uint64(C.lua_tointeger(L.s, 3))) return 1 } else { - L.PushString("Wrong assignment to field "+field_name) + L.PushString("Wrong assignment to field " + field_name) return -1 } @@ -138,7 +138,7 @@ func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cs fval.SetString(C.GoString(C.lua_tolstring(L.s, 3, nil))) return 1 } else { - L.PushString("Wrong assignment to field "+field_name) + L.PushString("Wrong assignment to field " + field_name) return -1 } @@ -149,12 +149,12 @@ func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cs fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) return 1 } else { - L.PushString("Wrong assignment to field "+field_name) + L.PushString("Wrong assignment to field " + field_name) return -1 } } - L.PushString("Unsupported type of field "+field_name+": "+fval.Type().String()) + L.PushString("Unsupported type of field " + field_name + ": " + fval.Type().String()) return -1 } @@ -210,7 +210,7 @@ func golua_interface_index_callback(gostateindex int, iid uint, field_name *C.ch return 1 } - L.PushString("Unsupported type of field: "+fval.Type().String()) + L.PushString("Unsupported type of field: " + fval.Type().String()) return -1 } diff --git a/lua/lauxlib.go b/lua/lauxlib.go index d2c5cd02..0ba5984d 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -9,8 +9,8 @@ import "C" import "unsafe" type LuaError struct { - code int - message string + code int + message string stackTrace []LuaStackEntry } @@ -96,7 +96,7 @@ func (L *State) DoFile(filename string) error { if r := L.LoadFile(filename); r != 0 { return &LuaError{r, L.ToString(-1), L.StackTrace()} } - return L.Call(0, LUA_MULTRET); + return L.Call(0, LUA_MULTRET) } // Executes the string, returns nil for no errors or the lua error string on failure @@ -213,4 +213,3 @@ func (L *State) Unref(t int, ref int) { func (L *State) Where(lvl int) { C.luaL_where(L.s, C.int(lvl)) } - diff --git a/lua/lua.go b/lua/lua.go index 3b48b1ea..ed27e591 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -26,8 +26,8 @@ import "unsafe" import "fmt" type LuaStackEntry struct { - Name string - Source string + Name string + Source string ShortSource string CurrentLine int } @@ -57,9 +57,9 @@ func (L *State) getFreeIndex() (index uint, ok bool) { freelen := len(L.freeIndices) //if there exist entries in the freelist if freelen > 0 { - i := L.freeIndices[freelen-1] //get index + i := L.freeIndices[freelen-1] //get index //fmt.Printf("Free indices before: %v\n", L.freeIndices) - L.freeIndices = L.freeIndices[0:freelen-1] //'pop' index from list + L.freeIndices = L.freeIndices[0 : freelen-1] //'pop' index from list //fmt.Printf("Free indices after: %v\n", L.freeIndices) return i, true } @@ -106,7 +106,7 @@ func (L *State) PushGoFunction(f LuaGoFunction) { // this permits the go function to reflect lua type 'function' when checking with type() // this implements behaviour akin to lua_pushcfunction() in lua C API. func (L *State) PushGoClosure(f LuaGoFunction) { - L.PushGoFunction(f) // leaves Go function userdata on stack + L.PushGoFunction(f) // leaves Go function userdata on stack C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function } @@ -125,7 +125,7 @@ func (L *State) PushGoClosure(f LuaGoFunction) { // // except this wouldn't work because pushing a go function results in user data not a cfunction func (L *State) SetMetaMethod(methodName string, f LuaGoFunction) { - L.PushGoFunction(f) // leaves Go function userdata on stack + L.PushGoFunction(f) // leaves Go function userdata on stack C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function L.SetField(-2, methodName) } @@ -181,20 +181,20 @@ func (L *State) pcall(nargs, nresults, errfunc int) int { } func (L *State) callEx(nargs, nresults int, catch bool) (err error) { - if (catch) { + if catch { defer func() { if err2 := recover(); err2 != nil { if _, ok := err2.(error); ok { err = err2.(error) } - return; + return } }() } L.GetGlobal(C.GOLUA_DEFAULT_MSGHANDLER) // We must record where we put the error handler in the stack otherwise it will be impossible to remove after the pcall when nresults == LUA_MULTRET - erridx := L.GetTop()-nargs-1 + erridx := L.GetTop() - nargs - 1 L.Insert(erridx) r := L.pcall(nargs, nresults, erridx) L.Remove(erridx) @@ -314,7 +314,9 @@ func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(inde func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } // lua_istable -func (L *State) IsTable(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } +func (L *State) IsTable(index int) bool { + return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTABLE +} // lua_isthread func (L *State) IsThread(index int) bool { @@ -506,17 +508,25 @@ func (L *State) ToBoolean(index int) bool { // Returns the value at index as a Go function (it must be something pushed with PushGoFunction) func (L *State) ToGoFunction(index int) (f LuaGoFunction) { - if !L.IsGoFunction(index) { return nil } + if !L.IsGoFunction(index) { + return nil + } fid := C.clua_togofunction(L.s, C.int(index)) - if fid < 0 { return nil } + if fid < 0 { + return nil + } return L.registry[fid].(LuaGoFunction) } // Returns the value at index as a Go Struct (it must be something pushed with PushGoStruct) func (L *State) ToGoStruct(index int) (f interface{}) { - if !L.IsGoStruct(index) { return nil } + if !L.IsGoStruct(index) { + return nil + } fid := C.clua_togostruct(L.s, C.int(index)) - if fid < 0 { return nil } + if fid < 0 { + return nil + } return L.registry[fid] } @@ -634,7 +644,7 @@ func (L *State) StackTrace() []LuaStackEntry { } ss := string(ssb) - r = append(r, LuaStackEntry{ C.GoString(d.name), C.GoString(d.source), ss, int(d.currentline) }) + r = append(r, LuaStackEntry{C.GoString(d.name), C.GoString(d.source), ss, int(d.currentline)}) } return r @@ -646,9 +656,9 @@ func (L *State) RaiseError(msg string) { if len(st) >= 1 { prefix = fmt.Sprintf("%s:%d: ", st[1].ShortSource, st[1].CurrentLine) } - panic(&LuaError{ 0, prefix + msg, st }) + panic(&LuaError{0, prefix + msg, st}) } func (L *State) NewError(msg string) *LuaError { - return &LuaError{ 0, msg, L.StackTrace() } + return &LuaError{0, msg, L.StackTrace()} } diff --git a/lua/lua_defs.go b/lua/lua_defs.go index 3c438a5c..008f1898 100644 --- a/lua/lua_defs.go +++ b/lua/lua_defs.go @@ -11,61 +11,61 @@ import "C" type LuaValType int const ( - LUA_TNIL = LuaValType(C.LUA_TNIL) - LUA_TNUMBER = LuaValType(C.LUA_TNUMBER) - LUA_TBOOLEAN = LuaValType(C.LUA_TBOOLEAN) - LUA_TSTRING = LuaValType(C.LUA_TSTRING) - LUA_TTABLE = LuaValType(C.LUA_TTABLE) - LUA_TFUNCTION = LuaValType(C.LUA_TFUNCTION) - LUA_TUSERDATA = LuaValType(C.LUA_TUSERDATA) - LUA_TTHREAD = LuaValType(C.LUA_TTHREAD) + LUA_TNIL = LuaValType(C.LUA_TNIL) + LUA_TNUMBER = LuaValType(C.LUA_TNUMBER) + LUA_TBOOLEAN = LuaValType(C.LUA_TBOOLEAN) + LUA_TSTRING = LuaValType(C.LUA_TSTRING) + LUA_TTABLE = LuaValType(C.LUA_TTABLE) + LUA_TFUNCTION = LuaValType(C.LUA_TFUNCTION) + LUA_TUSERDATA = LuaValType(C.LUA_TUSERDATA) + LUA_TTHREAD = LuaValType(C.LUA_TTHREAD) LUA_TLIGHTUSERDATA = LuaValType(C.LUA_TLIGHTUSERDATA) ) const ( - LUA_VERSION = C.LUA_VERSION - LUA_RELEASE = C.LUA_RELEASE - LUA_VERSION_NUM = C.LUA_VERSION_NUM - LUA_COPYRIGHT = C.LUA_COPYRIGHT - LUA_AUTHORS = C.LUA_AUTHORS - LUA_MULTRET = C.LUA_MULTRET + LUA_VERSION = C.LUA_VERSION + LUA_RELEASE = C.LUA_RELEASE + LUA_VERSION_NUM = C.LUA_VERSION_NUM + LUA_COPYRIGHT = C.LUA_COPYRIGHT + LUA_AUTHORS = C.LUA_AUTHORS + LUA_MULTRET = C.LUA_MULTRET LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX - LUA_ENVIRONINDEX = C.LUA_ENVIRONINDEX - LUA_GLOBALSINDEX = C.LUA_GLOBALSINDEX - LUA_YIELD = C.LUA_YIELD - LUA_ERRRUN = C.LUA_ERRRUN - LUA_ERRSYNTAX = C.LUA_ERRSYNTAX - LUA_ERRMEM = C.LUA_ERRMEM - LUA_ERRERR = C.LUA_ERRERR - LUA_TNONE = C.LUA_TNONE - LUA_MINSTACK = C.LUA_MINSTACK - LUA_GCSTOP = C.LUA_GCSTOP - LUA_GCRESTART = C.LUA_GCRESTART - LUA_GCCOLLECT = C.LUA_GCCOLLECT - LUA_GCCOUNT = C.LUA_GCCOUNT - LUA_GCCOUNTB = C.LUA_GCCOUNTB - LUA_GCSTEP = C.LUA_GCSTEP - LUA_GCSETPAUSE = C.LUA_GCSETPAUSE - LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL - LUA_HOOKCALL = C.LUA_HOOKCALL - LUA_HOOKRET = C.LUA_HOOKRET - LUA_HOOKLINE = C.LUA_HOOKLINE - LUA_HOOKCOUNT = C.LUA_HOOKCOUNT - LUA_HOOKTAILRET = C.LUA_HOOKTAILRET - LUA_MASKCALL = C.LUA_MASKCALL - LUA_MASKRET = C.LUA_MASKRET - LUA_MASKLINE = C.LUA_MASKLINE - LUA_MASKCOUNT = C.LUA_MASKCOUNT - LUA_ERRFILE = C.LUA_ERRFILE - LUA_NOREF = C.LUA_NOREF - LUA_REFNIL = C.LUA_REFNIL - LUA_FILEHANDLE = C.LUA_FILEHANDLE - LUA_COLIBNAME = C.LUA_COLIBNAME - LUA_TABLIBNAME = C.LUA_TABLIBNAME - LUA_IOLIBNAME = C.LUA_IOLIBNAME - LUA_OSLIBNAME = C.LUA_OSLIBNAME - LUA_STRLIBNAME = C.LUA_STRLIBNAME - LUA_MATHLIBNAME = C.LUA_MATHLIBNAME - LUA_DBLIBNAME = C.LUA_DBLIBNAME - LUA_LOADLIBNAME = C.LUA_LOADLIBNAME -) \ No newline at end of file + LUA_ENVIRONINDEX = C.LUA_ENVIRONINDEX + LUA_GLOBALSINDEX = C.LUA_GLOBALSINDEX + LUA_YIELD = C.LUA_YIELD + LUA_ERRRUN = C.LUA_ERRRUN + LUA_ERRSYNTAX = C.LUA_ERRSYNTAX + LUA_ERRMEM = C.LUA_ERRMEM + LUA_ERRERR = C.LUA_ERRERR + LUA_TNONE = C.LUA_TNONE + LUA_MINSTACK = C.LUA_MINSTACK + LUA_GCSTOP = C.LUA_GCSTOP + LUA_GCRESTART = C.LUA_GCRESTART + LUA_GCCOLLECT = C.LUA_GCCOLLECT + LUA_GCCOUNT = C.LUA_GCCOUNT + LUA_GCCOUNTB = C.LUA_GCCOUNTB + LUA_GCSTEP = C.LUA_GCSTEP + LUA_GCSETPAUSE = C.LUA_GCSETPAUSE + LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL + LUA_HOOKCALL = C.LUA_HOOKCALL + LUA_HOOKRET = C.LUA_HOOKRET + LUA_HOOKLINE = C.LUA_HOOKLINE + LUA_HOOKCOUNT = C.LUA_HOOKCOUNT + LUA_HOOKTAILRET = C.LUA_HOOKTAILRET + LUA_MASKCALL = C.LUA_MASKCALL + LUA_MASKRET = C.LUA_MASKRET + LUA_MASKLINE = C.LUA_MASKLINE + LUA_MASKCOUNT = C.LUA_MASKCOUNT + LUA_ERRFILE = C.LUA_ERRFILE + LUA_NOREF = C.LUA_NOREF + LUA_REFNIL = C.LUA_REFNIL + LUA_FILEHANDLE = C.LUA_FILEHANDLE + LUA_COLIBNAME = C.LUA_COLIBNAME + LUA_TABLIBNAME = C.LUA_TABLIBNAME + LUA_IOLIBNAME = C.LUA_IOLIBNAME + LUA_OSLIBNAME = C.LUA_OSLIBNAME + LUA_STRLIBNAME = C.LUA_STRLIBNAME + LUA_MATHLIBNAME = C.LUA_MATHLIBNAME + LUA_DBLIBNAME = C.LUA_DBLIBNAME + LUA_LOADLIBNAME = C.LUA_LOADLIBNAME +) diff --git a/lua/lua_test.go b/lua/lua_test.go index 9106b2d3..54e2a2b5 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -6,9 +6,9 @@ import ( ) type TestStruct struct { - IntField int + IntField int StringField string - FloatField float64 + FloatField float64 } func TestGoStruct(t *testing.T) { @@ -16,7 +16,7 @@ func TestGoStruct(t *testing.T) { L.OpenLibs() defer L.Close() - ts := &TestStruct{10, "test", 2.3 } + ts := &TestStruct{10, "test", 2.3} L.CheckStack(1) @@ -24,10 +24,14 @@ func TestGoStruct(t *testing.T) { L.SetGlobal("t") L.GetGlobal("t") - if !L.IsGoStruct(-1) { t.Fatal("Not go struct") } + if !L.IsGoStruct(-1) { + t.Fatal("Not go struct") + } tsr := L.ToGoStruct(-1).(*TestStruct) - if tsr != ts { t.Fatal("Retrieved something different from what we inserted") } + if tsr != ts { + t.Fatal("Retrieved something different from what we inserted") + } L.Pop(1) @@ -95,7 +99,7 @@ func TestCall(t *testing.T) { L.OpenLibs() defer L.Close() - test := func (L *State) int { + test := func(L *State) int { arg1 := L.ToString(1) arg2 := L.ToString(2) arg3 := L.ToString(3) @@ -171,7 +175,7 @@ func TestLikeBasic(t *testing.T) { L.GetField(LUA_GLOBALSINDEX, "print") L.PushString("Hello World!") - if err := L.Call(1,0); err != nil { + if err := L.Call(1, 0); err != nil { t.Fatalf("Call to print returned error") } @@ -180,24 +184,24 @@ func TestLikeBasic(t *testing.T) { L.PushGoFunction(test) L.PushGoFunction(test2) L.PushInteger(42) - if err := L.Call(1,0); err != nil { + if err := L.Call(1, 0); err != nil { t.Fatalf("Call to print returned error") } if (test2Arg != 42) || (test2Argfrombottom != 42) { t.Fatalf("Call to test2 didn't work") } - if err := L.Call(0,0); err != nil { + if err := L.Call(0, 0); err != nil { t.Fatalf("Call to print returned error") } - if err := L.Call(0,0); err != nil { + if err := L.Call(0, 0); err != nil { t.Fatalf("Call to print returned error") } - if err := L.Call(0,0); err != nil { + if err := L.Call(0, 0); err != nil { t.Fatalf("Call to print returned error") } if testCalled != 3 { - t.Fatalf("Test function not called the correct number of times: %d\n", testCalled); + t.Fatalf("Test function not called the correct number of times: %d\n", testCalled) } // this will fail as we didn't register test2 function @@ -232,18 +236,18 @@ func TestLikeQuickstart(t *testing.T) { // equivalent to userdata.go func TestLikeUserdata(t *testing.T) { type Userdata struct { - a,b int + a, b int } userDataProper := func(L *State) { - rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{}))); - var ptr *Userdata; - ptr = (*Userdata)(rawptr); - ptr.a = 2; - ptr.b = 3; + rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{}))) + var ptr *Userdata + ptr = (*Userdata)(rawptr) + ptr.a = 2 + ptr.b = 3 - rawptr2 := L.ToUserdata(-1); - ptr2 := (*Userdata)(rawptr2); + rawptr2 := L.ToUserdata(-1) + ptr2 := (*Userdata)(rawptr2) if ptr != ptr2 { t.Fatalf("Failed to create userdata\n") @@ -274,7 +278,7 @@ func TestLikeUserdata(t *testing.T) { t.Fatalf("Error executing test function: %v\n", err) } if testCalled != 1 { - t.Fatalf("It appears the test function wasn't actually called\n"); + t.Fatalf("It appears the test function wasn't actually called\n") } } From aa40b80e00c3d3dfcd73975b512058d95cb93cf8 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 22 Jan 2016 21:59:23 +0100 Subject: [PATCH 059/100] Make golua build on Fedora/CentOS The pkg-config package for lua is different in all architectures and therefore it can not be used. Partial revert of fa753832 (update build flags for osx) Fixes #43 --- lua/lua.go | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/lua.go b/lua/lua.go index ed27e591..1badfbaf 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -6,7 +6,6 @@ package lua /* -#cgo pkg-config: lua5.1 #cgo CFLAGS: -Ilua #cgo llua LDFLAGS: -llua #cgo luaa LDFLAGS: -llua -lm -ldl From d4351ab17557c115aab48c2d62d9a4f98710dee2 Mon Sep 17 00:00:00 2001 From: Shane Hansen Date: Wed, 6 Apr 2016 17:03:20 -0600 Subject: [PATCH 060/100] Use map to track gostate rather than slice Fixes #44 and removes 4 byte per lua State leak. --- lua/c-golua.c | 24 ++++++++++++------------ lua/golua.go | 26 +++++++++++++------------- lua/golua.h | 4 ++-- lua/lua.go | 6 +++--- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index 7ca79d51..4cb41d83 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -55,13 +55,13 @@ unsigned int* clua_checkgosomething(lua_State* L, int index, const char *desired } } -int clua_getgostate(lua_State* L) +size_t clua_getgostate(lua_State* L) { - int gostateindex; + size_t gostateindex; //get gostate from registry entry lua_pushlightuserdata(L,(void*)&GoStateRegistryKey); lua_gettable(L, LUA_REGISTRYINDEX); - gostateindex = lua_tointeger(L,-1); + gostateindex = (size_t)lua_touserdata(L,-1); lua_pop(L,1); return gostateindex; } @@ -72,7 +72,7 @@ int callback_function(lua_State* L) { int r; unsigned int *fid = clua_checkgosomething(L, 1, MT_GOFUNCTION); - int gostateindex = clua_getgostate(L); + size_t gostateindex = clua_getgostate(L); //remove the go function from the stack (to present same behavior as lua_CFunctions) lua_remove(L,1); return golua_callgofunction(gostateindex, fid!=NULL ? *fid : -1); @@ -83,7 +83,7 @@ int gchook_wrapper(lua_State* L) { //printf("Garbage collection wrapper\n"); unsigned int* fid = clua_checkgosomething(L, -1, NULL); - int gostateindex = clua_getgostate(L); + size_t gostateindex = clua_getgostate(L); if (fid != NULL) return golua_gchook(gostateindex,*fid); return 0; @@ -112,7 +112,7 @@ void clua_pushgofunction(lua_State* L, unsigned int fid) static int callback_c (lua_State* L) { int fid = clua_togofunction(L,lua_upvalueindex(1)); - int gostateindex = clua_getgostate(L); + size_t gostateindex = clua_getgostate(L); return golua_callgofunction(gostateindex,fid); } @@ -136,11 +136,11 @@ int default_panicf(lua_State *L) abort(); } -void clua_setgostate(lua_State* L, int gostateindex) +void clua_setgostate(lua_State* L, size_t gostateindex) { lua_atpanic(L, default_panicf); lua_pushlightuserdata(L,(void*)&GoStateRegistryKey); - lua_pushinteger(L, gostateindex); + lua_pushlightuserdata(L, (void*)gostateindex); //set into registry table lua_settable(L, LUA_REGISTRYINDEX); } @@ -162,7 +162,7 @@ int interface_index_callback(lua_State *L) return 1; } - int gostateindex = clua_getgostate(L); + size_t gostateindex = clua_getgostate(L); int r = golua_interface_index_callback(gostateindex, *iid, field_name); @@ -194,7 +194,7 @@ int interface_newindex_callback(lua_State *L) return 1; } - int gostateindex = clua_getgostate(L); + size_t gostateindex = clua_getgostate(L); int r = golua_interface_newindex_callback(gostateindex, *iid, field_name); @@ -211,7 +211,7 @@ int interface_newindex_callback(lua_State *L) int panic_msghandler(lua_State *L) { - int gostateindex = clua_getgostate(L); + size_t gostateindex = clua_getgostate(L); go_panic_msghandler(gostateindex, (char *)lua_tolstring(L, -1, NULL)); return 0; } @@ -273,7 +273,7 @@ int callback_panicf(lua_State* L) lua_gettable(L,LUA_REGISTRYINDEX); unsigned int fid = lua_tointeger(L,-1); lua_pop(L,1); - int gostateindex = clua_getgostate(L); + size_t gostateindex = clua_getgostate(L); return golua_callpanicfunction(gostateindex,fid); } diff --git a/lua/golua.go b/lua/golua.go index 4580dde7..a7a74a9e 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -28,7 +28,7 @@ type State struct { s *C.lua_State // index of this object inside the goStates array - Index int + Index uintptr // Registry of go object that have been pushed to Lua VM registry []interface{} @@ -37,34 +37,34 @@ type State struct { freeIndices []uint } -var goStates []*State +var goStates map[uintptr]*State var goStatesMutex sync.Mutex func init() { - goStates = make([]*State, 0, 16) + goStates = make(map[uintptr]*State, 16) } func registerGoState(L *State) { goStatesMutex.Lock() defer goStatesMutex.Unlock() - L.Index = len(goStates) - goStates = append(goStates, L) + L.Index = uintptr(unsafe.Pointer(L)) + goStates[L.Index] = L } func unregisterGoState(L *State) { goStatesMutex.Lock() defer goStatesMutex.Unlock() - goStates[L.Index] = nil + delete(goStates, L.Index) } -func getGoState(gostateindex int) *State { +func getGoState(gostateindex uintptr) *State { goStatesMutex.Lock() defer goStatesMutex.Unlock() return goStates[gostateindex] } //export golua_callgofunction -func golua_callgofunction(gostateindex int, fid uint) int { +func golua_callgofunction(gostateindex uintptr, fid uint) int { L1 := getGoState(gostateindex) if fid < 0 { panic(&LuaError{0, "Requested execution of an unknown function", L1.StackTrace()}) @@ -74,7 +74,7 @@ func golua_callgofunction(gostateindex int, fid uint) int { } //export golua_interface_newindex_callback -func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cstr *C.char) int { +func golua_interface_newindex_callback(gostateindex uintptr, iid uint, field_name_cstr *C.char) int { L := getGoState(gostateindex) iface := L.registry[iid] ifacevalue := reflect.ValueOf(iface).Elem() @@ -159,7 +159,7 @@ func golua_interface_newindex_callback(gostateindex int, iid uint, field_name_cs } //export golua_interface_index_callback -func golua_interface_index_callback(gostateindex int, iid uint, field_name *C.char) int { +func golua_interface_index_callback(gostateindex uintptr, iid uint, field_name *C.char) int { L := getGoState(gostateindex) iface := L.registry[iid] ifacevalue := reflect.ValueOf(iface).Elem() @@ -215,14 +215,14 @@ func golua_interface_index_callback(gostateindex int, iid uint, field_name *C.ch } //export golua_gchook -func golua_gchook(gostateindex int, id uint) int { +func golua_gchook(gostateindex uintptr, id uint) int { L1 := getGoState(gostateindex) L1.unregister(id) return 0 } //export golua_callpanicfunction -func golua_callpanicfunction(gostateindex int, id uint) int { +func golua_callpanicfunction(gostateindex uintptr, id uint) int { L1 := getGoState(gostateindex) f := L1.registry[id].(LuaGoFunction) return f(L1) @@ -244,7 +244,7 @@ func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { } //export go_panic_msghandler -func go_panic_msghandler(gostateindex int, z *C.char) { +func go_panic_msghandler(gostateindex uintptr, z *C.char) { L := getGoState(gostateindex) s := C.GoString(z) diff --git a/lua/golua.h b/lua/golua.h index e6f66a37..93fcdd5a 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -13,8 +13,8 @@ unsigned int clua_togostruct(lua_State *L, int index); void clua_pushcallback(lua_State* L); void clua_pushgofunction(lua_State* L, unsigned int fid); void clua_pushgostruct(lua_State *L, unsigned int fid); -void clua_setgostate(lua_State* L, int gostateindex); -GoInterface* clua_getgostate(lua_State* L); +void clua_setgostate(lua_State* L, size_t gostateindex); +size_t clua_getgostate(lua_State* L); GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id); int clua_callluacfunc(lua_State* L, lua_CFunction f); lua_State* clua_newstate(void* goallocf); diff --git a/lua/lua.go b/lua/lua.go index 1badfbaf..19bfb559 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -32,9 +32,9 @@ type LuaStackEntry struct { } func newState(L *C.lua_State) *State { - newstate := &State{L, -1, make([]interface{}, 0, 8), make([]uint, 0, 8)} + newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8)} registerGoState(newstate) - C.clua_setgostate(L, C.int(newstate.Index)) + C.clua_setgostate(L, C.size_t(newstate.Index)) C.clua_initstate(L) return newstate } @@ -347,7 +347,7 @@ func (L *State) NewThread() *State { //TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) - return &State{s, -1, nil, nil} + return &State{s, 0, nil, nil} } // lua_next From 3933e72318e931e4cb164be6b7a9f74aea1a284f Mon Sep 17 00:00:00 2001 From: Andrew Danforth Date: Wed, 3 Aug 2016 22:20:01 -0400 Subject: [PATCH 061/100] Added ToBytes and PushBytes methods. Updated magic struct reflection metamethods to handle conversion between Go byte slices and Lua strings. --- lua/golua.go | 17 +++++++++++++++++ lua/lua.go | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/lua/golua.go b/lua/golua.go index a7a74a9e..71836d0e 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -73,6 +73,8 @@ func golua_callgofunction(gostateindex uintptr, fid uint) int { return f(L1) } +var typeOfBytes = reflect.TypeOf([]byte(nil)) + //export golua_interface_newindex_callback func golua_interface_newindex_callback(gostateindex uintptr, iid uint, field_name_cstr *C.char) int { L := getGoState(gostateindex) @@ -152,6 +154,16 @@ func golua_interface_newindex_callback(gostateindex uintptr, iid uint, field_nam L.PushString("Wrong assignment to field " + field_name) return -1 } + case reflect.Slice: + if fval.Type() == typeOfBytes { + if luatype == LUA_TSTRING { + fval.SetBytes(L.ToBytes(3)) + return 1 + } else { + L.PushString("Wrong assignment to field " + field_name) + return -1 + } + } } L.PushString("Unsupported type of field " + field_name + ": " + fval.Type().String()) @@ -208,6 +220,11 @@ func golua_interface_index_callback(gostateindex uintptr, iid uint, field_name * case reflect.Float64: L.PushNumber(fval.Float()) return 1 + case reflect.Slice: + if fval.Type() == typeOfBytes { + L.PushBytes(fval.Bytes()) + return 1 + } } L.PushString("Unsupported type of field: " + fval.Type().String()) diff --git a/lua/lua.go b/lua/lua.go index 19bfb559..3d3ffcb3 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -385,6 +385,10 @@ func (L *State) PushString(str string) { C.lua_pushlstring(L.s, Cstr, C.size_t(len(str))) } +func (L *State) PushBytes(b []byte) { + C.lua_pushlstring(L.s, (*C.char)(unsafe.Pointer(&b[0])), C.size_t(len(b))) +} + // lua_pushinteger func (L *State) PushInteger(n int64) { C.lua_pushinteger(L.s, C.lua_Integer(n)) @@ -536,6 +540,12 @@ func (L *State) ToString(index int) string { return C.GoStringN(r, C.int(size)) } +func (L *State) ToBytes(index int) []byte { + var size C.size_t + b := C.lua_tolstring(L.s, C.int(index), &size) + return C.GoBytes(unsafe.Pointer(b), C.int(size)) +} + // lua_tointeger func (L *State) ToInteger(index int) int { return int(C.lua_tointeger(L.s, C.int(index))) From 13f31dc0f4053bfc918fcf7a7a07c77c6c8bb933 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sun, 7 Aug 2016 13:58:29 +0200 Subject: [PATCH 062/100] Add link to "golua unicode" --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 10dd87de..6817adec 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,8 @@ CONTRIBUTORS SEE ALSO --------------------- -[Luar](https://github.com/stevedonovan/luar/) is a reflection layer on top of golua API providing a simplified way to publish go functions to a Lua VM. +- [Luar](https://github.com/stevedonovan/luar/) is a reflection layer on top of golua API providing a simplified way to publish go functions to a Lua VM. +- [Golua unicode](https://bitbucket.org/ambrevar/golua/) is an extension library that adds unicode support to golua and replaces lua regular expressions with re2. Licensing ------------- From cf37152cc48aa4c67b1c2ea01ad900be1c2264de Mon Sep 17 00:00:00 2001 From: huangwei1024 Date: Mon, 13 Mar 2017 17:22:21 +0800 Subject: [PATCH 063/100] support mingw64 on windows --- README.md | 1 + lua/lua.go | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 6817adec..cc7a4636 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,7 @@ CONTRIBUTORS * HongZhen Peng * Admin36 * Pierre Neidhardt (@Ambrevar) +* HuangWei (@huangwei1024) SEE ALSO --------------------- diff --git a/lua/lua.go b/lua/lua.go index 3d3ffcb3..c9902e5a 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -12,6 +12,7 @@ package lua #cgo linux,!llua,!luaa LDFLAGS: -llua5.1 #cgo darwin,!luaa pkg-config: lua5.1 #cgo freebsd,!luaa LDFLAGS: -llua-5.1 +#cgo windows,!llua LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 #include #include From 398439a45a7a3ed2b25143f1e7dfd1ca8c413af8 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sun, 26 Mar 2017 07:59:14 +0200 Subject: [PATCH 064/100] update README to mention lua5.3 branch. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cc7a4636..c240c932 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,7 @@ ODDS AND ENDS --------------------- * Support for lua 5.2 is in the lua5.2 branch, this branch only supports lua5.1. +* Support for lua 5.3 is in the lua5.3 branch. * Compiling from source yields only a static link library (liblua.a), you can either produce the dynamic link library on your own or use the `luaa` build tag. LUAJIT From 8eb37ae21482de8d6bc04c3bcc1acff0febd08bc Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 22 May 2017 11:15:37 +0200 Subject: [PATCH 065/100] update to work with go1.9 See https://github.com/golang/go/issues/20266 --- lua/golua.go | 2 +- lua/lua.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/golua.go b/lua/golua.go index 71836d0e..381e2c1f 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -1,7 +1,7 @@ package lua /* -#cgo CFLAGS: -Ilua +#cgo CFLAGS: -I ${SRCDIR}/lua #include #include diff --git a/lua/lua.go b/lua/lua.go index c9902e5a..cea11e0c 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -6,7 +6,7 @@ package lua /* -#cgo CFLAGS: -Ilua +#cgo CFLAGS: -I ${SRCDIR}/lua #cgo llua LDFLAGS: -llua #cgo luaa LDFLAGS: -llua -lm -ldl #cgo linux,!llua,!luaa LDFLAGS: -llua5.1 From 8a6e7a0d5424388270950c473e6ec051abbf70d3 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 22 May 2017 11:26:14 +0200 Subject: [PATCH 066/100] Add travis check --- .travis.yml | 10 ++++++++++ README.md | 2 ++ 2 files changed, 12 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..4f5ccae9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: go +dist: trusty +before_install: + - sudo add-apt-repository ppa:vbernat/haproxy-1.6 -y + - sudo apt-get -qq update + - sudo apt-get install -y liblua5.1-dev + - sudo apt-get install -y liblua5.2-dev + - sudo apt-get install -y liblua5.3-dev +install: true +script: go test -v github.com/aarzilli/golua/lua diff --git a/README.md b/README.md index c240c932..98c76239 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Go Bindings for the lua C API ========================= +[![Build Status](https://travis-ci.org/aarzilli/golua.svg?branch=master)](https://travis-ci.org/aarzilli/golua) + Simplest way to install: # go get -u github.com/aarzilli/golua/lua From 812b106414f06932d1593ee14d8375a432de69fb Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Wed, 16 Aug 2017 11:04:52 +0800 Subject: [PATCH 067/100] force to link luajit with tag --- README.md | 4 ++-- lua/lua.go | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 98c76239..278e69fd 100644 --- a/README.md +++ b/README.md @@ -116,8 +116,8 @@ To link with [luajit-2.0.x](http://luajit.org/luajit.html), you can use CGO_CFLA ``` $ CGO_CFLAGS=`pkg-config luajit --cflags` -$ CGO_LDFLAGS=`pkg-config luajit --libs` -$ go get -f -u github.com/aarzilli/golua/lua +$ CGO_LDFLAGS=`pkg-config luajit --libs-only-L` +$ go get -f -u -tags luajit github.com/aarzilli/golua/lua ``` CONTRIBUTORS diff --git a/lua/lua.go b/lua/lua.go index cea11e0c..1aff2265 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -9,10 +9,11 @@ package lua #cgo CFLAGS: -I ${SRCDIR}/lua #cgo llua LDFLAGS: -llua #cgo luaa LDFLAGS: -llua -lm -ldl -#cgo linux,!llua,!luaa LDFLAGS: -llua5.1 -#cgo darwin,!luaa pkg-config: lua5.1 -#cgo freebsd,!luaa LDFLAGS: -llua-5.1 -#cgo windows,!llua LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 +#cgo luajit LDFLAGS: -lluajit-5.1 +#cgo linux,!llua,!luaa,!luajit LDFLAGS: -llua5.1 +#cgo darwin,!luaa,!luajit pkg-config: lua5.1 +#cgo freebsd,!luaa,!luajit LDFLAGS: -llua-5.1 +#cgo windows,!llua,!luajit LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 #include #include From 24dee68d5b73dfa9f3bf7634a75af35d93cc18ea Mon Sep 17 00:00:00 2001 From: Flier Lu Date: Wed, 16 Aug 2017 11:12:19 +0800 Subject: [PATCH 068/100] fix new state crash --- lua/lauxlib.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 0ba5984d..71569166 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -166,6 +166,9 @@ func (L *State) NewMetaTable(tname string) bool { // luaL_newstate func NewState() *State { ls := (C.luaL_newstate()) + if ls == nil { + return nil + } L := newState(ls) return L } From 24fe5b510806231d29be66de88ab2ce608311d33 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 4 Sep 2017 17:11:39 +0200 Subject: [PATCH 069/100] Changed golua unicode link. Fixes #61 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 278e69fd..a8ddb34f 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ SEE ALSO --------------------- - [Luar](https://github.com/stevedonovan/luar/) is a reflection layer on top of golua API providing a simplified way to publish go functions to a Lua VM. -- [Golua unicode](https://bitbucket.org/ambrevar/golua/) is an extension library that adds unicode support to golua and replaces lua regular expressions with re2. +- [Golua unicode](https://github.com/Ambrevar/golua) is an extension library that adds unicode support to golua and replaces lua regular expressions with re2. Licensing ------------- From 459c093c4212ae233459840a6e8d0ae98f78c37f Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 2 Mar 2018 09:44:41 +0100 Subject: [PATCH 070/100] Ensure that registry resize is large enough Fixes #64 --- lua/lua.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lua/lua.go b/lua/lua.go index 1aff2265..1460a3b5 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -77,7 +77,11 @@ func (L *State) register(f interface{}) uint { index = uint(len(L.registry)) //reallocate backing array if necessary if index+1 > uint(cap(L.registry)) { - newSlice := make([]interface{}, index, cap(L.registry)*2) + newcap := cap(L.registry)*2 + if index+1 > uint(newcap) { + newcap = int(index+1) + } + newSlice := make([]interface{}, index, newcap) copy(newSlice, L.registry) L.registry = newSlice } From e82ac2f91b40ba7485708ebca0cae0af96ac9ff7 Mon Sep 17 00:00:00 2001 From: "zhaoxin.yc" Date: Sat, 13 Jul 2019 19:01:01 +0800 Subject: [PATCH 071/100] add lua_dump and lua_load support --- example/dump_load.go | 41 ++++++++++++++++++++++++++++++++ lua/c-golua.c | 56 ++++++++++++++++++++++++++++++++++++++++++++ lua/golua.h | 2 ++ lua/lauxlib.go | 19 +++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 example/dump_load.go diff --git a/example/dump_load.go b/example/dump_load.go new file mode 100644 index 00000000..931ce9dd --- /dev/null +++ b/example/dump_load.go @@ -0,0 +1,41 @@ +package main + +import ( + "fmt" + + "../lua" +) + +// dumpAndLoadTest: dump a function chunk to bytecodes, then load bytecodes and call function +func dumpAndLoadTest(L *lua.State) { + loadret := L.LoadString(`print("msg from dump_and_load_test")`) + if loadret != 0 { + panic(fmt.Sprintf("LoadString error: %v", loadret)) + } + dumpret := L.Dump() + if dumpret != 0 { + panic(fmt.Sprintf("Dump error: %v", dumpret)) + } + + isstring := L.IsString(-1) + if !isstring { + panic("stack top not a string") + } + bytecodes := L.ToBytes(-1) + loadret = L.Load(bytecodes, "chunk_from_dump_and_load_test") + if loadret != 0 { + panic(fmt.Sprintf("Load error: %v", loadret)) + } + err := L.Call(0, 0) + if err != nil { + panic(fmt.Sprintf("Call error: %v", err)) + } +} + +func main() { + L := lua.NewState() + defer L.Close() + L.OpenLibs() + + dumpAndLoadTest(L) +} diff --git a/lua/c-golua.c b/lua/c-golua.c index 4cb41d83..6db57175 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -13,6 +13,12 @@ static const char GoStateRegistryKey = 'k'; //golua registry key static const char PanicFIDRegistryKey = 'k'; +typedef struct _chunk { + int size; // chunk size + char *buffer; // chunk data + char* toread; // chunk to read +} chunk; + /* taken from lua5.2 source */ void *testudata(lua_State *L, int ud, const char *tname) { @@ -145,6 +151,56 @@ void clua_setgostate(lua_State* L, size_t gostateindex) lua_settable(L, LUA_REGISTRYINDEX); } +static int writer (lua_State *L, const void* b, size_t size, void* B) { + static int count=0; + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 0; +} + +// dump function chunk from luaL_loadstring +int dump_chunk (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_settop(L, -1); + luaL_buffinit(L,&b); + int errno; + errno = lua_dump(L, writer, &b); + if (errno != 0){ + return luaL_error(L, "unable to dump given function, errno:%d", errno); + } + luaL_pushresult(&b); + return 0; +} + +static const char * reader (lua_State *L, void *ud, size_t *sz) { + chunk *ck = (chunk *)ud; + if (ck->size > LUAL_BUFFERSIZE) { + ck->size -= LUAL_BUFFERSIZE; + *sz = LUAL_BUFFERSIZE; + ck->toread = ck->buffer; + ck->buffer += LUAL_BUFFERSIZE; + }else{ + *sz = ck->size; + ck->toread = ck->buffer; + ck->size = 0; + } + return ck->toread; +} + +// load function chunk dumped from dump_chunk +int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { + chunk ck; + ck.buffer = b; + ck.size = size; + int errno; + errno = lua_load(L, reader, &ck, chunk_name); + if (errno != 0) { + return luaL_error(L, "unable to load chunk, errno: %d", errno); + } + return 0; +} + /* called when lua code attempts to access a field of a published go object */ int interface_index_callback(lua_State *L) { diff --git a/lua/golua.h b/lua/golua.h index 93fcdd5a..855cf07d 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -14,6 +14,8 @@ void clua_pushcallback(lua_State* L); void clua_pushgofunction(lua_State* L, unsigned int fid); void clua_pushgostruct(lua_State *L, unsigned int fid); void clua_setgostate(lua_State* L, size_t gostateindex); +int dump_chunk (lua_State *L); +int load_chunk(lua_State *L, const char *b, int size, const char* chunk_name); size_t clua_getgostate(lua_State* L); GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id); int clua_callluacfunc(lua_State* L, lua_CFunction f); diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 71569166..57dee754 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -156,6 +156,25 @@ func (L *State) LoadString(s string) int { return int(C.luaL_loadstring(L.s, Cs)) } +// lua_dump +func (L *State) Dump() int { + ret := int(C.dump_chunk(L.s)) + return ret +} + +// lua_load +func (L *State) Load(bs []byte, name string) int { + chunk := C.CString(string(bs)) + ckname := C.CString(name) + defer C.free(unsafe.Pointer(chunk)) + defer C.free(unsafe.Pointer(ckname)) + ret := int(C.load_chunk(L.s, chunk, C.int(len(bs)), ckname)) + if ret != 0 { + return ret + } + return 0 +} + // luaL_newmetatable func (L *State) NewMetaTable(tname string) bool { Ctname := C.CString(tname) From d4a430464f0f3f008103de72a761953ad1335372 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Sun, 14 Jul 2019 20:30:37 +0200 Subject: [PATCH 072/100] test dump and load --- lua/lua_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/lua/lua_test.go b/lua/lua_test.go index 54e2a2b5..167a745e 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -382,3 +382,32 @@ func TestConv(t *testing.T) { t.Fatalf("Wrong conversion (str -> str): <%s>", s) } } + +func TestDumpAndLoad(t *testing.T) { + L := NewState() + defer L.Close() + L.OpenLibs() + + loadret := L.LoadString(`print("msg from dump_and_load_test")`) + if loadret != 0 { + t.Fatalf("LoadString error: %v", loadret) + } + dumpret := L.Dump() + if dumpret != 0 { + t.Fatalf("Dump error: %v", dumpret) + } + + isstring := L.IsString(-1) + if !isstring { + t.Fatalf("stack top not a string") + } + bytecodes := L.ToBytes(-1) + loadret = L.Load(bytecodes, "chunk_from_dump_and_load_test") + if loadret != 0 { + t.Fatalf("Load error: %v", loadret) + } + err := L.Call(0, 0) + if err != nil { + t.Fatalf("Call error: %v", err) + } +} From 8cb2917bca196273dfe98d4ad455338db8deead5 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Sun, 19 Jan 2020 10:31:13 -0300 Subject: [PATCH 073/100] add lunatico --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a8ddb34f..9246c5ac 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,7 @@ SEE ALSO --------------------- - [Luar](https://github.com/stevedonovan/luar/) is a reflection layer on top of golua API providing a simplified way to publish go functions to a Lua VM. +- [lunatico](https://github.com/fiatjaf/lunatico) is a reflection layer that allows you to push and read Go values to a Lua VM without understanding the Lua stack. - [Golua unicode](https://github.com/Ambrevar/golua) is an extension library that adds unicode support to golua and replaces lua regular expressions with re2. Licensing From 421e0de0aa200830c11177a428340ca8ea5c766a Mon Sep 17 00:00:00 2001 From: edolphin Date: Fri, 14 Feb 2020 15:45:43 +0800 Subject: [PATCH 074/100] add GetState func --- lua/lua.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lua/lua.go b/lua/lua.go index 1460a3b5..eea582a7 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -77,9 +77,9 @@ func (L *State) register(f interface{}) uint { index = uint(len(L.registry)) //reallocate backing array if necessary if index+1 > uint(cap(L.registry)) { - newcap := cap(L.registry)*2 + newcap := cap(L.registry) * 2 if index+1 > uint(newcap) { - newcap = int(index+1) + newcap = int(index + 1) } newSlice := make([]interface{}, index, newcap) copy(newSlice, L.registry) @@ -677,3 +677,7 @@ func (L *State) RaiseError(msg string) { func (L *State) NewError(msg string) *LuaError { return &LuaError{0, msg, L.StackTrace()} } + +func (L *State) GetState() *C.lua_State { + return L.s +} From 703cd5714e62c6e34777aacabbabba589c0f670d Mon Sep 17 00:00:00 2001 From: Niels Widger Date: Wed, 22 Jul 2020 09:46:33 -0400 Subject: [PATCH 075/100] Fix vendoring of package using go mod vendor A directory with only C files will not be vendored by go mod vendor, see this issue: https://github.com/golang/go/issues/26366, specifically, Russ Cox's response https://github.com/golang/go/issues/26366#issuecomment-405683150. Because of this, when vendoring github.com/aarzilli/golua with go mod vendor, the C header files under github.com/aarzilli/golua/lua/lua are not vendored. This commits adds a workaround to this issue by adding dummy Go files which makes go mod behave correctly. This workaround was based on a similar one found here: https://github.com/crawshaw/sqlite/pull/88. --- lua/dummy.go | 18 ++++++++++++++++++ lua/lua/dummy.go | 7 +++++++ 2 files changed, 25 insertions(+) create mode 100644 lua/dummy.go create mode 100644 lua/lua/dummy.go diff --git a/lua/dummy.go b/lua/dummy.go new file mode 100644 index 00000000..24ab2842 --- /dev/null +++ b/lua/dummy.go @@ -0,0 +1,18 @@ +// +build dummy + +// This file is part of a workaround for `go mod vendor` which won't +// vendor C files if there are no Go files in the same directory. +// This prevents the C header files in lua/ from being vendored. +// +// This Go file imports the lua package where there is another +// dummy.go file which is the second part of this workaround. +// +// These two files combined make it so `go mod vendor` behaves correctly. +// +// See this issue for reference: https://github.com/golang/go/issues/26366 + +package lua + +import ( + _ "github.com/aarzilli/golua/lua/lua" +) diff --git a/lua/lua/dummy.go b/lua/lua/dummy.go new file mode 100644 index 00000000..651a7971 --- /dev/null +++ b/lua/lua/dummy.go @@ -0,0 +1,7 @@ +// +build dummy + +// Package lua contains only a C header files. +// +// This Go file is part of a workaround for `go mod vendor`. +// Please see the file dummy.go in the parent directory for more information. +package lua From 80ff49e0cd6344e594678b122a52e51e95878c61 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 3 Aug 2020 16:36:18 +0200 Subject: [PATCH 076/100] Add option to link to liblua-5.1.so Fixes #81 --- README.md | 4 ++++ lua/lua.go | 9 +++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9246c5ac..031c29f4 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,10 @@ If your linux system uses "lua" as the shared object name for lua (for example, # go get -u -tags llua github.com/aarzilli/golua/lua +If your linux system uses "lua-5.1" as the shared object name for lua (for example, some versions of CentOS do this) you can install using: + + # go get -u -tags lluadash5.1 github.com/aarzilli/golua/lua + You can then try to run the examples: diff --git a/lua/lua.go b/lua/lua.go index eea582a7..0bf5bb92 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -10,10 +10,11 @@ package lua #cgo llua LDFLAGS: -llua #cgo luaa LDFLAGS: -llua -lm -ldl #cgo luajit LDFLAGS: -lluajit-5.1 -#cgo linux,!llua,!luaa,!luajit LDFLAGS: -llua5.1 -#cgo darwin,!luaa,!luajit pkg-config: lua5.1 -#cgo freebsd,!luaa,!luajit LDFLAGS: -llua-5.1 -#cgo windows,!llua,!luajit LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 +#cgo lluadash5.1 LDFLAGS: -llua-5.1 +#cgo linux,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.1 +#cgo darwin,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.1 +#cgo freebsd,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.1 +#cgo windows,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 #include #include From 705f54a1ed352d7d945c14d4e4e02c1f99d323e6 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 3 Aug 2020 16:41:31 +0200 Subject: [PATCH 077/100] Add go.mod, fix eamples import paths, gofmt examples --- {example => _example}/alloc.go | 32 ++++++++++++------------- {example => _example}/basic.go | 13 +++++----- {example => _example}/calls.lua | 0 {example => _example}/dump_load.go | 2 +- {example => _example}/error.go | 2 +- _example/panic.go | 37 +++++++++++++++++++++++++++++ {example => _example}/quickstart.go | 2 +- {example => _example}/userdata.go | 34 +++++++++++++------------- example/panic.go | 37 ----------------------------- go.mod | 3 +++ 10 files changed, 81 insertions(+), 81 deletions(-) rename {example => _example}/alloc.go (62%) rename {example => _example}/basic.go (86%) rename {example => _example}/calls.lua (100%) rename {example => _example}/dump_load.go (96%) rename {example => _example}/error.go (95%) create mode 100644 _example/panic.go rename {example => _example}/quickstart.go (89%) rename {example => _example}/userdata.go (70%) delete mode 100644 example/panic.go create mode 100644 go.mod diff --git a/example/alloc.go b/_example/alloc.go similarity index 62% rename from example/alloc.go rename to _example/alloc.go index 41731604..06997db4 100644 --- a/example/alloc.go +++ b/_example/alloc.go @@ -1,23 +1,22 @@ package main -import "../lua" +import "github.com/aarzilli/golua/lua" import "unsafe" import "fmt" var refHolder = map[unsafe.Pointer][]byte{} - //a terrible allocator! //meant to be illustrative of the mechanics, //not usable as an actual implementation func AllocatorF(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { - if(nsize == 0) { + if nsize == 0 { if _, ok := refHolder[ptr]; ok { delete(refHolder, ptr) } ptr = unsafe.Pointer(nil) - } else if(osize != nsize) { - slice := make([]byte,nsize); + } else if osize != nsize { + slice := make([]byte, nsize) if oldslice, ok := refHolder[ptr]; ok { copy(slice, oldslice) @@ -25,33 +24,32 @@ func AllocatorF(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { delete(refHolder, ptr) } - ptr = unsafe.Pointer(&(slice[0])); + ptr = unsafe.Pointer(&(slice[0])) refHolder[ptr] = slice } //fmt.Println("in allocf"); - return ptr; + return ptr } - func A2(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { - return AllocatorF(ptr,osize,nsize); + return AllocatorF(ptr, osize, nsize) } func main() { //refHolder = make([][]byte,0,500); - L := lua.NewStateAlloc(AllocatorF); + L := lua.NewStateAlloc(AllocatorF) defer L.Close() - L.OpenLibs(); + L.OpenLibs() - L.SetAllocf(A2); + L.SetAllocf(A2) - for i:=0; i < 10; i++ { - L.GetField(lua.LUA_GLOBALSINDEX, "print"); - L.PushString("Hello World!"); - L.Call(1,0); + for i := 0; i < 10; i++ { + L.GetField(lua.LUA_GLOBALSINDEX, "print") + L.PushString("Hello World!") + L.Call(1, 0) } - fmt.Println(len(refHolder)); + fmt.Println(len(refHolder)) } diff --git a/example/basic.go b/_example/basic.go similarity index 86% rename from example/basic.go rename to _example/basic.go index 42581cc3..38789de5 100644 --- a/example/basic.go +++ b/_example/basic.go @@ -1,6 +1,6 @@ package main -import "../lua" +import "github.com/aarzilli/golua/lua" import "fmt" func test(L *lua.State) int { @@ -25,7 +25,7 @@ func main() { L.GetField(lua.LUA_GLOBALSINDEX, "print") L.PushString("Hello World!") - L.Call(1,0) + L.Call(1, 0) L.PushGoFunction(test) L.PushGoFunction(test) @@ -34,12 +34,11 @@ func main() { L.PushGoFunction(test2) L.PushInteger(42) - L.Call(1,0) + L.Call(1, 0) - - L.Call(0,0) - L.Call(0,0) - L.Call(0,0) + L.Call(0, 0) + L.Call(0, 0) + L.Call(0, 0) // this will fail as we didn't register test2 function err := L.DoString("test2(42)") diff --git a/example/calls.lua b/_example/calls.lua similarity index 100% rename from example/calls.lua rename to _example/calls.lua diff --git a/example/dump_load.go b/_example/dump_load.go similarity index 96% rename from example/dump_load.go rename to _example/dump_load.go index 931ce9dd..9d8c95b5 100644 --- a/example/dump_load.go +++ b/_example/dump_load.go @@ -3,7 +3,7 @@ package main import ( "fmt" - "../lua" + "github.com/aarzilli/golua/lua" ) // dumpAndLoadTest: dump a function chunk to bytecodes, then load bytecodes and call function diff --git a/example/error.go b/_example/error.go similarity index 95% rename from example/error.go rename to _example/error.go index 778d9425..5ae65d93 100644 --- a/example/error.go +++ b/_example/error.go @@ -1,6 +1,6 @@ package main -import "../lua" +import "github.com/aarzilli/golua/lua" import "fmt" import "errors" import "os" diff --git a/_example/panic.go b/_example/panic.go new file mode 100644 index 00000000..ef8b9d7d --- /dev/null +++ b/_example/panic.go @@ -0,0 +1,37 @@ +package main + +import "github.com/aarzilli/golua/lua" +import "fmt" + +func test(L *lua.State) int { + fmt.Println("hello world! from go!") + return 0 +} + +func main() { + + var L *lua.State + + L = lua.NewState() + defer L.Close() + L.OpenLibs() + + currentPanicf := L.AtPanic(nil) + currentPanicf = L.AtPanic(currentPanicf) + newPanic := func(L1 *lua.State) int { + fmt.Println("I AM PANICKING!!!", currentPanicf) + if currentPanicf != nil { + return currentPanicf(L1) + } + + return 1 + } + + L.AtPanic(newPanic) + + //force a panic + L.PushNil() + L.Call(0, 0) + + fmt.Println("End") +} diff --git a/example/quickstart.go b/_example/quickstart.go similarity index 89% rename from example/quickstart.go rename to _example/quickstart.go index bb9afd96..c20a3ac8 100644 --- a/example/quickstart.go +++ b/_example/quickstart.go @@ -1,6 +1,6 @@ package main -import "../lua" +import "github.com/aarzilli/golua/lua" func adder(L *lua.State) int { a := L.ToInteger(1) diff --git a/example/userdata.go b/_example/userdata.go similarity index 70% rename from example/userdata.go rename to _example/userdata.go index eb6ac3bd..5cd56b36 100644 --- a/example/userdata.go +++ b/_example/userdata.go @@ -1,30 +1,30 @@ package main -import "../lua" +import "github.com/aarzilli/golua/lua" import "unsafe" import "fmt" type Userdata struct { - a,b int + a, b int } func userDataProper(L *lua.State) { - rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{}))); - var ptr *Userdata; - ptr = (*Userdata)(rawptr); - ptr.a = 2; - ptr.b = 3; + rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{}))) + var ptr *Userdata + ptr = (*Userdata)(rawptr) + ptr.a = 2 + ptr.b = 3 - fmt.Println(ptr); + fmt.Println(ptr) - rawptr2 := L.ToUserdata(-1); - ptr2 := (*Userdata)(rawptr2); + rawptr2 := L.ToUserdata(-1) + ptr2 := (*Userdata)(rawptr2) - fmt.Println(ptr2); + fmt.Println(ptr2) } func example_function(L *lua.State) int { - fmt.Println("Heeeeelllllooooooooooo nuuurse!!!!"); + fmt.Println("Heeeeelllllooooooooooo nuuurse!!!!") return 0 } @@ -64,22 +64,22 @@ func goDefinedObjects(L *lua.State) { /* This code demonstrates access and assignment to a field of a go object */ L.MustDoString("print('AField of t is: ' .. t.AField .. ' before assignment');") - L.MustDoString("t.AField = 10;"); - L.MustDoString("print('AField of t is: ' .. t.AField .. ' after assignment');"); + L.MustDoString("t.AField = 10;") + L.MustDoString("print('AField of t is: ' .. t.AField .. ' after assignment');") } func main() { L := lua.NewState() defer L.Close() - L.OpenLibs(); + L.OpenLibs() /* - This function stores a go object inside Lua VM + This function stores a go object inside Lua VM */ userDataProper(L) /* - This function demonstrates exposing a function implemented in go to interpreted Lua code + This function demonstrates exposing a function implemented in go to interpreted Lua code */ goDefinedFunctions(L) diff --git a/example/panic.go b/example/panic.go deleted file mode 100644 index 1fc3f209..00000000 --- a/example/panic.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import "../lua" -import "fmt" - -func test(L *lua.State) int { - fmt.Println("hello world! from go!"); - return 0; -} - -func main() { - - var L *lua.State; - - L = lua.NewState(); - defer L.Close() - L.OpenLibs(); - - currentPanicf := L.AtPanic(nil); - currentPanicf = L.AtPanic(currentPanicf); - newPanic := func(L1 *lua.State) int { - fmt.Println("I AM PANICKING!!!", currentPanicf); - if currentPanicf != nil { - return currentPanicf(L1); - } - - return 1; - } - - L.AtPanic(newPanic); - - //force a panic - L.PushNil(); - L.Call(0,0); - - fmt.Println("End") -} diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..9a21e994 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/aarzilli/golua + +go 1.15 From 4563e621466f7275d96e596282b258a368719bdb Mon Sep 17 00:00:00 2001 From: aarzilli Date: Mon, 3 Aug 2020 16:46:44 +0200 Subject: [PATCH 078/100] fix references to example directory --- README.md | 2 +- lua/lua_test.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 031c29f4..6b96080b 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If your linux system uses "lua-5.1" as the shared object name for lua (for examp You can then try to run the examples: - $ cd /usr/local/go/src/pkg/github.com/aarzilli/golua/example/ + $ cd /usr/local/go/src/pkg/github.com/aarzilli/golua/_example/ $ go run basic.go $ go run alloc.go $ go run panic.go diff --git a/lua/lua_test.go b/lua/lua_test.go index 167a745e..a20d16ba 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -336,7 +336,7 @@ func TestStackTrace(t *testing.T) { defer L.Close() L.OpenLibs() - err := L.DoFile("../example/calls.lua") + err := L.DoFile("../_example/calls.lua") if err == nil { t.Fatal("No error returned from the execution of calls.lua") } @@ -387,7 +387,7 @@ func TestDumpAndLoad(t *testing.T) { L := NewState() defer L.Close() L.OpenLibs() - + loadret := L.LoadString(`print("msg from dump_and_load_test")`) if loadret != 0 { t.Fatalf("LoadString error: %v", loadret) From 7f78a3b61a8b21e46ea63e4e94a1d0d42fe1176c Mon Sep 17 00:00:00 2001 From: aarzilli Date: Tue, 25 Aug 2020 16:31:57 +0200 Subject: [PATCH 079/100] merge branches lua5.2 and lua5.3 into master Use build tags to select the version of lua to use. --- .travis.yml | 6 +- README.md | 31 +- _example/alloc.go | 2 +- _example/basic.go | 2 +- _example/quickstart.go | 2 +- lua/c-golua.c | 97 ---- lua/golua.go | 10 +- lua/golua_c_lua51.go | 204 +++++++ lua/golua_c_lua52.go | 225 ++++++++ lua/golua_c_lua53.go | 227 ++++++++ lua/lauxlib.go | 2 +- lua/lua.go | 100 +--- lua/{lua => lua51}/dummy.go | 0 lua/{lua => lua51}/lauxlib.h | 0 lua/{lua => lua51}/lua.h | 0 lua/{lua => lua51}/luaconf.h | 0 lua/{lua => lua51}/lualib.h | 0 lua/lua52/dummy.go | 7 + lua/lua52/lauxlib.h | 212 +++++++ lua/lua52/lua.h | 444 ++++++++++++++ lua/lua52/luaconf.h | 551 ++++++++++++++++++ lua/lua52/lualib.h | 55 ++ lua/lua53/dummy.go | 7 + lua/lua53/lauxlib.h | 256 +++++++++ lua/lua53/lua.h | 486 ++++++++++++++++ lua/lua53/luaconf.h | 763 +++++++++++++++++++++++++ lua/lua53/lualib.h | 58 ++ lua/{lua_defs.go => lua_defs_lua51.go} | 2 + lua/lua_defs_lua52.go | 70 +++ lua/lua_defs_lua53.go | 70 +++ lua/lua_test.go | 2 +- 31 files changed, 3686 insertions(+), 205 deletions(-) create mode 100644 lua/golua_c_lua51.go create mode 100644 lua/golua_c_lua52.go create mode 100644 lua/golua_c_lua53.go rename lua/{lua => lua51}/dummy.go (100%) rename lua/{lua => lua51}/lauxlib.h (100%) rename lua/{lua => lua51}/lua.h (100%) rename lua/{lua => lua51}/luaconf.h (100%) rename lua/{lua => lua51}/lualib.h (100%) create mode 100644 lua/lua52/dummy.go create mode 100644 lua/lua52/lauxlib.h create mode 100644 lua/lua52/lua.h create mode 100644 lua/lua52/luaconf.h create mode 100644 lua/lua52/lualib.h create mode 100644 lua/lua53/dummy.go create mode 100644 lua/lua53/lauxlib.h create mode 100644 lua/lua53/lua.h create mode 100644 lua/lua53/luaconf.h create mode 100644 lua/lua53/lualib.h rename lua/{lua_defs.go => lua_defs_lua51.go} (98%) create mode 100644 lua/lua_defs_lua52.go create mode 100644 lua/lua_defs_lua53.go diff --git a/.travis.yml b/.travis.yml index 4f5ccae9..a8e5c149 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,8 @@ before_install: - sudo apt-get install -y liblua5.2-dev - sudo apt-get install -y liblua5.3-dev install: true -script: go test -v github.com/aarzilli/golua/lua +script: + - go test -v github.com/aarzilli/golua/lua + - go test -v -tags lua52 github.com/aarzilli/golua/lua + - go test -v -tags lua53 github.com/aarzilli/golua/lua + diff --git a/README.md b/README.md index 6b96080b..9e5ceede 100644 --- a/README.md +++ b/README.md @@ -5,26 +5,28 @@ Go Bindings for the lua C API Simplest way to install: - # go get -u github.com/aarzilli/golua/lua - -Will work as long as your compiler can find a shared object called lua5.1 on linux, or lua anywhere else. -If your linux system uses "lua" as the shared object name for lua (for example, Fedora Core does this) you can install using: - - # go get -u -tags llua github.com/aarzilli/golua/lua - -If your linux system uses "lua-5.1" as the shared object name for lua (for example, some versions of CentOS do this) you can install using: - - # go get -u -tags lluadash5.1 github.com/aarzilli/golua/lua - + # go get github.com/aarzilli/golua/lua You can then try to run the examples: - $ cd /usr/local/go/src/pkg/github.com/aarzilli/golua/_example/ + $ cd golua/_example/ $ go run basic.go $ go run alloc.go $ go run panic.go $ go run userdata.go +This library is configured using build tags. By default it will look for a library (or "shared object") called: + +* lua5.1 on Linux and macOS +* lua on Windows +* lua-5.1 on FreeBSD + +If this doesn't work `-tags luadash5.1` can be used to force `lua-5.1`, and `-tags llua` can be used to force `lua`. + +If you want to statically link to liblua.a you can do that with `-tags luaaa`. Luajit can also be used by specifying `-tags luajit`. + +The library uses lua5.1 by default but also supports lua5.2 by specifying `-tags lua52` and lua5.3 by specifying `-tags lua53`. + QUICK START --------------------- @@ -40,7 +42,7 @@ Lua's Virtual Machine is stack based, you can call lua functions like this: ```go // push "print" function on the stack -L.GetField(lua.LUA_GLOBALSINDEX, "print") +L.GetGlobal("print") // push the string "Hello World!" on the stack L.PushString("Hello World!") // call print with one argument, expecting no results @@ -109,8 +111,7 @@ ON THREADS AND COROUTINES ODDS AND ENDS --------------------- -* Support for lua 5.2 is in the lua5.2 branch, this branch only supports lua5.1. -* Support for lua 5.3 is in the lua5.3 branch. +* If you want to build against lua5.2 or lua5.3 use the build tags lua52 or lua53 * Compiling from source yields only a static link library (liblua.a), you can either produce the dynamic link library on your own or use the `luaa` build tag. LUAJIT diff --git a/_example/alloc.go b/_example/alloc.go index 06997db4..cd3b437d 100644 --- a/_example/alloc.go +++ b/_example/alloc.go @@ -46,7 +46,7 @@ func main() { L.SetAllocf(A2) for i := 0; i < 10; i++ { - L.GetField(lua.LUA_GLOBALSINDEX, "print") + L.GetGlobal("print") L.PushString("Hello World!") L.Call(1, 0) } diff --git a/_example/basic.go b/_example/basic.go index 38789de5..28f766d6 100644 --- a/_example/basic.go +++ b/_example/basic.go @@ -23,7 +23,7 @@ func main() { defer L.Close() L.OpenLibs() - L.GetField(lua.LUA_GLOBALSINDEX, "print") + L.GetGlobal("print") L.PushString("Hello World!") L.Call(1, 0) diff --git a/_example/quickstart.go b/_example/quickstart.go index c20a3ac8..bffca02f 100644 --- a/_example/quickstart.go +++ b/_example/quickstart.go @@ -14,7 +14,7 @@ func main() { defer L.Close() L.OpenLibs() - L.GetField(lua.LUA_GLOBALSINDEX, "print") + L.GetGlobal("print") L.PushString("Hello World!") L.Call(1, 0) diff --git a/lua/c-golua.c b/lua/c-golua.c index 6db57175..853fe9ca 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -13,11 +13,6 @@ static const char GoStateRegistryKey = 'k'; //golua registry key static const char PanicFIDRegistryKey = 'k'; -typedef struct _chunk { - int size; // chunk size - char *buffer; // chunk data - char* toread; // chunk to read -} chunk; /* taken from lua5.2 source */ void *testudata(lua_State *L, int ud, const char *tname) @@ -151,56 +146,6 @@ void clua_setgostate(lua_State* L, size_t gostateindex) lua_settable(L, LUA_REGISTRYINDEX); } -static int writer (lua_State *L, const void* b, size_t size, void* B) { - static int count=0; - (void)L; - luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); - return 0; -} - -// dump function chunk from luaL_loadstring -int dump_chunk (lua_State *L) { - luaL_Buffer b; - luaL_checktype(L, -1, LUA_TFUNCTION); - lua_settop(L, -1); - luaL_buffinit(L,&b); - int errno; - errno = lua_dump(L, writer, &b); - if (errno != 0){ - return luaL_error(L, "unable to dump given function, errno:%d", errno); - } - luaL_pushresult(&b); - return 0; -} - -static const char * reader (lua_State *L, void *ud, size_t *sz) { - chunk *ck = (chunk *)ud; - if (ck->size > LUAL_BUFFERSIZE) { - ck->size -= LUAL_BUFFERSIZE; - *sz = LUAL_BUFFERSIZE; - ck->toread = ck->buffer; - ck->buffer += LUAL_BUFFERSIZE; - }else{ - *sz = ck->size; - ck->toread = ck->buffer; - ck->size = 0; - } - return ck->toread; -} - -// load function chunk dumped from dump_chunk -int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { - chunk ck; - ck.buffer = b; - ck.size = size; - int errno; - errno = lua_load(L, reader, &ck, chunk_name); - if (errno != 0) { - return luaL_error(L, "unable to load chunk, errno: %d", errno); - } - return 0; -} - /* called when lua code attempts to access a field of a published go object */ int interface_index_callback(lua_State *L) { @@ -394,48 +339,6 @@ void clua_openbase(lua_State* L) clua_hide_pcall(L); } -void clua_openio(lua_State* L) -{ - lua_pushcfunction(L,&luaopen_io); - lua_pushstring(L,"io"); - lua_call(L, 1, 0); -} - -void clua_openmath(lua_State* L) -{ - lua_pushcfunction(L,&luaopen_math); - lua_pushstring(L,"math"); - lua_call(L, 1, 0); -} - -void clua_openpackage(lua_State* L) -{ - lua_pushcfunction(L,&luaopen_package); - lua_pushstring(L,"package"); - lua_call(L, 1, 0); -} - -void clua_openstring(lua_State* L) -{ - lua_pushcfunction(L,&luaopen_string); - lua_pushstring(L,"string"); - lua_call(L, 1, 0); -} - -void clua_opentable(lua_State* L) -{ - lua_pushcfunction(L,&luaopen_table); - lua_pushstring(L,"table"); - lua_call(L, 1, 0); -} - -void clua_openos(lua_State* L) -{ - lua_pushcfunction(L,&luaopen_os); - lua_pushstring(L,"os"); - lua_call(L, 1, 0); -} - void clua_hook_function(lua_State *L, lua_Debug *ar) { lua_checkstack(L, 2); diff --git a/lua/golua.go b/lua/golua.go index 381e2c1f..06d275e9 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -1,7 +1,9 @@ package lua /* -#cgo CFLAGS: -I ${SRCDIR}/lua +#cgo !lua52,!lua53 CFLAGS: -I ${SRCDIR}/lua51 +#cgo lua52 CFLAGS: -I ${SRCDIR}/lua52 +#cgo lua53 CFLAGS: -I ${SRCDIR}/lua53 #include #include @@ -111,7 +113,7 @@ func golua_interface_newindex_callback(gostateindex uintptr, iid uint, field_nam fallthrough case reflect.Int64: if luatype == LUA_TNUMBER { - fval.SetInt(int64(C.lua_tointeger(L.s, 3))) + fval.SetInt(int64(luaToInteger(L.s, 3))) return 1 } else { L.PushString("Wrong assignment to field " + field_name) @@ -128,7 +130,7 @@ func golua_interface_newindex_callback(gostateindex uintptr, iid uint, field_nam fallthrough case reflect.Uint64: if luatype == LUA_TNUMBER { - fval.SetUint(uint64(C.lua_tointeger(L.s, 3))) + fval.SetUint(uint64(luaToInteger(L.s, 3))) return 1 } else { L.PushString("Wrong assignment to field " + field_name) @@ -148,7 +150,7 @@ func golua_interface_newindex_callback(gostateindex uintptr, iid uint, field_nam fallthrough case reflect.Float64: if luatype == LUA_TNUMBER { - fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) + fval.SetFloat(float64(luaToNumber(L.s, 3))) return 1 } else { L.PushString("Wrong assignment to field " + field_name) diff --git a/lua/golua_c_lua51.go b/lua/golua_c_lua51.go new file mode 100644 index 00000000..5d242cb9 --- /dev/null +++ b/lua/golua_c_lua51.go @@ -0,0 +1,204 @@ +//+build !lua52,!lua53 + +package lua + +/* +#include +#include +#include +#include + +typedef struct _chunk { + int size; // chunk size + char *buffer; // chunk data + char* toread; // chunk to read +} chunk; + +static const char * reader (lua_State *L, void *ud, size_t *sz) { + chunk *ck = (chunk *)ud; + if (ck->size > LUAL_BUFFERSIZE) { + ck->size -= LUAL_BUFFERSIZE; + *sz = LUAL_BUFFERSIZE; + ck->toread = ck->buffer; + ck->buffer += LUAL_BUFFERSIZE; + }else{ + *sz = ck->size; + ck->toread = ck->buffer; + ck->size = 0; + } + return ck->toread; +} + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + static int count=0; + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 0; +} + +// load function chunk dumped from dump_chunk +int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { + chunk ck; + ck.buffer = b; + ck.size = size; + int errno; + errno = lua_load(L, reader, &ck, chunk_name); + if (errno != 0) { + return luaL_error(L, "unable to load chunk, errno: %d", errno); + } + return 0; +} + +void clua_openio(lua_State* L) +{ + lua_pushcfunction(L,&luaopen_io); + lua_pushstring(L,"io"); + lua_call(L, 1, 0); +} + +void clua_openmath(lua_State* L) +{ + lua_pushcfunction(L,&luaopen_math); + lua_pushstring(L,"math"); + lua_call(L, 1, 0); +} + +void clua_openpackage(lua_State* L) +{ + lua_pushcfunction(L,&luaopen_package); + lua_pushstring(L,"package"); + lua_call(L, 1, 0); +} + +void clua_openstring(lua_State* L) +{ + lua_pushcfunction(L,&luaopen_string); + lua_pushstring(L,"string"); + lua_call(L, 1, 0); +} + +void clua_opentable(lua_State* L) +{ + lua_pushcfunction(L,&luaopen_table); + lua_pushstring(L,"table"); + lua_call(L, 1, 0); +} + +void clua_openos(lua_State* L) +{ + lua_pushcfunction(L,&luaopen_os); + lua_pushstring(L,"os"); + lua_call(L, 1, 0); +} + +// dump function chunk from luaL_loadstring +int dump_chunk (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_settop(L, -1); + luaL_buffinit(L,&b); + int errno; + errno = lua_dump(L, writer, &b); + if (errno != 0){ + return luaL_error(L, "unable to dump given function, errno:%d", errno); + } + luaL_pushresult(&b); + return 0; +} +*/ +import "C" + +import "unsafe" + +func luaToInteger(s *C.lua_State, n C.int) C.long { + return C.lua_tointeger(s, n) +} + +func luaToNumber(s *C.lua_State, n C.int) C.double { + return C.lua_tonumber(s, n) +} + +func lualLoadFile(s *C.lua_State, filename *C.char) C.int { + return C.luaL_loadfile(s, filename) +} + +// lua_equal +func (L *State) Equal(index1, index2 int) bool { + return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 +} + +// lua_getfenv +func (L *State) GetfEnv(index int) { + C.lua_getfenv(L.s, C.int(index)) +} + +// lua_lessthan +func (L *State) LessThan(index1, index2 int) bool { + return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 +} + +// lua_setfenv +func (L *State) SetfEnv(index int) { + C.lua_setfenv(L.s, C.int(index)) +} + +func (L *State) ObjLen(index int) uint { + return uint(C.lua_objlen(L.s, C.int(index))) +} + +// lua_tointeger +func (L *State) ToInteger(index int) int { + return int(C.lua_tointeger(L.s, C.int(index))) +} + +// lua_tonumber +func (L *State) ToNumber(index int) float64 { + return float64(C.lua_tonumber(L.s, C.int(index))) +} + +// lua_yield +func (L *State) Yield(nresults int) int { + return int(C.lua_yield(L.s, C.int(nresults))) +} + +func (L *State) pcall(nargs, nresults, errfunc int) int { + return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) +} + +// Pushes on the stack the value of a global variable (lua_getglobal) +func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } + +// lua_resume +func (L *State) Resume(narg int) int { + return int(C.lua_resume(L.s, C.int(narg))) +} + +// lua_setglobal +func (L *State) SetGlobal(name string) { + Cname := C.CString(name) + defer C.free(unsafe.Pointer(Cname)) + C.lua_setfield(L.s, C.int(LUA_GLOBALSINDEX), Cname) +} + +// lua_insert +func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } + +// lua_remove +func (L *State) Remove(index int) { + C.lua_remove(L.s, C.int(index)) +} + +// lua_replace +func (L *State) Replace(index int) { + C.lua_replace(L.s, C.int(index)) +} + +// lua_rawgeti +func (L *State) RawGeti(index int, n int) { + C.lua_rawgeti(L.s, C.int(index), C.int(n)) +} + +// lua_rawseti +func (L *State) RawSeti(index int, n int) { + C.lua_rawseti(L.s, C.int(index), C.int(n)) +} diff --git a/lua/golua_c_lua52.go b/lua/golua_c_lua52.go new file mode 100644 index 00000000..3961ff19 --- /dev/null +++ b/lua/golua_c_lua52.go @@ -0,0 +1,225 @@ +//+build lua52 + +package lua + +/* +#include +#include +#include +#include + +typedef struct _chunk { + int size; // chunk size + char *buffer; // chunk data + char* toread; // chunk to read +} chunk; + +static const char * reader (lua_State *L, void *ud, size_t *sz) { + chunk *ck = (chunk *)ud; + if (ck->size > LUAL_BUFFERSIZE) { + ck->size -= LUAL_BUFFERSIZE; + *sz = LUAL_BUFFERSIZE; + ck->toread = ck->buffer; + ck->buffer += LUAL_BUFFERSIZE; + }else{ + *sz = ck->size; + ck->toread = ck->buffer; + ck->size = 0; + } + return ck->toread; +} + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + static int count=0; + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 0; +} + +// load function chunk dumped from dump_chunk +int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { + chunk ck; + ck.buffer = b; + ck.size = size; + int errno; + errno = lua_load(L, reader, &ck, chunk_name, NULL); + if (errno != 0) { + return luaL_error(L, "unable to load chunk, errno: %d", errno); + } + return 0; +} + +void clua_openio(lua_State* L) +{ + luaL_requiref(L, "io", &luaopen_io, 1); + lua_pop(L, 1); +} + +void clua_openmath(lua_State* L) +{ + luaL_requiref(L, "math", &luaopen_math, 1); + lua_pop(L, 1); +} + +void clua_openpackage(lua_State* L) +{ + luaL_requiref(L, "package", &luaopen_package, 1); + lua_pop(L, 1); +} + +void clua_openstring(lua_State* L) +{ + luaL_requiref(L, "string", &luaopen_string, 1); + lua_pop(L, 1); +} + +void clua_opentable(lua_State* L) +{ + luaL_requiref(L, "table", &luaopen_table, 1); + lua_pop(L, 1); +} + +void clua_openos(lua_State* L) +{ + luaL_requiref(L, "os", &luaopen_os, 1); + lua_pop(L, 1); +} + +void clua_opencoroutine(lua_State *L) +{ + luaL_requiref(L, "coroutine", &luaopen_coroutine, 1); + lua_pop(L, 1); +} + +void clua_opendebug(lua_State *L) +{ + luaL_requiref(L, "debug", &luaopen_debug, 1); + lua_pop(L, 1); +} + +void clua_openbit32(lua_State *L) +{ + luaL_requiref(L, "bit32", &luaopen_bit32, 1); + lua_pop(L, 1); +} + +// dump function chunk from luaL_loadstring +int dump_chunk (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_settop(L, -1); + luaL_buffinit(L,&b); + int errno; + errno = lua_dump(L, writer, &b); + if (errno != 0){ + return luaL_error(L, "unable to dump given function, errno:%d", errno); + } + luaL_pushresult(&b); + return 0; +} +*/ +import "C" + +import "unsafe" + +func luaToInteger(s *C.lua_State, n C.int) C.long { + return C.lua_tointegerx(s, n, nil) +} + +func luaToNumber(s *C.lua_State, n C.int) C.double { + return C.lua_tonumberx(s, n, nil) +} + +func lualLoadFile(s *C.lua_State, filename *C.char) C.int { + return C.luaL_loadfilex(s, filename, nil) +} + +// lua_equal +func (L *State) Equal(index1, index2 int) bool { + return C.lua_compare(L.s, C.int(index1), C.int(index2), C.LUA_OPEQ) == 1 +} + +// lua_lessthan +func (L *State) LessThan(index1, index2 int) bool { + return C.lua_compare(L.s, C.int(index1), C.int(index2), C.LUA_OPLT) == 1 +} + +func (L *State) ObjLen(index int) uint { + return uint(C.lua_rawlen(L.s, C.int(index))) +} + +// lua_tointeger +func (L *State) ToInteger(index int) int { + return int(C.lua_tointegerx(L.s, C.int(index), nil)) +} + +// lua_tonumber +func (L *State) ToNumber(index int) float64 { + return float64(C.lua_tonumberx(L.s, C.int(index), nil)) +} + +// lua_yield +func (L *State) Yield(nresults int) int { + return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) +} + +func (L *State) pcall(nargs, nresults, errfunc int) int { + return int(C.lua_pcallk(L.s, C.int(nargs), C.int(nresults), C.int(errfunc), 0, nil)) +} + +// Pushes on the stack the value of a global variable (lua_getglobal) +func (L *State) GetGlobal(name string) { + Ck := C.CString(name) + defer C.free(unsafe.Pointer(Ck)) + C.lua_getglobal(L.s, Ck) +} + +// lua_resume +func (L *State) Resume(narg int) int { + return int(C.lua_resume(L.s, nil, C.int(narg))) +} + +// lua_setglobal +func (L *State) SetGlobal(name string) { + Cname := C.CString(name) + defer C.free(unsafe.Pointer(Cname)) + C.lua_setglobal(L.s, Cname) +} + +// Calls luaopen_debug +func (L *State) OpenDebug() { + C.clua_opendebug(L.s) +} + +// Calls luaopen_bit32 +func (L *State) OpenBit32() { + C.clua_openbit32(L.s) +} + +// Calls luaopen_coroutine +func (L *State) OpenCoroutine() { + C.clua_opencoroutine(L.s) +} + +// lua_insert +func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } + +// lua_remove +func (L *State) Remove(index int) { + C.lua_remove(L.s, C.int(index)) +} + +// lua_replace +func (L *State) Replace(index int) { + C.lua_replace(L.s, C.int(index)) +} + +// lua_rawgeti +func (L *State) RawGeti(index int, n int) { + C.lua_rawgeti(L.s, C.int(index), C.int(n)) +} + +// lua_rawseti +func (L *State) RawSeti(index int, n int) { + C.lua_rawseti(L.s, C.int(index), C.int(n)) +} diff --git a/lua/golua_c_lua53.go b/lua/golua_c_lua53.go new file mode 100644 index 00000000..62b9dbe5 --- /dev/null +++ b/lua/golua_c_lua53.go @@ -0,0 +1,227 @@ +//+build lua53 + +package lua + +/* +#include +#include +#include +#include + +typedef struct _chunk { + int size; // chunk size + char *buffer; // chunk data + char* toread; // chunk to read +} chunk; + +static const char * reader (lua_State *L, void *ud, size_t *sz) { + chunk *ck = (chunk *)ud; + if (ck->size > LUAL_BUFFERSIZE) { + ck->size -= LUAL_BUFFERSIZE; + *sz = LUAL_BUFFERSIZE; + ck->toread = ck->buffer; + ck->buffer += LUAL_BUFFERSIZE; + }else{ + *sz = ck->size; + ck->toread = ck->buffer; + ck->size = 0; + } + return ck->toread; +} + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + static int count=0; + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 0; +} + +// load function chunk dumped from dump_chunk +int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { + chunk ck; + ck.buffer = b; + ck.size = size; + int errno; + errno = lua_load(L, reader, &ck, chunk_name, NULL); + if (errno != 0) { + return luaL_error(L, "unable to load chunk, errno: %d", errno); + } + return 0; +} + +void clua_openio(lua_State* L) +{ + luaL_requiref(L, "io", &luaopen_io, 1); + lua_pop(L, 1); +} + +void clua_openmath(lua_State* L) +{ + luaL_requiref(L, "math", &luaopen_math, 1); + lua_pop(L, 1); +} + +void clua_openpackage(lua_State* L) +{ + luaL_requiref(L, "package", &luaopen_package, 1); + lua_pop(L, 1); +} + +void clua_openstring(lua_State* L) +{ + luaL_requiref(L, "string", &luaopen_string, 1); + lua_pop(L, 1); +} + +void clua_opentable(lua_State* L) +{ + luaL_requiref(L, "table", &luaopen_table, 1); + lua_pop(L, 1); +} + +void clua_openos(lua_State* L) +{ + luaL_requiref(L, "os", &luaopen_os, 1); + lua_pop(L, 1); +} + +void clua_opencoroutine(lua_State *L) +{ + luaL_requiref(L, "coroutine", &luaopen_coroutine, 1); + lua_pop(L, 1); +} + +void clua_opendebug(lua_State *L) +{ + luaL_requiref(L, "debug", &luaopen_debug, 1); + lua_pop(L, 1); +} + +void clua_openbit32(lua_State *L) +{ + luaL_requiref(L, "bit32", &luaopen_bit32, 1); + lua_pop(L, 1); +} + +// dump function chunk from luaL_loadstring +int dump_chunk (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_settop(L, -1); + luaL_buffinit(L,&b); + int errno; + errno = lua_dump(L, writer, &b, 0); + if (errno != 0){ + return luaL_error(L, "unable to dump given function, errno:%d", errno); + } + luaL_pushresult(&b); + return 0; +} +*/ +import "C" + +import "unsafe" + +func luaToInteger(s *C.lua_State, n C.int) C.longlong { + return C.lua_tointegerx(s, n, nil) +} + +func luaToNumber(s *C.lua_State, n C.int) C.double { + return C.lua_tonumberx(s, n, nil) +} + +func lualLoadFile(s *C.lua_State, filename *C.char) C.int { + return C.luaL_loadfilex(s, filename, nil) +} + +// lua_equal +func (L *State) Equal(index1, index2 int) bool { + return C.lua_compare(L.s, C.int(index1), C.int(index2), C.LUA_OPEQ) == 1 +} + +// lua_lessthan +func (L *State) LessThan(index1, index2 int) bool { + return C.lua_compare(L.s, C.int(index1), C.int(index2), C.LUA_OPLT) == 1 +} + +func (L *State) ObjLen(index int) uint { + return uint(C.lua_rawlen(L.s, C.int(index))) +} + +// lua_tointeger +func (L *State) ToInteger(index int) int { + return int(C.lua_tointegerx(L.s, C.int(index), nil)) +} + +// lua_tonumber +func (L *State) ToNumber(index int) float64 { + return float64(C.lua_tonumberx(L.s, C.int(index), nil)) +} + +// lua_yield +func (L *State) Yield(nresults int) int { + return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) +} + +func (L *State) pcall(nargs, nresults, errfunc int) int { + return int(C.lua_pcallk(L.s, C.int(nargs), C.int(nresults), C.int(errfunc), 0, nil)) +} + +// Pushes on the stack the value of a global variable (lua_getglobal) +func (L *State) GetGlobal(name string) { + Ck := C.CString(name) + defer C.free(unsafe.Pointer(Ck)) + C.lua_getglobal(L.s, Ck) +} + +// lua_resume +func (L *State) Resume(narg int) int { + return int(C.lua_resume(L.s, nil, C.int(narg))) +} + +// lua_setglobal +func (L *State) SetGlobal(name string) { + Cname := C.CString(name) + defer C.free(unsafe.Pointer(Cname)) + C.lua_setglobal(L.s, Cname) +} + +// Calls luaopen_debug +func (L *State) OpenDebug() { + C.clua_opendebug(L.s) +} + +// Calls luaopen_bit32 +func (L *State) OpenBit32() { + C.clua_openbit32(L.s) +} + +// Calls luaopen_coroutine +func (L *State) OpenCoroutine() { + C.clua_opencoroutine(L.s) +} + +// lua_insert +func (L *State) Insert(index int) { C.lua_rotate(L.s, C.int(index), 1) } + +// lua_remove +func (L *State) Remove(index int) { + C.lua_rotate(L.s, C.int(index), -1) + C.lua_settop(L.s, C.int(-2)) +} + +// lua_replace +func (L *State) Replace(index int) { + C.lua_copy(L.s, -1, C.int(index)) + C.lua_settop(L.s, -2) +} + +// lua_rawgeti +func (L *State) RawGeti(index int, n int) { + C.lua_rawgeti(L.s, C.int(index), C.longlong(n)) +} + +// lua_rawseti +func (L *State) RawSeti(index int, n int) { + C.lua_rawseti(L.s, C.int(index), C.longlong(n)) +} diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 57dee754..343da926 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -146,7 +146,7 @@ func (L *State) GSub(s string, p string, r string) string { func (L *State) LoadFile(filename string) int { Cfilename := C.CString(filename) defer C.free(unsafe.Pointer(Cfilename)) - return int(C.luaL_loadfile(L.s, Cfilename)) + return int(lualLoadFile(L.s, Cfilename)) } // luaL_loadstring diff --git a/lua/lua.go b/lua/lua.go index 0bf5bb92..9da1ec71 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -6,14 +6,27 @@ package lua /* -#cgo CFLAGS: -I ${SRCDIR}/lua +#cgo !lua52,!lua53 CFLAGS: -I ${SRCDIR}/lua51 +#cgo lua52 CFLAGS: -I ${SRCDIR}/lua52 +#cgo lua53 CFLAGS: -I ${SRCDIR}/lua53 #cgo llua LDFLAGS: -llua + #cgo luaa LDFLAGS: -llua -lm -ldl #cgo luajit LDFLAGS: -lluajit-5.1 #cgo lluadash5.1 LDFLAGS: -llua-5.1 -#cgo linux,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.1 -#cgo darwin,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.1 -#cgo freebsd,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.1 + +#cgo linux,!lua52,!lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.1 +#cgo linux,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.2 +#cgo linux,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.3 + +#cgo darwin,!lua52,!lua53,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.1 +#cgo darwin,lua52,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.2 +#cgo darwin,lua53,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.3 + +#cgo freebsd,!lua52,!lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.1 +#cgo freebsd,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.2 +#cgo freebsd,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.3 + #cgo windows,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 #include @@ -182,10 +195,6 @@ func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { return nil } -func (L *State) pcall(nargs, nresults, errfunc int) int { - return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) -} - func (L *State) callEx(nargs, nresults int, catch bool) (err error) { if catch { defer func() { @@ -244,17 +253,9 @@ func (L *State) CreateTable(narr int, nrec int) { C.lua_createtable(L.s, C.int(narr), C.int(nrec)) } -// lua_equal -func (L *State) Equal(index1, index2 int) bool { - return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 -} - // lua_gc func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } -// lua_getfenv -func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } - // lua_getfield func (L *State) GetField(index int, k string) { Ck := C.CString(k) @@ -262,9 +263,6 @@ func (L *State) GetField(index int, k string) { C.lua_getfield(L.s, C.int(index), Ck) } -// Pushes on the stack the value of a global variable (lua_getglobal) -func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } - // lua_getmetatable func (L *State) GetMetaTable(index int) bool { return C.lua_getmetatable(L.s, C.int(index)) != 0 @@ -276,9 +274,6 @@ func (L *State) GetTable(index int) { C.lua_gettable(L.s, C.int(index)) } // lua_gettop func (L *State) GetTop() int { return int(C.lua_gettop(L.s)) } -// lua_insert -func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } - // Returns true if lua_type == LUA_TBOOLEAN func (L *State) IsBoolean(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TBOOLEAN @@ -332,11 +327,6 @@ func (L *State) IsThread(index int) bool { // lua_isuserdata func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int(index)) == 1 } -// lua_lessthan -func (L *State) LessThan(index1, index2 int) bool { - return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 -} - // Creates a new lua interpreter state with the given allocation function func NewStateAlloc(f Alloc) *State { ls := C.clua_newstate(unsafe.Pointer(&f)) @@ -363,10 +353,6 @@ func (L *State) Next(index int) int { } // lua_objlen -func (L *State) ObjLen(index int) uint { - return uint(C.lua_objlen(L.s, C.int(index))) -} - // lua_pop func (L *State) Pop(n int) { //Why is this implemented this way? I don't get it... @@ -431,52 +417,22 @@ func (L *State) RawGet(index int) { C.lua_rawget(L.s, C.int(index)) } -// lua_rawgeti -func (L *State) RawGeti(index int, n int) { - C.lua_rawgeti(L.s, C.int(index), C.int(n)) -} - // lua_rawset func (L *State) RawSet(index int) { C.lua_rawset(L.s, C.int(index)) } -// lua_rawseti -func (L *State) RawSeti(index int, n int) { - C.lua_rawseti(L.s, C.int(index), C.int(n)) -} - // Registers a Go function as a global variable func (L *State) Register(name string, f LuaGoFunction) { L.PushGoFunction(f) L.SetGlobal(name) } -// lua_remove -func (L *State) Remove(index int) { - C.lua_remove(L.s, C.int(index)) -} - -// lua_replace -func (L *State) Replace(index int) { - C.lua_replace(L.s, C.int(index)) -} - -// lua_resume -func (L *State) Resume(narg int) int { - return int(C.lua_resume(L.s, C.int(narg))) -} - // lua_setallocf func (L *State) SetAllocf(f Alloc) { C.clua_setallocf(L.s, unsafe.Pointer(&f)) } -// lua_setfenv -func (L *State) SetfEnv(index int) { - C.lua_setfenv(L.s, C.int(index)) -} - // lua_setfield func (L *State) SetField(index int, k string) { Ck := C.CString(k) @@ -484,13 +440,6 @@ func (L *State) SetField(index int, k string) { C.lua_setfield(L.s, C.int(index), Ck) } -// lua_setglobal -func (L *State) SetGlobal(name string) { - Cname := C.CString(name) - defer C.free(unsafe.Pointer(Cname)) - C.lua_setfield(L.s, C.int(LUA_GLOBALSINDEX), Cname) -} - // lua_setmetatable func (L *State) SetMetaTable(index int) { C.lua_setmetatable(L.s, C.int(index)) @@ -553,16 +502,6 @@ func (L *State) ToBytes(index int) []byte { return C.GoBytes(unsafe.Pointer(b), C.int(size)) } -// lua_tointeger -func (L *State) ToInteger(index int) int { - return int(C.lua_tointeger(L.s, C.int(index))) -} - -// lua_tonumber -func (L *State) ToNumber(index int) float64 { - return float64(C.lua_tonumber(L.s, C.int(index))) -} - // lua_topointer func (L *State) ToPointer(index int) uintptr { return uintptr(C.lua_topointer(L.s, C.int(index))) @@ -594,11 +533,6 @@ func XMove(from *State, to *State, n int) { C.lua_xmove(from.s, to.s, C.int(n)) } -// lua_yield -func (L *State) Yield(nresults int) int { - return int(C.lua_yield(L.s, C.int(nresults))) -} - // Restricted library opens // Calls luaopen_base diff --git a/lua/lua/dummy.go b/lua/lua51/dummy.go similarity index 100% rename from lua/lua/dummy.go rename to lua/lua51/dummy.go diff --git a/lua/lua/lauxlib.h b/lua/lua51/lauxlib.h similarity index 100% rename from lua/lua/lauxlib.h rename to lua/lua51/lauxlib.h diff --git a/lua/lua/lua.h b/lua/lua51/lua.h similarity index 100% rename from lua/lua/lua.h rename to lua/lua51/lua.h diff --git a/lua/lua/luaconf.h b/lua/lua51/luaconf.h similarity index 100% rename from lua/lua/luaconf.h rename to lua/lua51/luaconf.h diff --git a/lua/lua/lualib.h b/lua/lua51/lualib.h similarity index 100% rename from lua/lua/lualib.h rename to lua/lua51/lualib.h diff --git a/lua/lua52/dummy.go b/lua/lua52/dummy.go new file mode 100644 index 00000000..651a7971 --- /dev/null +++ b/lua/lua52/dummy.go @@ -0,0 +1,7 @@ +// +build dummy + +// Package lua contains only a C header files. +// +// This Go file is part of a workaround for `go mod vendor`. +// Please see the file dummy.go in the parent directory for more information. +package lua diff --git a/lua/lua52/lauxlib.h b/lua/lua52/lauxlib.h new file mode 100644 index 00000000..ac4d15fb --- /dev/null +++ b/lua/lua52/lauxlib.h @@ -0,0 +1,212 @@ +/* +** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); +#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); +LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); +LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, + lua_Unsigned def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API int (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +#endif + + diff --git a/lua/lua52/lua.h b/lua/lua52/lua.h new file mode 100644 index 00000000..f9800fc0 --- /dev/null +++ b/lua/lua52/lua.h @@ -0,0 +1,444 @@ +/* +** $Id: lua.h,v 1.285 2013/03/15 13:04:22 roberto Exp $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "2" +#define LUA_VERSION_NUM 502 +#define LUA_VERSION_RELEASE "2" + +#define LUA_VERSION "Lua 5.2" +#define LUA_RELEASE "Lua 5.2.2" +#define LUA_COPYRIGHT "Lua 5.2.2 Copyright (C) 1994-2013 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTAGS 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API const lua_Number *(lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_getglobal) (lua_State *L, const char *var); +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getuservalue) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *var); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_getctx) (lua_State *L, int *ctx); + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, + const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, + lua_CFunction k); +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCSETMAJORINC 8 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) +#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_pushglobaltable(L) \ + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2013 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/lua/lua52/luaconf.h b/lua/lua52/luaconf.h new file mode 100644 index 00000000..df802c95 --- /dev/null +++ b/lua/lua52/luaconf.h @@ -0,0 +1,551 @@ +/* +** $Id: luaconf.h,v 1.176 2013/03/16 21:10:18 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef lconfig_h +#define lconfig_h + +#include +#include + + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_WIN /* enable goodies for regular Windows platforms */ +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#endif + + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionality listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#define LUA_USE_GMTIME_R +#endif + + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + + +/* +@@ LUA_ENV is the name of the variable that holds the current +@@ environment, used to access global names. +** CHANGE it if you do not like this name. +*/ +#define LUA_ENV "_ENV" + + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +@* that are not to be exported to outside modules (LUAI_DDEF for +@* definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +#else /* }{ */ +#define LUAI_FUNC extern +#define LUAI_DDEC extern +#define LUAI_DDEF /* empty */ +#endif /* } */ + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ luai_writestring/luai_writeline define how 'print' prints its results. +** They are only used in libraries and the stand-alone program. (The #if +** avoids including 'stdio.h' everywhere.) +*/ +#if defined(LUA_LIB) || defined(lua_c) +#include +#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) +#endif + +/* +@@ luai_writestringerror defines how to print error messages. +** (A format string with one argument is enough for Lua...) +*/ +#define luai_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) + + +/* +@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, +** strings that are internalized. (Cannot be smaller than reserved words +** or tags for metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#define LUAI_MAXSHORTLEN 40 + + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_ALL controls all compatibility options. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_ALL) /* { */ + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#endif /* } */ + +/* }================================================================== */ + + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 /* { */ +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L /* }{ */ +/* int has at least 32 bits */ +#define LUAI_BITSINT 32 +#else /* }{ */ +#error "you must define LUA_BITSINT with number of bits in an integer" +#endif /* } */ + + +/* +@@ LUA_INT32 is an signed integer with exactly 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. Probably you do not need to change +** this. +*/ +#if LUAI_BITSINT >= 32 /* { */ +#define LUA_INT32 int +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else /* }{ */ +/* 16-bit ints */ +#define LUA_INT32 long +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif /* } */ + + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua to consume unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + +/* reserve some space for error handling */ +#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) + + + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. +*/ +#define LUAL_BUFFERSIZE BUFSIZ + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double + +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +#define LUAI_UACNUMBER double + + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +*/ +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ + + +/* +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations +*/ +#define l_mathop(x) (x) + + +/* +@@ lua_str2number converts a decimal numeric string to a number. +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does both conversions. C89, however, has no function +** to convert floating hexadecimal strings to numbers. For these +** systems, you can leave 'lua_strx2number' undefined and Lua will +** provide its own implementation. +*/ +#define lua_str2number(s,p) strtod((s), (p)) + +#if defined(LUA_USE_STRTODHEX) +#define lua_strx2number(s,p) strtod((s), (p)) +#endif + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ + +/* the following operations need the math library */ +#if defined(lobject_c) || defined(lvm_c) +#include +#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) +#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) +#endif + +/* these are quite standard operations */ +#if defined(LUA_CORE) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numdiv(L,a,b) ((a)/(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(L,a,b) ((a)<(b)) +#define luai_numle(L,a,b) ((a)<=(b)) +#define luai_numisnan(L,a) (!luai_numeq((a), (a))) +#endif + + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ +#define LUA_INTEGER ptrdiff_t + +/* +@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. +** It must have at least 32 bits. +*/ +#define LUA_UNSIGNED unsigned LUA_INT32 + + + +/* +** Some tricks with doubles +*/ + +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ +/* +** The next definitions activate some tricks to speed up the +** conversion from doubles to integer types, mainly to LUA_UNSIGNED. +** +@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a +** DirectX idiosyncrasy. +** +@@ LUA_IEEE754TRICK uses a trick that should work on any machine +** using IEEE754 with a 32-bit integer type. +** +@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be +** defined when LUA_INTEGER is a 32-bit integer. +** +@@ LUA_IEEEENDIAN is the endianness of doubles in your machine +** (0 for little endian, 1 for big endian); if not defined, Lua will +** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK). +** +@@ LUA_NANTRICK controls the use of a trick to pack all types into +** a single double value, using NaN values to represent non-number +** values. The trick only works on 32-bit machines (ints and pointers +** are 32-bit values) with numbers represented as IEEE 754-2008 doubles +** with conventional endianess (12345678 or 87654321), in CPUs that do +** not produce signaling NaN values (all NaNs are quiet). +*/ + +/* Microsoft compiler on a Pentium (32 bit) ? */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ + +#define LUA_MSASMTRICK +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + + +/* pentium 32 bits? */ +#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEELL +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 64 bits? */ +#elif defined(__x86_64) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 0 + +#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 1 + +#else /* }{ */ + +/* assume IEEE754 and a 32-bit integer type */ +#define LUA_IEEE754TRICK + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/lua/lua52/lualib.h b/lua/lua52/lualib.h new file mode 100644 index 00000000..9fd126bf --- /dev/null +++ b/lua/lua52/lualib.h @@ -0,0 +1,55 @@ +/* +** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/lua/lua53/dummy.go b/lua/lua53/dummy.go new file mode 100644 index 00000000..651a7971 --- /dev/null +++ b/lua/lua53/dummy.go @@ -0,0 +1,7 @@ +// +build dummy + +// Package lua contains only a C header files. +// +// This Go file is part of a workaround for `go mod vendor`. +// Please see the file dummy.go in the parent directory for more information. +package lua diff --git a/lua/lua53/lauxlib.h b/lua/lua53/lauxlib.h new file mode 100644 index 00000000..0bac2467 --- /dev/null +++ b/lua/lua53/lauxlib.h @@ -0,0 +1,256 @@ +/* +** $Id: lauxlib.h,v 1.128 2014/10/29 16:11:17 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + + +/* extra error code for 'luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + diff --git a/lua/lua53/lua.h b/lua/lua53/lua.h new file mode 100644 index 00000000..6ae3112f --- /dev/null +++ b/lua/lua53/lua.h @@ -0,0 +1,486 @@ +/* +** $Id: lua.h,v 1.328 2015/06/03 13:03:38 roberto Exp $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "1" + +#define LUA_VERSION "Lua 5.3" +#define LUA_RELEASE "Lua 5.3.1" +#define LUA_COPYRIGHT "Lua 5.3.1 Copyright (C) 1994-2015 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) +*/ +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 + + +typedef struct lua_State lua_State; + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTAGS 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API const lua_Number *(lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_rotate) (lua_State *L, int idx, int n); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int n); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API int (lua_getglobal) (lua_State *L, const char *name); +LUA_API int (lua_gettable) (lua_State *L, int idx); +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawget) (lua_State *L, int idx); +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); + +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API int (lua_getuservalue) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *name); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); +LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_isyieldable) (lua_State *L); + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** {============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) + +#define lua_pushglobaltable(L) \ + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) + +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) + +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros for unsigned conversions +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif +/* }============================================================== */ + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2015 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/lua/lua53/luaconf.h b/lua/lua53/luaconf.h new file mode 100644 index 00000000..d1cdc48e --- /dev/null +++ b/lua/lua53/luaconf.h @@ -0,0 +1,763 @@ +/* +** $Id: luaconf.h,v 1.251 2015/05/20 17:39:23 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance compiling it with 32-bit numbers or +** restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You +** can also define LUA_32BITS in the make file, but changing here you +** ensure that all software connected to Lua will be compiled with the +** same configuration. +*/ +/* #define LUA_32BITS */ + + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. +*/ +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ +#endif + + +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ +#endif + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#endif + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS +#endif + + + +/* +@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. +*/ +/* avoid undefined shifts */ +#if ((INT_MAX >> 15) >> 15) >= 1 +#define LUAI_BITSINT 32 +#else +/* 'int' always must have at least 16 bits */ +#define LUAI_BITSINT 16 +#endif + + +/* +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options (if supported +** by your C compiler). The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). +*/ + +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + +#if defined(LUA_32BITS) /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_BITSINT >= 32 /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif defined(LUA_C89_NUMBERS) /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + + +/* +** default configuration for 64-bit Lua ('long long' and 'double') +*/ +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif + +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE +#endif /* } */ + +/* }================================================================== */ + + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +** Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +** C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +/* This defines DEB_HOST_MULTIARCH */ +//#include "lua5.3-deb-multiarch.h" + +#define LUA_ROOT "/usr/local/" +#define LUA_ROOT2 "/usr/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_LDIR2 LUA_ROOT2 "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" +#define LUA_CDIR2 LUA_ROOT2 "lib/" DEB_HOST_MULTIARCH "/lua/" LUA_VDIR "/" +#define LUA_CDIR3 LUA_ROOT2 "lib/lua/" LUA_VDIR "/" + +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + LUA_LDIR2"?.lua;" LUA_LDIR2"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR2"?.so;" LUA_CDIR3"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== +*/ + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#ifdef __cplusplus +#define LUA_API extern "C" +#else +#define LUA_API extern +#endif + +#endif /* } */ + + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +** that are not to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2. +@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_2) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. +*/ +#define LUA_COMPAT_BITLIB + +/* +@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod. +*/ +#define LUA_COMPAT_IPAIRS + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +*/ +#define LUA_COMPAT_APIINTCASTS + +#endif /* } */ + + +#if defined(LUA_COMPAT_5_1) /* { */ + +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#endif /* } */ + + +/* +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. +*/ +/* #define LUA_COMPAT_FLOATSTRING */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers. +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUA_NUMBER is the floating-point type used by Lua. +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@@ over a floating number. +@@ l_mathlim(x) corrects limit name 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ lua_str2number converts a decimal numeric string to a number. +*/ + +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ + +#define LUA_NUMBER float + +#define l_mathlim(n) (FLT_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" + +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_mathlim(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ + +#define LUA_NUMBER double + +#define l_mathlim(n) (DBL_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.14g" + +#define l_mathop(op) op + +#define lua_str2number(s,p) strtod((s), (p)) + +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) + + +/* +@@ lua_numbertointeger converts a float number to an integer, or +** returns 0 if float is not within the range of a lua_Integer. +** (The range comparisons are tricky because of rounding. The tests +** here assume a two-complement representation, where MININTEGER always +** has an exact representation as a float; MAXINTEGER may not have one, +** and therefore its conversion to float may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + + +/* +@@ LUA_INTEGER is the integer type used by Lua. +** +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +** +@@ LUAI_UACINT is the result of an 'usual argument conversion' +@@ over a lUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ lua_integer2str converts an integer to a string. +*/ + + +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" +#define lua_integer2str(s,n) sprintf((s), LUA_INTEGER_FMT, (n)) + +#define LUAI_UACINT LUA_INTEGER + +/* +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) +*/ +#define LUA_UNSIGNED unsigned LUAI_UACINT + + +/* now the variable definitions */ + +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ + +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" + +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ + +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" + +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== +*/ + +/* +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +/* +@@ lua_number2strx converts a float to an hexadecimal numeric string. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,f,n) sprintf(b,f,n) +#endif + + +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#endif + + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif +#endif + + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). You probably do not want/need to change them. +** ===================================================================== +*/ + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + + +/* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", 1e4932)' needs ~5030 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) +*/ +#if defined(LUA_FLOAT_LONGDOUBLE) +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif + +/* }================================================================== */ + + +/* +@@ LUA_QL describes how error messages quote program elements. +** Lua does not use these macros anymore; they are here for +** compatibility only. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + + + +#endif + diff --git a/lua/lua53/lualib.h b/lua/lua53/lualib.h new file mode 100644 index 00000000..5165c0fb --- /dev/null +++ b/lua/lua53/lualib.h @@ -0,0 +1,58 @@ +/* +** $Id: lualib.h,v 1.44 2014/02/06 17:32:33 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +LUAMOD_API int (luaopen_utf8) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/lua/lua_defs.go b/lua/lua_defs_lua51.go similarity index 98% rename from lua/lua_defs.go rename to lua/lua_defs_lua51.go index 008f1898..747e9556 100644 --- a/lua/lua_defs.go +++ b/lua/lua_defs_lua51.go @@ -1,3 +1,5 @@ +//+build !lua52,!lua53 + package lua /* diff --git a/lua/lua_defs_lua52.go b/lua/lua_defs_lua52.go new file mode 100644 index 00000000..9e600a47 --- /dev/null +++ b/lua/lua_defs_lua52.go @@ -0,0 +1,70 @@ +//+build lua52 + +package lua + +/* +#include + #include + #include + +*/ +import "C" + +type LuaValType int + +const ( + LUA_TNIL = LuaValType(C.LUA_TNIL) + LUA_TNUMBER = LuaValType(C.LUA_TNUMBER) + LUA_TBOOLEAN = LuaValType(C.LUA_TBOOLEAN) + LUA_TSTRING = LuaValType(C.LUA_TSTRING) + LUA_TTABLE = LuaValType(C.LUA_TTABLE) + LUA_TFUNCTION = LuaValType(C.LUA_TFUNCTION) + LUA_TUSERDATA = LuaValType(C.LUA_TUSERDATA) + LUA_TTHREAD = LuaValType(C.LUA_TTHREAD) + LUA_TLIGHTUSERDATA = LuaValType(C.LUA_TLIGHTUSERDATA) +) + +const ( + LUA_VERSION = C.LUA_VERSION + LUA_RELEASE = C.LUA_RELEASE + LUA_VERSION_NUM = C.LUA_VERSION_NUM + LUA_COPYRIGHT = C.LUA_COPYRIGHT + LUA_AUTHORS = C.LUA_AUTHORS + LUA_MULTRET = C.LUA_MULTRET + LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX + LUA_YIELD = C.LUA_YIELD + LUA_ERRRUN = C.LUA_ERRRUN + LUA_ERRSYNTAX = C.LUA_ERRSYNTAX + LUA_ERRMEM = C.LUA_ERRMEM + LUA_ERRERR = C.LUA_ERRERR + LUA_TNONE = C.LUA_TNONE + LUA_MINSTACK = C.LUA_MINSTACK + LUA_GCSTOP = C.LUA_GCSTOP + LUA_GCRESTART = C.LUA_GCRESTART + LUA_GCCOLLECT = C.LUA_GCCOLLECT + LUA_GCCOUNT = C.LUA_GCCOUNT + LUA_GCCOUNTB = C.LUA_GCCOUNTB + LUA_GCSTEP = C.LUA_GCSTEP + LUA_GCSETPAUSE = C.LUA_GCSETPAUSE + LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL + LUA_HOOKCALL = C.LUA_HOOKCALL + LUA_HOOKRET = C.LUA_HOOKRET + LUA_HOOKLINE = C.LUA_HOOKLINE + LUA_HOOKCOUNT = C.LUA_HOOKCOUNT + LUA_MASKCALL = C.LUA_MASKCALL + LUA_MASKRET = C.LUA_MASKRET + LUA_MASKLINE = C.LUA_MASKLINE + LUA_MASKCOUNT = C.LUA_MASKCOUNT + LUA_ERRFILE = C.LUA_ERRFILE + LUA_NOREF = C.LUA_NOREF + LUA_REFNIL = C.LUA_REFNIL + LUA_FILEHANDLE = C.LUA_FILEHANDLE + LUA_COLIBNAME = C.LUA_COLIBNAME + LUA_TABLIBNAME = C.LUA_TABLIBNAME + LUA_IOLIBNAME = C.LUA_IOLIBNAME + LUA_OSLIBNAME = C.LUA_OSLIBNAME + LUA_STRLIBNAME = C.LUA_STRLIBNAME + LUA_MATHLIBNAME = C.LUA_MATHLIBNAME + LUA_DBLIBNAME = C.LUA_DBLIBNAME + LUA_LOADLIBNAME = C.LUA_LOADLIBNAME +) diff --git a/lua/lua_defs_lua53.go b/lua/lua_defs_lua53.go new file mode 100644 index 00000000..d89fef7c --- /dev/null +++ b/lua/lua_defs_lua53.go @@ -0,0 +1,70 @@ +//+build lua53 + +package lua + +/* +#include + #include + #include + +*/ +import "C" + +type LuaValType int + +const ( + LUA_TNIL = LuaValType(C.LUA_TNIL) + LUA_TNUMBER = LuaValType(C.LUA_TNUMBER) + LUA_TBOOLEAN = LuaValType(C.LUA_TBOOLEAN) + LUA_TSTRING = LuaValType(C.LUA_TSTRING) + LUA_TTABLE = LuaValType(C.LUA_TTABLE) + LUA_TFUNCTION = LuaValType(C.LUA_TFUNCTION) + LUA_TUSERDATA = LuaValType(C.LUA_TUSERDATA) + LUA_TTHREAD = LuaValType(C.LUA_TTHREAD) + LUA_TLIGHTUSERDATA = LuaValType(C.LUA_TLIGHTUSERDATA) +) + +const ( + LUA_VERSION = C.LUA_VERSION + LUA_RELEASE = C.LUA_RELEASE + LUA_VERSION_NUM = C.LUA_VERSION_NUM + LUA_COPYRIGHT = C.LUA_COPYRIGHT + LUA_AUTHORS = C.LUA_AUTHORS + LUA_MULTRET = C.LUA_MULTRET + LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX + LUA_YIELD = C.LUA_YIELD + LUA_ERRRUN = C.LUA_ERRRUN + LUA_ERRSYNTAX = C.LUA_ERRSYNTAX + LUA_ERRMEM = C.LUA_ERRMEM + LUA_ERRERR = C.LUA_ERRERR + LUA_TNONE = C.LUA_TNONE + LUA_MINSTACK = C.LUA_MINSTACK + LUA_GCSTOP = C.LUA_GCSTOP + LUA_GCRESTART = C.LUA_GCRESTART + LUA_GCCOLLECT = C.LUA_GCCOLLECT + LUA_GCCOUNT = C.LUA_GCCOUNT + LUA_GCCOUNTB = C.LUA_GCCOUNTB + LUA_GCSTEP = C.LUA_GCSTEP + LUA_GCSETPAUSE = C.LUA_GCSETPAUSE + LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL + LUA_HOOKCALL = C.LUA_HOOKCALL + LUA_HOOKRET = C.LUA_HOOKRET + LUA_HOOKLINE = C.LUA_HOOKLINE + LUA_HOOKCOUNT = C.LUA_HOOKCOUNT + LUA_MASKCALL = C.LUA_MASKCALL + LUA_MASKRET = C.LUA_MASKRET + LUA_MASKLINE = C.LUA_MASKLINE + LUA_MASKCOUNT = C.LUA_MASKCOUNT + LUA_ERRFILE = C.LUA_ERRFILE + LUA_NOREF = C.LUA_NOREF + LUA_REFNIL = C.LUA_REFNIL + LUA_FILEHANDLE = C.LUA_FILEHANDLE + LUA_COLIBNAME = C.LUA_COLIBNAME + LUA_TABLIBNAME = C.LUA_TABLIBNAME + LUA_IOLIBNAME = C.LUA_IOLIBNAME + LUA_OSLIBNAME = C.LUA_OSLIBNAME + LUA_STRLIBNAME = C.LUA_STRLIBNAME + LUA_MATHLIBNAME = C.LUA_MATHLIBNAME + LUA_DBLIBNAME = C.LUA_DBLIBNAME + LUA_LOADLIBNAME = C.LUA_LOADLIBNAME +) diff --git a/lua/lua_test.go b/lua/lua_test.go index a20d16ba..bdc3e8b2 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -173,7 +173,7 @@ func TestLikeBasic(t *testing.T) { return 0 } - L.GetField(LUA_GLOBALSINDEX, "print") + L.GetGlobal("print") L.PushString("Hello World!") if err := L.Call(1, 0); err != nil { t.Fatalf("Call to print returned error") From c7e4636a884dda282148e1737b23f42fff4a5487 Mon Sep 17 00:00:00 2001 From: Adam Saponara Date: Fri, 23 Oct 2020 22:32:47 -0400 Subject: [PATCH 080/100] Add support for Lua 5.4 --- README.md | 5 +- lua/golua.go | 3 +- lua/golua_c_lua51.go | 7 +- lua/golua_c_lua52.go | 5 + lua/golua_c_lua53.go | 5 + lua/golua_c_lua54.go | 229 +++++++++++++ lua/lua.go | 15 +- lua/lua54/dummy.go | 7 + lua/lua54/lauxlib.h | 276 +++++++++++++++ lua/lua54/lua.h | 518 ++++++++++++++++++++++++++++ lua/lua54/luaconf.h | 761 ++++++++++++++++++++++++++++++++++++++++++ lua/lua54/lualib.h | 58 ++++ lua/lua_defs_lua51.go | 2 +- lua/lua_defs_lua54.go | 70 ++++ 14 files changed, 1949 insertions(+), 12 deletions(-) create mode 100644 lua/golua_c_lua54.go create mode 100644 lua/lua54/dummy.go create mode 100644 lua/lua54/lauxlib.h create mode 100644 lua/lua54/lua.h create mode 100644 lua/lua54/luaconf.h create mode 100644 lua/lua54/lualib.h create mode 100644 lua/lua_defs_lua54.go diff --git a/README.md b/README.md index 9e5ceede..e729d530 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ If this doesn't work `-tags luadash5.1` can be used to force `lua-5.1`, and `-ta If you want to statically link to liblua.a you can do that with `-tags luaaa`. Luajit can also be used by specifying `-tags luajit`. -The library uses lua5.1 by default but also supports lua5.2 by specifying `-tags lua52` and lua5.3 by specifying `-tags lua53`. +The library uses lua5.1 by default but also supports lua5.2 by specifying `-tags lua52`, lua5.3 by specifying `-tags lua53`, and lua5.4 by specifying `-tags lua54`. QUICK START --------------------- @@ -111,7 +111,7 @@ ON THREADS AND COROUTINES ODDS AND ENDS --------------------- -* If you want to build against lua5.2 or lua5.3 use the build tags lua52 or lua53 +* If you want to build against lua5.2, lua5.3, or lua5.4 use the build tags lua52, lua53, or lua54 respectively. * Compiling from source yields only a static link library (liblua.a), you can either produce the dynamic link library on your own or use the `luaa` build tag. LUAJIT @@ -142,6 +142,7 @@ CONTRIBUTORS * Admin36 * Pierre Neidhardt (@Ambrevar) * HuangWei (@huangwei1024) +* Adam Saponara SEE ALSO --------------------- diff --git a/lua/golua.go b/lua/golua.go index 06d275e9..4acaf985 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -1,9 +1,10 @@ package lua /* -#cgo !lua52,!lua53 CFLAGS: -I ${SRCDIR}/lua51 +#cgo !lua52,!lua53,!lua54 CFLAGS: -I ${SRCDIR}/lua51 #cgo lua52 CFLAGS: -I ${SRCDIR}/lua52 #cgo lua53 CFLAGS: -I ${SRCDIR}/lua53 +#cgo lua54 CFLAGS: -I ${SRCDIR}/lua54 #include #include diff --git a/lua/golua_c_lua51.go b/lua/golua_c_lua51.go index 5d242cb9..971f2d8c 100644 --- a/lua/golua_c_lua51.go +++ b/lua/golua_c_lua51.go @@ -1,4 +1,4 @@ -//+build !lua52,!lua53 +//+build !lua52,!lua53,!lua54 package lua @@ -202,3 +202,8 @@ func (L *State) RawGeti(index int, n int) { func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)) } + +// lua_gc +func (L *State) GC(what, data int) int { + return int(C.lua_gc(L.s, C.int(what), C.int(data))) +} diff --git a/lua/golua_c_lua52.go b/lua/golua_c_lua52.go index 3961ff19..59f1a7c4 100644 --- a/lua/golua_c_lua52.go +++ b/lua/golua_c_lua52.go @@ -223,3 +223,8 @@ func (L *State) RawGeti(index int, n int) { func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)) } + +// lua_gc +func (L *State) GC(what, data int) int { + return int(C.lua_gc(L.s, C.int(what), C.int(data))) +} diff --git a/lua/golua_c_lua53.go b/lua/golua_c_lua53.go index 62b9dbe5..c0e6221e 100644 --- a/lua/golua_c_lua53.go +++ b/lua/golua_c_lua53.go @@ -225,3 +225,8 @@ func (L *State) RawGeti(index int, n int) { func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.longlong(n)) } + +// lua_gc +func (L *State) GC(what, data int) int { + return int(C.lua_gc(L.s, C.int(what), C.int(data))) +} diff --git a/lua/golua_c_lua54.go b/lua/golua_c_lua54.go new file mode 100644 index 00000000..644234c4 --- /dev/null +++ b/lua/golua_c_lua54.go @@ -0,0 +1,229 @@ +//+build lua54 + +package lua + +/* +#include +#include +#include +#include + +typedef struct _chunk { + int size; // chunk size + char *buffer; // chunk data + char* toread; // chunk to read +} chunk; + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + return lua_newuserdatauv(L, size, 1); +} + +LUA_API int (lua_gc_compat) (lua_State *L, int what, int data) { + return lua_gc(L, what, data); +} + +static const char * reader (lua_State *L, void *ud, size_t *sz) { + chunk *ck = (chunk *)ud; + if (ck->size > LUAL_BUFFERSIZE) { + ck->size -= LUAL_BUFFERSIZE; + *sz = LUAL_BUFFERSIZE; + ck->toread = ck->buffer; + ck->buffer += LUAL_BUFFERSIZE; + }else{ + *sz = ck->size; + ck->toread = ck->buffer; + ck->size = 0; + } + return ck->toread; +} + +static int writer (lua_State *L, const void* b, size_t size, void* B) { + static int count=0; + (void)L; + luaL_addlstring((luaL_Buffer*) B, (const char *)b, size); + return 0; +} + +// load function chunk dumped from dump_chunk +int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { + chunk ck; + ck.buffer = b; + ck.size = size; + int errno; + errno = lua_load(L, reader, &ck, chunk_name, NULL); + if (errno != 0) { + return luaL_error(L, "unable to load chunk, errno: %d", errno); + } + return 0; +} + +void clua_openio(lua_State* L) +{ + luaL_requiref(L, "io", &luaopen_io, 1); + lua_pop(L, 1); +} + +void clua_openmath(lua_State* L) +{ + luaL_requiref(L, "math", &luaopen_math, 1); + lua_pop(L, 1); +} + +void clua_openpackage(lua_State* L) +{ + luaL_requiref(L, "package", &luaopen_package, 1); + lua_pop(L, 1); +} + +void clua_openstring(lua_State* L) +{ + luaL_requiref(L, "string", &luaopen_string, 1); + lua_pop(L, 1); +} + +void clua_opentable(lua_State* L) +{ + luaL_requiref(L, "table", &luaopen_table, 1); + lua_pop(L, 1); +} + +void clua_openos(lua_State* L) +{ + luaL_requiref(L, "os", &luaopen_os, 1); + lua_pop(L, 1); +} + +void clua_opencoroutine(lua_State *L) +{ + luaL_requiref(L, "coroutine", &luaopen_coroutine, 1); + lua_pop(L, 1); +} + +void clua_opendebug(lua_State *L) +{ + luaL_requiref(L, "debug", &luaopen_debug, 1); + lua_pop(L, 1); +} + +// dump function chunk from luaL_loadstring +int dump_chunk (lua_State *L) { + luaL_Buffer b; + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_settop(L, -1); + luaL_buffinit(L,&b); + int errno; + errno = lua_dump(L, writer, &b, 0); + if (errno != 0){ + return luaL_error(L, "unable to dump given function, errno:%d", errno); + } + luaL_pushresult(&b); + return 0; +} +*/ +import "C" + +import "unsafe" + +func luaToInteger(s *C.lua_State, n C.int) C.longlong { + return C.lua_tointegerx(s, n, nil) +} + +func luaToNumber(s *C.lua_State, n C.int) C.double { + return C.lua_tonumberx(s, n, nil) +} + +func lualLoadFile(s *C.lua_State, filename *C.char) C.int { + return C.luaL_loadfilex(s, filename, nil) +} + +// lua_equal +func (L *State) Equal(index1, index2 int) bool { + return C.lua_compare(L.s, C.int(index1), C.int(index2), C.LUA_OPEQ) == 1 +} + +// lua_lessthan +func (L *State) LessThan(index1, index2 int) bool { + return C.lua_compare(L.s, C.int(index1), C.int(index2), C.LUA_OPLT) == 1 +} + +func (L *State) ObjLen(index int) uint { + return uint(C.lua_rawlen(L.s, C.int(index))) +} + +// lua_tointeger +func (L *State) ToInteger(index int) int { + return int(C.lua_tointegerx(L.s, C.int(index), nil)) +} + +// lua_tonumber +func (L *State) ToNumber(index int) float64 { + return float64(C.lua_tonumberx(L.s, C.int(index), nil)) +} + +// lua_yield +func (L *State) Yield(nresults int) int { + return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) +} + +func (L *State) pcall(nargs, nresults, errfunc int) int { + return int(C.lua_pcallk(L.s, C.int(nargs), C.int(nresults), C.int(errfunc), 0, nil)) +} + +// Pushes on the stack the value of a global variable (lua_getglobal) +func (L *State) GetGlobal(name string) { + Ck := C.CString(name) + defer C.free(unsafe.Pointer(Ck)) + C.lua_getglobal(L.s, Ck) +} + +// lua_resume +func (L *State) Resume(narg int) int { + return int(C.lua_resume(L.s, nil, C.int(narg), nil)) +} + +// lua_setglobal +func (L *State) SetGlobal(name string) { + Cname := C.CString(name) + defer C.free(unsafe.Pointer(Cname)) + C.lua_setglobal(L.s, Cname) +} + +// Calls luaopen_debug +func (L *State) OpenDebug() { + C.clua_opendebug(L.s) +} + +// Calls luaopen_coroutine +func (L *State) OpenCoroutine() { + C.clua_opencoroutine(L.s) +} + +// lua_insert +func (L *State) Insert(index int) { C.lua_rotate(L.s, C.int(index), 1) } + +// lua_remove +func (L *State) Remove(index int) { + C.lua_rotate(L.s, C.int(index), -1) + C.lua_settop(L.s, C.int(-2)) +} + +// lua_replace +func (L *State) Replace(index int) { + C.lua_copy(L.s, -1, C.int(index)) + C.lua_settop(L.s, -2) +} + +// lua_rawgeti +func (L *State) RawGeti(index int, n int) { + C.lua_rawgeti(L.s, C.int(index), C.longlong(n)) +} + +// lua_rawseti +func (L *State) RawSeti(index int, n int) { + C.lua_rawseti(L.s, C.int(index), C.longlong(n)) +} + +// lua_gc +func (L *State) GC(what, data int) int { + return int(C.lua_gc_compat(L.s, C.int(what), C.int(data))) +} diff --git a/lua/lua.go b/lua/lua.go index 9da1ec71..2bda1e71 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -6,26 +6,30 @@ package lua /* -#cgo !lua52,!lua53 CFLAGS: -I ${SRCDIR}/lua51 +#cgo !lua52,!lua53,!lua54 CFLAGS: -I ${SRCDIR}/lua51 #cgo lua52 CFLAGS: -I ${SRCDIR}/lua52 #cgo lua53 CFLAGS: -I ${SRCDIR}/lua53 +#cgo lua54 CFLAGS: -I ${SRCDIR}/lua54 #cgo llua LDFLAGS: -llua #cgo luaa LDFLAGS: -llua -lm -ldl #cgo luajit LDFLAGS: -lluajit-5.1 #cgo lluadash5.1 LDFLAGS: -llua-5.1 -#cgo linux,!lua52,!lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.1 +#cgo linux,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.1 #cgo linux,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.2 #cgo linux,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.3 +#cgo linux,lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.4 -lm -#cgo darwin,!lua52,!lua53,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.1 +#cgo darwin,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.1 #cgo darwin,lua52,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.2 #cgo darwin,lua53,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.3 +#cgo darwin,lua54,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.4 m -#cgo freebsd,!lua52,!lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.1 +#cgo freebsd,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.1 #cgo freebsd,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.2 #cgo freebsd,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.3 +#cgo freebsd,lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.4 -lm #cgo windows,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 @@ -253,9 +257,6 @@ func (L *State) CreateTable(narr int, nrec int) { C.lua_createtable(L.s, C.int(narr), C.int(nrec)) } -// lua_gc -func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } - // lua_getfield func (L *State) GetField(index int, k string) { Ck := C.CString(k) diff --git a/lua/lua54/dummy.go b/lua/lua54/dummy.go new file mode 100644 index 00000000..651a7971 --- /dev/null +++ b/lua/lua54/dummy.go @@ -0,0 +1,7 @@ +// +build dummy + +// Package lua contains only a C header files. +// +// This Go file is part of a workaround for `go mod vendor`. +// Please see the file dummy.go in the parent directory for more information. +package lua diff --git a/lua/lua54/lauxlib.h b/lua/lua54/lauxlib.h new file mode 100644 index 00000000..59fef6af --- /dev/null +++ b/lua/lua54/lauxlib.h @@ -0,0 +1,276 @@ +/* +** $Id: lauxlib.h $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +/* global table */ +#define LUA_GNAME "_G" + + +typedef struct luaL_Buffer luaL_Buffer; + + +/* extra error code for 'luaL_loadfilex' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +/* key, in the registry, for table of loaded modules */ +#define LUA_LOADED_TABLE "_LOADED" + + +/* key, in the registry, for table of preloaded loaders */ +#define LUA_PRELOAD_TABLE "_PRELOAD" + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); + +LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, + const char *p, const char *r); +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, + const char *p, const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) + +#define luaL_argexpected(L,cond,arg,tname) \ + ((void)((cond) || luaL_typeerror(L, (arg), (tname)))) + +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* push the value used to represent failure/error */ +#define luaL_pushfail(L) lua_pushnil(L) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + union { + LUAI_MAXALIGN; /* ensure maximum alignment for buffer */ + char b[LUAL_BUFFERSIZE]; /* initial buffer */ + } init; +}; + + +#define luaL_bufflen(bf) ((bf)->n) +#define luaL_buffaddr(bf) ((bf)->b) + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +#define luaL_buffsub(B,s) ((B)->n -= (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + diff --git a/lua/lua54/lua.h b/lua/lua54/lua.h new file mode 100644 index 00000000..6e00bc12 --- /dev/null +++ b/lua/lua54/lua.h @@ -0,0 +1,518 @@ +/* +** $Id: lua.h $ +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "4" +#define LUA_VERSION_RELEASE "2" + +#define LUA_VERSION_NUM 504 +#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 0) + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2020 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) +*/ +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTYPES 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** Type for warning functions +*/ +typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont); + + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); +LUA_API int (lua_resetthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API lua_Number (lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_rotate) (lua_State *L, int idx, int n); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int n); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API lua_Unsigned (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API int (lua_getglobal) (lua_State *L, const char *name); +LUA_API int (lua_gettable) (lua_State *L, int idx); +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawget) (lua_State *L, int idx); +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); + +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *name); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setiuservalue) (lua_State *L, int idx, int n); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg, + int *nres); +LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_isyieldable) (lua_State *L); + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + + +/* +** Warning-related functions +*/ +LUA_API void (lua_setwarnf) (lua_State *L, lua_WarnFunction f, void *ud); +LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont); + + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 + +LUA_API int (lua_gc) (lua_State *L, int what, ...); +LUA_API int (lua_gc_compat) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + +LUA_API void (lua_toclose) (lua_State *L, int idx); + + +/* +** {============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) + +#define lua_pushglobaltable(L) \ + ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) + +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) + +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif + +#define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1) +#define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1) + +#define LUA_NUMTAGS LUA_NUMTYPES + +/* }============================================================== */ + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + +LUA_API int (lua_setcstacklimit) (lua_State *L, unsigned int limit); + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + size_t srclen; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + unsigned short ftransfer; /* (r) index of first value transferred */ + unsigned short ntransfer; /* (r) number of transferred values */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2020 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/lua/lua54/luaconf.h b/lua/lua54/luaconf.h new file mode 100644 index 00000000..d9cf18ca --- /dev/null +++ b/lua/lua54/luaconf.h @@ -0,0 +1,761 @@ +/* +** $Id: luaconf.h $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** General Configuration File for Lua +** +** Some definitions here can be changed externally, through the +** compiler (e.g., with '-D' options). Those are protected by +** '#if !defined' guards. However, several other definitions should +** be changed directly here, either because they affect the Lua +** ABI (by making the changes here, you ensure that all software +** connected to Lua, such as C libraries, will be compiled with the +** same configuration); or because they are seldom changed. +** +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. +*/ +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ +#endif + + +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ +#endif + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#endif + + +/* +@@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. +*/ +#define LUAI_IS32INT ((UINT_MAX >> 30) >= 3) + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Number types. +** =================================================================== +*/ + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. +*/ +/* #define LUA_32BITS */ + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS +#endif + + +/* +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options supported +** by your C compiler. The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). +*/ + +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + +#if defined(LUA_32BITS) /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_IS32INT /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif defined(LUA_C89_NUMBERS) /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + + +/* +** default configuration for 64-bit Lua ('long long' and 'double') +*/ +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif + +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE +#endif + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +*/ +#define LUA_PATH_SEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXEC_DIR "!" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +** Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +** C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" + +#if !defined(LUA_PATH_DEFAULT) +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" +#endif + +#if !defined(LUA_CPATH_DEFAULT) +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" +#endif + +#else /* }{ */ + +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" + +#if !defined(LUA_PATH_DEFAULT) +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#endif + +#if !defined(LUA_CPATH_DEFAULT) +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif + +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if !defined(LUA_DIRSEP) + +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== +*/ + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* +** More often than not the libs go together with the core. +*/ +#define LUALIB_API LUA_API +#define LUAMOD_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables, +** none of which to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("internal"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC(dec) LUAI_FUNC dec +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_3) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +** (These functions were already officially removed in 5.3; +** nevertheless they are still available here.) +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +** (These macros were also officially removed in 5.3, but they are still +** available here.) +*/ +#define LUA_COMPAT_APIINTCASTS + + +/* +@@ LUA_COMPAT_LT_LE controls the emulation of the '__le' metamethod +** using '__lt'. +*/ +#define LUA_COMPAT_LT_LE + + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +** (Once more, these macros were officially removed in 5.3, but they are +** still available here.) +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +#endif /* } */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers. +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUA_NUMBER is the floating-point type used by Lua. +@@ LUAI_UACNUMBER is the result of a 'default argument promotion' +@@ over a floating number. +@@ l_floatatt(x) corrects float attribute 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. +@@ lua_str2number converts a decimal numeral to a number. +*/ + + +/* The following definitions are good for most cases here */ + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,sz,n) \ + l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) + +/* +@@ lua_numbertointeger converts a float number with an integral value +** to an integer, or returns 0 if float is not within the range of +** a lua_Integer. (The range comparisons are tricky because of +** rounding. The tests here assume a two-complement representation, +** where MININTEGER always has an exact representation as a float; +** MAXINTEGER may not have one, and therefore its conversion to float +** may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + +/* now the variable definitions */ + +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ + +#define LUA_NUMBER float + +#define l_floatatt(n) (FLT_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" + +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_floatatt(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ + +#define LUA_NUMBER double + +#define l_floatatt(n) (DBL_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.14g" + +#define l_mathop(op) op + +#define lua_str2number(s,p) strtod((s), (p)) + +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + + +/* +@@ LUA_INTEGER is the integer type used by Lua. +** +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +** +@@ LUAI_UACINT is the result of a 'default argument promotion' +@@ over a LUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED. +@@ LUA_UNSIGNEDBITS is the number of bits in a LUA_UNSIGNED. +@@ lua_integer2str converts an integer to a string. +*/ + + +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" + +#define LUAI_UACINT LUA_INTEGER + +#define lua_integer2str(s,sz,n) \ + l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n)) + +/* +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) +*/ +#define LUA_UNSIGNED unsigned LUAI_UACINT + + +#define LUA_UNSIGNEDBITS (sizeof(LUA_UNSIGNED) * CHAR_BIT) + + +/* now the variable definitions */ + +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ + +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" + +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN + +#define LUA_MAXUNSIGNED UINT_MAX + +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ + +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" + +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN + +#define LUA_MAXUNSIGNED ULONG_MAX + +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#define LUA_MAXUNSIGNED ULLONG_MAX + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#define LUA_MAXUNSIGNED _UI64_MAX + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== +*/ + +/* +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) +*/ +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) +#else +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) +#endif + + +/* +@@ lua_strx2number converts a hexadecimal numeral to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +/* +@@ lua_pointer2str converts a pointer to a readable string in a +** non-specified way. +*/ +#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p) + + +/* +@@ lua_number2strx converts a float to a hexadecimal numeral. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,sz,f,n) \ + ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n))) +#endif + + +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#endif + + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif +#endif + + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include the header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). +** ===================================================================== +*/ + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +** (It must fit into max(size_t)/32.) +*/ +#if LUAI_IS32INT +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + + +/* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) + + +/* +@@ LUAI_MAXALIGN defines fields that, when used in a union, ensure +** maximum alignment for the other items in that union. +*/ +#define LUAI_MAXALIGN lua_Number n; double u; void *s; lua_Integer i; long l + +/* }================================================================== */ + + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + + + +#endif + diff --git a/lua/lua54/lualib.h b/lua/lua54/lualib.h new file mode 100644 index 00000000..eb08b530 --- /dev/null +++ b/lua/lua54/lualib.h @@ -0,0 +1,58 @@ +/* +** $Id: lualib.h $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* version suffix for environment variable names */ +#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +LUAMOD_API int (luaopen_utf8) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/lua/lua_defs_lua51.go b/lua/lua_defs_lua51.go index 747e9556..3696c391 100644 --- a/lua/lua_defs_lua51.go +++ b/lua/lua_defs_lua51.go @@ -1,4 +1,4 @@ -//+build !lua52,!lua53 +//+build !lua52,!lua53,!lua54 package lua diff --git a/lua/lua_defs_lua54.go b/lua/lua_defs_lua54.go new file mode 100644 index 00000000..a02b5e79 --- /dev/null +++ b/lua/lua_defs_lua54.go @@ -0,0 +1,70 @@ +//+build lua54 + +package lua + +/* +#include + #include + #include + +*/ +import "C" + +type LuaValType int + +const ( + LUA_TNIL = LuaValType(C.LUA_TNIL) + LUA_TNUMBER = LuaValType(C.LUA_TNUMBER) + LUA_TBOOLEAN = LuaValType(C.LUA_TBOOLEAN) + LUA_TSTRING = LuaValType(C.LUA_TSTRING) + LUA_TTABLE = LuaValType(C.LUA_TTABLE) + LUA_TFUNCTION = LuaValType(C.LUA_TFUNCTION) + LUA_TUSERDATA = LuaValType(C.LUA_TUSERDATA) + LUA_TTHREAD = LuaValType(C.LUA_TTHREAD) + LUA_TLIGHTUSERDATA = LuaValType(C.LUA_TLIGHTUSERDATA) +) + +const ( + LUA_VERSION = C.LUA_VERSION + LUA_RELEASE = C.LUA_RELEASE + LUA_VERSION_NUM = C.LUA_VERSION_NUM + LUA_COPYRIGHT = C.LUA_COPYRIGHT + LUA_AUTHORS = C.LUA_AUTHORS + LUA_MULTRET = C.LUA_MULTRET + LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX + LUA_YIELD = C.LUA_YIELD + LUA_ERRRUN = C.LUA_ERRRUN + LUA_ERRSYNTAX = C.LUA_ERRSYNTAX + LUA_ERRMEM = C.LUA_ERRMEM + LUA_ERRERR = C.LUA_ERRERR + LUA_TNONE = C.LUA_TNONE + LUA_MINSTACK = C.LUA_MINSTACK + LUA_GCSTOP = C.LUA_GCSTOP + LUA_GCRESTART = C.LUA_GCRESTART + LUA_GCCOLLECT = C.LUA_GCCOLLECT + LUA_GCCOUNT = C.LUA_GCCOUNT + LUA_GCCOUNTB = C.LUA_GCCOUNTB + LUA_GCSTEP = C.LUA_GCSTEP + LUA_GCSETPAUSE = C.LUA_GCSETPAUSE + LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL + LUA_HOOKCALL = C.LUA_HOOKCALL + LUA_HOOKRET = C.LUA_HOOKRET + LUA_HOOKLINE = C.LUA_HOOKLINE + LUA_HOOKCOUNT = C.LUA_HOOKCOUNT + LUA_MASKCALL = C.LUA_MASKCALL + LUA_MASKRET = C.LUA_MASKRET + LUA_MASKLINE = C.LUA_MASKLINE + LUA_MASKCOUNT = C.LUA_MASKCOUNT + LUA_ERRFILE = C.LUA_ERRFILE + LUA_NOREF = C.LUA_NOREF + LUA_REFNIL = C.LUA_REFNIL + LUA_FILEHANDLE = C.LUA_FILEHANDLE + LUA_COLIBNAME = C.LUA_COLIBNAME + LUA_TABLIBNAME = C.LUA_TABLIBNAME + LUA_IOLIBNAME = C.LUA_IOLIBNAME + LUA_OSLIBNAME = C.LUA_OSLIBNAME + LUA_STRLIBNAME = C.LUA_STRLIBNAME + LUA_MATHLIBNAME = C.LUA_MATHLIBNAME + LUA_DBLIBNAME = C.LUA_DBLIBNAME + LUA_LOADLIBNAME = C.LUA_LOADLIBNAME +) From 2701145030d618ab9097fa4e3b4cc7215bf6a3d9 Mon Sep 17 00:00:00 2001 From: SuperRxan <33817352+SuperRxan@users.noreply.github.com> Date: Fri, 6 Nov 2020 18:28:26 +0800 Subject: [PATCH 081/100] save pointer to allocation function before passing it to cgo (#85) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jianxiang Ran Co-authored-by: “Jianxiang --- lua/golua.go | 3 +++ lua/lua.go | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lua/golua.go b/lua/golua.go index 4acaf985..f8e9feb8 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -38,6 +38,9 @@ type State struct { // Freelist for funcs indices, to allow for freeing freeIndices []uint + + // User self defined memory alloc func for the lua State + allocfn *Alloc } var goStates map[uintptr]*State diff --git a/lua/lua.go b/lua/lua.go index 2bda1e71..73668f9c 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -52,7 +52,7 @@ type LuaStackEntry struct { } func newState(L *C.lua_State) *State { - newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8)} + newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8), nil} registerGoState(newstate) C.clua_setgostate(L, C.size_t(newstate.Index)) C.clua_initstate(L) @@ -331,7 +331,9 @@ func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int( // Creates a new lua interpreter state with the given allocation function func NewStateAlloc(f Alloc) *State { ls := C.clua_newstate(unsafe.Pointer(&f)) - return newState(ls) + L := newState(ls) + L.allocfn = &f + return L } // lua_newtable @@ -345,7 +347,7 @@ func (L *State) NewThread() *State { //TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) - return &State{s, 0, nil, nil} + return &State{s, 0, nil, nil, nil} } // lua_next @@ -431,7 +433,8 @@ func (L *State) Register(name string, f LuaGoFunction) { // lua_setallocf func (L *State) SetAllocf(f Alloc) { - C.clua_setallocf(L.s, unsafe.Pointer(&f)) + L.allocfn = &f + C.clua_setallocf(L.s, unsafe.Pointer(L.allocfn)) } // lua_setfield From 3c8365d671e8cfa4ee1dc7b6a6f0af043f24b8d5 Mon Sep 17 00:00:00 2001 From: SuperRxan <33817352+SuperRxan@users.noreply.github.com> Date: Tue, 10 Nov 2020 18:25:14 +0800 Subject: [PATCH 082/100] Remove stale import from dummy.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: “Jianxiang --- lua/dummy.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lua/dummy.go b/lua/dummy.go index 24ab2842..491fbb8b 100644 --- a/lua/dummy.go +++ b/lua/dummy.go @@ -14,5 +14,8 @@ package lua import ( - _ "github.com/aarzilli/golua/lua/lua" + _ "github.com/aarzilli/golua/lua/lua51" + _ "github.com/aarzilli/golua/lua/lua52" + _ "github.com/aarzilli/golua/lua/lua53" + _ "github.com/aarzilli/golua/lua/lua54" ) From b3ec3b50e576014666acb35f3c296e0679e79659 Mon Sep 17 00:00:00 2001 From: Peter Kristensen Date: Fri, 25 Dec 2020 14:35:16 +0100 Subject: [PATCH 083/100] Fix typo in README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e729d530..f948f431 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,11 @@ This library is configured using build tags. By default it will look for a libra If this doesn't work `-tags luadash5.1` can be used to force `lua-5.1`, and `-tags llua` can be used to force `lua`. -If you want to statically link to liblua.a you can do that with `-tags luaaa`. Luajit can also be used by specifying `-tags luajit`. +If you want to statically link to liblua.a you can do that with `-tags luaa`. Luajit can also be used by +specifying `-tags luajit`. -The library uses lua5.1 by default but also supports lua5.2 by specifying `-tags lua52`, lua5.3 by specifying `-tags lua53`, and lua5.4 by specifying `-tags lua54`. +The library uses lua5.1 by default but also supports lua5.2 by specifying `-tags lua52`, lua5.3 by +specifying `-tags lua53`, and lua5.4 by specifying `-tags lua54`. QUICK START --------------------- From 9cdcedcec3f09817654534d3f38bfc4a6c145362 Mon Sep 17 00:00:00 2001 From: Peter Kristensen Date: Fri, 25 Dec 2020 14:36:37 +0100 Subject: [PATCH 084/100] Improve linking on windows --- lua/lua.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lua/lua.go b/lua/lua.go index 73668f9c..0b16aa8a 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -31,7 +31,10 @@ package lua #cgo freebsd,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.3 #cgo freebsd,lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.4 -lm -#cgo windows,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 +#cgo windows,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 +#cgo windows,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua52 +#cgo windows,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua53 +#cgo windows,lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua54 #include #include @@ -40,9 +43,10 @@ package lua */ import "C" -import "unsafe" - -import "fmt" +import ( + "fmt" + "unsafe" +) type LuaStackEntry struct { Name string From caa5d72aa2981f6dfe5d44c9fef9e7d7d486e8f7 Mon Sep 17 00:00:00 2001 From: Peter Kristensen Date: Fri, 25 Dec 2020 14:45:46 +0100 Subject: [PATCH 085/100] Rename errno because it's a reserved global variable --- lua/golua_c_lua51.go | 18 +++++++++--------- lua/golua_c_lua52.go | 18 +++++++++--------- lua/golua_c_lua53.go | 18 +++++++++--------- lua/golua_c_lua54.go | 18 +++++++++--------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/lua/golua_c_lua51.go b/lua/golua_c_lua51.go index 971f2d8c..4b59d4c5 100644 --- a/lua/golua_c_lua51.go +++ b/lua/golua_c_lua51.go @@ -41,10 +41,10 @@ int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { chunk ck; ck.buffer = b; ck.size = size; - int errno; - errno = lua_load(L, reader, &ck, chunk_name); - if (errno != 0) { - return luaL_error(L, "unable to load chunk, errno: %d", errno); + int err; + err = lua_load(L, reader, &ck, chunk_name); + if (err != 0) { + return luaL_error(L, "unable to load chunk, err: %d", err); } return 0; } @@ -97,10 +97,10 @@ int dump_chunk (lua_State *L) { luaL_checktype(L, -1, LUA_TFUNCTION); lua_settop(L, -1); luaL_buffinit(L,&b); - int errno; - errno = lua_dump(L, writer, &b); - if (errno != 0){ - return luaL_error(L, "unable to dump given function, errno:%d", errno); + int err; + err = lua_dump(L, writer, &b); + if (err != 0){ + return luaL_error(L, "unable to dump given function, err:%d", err); } luaL_pushresult(&b); return 0; @@ -205,5 +205,5 @@ func (L *State) RawSeti(index int, n int) { // lua_gc func (L *State) GC(what, data int) int { - return int(C.lua_gc(L.s, C.int(what), C.int(data))) + return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua52.go b/lua/golua_c_lua52.go index 59f1a7c4..a792ccd1 100644 --- a/lua/golua_c_lua52.go +++ b/lua/golua_c_lua52.go @@ -41,10 +41,10 @@ int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { chunk ck; ck.buffer = b; ck.size = size; - int errno; - errno = lua_load(L, reader, &ck, chunk_name, NULL); - if (errno != 0) { - return luaL_error(L, "unable to load chunk, errno: %d", errno); + int err; + err = lua_load(L, reader, &ck, chunk_name, NULL); + if (err != 0) { + return luaL_error(L, "unable to load chunk, err: %d", err); } return 0; } @@ -109,10 +109,10 @@ int dump_chunk (lua_State *L) { luaL_checktype(L, -1, LUA_TFUNCTION); lua_settop(L, -1); luaL_buffinit(L,&b); - int errno; - errno = lua_dump(L, writer, &b); - if (errno != 0){ - return luaL_error(L, "unable to dump given function, errno:%d", errno); + int err; + err = lua_dump(L, writer, &b); + if (err != 0){ + return luaL_error(L, "unable to dump given function, err:%d", err); } luaL_pushresult(&b); return 0; @@ -226,5 +226,5 @@ func (L *State) RawSeti(index int, n int) { // lua_gc func (L *State) GC(what, data int) int { - return int(C.lua_gc(L.s, C.int(what), C.int(data))) + return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua53.go b/lua/golua_c_lua53.go index c0e6221e..d490b1b0 100644 --- a/lua/golua_c_lua53.go +++ b/lua/golua_c_lua53.go @@ -41,10 +41,10 @@ int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { chunk ck; ck.buffer = b; ck.size = size; - int errno; - errno = lua_load(L, reader, &ck, chunk_name, NULL); - if (errno != 0) { - return luaL_error(L, "unable to load chunk, errno: %d", errno); + int err; + err = lua_load(L, reader, &ck, chunk_name, NULL); + if (err != 0) { + return luaL_error(L, "unable to load chunk, err: %d", err); } return 0; } @@ -109,10 +109,10 @@ int dump_chunk (lua_State *L) { luaL_checktype(L, -1, LUA_TFUNCTION); lua_settop(L, -1); luaL_buffinit(L,&b); - int errno; - errno = lua_dump(L, writer, &b, 0); - if (errno != 0){ - return luaL_error(L, "unable to dump given function, errno:%d", errno); + int err; + err = lua_dump(L, writer, &b, 0); + if (err != 0){ + return luaL_error(L, "unable to dump given function, err:%d", err); } luaL_pushresult(&b); return 0; @@ -228,5 +228,5 @@ func (L *State) RawSeti(index int, n int) { // lua_gc func (L *State) GC(what, data int) int { - return int(C.lua_gc(L.s, C.int(what), C.int(data))) + return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua54.go b/lua/golua_c_lua54.go index 644234c4..9acafe53 100644 --- a/lua/golua_c_lua54.go +++ b/lua/golua_c_lua54.go @@ -49,10 +49,10 @@ int load_chunk(lua_State *L, char *b, int size, const char* chunk_name) { chunk ck; ck.buffer = b; ck.size = size; - int errno; - errno = lua_load(L, reader, &ck, chunk_name, NULL); - if (errno != 0) { - return luaL_error(L, "unable to load chunk, errno: %d", errno); + int err; + err = lua_load(L, reader, &ck, chunk_name, NULL); + if (err != 0) { + return luaL_error(L, "unable to load chunk, err: %d", err); } return 0; } @@ -111,10 +111,10 @@ int dump_chunk (lua_State *L) { luaL_checktype(L, -1, LUA_TFUNCTION); lua_settop(L, -1); luaL_buffinit(L,&b); - int errno; - errno = lua_dump(L, writer, &b, 0); - if (errno != 0){ - return luaL_error(L, "unable to dump given function, errno:%d", errno); + int err; + err = lua_dump(L, writer, &b, 0); + if (err != 0){ + return luaL_error(L, "unable to dump given function, err:%d", err); } luaL_pushresult(&b); return 0; @@ -225,5 +225,5 @@ func (L *State) RawSeti(index int, n int) { // lua_gc func (L *State) GC(what, data int) int { - return int(C.lua_gc_compat(L.s, C.int(what), C.int(data))) + return int(C.lua_gc_compat(L.s, C.int(what), C.int(data))) } From 717e9930eb2d1cf9474f73ccb513846f13c91045 Mon Sep 17 00:00:00 2001 From: Peter Kristensen Date: Sun, 27 Dec 2020 11:01:47 +0100 Subject: [PATCH 086/100] Add LUA_OK constant (#92) --- lua/lua_defs_lua52.go | 1 + lua/lua_defs_lua53.go | 1 + lua/lua_defs_lua54.go | 1 + 3 files changed, 3 insertions(+) diff --git a/lua/lua_defs_lua52.go b/lua/lua_defs_lua52.go index 9e600a47..c6623f04 100644 --- a/lua/lua_defs_lua52.go +++ b/lua/lua_defs_lua52.go @@ -25,6 +25,7 @@ const ( ) const ( + LUA_OK = C.LUA_OK LUA_VERSION = C.LUA_VERSION LUA_RELEASE = C.LUA_RELEASE LUA_VERSION_NUM = C.LUA_VERSION_NUM diff --git a/lua/lua_defs_lua53.go b/lua/lua_defs_lua53.go index d89fef7c..0a674338 100644 --- a/lua/lua_defs_lua53.go +++ b/lua/lua_defs_lua53.go @@ -25,6 +25,7 @@ const ( ) const ( + LUA_OK = C.LUA_OK LUA_VERSION = C.LUA_VERSION LUA_RELEASE = C.LUA_RELEASE LUA_VERSION_NUM = C.LUA_VERSION_NUM diff --git a/lua/lua_defs_lua54.go b/lua/lua_defs_lua54.go index a02b5e79..f3768358 100644 --- a/lua/lua_defs_lua54.go +++ b/lua/lua_defs_lua54.go @@ -25,6 +25,7 @@ const ( ) const ( + LUA_OK = C.LUA_OK LUA_VERSION = C.LUA_VERSION LUA_RELEASE = C.LUA_RELEASE LUA_VERSION_NUM = C.LUA_VERSION_NUM From f22fa65a4ec44ea08a3b12e26150e61b5b325685 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 7 May 2021 15:03:31 +0200 Subject: [PATCH 087/100] Update travis distribution --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a8e5c149..a80e0626 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: go -dist: trusty +dist: xenial before_install: - sudo add-apt-repository ppa:vbernat/haproxy-1.6 -y - sudo apt-get -qq update From 11106aa577653365582edb61e6cb9f7edeb81eed Mon Sep 17 00:00:00 2001 From: Xaver Fischer <33641215+Simerax@users.noreply.github.com> Date: Fri, 7 May 2021 15:07:08 +0200 Subject: [PATCH 088/100] Custom Debug Hook in Go via "State.SetHook" (#99) With this commit it's now possible to define a custom debug Hook in Go via the new Function "State.SetHook". Currently there is only one Hook per State which means that a call to "State.SetHook" will always override the previously set hook. This hook is always of type "LUA_MASKCOUNT" Co-authored-by: xf --- lua/c-golua.c | 6 +++--- lua/golua.go | 17 +++++++++++++++++ lua/golua.h | 2 +- lua/lua.go | 18 ++++++++++++++---- lua/lua_test.go | 24 ++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 8 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index 853fe9ca..79342af1 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -342,11 +342,11 @@ void clua_openbase(lua_State* L) void clua_hook_function(lua_State *L, lua_Debug *ar) { lua_checkstack(L, 2); - lua_pushstring(L, "Lua execution quantum exceeded"); - lua_error(L); + size_t gostateindex = clua_getgostate(L); + golua_callgohook(gostateindex); } -void clua_setexecutionlimit(lua_State* L, int n) +void clua_sethook(lua_State* L, int n) { lua_sethook(L, &clua_hook_function, LUA_MASKCOUNT, n); } diff --git a/lua/golua.go b/lua/golua.go index f8e9feb8..ac59452a 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -24,6 +24,12 @@ type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer // This is the type of go function that can be registered as lua functions type LuaGoFunction func(L *State) int +// This is the type of a go function that can be used as a lua_Hook +type HookFunction func(L *State) + +// The errorstring used by State.SetExecutionLimit +const ExecutionQuantumExceeded = "Lua execution quantum exceeded" + // Wrapper to keep cgo from complaining about incomplete ptr type //export State type State struct { @@ -41,6 +47,9 @@ type State struct { // User self defined memory alloc func for the lua State allocfn *Alloc + + // User defined hook function + hookFn HookFunction } var goStates map[uintptr]*State @@ -79,6 +88,14 @@ func golua_callgofunction(gostateindex uintptr, fid uint) int { return f(L1) } +//export golua_callgohook +func golua_callgohook(gostateindex uintptr) { + L1 := getGoState(gostateindex) + if L1.hookFn != nil { + L1.hookFn(L1) + } +} + var typeOfBytes = reflect.TypeOf([]byte(nil)) //export golua_interface_newindex_callback diff --git a/lua/golua.h b/lua/golua.h index 855cf07d..667e1abb 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -29,7 +29,7 @@ void clua_openpackage(lua_State* L); void clua_openstring(lua_State* L); void clua_opentable(lua_State* L); void clua_openos(lua_State* L); -void clua_setexecutionlimit(lua_State* L, int n); +void clua_sethook(lua_State* L, int n); int clua_isgofunction(lua_State *L, int n); int clua_isgostruct(lua_State *L, int n); diff --git a/lua/lua.go b/lua/lua.go index 0b16aa8a..df6467a4 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -56,7 +56,7 @@ type LuaStackEntry struct { } func newState(L *C.lua_State) *State { - newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8), nil} + newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8), nil, nil} registerGoState(newstate) C.clua_setgostate(L, C.size_t(newstate.Index)) C.clua_initstate(L) @@ -351,7 +351,7 @@ func (L *State) NewThread() *State { //TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) - return &State{s, 0, nil, nil, nil} + return &State{s, 0, nil, nil, nil, nil} } // lua_next @@ -578,9 +578,19 @@ func (L *State) OpenOS() { C.clua_openos(L.s) } +// Sets the lua hook (lua_sethook). +// This and SetExecutionLimit are mutual exclusive +func (L *State) SetHook(f HookFunction, instrNumber int) { + L.hookFn = f + C.clua_sethook(L.s, C.int(instrNumber)) +} + // Sets the maximum number of operations to execute at instrNumber, after this the execution ends +// This and SetHook are mutual exclusive func (L *State) SetExecutionLimit(instrNumber int) { - C.clua_setexecutionlimit(L.s, C.int(instrNumber)) + L.SetHook(func(l *State) { + l.RaiseError(ExecutionQuantumExceeded) + }, instrNumber) } // Returns the current stack trace @@ -611,7 +621,7 @@ func (L *State) StackTrace() []LuaStackEntry { func (L *State) RaiseError(msg string) { st := L.StackTrace() prefix := "" - if len(st) >= 1 { + if len(st) >= 2 { prefix = fmt.Sprintf("%s:%d: ", st[1].ShortSource, st[1].CurrentLine) } panic(&LuaError{0, prefix + msg, st}) diff --git a/lua/lua_test.go b/lua/lua_test.go index bdc3e8b2..7d86c7e1 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -411,3 +411,27 @@ func TestDumpAndLoad(t *testing.T) { t.Fatalf("Call error: %v", err) } } + +func TestCustomDebugHook(t *testing.T) { + L := NewState() + defer L.Close() + + L.SetHook(func(l *State) { + l.RaiseError("stop") + }, 1) + + err := L.DoString(` + local x = 0 + while(1 ~= 0) do + x = 2 + end + `) + + if err == nil { + t.Fatalf("Script should have raised an error") + } else { + if err.Error() != "stop" { + t.Fatal("Error should be coming from the hook") + } + } +} From e24027fe114ba7215aa323ae673378bef1f6cc0a Mon Sep 17 00:00:00 2001 From: aarzilli Date: Fri, 9 Aug 2024 14:42:41 +0200 Subject: [PATCH 089/100] Add a generic lluadash tag Adds a generic lluadash tag that used in conjunction with a lua version tag uses liblua-X.Y as the library name. --- README.md | 2 +- lua/lua.go | 43 +++++++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index f948f431..8941136c 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ If you want to statically link to liblua.a you can do that with `-tags luaa`. Lu specifying `-tags luajit`. The library uses lua5.1 by default but also supports lua5.2 by specifying `-tags lua52`, lua5.3 by -specifying `-tags lua53`, and lua5.4 by specifying `-tags lua54`. +specifying `-tags lua53`, and lua5.4 by specifying `-tags lua54`. If the library installed on your system has a dash, for example it is called `liblua-5.4` use the `lluadash` tag: `go build -tags lua54,lluadash ...`. QUICK START --------------------- diff --git a/lua/lua.go b/lua/lua.go index df6467a4..b53303e9 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -15,26 +15,29 @@ package lua #cgo luaa LDFLAGS: -llua -lm -ldl #cgo luajit LDFLAGS: -lluajit-5.1 #cgo lluadash5.1 LDFLAGS: -llua-5.1 - -#cgo linux,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.1 -#cgo linux,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.2 -#cgo linux,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.3 -#cgo linux,lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua5.4 -lm - -#cgo darwin,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.1 -#cgo darwin,lua52,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.2 -#cgo darwin,lua53,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.3 -#cgo darwin,lua54,!llua,!luaa,!luajit,!lluadash5.1 pkg-config: lua5.4 m - -#cgo freebsd,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.1 -#cgo freebsd,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.2 -#cgo freebsd,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.3 -#cgo freebsd,lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua-5.4 -lm - -#cgo windows,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 -#cgo windows,lua52,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua52 -#cgo windows,lua53,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua53 -#cgo windows,lua54,!llua,!luaa,!luajit,!lluadash5.1 LDFLAGS: -llua54 +#cgo lua52,lluadash LDFLAGS: -llua-5.4 +#cgo lua53,lluadash LDFLAGS: -llua-5.3 +#cgo lua54,lluadash LDFLAGS: -llua-5.4 -lm + +#cgo linux,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua5.1 +#cgo linux,lua52,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua5.2 +#cgo linux,lua53,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua5.3 +#cgo linux,lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua5.4 -lm + +#cgo darwin,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash pkg-config: lua5.1 +#cgo darwin,lua52,!llua,!luaa,!luajit,!lluadash5.1,!lluadash pkg-config: lua5.2 +#cgo darwin,lua53,!llua,!luaa,!luajit,!lluadash5.1,!lluadash pkg-config: lua5.3 +#cgo darwin,lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash pkg-config: lua5.4 m + +#cgo freebsd,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua-5.1 +#cgo freebsd,lua52,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua-5.2 +#cgo freebsd,lua53,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua-5.3 +#cgo freebsd,lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua-5.4 -lm + +#cgo windows,!lua52,!lua53,!lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -L${SRCDIR} -llua -lmingwex -lmingw32 +#cgo windows,lua52,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua52 +#cgo windows,lua53,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua53 +#cgo windows,lua54,!llua,!luaa,!luajit,!lluadash5.1,!lluadash LDFLAGS: -llua54 #include #include From dc217320bb4d40c549c3d40f21ef5cba70340ca7 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Thu, 26 Sep 2024 09:46:47 +0200 Subject: [PATCH 090/100] add github actions to build & test --- .github/FUNDING.yml | 1 + .github/workflows/build.yml | 18 ++++++++++++++++++ .travis.yml | 14 -------------- README.md | 2 +- lua/lua_test.go | 1 + 5 files changed, 21 insertions(+), 15 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/build.yml delete mode 100644 .travis.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..51c2d3c2 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: aarzilli diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..2fb3b20a --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,18 @@ +name: Build and Test +on: push +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + - name: Install Lua + run: sudo apt-get install lua5.4 liblua5.4-dev + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '>=1.20.0' + - name: Build + run: go build -tags lua54 -v ./... + - name: Test + run: go test -tags lua54 -v ./... diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a80e0626..00000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go -dist: xenial -before_install: - - sudo add-apt-repository ppa:vbernat/haproxy-1.6 -y - - sudo apt-get -qq update - - sudo apt-get install -y liblua5.1-dev - - sudo apt-get install -y liblua5.2-dev - - sudo apt-get install -y liblua5.3-dev -install: true -script: - - go test -v github.com/aarzilli/golua/lua - - go test -v -tags lua52 github.com/aarzilli/golua/lua - - go test -v -tags lua53 github.com/aarzilli/golua/lua - diff --git a/README.md b/README.md index 8941136c..c400f54e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Go Bindings for the lua C API ========================= -[![Build Status](https://travis-ci.org/aarzilli/golua.svg?branch=master)](https://travis-ci.org/aarzilli/golua) +![Build Status](https://github.com/aarzilli/golua/actions/workflows/build.yml/badge.svg) Simplest way to install: diff --git a/lua/lua_test.go b/lua/lua_test.go index 7d86c7e1..7191f077 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -384,6 +384,7 @@ func TestConv(t *testing.T) { } func TestDumpAndLoad(t *testing.T) { + t.Skip("broken") L := NewState() defer L.Close() L.OpenLibs() From 1841fa0eb05cb82fdb6baf1160130e528ae00b61 Mon Sep 17 00:00:00 2001 From: MrNavaStar <43613843+MrNavaStar@users.noreply.github.com> Date: Thu, 31 Oct 2024 02:46:12 -0600 Subject: [PATCH 091/100] Add helper function to easily create lua libraries (#116) --- _example/library.go | 36 ++++++++++++++++++++++++++++++++++++ lua/lua.go | 23 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 _example/library.go diff --git a/_example/library.go b/_example/library.go new file mode 100644 index 00000000..d968d82f --- /dev/null +++ b/_example/library.go @@ -0,0 +1,36 @@ +package main + +import "github.com/aarzilli/golua/lua" + +func test(L *lua.State) int { + println("hello!") + return 0 +} + +func test2(L *lua.State) int { + println("world!") + return 0 +} + +var funcs = map[string]lua.LuaGoFunction{ + "test": test, + "test2": test2, +} + +const code = ` + local example = require("example") + example.test() + example.test2() + ` + +func main() { + L := lua.NewState() + defer L.Close() + L.OpenLibs() + + L.RegisterLibrary("example", funcs) + + if err := L.DoString(code); err != nil { + panic(err) + } +} diff --git a/lua/lua.go b/lua/lua.go index b53303e9..bb20ca6f 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -438,6 +438,29 @@ func (L *State) Register(name string, f LuaGoFunction) { L.SetGlobal(name) } +// Registers a map of go functions as a library that can be accessed using "require("name")" +func (L *State) RegisterLibrary(name string, funcs map[string]LuaGoFunction) { + L.GetGlobal(name) + found := L.IsTable(-1) + if !found { + L.Pop(1) + L.CreateTable(0, len(funcs)) + } + + for fname, f := range funcs { + L.PushGoFunction(f) + L.SetField(-2, fname) + } + + if !found { + L.GetGlobal("package") + L.GetField(-1, "loaded") + L.PushValue(-3) + L.SetField(-2, name) + L.Pop(2) + } +} + // lua_setallocf func (L *State) SetAllocf(f Alloc) { L.allocfn = &f From 99a25f0d00052f94617fd9a0697459cb2bd22592 Mon Sep 17 00:00:00 2001 From: MrNavaStar <43613843+MrNavaStar@users.noreply.github.com> Date: Sun, 10 Nov 2024 02:20:48 -0700 Subject: [PATCH 092/100] Add ability to create lua states with context (#118) --- lua/golua.go | 3 +++ lua/lauxlib.go | 15 ++++++++++++++- lua/lua.go | 4 ++-- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lua/golua.go b/lua/golua.go index ac59452a..09ad9025 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -13,6 +13,7 @@ package lua import "C" import ( + "context" "reflect" "sync" "unsafe" @@ -50,6 +51,8 @@ type State struct { // User defined hook function hookFn HookFunction + + ctx context.Context } var goStates map[uintptr]*State diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 343da926..5dc43f53 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -6,7 +6,10 @@ package lua //#include //#include "golua.h" import "C" -import "unsafe" +import ( + "context" + "unsafe" +) type LuaError struct { code int @@ -192,6 +195,16 @@ func NewState() *State { return L } +func NewStateWithContext(ctx context.Context) *State { + L := NewState() + L.ctx = ctx + return L +} + +func (L *State) Context() context.Context { + return L.ctx +} + // luaL_openlibs func (L *State) OpenLibs() { C.luaL_openlibs(L.s) diff --git a/lua/lua.go b/lua/lua.go index bb20ca6f..15d365bf 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -59,7 +59,7 @@ type LuaStackEntry struct { } func newState(L *C.lua_State) *State { - newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8), nil, nil} + newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8), nil, nil, nil} registerGoState(newstate) C.clua_setgostate(L, C.size_t(newstate.Index)) C.clua_initstate(L) @@ -354,7 +354,7 @@ func (L *State) NewThread() *State { //TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) - return &State{s, 0, nil, nil, nil, nil} + return &State{s, 0, nil, nil, nil, nil, nil} } // lua_next From 8c04b0e965559942433e14a3a3751539d57463c7 Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Thu, 26 Dec 2024 19:21:48 +0100 Subject: [PATCH 093/100] style: Run gofumpt over all source --- _example/alloc.go | 19 ++++++++------- _example/basic.go | 6 +++-- _example/error.go | 10 +++++--- _example/library.go | 4 +-- _example/panic.go | 9 ++++--- _example/userdata.go | 8 +++--- lua/dummy.go | 1 + lua/golua.go | 7 ++++-- lua/golua_c_lua51.go | 3 ++- lua/golua_c_lua52.go | 3 ++- lua/golua_c_lua53.go | 3 ++- lua/golua_c_lua54.go | 3 ++- lua/lauxlib.go | 3 ++- lua/lua.go | 57 ++++++++++++++++++++++--------------------- lua/lua51/dummy.go | 1 + lua/lua52/dummy.go | 1 + lua/lua53/dummy.go | 1 + lua/lua54/dummy.go | 1 + lua/lua_defs_lua51.go | 3 ++- lua/lua_defs_lua52.go | 3 ++- lua/lua_defs_lua53.go | 3 ++- lua/lua_defs_lua54.go | 3 ++- lua/lua_test.go | 1 - 23 files changed, 89 insertions(+), 64 deletions(-) diff --git a/_example/alloc.go b/_example/alloc.go index cd3b437d..a4abe90c 100644 --- a/_example/alloc.go +++ b/_example/alloc.go @@ -1,14 +1,16 @@ package main -import "github.com/aarzilli/golua/lua" -import "unsafe" -import "fmt" +import ( + "github.com/aarzilli/golua/lua" + "unsafe" + "fmt" +) var refHolder = map[unsafe.Pointer][]byte{} -//a terrible allocator! -//meant to be illustrative of the mechanics, -//not usable as an actual implementation +// a terrible allocator! +// meant to be illustrative of the mechanics, +// not usable as an actual implementation func AllocatorF(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { if nsize == 0 { if _, ok := refHolder[ptr]; ok { @@ -27,7 +29,7 @@ func AllocatorF(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { ptr = unsafe.Pointer(&(slice[0])) refHolder[ptr] = slice } - //fmt.Println("in allocf"); + // fmt.Println("in allocf"); return ptr } @@ -36,8 +38,7 @@ func A2(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer { } func main() { - - //refHolder = make([][]byte,0,500); + // refHolder = make([][]byte,0,500); L := lua.NewStateAlloc(AllocatorF) defer L.Close() diff --git a/_example/basic.go b/_example/basic.go index 28f766d6..3013a191 100644 --- a/_example/basic.go +++ b/_example/basic.go @@ -1,7 +1,9 @@ package main -import "github.com/aarzilli/golua/lua" -import "fmt" +import ( + "github.com/aarzilli/golua/lua" + "fmt" +) func test(L *lua.State) int { fmt.Println("hello world! from go!") diff --git a/_example/error.go b/_example/error.go index 5ae65d93..08120014 100644 --- a/_example/error.go +++ b/_example/error.go @@ -1,9 +1,11 @@ package main -import "github.com/aarzilli/golua/lua" -import "fmt" -import "errors" -import "os" +import ( + "github.com/aarzilli/golua/lua" + "fmt" + "errors" + "os" +) func testDefault(L *lua.State) { err := L.DoString("print(\"Unknown variable\" .. x)") diff --git a/_example/library.go b/_example/library.go index d968d82f..110028bd 100644 --- a/_example/library.go +++ b/_example/library.go @@ -13,7 +13,7 @@ func test2(L *lua.State) int { } var funcs = map[string]lua.LuaGoFunction{ - "test": test, + "test": test, "test2": test2, } @@ -27,7 +27,7 @@ func main() { L := lua.NewState() defer L.Close() L.OpenLibs() - + L.RegisterLibrary("example", funcs) if err := L.DoString(code); err != nil { diff --git a/_example/panic.go b/_example/panic.go index ef8b9d7d..cdc36cf0 100644 --- a/_example/panic.go +++ b/_example/panic.go @@ -1,7 +1,9 @@ package main -import "github.com/aarzilli/golua/lua" -import "fmt" +import ( + "github.com/aarzilli/golua/lua" + "fmt" +) func test(L *lua.State) int { fmt.Println("hello world! from go!") @@ -9,7 +11,6 @@ func test(L *lua.State) int { } func main() { - var L *lua.State L = lua.NewState() @@ -29,7 +30,7 @@ func main() { L.AtPanic(newPanic) - //force a panic + // force a panic L.PushNil() L.Call(0, 0) diff --git a/_example/userdata.go b/_example/userdata.go index 5cd56b36..e4c9e06f 100644 --- a/_example/userdata.go +++ b/_example/userdata.go @@ -1,8 +1,10 @@ package main -import "github.com/aarzilli/golua/lua" -import "unsafe" -import "fmt" +import ( + "github.com/aarzilli/golua/lua" + "unsafe" + "fmt" +) type Userdata struct { a, b int diff --git a/lua/dummy.go b/lua/dummy.go index 491fbb8b..485ec273 100644 --- a/lua/dummy.go +++ b/lua/dummy.go @@ -1,3 +1,4 @@ +//go:build dummy // +build dummy // This file is part of a workaround for `go mod vendor` which won't diff --git a/lua/golua.go b/lua/golua.go index 09ad9025..d09f5ad2 100644 --- a/lua/golua.go +++ b/lua/golua.go @@ -32,6 +32,7 @@ type HookFunction func(L *State) const ExecutionQuantumExceeded = "Lua execution quantum exceeded" // Wrapper to keep cgo from complaining about incomplete ptr type +// //export State type State struct { // Wrapped lua_State object @@ -55,8 +56,10 @@ type State struct { ctx context.Context } -var goStates map[uintptr]*State -var goStatesMutex sync.Mutex +var ( + goStates map[uintptr]*State + goStatesMutex sync.Mutex +) func init() { goStates = make(map[uintptr]*State, 16) diff --git a/lua/golua_c_lua51.go b/lua/golua_c_lua51.go index 4b59d4c5..1b08dfff 100644 --- a/lua/golua_c_lua51.go +++ b/lua/golua_c_lua51.go @@ -1,4 +1,5 @@ -//+build !lua52,!lua53,!lua54 +//go:build !lua52 && !lua53 && !lua54 +// +build !lua52,!lua53,!lua54 package lua diff --git a/lua/golua_c_lua52.go b/lua/golua_c_lua52.go index a792ccd1..ec891f81 100644 --- a/lua/golua_c_lua52.go +++ b/lua/golua_c_lua52.go @@ -1,4 +1,5 @@ -//+build lua52 +//go:build lua52 +// +build lua52 package lua diff --git a/lua/golua_c_lua53.go b/lua/golua_c_lua53.go index d490b1b0..5a11aec8 100644 --- a/lua/golua_c_lua53.go +++ b/lua/golua_c_lua53.go @@ -1,4 +1,5 @@ -//+build lua53 +//go:build lua53 +// +build lua53 package lua diff --git a/lua/golua_c_lua54.go b/lua/golua_c_lua54.go index 9acafe53..e27e4df0 100644 --- a/lua/golua_c_lua54.go +++ b/lua/golua_c_lua54.go @@ -1,4 +1,5 @@ -//+build lua54 +//go:build lua54 +// +build lua54 package lua diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 5dc43f53..282187f4 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -6,6 +6,7 @@ package lua //#include //#include "golua.h" import "C" + import ( "context" "unsafe" @@ -78,7 +79,7 @@ func (L *State) CheckString(narg int) string { // // BUG(everyone_involved): not implemented func (L *State) CheckOption(narg int, def string, lst []string) int { - //TODO: complication: lst conversion to const char* lst[] from string slice + // TODO: complication: lst conversion to const char* lst[] from string slice return 0 } diff --git a/lua/lua.go b/lua/lua.go index 15d365bf..207d0b1c 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -46,6 +46,7 @@ package lua */ import "C" + import ( "fmt" "unsafe" @@ -68,39 +69,39 @@ func newState(L *C.lua_State) *State { func (L *State) addFreeIndex(i uint) { freelen := len(L.freeIndices) - //reallocate if necessary + // reallocate if necessary if freelen+1 > cap(L.freeIndices) { newSlice := make([]uint, freelen, cap(L.freeIndices)*2) copy(newSlice, L.freeIndices) L.freeIndices = newSlice } - //reslice + // reslice L.freeIndices = L.freeIndices[0 : freelen+1] L.freeIndices[freelen] = i } func (L *State) getFreeIndex() (index uint, ok bool) { freelen := len(L.freeIndices) - //if there exist entries in the freelist + // if there exist entries in the freelist if freelen > 0 { - i := L.freeIndices[freelen-1] //get index - //fmt.Printf("Free indices before: %v\n", L.freeIndices) + i := L.freeIndices[freelen-1] // get index + // fmt.Printf("Free indices before: %v\n", L.freeIndices) L.freeIndices = L.freeIndices[0 : freelen-1] //'pop' index from list - //fmt.Printf("Free indices after: %v\n", L.freeIndices) + // fmt.Printf("Free indices after: %v\n", L.freeIndices) return i, true } return 0, false } -//returns the registered function id +// returns the registered function id func (L *State) register(f interface{}) uint { - //fmt.Printf("Registering %v\n") + // fmt.Printf("Registering %v\n") index, ok := L.getFreeIndex() - //fmt.Printf("\tfreeindex: index = %v, ok = %v\n", index, ok) - //if not ok, then we need to add new index by extending the slice + // fmt.Printf("\tfreeindex: index = %v, ok = %v\n", index, ok) + // if not ok, then we need to add new index by extending the slice if !ok { index = uint(len(L.registry)) - //reallocate backing array if necessary + // reallocate backing array if necessary if index+1 > uint(cap(L.registry)) { newcap := cap(L.registry) * 2 if index+1 > uint(newcap) { @@ -110,16 +111,16 @@ func (L *State) register(f interface{}) uint { copy(newSlice, L.registry) L.registry = newSlice } - //reslice + // reslice L.registry = L.registry[0 : index+1] } - //fmt.Printf("\tregistering %d %v\n", index, f) + // fmt.Printf("\tregistering %d %v\n", index, f) L.registry[index] = f return index } func (L *State) unregister(fid uint) { - //fmt.Printf("Unregistering %d (len: %d, value: %v)\n", fid, len(L.registry), L.registry[fid]) + // fmt.Printf("Unregistering %d (len: %d, value: %v)\n", fid, len(L.registry), L.registry[fid]) if (fid < uint(len(L.registry))) && (L.registry[fid] != nil) { L.registry[fid] = nil L.addFreeIndex(fid) @@ -144,14 +145,14 @@ func (L *State) PushGoClosure(f LuaGoFunction) { // // The code: // -// L.LGetMetaTable(tableName) -// L.SetMetaMethod(methodName, function) +// L.LGetMetaTable(tableName) +// L.SetMetaMethod(methodName, function) // // is the logical equivalent of: // -// L.LGetMetaTable(tableName) -// L.PushGoFunction(function) -// L.SetField(-2, methodName) +// L.LGetMetaTable(tableName) +// L.PushGoFunction(function) +// L.SetField(-2, methodName) // // except this wouldn't work because pushing a go function results in user data not a cfunction func (L *State) SetMetaMethod(methodName string, f LuaGoFunction) { @@ -172,7 +173,7 @@ func (L *State) PushGoStruct(iface interface{}) { // // This function doesn't save a reference to the interface, it is the responsibility of the caller of this function to insure that the interface outlasts the lifetime of the lua object that this function creates. func (L *State) PushLightUserdata(ud *interface{}) { - //push + // push C.lua_pushlightuserdata(L.s, unsafe.Pointer(ud)) } @@ -193,7 +194,7 @@ func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { switch i := oldres.(type) { case C.uint: f := L.registry[uint(i)].(LuaGoFunction) - //free registry entry + // free registry entry L.unregister(uint(i)) return f case C.lua_CFunction: @@ -201,8 +202,8 @@ func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { return int(C.clua_callluacfunc(L1.s, i)) } } - //generally we only get here if the panicf got set to something like nil - //potentially dangerous because we may silently fail + // generally we only get here if the panicf got set to something like nil + // potentially dangerous because we may silently fail return nil } @@ -350,8 +351,8 @@ func (L *State) NewTable() { // lua_newthread func (L *State) NewThread() *State { - //TODO: call newState with result from C.lua_newthread and return it - //TODO: should have same lists as parent + // TODO: call newState with result from C.lua_newthread and return it + // TODO: should have same lists as parent // but may complicate gc s := C.lua_newthread(L.s) return &State{s, 0, nil, nil, nil, nil, nil} @@ -365,8 +366,8 @@ func (L *State) Next(index int) int { // lua_objlen // lua_pop func (L *State) Pop(n int) { - //Why is this implemented this way? I don't get it... - //C.lua_pop(L.s, C.int(n)); + // Why is this implemented this way? I don't get it... + // C.lua_pop(L.s, C.int(n)); C.lua_settop(L.s, C.int(-n-1)) } @@ -543,7 +544,7 @@ func (L *State) ToPointer(index int) uintptr { // lua_tothread func (L *State) ToThread(index int) *State { - //TODO: find a way to link lua_State* to existing *State, return that + // TODO: find a way to link lua_State* to existing *State, return that return &State{} } diff --git a/lua/lua51/dummy.go b/lua/lua51/dummy.go index 651a7971..b632fce4 100644 --- a/lua/lua51/dummy.go +++ b/lua/lua51/dummy.go @@ -1,3 +1,4 @@ +//go:build dummy // +build dummy // Package lua contains only a C header files. diff --git a/lua/lua52/dummy.go b/lua/lua52/dummy.go index 651a7971..b632fce4 100644 --- a/lua/lua52/dummy.go +++ b/lua/lua52/dummy.go @@ -1,3 +1,4 @@ +//go:build dummy // +build dummy // Package lua contains only a C header files. diff --git a/lua/lua53/dummy.go b/lua/lua53/dummy.go index 651a7971..b632fce4 100644 --- a/lua/lua53/dummy.go +++ b/lua/lua53/dummy.go @@ -1,3 +1,4 @@ +//go:build dummy // +build dummy // Package lua contains only a C header files. diff --git a/lua/lua54/dummy.go b/lua/lua54/dummy.go index 651a7971..b632fce4 100644 --- a/lua/lua54/dummy.go +++ b/lua/lua54/dummy.go @@ -1,3 +1,4 @@ +//go:build dummy // +build dummy // Package lua contains only a C header files. diff --git a/lua/lua_defs_lua51.go b/lua/lua_defs_lua51.go index 3696c391..2f945fed 100644 --- a/lua/lua_defs_lua51.go +++ b/lua/lua_defs_lua51.go @@ -1,4 +1,5 @@ -//+build !lua52,!lua53,!lua54 +//go:build !lua52 && !lua53 && !lua54 +// +build !lua52,!lua53,!lua54 package lua diff --git a/lua/lua_defs_lua52.go b/lua/lua_defs_lua52.go index c6623f04..34901b1b 100644 --- a/lua/lua_defs_lua52.go +++ b/lua/lua_defs_lua52.go @@ -1,4 +1,5 @@ -//+build lua52 +//go:build lua52 +// +build lua52 package lua diff --git a/lua/lua_defs_lua53.go b/lua/lua_defs_lua53.go index 0a674338..e3ad80ef 100644 --- a/lua/lua_defs_lua53.go +++ b/lua/lua_defs_lua53.go @@ -1,4 +1,5 @@ -//+build lua53 +//go:build lua53 +// +build lua53 package lua diff --git a/lua/lua_defs_lua54.go b/lua/lua_defs_lua54.go index f3768358..122479a0 100644 --- a/lua/lua_defs_lua54.go +++ b/lua/lua_defs_lua54.go @@ -1,4 +1,5 @@ -//+build lua54 +//go:build lua54 +// +build lua54 package lua diff --git a/lua/lua_test.go b/lua/lua_test.go index 7191f077..895b71fb 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -130,7 +130,6 @@ func TestCall(t *testing.T) { L.PushString("Argument2") L.PushString("Argument3") err := L.Call(3, 2) - if err != nil { t.Fatalf("Error executing call: %v\n", err) } From 7609e5d3e887c3ad0d9b352b25ac3aed0081bdf8 Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Thu, 26 Dec 2024 19:54:50 +0100 Subject: [PATCH 094/100] feat: Add PushGoClosureWithUpvalues Also add GetUpvalue, SetUpvalue and UpvalueIndex --- lua/c-golua.c | 4 +-- lua/golua.h | 2 +- lua/lua.go | 38 +++++++++++++++++++++++--- lua/lua_test.go | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 7 deletions(-) diff --git a/lua/c-golua.c b/lua/c-golua.c index 79342af1..9c223754 100644 --- a/lua/c-golua.c +++ b/lua/c-golua.c @@ -117,9 +117,9 @@ static int callback_c (lua_State* L) return golua_callgofunction(gostateindex,fid); } -void clua_pushcallback(lua_State* L) +void clua_pushcallback(lua_State* L, unsigned int nup) { - lua_pushcclosure(L,callback_c,1); + lua_pushcclosure(L,callback_c, 1 + nup); } void clua_pushgostruct(lua_State* L, unsigned int iid) diff --git a/lua/golua.h b/lua/golua.h index 667e1abb..f9e6371a 100644 --- a/lua/golua.h +++ b/lua/golua.h @@ -10,7 +10,7 @@ void clua_hide_pcall(lua_State *L); unsigned int clua_togofunction(lua_State* L, int index); unsigned int clua_togostruct(lua_State *L, int index); -void clua_pushcallback(lua_State* L); +void clua_pushcallback(lua_State* L, unsigned int nup); void clua_pushgofunction(lua_State* L, unsigned int fid); void clua_pushgostruct(lua_State *L, unsigned int fid); void clua_setgostate(lua_State* L, size_t gostateindex); diff --git a/lua/lua.go b/lua/lua.go index 207d0b1c..9b479bd7 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -44,6 +44,11 @@ package lua #include "golua.h" +int clua_upvalueindex(int n) +{ + return lua_upvalueindex(n); +} + */ import "C" @@ -137,8 +142,33 @@ func (L *State) PushGoFunction(f LuaGoFunction) { // this permits the go function to reflect lua type 'function' when checking with type() // this implements behaviour akin to lua_pushcfunction() in lua C API. func (L *State) PushGoClosure(f LuaGoFunction) { - L.PushGoFunction(f) // leaves Go function userdata on stack - C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function + L.PushGoFunction(f) // leaves Go function userdata on stack + C.clua_pushcallback(L.s, 0) // wraps the userdata object with a closure making it into a function +} + +// PushGoClosureWithUpvalues pushes a GoClosure and provides 'nup' upvalues starting at index 2, +// because index 1 is to store the GoFunction in the Lua Closure +func (L *State) PushGoClosureWithUpvalues(f LuaGoFunction, nup uint) { + L.PushGoFunction(f) // leaves Go function userdata on stack + if nup > 0 { // GoFunction must be at upvalue 1 so push it back + L.Insert(-int(nup) - 1) + } + C.clua_pushcallback(L.s, C.uint(nup)) // wraps the userdata object with a closure making it into a function +} + +// lua_upvalueid +func (L *State) UpvalueIndex(n int) int { + return int(C.clua_upvalueindex(C.int32_t(n))) +} + +// lua_setupvalue +func (L *State) SetUpvalue(funcindex, n int) bool { + return C.lua_setupvalue(L.s, C.int(funcindex), C.int(n)) != nil +} + +// lua_getupvalue +func (L *State) GetUpvalue(funcindex, n int) { + C.lua_getupvalue(L.s, C.int(funcindex), C.int(n)) } // Sets a metamethod to execute a go function @@ -156,8 +186,8 @@ func (L *State) PushGoClosure(f LuaGoFunction) { // // except this wouldn't work because pushing a go function results in user data not a cfunction func (L *State) SetMetaMethod(methodName string, f LuaGoFunction) { - L.PushGoFunction(f) // leaves Go function userdata on stack - C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function + L.PushGoFunction(f) // leaves Go function userdata on stack + C.clua_pushcallback(L.s, 0) // wraps the userdata object with a closure making it into a function L.SetField(-2, methodName) } diff --git a/lua/lua_test.go b/lua/lua_test.go index 895b71fb..80c578fa 100644 --- a/lua/lua_test.go +++ b/lua/lua_test.go @@ -435,3 +435,75 @@ func TestCustomDebugHook(t *testing.T) { } } } + +func TestSetUpValueShouldErrorOnInvalidCall(t *testing.T) { + L := NewState() + defer L.Close() + + L.PushGoFunction(func(L *State) int { return 0 }) + L.PushString("Hello") + if L.SetUpvalue(-2, 1) == true { // Should not be succesful + t.Fatal("SetUpvalue should return false because an upvalue can't be set on userdata") + } + if L.GetTop() != 2 { + t.Fatal("Expected SetUpvalue to pop nothing on error") + } +} + +// This test is more an example to show why we can't directly set Upvalue on PushGoClosure, but rather +// have to rely on PushGoClosureWithUpvalues +func TestSetUpvalueOnGoClosureShouldErrorAt2(t *testing.T) { + L := NewState() + defer L.Close() + + L.PushGoClosure(func(L *State) int { return 0 }) + L.PushString("Hello") + // Should be succesful because the function returned by PushGoClosure actually has an upvalue + // at 1, which is the GoFunction userdata, that the closure calls. + if !L.SetUpvalue(-2, 1) { + t.Fatal("SetUpvalue should return false because an upvalue can't be set on userdata") + } + // Only the GoClosure should be left on the stack, since SetUpvalue was succesful + if L.GetTop() != 1 { + t.Fatalf("Expected GetTop to return 1 as SetUpvalue should pop value on success, but top is at: %d\n", L.GetTop()) + } + + L.PushString("Hello") + // Since this closure only has 1 upvalue. It shouldn't be possible to add a second after the fact + if L.SetUpvalue(-2, 2) { + t.Fatal("SetUpvalue should return false because setting an upvalue at a higher index after creation is not possible") + } + // Since SetUpvalue failed, the string should remain + if L.GetTop() != 2 { + t.Fatal("Expected SetUpvalue to pop nothing on error") + } +} + +func TestPushGoClosureWithUpvalues(t *testing.T) { + L := NewState() + defer L.Close() + + closure := func(L *State) int { + if !L.IsString(L.UpvalueIndex(2)) { + t.Fatalf("upvalue 2 not set correctly, expected it to be a string") + } + if !L.IsNumber(L.UpvalueIndex(3)) { + t.Fatalf("upvalue 3 not set correctly, expected it to be an number") + } + if L.ToString(L.UpvalueIndex(2)) != "Hello" { + t.Fatalf("upvalue 2 not set correctly, expected it to equal \"Hello\"") + } + if L.ToInteger(L.UpvalueIndex(3)) != 15 { + t.Fatalf("upvalue 3 not set correctly, expected it to equal 15") + } + return 0 + } + + L.PushString("Hello") + L.PushInteger(15) + L.PushGoClosureWithUpvalues(closure, 2) + err := L.Call(0, 0) + if err != nil { + t.Fatalf("Call to function returned by PushGoClosureWithUpvalues should not fail: %s\n", err.Error()) + } +} From c0240bbe60766217097edaee9c0e4a1e6fec48a6 Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Fri, 27 Dec 2024 00:29:21 +0100 Subject: [PATCH 095/100] docs: create doc generator --- _docgenerator/.gitignore | 1 + _docgenerator/example.txt | 8 ++ _docgenerator/go.mod | 10 ++ _docgenerator/go.sum | 40 ++++++++ _docgenerator/main.go | 188 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 _docgenerator/.gitignore create mode 100644 _docgenerator/example.txt create mode 100644 _docgenerator/go.mod create mode 100644 _docgenerator/go.sum create mode 100644 _docgenerator/main.go diff --git a/_docgenerator/.gitignore b/_docgenerator/.gitignore new file mode 100644 index 00000000..ceddaa37 --- /dev/null +++ b/_docgenerator/.gitignore @@ -0,0 +1 @@ +.cache/ diff --git a/_docgenerator/example.txt b/_docgenerator/example.txt new file mode 100644 index 00000000..39c47e82 --- /dev/null +++ b/_docgenerator/example.txt @@ -0,0 +1,8 @@ +// lua_upvalueid +/* + * [-0, +0, –] + * Returns a unique identifier for the upvalue numbered n from the closure at index funcindex. +*/ +func (L *State) UpvalueIndex(n int) int { + return int(C.clua_upvalueindex(C.int32_t(n))) +} diff --git a/_docgenerator/go.mod b/_docgenerator/go.mod new file mode 100644 index 00000000..cd9d9f82 --- /dev/null +++ b/_docgenerator/go.mod @@ -0,0 +1,10 @@ +module docgen + +go 1.23.4 + +require github.com/PuerkitoBio/goquery v1.10.0 + +require ( + github.com/andybalholm/cascadia v1.3.2 // indirect + golang.org/x/net v0.29.0 // indirect +) diff --git a/_docgenerator/go.sum b/_docgenerator/go.sum new file mode 100644 index 00000000..78d3c7af --- /dev/null +++ b/_docgenerator/go.sum @@ -0,0 +1,40 @@ +github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4= +github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/_docgenerator/main.go b/_docgenerator/main.go new file mode 100644 index 00000000..475fb255 --- /dev/null +++ b/_docgenerator/main.go @@ -0,0 +1,188 @@ +package main + +import ( + "flag" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/PuerkitoBio/goquery" +) + +var ( + flagDoWrite = flag.Bool("write", false, "Write to the opened file") + flagLuaVersion = flag.String("luaversion", "5.1", "Lua documentation version") + // flagHelp = flag.Bool("help", false, "Show help") + // flagHelpShort = flag.Bool("h", false, "Show help") +) + +func main() { + flag.Parse() + // if *flagHelp || *flagHelpShort { + // flag.Usage() + // return + // } + if len(os.Args) < 2 { + fmt.Printf("Usage: %s [-write] [-luaversion ] ", os.Args[0]) + os.Exit(1) + } + + goFile := flag.Arg(0) + + // Read Go code from file + goCode, err := os.ReadFile(goFile) + if err != nil { + fmt.Println("Error reading Go file:", err) + os.Exit(1) + } + + // Fetch or load cached Lua documentation + luadocs, err := getCachedLuaDocs() + if err != nil { + fmt.Println("Error fetching Lua documentation:", err) + os.Exit(1) + } + + luaFuncs, err := parseLuaDocs(luadocs) + if err != nil { + fmt.Println("Error parsing Lua documentation:", err) + os.Exit(1) + } + + // Add comments to the Go code + annotatedCode := addDocumentation(string(goCode), luaFuncs) + + if *flagDoWrite { + err := os.WriteFile(goFile, []byte(annotatedCode), 0644) + if err != nil { + fmt.Println("Error writing annotated code to file:", err) + os.Exit(1) + } + fmt.Println("Annotated code written back to", goFile) + } else { + fmt.Println(annotatedCode) + } +} + +// Fetch or load cached Lua documentation +func getCachedLuaDocs() (string, error) { + cacheDir := ".cache" + cacheFile := filepath.Join(cacheDir, fmt.Sprintf("lua_manual_%s.html", *flagLuaVersion)) + + // Ensure cache directory exists + if _, err := os.Stat(cacheDir); os.IsNotExist(err) { + err := os.Mkdir(cacheDir, 0755) + if err != nil { + return "", err + } + } + + // Check if cached file exists + var body string + if _, err := os.Stat(cacheFile); err == nil { + cachedBody, err := os.ReadFile(cacheFile) + if err != nil { + return "", err + } + body = string(cachedBody) + } else { + // Fetch Lua manual and cache it + url := fmt.Sprintf("https://www.lua.org/manual/%s/manual.html", *flagLuaVersion) // Change version as needed + resp, err := http.Get(url) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode > 299 { + return "", fmt.Errorf("unexpected error code for lua doc: %d", resp.StatusCode) + } + + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + body = string(bodyBytes) + + err = os.WriteFile(cacheFile, bodyBytes, 0644) + if err != nil { + return "", err + } + } + return body, nil +} + +type LuaFunction struct { + Name string + StackEffect string + Signature string + Description string +} + +func parseLuaDocs(html string) (map[string]LuaFunction, error) { + doc, err := goquery.NewDocumentFromReader(strings.NewReader(html)) + if err != nil { + return nil, err + } + + functions := map[string]LuaFunction{} + + doc.Find("hr + h3").Has("a[name^='lua_']").Each(func(i int, s *goquery.Selection) { + var luaFunc LuaFunction + + // Extract name + luaFunc.Name = s.Find("code").Text() + + // Extract stack effect + if goquery.NodeName(s.Next()) == "p" { + luaFunc.StackEffect = strings.TrimSpace(s.Next().Text()) + s = s.Next() + } + + if goquery.NodeName(s.Next()) == "pre" { + luaFunc.Signature = strings.TrimSpace(s.Next().Text()) + s = s.Next() + } + + if goquery.NodeName(s.Next()) == "p" { + luaFunc.Description = strings.ReplaceAll(strings.TrimSpace(s.Next().Text()), "\n", " ") + // s = s.Next() + } + + functions[strings.ToLower(luaFunc.Name)] = luaFunc + }) + + return functions, nil +} + +func removeOldDocumentation(code string) string { + blockCommentRegex := regexp.MustCompile(`(?m)(// lua_.*$\n)/\*\n(?: \*.*$\n)+[ ]?\*/$\n`) + return blockCommentRegex.ReplaceAllString(code, "$1") +} + +// Add documentation comments to the Go code +func addDocumentation(code string, luaFuncs map[string]LuaFunction) string { + code = removeOldDocumentation(code) + + lines := strings.Split(code, "\n") + var annotatedLines []string + + for _, line := range lines { + annotatedLines = append(annotatedLines, line) + if strings.HasPrefix(line, "// lua_") { + functionName := strings.TrimPrefix(line, "// ") + if doc, exists := luaFuncs[functionName]; exists { + annotatedLines = append(annotatedLines, "/*") + annotatedLines = append(annotatedLines, " * "+doc.StackEffect) + annotatedLines = append(annotatedLines, " * "+doc.Description) + annotatedLines = append(annotatedLines, " */") + } + } + } + + return strings.Join(annotatedLines, "\n") +} From 25c97913ed61a732e4bde2945e4d481693ee40dd Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Fri, 27 Dec 2024 00:31:26 +0100 Subject: [PATCH 096/100] docs: add documentation to methods --- lua/golua_c_lua51.go | 60 ++++++++++++++ lua/golua_c_lua52.go | 44 ++++++++++ lua/golua_c_lua53.go | 44 ++++++++++ lua/golua_c_lua54.go | 44 ++++++++++ lua/lua.go | 192 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 384 insertions(+) diff --git a/lua/golua_c_lua51.go b/lua/golua_c_lua51.go index 1b08dfff..27b97efb 100644 --- a/lua/golua_c_lua51.go +++ b/lua/golua_c_lua51.go @@ -124,21 +124,37 @@ func lualLoadFile(s *C.lua_State, filename *C.char) C.int { } // lua_equal +/* + * [-0, +0, e] + * Returns 1 if the two values in acceptable indices index1 and index2 are equal, following the semantics of the Lua == operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid. + */ func (L *State) Equal(index1, index2 int) bool { return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 } // lua_getfenv +/* + * [-0, +1, -] + * Pushes onto the stack the environment table of the value at the given index. + */ func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } // lua_lessthan +/* + * [-0, +0, e] + * Returns 1 if the value at acceptable index index1 is smaller than the value at acceptable index index2, following the semantics of the Lua < operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid. + */ func (L *State) LessThan(index1, index2 int) bool { return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 } // lua_setfenv +/* + * [-1, +0, -] + * Pops a table from the stack and sets it as the new environment for the value at the given index. If the value at the given index is neither a function nor a thread nor a userdata, lua_setfenv returns 0. Otherwise it returns 1. + */ func (L *State) SetfEnv(index int) { C.lua_setfenv(L.s, C.int(index)) } @@ -148,16 +164,28 @@ func (L *State) ObjLen(index int) uint { } // lua_tointeger +/* + * [-0, +0, -] + * Converts the Lua value at the given acceptable index to the signed integral type lua_Integer. The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tointeger returns 0. + */ func (L *State) ToInteger(index int) int { return int(C.lua_tointeger(L.s, C.int(index))) } // lua_tonumber +/* + * [-0, +0, -] + * Converts the Lua value at the given acceptable index to the C type lua_Number (see lua_Number). The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tonumber returns 0. + */ func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumber(L.s, C.int(index))) } // lua_yield +/* + * [-?, +?, -] + * Yields a coroutine. + */ func (L *State) Yield(nresults int) int { return int(C.lua_yield(L.s, C.int(nresults))) } @@ -170,11 +198,19 @@ func (L *State) pcall(nargs, nresults, errfunc int) int { func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } // lua_resume +/* + * [-?, +?, -] + * Starts and resumes a coroutine in a given thread. + */ func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, C.int(narg))) } // lua_setglobal +/* + * [-1, +0, e] + * Pops a value from the stack and sets it as the new value of global name. It is defined as a macro: + */ func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) @@ -182,29 +218,53 @@ func (L *State) SetGlobal(name string) { } // lua_insert +/* + * [-1, +1, -] + * Moves the top element into the given valid index, shifting up the elements above this index to open space. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } // lua_remove +/* + * [-1, +0, -] + * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Remove(index int) { C.lua_remove(L.s, C.int(index)) } // lua_replace +/* + * [-1, +0, -] + * Moves the top element into the given position (and pops it), without shifting any element (therefore replacing the value at the given position). + */ func (L *State) Replace(index int) { C.lua_replace(L.s, C.int(index)) } // lua_rawgeti +/* + * [-0, +1, -] + * Pushes onto the stack the value t[n], where t is the value at the given valid index. The access is raw; that is, it does not invoke metamethods. + */ func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.int(n)) } // lua_rawseti +/* + * [-1, +0, m] + * Does the equivalent of t[n] = v, where t is the value at the given valid index and v is the value at the top of the stack. + */ func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)) } // lua_gc +/* + * [-0, +0, e] + * Controls the garbage collector. + */ func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua52.go b/lua/golua_c_lua52.go index ec891f81..17b93b22 100644 --- a/lua/golua_c_lua52.go +++ b/lua/golua_c_lua52.go @@ -150,16 +150,28 @@ func (L *State) ObjLen(index int) uint { } // lua_tointeger +/* + * [-0, +0, –] + * Equivalent to lua_tointegerx with isnum equal to NULL. + */ func (L *State) ToInteger(index int) int { return int(C.lua_tointegerx(L.s, C.int(index), nil)) } // lua_tonumber +/* + * [-0, +0, –] + * Equivalent to lua_tonumberx with isnum equal to NULL. + */ func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumberx(L.s, C.int(index), nil)) } // lua_yield +/* + * [-?, +?, –] + * This function is equivalent to lua_yieldk, but it has no continuation (see §4.7). Therefore, when the thread resumes, it returns to the function that called the function calling lua_yield. + */ func (L *State) Yield(nresults int) int { return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) } @@ -176,11 +188,19 @@ func (L *State) GetGlobal(name string) { } // lua_resume +/* + * [-?, +?, –] + * Starts and resumes a coroutine in a given thread. + */ func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, nil, C.int(narg))) } // lua_setglobal +/* + * [-1, +0, e] + * Pops a value from the stack and sets it as the new value of global name. + */ func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) @@ -203,29 +223,53 @@ func (L *State) OpenCoroutine() { } // lua_insert +/* + * [-1, +1, –] + * Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } // lua_remove +/* + * [-1, +0, –] + * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Remove(index int) { C.lua_remove(L.s, C.int(index)) } // lua_replace +/* + * [-1, +0, –] + * Moves the top element into the given valid index without shifting any element (therefore replacing the value at the given index), and then pops the top element. + */ func (L *State) Replace(index int) { C.lua_replace(L.s, C.int(index)) } // lua_rawgeti +/* + * [-0, +1, –] + * Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw; that is, it does not invoke metamethods. + */ func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.int(n)) } // lua_rawseti +/* + * [-1, +0, e] + * Does the equivalent of t[n] = v, where t is the table at the given index and v is the value at the top of the stack. + */ func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)) } // lua_gc +/* + * [-0, +0, e] + * Controls the garbage collector. + */ func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua53.go b/lua/golua_c_lua53.go index 5a11aec8..993f97dd 100644 --- a/lua/golua_c_lua53.go +++ b/lua/golua_c_lua53.go @@ -150,16 +150,28 @@ func (L *State) ObjLen(index int) uint { } // lua_tointeger +/* + * [-0, +0, –] + * Equivalent to lua_tointegerx with isnum equal to NULL. + */ func (L *State) ToInteger(index int) int { return int(C.lua_tointegerx(L.s, C.int(index), nil)) } // lua_tonumber +/* + * [-0, +0, –] + * Equivalent to lua_tonumberx with isnum equal to NULL. + */ func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumberx(L.s, C.int(index), nil)) } // lua_yield +/* + * [-?, +?, e] + * This function is equivalent to lua_yieldk, but it has no continuation (see §4.7). Therefore, when the thread resumes, it continues the function that called the function calling lua_yield. + */ func (L *State) Yield(nresults int) int { return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) } @@ -176,11 +188,19 @@ func (L *State) GetGlobal(name string) { } // lua_resume +/* + * [-?, +?, –] + * Starts and resumes a coroutine in the given thread L. + */ func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, nil, C.int(narg))) } // lua_setglobal +/* + * [-1, +0, e] + * Pops a value from the stack and sets it as the new value of global name. + */ func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) @@ -203,31 +223,55 @@ func (L *State) OpenCoroutine() { } // lua_insert +/* + * [-1, +1, –] + * Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Insert(index int) { C.lua_rotate(L.s, C.int(index), 1) } // lua_remove +/* + * [-1, +0, –] + * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Remove(index int) { C.lua_rotate(L.s, C.int(index), -1) C.lua_settop(L.s, C.int(-2)) } // lua_replace +/* + * [-1, +0, –] + * Moves the top element into the given valid index without shifting any element (therefore replacing the value at that given index), and then pops the top element. + */ func (L *State) Replace(index int) { C.lua_copy(L.s, -1, C.int(index)) C.lua_settop(L.s, -2) } // lua_rawgeti +/* + * [-0, +1, –] + * Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw, that is, it does not invoke the __index metamethod. + */ func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.longlong(n)) } // lua_rawseti +/* + * [-1, +0, m] + * Does the equivalent of t[i] = v, where t is the table at the given index and v is the value at the top of the stack. + */ func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.longlong(n)) } // lua_gc +/* + * [-0, +0, m] + * Controls the garbage collector. + */ func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua54.go b/lua/golua_c_lua54.go index e27e4df0..10f4fecc 100644 --- a/lua/golua_c_lua54.go +++ b/lua/golua_c_lua54.go @@ -152,16 +152,28 @@ func (L *State) ObjLen(index int) uint { } // lua_tointeger +/* + * [-0, +0, –] + * Equivalent to lua_tointegerx with isnum equal to NULL. + */ func (L *State) ToInteger(index int) int { return int(C.lua_tointegerx(L.s, C.int(index), nil)) } // lua_tonumber +/* + * [-0, +0, –] + * Equivalent to lua_tonumberx with isnum equal to NULL. + */ func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumberx(L.s, C.int(index), nil)) } // lua_yield +/* + * [-?, +?, v] + * This function is equivalent to lua_yieldk, but it has no continuation (see §4.5). Therefore, when the thread resumes, it continues the function that called the function calling lua_yield. To avoid surprises, this function should be called only in a tail call. + */ func (L *State) Yield(nresults int) int { return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) } @@ -178,11 +190,19 @@ func (L *State) GetGlobal(name string) { } // lua_resume +/* + * [-?, +?, –] + * Starts and resumes a coroutine in the given thread L. + */ func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, nil, C.int(narg), nil)) } // lua_setglobal +/* + * [-1, +0, e] + * Pops a value from the stack and sets it as the new value of global name. + */ func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) @@ -200,31 +220,55 @@ func (L *State) OpenCoroutine() { } // lua_insert +/* + * [-1, +1, –] + * Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Insert(index int) { C.lua_rotate(L.s, C.int(index), 1) } // lua_remove +/* + * [-1, +0, –] + * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. + */ func (L *State) Remove(index int) { C.lua_rotate(L.s, C.int(index), -1) C.lua_settop(L.s, C.int(-2)) } // lua_replace +/* + * [-1, +0, –] + * Moves the top element into the given valid index without shifting any element (therefore replacing the value at that given index), and then pops the top element. + */ func (L *State) Replace(index int) { C.lua_copy(L.s, -1, C.int(index)) C.lua_settop(L.s, -2) } // lua_rawgeti +/* + * [-0, +1, –] + * Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw, that is, it does not use the __index metavalue. + */ func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.longlong(n)) } // lua_rawseti +/* + * [-1, +0, m] + * Does the equivalent of t[i] = v, where t is the table at the given index and v is the value on the top of the stack. + */ func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.longlong(n)) } // lua_gc +/* + * [-0, +0, –] + * Controls the garbage collector. + */ func (L *State) GC(what, data int) int { return int(C.lua_gc_compat(L.s, C.int(what), C.int(data))) } diff --git a/lua/lua.go b/lua/lua.go index 9b479bd7..dc273bea 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -162,11 +162,19 @@ func (L *State) UpvalueIndex(n int) int { } // lua_setupvalue +/* + * [-(0|1), +0, -] + * Sets the value of a closure's upvalue. It assigns the value at the top of the stack to the upvalue and returns its name. It also pops the value from the stack. Parameters funcindex and n are as in the lua_getupvalue (see lua_getupvalue). + */ func (L *State) SetUpvalue(funcindex, n int) bool { return C.lua_setupvalue(L.s, C.int(funcindex), C.int(n)) != nil } // lua_getupvalue +/* + * [-0, +(0|1), -] + * Gets information about a closure's upvalue. (For Lua functions, upvalues are the external local variables that the function uses, and that are consequently included in its closure.) lua_getupvalue gets the index n of an upvalue, pushes the upvalue's value onto the stack, and returns its name. funcindex points to the closure in the stack. (Upvalues have no particular order, as they are active through the whole function. So, they are numbered in an arbitrary order.) + */ func (L *State) GetUpvalue(funcindex, n int) { C.lua_getupvalue(L.s, C.int(funcindex), C.int(n)) } @@ -265,6 +273,10 @@ func (L *State) callEx(nargs, nresults int, catch bool) (err error) { } // lua_call +/* + * [-(nargs + 1), +nresults, e] + * Calls a function. + */ func (L *State) Call(nargs, nresults int) (err error) { return L.callEx(nargs, nresults, true) } @@ -275,27 +287,47 @@ func (L *State) MustCall(nargs, nresults int) { } // lua_checkstack +/* + * [-0, +0, m] + * Ensures that there are at least extra free stack slots in the stack. It returns false if it cannot grow the stack to that size. This function never shrinks the stack; if the stack is already larger than the new size, it is left unchanged. + */ func (L *State) CheckStack(extra int) bool { return C.lua_checkstack(L.s, C.int(extra)) != 0 } // lua_close +/* + * [-0, +0, -] + * Destroys all objects in the given Lua state (calling the corresponding garbage-collection metamethods, if any) and frees all dynamic memory used by this state. On several platforms, you may not need to call this function, because all resources are naturally released when the host program ends. On the other hand, long-running programs, such as a daemon or a web server, might need to release states as soon as they are not needed, to avoid growing too large. + */ func (L *State) Close() { C.lua_close(L.s) unregisterGoState(L) } // lua_concat +/* + * [-n, +1, e] + * Concatenates the n values at the top of the stack, pops them, and leaves the result at the top. If n is 1, the result is the single value on the stack (that is, the function does nothing); if n is 0, the result is the empty string. Concatenation is performed following the usual semantics of Lua (see §2.5.4). + */ func (L *State) Concat(n int) { C.lua_concat(L.s, C.int(n)) } // lua_createtable +/* + * [-0, +1, m] + * Creates a new empty table and pushes it onto the stack. The new table has space pre-allocated for narr array elements and nrec non-array elements. This pre-allocation is useful when you know exactly how many elements the table will have. Otherwise you can use the function lua_newtable. + */ func (L *State) CreateTable(narr int, nrec int) { C.lua_createtable(L.s, C.int(narr), C.int(nrec)) } // lua_getfield +/* + * [-0, +1, e] + * Pushes onto the stack the value t[k], where t is the value at the given valid index. As in Lua, this function may trigger a metamethod for the "index" event (see §2.8). + */ func (L *State) GetField(index int, k string) { Ck := C.CString(k) defer C.free(unsafe.Pointer(Ck)) @@ -303,14 +335,26 @@ func (L *State) GetField(index int, k string) { } // lua_getmetatable +/* + * [-0, +(0|1), -] + * Pushes onto the stack the metatable of the value at the given acceptable index. If the index is not valid, or if the value does not have a metatable, the function returns 0 and pushes nothing on the stack. + */ func (L *State) GetMetaTable(index int) bool { return C.lua_getmetatable(L.s, C.int(index)) != 0 } // lua_gettable +/* + * [-1, +1, e] + * Pushes onto the stack the value t[k], where t is the value at the given valid index and k is the value at the top of the stack. + */ func (L *State) GetTable(index int) { C.lua_gettable(L.s, C.int(index)) } // lua_gettop +/* + * [-0, +0, -] + * Returns the index of the top element in the stack. Because indices start at 1, this result is equal to the number of elements in the stack (and so 0 means an empty stack). + */ func (L *State) GetTop() int { return int(C.lua_gettop(L.s)) } // Returns true if lua_type == LUA_TBOOLEAN @@ -339,31 +383,63 @@ func (L *State) IsLightUserdata(index int) bool { } // lua_isnil +/* + * [-0, +0, -] + * Returns 1 if the value at the given acceptable index is nil, and 0 otherwise. + */ func (L *State) IsNil(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNIL } // lua_isnone +/* + * [-0, +0, -] + * Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack), and 0 otherwise. + */ func (L *State) IsNone(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNONE } // lua_isnoneornil +/* + * [-0, +0, -] + * Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack) or if the value at this index is nil, and 0 otherwise. + */ func (L *State) IsNoneOrNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) <= 0 } // lua_isnumber +/* + * [-0, +0, -] + * Returns 1 if the value at the given acceptable index is a number or a string convertible to a number, and 0 otherwise. + */ func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(index)) == 1 } // lua_isstring +/* + * [-0, +0, -] + * Returns 1 if the value at the given acceptable index is a string or a number (which is always convertible to a string), and 0 otherwise. + */ func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } // lua_istable +/* + * [-0, +0, -] + * Returns 1 if the value at the given acceptable index is a table, and 0 otherwise. + */ func (L *State) IsTable(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } // lua_isthread +/* + * [-0, +0, -] + * Returns 1 if the value at the given acceptable index is a thread, and 0 otherwise. + */ func (L *State) IsThread(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTHREAD } // lua_isuserdata +/* + * [-0, +0, -] + * Returns 1 if the value at the given acceptable index is a userdata (either full or light), and 0 otherwise. + */ func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int(index)) == 1 } // Creates a new lua interpreter state with the given allocation function @@ -375,11 +451,19 @@ func NewStateAlloc(f Alloc) *State { } // lua_newtable +/* + * [-0, +1, m] + * Creates a new empty table and pushes it onto the stack. It is equivalent to lua_createtable(L, 0, 0). + */ func (L *State) NewTable() { C.lua_createtable(L.s, 0, 0) } // lua_newthread +/* + * [-0, +1, m] + * Creates a new thread, pushes it on the stack, and returns a pointer to a lua_State that represents this new thread. The new state returned by this function shares with the original state all global objects (such as tables), but has an independent execution stack. + */ func (L *State) NewThread() *State { // TODO: call newState with result from C.lua_newthread and return it // TODO: should have same lists as parent @@ -389,12 +473,24 @@ func (L *State) NewThread() *State { } // lua_next +/* + * [-1, +(2|0), e] + * Pops a key from the stack, and pushes a key-value pair from the table at the given index (the "next" pair after the given key). If there are no more elements in the table, then lua_next returns 0 (and pushes nothing). + */ func (L *State) Next(index int) int { return int(C.lua_next(L.s, C.int(index))) } // lua_objlen +/* + * [-0, +0, -] + * Returns the "length" of the value at the given acceptable index: for strings, this is the string length; for tables, this is the result of the length operator ('#'); for userdata, this is the size of the block of memory allocated for the userdata; for other values, it is 0. + */ // lua_pop +/* + * [-n, +0, -] + * Pops n elements from the stack. + */ func (L *State) Pop(n int) { // Why is this implemented this way? I don't get it... // C.lua_pop(L.s, C.int(n)); @@ -402,6 +498,10 @@ func (L *State) Pop(n int) { } // lua_pushboolean +/* + * [-0, +1, -] + * Pushes a boolean value with value b onto the stack. + */ func (L *State) PushBoolean(b bool) { var bint int if b { @@ -413,6 +513,10 @@ func (L *State) PushBoolean(b bool) { } // lua_pushstring +/* + * [-0, +1, m] + * Pushes the zero-terminated string pointed to by s onto the stack. Lua makes (or reuses) an internal copy of the given string, so the memory at s can be freed or reused immediately after the function returns. The string cannot contain embedded zeros; it is assumed to end at the first zero. + */ func (L *State) PushString(str string) { Cstr := C.CString(str) defer C.free(unsafe.Pointer(Cstr)) @@ -424,41 +528,73 @@ func (L *State) PushBytes(b []byte) { } // lua_pushinteger +/* + * [-0, +1, -] + * Pushes a number with value n onto the stack. + */ func (L *State) PushInteger(n int64) { C.lua_pushinteger(L.s, C.lua_Integer(n)) } // lua_pushnil +/* + * [-0, +1, -] + * Pushes a nil value onto the stack. + */ func (L *State) PushNil() { C.lua_pushnil(L.s) } // lua_pushnumber +/* + * [-0, +1, -] + * Pushes a number with value n onto the stack. + */ func (L *State) PushNumber(n float64) { C.lua_pushnumber(L.s, C.lua_Number(n)) } // lua_pushthread +/* + * [-0, +1, -] + * Pushes the thread represented by L onto the stack. Returns 1 if this thread is the main thread of its state. + */ func (L *State) PushThread() (isMain bool) { return C.lua_pushthread(L.s) != 0 } // lua_pushvalue +/* + * [-0, +1, -] + * Pushes a copy of the element at the given valid index onto the stack. + */ func (L *State) PushValue(index int) { C.lua_pushvalue(L.s, C.int(index)) } // lua_rawequal +/* + * [-0, +0, -] + * Returns 1 if the two values in acceptable indices index1 and index2 are primitively equal (that is, without calling metamethods). Otherwise returns 0. Also returns 0 if any of the indices are non valid. + */ func (L *State) RawEqual(index1 int, index2 int) bool { return C.lua_rawequal(L.s, C.int(index1), C.int(index2)) != 0 } // lua_rawget +/* + * [-1, +1, -] + * Similar to lua_gettable, but does a raw access (i.e., without metamethods). + */ func (L *State) RawGet(index int) { C.lua_rawget(L.s, C.int(index)) } // lua_rawset +/* + * [-2, +0, m] + * Similar to lua_settable, but does a raw assignment (i.e., without metamethods). + */ func (L *State) RawSet(index int) { C.lua_rawset(L.s, C.int(index)) } @@ -493,12 +629,20 @@ func (L *State) RegisterLibrary(name string, funcs map[string]LuaGoFunction) { } // lua_setallocf +/* + * [-0, +0, -] + * Changes the allocator function of a given state to f with user data ud. + */ func (L *State) SetAllocf(f Alloc) { L.allocfn = &f C.clua_setallocf(L.s, unsafe.Pointer(L.allocfn)) } // lua_setfield +/* + * [-1, +0, e] + * Does the equivalent to t[k] = v, where t is the value at the given valid index and v is the value at the top of the stack. + */ func (L *State) SetField(index int, k string) { Ck := C.CString(k) defer C.free(unsafe.Pointer(Ck)) @@ -506,26 +650,46 @@ func (L *State) SetField(index int, k string) { } // lua_setmetatable +/* + * [-1, +0, -] + * Pops a table from the stack and sets it as the new metatable for the value at the given acceptable index. + */ func (L *State) SetMetaTable(index int) { C.lua_setmetatable(L.s, C.int(index)) } // lua_settable +/* + * [-2, +0, e] + * Does the equivalent to t[k] = v, where t is the value at the given valid index, v is the value at the top of the stack, and k is the value just below the top. + */ func (L *State) SetTable(index int) { C.lua_settable(L.s, C.int(index)) } // lua_settop +/* + * [-?, +?, -] + * Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with nil. If index is 0, then all stack elements are removed. + */ func (L *State) SetTop(index int) { C.lua_settop(L.s, C.int(index)) } // lua_status +/* + * [-0, +0, -] + * Returns the status of the thread L. + */ func (L *State) Status() int { return int(C.lua_status(L.s)) } // lua_toboolean +/* + * [-0, +0, -] + * Converts the Lua value at the given acceptable index to a C boolean value (0 or 1). Like all tests in Lua, lua_toboolean returns 1 for any Lua value different from false and nil; otherwise it returns 0. It also returns 0 when called with a non-valid index. (If you want to accept only actual boolean values, use lua_isboolean to test the value's type.) + */ func (L *State) ToBoolean(index int) bool { return C.lua_toboolean(L.s, C.int(index)) != 0 } @@ -555,6 +719,10 @@ func (L *State) ToGoStruct(index int) (f interface{}) { } // lua_tostring +/* + * [-0, +0, m] + * Equivalent to lua_tolstring with len equal to NULL. + */ func (L *State) ToString(index int) string { var size C.size_t r := C.lua_tolstring(L.s, C.int(index), &size) @@ -568,32 +736,56 @@ func (L *State) ToBytes(index int) []byte { } // lua_topointer +/* + * [-0, +0, -] + * Converts the value at the given acceptable index to a generic C pointer (void*). The value can be a userdata, a table, a thread, or a function; otherwise, lua_topointer returns NULL. Different objects will give different pointers. There is no way to convert the pointer back to its original value. + */ func (L *State) ToPointer(index int) uintptr { return uintptr(C.lua_topointer(L.s, C.int(index))) } // lua_tothread +/* + * [-0, +0, -] + * Converts the value at the given acceptable index to a Lua thread (represented as lua_State*). This value must be a thread; otherwise, the function returns NULL. + */ func (L *State) ToThread(index int) *State { // TODO: find a way to link lua_State* to existing *State, return that return &State{} } // lua_touserdata +/* + * [-0, +0, -] + * If the value at the given acceptable index is a full userdata, returns its block address. If the value is a light userdata, returns its pointer. Otherwise, returns NULL. + */ func (L *State) ToUserdata(index int) unsafe.Pointer { return unsafe.Pointer(C.lua_touserdata(L.s, C.int(index))) } // lua_type +/* + * [-0, +0, -] + * Returns the type of the value in the given acceptable index, or LUA_TNONE for a non-valid index (that is, an index to an "empty" stack position). The types returned by lua_type are coded by the following constants defined in lua.h: LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA. + */ func (L *State) Type(index int) LuaValType { return LuaValType(C.lua_type(L.s, C.int(index))) } // lua_typename +/* + * [-0, +0, -] + * Returns the name of the type encoded by the value tp, which must be one the values returned by lua_type. + */ func (L *State) Typename(tp int) string { return C.GoString(C.lua_typename(L.s, C.int(tp))) } // lua_xmove +/* + * [-?, +?, -] + * Exchange values between different threads of the same global state. + */ func XMove(from *State, to *State, n int) { C.lua_xmove(from.s, to.s, C.int(n)) } From b6690b5a9e92716b6b684a3436a8237cbc813b40 Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Fri, 27 Dec 2024 00:41:33 +0100 Subject: [PATCH 097/100] docs: Add -clean option to remove added docs --- _docgenerator/main.go | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/_docgenerator/main.go b/_docgenerator/main.go index 475fb255..ba81c375 100644 --- a/_docgenerator/main.go +++ b/_docgenerator/main.go @@ -15,6 +15,7 @@ import ( var ( flagDoWrite = flag.Bool("write", false, "Write to the opened file") + flagClean = flag.Bool("clean", false, "Removes the added documentation (use with -write)") flagLuaVersion = flag.String("luaversion", "5.1", "Lua documentation version") // flagHelp = flag.Bool("help", false, "Show help") // flagHelpShort = flag.Bool("h", false, "Show help") @@ -27,7 +28,7 @@ func main() { // return // } if len(os.Args) < 2 { - fmt.Printf("Usage: %s [-write] [-luaversion ] ", os.Args[0]) + fmt.Printf("Usage: %s [-write] [-clean] [-luaversion ] ", os.Args[0]) os.Exit(1) } @@ -40,31 +41,37 @@ func main() { os.Exit(1) } - // Fetch or load cached Lua documentation - luadocs, err := getCachedLuaDocs() - if err != nil { - fmt.Println("Error fetching Lua documentation:", err) - os.Exit(1) - } + updatedCode := "" + if *flagClean { + updatedCode = removeOldDocumentation(string(goCode)) + } else { - luaFuncs, err := parseLuaDocs(luadocs) - if err != nil { - fmt.Println("Error parsing Lua documentation:", err) - os.Exit(1) - } + // Fetch or load cached Lua documentation + luadocs, err := getCachedLuaDocs() + if err != nil { + fmt.Println("Error fetching Lua documentation:", err) + os.Exit(1) + } - // Add comments to the Go code - annotatedCode := addDocumentation(string(goCode), luaFuncs) + luaFuncs, err := parseLuaDocs(luadocs) + if err != nil { + fmt.Println("Error parsing Lua documentation:", err) + os.Exit(1) + } + + // Add comments to the Go code + updatedCode = addDocumentation(string(goCode), luaFuncs) + } if *flagDoWrite { - err := os.WriteFile(goFile, []byte(annotatedCode), 0644) + err := os.WriteFile(goFile, []byte(updatedCode), 0644) if err != nil { fmt.Println("Error writing annotated code to file:", err) os.Exit(1) } fmt.Println("Annotated code written back to", goFile) } else { - fmt.Println(annotatedCode) + fmt.Println(updatedCode) } } From e3db1ba0c573d78a7c7caa066a540aa7d178e9da Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Fri, 27 Dec 2024 20:44:07 +0100 Subject: [PATCH 098/100] docs: fix comment formatting --- _docgenerator/example.txt | 6 +- _docgenerator/main.go | 39 +-- lua/golua_c_lua51.go | 150 ++++++------ lua/golua_c_lua52.go | 110 ++++----- lua/golua_c_lua53.go | 110 ++++----- lua/golua_c_lua54.go | 110 ++++----- lua/lauxlib.go | 162 ++++++++++--- lua/lua.go | 482 +++++++++++++++++++------------------- 8 files changed, 641 insertions(+), 528 deletions(-) diff --git a/_docgenerator/example.txt b/_docgenerator/example.txt index 39c47e82..03257ff8 100644 --- a/_docgenerator/example.txt +++ b/_docgenerator/example.txt @@ -1,8 +1,4 @@ -// lua_upvalueid -/* - * [-0, +0, –] - * Returns a unique identifier for the upvalue numbered n from the closure at index funcindex. -*/ +// lua_upvalueindex func (L *State) UpvalueIndex(n int) int { return int(C.clua_upvalueindex(C.int32_t(n))) } diff --git a/_docgenerator/main.go b/_docgenerator/main.go index ba81c375..5d2ad2d8 100644 --- a/_docgenerator/main.go +++ b/_docgenerator/main.go @@ -45,7 +45,6 @@ func main() { if *flagClean { updatedCode = removeOldDocumentation(string(goCode)) } else { - // Fetch or load cached Lua documentation luadocs, err := getCachedLuaDocs() if err != nil { @@ -64,7 +63,7 @@ func main() { } if *flagDoWrite { - err := os.WriteFile(goFile, []byte(updatedCode), 0644) + err := os.WriteFile(goFile, []byte(updatedCode), 0o644) if err != nil { fmt.Println("Error writing annotated code to file:", err) os.Exit(1) @@ -82,7 +81,7 @@ func getCachedLuaDocs() (string, error) { // Ensure cache directory exists if _, err := os.Stat(cacheDir); os.IsNotExist(err) { - err := os.Mkdir(cacheDir, 0755) + err := os.Mkdir(cacheDir, 0o755) if err != nil { return "", err } @@ -98,7 +97,7 @@ func getCachedLuaDocs() (string, error) { body = string(cachedBody) } else { // Fetch Lua manual and cache it - url := fmt.Sprintf("https://www.lua.org/manual/%s/manual.html", *flagLuaVersion) // Change version as needed + url := luaManualURL("") resp, err := http.Get(url) if err != nil { return "", err @@ -115,7 +114,7 @@ func getCachedLuaDocs() (string, error) { } body = string(bodyBytes) - err = os.WriteFile(cacheFile, bodyBytes, 0644) + err = os.WriteFile(cacheFile, bodyBytes, 0o644) if err != nil { return "", err } @@ -130,6 +129,10 @@ type LuaFunction struct { Description string } +func luaManualURL(anchor string) string { + return fmt.Sprintf("https://www.lua.org/manual/%s/manual.html#%s", *flagLuaVersion, anchor) // Change version as needed +} + func parseLuaDocs(html string) (map[string]LuaFunction, error) { doc, err := goquery.NewDocumentFromReader(strings.NewReader(html)) if err != nil { @@ -138,7 +141,7 @@ func parseLuaDocs(html string) (map[string]LuaFunction, error) { functions := map[string]LuaFunction{} - doc.Find("hr + h3").Has("a[name^='lua_']").Each(func(i int, s *goquery.Selection) { + doc.Find("hr + h3").Has("a[name^='lua']").Each(func(i int, s *goquery.Selection) { var luaFunc LuaFunction // Extract name @@ -167,8 +170,8 @@ func parseLuaDocs(html string) (map[string]LuaFunction, error) { } func removeOldDocumentation(code string) string { - blockCommentRegex := regexp.MustCompile(`(?m)(// lua_.*$\n)/\*\n(?: \*.*$\n)+[ ]?\*/$\n`) - return blockCommentRegex.ReplaceAllString(code, "$1") + blockCommentRegex := regexp.MustCompile(`(?m)// \[(lua.*)\] -> .*$\n(// .*$\n)+`) + return blockCommentRegex.ReplaceAllString(code, "// $1\n") } // Add documentation comments to the Go code @@ -178,16 +181,22 @@ func addDocumentation(code string, luaFuncs map[string]LuaFunction) string { lines := strings.Split(code, "\n") var annotatedLines []string + matchComment := regexp.MustCompile(`// luaL?_.+`) + for _, line := range lines { - annotatedLines = append(annotatedLines, line) - if strings.HasPrefix(line, "// lua_") { + if matchComment.MatchString(line) { functionName := strings.TrimPrefix(line, "// ") - if doc, exists := luaFuncs[functionName]; exists { - annotatedLines = append(annotatedLines, "/*") - annotatedLines = append(annotatedLines, " * "+doc.StackEffect) - annotatedLines = append(annotatedLines, " * "+doc.Description) - annotatedLines = append(annotatedLines, " */") + if doc, exists := luaFuncs[strings.ToLower(functionName)]; exists { + annotatedLines = append(annotatedLines, fmt.Sprintf("// [%s] -> %s", doc.Name, doc.StackEffect)) + annotatedLines = append(annotatedLines, "//") + annotatedLines = append(annotatedLines, "// "+doc.Description) + annotatedLines = append(annotatedLines, "//") + annotatedLines = append(annotatedLines, fmt.Sprintf("// [%s]: %s", doc.Name, luaManualURL(strings.ToLower(doc.Name)))) + } else { + annotatedLines = append(annotatedLines, "// "+functionName) } + } else { + annotatedLines = append(annotatedLines, line) } } diff --git a/lua/golua_c_lua51.go b/lua/golua_c_lua51.go index 27b97efb..39a7cd07 100644 --- a/lua/golua_c_lua51.go +++ b/lua/golua_c_lua51.go @@ -123,38 +123,38 @@ func lualLoadFile(s *C.lua_State, filename *C.char) C.int { return C.luaL_loadfile(s, filename) } -// lua_equal -/* - * [-0, +0, e] - * Returns 1 if the two values in acceptable indices index1 and index2 are equal, following the semantics of the Lua == operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid. - */ +// [lua_equal] -> [-0, +0, e] +// +// Returns 1 if the two values in acceptable indices index1 and index2 are equal, following the semantics of the Lua == operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid. +// +// [lua_equal]: https://www.lua.org/manual/5.1/manual.html#lua_equal func (L *State) Equal(index1, index2 int) bool { return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 } -// lua_getfenv -/* - * [-0, +1, -] - * Pushes onto the stack the environment table of the value at the given index. - */ +// [lua_getfenv] -> [-0, +1, -] +// +// Pushes onto the stack the environment table of the value at the given index. +// +// [lua_getfenv]: https://www.lua.org/manual/5.1/manual.html#lua_getfenv func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } -// lua_lessthan -/* - * [-0, +0, e] - * Returns 1 if the value at acceptable index index1 is smaller than the value at acceptable index index2, following the semantics of the Lua < operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid. - */ +// [lua_lessthan] -> [-0, +0, e] +// +// Returns 1 if the value at acceptable index index1 is smaller than the value at acceptable index index2, following the semantics of the Lua < operator (that is, may call metamethods). Otherwise returns 0. Also returns 0 if any of the indices is non valid. +// +// [lua_lessthan]: https://www.lua.org/manual/5.1/manual.html#lua_lessthan func (L *State) LessThan(index1, index2 int) bool { return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 } -// lua_setfenv -/* - * [-1, +0, -] - * Pops a table from the stack and sets it as the new environment for the value at the given index. If the value at the given index is neither a function nor a thread nor a userdata, lua_setfenv returns 0. Otherwise it returns 1. - */ +// [lua_setfenv] -> [-1, +0, -] +// +// Pops a table from the stack and sets it as the new environment for the value at the given index. If the value at the given index is neither a function nor a thread nor a userdata, lua_setfenv returns 0. Otherwise it returns 1. +// +// [lua_setfenv]: https://www.lua.org/manual/5.1/manual.html#lua_setfenv func (L *State) SetfEnv(index int) { C.lua_setfenv(L.s, C.int(index)) } @@ -163,29 +163,29 @@ func (L *State) ObjLen(index int) uint { return uint(C.lua_objlen(L.s, C.int(index))) } -// lua_tointeger -/* - * [-0, +0, -] - * Converts the Lua value at the given acceptable index to the signed integral type lua_Integer. The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tointeger returns 0. - */ +// [lua_tointeger] -> [-0, +0, -] +// +// Converts the Lua value at the given acceptable index to the signed integral type lua_Integer. The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tointeger returns 0. +// +// [lua_tointeger]: https://www.lua.org/manual/5.1/manual.html#lua_tointeger func (L *State) ToInteger(index int) int { return int(C.lua_tointeger(L.s, C.int(index))) } -// lua_tonumber -/* - * [-0, +0, -] - * Converts the Lua value at the given acceptable index to the C type lua_Number (see lua_Number). The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tonumber returns 0. - */ +// [lua_tonumber] -> [-0, +0, -] +// +// Converts the Lua value at the given acceptable index to the C type lua_Number (see lua_Number). The Lua value must be a number or a string convertible to a number (see §2.2.1); otherwise, lua_tonumber returns 0. +// +// [lua_tonumber]: https://www.lua.org/manual/5.1/manual.html#lua_tonumber func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumber(L.s, C.int(index))) } -// lua_yield -/* - * [-?, +?, -] - * Yields a coroutine. - */ +// [lua_yield] -> [-?, +?, -] +// +// Yields a coroutine. +// +// [lua_yield]: https://www.lua.org/manual/5.1/manual.html#lua_yield func (L *State) Yield(nresults int) int { return int(C.lua_yield(L.s, C.int(nresults))) } @@ -197,74 +197,74 @@ func (L *State) pcall(nargs, nresults, errfunc int) int { // Pushes on the stack the value of a global variable (lua_getglobal) func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } -// lua_resume -/* - * [-?, +?, -] - * Starts and resumes a coroutine in a given thread. - */ +// [lua_resume] -> [-?, +?, -] +// +// Starts and resumes a coroutine in a given thread. +// +// [lua_resume]: https://www.lua.org/manual/5.1/manual.html#lua_resume func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, C.int(narg))) } -// lua_setglobal -/* - * [-1, +0, e] - * Pops a value from the stack and sets it as the new value of global name. It is defined as a macro: - */ +// [lua_setglobal] -> [-1, +0, e] +// +// Pops a value from the stack and sets it as the new value of global name. It is defined as a macro: +// +// [lua_setglobal]: https://www.lua.org/manual/5.1/manual.html#lua_setglobal func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) C.lua_setfield(L.s, C.int(LUA_GLOBALSINDEX), Cname) } -// lua_insert -/* - * [-1, +1, -] - * Moves the top element into the given valid index, shifting up the elements above this index to open space. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_insert] -> [-1, +1, -] +// +// Moves the top element into the given valid index, shifting up the elements above this index to open space. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_insert]: https://www.lua.org/manual/5.1/manual.html#lua_insert func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } -// lua_remove -/* - * [-1, +0, -] - * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_remove] -> [-1, +0, -] +// +// Removes the element at the given valid index, shifting down the elements above this index to fill the gap. Cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_remove]: https://www.lua.org/manual/5.1/manual.html#lua_remove func (L *State) Remove(index int) { C.lua_remove(L.s, C.int(index)) } -// lua_replace -/* - * [-1, +0, -] - * Moves the top element into the given position (and pops it), without shifting any element (therefore replacing the value at the given position). - */ +// [lua_replace] -> [-1, +0, -] +// +// Moves the top element into the given position (and pops it), without shifting any element (therefore replacing the value at the given position). +// +// [lua_replace]: https://www.lua.org/manual/5.1/manual.html#lua_replace func (L *State) Replace(index int) { C.lua_replace(L.s, C.int(index)) } -// lua_rawgeti -/* - * [-0, +1, -] - * Pushes onto the stack the value t[n], where t is the value at the given valid index. The access is raw; that is, it does not invoke metamethods. - */ +// [lua_rawgeti] -> [-0, +1, -] +// +// Pushes onto the stack the value t[n], where t is the value at the given valid index. The access is raw; that is, it does not invoke metamethods. +// +// [lua_rawgeti]: https://www.lua.org/manual/5.1/manual.html#lua_rawgeti func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.int(n)) } -// lua_rawseti -/* - * [-1, +0, m] - * Does the equivalent of t[n] = v, where t is the value at the given valid index and v is the value at the top of the stack. - */ +// [lua_rawseti] -> [-1, +0, m] +// +// Does the equivalent of t[n] = v, where t is the value at the given valid index and v is the value at the top of the stack. +// +// [lua_rawseti]: https://www.lua.org/manual/5.1/manual.html#lua_rawseti func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)) } -// lua_gc -/* - * [-0, +0, e] - * Controls the garbage collector. - */ +// [lua_gc] -> [-0, +0, e] +// +// Controls the garbage collector. +// +// [lua_gc]: https://www.lua.org/manual/5.1/manual.html#lua_gc func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua52.go b/lua/golua_c_lua52.go index 17b93b22..87b10e3c 100644 --- a/lua/golua_c_lua52.go +++ b/lua/golua_c_lua52.go @@ -149,29 +149,29 @@ func (L *State) ObjLen(index int) uint { return uint(C.lua_rawlen(L.s, C.int(index))) } -// lua_tointeger -/* - * [-0, +0, –] - * Equivalent to lua_tointegerx with isnum equal to NULL. - */ +// [lua_tointeger] -> [-0, +0, –] +// +// Equivalent to lua_tointegerx with isnum equal to NULL. +// +// [lua_tointeger]: https://www.lua.org/manual/5.2/manual.html#lua_tointeger func (L *State) ToInteger(index int) int { return int(C.lua_tointegerx(L.s, C.int(index), nil)) } -// lua_tonumber -/* - * [-0, +0, –] - * Equivalent to lua_tonumberx with isnum equal to NULL. - */ +// [lua_tonumber] -> [-0, +0, –] +// +// Equivalent to lua_tonumberx with isnum equal to NULL. +// +// [lua_tonumber]: https://www.lua.org/manual/5.2/manual.html#lua_tonumber func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumberx(L.s, C.int(index), nil)) } -// lua_yield -/* - * [-?, +?, –] - * This function is equivalent to lua_yieldk, but it has no continuation (see §4.7). Therefore, when the thread resumes, it returns to the function that called the function calling lua_yield. - */ +// [lua_yield] -> [-?, +?, –] +// +// This function is equivalent to lua_yieldk, but it has no continuation (see §4.7). Therefore, when the thread resumes, it returns to the function that called the function calling lua_yield. +// +// [lua_yield]: https://www.lua.org/manual/5.2/manual.html#lua_yield func (L *State) Yield(nresults int) int { return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) } @@ -187,20 +187,20 @@ func (L *State) GetGlobal(name string) { C.lua_getglobal(L.s, Ck) } -// lua_resume -/* - * [-?, +?, –] - * Starts and resumes a coroutine in a given thread. - */ +// [lua_resume] -> [-?, +?, –] +// +// Starts and resumes a coroutine in a given thread. +// +// [lua_resume]: https://www.lua.org/manual/5.2/manual.html#lua_resume func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, nil, C.int(narg))) } -// lua_setglobal -/* - * [-1, +0, e] - * Pops a value from the stack and sets it as the new value of global name. - */ +// [lua_setglobal] -> [-1, +0, e] +// +// Pops a value from the stack and sets it as the new value of global name. +// +// [lua_setglobal]: https://www.lua.org/manual/5.2/manual.html#lua_setglobal func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) @@ -222,54 +222,54 @@ func (L *State) OpenCoroutine() { C.clua_opencoroutine(L.s) } -// lua_insert -/* - * [-1, +1, –] - * Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_insert] -> [-1, +1, –] +// +// Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_insert]: https://www.lua.org/manual/5.2/manual.html#lua_insert func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } -// lua_remove -/* - * [-1, +0, –] - * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_remove] -> [-1, +0, –] +// +// Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_remove]: https://www.lua.org/manual/5.2/manual.html#lua_remove func (L *State) Remove(index int) { C.lua_remove(L.s, C.int(index)) } -// lua_replace -/* - * [-1, +0, –] - * Moves the top element into the given valid index without shifting any element (therefore replacing the value at the given index), and then pops the top element. - */ +// [lua_replace] -> [-1, +0, –] +// +// Moves the top element into the given valid index without shifting any element (therefore replacing the value at the given index), and then pops the top element. +// +// [lua_replace]: https://www.lua.org/manual/5.2/manual.html#lua_replace func (L *State) Replace(index int) { C.lua_replace(L.s, C.int(index)) } -// lua_rawgeti -/* - * [-0, +1, –] - * Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw; that is, it does not invoke metamethods. - */ +// [lua_rawgeti] -> [-0, +1, –] +// +// Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw; that is, it does not invoke metamethods. +// +// [lua_rawgeti]: https://www.lua.org/manual/5.2/manual.html#lua_rawgeti func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.int(n)) } -// lua_rawseti -/* - * [-1, +0, e] - * Does the equivalent of t[n] = v, where t is the table at the given index and v is the value at the top of the stack. - */ +// [lua_rawseti] -> [-1, +0, e] +// +// Does the equivalent of t[n] = v, where t is the table at the given index and v is the value at the top of the stack. +// +// [lua_rawseti]: https://www.lua.org/manual/5.2/manual.html#lua_rawseti func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.int(n)) } -// lua_gc -/* - * [-0, +0, e] - * Controls the garbage collector. - */ +// [lua_gc] -> [-0, +0, e] +// +// Controls the garbage collector. +// +// [lua_gc]: https://www.lua.org/manual/5.2/manual.html#lua_gc func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua53.go b/lua/golua_c_lua53.go index 993f97dd..3b5ec18b 100644 --- a/lua/golua_c_lua53.go +++ b/lua/golua_c_lua53.go @@ -149,29 +149,29 @@ func (L *State) ObjLen(index int) uint { return uint(C.lua_rawlen(L.s, C.int(index))) } -// lua_tointeger -/* - * [-0, +0, –] - * Equivalent to lua_tointegerx with isnum equal to NULL. - */ +// [lua_tointeger] -> [-0, +0, –] +// +// Equivalent to lua_tointegerx with isnum equal to NULL. +// +// [lua_tointeger]: https://www.lua.org/manual/5.3/manual.html#lua_tointeger func (L *State) ToInteger(index int) int { return int(C.lua_tointegerx(L.s, C.int(index), nil)) } -// lua_tonumber -/* - * [-0, +0, –] - * Equivalent to lua_tonumberx with isnum equal to NULL. - */ +// [lua_tonumber] -> [-0, +0, –] +// +// Equivalent to lua_tonumberx with isnum equal to NULL. +// +// [lua_tonumber]: https://www.lua.org/manual/5.3/manual.html#lua_tonumber func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumberx(L.s, C.int(index), nil)) } -// lua_yield -/* - * [-?, +?, e] - * This function is equivalent to lua_yieldk, but it has no continuation (see §4.7). Therefore, when the thread resumes, it continues the function that called the function calling lua_yield. - */ +// [lua_yield] -> [-?, +?, e] +// +// This function is equivalent to lua_yieldk, but it has no continuation (see §4.7). Therefore, when the thread resumes, it continues the function that called the function calling lua_yield. +// +// [lua_yield]: https://www.lua.org/manual/5.3/manual.html#lua_yield func (L *State) Yield(nresults int) int { return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) } @@ -187,20 +187,20 @@ func (L *State) GetGlobal(name string) { C.lua_getglobal(L.s, Ck) } -// lua_resume -/* - * [-?, +?, –] - * Starts and resumes a coroutine in the given thread L. - */ +// [lua_resume] -> [-?, +?, –] +// +// Starts and resumes a coroutine in the given thread L. +// +// [lua_resume]: https://www.lua.org/manual/5.3/manual.html#lua_resume func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, nil, C.int(narg))) } -// lua_setglobal -/* - * [-1, +0, e] - * Pops a value from the stack and sets it as the new value of global name. - */ +// [lua_setglobal] -> [-1, +0, e] +// +// Pops a value from the stack and sets it as the new value of global name. +// +// [lua_setglobal]: https://www.lua.org/manual/5.3/manual.html#lua_setglobal func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) @@ -222,56 +222,56 @@ func (L *State) OpenCoroutine() { C.clua_opencoroutine(L.s) } -// lua_insert -/* - * [-1, +1, –] - * Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_insert] -> [-1, +1, –] +// +// Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_insert]: https://www.lua.org/manual/5.3/manual.html#lua_insert func (L *State) Insert(index int) { C.lua_rotate(L.s, C.int(index), 1) } -// lua_remove -/* - * [-1, +0, –] - * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_remove] -> [-1, +0, –] +// +// Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_remove]: https://www.lua.org/manual/5.3/manual.html#lua_remove func (L *State) Remove(index int) { C.lua_rotate(L.s, C.int(index), -1) C.lua_settop(L.s, C.int(-2)) } -// lua_replace -/* - * [-1, +0, –] - * Moves the top element into the given valid index without shifting any element (therefore replacing the value at that given index), and then pops the top element. - */ +// [lua_replace] -> [-1, +0, –] +// +// Moves the top element into the given valid index without shifting any element (therefore replacing the value at that given index), and then pops the top element. +// +// [lua_replace]: https://www.lua.org/manual/5.3/manual.html#lua_replace func (L *State) Replace(index int) { C.lua_copy(L.s, -1, C.int(index)) C.lua_settop(L.s, -2) } -// lua_rawgeti -/* - * [-0, +1, –] - * Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw, that is, it does not invoke the __index metamethod. - */ +// [lua_rawgeti] -> [-0, +1, –] +// +// Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw, that is, it does not invoke the __index metamethod. +// +// [lua_rawgeti]: https://www.lua.org/manual/5.3/manual.html#lua_rawgeti func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.longlong(n)) } -// lua_rawseti -/* - * [-1, +0, m] - * Does the equivalent of t[i] = v, where t is the table at the given index and v is the value at the top of the stack. - */ +// [lua_rawseti] -> [-1, +0, m] +// +// Does the equivalent of t[i] = v, where t is the table at the given index and v is the value at the top of the stack. +// +// [lua_rawseti]: https://www.lua.org/manual/5.3/manual.html#lua_rawseti func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.longlong(n)) } -// lua_gc -/* - * [-0, +0, m] - * Controls the garbage collector. - */ +// [lua_gc] -> [-0, +0, m] +// +// Controls the garbage collector. +// +// [lua_gc]: https://www.lua.org/manual/5.3/manual.html#lua_gc func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } diff --git a/lua/golua_c_lua54.go b/lua/golua_c_lua54.go index 10f4fecc..f39aae26 100644 --- a/lua/golua_c_lua54.go +++ b/lua/golua_c_lua54.go @@ -151,29 +151,29 @@ func (L *State) ObjLen(index int) uint { return uint(C.lua_rawlen(L.s, C.int(index))) } -// lua_tointeger -/* - * [-0, +0, –] - * Equivalent to lua_tointegerx with isnum equal to NULL. - */ +// [lua_tointeger] -> [-0, +0, –] +// +// Equivalent to lua_tointegerx with isnum equal to NULL. +// +// [lua_tointeger]: https://www.lua.org/manual/5.4/manual.html#lua_tointeger func (L *State) ToInteger(index int) int { return int(C.lua_tointegerx(L.s, C.int(index), nil)) } -// lua_tonumber -/* - * [-0, +0, –] - * Equivalent to lua_tonumberx with isnum equal to NULL. - */ +// [lua_tonumber] -> [-0, +0, –] +// +// Equivalent to lua_tonumberx with isnum equal to NULL. +// +// [lua_tonumber]: https://www.lua.org/manual/5.4/manual.html#lua_tonumber func (L *State) ToNumber(index int) float64 { return float64(C.lua_tonumberx(L.s, C.int(index), nil)) } -// lua_yield -/* - * [-?, +?, v] - * This function is equivalent to lua_yieldk, but it has no continuation (see §4.5). Therefore, when the thread resumes, it continues the function that called the function calling lua_yield. To avoid surprises, this function should be called only in a tail call. - */ +// [lua_yield] -> [-?, +?, v] +// +// This function is equivalent to lua_yieldk, but it has no continuation (see §4.5). Therefore, when the thread resumes, it continues the function that called the function calling lua_yield. To avoid surprises, this function should be called only in a tail call. +// +// [lua_yield]: https://www.lua.org/manual/5.4/manual.html#lua_yield func (L *State) Yield(nresults int) int { return int(C.lua_yieldk(L.s, C.int(nresults), 0, nil)) } @@ -189,20 +189,20 @@ func (L *State) GetGlobal(name string) { C.lua_getglobal(L.s, Ck) } -// lua_resume -/* - * [-?, +?, –] - * Starts and resumes a coroutine in the given thread L. - */ +// [lua_resume] -> [-?, +?, –] +// +// Starts and resumes a coroutine in the given thread L. +// +// [lua_resume]: https://www.lua.org/manual/5.4/manual.html#lua_resume func (L *State) Resume(narg int) int { return int(C.lua_resume(L.s, nil, C.int(narg), nil)) } -// lua_setglobal -/* - * [-1, +0, e] - * Pops a value from the stack and sets it as the new value of global name. - */ +// [lua_setglobal] -> [-1, +0, e] +// +// Pops a value from the stack and sets it as the new value of global name. +// +// [lua_setglobal]: https://www.lua.org/manual/5.4/manual.html#lua_setglobal func (L *State) SetGlobal(name string) { Cname := C.CString(name) defer C.free(unsafe.Pointer(Cname)) @@ -219,56 +219,56 @@ func (L *State) OpenCoroutine() { C.clua_opencoroutine(L.s) } -// lua_insert -/* - * [-1, +1, –] - * Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_insert] -> [-1, +1, –] +// +// Moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_insert]: https://www.lua.org/manual/5.4/manual.html#lua_insert func (L *State) Insert(index int) { C.lua_rotate(L.s, C.int(index), 1) } -// lua_remove -/* - * [-1, +0, –] - * Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. - */ +// [lua_remove] -> [-1, +0, –] +// +// Removes the element at the given valid index, shifting down the elements above this index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position. +// +// [lua_remove]: https://www.lua.org/manual/5.4/manual.html#lua_remove func (L *State) Remove(index int) { C.lua_rotate(L.s, C.int(index), -1) C.lua_settop(L.s, C.int(-2)) } -// lua_replace -/* - * [-1, +0, –] - * Moves the top element into the given valid index without shifting any element (therefore replacing the value at that given index), and then pops the top element. - */ +// [lua_replace] -> [-1, +0, –] +// +// Moves the top element into the given valid index without shifting any element (therefore replacing the value at that given index), and then pops the top element. +// +// [lua_replace]: https://www.lua.org/manual/5.4/manual.html#lua_replace func (L *State) Replace(index int) { C.lua_copy(L.s, -1, C.int(index)) C.lua_settop(L.s, -2) } -// lua_rawgeti -/* - * [-0, +1, –] - * Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw, that is, it does not use the __index metavalue. - */ +// [lua_rawgeti] -> [-0, +1, –] +// +// Pushes onto the stack the value t[n], where t is the table at the given index. The access is raw, that is, it does not use the __index metavalue. +// +// [lua_rawgeti]: https://www.lua.org/manual/5.4/manual.html#lua_rawgeti func (L *State) RawGeti(index int, n int) { C.lua_rawgeti(L.s, C.int(index), C.longlong(n)) } -// lua_rawseti -/* - * [-1, +0, m] - * Does the equivalent of t[i] = v, where t is the table at the given index and v is the value on the top of the stack. - */ +// [lua_rawseti] -> [-1, +0, m] +// +// Does the equivalent of t[i] = v, where t is the table at the given index and v is the value on the top of the stack. +// +// [lua_rawseti]: https://www.lua.org/manual/5.4/manual.html#lua_rawseti func (L *State) RawSeti(index int, n int) { C.lua_rawseti(L.s, C.int(index), C.longlong(n)) } -// lua_gc -/* - * [-0, +0, –] - * Controls the garbage collector. - */ +// [lua_gc] -> [-0, +0, –] +// +// Controls the garbage collector. +// +// [lua_gc]: https://www.lua.org/manual/5.4/manual.html#lua_gc func (L *State) GC(what, data int) int { return int(C.lua_gc_compat(L.s, C.int(what), C.int(data))) } diff --git a/lua/lauxlib.go b/lua/lauxlib.go index 282187f4..25b0d315 100644 --- a/lua/lauxlib.go +++ b/lua/lauxlib.go @@ -30,7 +30,11 @@ func (err *LuaError) StackTrace() []LuaStackEntry { return err.stackTrace } -// luaL_argcheck +// [luaL_argcheck] -> [-0, +0, v] +// +// Checks whether cond is true. If not, raises an error with the following message, where func is retrieved from the call stack: +// +// [luaL_argcheck]: https://www.lua.org/manual/5.1/manual.html#lual_argcheck // WARNING: before b30b2c62c6712c6683a9d22ff0abfa54c8267863 the function ArgCheck had the opposite behaviour func (L *State) Argcheck(cond bool, narg int, extramsg string) { if !cond { @@ -40,42 +44,70 @@ func (L *State) Argcheck(cond bool, narg int, extramsg string) { } } -// luaL_argerror +// [luaL_argerror] -> [-0, +0, v] +// +// Raises an error with the following message, where func is retrieved from the call stack: +// +// [luaL_argerror]: https://www.lua.org/manual/5.1/manual.html#lual_argerror func (L *State) ArgError(narg int, extramsg string) int { Cextramsg := C.CString(extramsg) defer C.free(unsafe.Pointer(Cextramsg)) return int(C.luaL_argerror(L.s, C.int(narg), Cextramsg)) } -// luaL_callmeta +// [luaL_callmeta] -> [-0, +(0|1), e] +// +// Calls a metamethod. +// +// [luaL_callmeta]: https://www.lua.org/manual/5.1/manual.html#lual_callmeta func (L *State) CallMeta(obj int, e string) int { Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) return int(C.luaL_callmeta(L.s, C.int(obj), Ce)) } -// luaL_checkany +// [luaL_checkany] -> [-0, +0, v] +// +// Checks whether the function has an argument of any type (including nil) at position narg. +// +// [luaL_checkany]: https://www.lua.org/manual/5.1/manual.html#lual_checkany func (L *State) CheckAny(narg int) { C.luaL_checkany(L.s, C.int(narg)) } -// luaL_checkinteger +// [luaL_checkinteger] -> [-0, +0, v] +// +// Checks whether the function argument narg is a number and returns this number cast to a lua_Integer. +// +// [luaL_checkinteger]: https://www.lua.org/manual/5.1/manual.html#lual_checkinteger func (L *State) CheckInteger(narg int) int { return int(C.luaL_checkinteger(L.s, C.int(narg))) } -// luaL_checknumber +// [luaL_checknumber] -> [-0, +0, v] +// +// Checks whether the function argument narg is a number and returns this number. +// +// [luaL_checknumber]: https://www.lua.org/manual/5.1/manual.html#lual_checknumber func (L *State) CheckNumber(narg int) float64 { return float64(C.luaL_checknumber(L.s, C.int(narg))) } -// luaL_checkstring +// [luaL_checkstring] -> [-0, +0, v] +// +// Checks whether the function argument narg is a string and returns this string. +// +// [luaL_checkstring]: https://www.lua.org/manual/5.1/manual.html#lual_checkstring func (L *State) CheckString(narg int) string { var length C.size_t return C.GoString(C.luaL_checklstring(L.s, C.int(narg), &length)) } -// luaL_checkoption +// [luaL_checkoption] -> [-0, +0, v] +// +// Checks whether the function argument narg is a string and searches for this string in the array lst (which must be NULL-terminated). Returns the index in the array where the string was found. Raises an error if the argument is not a string or if the string cannot be found. +// +// [luaL_checkoption]: https://www.lua.org/manual/5.1/manual.html#lual_checkoption // // BUG(everyone_involved): not implemented func (L *State) CheckOption(narg int, def string, lst []string) int { @@ -83,12 +115,20 @@ func (L *State) CheckOption(narg int, def string, lst []string) int { return 0 } -// luaL_checktype +// [luaL_checktype] -> [-0, +0, v] +// +// Checks whether the function argument narg has type t. See lua_type for the encoding of types for t. +// +// [luaL_checktype]: https://www.lua.org/manual/5.1/manual.html#lual_checktype func (L *State) CheckType(narg int, t LuaValType) { C.luaL_checktype(L.s, C.int(narg), C.int(t)) } -// luaL_checkudata +// [luaL_checkudata] -> [-0, +0, v] +// +// Checks whether the function argument narg is a userdata of the type tname (see luaL_newmetatable). +// +// [luaL_checkudata]: https://www.lua.org/manual/5.1/manual.html#lual_checkudata func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) @@ -118,21 +158,33 @@ func (L *State) MustDoString(str string) { } } -// luaL_getmetafield +// [luaL_getmetafield] -> [-0, +(0|1), m] +// +// Pushes onto the stack the field e from the metatable of the object at index obj. If the object does not have a metatable, or if the metatable does not have this field, returns 0 and pushes nothing. +// +// [luaL_getmetafield]: https://www.lua.org/manual/5.1/manual.html#lual_getmetafield func (L *State) GetMetaField(obj int, e string) bool { Ce := C.CString(e) defer C.free(unsafe.Pointer(Ce)) return C.luaL_getmetafield(L.s, C.int(obj), Ce) != 0 } -// luaL_getmetatable +// [luaL_getmetatable] -> [-0, +1, -] +// +// Pushes onto the stack the metatable associated with name tname in the registry (see luaL_newmetatable). +// +// [luaL_getmetatable]: https://www.lua.org/manual/5.1/manual.html#lual_getmetatable func (L *State) LGetMetaTable(tname string) { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) C.lua_getfield(L.s, LUA_REGISTRYINDEX, Ctname) } -// luaL_gsub +// [luaL_gsub] -> [-0, +1, m] +// +// Creates a copy of string s by replacing any occurrence of the string p with the string r. Pushes the resulting string on the stack and returns it. +// +// [luaL_gsub]: https://www.lua.org/manual/5.1/manual.html#lual_gsub func (L *State) GSub(s string, p string, r string) string { Cs := C.CString(s) Cp := C.CString(p) @@ -146,27 +198,43 @@ func (L *State) GSub(s string, p string, r string) string { return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) } -// luaL_loadfile +// [luaL_loadfile] -> [-0, +1, m] +// +// Loads a file as a Lua chunk. This function uses lua_load to load the chunk in the file named filename. If filename is NULL, then it loads from the standard input. The first line in the file is ignored if it starts with a #. +// +// [luaL_loadfile]: https://www.lua.org/manual/5.1/manual.html#lual_loadfile func (L *State) LoadFile(filename string) int { Cfilename := C.CString(filename) defer C.free(unsafe.Pointer(Cfilename)) return int(lualLoadFile(L.s, Cfilename)) } -// luaL_loadstring +// [luaL_loadstring] -> [-0, +1, m] +// +// Loads a string as a Lua chunk. This function uses lua_load to load the chunk in the zero-terminated string s. +// +// [luaL_loadstring]: https://www.lua.org/manual/5.1/manual.html#lual_loadstring func (L *State) LoadString(s string) int { Cs := C.CString(s) defer C.free(unsafe.Pointer(Cs)) return int(C.luaL_loadstring(L.s, Cs)) } -// lua_dump +// [lua_dump] -> [-0, +0, m] +// +// Dumps a function as a binary chunk. Receives a Lua function on the top of the stack and produces a binary chunk that, if loaded again, results in a function equivalent to the one dumped. As it produces parts of the chunk, lua_dump calls function writer (see lua_Writer) with the given data to write them. +// +// [lua_dump]: https://www.lua.org/manual/5.1/manual.html#lua_dump func (L *State) Dump() int { ret := int(C.dump_chunk(L.s)) return ret } -// lua_load +// [lua_load] -> [-0, +1, -] +// +// Loads a Lua chunk. If there are no errors, lua_load pushes the compiled chunk as a Lua function on top of the stack. Otherwise, it pushes an error message. The return values of lua_load are: +// +// [lua_load]: https://www.lua.org/manual/5.1/manual.html#lua_load func (L *State) Load(bs []byte, name string) int { chunk := C.CString(string(bs)) ckname := C.CString(name) @@ -179,14 +247,22 @@ func (L *State) Load(bs []byte, name string) int { return 0 } -// luaL_newmetatable +// [luaL_newmetatable] -> [-0, +1, m] +// +// If the registry already has the key tname, returns 0. Otherwise, creates a new table to be used as a metatable for userdata, adds it to the registry with key tname, and returns 1. +// +// [luaL_newmetatable]: https://www.lua.org/manual/5.1/manual.html#lual_newmetatable func (L *State) NewMetaTable(tname string) bool { Ctname := C.CString(tname) defer C.free(unsafe.Pointer(Ctname)) return C.luaL_newmetatable(L.s, Ctname) != 0 } -// luaL_newstate +// [luaL_newstate] -> [-0, +0, -] +// +// Creates a new Lua state. It calls lua_newstate with an allocator based on the standard C realloc function and then sets a panic function (see lua_atpanic) that prints an error message to the standard error output in case of fatal errors. +// +// [luaL_newstate]: https://www.lua.org/manual/5.1/manual.html#lual_newstate func NewState() *State { ls := (C.luaL_newstate()) if ls == nil { @@ -206,23 +282,39 @@ func (L *State) Context() context.Context { return L.ctx } -// luaL_openlibs +// [luaL_openlibs] -> [-0, +0, m] +// +// Opens all standard Lua libraries into the given state. +// +// [luaL_openlibs]: https://www.lua.org/manual/5.1/manual.html#lual_openlibs func (L *State) OpenLibs() { C.luaL_openlibs(L.s) C.clua_hide_pcall(L.s) } -// luaL_optinteger +// [luaL_optinteger] -> [-0, +0, v] +// +// If the function argument narg is a number, returns this number cast to a lua_Integer. If this argument is absent or is nil, returns d. Otherwise, raises an error. +// +// [luaL_optinteger]: https://www.lua.org/manual/5.1/manual.html#lual_optinteger func (L *State) OptInteger(narg int, d int) int { return int(C.luaL_optinteger(L.s, C.int(narg), C.lua_Integer(d))) } -// luaL_optnumber +// [luaL_optnumber] -> [-0, +0, v] +// +// If the function argument narg is a number, returns this number. If this argument is absent or is nil, returns d. Otherwise, raises an error. +// +// [luaL_optnumber]: https://www.lua.org/manual/5.1/manual.html#lual_optnumber func (L *State) OptNumber(narg int, d float64) float64 { return float64(C.luaL_optnumber(L.s, C.int(narg), C.lua_Number(d))) } -// luaL_optstring +// [luaL_optstring] -> [-0, +0, v] +// +// If the function argument narg is a string, returns this string. If this argument is absent or is nil, returns d. Otherwise, raises an error. +// +// [luaL_optstring]: https://www.lua.org/manual/5.1/manual.html#lual_optstring func (L *State) OptString(narg int, d string) string { var length C.size_t Cd := C.CString(d) @@ -230,22 +322,38 @@ func (L *State) OptString(narg int, d string) string { return C.GoString(C.luaL_optlstring(L.s, C.int(narg), Cd, &length)) } -// luaL_ref +// [luaL_ref] -> [-1, +0, m] +// +// Creates and returns a reference, in the table at index t, for the object at the top of the stack (and pops the object). +// +// [luaL_ref]: https://www.lua.org/manual/5.1/manual.html#lual_ref func (L *State) Ref(t int) int { return int(C.luaL_ref(L.s, C.int(t))) } -// luaL_typename +// [luaL_typename] -> [-0, +0, -] +// +// Returns the name of the type of the value at the given index. +// +// [luaL_typename]: https://www.lua.org/manual/5.1/manual.html#lual_typename func (L *State) LTypename(index int) string { return C.GoString(C.lua_typename(L.s, C.lua_type(L.s, C.int(index)))) } -// luaL_unref +// [luaL_unref] -> [-0, +0, -] +// +// Releases reference ref from the table at index t (see luaL_ref). The entry is removed from the table, so that the referred object can be collected. The reference ref is also freed to be used again. +// +// [luaL_unref]: https://www.lua.org/manual/5.1/manual.html#lual_unref func (L *State) Unref(t int, ref int) { C.luaL_unref(L.s, C.int(t), C.int(ref)) } -// luaL_where +// [luaL_where] -> [-0, +1, m] +// +// Pushes onto the stack a string identifying the current position of the control at level lvl in the call stack. Typically this string has the following format: +// +// [luaL_where]: https://www.lua.org/manual/5.1/manual.html#lual_where func (L *State) Where(lvl int) { C.luaL_where(L.s, C.int(lvl)) } diff --git a/lua/lua.go b/lua/lua.go index dc273bea..0762ba65 100644 --- a/lua/lua.go +++ b/lua/lua.go @@ -156,25 +156,25 @@ func (L *State) PushGoClosureWithUpvalues(f LuaGoFunction, nup uint) { C.clua_pushcallback(L.s, C.uint(nup)) // wraps the userdata object with a closure making it into a function } -// lua_upvalueid +// lua_upvalueindex func (L *State) UpvalueIndex(n int) int { return int(C.clua_upvalueindex(C.int32_t(n))) } -// lua_setupvalue -/* - * [-(0|1), +0, -] - * Sets the value of a closure's upvalue. It assigns the value at the top of the stack to the upvalue and returns its name. It also pops the value from the stack. Parameters funcindex and n are as in the lua_getupvalue (see lua_getupvalue). - */ +// [lua_setupvalue] -> [-(0|1), +0, -] +// +// Sets the value of a closure's upvalue. It assigns the value at the top of the stack to the upvalue and returns its name. It also pops the value from the stack. Parameters funcindex and n are as in the lua_getupvalue (see lua_getupvalue). +// +// [lua_setupvalue]: https://www.lua.org/manual/5.1/manual.html#lua_setupvalue func (L *State) SetUpvalue(funcindex, n int) bool { return C.lua_setupvalue(L.s, C.int(funcindex), C.int(n)) != nil } -// lua_getupvalue -/* - * [-0, +(0|1), -] - * Gets information about a closure's upvalue. (For Lua functions, upvalues are the external local variables that the function uses, and that are consequently included in its closure.) lua_getupvalue gets the index n of an upvalue, pushes the upvalue's value onto the stack, and returns its name. funcindex points to the closure in the stack. (Upvalues have no particular order, as they are active through the whole function. So, they are numbered in an arbitrary order.) - */ +// [lua_getupvalue] -> [-0, +(0|1), -] +// +// Gets information about a closure's upvalue. (For Lua functions, upvalues are the external local variables that the function uses, and that are consequently included in its closure.) lua_getupvalue gets the index n of an upvalue, pushes the upvalue's value onto the stack, and returns its name. funcindex points to the closure in the stack. (Upvalues have no particular order, as they are active through the whole function. So, they are numbered in an arbitrary order.) +// +// [lua_getupvalue]: https://www.lua.org/manual/5.1/manual.html#lua_getupvalue func (L *State) GetUpvalue(funcindex, n int) { C.lua_getupvalue(L.s, C.int(funcindex), C.int(n)) } @@ -272,11 +272,11 @@ func (L *State) callEx(nargs, nresults int, catch bool) (err error) { return } -// lua_call -/* - * [-(nargs + 1), +nresults, e] - * Calls a function. - */ +// [lua_call] -> [-(nargs + 1), +nresults, e] +// +// Calls a function. +// +// [lua_call]: https://www.lua.org/manual/5.1/manual.html#lua_call func (L *State) Call(nargs, nresults int) (err error) { return L.callEx(nargs, nresults, true) } @@ -286,75 +286,75 @@ func (L *State) MustCall(nargs, nresults int) { L.callEx(nargs, nresults, false) } -// lua_checkstack -/* - * [-0, +0, m] - * Ensures that there are at least extra free stack slots in the stack. It returns false if it cannot grow the stack to that size. This function never shrinks the stack; if the stack is already larger than the new size, it is left unchanged. - */ +// [lua_checkstack] -> [-0, +0, m] +// +// Ensures that there are at least extra free stack slots in the stack. It returns false if it cannot grow the stack to that size. This function never shrinks the stack; if the stack is already larger than the new size, it is left unchanged. +// +// [lua_checkstack]: https://www.lua.org/manual/5.1/manual.html#lua_checkstack func (L *State) CheckStack(extra int) bool { return C.lua_checkstack(L.s, C.int(extra)) != 0 } -// lua_close -/* - * [-0, +0, -] - * Destroys all objects in the given Lua state (calling the corresponding garbage-collection metamethods, if any) and frees all dynamic memory used by this state. On several platforms, you may not need to call this function, because all resources are naturally released when the host program ends. On the other hand, long-running programs, such as a daemon or a web server, might need to release states as soon as they are not needed, to avoid growing too large. - */ +// [lua_close] -> [-0, +0, -] +// +// Destroys all objects in the given Lua state (calling the corresponding garbage-collection metamethods, if any) and frees all dynamic memory used by this state. On several platforms, you may not need to call this function, because all resources are naturally released when the host program ends. On the other hand, long-running programs, such as a daemon or a web server, might need to release states as soon as they are not needed, to avoid growing too large. +// +// [lua_close]: https://www.lua.org/manual/5.1/manual.html#lua_close func (L *State) Close() { C.lua_close(L.s) unregisterGoState(L) } -// lua_concat -/* - * [-n, +1, e] - * Concatenates the n values at the top of the stack, pops them, and leaves the result at the top. If n is 1, the result is the single value on the stack (that is, the function does nothing); if n is 0, the result is the empty string. Concatenation is performed following the usual semantics of Lua (see §2.5.4). - */ +// [lua_concat] -> [-n, +1, e] +// +// Concatenates the n values at the top of the stack, pops them, and leaves the result at the top. If n is 1, the result is the single value on the stack (that is, the function does nothing); if n is 0, the result is the empty string. Concatenation is performed following the usual semantics of Lua (see §2.5.4). +// +// [lua_concat]: https://www.lua.org/manual/5.1/manual.html#lua_concat func (L *State) Concat(n int) { C.lua_concat(L.s, C.int(n)) } -// lua_createtable -/* - * [-0, +1, m] - * Creates a new empty table and pushes it onto the stack. The new table has space pre-allocated for narr array elements and nrec non-array elements. This pre-allocation is useful when you know exactly how many elements the table will have. Otherwise you can use the function lua_newtable. - */ +// [lua_createtable] -> [-0, +1, m] +// +// Creates a new empty table and pushes it onto the stack. The new table has space pre-allocated for narr array elements and nrec non-array elements. This pre-allocation is useful when you know exactly how many elements the table will have. Otherwise you can use the function lua_newtable. +// +// [lua_createtable]: https://www.lua.org/manual/5.1/manual.html#lua_createtable func (L *State) CreateTable(narr int, nrec int) { C.lua_createtable(L.s, C.int(narr), C.int(nrec)) } -// lua_getfield -/* - * [-0, +1, e] - * Pushes onto the stack the value t[k], where t is the value at the given valid index. As in Lua, this function may trigger a metamethod for the "index" event (see §2.8). - */ +// [lua_getfield] -> [-0, +1, e] +// +// Pushes onto the stack the value t[k], where t is the value at the given valid index. As in Lua, this function may trigger a metamethod for the "index" event (see §2.8). +// +// [lua_getfield]: https://www.lua.org/manual/5.1/manual.html#lua_getfield func (L *State) GetField(index int, k string) { Ck := C.CString(k) defer C.free(unsafe.Pointer(Ck)) C.lua_getfield(L.s, C.int(index), Ck) } -// lua_getmetatable -/* - * [-0, +(0|1), -] - * Pushes onto the stack the metatable of the value at the given acceptable index. If the index is not valid, or if the value does not have a metatable, the function returns 0 and pushes nothing on the stack. - */ +// [lua_getmetatable] -> [-0, +(0|1), -] +// +// Pushes onto the stack the metatable of the value at the given acceptable index. If the index is not valid, or if the value does not have a metatable, the function returns 0 and pushes nothing on the stack. +// +// [lua_getmetatable]: https://www.lua.org/manual/5.1/manual.html#lua_getmetatable func (L *State) GetMetaTable(index int) bool { return C.lua_getmetatable(L.s, C.int(index)) != 0 } -// lua_gettable -/* - * [-1, +1, e] - * Pushes onto the stack the value t[k], where t is the value at the given valid index and k is the value at the top of the stack. - */ +// [lua_gettable] -> [-1, +1, e] +// +// Pushes onto the stack the value t[k], where t is the value at the given valid index and k is the value at the top of the stack. +// +// [lua_gettable]: https://www.lua.org/manual/5.1/manual.html#lua_gettable func (L *State) GetTable(index int) { C.lua_gettable(L.s, C.int(index)) } -// lua_gettop -/* - * [-0, +0, -] - * Returns the index of the top element in the stack. Because indices start at 1, this result is equal to the number of elements in the stack (and so 0 means an empty stack). - */ +// [lua_gettop] -> [-0, +0, -] +// +// Returns the index of the top element in the stack. Because indices start at 1, this result is equal to the number of elements in the stack (and so 0 means an empty stack). +// +// [lua_gettop]: https://www.lua.org/manual/5.1/manual.html#lua_gettop func (L *State) GetTop() int { return int(C.lua_gettop(L.s)) } // Returns true if lua_type == LUA_TBOOLEAN @@ -382,64 +382,64 @@ func (L *State) IsLightUserdata(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TLIGHTUSERDATA } -// lua_isnil -/* - * [-0, +0, -] - * Returns 1 if the value at the given acceptable index is nil, and 0 otherwise. - */ +// [lua_isnil] -> [-0, +0, -] +// +// Returns 1 if the value at the given acceptable index is nil, and 0 otherwise. +// +// [lua_isnil]: https://www.lua.org/manual/5.1/manual.html#lua_isnil func (L *State) IsNil(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNIL } -// lua_isnone -/* - * [-0, +0, -] - * Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack), and 0 otherwise. - */ +// [lua_isnone] -> [-0, +0, -] +// +// Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack), and 0 otherwise. +// +// [lua_isnone]: https://www.lua.org/manual/5.1/manual.html#lua_isnone func (L *State) IsNone(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNONE } -// lua_isnoneornil -/* - * [-0, +0, -] - * Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack) or if the value at this index is nil, and 0 otherwise. - */ +// [lua_isnoneornil] -> [-0, +0, -] +// +// Returns 1 if the given acceptable index is not valid (that is, it refers to an element outside the current stack) or if the value at this index is nil, and 0 otherwise. +// +// [lua_isnoneornil]: https://www.lua.org/manual/5.1/manual.html#lua_isnoneornil func (L *State) IsNoneOrNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) <= 0 } -// lua_isnumber -/* - * [-0, +0, -] - * Returns 1 if the value at the given acceptable index is a number or a string convertible to a number, and 0 otherwise. - */ +// [lua_isnumber] -> [-0, +0, -] +// +// Returns 1 if the value at the given acceptable index is a number or a string convertible to a number, and 0 otherwise. +// +// [lua_isnumber]: https://www.lua.org/manual/5.1/manual.html#lua_isnumber func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(index)) == 1 } -// lua_isstring -/* - * [-0, +0, -] - * Returns 1 if the value at the given acceptable index is a string or a number (which is always convertible to a string), and 0 otherwise. - */ +// [lua_isstring] -> [-0, +0, -] +// +// Returns 1 if the value at the given acceptable index is a string or a number (which is always convertible to a string), and 0 otherwise. +// +// [lua_isstring]: https://www.lua.org/manual/5.1/manual.html#lua_isstring func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } -// lua_istable -/* - * [-0, +0, -] - * Returns 1 if the value at the given acceptable index is a table, and 0 otherwise. - */ +// [lua_istable] -> [-0, +0, -] +// +// Returns 1 if the value at the given acceptable index is a table, and 0 otherwise. +// +// [lua_istable]: https://www.lua.org/manual/5.1/manual.html#lua_istable func (L *State) IsTable(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTABLE } -// lua_isthread -/* - * [-0, +0, -] - * Returns 1 if the value at the given acceptable index is a thread, and 0 otherwise. - */ +// [lua_isthread] -> [-0, +0, -] +// +// Returns 1 if the value at the given acceptable index is a thread, and 0 otherwise. +// +// [lua_isthread]: https://www.lua.org/manual/5.1/manual.html#lua_isthread func (L *State) IsThread(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTHREAD } -// lua_isuserdata -/* - * [-0, +0, -] - * Returns 1 if the value at the given acceptable index is a userdata (either full or light), and 0 otherwise. - */ +// [lua_isuserdata] -> [-0, +0, -] +// +// Returns 1 if the value at the given acceptable index is a userdata (either full or light), and 0 otherwise. +// +// [lua_isuserdata]: https://www.lua.org/manual/5.1/manual.html#lua_isuserdata func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int(index)) == 1 } // Creates a new lua interpreter state with the given allocation function @@ -450,20 +450,20 @@ func NewStateAlloc(f Alloc) *State { return L } -// lua_newtable -/* - * [-0, +1, m] - * Creates a new empty table and pushes it onto the stack. It is equivalent to lua_createtable(L, 0, 0). - */ +// [lua_newtable] -> [-0, +1, m] +// +// Creates a new empty table and pushes it onto the stack. It is equivalent to lua_createtable(L, 0, 0). +// +// [lua_newtable]: https://www.lua.org/manual/5.1/manual.html#lua_newtable func (L *State) NewTable() { C.lua_createtable(L.s, 0, 0) } -// lua_newthread -/* - * [-0, +1, m] - * Creates a new thread, pushes it on the stack, and returns a pointer to a lua_State that represents this new thread. The new state returned by this function shares with the original state all global objects (such as tables), but has an independent execution stack. - */ +// [lua_newthread] -> [-0, +1, m] +// +// Creates a new thread, pushes it on the stack, and returns a pointer to a lua_State that represents this new thread. The new state returned by this function shares with the original state all global objects (such as tables), but has an independent execution stack. +// +// [lua_newthread]: https://www.lua.org/manual/5.1/manual.html#lua_newthread func (L *State) NewThread() *State { // TODO: call newState with result from C.lua_newthread and return it // TODO: should have same lists as parent @@ -472,36 +472,36 @@ func (L *State) NewThread() *State { return &State{s, 0, nil, nil, nil, nil, nil} } -// lua_next -/* - * [-1, +(2|0), e] - * Pops a key from the stack, and pushes a key-value pair from the table at the given index (the "next" pair after the given key). If there are no more elements in the table, then lua_next returns 0 (and pushes nothing). - */ +// [lua_next] -> [-1, +(2|0), e] +// +// Pops a key from the stack, and pushes a key-value pair from the table at the given index (the "next" pair after the given key). If there are no more elements in the table, then lua_next returns 0 (and pushes nothing). +// +// [lua_next]: https://www.lua.org/manual/5.1/manual.html#lua_next func (L *State) Next(index int) int { return int(C.lua_next(L.s, C.int(index))) } -// lua_objlen -/* - * [-0, +0, -] - * Returns the "length" of the value at the given acceptable index: for strings, this is the string length; for tables, this is the result of the length operator ('#'); for userdata, this is the size of the block of memory allocated for the userdata; for other values, it is 0. - */ -// lua_pop -/* - * [-n, +0, -] - * Pops n elements from the stack. - */ +// [lua_objlen] -> [-0, +0, -] +// +// Returns the "length" of the value at the given acceptable index: for strings, this is the string length; for tables, this is the result of the length operator ('#'); for userdata, this is the size of the block of memory allocated for the userdata; for other values, it is 0. +// +// [lua_objlen]: https://www.lua.org/manual/5.1/manual.html#lua_objlen +// [lua_pop] -> [-n, +0, -] +// +// Pops n elements from the stack. +// +// [lua_pop]: https://www.lua.org/manual/5.1/manual.html#lua_pop func (L *State) Pop(n int) { // Why is this implemented this way? I don't get it... // C.lua_pop(L.s, C.int(n)); C.lua_settop(L.s, C.int(-n-1)) } -// lua_pushboolean -/* - * [-0, +1, -] - * Pushes a boolean value with value b onto the stack. - */ +// [lua_pushboolean] -> [-0, +1, -] +// +// Pushes a boolean value with value b onto the stack. +// +// [lua_pushboolean]: https://www.lua.org/manual/5.1/manual.html#lua_pushboolean func (L *State) PushBoolean(b bool) { var bint int if b { @@ -512,11 +512,11 @@ func (L *State) PushBoolean(b bool) { C.lua_pushboolean(L.s, C.int(bint)) } -// lua_pushstring -/* - * [-0, +1, m] - * Pushes the zero-terminated string pointed to by s onto the stack. Lua makes (or reuses) an internal copy of the given string, so the memory at s can be freed or reused immediately after the function returns. The string cannot contain embedded zeros; it is assumed to end at the first zero. - */ +// [lua_pushstring] -> [-0, +1, m] +// +// Pushes the zero-terminated string pointed to by s onto the stack. Lua makes (or reuses) an internal copy of the given string, so the memory at s can be freed or reused immediately after the function returns. The string cannot contain embedded zeros; it is assumed to end at the first zero. +// +// [lua_pushstring]: https://www.lua.org/manual/5.1/manual.html#lua_pushstring func (L *State) PushString(str string) { Cstr := C.CString(str) defer C.free(unsafe.Pointer(Cstr)) @@ -527,74 +527,74 @@ func (L *State) PushBytes(b []byte) { C.lua_pushlstring(L.s, (*C.char)(unsafe.Pointer(&b[0])), C.size_t(len(b))) } -// lua_pushinteger -/* - * [-0, +1, -] - * Pushes a number with value n onto the stack. - */ +// [lua_pushinteger] -> [-0, +1, -] +// +// Pushes a number with value n onto the stack. +// +// [lua_pushinteger]: https://www.lua.org/manual/5.1/manual.html#lua_pushinteger func (L *State) PushInteger(n int64) { C.lua_pushinteger(L.s, C.lua_Integer(n)) } -// lua_pushnil -/* - * [-0, +1, -] - * Pushes a nil value onto the stack. - */ +// [lua_pushnil] -> [-0, +1, -] +// +// Pushes a nil value onto the stack. +// +// [lua_pushnil]: https://www.lua.org/manual/5.1/manual.html#lua_pushnil func (L *State) PushNil() { C.lua_pushnil(L.s) } -// lua_pushnumber -/* - * [-0, +1, -] - * Pushes a number with value n onto the stack. - */ +// [lua_pushnumber] -> [-0, +1, -] +// +// Pushes a number with value n onto the stack. +// +// [lua_pushnumber]: https://www.lua.org/manual/5.1/manual.html#lua_pushnumber func (L *State) PushNumber(n float64) { C.lua_pushnumber(L.s, C.lua_Number(n)) } -// lua_pushthread -/* - * [-0, +1, -] - * Pushes the thread represented by L onto the stack. Returns 1 if this thread is the main thread of its state. - */ +// [lua_pushthread] -> [-0, +1, -] +// +// Pushes the thread represented by L onto the stack. Returns 1 if this thread is the main thread of its state. +// +// [lua_pushthread]: https://www.lua.org/manual/5.1/manual.html#lua_pushthread func (L *State) PushThread() (isMain bool) { return C.lua_pushthread(L.s) != 0 } -// lua_pushvalue -/* - * [-0, +1, -] - * Pushes a copy of the element at the given valid index onto the stack. - */ +// [lua_pushvalue] -> [-0, +1, -] +// +// Pushes a copy of the element at the given valid index onto the stack. +// +// [lua_pushvalue]: https://www.lua.org/manual/5.1/manual.html#lua_pushvalue func (L *State) PushValue(index int) { C.lua_pushvalue(L.s, C.int(index)) } -// lua_rawequal -/* - * [-0, +0, -] - * Returns 1 if the two values in acceptable indices index1 and index2 are primitively equal (that is, without calling metamethods). Otherwise returns 0. Also returns 0 if any of the indices are non valid. - */ +// [lua_rawequal] -> [-0, +0, -] +// +// Returns 1 if the two values in acceptable indices index1 and index2 are primitively equal (that is, without calling metamethods). Otherwise returns 0. Also returns 0 if any of the indices are non valid. +// +// [lua_rawequal]: https://www.lua.org/manual/5.1/manual.html#lua_rawequal func (L *State) RawEqual(index1 int, index2 int) bool { return C.lua_rawequal(L.s, C.int(index1), C.int(index2)) != 0 } -// lua_rawget -/* - * [-1, +1, -] - * Similar to lua_gettable, but does a raw access (i.e., without metamethods). - */ +// [lua_rawget] -> [-1, +1, -] +// +// Similar to lua_gettable, but does a raw access (i.e., without metamethods). +// +// [lua_rawget]: https://www.lua.org/manual/5.1/manual.html#lua_rawget func (L *State) RawGet(index int) { C.lua_rawget(L.s, C.int(index)) } -// lua_rawset -/* - * [-2, +0, m] - * Similar to lua_settable, but does a raw assignment (i.e., without metamethods). - */ +// [lua_rawset] -> [-2, +0, m] +// +// Similar to lua_settable, but does a raw assignment (i.e., without metamethods). +// +// [lua_rawset]: https://www.lua.org/manual/5.1/manual.html#lua_rawset func (L *State) RawSet(index int) { C.lua_rawset(L.s, C.int(index)) } @@ -628,68 +628,68 @@ func (L *State) RegisterLibrary(name string, funcs map[string]LuaGoFunction) { } } -// lua_setallocf -/* - * [-0, +0, -] - * Changes the allocator function of a given state to f with user data ud. - */ +// [lua_setallocf] -> [-0, +0, -] +// +// Changes the allocator function of a given state to f with user data ud. +// +// [lua_setallocf]: https://www.lua.org/manual/5.1/manual.html#lua_setallocf func (L *State) SetAllocf(f Alloc) { L.allocfn = &f C.clua_setallocf(L.s, unsafe.Pointer(L.allocfn)) } -// lua_setfield -/* - * [-1, +0, e] - * Does the equivalent to t[k] = v, where t is the value at the given valid index and v is the value at the top of the stack. - */ +// [lua_setfield] -> [-1, +0, e] +// +// Does the equivalent to t[k] = v, where t is the value at the given valid index and v is the value at the top of the stack. +// +// [lua_setfield]: https://www.lua.org/manual/5.1/manual.html#lua_setfield func (L *State) SetField(index int, k string) { Ck := C.CString(k) defer C.free(unsafe.Pointer(Ck)) C.lua_setfield(L.s, C.int(index), Ck) } -// lua_setmetatable -/* - * [-1, +0, -] - * Pops a table from the stack and sets it as the new metatable for the value at the given acceptable index. - */ +// [lua_setmetatable] -> [-1, +0, -] +// +// Pops a table from the stack and sets it as the new metatable for the value at the given acceptable index. +// +// [lua_setmetatable]: https://www.lua.org/manual/5.1/manual.html#lua_setmetatable func (L *State) SetMetaTable(index int) { C.lua_setmetatable(L.s, C.int(index)) } -// lua_settable -/* - * [-2, +0, e] - * Does the equivalent to t[k] = v, where t is the value at the given valid index, v is the value at the top of the stack, and k is the value just below the top. - */ +// [lua_settable] -> [-2, +0, e] +// +// Does the equivalent to t[k] = v, where t is the value at the given valid index, v is the value at the top of the stack, and k is the value just below the top. +// +// [lua_settable]: https://www.lua.org/manual/5.1/manual.html#lua_settable func (L *State) SetTable(index int) { C.lua_settable(L.s, C.int(index)) } -// lua_settop -/* - * [-?, +?, -] - * Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with nil. If index is 0, then all stack elements are removed. - */ +// [lua_settop] -> [-?, +?, -] +// +// Accepts any acceptable index, or 0, and sets the stack top to this index. If the new top is larger than the old one, then the new elements are filled with nil. If index is 0, then all stack elements are removed. +// +// [lua_settop]: https://www.lua.org/manual/5.1/manual.html#lua_settop func (L *State) SetTop(index int) { C.lua_settop(L.s, C.int(index)) } -// lua_status -/* - * [-0, +0, -] - * Returns the status of the thread L. - */ +// [lua_status] -> [-0, +0, -] +// +// Returns the status of the thread L. +// +// [lua_status]: https://www.lua.org/manual/5.1/manual.html#lua_status func (L *State) Status() int { return int(C.lua_status(L.s)) } -// lua_toboolean -/* - * [-0, +0, -] - * Converts the Lua value at the given acceptable index to a C boolean value (0 or 1). Like all tests in Lua, lua_toboolean returns 1 for any Lua value different from false and nil; otherwise it returns 0. It also returns 0 when called with a non-valid index. (If you want to accept only actual boolean values, use lua_isboolean to test the value's type.) - */ +// [lua_toboolean] -> [-0, +0, -] +// +// Converts the Lua value at the given acceptable index to a C boolean value (0 or 1). Like all tests in Lua, lua_toboolean returns 1 for any Lua value different from false and nil; otherwise it returns 0. It also returns 0 when called with a non-valid index. (If you want to accept only actual boolean values, use lua_isboolean to test the value's type.) +// +// [lua_toboolean]: https://www.lua.org/manual/5.1/manual.html#lua_toboolean func (L *State) ToBoolean(index int) bool { return C.lua_toboolean(L.s, C.int(index)) != 0 } @@ -718,11 +718,11 @@ func (L *State) ToGoStruct(index int) (f interface{}) { return L.registry[fid] } -// lua_tostring -/* - * [-0, +0, m] - * Equivalent to lua_tolstring with len equal to NULL. - */ +// [lua_tostring] -> [-0, +0, m] +// +// Equivalent to lua_tolstring with len equal to NULL. +// +// [lua_tostring]: https://www.lua.org/manual/5.1/manual.html#lua_tostring func (L *State) ToString(index int) string { var size C.size_t r := C.lua_tolstring(L.s, C.int(index), &size) @@ -735,57 +735,57 @@ func (L *State) ToBytes(index int) []byte { return C.GoBytes(unsafe.Pointer(b), C.int(size)) } -// lua_topointer -/* - * [-0, +0, -] - * Converts the value at the given acceptable index to a generic C pointer (void*). The value can be a userdata, a table, a thread, or a function; otherwise, lua_topointer returns NULL. Different objects will give different pointers. There is no way to convert the pointer back to its original value. - */ +// [lua_topointer] -> [-0, +0, -] +// +// Converts the value at the given acceptable index to a generic C pointer (void*). The value can be a userdata, a table, a thread, or a function; otherwise, lua_topointer returns NULL. Different objects will give different pointers. There is no way to convert the pointer back to its original value. +// +// [lua_topointer]: https://www.lua.org/manual/5.1/manual.html#lua_topointer func (L *State) ToPointer(index int) uintptr { return uintptr(C.lua_topointer(L.s, C.int(index))) } -// lua_tothread -/* - * [-0, +0, -] - * Converts the value at the given acceptable index to a Lua thread (represented as lua_State*). This value must be a thread; otherwise, the function returns NULL. - */ +// [lua_tothread] -> [-0, +0, -] +// +// Converts the value at the given acceptable index to a Lua thread (represented as lua_State*). This value must be a thread; otherwise, the function returns NULL. +// +// [lua_tothread]: https://www.lua.org/manual/5.1/manual.html#lua_tothread func (L *State) ToThread(index int) *State { // TODO: find a way to link lua_State* to existing *State, return that return &State{} } -// lua_touserdata -/* - * [-0, +0, -] - * If the value at the given acceptable index is a full userdata, returns its block address. If the value is a light userdata, returns its pointer. Otherwise, returns NULL. - */ +// [lua_touserdata] -> [-0, +0, -] +// +// If the value at the given acceptable index is a full userdata, returns its block address. If the value is a light userdata, returns its pointer. Otherwise, returns NULL. +// +// [lua_touserdata]: https://www.lua.org/manual/5.1/manual.html#lua_touserdata func (L *State) ToUserdata(index int) unsafe.Pointer { return unsafe.Pointer(C.lua_touserdata(L.s, C.int(index))) } -// lua_type -/* - * [-0, +0, -] - * Returns the type of the value in the given acceptable index, or LUA_TNONE for a non-valid index (that is, an index to an "empty" stack position). The types returned by lua_type are coded by the following constants defined in lua.h: LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA. - */ +// [lua_type] -> [-0, +0, -] +// +// Returns the type of the value in the given acceptable index, or LUA_TNONE for a non-valid index (that is, an index to an "empty" stack position). The types returned by lua_type are coded by the following constants defined in lua.h: LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA. +// +// [lua_type]: https://www.lua.org/manual/5.1/manual.html#lua_type func (L *State) Type(index int) LuaValType { return LuaValType(C.lua_type(L.s, C.int(index))) } -// lua_typename -/* - * [-0, +0, -] - * Returns the name of the type encoded by the value tp, which must be one the values returned by lua_type. - */ +// [lua_typename] -> [-0, +0, -] +// +// Returns the name of the type encoded by the value tp, which must be one the values returned by lua_type. +// +// [lua_typename]: https://www.lua.org/manual/5.1/manual.html#lua_typename func (L *State) Typename(tp int) string { return C.GoString(C.lua_typename(L.s, C.int(tp))) } -// lua_xmove -/* - * [-?, +?, -] - * Exchange values between different threads of the same global state. - */ +// [lua_xmove] -> [-?, +?, -] +// +// Exchange values between different threads of the same global state. +// +// [lua_xmove]: https://www.lua.org/manual/5.1/manual.html#lua_xmove func XMove(from *State, to *State, n int) { C.lua_xmove(from.s, to.s, C.int(n)) } From cd31ab23902e3e9222c91c3a42145700a8164b62 Mon Sep 17 00:00:00 2001 From: Tim van Osch Date: Fri, 27 Dec 2024 20:52:25 +0100 Subject: [PATCH 099/100] docs: add TimVosch to contributors --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c400f54e..ff3d8454 100644 --- a/README.md +++ b/README.md @@ -145,6 +145,7 @@ CONTRIBUTORS * Pierre Neidhardt (@Ambrevar) * HuangWei (@huangwei1024) * Adam Saponara +* [Tim van Osch](https://github.com/TimVosch) SEE ALSO --------------------- From 248753f411c4beff8c83c02f85a4573043d20fee Mon Sep 17 00:00:00 2001 From: Mark Puha Date: Mon, 17 Feb 2025 10:14:09 +0100 Subject: [PATCH 100/100] Fix C.lua_tointeger returning C.integer in some compilers (#122) --- lua/golua_c_lua51.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/golua_c_lua51.go b/lua/golua_c_lua51.go index 39a7cd07..295211cd 100644 --- a/lua/golua_c_lua51.go +++ b/lua/golua_c_lua51.go @@ -112,7 +112,7 @@ import "C" import "unsafe" func luaToInteger(s *C.lua_State, n C.int) C.long { - return C.lua_tointeger(s, n) + return C.long(C.lua_tointeger(s, n)) } func luaToNumber(s *C.lua_State, n C.int) C.double {