From 6ce3373d6a6338463d18cff34edb369e513f4af2 Mon Sep 17 00:00:00 2001 From: Brenden Matthews Date: Sun, 25 Feb 2024 09:22:19 -0500 Subject: [PATCH] Fix C mangling for lua bindings This should resolve #1749. --- 3rdparty/toluapp/include/tolua++.h | 221 +++++----- 3rdparty/toluapp/src/bin/lua/package.lua | 501 ++++++++++++----------- 2 files changed, 373 insertions(+), 349 deletions(-) diff --git a/3rdparty/toluapp/include/tolua++.h b/3rdparty/toluapp/include/tolua++.h index cd21db4e5..317268820 100644 --- a/3rdparty/toluapp/include/tolua++.h +++ b/3rdparty/toluapp/include/tolua++.h @@ -12,12 +12,15 @@ ** enhancements, or modifications. */ - #ifndef TOLUA_H #define TOLUA_H #ifndef TOLUA_API +#ifdef __cplusplus +#define TOLUA_API extern "C" +#else /* __cplusplus */ #define TOLUA_API extern +#endif /* __cplusplus */ #endif #define TOLUA_VERSION "tolua++-1.0.92" @@ -26,14 +29,15 @@ extern "C" { #endif -#define tolua_pushcppstring(x,y) tolua_pushstring(x,y.c_str()) -#define tolua_iscppstring tolua_isstring +#define tolua_pushcppstring(x, y) tolua_pushstring(x, y.c_str()) +#define tolua_iscppstring tolua_isstring #define tolua_iscppstringarray tolua_isstringarray -#define tolua_pushfieldcppstring(L,lo,idx,s) tolua_pushfieldstring(L, lo, idx, s.c_str()) +#define tolua_pushfieldcppstring(L, lo, idx, s) \ + tolua_pushfieldstring(L, lo, idx, s.c_str()) #ifndef TEMPLATE_BIND - #define TEMPLATE_BIND(p) +#define TEMPLATE_BIND(p) #endif #define TOLUA_TEMPLATE_BIND(p) @@ -43,109 +47,127 @@ extern "C" { typedef int lua_Object; -#include #include +#include -struct tolua_Error -{ - int index; - int array; - const char* type; +struct tolua_Error { + int index; + int array; + const char* type; }; typedef struct tolua_Error tolua_Error; -#define TOLUA_NOPEER LUA_REGISTRYINDEX /* for lua 5.1 */ - -TOLUA_API const char* tolua_typename (lua_State* L, int lo); -TOLUA_API void tolua_error (lua_State* L, const char* msg, tolua_Error* err); -TOLUA_API int tolua_isnoobj (lua_State* L, int lo, tolua_Error* err); -TOLUA_API int tolua_isvalue (lua_State* L, int lo, int def, tolua_Error* err); -TOLUA_API int tolua_isvaluenil (lua_State* L, int lo, tolua_Error* err); -TOLUA_API int tolua_isboolean (lua_State* L, int lo, int def, tolua_Error* err); -TOLUA_API int tolua_isnumber (lua_State* L, int lo, int def, tolua_Error* err); -TOLUA_API int tolua_isstring (lua_State* L, int lo, int def, tolua_Error* err); -TOLUA_API int tolua_istable (lua_State* L, int lo, int def, tolua_Error* err); -TOLUA_API int tolua_isusertable (lua_State* L, int lo, const char* type, int def, tolua_Error* err); -TOLUA_API int tolua_isuserdata (lua_State* L, int lo, int def, tolua_Error* err); -TOLUA_API int tolua_isusertype (lua_State* L, int lo, const char* type, int def, tolua_Error* err); -TOLUA_API int tolua_isvaluearray - (lua_State* L, int lo, int dim, int def, tolua_Error* err); -TOLUA_API int tolua_isbooleanarray - (lua_State* L, int lo, int dim, int def, tolua_Error* err); -TOLUA_API int tolua_isnumberarray - (lua_State* L, int lo, int dim, int def, tolua_Error* err); -TOLUA_API int tolua_isstringarray - (lua_State* L, int lo, int dim, int def, tolua_Error* err); -TOLUA_API int tolua_istablearray - (lua_State* L, int lo, int dim, int def, tolua_Error* err); -TOLUA_API int tolua_isuserdataarray - (lua_State* L, int lo, int dim, int def, tolua_Error* err); -TOLUA_API int tolua_isusertypearray - (lua_State* L, int lo, const char* type, int dim, int def, tolua_Error* err); - -TOLUA_API void tolua_open (lua_State* L); - -TOLUA_API void* tolua_copy (lua_State* L, void* value, unsigned int size); -TOLUA_API int tolua_register_gc (lua_State* L, int lo); -TOLUA_API int tolua_default_collect (lua_State* tolua_S); - -TOLUA_API void tolua_usertype (lua_State* L, const char* type); -TOLUA_API void tolua_beginmodule (lua_State* L, const char* name); -TOLUA_API void tolua_endmodule (lua_State* L); -TOLUA_API void tolua_module (lua_State* L, const char* name, int hasvar); -TOLUA_API void tolua_class (lua_State* L, const char* name, const char* base); -TOLUA_API void tolua_cclass (lua_State* L, const char* lname, const char* name, const char* base, lua_CFunction col); -TOLUA_API void tolua_function (lua_State* L, const char* name, lua_CFunction func); -TOLUA_API void tolua_constant (lua_State* L, const char* name, lua_Number value); -TOLUA_API void tolua_variable (lua_State* L, const char* name, lua_CFunction get, lua_CFunction set); -TOLUA_API void tolua_array (lua_State* L,const char* name, lua_CFunction get, lua_CFunction set); - -/* TOLUA_API void tolua_set_call_event(lua_State* L, lua_CFunction func, char* type); */ +#define TOLUA_NOPEER LUA_REGISTRYINDEX /* for lua 5.1 */ + +TOLUA_API const char* tolua_typename(lua_State* L, int lo); +TOLUA_API void tolua_error(lua_State* L, const char* msg, tolua_Error* err); +TOLUA_API int tolua_isnoobj(lua_State* L, int lo, tolua_Error* err); +TOLUA_API int tolua_isvalue(lua_State* L, int lo, int def, tolua_Error* err); +TOLUA_API int tolua_isvaluenil(lua_State* L, int lo, tolua_Error* err); +TOLUA_API int tolua_isboolean(lua_State* L, int lo, int def, tolua_Error* err); +TOLUA_API int tolua_isnumber(lua_State* L, int lo, int def, tolua_Error* err); +TOLUA_API int tolua_isstring(lua_State* L, int lo, int def, tolua_Error* err); +TOLUA_API int tolua_istable(lua_State* L, int lo, int def, tolua_Error* err); +TOLUA_API int tolua_isusertable(lua_State* L, int lo, const char* type, int def, + tolua_Error* err); +TOLUA_API int tolua_isuserdata(lua_State* L, int lo, int def, tolua_Error* err); +TOLUA_API int tolua_isusertype(lua_State* L, int lo, const char* type, int def, + tolua_Error* err); +TOLUA_API int tolua_isvaluearray(lua_State* L, int lo, int dim, int def, + tolua_Error* err); +TOLUA_API int tolua_isbooleanarray(lua_State* L, int lo, int dim, int def, + tolua_Error* err); +TOLUA_API int tolua_isnumberarray(lua_State* L, int lo, int dim, int def, + tolua_Error* err); +TOLUA_API int tolua_isstringarray(lua_State* L, int lo, int dim, int def, + tolua_Error* err); +TOLUA_API int tolua_istablearray(lua_State* L, int lo, int dim, int def, + tolua_Error* err); +TOLUA_API int tolua_isuserdataarray(lua_State* L, int lo, int dim, int def, + tolua_Error* err); +TOLUA_API int tolua_isusertypearray(lua_State* L, int lo, const char* type, + int dim, int def, tolua_Error* err); + +TOLUA_API void tolua_open(lua_State* L); + +TOLUA_API void* tolua_copy(lua_State* L, void* value, unsigned int size); +TOLUA_API int tolua_register_gc(lua_State* L, int lo); +TOLUA_API int tolua_default_collect(lua_State* tolua_S); + +TOLUA_API void tolua_usertype(lua_State* L, const char* type); +TOLUA_API void tolua_beginmodule(lua_State* L, const char* name); +TOLUA_API void tolua_endmodule(lua_State* L); +TOLUA_API void tolua_module(lua_State* L, const char* name, int hasvar); +TOLUA_API void tolua_class(lua_State* L, const char* name, const char* base); +TOLUA_API void tolua_cclass(lua_State* L, const char* lname, const char* name, + const char* base, lua_CFunction col); +TOLUA_API void tolua_function(lua_State* L, const char* name, + lua_CFunction func); +TOLUA_API void tolua_constant(lua_State* L, const char* name, lua_Number value); +TOLUA_API void tolua_variable(lua_State* L, const char* name, lua_CFunction get, + lua_CFunction set); +TOLUA_API void tolua_array(lua_State* L, const char* name, lua_CFunction get, + lua_CFunction set); + +/* TOLUA_API void tolua_set_call_event(lua_State* L, lua_CFunction func, char* + * type); */ /* TOLUA_API void tolua_addbase(lua_State* L, char* name, char* base); */ -TOLUA_API void tolua_pushvalue (lua_State* L, int lo); -TOLUA_API void tolua_pushboolean (lua_State* L, int value); -TOLUA_API void tolua_pushnumber (lua_State* L, lua_Number value); -TOLUA_API void tolua_pushstring (lua_State* L, const char* value); -TOLUA_API void tolua_pushuserdata (lua_State* L, void* value); -TOLUA_API void tolua_pushusertype (lua_State* L, void* value, const char* type); -TOLUA_API void tolua_pushusertype_and_takeownership(lua_State* L, void* value, const char* type); -TOLUA_API void tolua_pushfieldvalue (lua_State* L, int lo, int index, int v); -TOLUA_API void tolua_pushfieldboolean (lua_State* L, int lo, int index, int v); -TOLUA_API void tolua_pushfieldnumber (lua_State* L, int lo, int index, lua_Number v); -TOLUA_API void tolua_pushfieldstring (lua_State* L, int lo, int index, const char* v); -TOLUA_API void tolua_pushfielduserdata (lua_State* L, int lo, int index, void* v); -TOLUA_API void tolua_pushfieldusertype (lua_State* L, int lo, int index, void* v, const char* type); -TOLUA_API void tolua_pushfieldusertype_and_takeownership (lua_State* L, int lo, int index, void* v, const char* type); - -TOLUA_API lua_Number tolua_tonumber (lua_State* L, int narg, lua_Number def); -TOLUA_API const char* tolua_tostring (lua_State* L, int narg, const char* def); -TOLUA_API void* tolua_touserdata (lua_State* L, int narg, void* def); -TOLUA_API void* tolua_tousertype (lua_State* L, int narg, void* def); -TOLUA_API int tolua_tovalue (lua_State* L, int narg, int def); -TOLUA_API int tolua_toboolean (lua_State* L, int narg, int def); -TOLUA_API lua_Number tolua_tofieldnumber (lua_State* L, int lo, int index, lua_Number def); -TOLUA_API const char* tolua_tofieldstring (lua_State* L, int lo, int index, const char* def); -TOLUA_API void* tolua_tofielduserdata (lua_State* L, int lo, int index, void* def); -TOLUA_API void* tolua_tofieldusertype (lua_State* L, int lo, int index, void* def); -TOLUA_API int tolua_tofieldvalue (lua_State* L, int lo, int index, int def); -TOLUA_API int tolua_getfieldboolean (lua_State* L, int lo, int index, int def); - -TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, const char* name); - -TOLUA_API int class_gc_event (lua_State* L); +TOLUA_API void tolua_pushvalue(lua_State* L, int lo); +TOLUA_API void tolua_pushboolean(lua_State* L, int value); +TOLUA_API void tolua_pushnumber(lua_State* L, lua_Number value); +TOLUA_API void tolua_pushstring(lua_State* L, const char* value); +TOLUA_API void tolua_pushuserdata(lua_State* L, void* value); +TOLUA_API void tolua_pushusertype(lua_State* L, void* value, const char* type); +TOLUA_API void tolua_pushusertype_and_takeownership(lua_State* L, void* value, + const char* type); +TOLUA_API void tolua_pushfieldvalue(lua_State* L, int lo, int index, int v); +TOLUA_API void tolua_pushfieldboolean(lua_State* L, int lo, int index, int v); +TOLUA_API void tolua_pushfieldnumber(lua_State* L, int lo, int index, + lua_Number v); +TOLUA_API void tolua_pushfieldstring(lua_State* L, int lo, int index, + const char* v); +TOLUA_API void tolua_pushfielduserdata(lua_State* L, int lo, int index, + void* v); +TOLUA_API void tolua_pushfieldusertype(lua_State* L, int lo, int index, void* v, + const char* type); +TOLUA_API void tolua_pushfieldusertype_and_takeownership(lua_State* L, int lo, + int index, void* v, + const char* type); + +TOLUA_API lua_Number tolua_tonumber(lua_State* L, int narg, lua_Number def); +TOLUA_API const char* tolua_tostring(lua_State* L, int narg, const char* def); +TOLUA_API void* tolua_touserdata(lua_State* L, int narg, void* def); +TOLUA_API void* tolua_tousertype(lua_State* L, int narg, void* def); +TOLUA_API int tolua_tovalue(lua_State* L, int narg, int def); +TOLUA_API int tolua_toboolean(lua_State* L, int narg, int def); +TOLUA_API lua_Number tolua_tofieldnumber(lua_State* L, int lo, int index, + lua_Number def); +TOLUA_API const char* tolua_tofieldstring(lua_State* L, int lo, int index, + const char* def); +TOLUA_API void* tolua_tofielduserdata(lua_State* L, int lo, int index, + void* def); +TOLUA_API void* tolua_tofieldusertype(lua_State* L, int lo, int index, + void* def); +TOLUA_API int tolua_tofieldvalue(lua_State* L, int lo, int index, int def); +TOLUA_API int tolua_getfieldboolean(lua_State* L, int lo, int index, int def); + +TOLUA_API void tolua_dobuffer(lua_State* L, char* B, unsigned int size, + const char* name); + +TOLUA_API int class_gc_event(lua_State* L); #ifdef __cplusplus -static inline const char* tolua_tocppstring (lua_State* L, int narg, const char* def) { - - const char* s = tolua_tostring(L, narg, def); - return s?s:""; +static inline const char* tolua_tocppstring(lua_State* L, int narg, + const char* def) { + const char* s = tolua_tostring(L, narg, def); + return s ? s : ""; } -static inline const char* tolua_tofieldcppstring (lua_State* L, int lo, int index, const char* def) { - - const char* s = tolua_tofieldstring(L, lo, index, def); - return s?s:""; +static inline const char* tolua_tofieldcppstring(lua_State* L, int lo, + int index, const char* def) { + const char* s = tolua_tofieldstring(L, lo, index, def); + return s ? s : ""; } #else @@ -153,7 +175,8 @@ static inline const char* tolua_tofieldcppstring (lua_State* L, int lo, int inde #define tolua_tofieldcppstring tolua_tofieldstring #endif -TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int super_index); +TOLUA_API int tolua_fast_isa(lua_State* L, int mt_indexa, int mt_indexb, + int super_index); #ifndef Mtolua_new #define Mtolua_new(EXP) new EXP @@ -168,7 +191,7 @@ TOLUA_API int tolua_fast_isa(lua_State *L, int mt_indexa, int mt_indexb, int sup #endif #ifndef Mtolua_delete_dim -#define Mtolua_delete_dim(EXP) delete [] EXP +#define Mtolua_delete_dim(EXP) delete[] EXP #endif #ifndef tolua_outside diff --git a/3rdparty/toluapp/src/bin/lua/package.lua b/3rdparty/toluapp/src/bin/lua/package.lua index e3638337d..7c6ae4dab 100644 --- a/3rdparty/toluapp/src/bin/lua/package.lua +++ b/3rdparty/toluapp/src/bin/lua/package.lua @@ -16,127 +16,126 @@ -- The following fields are stored: -- {i} = list of objects in the package. classPackage = { - classtype = 'package' + classtype = 'package' } classPackage.__index = classPackage -setmetatable(classPackage,classContainer) +setmetatable(classPackage, classContainer) -- Print method -function classPackage:print () - print("Package: "..self.name) - local i=1 - while self[i] do - self[i]:print("","") - i = i+1 - end +function classPackage:print() + print("Package: " .. self.name) + local i = 1 + while self[i] do + self[i]:print("", "") + i = i + 1 + end end -function classPackage:preprocess () - - -- avoid preprocessing embedded Lua code - local L = {} - self.code = gsub(self.code,"\n%s*%$%[","\1") -- deal with embedded lua code - self.code = gsub(self.code,"\n%s*%$%]","\2") - self.code = gsub(self.code,"(%b\1\2)", function (c) - tinsert(L,c) - return "\n#[".. #L .."]#" - end) - -- avoid preprocessing embedded C code - local C = {} - self.code = gsub(self.code,"\n%s*%$%<","\3") -- deal with embedded C code - self.code = gsub(self.code,"\n%s*%$%>","\4") - self.code = gsub(self.code,"(%b\3\4)", function (c) - tinsert(C,c) - return "\n#<".. #C ..">#" - end) - -- avoid preprocessing embedded C code - self.code = gsub(self.code,"\n%s*%$%{","\5") -- deal with embedded C code - self.code = gsub(self.code,"\n%s*%$%}","\6") - self.code = gsub(self.code,"(%b\5\6)", function (c) - tinsert(C,c) - return "\n#<".. #C..">#" - end) - - --self.code = gsub(self.code,"\n%s*#[^d][^\n]*\n", "\n\n") -- eliminate preprocessor directives that don't start with 'd' - self.code = gsub(self.code,"\n[ \t]*#[ \t]*[^d%<%[]", "\n//") -- eliminate preprocessor directives that don't start with 'd' - - -- avoid preprocessing verbatim lines - local V = {} - self.code = gsub(self.code,"\n(%s*%$[^%[%]][^\n]*)",function (v) - tinsert(V,v) - return "\n#".. #V .."#" - end) - - -- perform global substitution - - self.code = gsub(self.code,"(//[^\n]*)","") -- eliminate C++ comments - self.code = gsub(self.code,"/%*","\1") - self.code = gsub(self.code,"%*/","\2") - self.code = gsub(self.code,"%b\1\2","") - self.code = gsub(self.code,"\1","/%*") - self.code = gsub(self.code,"\2","%*/") - self.code = gsub(self.code,"%s*@%s*","@") -- eliminate spaces beside @ - self.code = gsub(self.code,"%s?inline(%s)","%1") -- eliminate 'inline' keyword - --self.code = gsub(self.code,"%s?extern(%s)","%1") -- eliminate 'extern' keyword - --self.code = gsub(self.code,"%s?virtual(%s)","%1") -- eliminate 'virtual' keyword - --self.code = gsub(self.code,"public:","") -- eliminate 'public:' keyword - self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*' - self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*' - self.code = gsub(self.code,"([^%w_])char%s*%*","%1_cstring ") -- substitute 'char*' - self.code = gsub(self.code,"([^%w_])lua_State%s*%*","%1_lstate ") -- substitute 'lua_State*' - - -- restore embedded Lua code - self.code = gsub(self.code,"%#%[(%d+)%]%#",function (n) - return L[tonumber(n)] - end) - -- restore embedded C code - self.code = gsub(self.code,"%#%<(%d+)%>%#",function (n) - return C[tonumber(n)] - end) - -- restore verbatim lines - self.code = gsub(self.code,"%#(%d+)%#",function (n) - return V[tonumber(n)] - end) - - self.code = string.gsub(self.code, "\n%s*%$([^\n]+)", function (l) - Verbatim(l.."\n") - return "\n" - end) +function classPackage:preprocess() + -- avoid preprocessing embedded Lua code + local L = {} + self.code = gsub(self.code, "\n%s*%$%[", "\1") -- deal with embedded lua code + self.code = gsub(self.code, "\n%s*%$%]", "\2") + self.code = gsub(self.code, "(%b\1\2)", function(c) + tinsert(L, c) + return "\n#[" .. #L .. "]#" + end) + -- avoid preprocessing embedded C code + local C = {} + self.code = gsub(self.code, "\n%s*%$%<", "\3") -- deal with embedded C code + self.code = gsub(self.code, "\n%s*%$%>", "\4") + self.code = gsub(self.code, "(%b\3\4)", function(c) + tinsert(C, c) + return "\n#<" .. #C .. ">#" + end) + -- avoid preprocessing embedded C code + self.code = gsub(self.code, "\n%s*%$%{", "\5") -- deal with embedded C code + self.code = gsub(self.code, "\n%s*%$%}", "\6") + self.code = gsub(self.code, "(%b\5\6)", function(c) + tinsert(C, c) + return "\n#<" .. #C .. ">#" + end) + + --self.code = gsub(self.code,"\n%s*#[^d][^\n]*\n", "\n\n") -- eliminate preprocessor directives that don't start with 'd' + self.code = gsub(self.code, "\n[ \t]*#[ \t]*[^d%<%[]", "\n//") -- eliminate preprocessor directives that don't start with 'd' + + -- avoid preprocessing verbatim lines + local V = {} + self.code = gsub(self.code, "\n(%s*%$[^%[%]][^\n]*)", function(v) + tinsert(V, v) + return "\n#" .. #V .. "#" + end) + + -- perform global substitution + + self.code = gsub(self.code, "(//[^\n]*)", "") -- eliminate C++ comments + self.code = gsub(self.code, "/%*", "\1") + self.code = gsub(self.code, "%*/", "\2") + self.code = gsub(self.code, "%b\1\2", "") + self.code = gsub(self.code, "\1", "/%*") + self.code = gsub(self.code, "\2", "%*/") + self.code = gsub(self.code, "%s*@%s*", "@") -- eliminate spaces beside @ + self.code = gsub(self.code, "%s?inline(%s)", "%1") -- eliminate 'inline' keyword + --self.code = gsub(self.code,"%s?extern(%s)","%1") -- eliminate 'extern' keyword + --self.code = gsub(self.code,"%s?virtual(%s)","%1") -- eliminate 'virtual' keyword + --self.code = gsub(self.code,"public:","") -- eliminate 'public:' keyword + self.code = gsub(self.code, "([^%w_])void%s*%*", "%1_userdata ") -- substitute 'void*' + self.code = gsub(self.code, "([^%w_])void%s*%*", "%1_userdata ") -- substitute 'void*' + self.code = gsub(self.code, "([^%w_])char%s*%*", "%1_cstring ") -- substitute 'char*' + self.code = gsub(self.code, "([^%w_])lua_State%s*%*", "%1_lstate ") -- substitute 'lua_State*' + + -- restore embedded Lua code + self.code = gsub(self.code, "%#%[(%d+)%]%#", function(n) + return L[tonumber(n)] + end) + -- restore embedded C code + self.code = gsub(self.code, "%#%<(%d+)%>%#", function(n) + return C[tonumber(n)] + end) + -- restore verbatim lines + self.code = gsub(self.code, "%#(%d+)%#", function(n) + return V[tonumber(n)] + end) + + self.code = string.gsub(self.code, "\n%s*%$([^\n]+)", function(l) + Verbatim(l .. "\n") + return "\n" + end) end -- translate verbatim -function classPackage:preamble () - output('/*\n') - output('** Lua binding: '..self.name..'\n') - output('** Generated automatically by '..TOLUA_VERSION..'.\n') - output('*/\n\n') +function classPackage:preamble() + output('/*\n') + output('** Lua binding: ' .. self.name .. '\n') + output('** Generated automatically by ' .. TOLUA_VERSION .. '.\n') + output('*/\n\n') output('#ifndef __cplusplus\n') output('#include "stdlib.h"\n') output('#endif\n') output('#include "string.h"\n\n') - output('#include "tolua++.h"\n\n') + output('#include "tolua++.h"\n\n') - if not flags.h then - output('/* Exported function */') - output('TOLUA_API int tolua_'..self.name..'_open (lua_State* tolua_S);') - output('\n') - end + if not flags.h then + output('/* Exported function */') + output('TOLUA_API int tolua_' .. self.name .. '_open (lua_State* tolua_S);') + output('\n') + end - local i=1 - while self[i] do - self[i]:preamble() - i = i+1 - end + local i = 1 + while self[i] do + self[i]:preamble() + i = i + 1 + end if self:requirecollection(_collect) then output('\n') output('/* function to release collected object via destructor */') output('#ifdef __cplusplus\n') - for i,v in op:ordered_pairs(_collect) do - output('\nstatic int '..v..' (lua_State* tolua_S)') + for i, v in op:ordered_pairs(_collect) do + output('\nstatic int ' .. v .. ' (lua_State* tolua_S)') output('{') - output(' '..i..'* self = ('..i..'*) tolua_tousertype(tolua_S,1,0);') + output(' ' .. i .. '* self = (' .. i .. '*) tolua_tousertype(tolua_S,1,0);') output(' Mtolua_delete(self);') output(' return 0;') output('}') @@ -144,199 +143,201 @@ function classPackage:preamble () output('#endif\n\n') end - output('\n') - output('/* function to register type */') - output('static void tolua_reg_types (lua_State* tolua_S)') - output('{') + output('\n') + output('/* function to register type */') + output('static void tolua_reg_types (lua_State* tolua_S)') + output('{') if flags.t then output("#ifndef Mtolua_typeid\n#define Mtolua_typeid(L,TI,T)\n#endif\n") end - for n,v in op:ordered_pairs(_usertype) do + for n, v in op:ordered_pairs(_usertype) do if (not _global_classes[v]) or _global_classes[v]:check_public_access() then - output(' tolua_usertype(tolua_S,"',v,'");') + output(' tolua_usertype(tolua_S,"', v, '");') if flags.t then - output(' Mtolua_typeid(tolua_S,typeid(',v,'), "',v,'");') + output(' Mtolua_typeid(tolua_S,typeid(', v, '), "', v, '");') end end - end - output('}') - output('\n') + end + output('}') + output('\n') end -- register package -- write package open function -function classPackage:register (pre) - pre = pre or '' - push(self) - output(pre.."/* Open function */") - output(pre.."TOLUA_API int tolua_"..self.name.."_open (lua_State* tolua_S)") - output(pre.."{") - output(pre.." tolua_open(tolua_S);") - output(pre.." tolua_reg_types(tolua_S);") - output(pre.." tolua_module(tolua_S,NULL,",self:hasvar(),");") - output(pre.." tolua_beginmodule(tolua_S,NULL);") - local i=1 - while self[i] do - self[i]:register(pre.." ") - i = i+1 - end - output(pre.." tolua_endmodule(tolua_S);") - output(pre.." return 1;") - output(pre.."}") - - output("\n\n") - output("#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501\n"); - output(pre.."TOLUA_API int luaopen_"..self.name.." (lua_State* tolua_S) {") - output(pre.." return tolua_"..self.name.."_open(tolua_S);") - output(pre.."}") - output("#endif\n\n") +function classPackage:register(pre) + pre = pre or '' + push(self) + output(pre .. "/* Open function */") + output(pre .. "TOLUA_API int tolua_" .. self.name .. "_open (lua_State* tolua_S)") + output(pre .. "{") + output(pre .. " tolua_open(tolua_S);") + output(pre .. " tolua_reg_types(tolua_S);") + output(pre .. " tolua_module(tolua_S,NULL,", self:hasvar(), ");") + output(pre .. " tolua_beginmodule(tolua_S,NULL);") + local i = 1 + while self[i] do + self[i]:register(pre .. " ") + i = i + 1 + end + output(pre .. " tolua_endmodule(tolua_S);") + output(pre .. " return 1;") + output(pre .. "}") + + output("\n\n") + output("#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501\n"); + output(pre .. "TOLUA_API int luaopen_" .. self.name .. " (lua_State* tolua_S) {") + output(pre .. " return tolua_" .. self.name .. "_open(tolua_S);") + output(pre .. "}") + output("#endif\n\n") pop() end -- write header file -function classPackage:header () - output('/*\n') output('** Lua binding: '..self.name..'\n') - output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n') - output('*/\n\n') - - if not flags.h then - output('/* Exported function */') - output('TOLUA_API int tolua_'..self.name..'_open (lua_State* tolua_S);') - output('\n') - end +function classPackage:header() + output('/*\n') + output('** Lua binding: ' .. self.name .. '\n') + output('** Generated automatically by ' .. TOLUA_VERSION .. ' on ' .. date() .. '.\n') + output('*/\n\n') + + if not flags.h then + output('/* Exported function */') + output('TOLUA_API int tolua_' .. self.name .. '_open (lua_State* tolua_S);') + output('\n') + end end -- Internal constructor -function _Package (self) - setmetatable(self,classPackage) - return self +function _Package(self) + setmetatable(self, classPackage) + return self end -- Parse C header file with tolua directives -- *** Thanks to Ariel Manzur for fixing bugs in nested directives *** -function extract_code(fn,s) - local code = '\n$#include "'..fn..'"\n' - s= "\n" .. s .. "\n" -- add blank lines as sentinels - local _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n") +function extract_code(fn, s) + local code = '\n$#include "' .. fn .. '"\n' + s = "\n" .. s .. "\n" -- add blank lines as sentinels + local _, e, c, t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n") while e do t = strlower(t) if t == "begin" then - _,e,c = strfind(s,"(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n",e) + _, e, c = strfind(s, "(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n", e) if not e then - tolua_error("Unbalanced 'tolua_begin' directive in header file") + tolua_error("Unbalanced 'tolua_begin' directive in header file") end end code = code .. c .. "\n" - _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n",e) + _, e, c, t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n", e) end return code end -- Constructor -- Expects the package name, the file extension, and the file text. -function Package (name,fn) - local ext = "pkg" - - -- open input file, if any - local st,msg - if fn then - st, msg = readfrom(flags.f) - if not st then - error('#'..msg) - end - local _; _, _, ext = strfind(fn,".*%.(.*)$") - end - local code - if ext == 'pkg' then - code = prep(st) - else - code = "\n" .. read('*a') - if ext == 'h' or ext == 'hpp' then - code = extract_code(fn,code) - end - end - - -- close file - if fn then - readfrom() - end - - -- deal with include directive - local nsubst - repeat - code,nsubst = gsub(code,'\n%s*%$(.)file%s*"(.-)"([^\n]*)\n', - function (kind,fn,extra) - local _, _, ext = strfind(fn,".*%.(.*)$") - local fp,msg = openfile(fn,'r') - if not fp then - error('#'..msg..': '..fn) - end - if kind == 'p' then - local s = prep(fp) +function Package(name, fn) + local ext = "pkg" + + -- open input file, if any + local st, msg + if fn then + st, msg = readfrom(flags.f) + if not st then + error('#' .. msg) + end + local _; _, _, ext = strfind(fn, ".*%.(.*)$") + end + local code + if ext == 'pkg' then + code = prep(st) + else + code = "\n" .. read('*a') + if ext == 'h' or ext == 'hpp' then + code = extract_code(fn, code) + end + end + + -- close file + if fn then + readfrom() + end + + -- deal with include directive + local nsubst + repeat + code, nsubst = gsub(code, '\n%s*%$(.)file%s*"(.-)"([^\n]*)\n', + function(kind, fn, extra) + local _, _, ext = strfind(fn, ".*%.(.*)$") + local fp, msg = openfile(fn, 'r') + if not fp then + error('#' .. msg .. ': ' .. fn) + end + if kind == 'p' then + local s = prep(fp) + closefile(fp) + return s + end + local s = read(fp, '*a') closefile(fp) - return s - end - local s = read(fp,'*a') - closefile(fp) - if kind == 'c' or kind == 'h' then - return extract_code(fn,s) - elseif kind == 'l' then - return "\n$[--##"..fn.."\n" .. s .. "\n$]\n" - elseif kind == 'i' then - local t = {code=s} - extra = string.gsub(extra, "^%s*,%s*", "") - local pars = split_c_tokens(extra, ",") - include_file_hook(t, fn, table.unpack(pars)) - return "\n\n" .. t.code - else - error('#Invalid include directive (use $cfile, $pfile, $lfile or $ifile)') - end + if kind == 'c' or kind == 'h' then + return extract_code(fn, s) + elseif kind == 'l' then + return "\n$[--##" .. fn .. "\n" .. s .. "\n$]\n" + elseif kind == 'i' then + local t = { code = s } + extra = string.gsub(extra, "^%s*,%s*", "") + local pars = split_c_tokens(extra, ",") + include_file_hook(t, fn, table.unpack(pars)) + return "\n\n" .. t.code + else + error('#Invalid include directive (use $cfile, $pfile, $lfile or $ifile)') + end + end) + until nsubst == 0 + + -- deal with renaming directive + repeat -- I don't know why this is necesary + code, nsubst = gsub(code, '\n%s*%$renaming%s*(.-)%s*\n', function(r) + appendrenaming(r) + return "\n" end) - until nsubst==0 - - -- deal with renaming directive - repeat -- I don't know why this is necesary - code,nsubst = gsub(code,'\n%s*%$renaming%s*(.-)%s*\n', function (r) appendrenaming(r) return "\n" end) - until nsubst == 0 - - local t = _Package(_Container{name=name, code=code}) - push(t) - preprocess_hook(t) - t:preprocess() - preparse_hook(t) - t:parse(t.code) - pop() - return t + until nsubst == 0 + + local t = _Package(_Container { name = name, code = code }) + push(t) + preprocess_hook(t) + t:preprocess() + preparse_hook(t) + t:parse(t.code) + pop() + return t end - setmetatable(_extra_parameters, { __index = _G }) function prep(file) - - local chunk = {'local __ret = {"\\n"}\n'} - for line in file:lines() do - if string.find(line, "^##") then - table.insert(chunk, string.sub(line, 3) .. "\n") - else - local last = 1 - for text, expr, index in string.gmatch(line, "(.-)$(%b())()") do - last = index - if text ~= "" then - table.insert(chunk, string.format('table.insert(__ret, %q )', text)) - end - table.insert(chunk, string.format('table.insert(__ret, %s )', expr)) - end - table.insert(chunk, string.format('table.insert(__ret, %q)\n', - string.sub(line, last).."\n")) - end - end - table.insert(chunk, '\nreturn table.concat(__ret)\n') - local f,e = load(table.concat(chunk), nil, "t", _extra_parameters) - if e then - error("#"..e) - end - return f() + local chunk = { 'local __ret = {"\\n"}\n' } + for line in file:lines() do + if string.find(line, "^##") then + table.insert(chunk, string.sub(line, 3) .. "\n") + else + local last = 1 + for text, expr, index in string.gmatch(line, "(.-)$(%b())()") do + last = index + if text ~= "" then + table.insert(chunk, string.format('table.insert(__ret, %q )', text)) + end + table.insert(chunk, string.format('table.insert(__ret, %s )', expr)) + end + table.insert(chunk, string.format('table.insert(__ret, %q)\n', + string.sub(line, last) .. "\n")) + end + end + table.insert(chunk, '\nreturn table.concat(__ret)\n') + local f, e = load(table.concat(chunk), nil, "t", _extra_parameters) + if e then + error("#" .. e) + end + return f() end