This commit is contained in:
aixianling
2025-01-09 17:45:40 +08:00
commit 5c9f1dae4a
3482 changed files with 1146531 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<noInheritable></noInheritable>
<assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50727.762" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
<file name="msvcr80.dll" hash="10f4cb2831f1e9288a73387a8734a8b604e5beaa" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>n9On8FItNsK/DmT8UQxu6jYDtWQ=</dsig:DigestValue></asmv2:hash></file>
<file name="msvcp80.dll" hash="b2082dfd3009365c5b287448dcb3b4e2158a6d26" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>0KJ/VTwP4OUHx98HlIW2AdW1kuY=</dsig:DigestValue></asmv2:hash></file>
<file name="msvcm80.dll" hash="542490d0fcf8615c46d0ca487033ccaeb3941f0b" hashalg="SHA1"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>YJuB+9Os2oxW4mY+2oC/r8lICZE=</dsig:DigestValue></asmv2:hash></file>
</assembly>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,29 @@
--dofile(path.."compat-5.1.lua")
dofile(path.."compat.lua")
dofile(path.."basic.lua")
dofile(path.."feature.lua")
dofile(path.."verbatim.lua")
dofile(path.."code.lua")
dofile(path.."typedef.lua")
dofile(path.."container.lua")
dofile(path.."package.lua")
dofile(path.."module.lua")
dofile(path.."namespace.lua")
dofile(path.."define.lua")
dofile(path.."enumerate.lua")
dofile(path.."declaration.lua")
dofile(path.."variable.lua")
dofile(path.."array.lua")
dofile(path.."function.lua")
dofile(path.."operator.lua")
dofile(path.."class.lua")
dofile(path.."clean.lua")
--dofile(path.."custom.lua")
dofile(path.."doit.lua")
local err,msg = xpcall(doit, debug.traceback)
if not err then
--print("**** msg is "..tostring(msg))
local _,_,label,msg = strfind(msg,"(.-:.-:%s*)(.*)")
tolua_error(msg,label)
end

View File

@@ -0,0 +1,227 @@
-- tolua: array class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1999
-- $Id: array.lua 1141 2006-05-18 23:58:45Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Array class
-- Represents a extern array variable or a public member of a class.
-- Stores all fields present in a declaration.
classArray = {
}
classArray.__index = classArray
setmetatable(classArray,classDeclaration)
-- Print method
function classArray:print (ident,close)
print(ident.."Array{")
print(ident.." mod = '"..self.mod.."',")
print(ident.." type = '"..self.type.."',")
print(ident.." ptr = '"..self.ptr.."',")
print(ident.." name = '"..self.name.."',")
print(ident.." def = '"..self.def.."',")
print(ident.." dim = '"..self.dim.."',")
print(ident.." ret = '"..self.ret.."',")
print(ident.."}"..close)
end
-- check if it is a variable
function classArray:isvariable ()
return true
end
-- get variable value
function classArray:getvalue (class,static)
if class and static then
return class..'::'..self.name..'[tolua_index]'
elseif class then
return 'self->'..self.name..'[tolua_index]'
else
return self.name..'[tolua_index]'
end
end
-- Write binding functions
function classArray:supcode ()
local class = self:inclass()
-- get function ------------------------------------------------
if class then
output("/* get function:",self.name," of class ",class," */")
else
output("/* get function:",self.name," */")
end
self.cgetname = self:cfuncname("tolua_get")
output("#ifndef TOLUA_DISABLE_"..self.cgetname)
output("\nstatic int",self.cgetname,"(lua_State* tolua_S)")
output("{")
output(" int tolua_index;")
-- declare self, if the case
local _,_,static = strfind(self.mod,'^%s*(static)')
if class and static==nil then
output(' ',self.parent.type,'*','self;')
output(' lua_pushstring(tolua_S,".self");')
output(' lua_rawget(tolua_S,1);')
output(' self = ')
output('(',self.parent.type,'*) ')
output('lua_touserdata(tolua_S,-1);')
elseif static then
_,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
end
-- check index
output('#ifndef TOLUA_RELEASE\n')
output(' {')
output(' tolua_Error tolua_err;')
output(' if (!tolua_isnumber(tolua_S,2,0,&tolua_err))')
output(' tolua_error(tolua_S,(char*)"#vinvalid type in array indexing.",&tolua_err);')
output(' }')
output('#endif\n')
if flags['1'] then -- for compatibility with tolua5 ?
output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0)-1;')
else
output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0);')
end
output('#ifndef TOLUA_RELEASE\n')
if self.dim and self.dim ~= '' then
output(' if (tolua_index<0 || tolua_index>='..self.dim..')')
else
output(' if (tolua_index<0)')
end
output(' tolua_error(tolua_S,(char*)"array indexing out of range.",NULL);')
output('#endif\n')
-- return value
local t,ct = isbasic(self.type)
if t then
output(' tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static)..');')
else
t = self.type
if self.ptr == '&' or self.ptr == '' then
output(' tolua_pushusertype(tolua_S,(void*)&'..self:getvalue(class,static)..',"',t,'");')
else
output(' tolua_pushusertype(tolua_S,(void*)'..self:getvalue(class,static)..',"',t,'");')
end
end
output(' return 1;')
output('}')
output('#endif //#ifndef TOLUA_DISABLE\n')
output('\n')
-- set function ------------------------------------------------
if not strfind(self.type,'const') then
if class then
output("/* set function:",self.name," of class ",class," */")
else
output("/* set function:",self.name," */")
end
self.csetname = self:cfuncname("tolua_set")
output("#ifndef TOLUA_DISABLE_"..self.csetname)
output("\nstatic int",self.csetname,"(lua_State* tolua_S)")
output("{")
-- declare index
output(' int tolua_index;')
-- declare self, if the case
local _,_,static = strfind(self.mod,'^%s*(static)')
if class and static==nil then
output(' ',self.parent.type,'*','self;')
output(' lua_pushstring(tolua_S,".self");')
output(' lua_rawget(tolua_S,1);')
output(' self = ')
output('(',self.parent.type,'*) ')
output('lua_touserdata(tolua_S,-1);')
elseif static then
_,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
end
-- check index
output('#ifndef TOLUA_RELEASE\n')
output(' {')
output(' tolua_Error tolua_err;')
output(' if (!tolua_isnumber(tolua_S,2,0,&tolua_err))')
output(' tolua_error(tolua_S,(char*)"#vinvalid type in array indexing.",&tolua_err);')
output(' }')
output('#endif\n')
if flags['1'] then -- for compatibility with tolua5 ?
output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0)-1;')
else
output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0);')
end
output('#ifndef TOLUA_RELEASE\n')
if self.dim and self.dim ~= '' then
output(' if (tolua_index<0 || tolua_index>='..self.dim..')')
else
output(' if (tolua_index<0)')
end
output(' tolua_error(tolua_S,(char*)"array indexing out of range.",NULL);')
output('#endif\n')
-- assign value
local ptr = ''
if self.ptr~='' then ptr = '*' end
output(' ')
if class and static then
output(class..'::'..self.name..'[tolua_index]')
elseif class then
output('self->'..self.name..'[tolua_index]')
else
output(self.name..'[tolua_index]')
end
local t = isbasic(self.type)
output(' = ')
if not t and ptr=='' then output('*') end
output('((',self.mod,self.type)
if not t then
output('*')
end
output(') ')
local def = 0
if self.def ~= '' then def = self.def end
if t then
output('tolua_to'..t,'(tolua_S,3,',def,'));')
else
output('tolua_tousertype(tolua_S,3,',def,'));')
end
output(' return 0;')
output('}')
output('#endif //#ifndef TOLUA_DISABLE\n')
output('\n')
end
end
function classArray:register (pre)
pre = pre or ''
if self.csetname then
output(pre..'tolua_array(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');')
else
output(pre..'tolua_array(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);')
end
end
-- Internal constructor
function _Array (t)
setmetatable(t,classArray)
append(t)
return t
end
-- Constructor
-- Expects a string representing the variable declaration.
function Array (s)
return _Array (Declaration(s,'var'))
end

View File

@@ -0,0 +1,435 @@
-- tolua: basic utility functions
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- Last update: Apr 2003
-- $Id: basic.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Basic C types and their corresponding Lua types
-- All occurrences of "char*" will be replaced by "_cstring",
-- and all occurrences of "void*" will be replaced by "_userdata"
_basic = {
['void'] = '',
['char'] = 'number',
['int'] = 'number',
['short'] = 'number',
['long'] = 'number',
['unsigned'] = 'number',
['float'] = 'number',
['double'] = 'number',
['_cstring'] = 'string',
['_userdata'] = 'userdata',
['char*'] = 'string',
['void*'] = 'userdata',
['bool'] = 'boolean',
['lua_Object'] = 'value',
['LUA_VALUE'] = 'value', -- for compatibility with tolua 4.0
['lua_State*'] = 'state',
['_lstate'] = 'state',
['lua_Function'] = 'value',
-- modified by PeakGao
['__int64'] = 'number',
['wchar_t'] = 'number',
['String'] = 'string',
}
_basic_ctype = {
number = "lua_Number",
string = "const char*",
userdata = "void*",
boolean = "bool",
value = "int",
state = "lua_State*",
}
-- functions the are used to do a 'raw push' of basic types
_basic_raw_push = {}
-- List of user defined types
-- Each type corresponds to a variable name that stores its tag value.
_usertype = {}
-- List of types that have to be collected
_collect = {}
-- List of types
_global_types = {n=0}
_global_types_hash = {}
-- list of classes
_global_classes = {}
-- List of enum constants
_global_enums = {}
-- List of auto renaming
_renaming = {}
function appendrenaming (s)
local b,e,old,new = strfind(s,"%s*(.-)%s*@%s*(.-)%s*$")
if not b then
error("#Invalid renaming syntax; it should be of the form: pattern@pattern")
end
tinsert(_renaming,{old=old, new=new})
end
function applyrenaming (s)
for i=1,getn(_renaming) do
local m,n = gsub(s,_renaming[i].old,_renaming[i].new)
if n ~= 0 then
return m
end
end
return nil
end
-- Error handler
function tolua_error (s,f)
if _curr_code then
print("***curr code for error is "..tostring(_curr_code))
print(debug.traceback())
end
local out = _OUTPUT
_OUTPUT = _STDERR
if strsub(s,1,1) == '#' then
write("\n** tolua: "..strsub(s,2)..".\n\n")
if _curr_code then
local _,_,s = strfind(_curr_code,"^%s*(.-\n)") -- extract first line
if s==nil then s = _curr_code end
s = gsub(s,"_userdata","void*") -- return with 'void*'
s = gsub(s,"_cstring","char*") -- return with 'char*'
s = gsub(s,"_lstate","lua_State*") -- return with 'lua_State*'
write("Code being processed:\n"..s.."\n")
end
else
if not f then f = "(f is nil)" end
print("\n** tolua internal error: "..f..s..".\n\n")
return
end
_OUTPUT = out
end
function warning (msg)
local out = _OUTPUT
_OUTPUT = _STDERR
write("\n** tolua warning: "..msg..".\n\n")
_OUTPUT = out
end
-- register an user defined type: returns full type
function regtype (t)
--if isbasic(t) then
-- return t
--end
local ft = findtype(t)
if not _usertype[ft] then
return appendusertype(t)
end
return ft
end
-- return type name: returns full type
function typevar(type)
if type == '' or type == 'void' then
return type
else
local ft = findtype(type)
if ft then
return ft
end
_usertype[type] = type
return type
end
end
-- check if basic type
function isbasic (type)
local t = gsub(type,'const ','')
local m,t = applytypedef('', t)
local b = _basic[t]
if b then
return b,_basic_ctype[b]
end
return nil
end
-- split string using a token
function split (s,t)
local l = {n=0}
local f = function (s)
l.n = l.n + 1
l[l.n] = s
return ""
end
local p = "%s*(.-)%s*"..t.."%s*"
s = gsub(s,"^%s+","")
s = gsub(s,"%s+$","")
s = gsub(s,p,f)
l.n = l.n + 1
l[l.n] = gsub(s,"(%s%s*)$","")
return l
end
-- splits a string using a pattern, considering the spacial cases of C code (templates, function parameters, etc)
-- pattern can't contain the '^' (as used to identify the begining of the line)
-- also strips whitespace
function split_c_tokens(s, pat)
s = string.gsub(s, "^%s*", "")
s = string.gsub(s, "%s*$", "")
local token_begin = 1
local token_end = 1
local ofs = 1
local ret = {n=0}
function add_token(ofs)
local t = string.sub(s, token_begin, ofs)
t = string.gsub(t, "^%s*", "")
t = string.gsub(t, "%s*$", "")
ret.n = ret.n + 1
ret[ret.n] = t
end
while ofs <= string.len(s) do
local sub = string.sub(s, ofs, -1)
local b,e = string.find(sub, "^"..pat)
if b then
add_token(ofs-1)
ofs = ofs+e
token_begin = ofs
else
local char = string.sub(s, ofs, ofs)
if char == "(" or char == "<" then
local block
if char == "(" then block = "^%b()" end
if char == "<" then block = "^%b<>" end
b,e = string.find(sub, block)
if not b then
-- unterminated block?
ofs = ofs+1
else
ofs = ofs + e
end
else
ofs = ofs+1
end
end
end
add_token(ofs)
--if ret.n == 0 then
-- ret.n=1
-- ret[1] = ""
--end
return ret
end
-- concatenate strings of a table
function concat (t,f,l,jstr)
jstr = jstr or " "
local s = ''
local i=f
while i<=l do
s = s..t[i]
i = i+1
if i <= l then s = s..jstr end
end
return s
end
-- concatenate all parameters, following output rules
function concatparam (line, ...)
local i=1
while i<=arg.n do
if _cont and not strfind(_cont,'[%(,"]') and
strfind(arg[i],"^[%a_~]") then
line = line .. ' '
end
line = line .. arg[i]
if arg[i] ~= '' then
_cont = strsub(arg[i],-1,-1)
end
i = i+1
end
if strfind(arg[arg.n],"[%/%)%;%{%}]$") then
_cont=nil line = line .. '\n'
end
return line
end
-- output line
function output (...)
local i=1
while i<=arg.n do
if _cont and not strfind(_cont,'[%(,"]') and
strfind(arg[i],"^[%a_~]") then
write(' ')
end
write(arg[i])
if arg[i] ~= '' then
_cont = strsub(arg[i],-1,-1)
end
i = i+1
end
if strfind(arg[arg.n],"[%/%)%;%{%}]$") then
_cont=nil write('\n')
end
end
function get_property_methods(ptype, name)
if get_property_methods_hook and get_property_methods_hook(ptype,name) then
return get_property_methods_hook(ptype, name)
end
if ptype == "default" then -- get_name, set_name
return "get_"..name, "set_"..name
end
if ptype == "qt" then -- name, setName
return name, "set"..string.upper(string.sub(name, 1, 1))..string.sub(name, 2, -1)
end
if ptype == "overload" then -- name, name
return name,name
end
return nil
end
-------------- the hooks
-- called right after processing the $[ichl]file directives,
-- right before processing anything else
-- takes the package object as the parameter
-- modified by PeakGao
myTypeDef = {
"Void", "HEntity","HItem",
"Bool",
"Int8", "Uint8",
"Int16", "Uint16",
"Int", "Uint", "size_t",
"Int32", "Uint32",
"Int64", "Uint64",
"Float", "Double",
"AChar", "WChar", "Char",
"PAChar", "PWChar", "PChar",
"CPAChar", "CPWChar", "CPChar",
"SString",
"Range",
"UID",
"PT_KEY",
}
myTypeDefReplace = {
"void", "unsigned long","unsigned long",
"bool",
"char", "unsigned char",
"short", "unsigned short",
"int", "unsigned int", "unsigned int",
"long", "unsigned long",
"__int64", "unsigned __int64",
"float", "double",
"char", "wchar_t", "char",
"char*", "wchar_t*", "char*",
"const char*", "const wchar_t*", "const char*",
"const char*",
"__int64",
"__int64",
"unsigned long",
}
function preprocess_hook(p)
-- p.code has all the input code from the pkg
--print(p.code)
--local _, _, key = strfind(p.code, "#ifndef%s*([%w_]+)")
--p.code = gsub(p.code, "#define%s*"..key, "");
p.code = gsub(p.code, "(#define%s*[%w_]+%()", "// %1") -- 注释函数型定义宏
p.code = gsub(p.code, "#define%s*[%w_]+%s*%c*\n", "") -- 注释头文件防止多次包含的宏
p.code = gsub(p.code, "%s*class%s*[%w_]+%s*;", "") -- 删除前向声明的类
p.code = gsub(p.code, "%s*struct%s*[%w_]+%s*;", "") -- 删除前向声明的结构
--print(p.code)
local count = table.getn(myTypeDef)
local mode
local mode_replace
for i, count in pairs(myTypeDef) do
mode = "([^%w_])" .. myTypeDef[i] .. "([^%w_])"
mode_replace = "%1" .. myTypeDefReplace[i] .. "%2"
p.code = gsub(p.code, mode, mode_replace)
end
--print(p.code)
end
-- called for every $ifile directive
-- takes a table with a string called 'code' inside, the filename, and any extra arguments
-- passed to $ifile. no return value
function include_file_hook(t, filename, ...)
end
-- called after processing anything that's not code (like '$renaming', comments, etc)
-- and right before parsing the actual code.
-- takes the Package object with all the code on the 'code' key. no return value
function preparse_hook(package)
-- modified by PeakGao
--print(package.code)
package.code = gsub(package.code, "%s?Inline(%s)", "%1") -- eliminate 'Inline' keyword
package.code = gsub(package.code, "%s?InlineFC(%s)", "%1") -- eliminate 'InlineFC' keyword
package.code = gsub(package.code, "(%s*)FCL_CLASS_DECL(%s*)", " ") -- eliminate 'FCL_CLASS_DECL' keyword
package.code = gsub(package.code, "(%s*)FCLAPI(%s*)", "") -- eliminate 'FCLAPI' keyword
package.code = gsub(package.code, "(%s*)SDK_API(%s*)", "") -- eliminate 'FCLAPI' keyword
package.code = gsub(package.code, "(%s*)DECAPI(%s*)", "") -- eliminate 'FCLAPI' keyword
package.code = gsub(package.code, "(%s*)MT_API(%s*)", "") -- eliminate 'MT_API' keyword
package.code = gsub(package.code, "(%s*)GAME_ENGINE_API(%s*)", "") -- eliminate 'GAME_ENGINE_API' keyword
package.code = gsub(package.code, "(%s*)LUASVR_API(%s*)", "") -- eliminate 'LUASVR_API' keyword
package.code = gsub(package.code, "BEGIN_NAMESPACE_FCL", "")
package.code = gsub(package.code, "END_NAMESPACE", "")
package.code = gsub(package.code, "BEGIN_NAMESPACE_MMORPG", "")
package.code = gsub(package.code, "BEGIN_API", "")
package.code = gsub(package.code, "END_API", "")
package.code = gsub(package.code, "([^%w_])%s*IN%s*([^%w_])", "%1%2")
package.code = gsub(package.code, "([^%w_])%s*OUT%s*([^%w_])", "%1%2")
--print(package.code)
end
-- called after writing all the output.
-- takes the Package object
function post_output_hook(package)
end
-- called from 'get_property_methods' to get the methods to retrieve a property
-- according to its type
function get_property_methods_hook(property_type, name)
end
-- called from ClassContainer:doparse with the string being parsed
-- return nil, or a substring
function parser_hook(s)
return nil
end

View File

@@ -0,0 +1,220 @@
-- tolua: class class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: class.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Class class
-- Represents a class definition.
-- Stores the following fields:
-- name = class name
-- base = class base, if any (only single inheritance is supported)
-- {i} = list of members
classClass = {
classtype = 'class',
name = '',
base = '',
type = '',
btype = '',
ctype = '',
}
classClass.__index = classClass
setmetatable(classClass,classContainer)
-- register class
function classClass:register (pre)
if not self:check_public_access() then
return
end
pre = pre or ''
push(self)
if _collect[self.type] then
output(pre,'#ifdef __cplusplus\n')
output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",'.._collect[self.type]..');')
output(pre,'#else\n')
output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
output(pre,'#endif\n')
else
output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
end
if self.extra_bases then
for k,base in ipairs(self.extra_bases) do
-- not now
--output(pre..' tolua_addbase(tolua_S, "'..self.type..'", "'..base..'");')
end
end
output(pre..'tolua_beginmodule(tolua_S,(char*)"'..self.lname..'");')
local i=1
while self[i] do
self[i]:register(pre..' ')
i = i+1
end
output(pre..'tolua_endmodule(tolua_S);')
pop()
end
-- return collection requirement
function classClass:requirecollection (t)
if self.flags.protected_destructor then
return false
end
push(self)
local r = false
local i=1
while self[i] do
r = self[i]:requirecollection(t) or r
i = i+1
end
pop()
-- only class that exports destructor can be appropriately collected
-- classes that export constructors need to have a collector (overrided by -D flag on command line)
if self._delete or ((not flags['D']) and self._new) then
--t[self.type] = "tolua_collect_" .. gsub(self.type,"::","_")
t[self.type] = "tolua_collect_" .. clean_template(self.type)
r = true
end
return r
end
-- output tags
function classClass:decltype ()
push(self)
self.type = regtype(self.original_name or self.name)
self.btype = typevar(self.base)
self.ctype = 'const '..self.type
if self.extra_bases then
for i=1,table.getn(self.extra_bases) do
self.extra_bases[i] = typevar(self.extra_bases[i])
end
end
local i=1
while self[i] do
self[i]:decltype()
i = i+1
end
pop()
end
-- Print method
function classClass:print (ident,close)
print(ident.."Class{")
print(ident.." name = '"..self.name.."',")
print(ident.." base = '"..self.base.."';")
print(ident.." lname = '"..self.lname.."',")
print(ident.." type = '"..self.type.."',")
print(ident.." btype = '"..self.btype.."',")
print(ident.." ctype = '"..self.ctype.."',")
local i=1
while self[i] do
self[i]:print(ident.." ",",")
i = i+1
end
print(ident.."}"..close)
end
function classClass:set_protected_destructor(p)
self.flags.protected_destructor = self.flags.protected_destructor or p
end
-- Internal constructor
function _Class (t)
setmetatable(t,classClass)
t:buildnames()
append(t)
return t
end
-- Constructor
-- Expects the name, the base (array) and the body of the class.
function Class (n,p,b)
if table.getn(p) > 1 then
b = string.sub(b, 1, -2)
for i=2,table.getn(p),1 do
b = b.."\n tolua_inherits "..p[i].." __"..p[i].."__;\n"
end
b = b.."\n}"
end
-- check for template
b = string.gsub(b, "^{%s*TEMPLATE_BIND", "{\nTOLUA_TEMPLATE_BIND")
local t,_,T,I = string.find(b, "^{%s*TOLUA_TEMPLATE_BIND%s*%(+%s*\"?([^\",]*)\"?%s*,%s*([^%)]*)%s*%)+")
if t then
-- remove quotes
I = string.gsub(I, "\"", "")
T = string.gsub(T, "\"", "")
-- get type list
local types = split_c_tokens(I, ",")
-- remove TEMPLATE_BIND line
local bs = string.gsub(b, "^{%s*TOLUA_TEMPLATE_BIND[^\n]*\n", "{\n")
-- replace
for i =1 , types.n do
local Tl = split(T, " ")
local Il = split_c_tokens(types[i], " ")
local bI = bs
local pI = {}
for j = 1,Tl.n do
Tl[j] = findtype(Tl[j]) or Tl[j]
bI = string.gsub(bI, "([^_%w])"..Tl[j].."([^_%w])", "%1"..Il[j].."%2")
if p then
for i=1,table.getn(p) do
pI[i] = string.gsub(p[i], "([^_%w]?)"..Tl[j].."([^_%w]?)", "%1"..Il[j].."%2")
end
end
end
--local append = "<"..string.gsub(types[i], "%s+", ",")..">"
local append = "<"..concat(Il, 1, table.getn(Il), ",")..">"
append = string.gsub(append, "%s*,%s*", ",")
append = string.gsub(append, ">>", "> >")
for i=1,table.getn(pI) do
--pI[i] = string.gsub(pI[i], ">>", "> >")
pI[i] = resolve_template_types(pI[i])
end
bI = string.gsub(bI, ">>", "> >")
Class(n..append, pI, bI)
end
return
end
local mbase
if p then
mbase = table.remove(p, 1)
if not p[1] then p = nil end
end
mbase = mbase and resolve_template_types(mbase)
local c
local oname = string.gsub(n, "@.*$", "")
oname = getnamespace(classContainer.curr)..oname
if _global_classes[oname] then
c = _global_classes[oname]
if mbase and ((not c.base) or c.base == "") then
c.base = mbase
end
else
c = _Class(_Container{name=n, base=mbase, extra_bases=p})
local ft = getnamespace(c.parent)..c.original_name
append_global_type(ft, c)
end
push(c)
c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
pop()
end

View File

@@ -0,0 +1,79 @@
-- mark up comments and strings
STR1 = "\001"
STR2 = "\002"
STR3 = "\003"
STR4 = "\004"
REM = "\005"
ANY = "([\001-\005])"
ESC1 = "\006"
ESC2 = "\007"
MASK = { -- the substitution order is important
{ESC1, "\\'"},
{ESC2, '\\"'},
{STR1, "'"},
{STR2, '"'},
{STR3, "%[%["},
{STR4, "%]%]"},
{REM , "%-%-"},
}
function mask (s)
for i = 1,getn(MASK) do
s = gsub(s,MASK[i][2],MASK[i][1])
end
return s
end
function unmask (s)
for i = 1,getn(MASK) do
s = gsub(s,MASK[i][1],MASK[i][2])
end
return s
end
function clean (s)
-- check for compilation error
local code = "return function ()\n" .. s .. "\n end"
if not dostring(code) then
return nil
end
if flags['C'] then
return s
end
local S = "" -- saved string
s = mask(s)
-- remove blanks and comments
while 1 do
local b,e,d = strfind(s,ANY)
if b then
S = S..strsub(s,1,b-1)
s = strsub(s,b+1)
if d==STR1 or d==STR2 then
e = strfind(s,d)
S = S ..d..strsub(s,1,e)
s = strsub(s,e+1)
elseif d==STR3 then
e = strfind(s,STR4)
S = S..d..strsub(s,1,e)
s = strsub(s,e+1)
elseif d==REM then
s = gsub(s,"[^\n]*(\n?)","%1",1)
end
else
S = S..s
break
end
end
-- eliminate unecessary spaces
S = gsub(S,"[ \t]+"," ")
S = gsub(S,"[ \t]*\n[ \t]*","\n")
S = gsub(S,"\n+","\n")
S = unmask(S)
return S
end

View File

@@ -0,0 +1,96 @@
-- tolua: code class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1999
-- $Id: code.lua 1141 2006-05-18 23:58:45Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- global
code_n = 1
-- Code class
-- Represents Lua code to be compiled and included
-- in the initialization function.
-- The following fields are stored:
-- text = text code
classCode = {
text = '',
}
classCode.__index = classCode
setmetatable(classCode,classFeature)
-- register code
function classCode:register (pre)
pre = pre or ''
-- clean Lua code
local s = clean(self.text)
if not s then
--print(self.text)
error("parser error in embedded code")
end
-- get first line
local _, _, first_line=string.find(self.text, "^([^\n\r]*)")
if string.find(first_line, "^%s*%-%-") then
if string.find(first_line, "^%-%-##") then
first_line = string.gsub(first_line, "^%-%-##", "")
if flags['C'] then
s = string.gsub(s, "^%-%-##[^\n\r]*\n", "")
end
end
else
first_line = ""
end
-- convert to C
output('\n'..pre..'{ /* begin embedded lua code */\n')
output(pre..' int top = lua_gettop(tolua_S);')
output(pre..' static unsigned char B[] = {\n ')
local t={n=0}
local b = gsub(s,'(.)',function (c)
local e = ''
t.n=t.n+1 if t.n==15 then t.n=0 e='\n'..pre..' ' end
return format('%3u,%s',strbyte(c),e)
end
)
output(b..strbyte(" "))
output('\n'..pre..' };\n')
if first_line and first_line ~= "" then
output(pre..' tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: '..first_line..'");')
else
output(pre..' tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua: embedded Lua code '..code_n..'");')
end
output(pre..' lua_settop(tolua_S, top);')
output(pre..'} /* end of embedded lua code */\n\n')
code_n = code_n +1
end
-- Print method
function classCode:print (ident,close)
print(ident.."Code{")
print(ident.." text = [["..self.text.."]],")
print(ident.."}"..close)
end
-- Internal constructor
function _Code (t)
setmetatable(t,classCode)
append(t)
return t
end
-- Constructor
-- Expects a string representing the code text
function Code (l)
return _Code {
text = l
}
end

View File

@@ -0,0 +1,53 @@
if string.find(_VERSION, "5%.0") then
return
end
-- "loadfile"
local function pp_dofile(path)
local loaded = false
local getfile = function()
if loaded then
return
else
local file,err = io.open(path)
if not file then
error("error loading file "..path..": "..err)
end
local ret = file:read("*a")
file:close()
ret = string.gsub(ret, "%.%.%.%s*%)", "...) local arg = {n=select('#', ...), ...};")
loaded = true
return ret
end
end
local f = load(getfile, path)
return f()
end
old_dofile = dofile
dofile = pp_dofile
-- string.gsub
--[[
local ogsub = string.gsub
local function compgsub(a,b,c,d)
if type(c) == "function" then
local oc = c
c = function (...) return oc(...) or '' end
end
return ogsub(a,b,c,d)
end
string.repl = ogsub
--]]
--string.gsub = compgsub

View File

@@ -0,0 +1,193 @@
-------------------------------------------------------------------
-- Real globals
-- _ALERT
-- _ERRORMESSAGE
-- _VERSION
-- _G
-- assert
-- error
-- metatable
-- next
-- print
-- require
-- tonumber
-- tostring
-- type
-- unpack
-------------------------------------------------------------------
-- collectgarbage
-- gcinfo
-- globals
-- call -> protect(f, err)
-- loadfile
-- loadstring
-- rawget
-- rawset
-- getargs = Main.getargs ??
rawtype = type
function do_ (f, err)
if not f then print(err); return end
local a,b = pcall(f)
if not a then print(b); return nil
else return b or true
end
end
function dostring(s) return do_(loadstring(s)) end
-- function dofile(s) return do_(loadfile(s)) end
-------------------------------------------------------------------
-- Table library
local tab = table
foreach = tab.foreach
foreachi = tab.foreachi
getn = tab.getn
tinsert = tab.insert
tremove = tab.remove
sort = tab.sort
-------------------------------------------------------------------
-- Debug library
local dbg = debug
getinfo = dbg.getinfo
getlocal = dbg.getlocal
setcallhook = function () error"`setcallhook' is deprecated" end
setlinehook = function () error"`setlinehook' is deprecated" end
setlocal = dbg.setlocal
-------------------------------------------------------------------
-- math library
local math = math
abs = math.abs
acos = function (x) return math.deg(math.acos(x)) end
asin = function (x) return math.deg(math.asin(x)) end
atan = function (x) return math.deg(math.atan(x)) end
atan2 = function (x,y) return math.deg(math.atan2(x,y)) end
ceil = math.ceil
cos = function (x) return math.cos(math.rad(x)) end
deg = math.deg
exp = math.exp
floor = math.floor
frexp = math.frexp
ldexp = math.ldexp
log = math.log
log10 = math.log10
max = math.max
min = math.min
mod = math.mod
PI = math.pi
--??? pow = math.pow
rad = math.rad
random = math.random
randomseed = math.randomseed
sin = function (x) return math.sin(math.rad(x)) end
sqrt = math.sqrt
tan = function (x) return math.tan(math.rad(x)) end
-------------------------------------------------------------------
-- string library
local str = string
strbyte = str.byte
strchar = str.char
strfind = str.find
format = str.format
gsub = str.gsub
strlen = str.len
strlower = str.lower
strrep = str.rep
strsub = str.sub
strupper = str.upper
-------------------------------------------------------------------
-- os library
clock = os.clock
date = os.date
difftime = os.difftime
execute = os.execute --?
exit = os.exit
getenv = os.getenv
remove = os.remove
rename = os.rename
setlocale = os.setlocale
time = os.time
tmpname = os.tmpname
-------------------------------------------------------------------
-- compatibility only
getglobal = function (n) return _G[n] end
setglobal = function (n,v) _G[n] = v end
-------------------------------------------------------------------
local io, tab = io, table
-- IO library (files)
_STDIN = io.stdin
_STDERR = io.stderr
_STDOUT = io.stdout
_INPUT = io.stdin
_OUTPUT = io.stdout
seek = io.stdin.seek -- sick ;-)
tmpfile = io.tmpfile
closefile = io.close
openfile = io.open
function flush (f)
if f then f:flush()
else _OUTPUT:flush()
end
end
function readfrom (name)
if name == nil then
local f, err, cod = io.close(_INPUT)
_INPUT = io.stdin
return f, err, cod
else
local f, err, cod = io.open(name, "r")
_INPUT = f or _INPUT
return f, err, cod
end
end
function writeto (name)
if name == nil then
local f, err, cod = io.close(_OUTPUT)
_OUTPUT = io.stdout
return f, err, cod
else
local f, err, cod = io.open(name, "w")
_OUTPUT = f or _OUTPUT
return f, err, cod
end
end
function appendto (name)
local f, err, cod = io.open(name, "a")
_OUTPUT = f or _OUTPUT
return f, err, cod
end
function read (...)
local f = _INPUT
if rawtype(arg[1]) == 'userdata' then
f = tab.remove(arg, 1)
end
return f:read(unpack(arg))
end
function write (...)
local f = _OUTPUT
if rawtype(arg[1]) == 'userdata' then
f = tab.remove(arg, 1)
end
return f:write(unpack(arg))
end

View File

@@ -0,0 +1,771 @@
-- tolua: container abstract class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: container.lua 1141 2006-05-18 23:58:45Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- table to store namespaced typedefs/enums in global scope
global_typedefs = {}
global_enums = {}
-- Container class
-- Represents a container of features to be bound
-- to lua.
classContainer =
{
curr = nil,
}
classContainer.__index = classContainer
setmetatable(classContainer,classFeature)
-- output tags
function classContainer:decltype ()
push(self)
local i=1
while self[i] do
self[i]:decltype()
i = i+1
end
pop()
end
-- write support code
function classContainer:supcode ()
if not self:check_public_access() then
return
end
push(self)
local i=1
while self[i] do
if self[i]:check_public_access() then
self[i]:supcode()
end
i = i+1
end
pop()
end
function classContainer:hasvar ()
local i=1
while self[i] do
if self[i]:isvariable() then
return 1
end
i = i+1
end
return 0
end
-- Internal container constructor
function _Container (self)
setmetatable(self,classContainer)
self.n = 0
self.typedefs = {tolua_n=0}
self.usertypes = {}
self.enums = {tolua_n=0}
self.lnames = {}
return self
end
-- push container
function push (t)
t.prox = classContainer.curr
classContainer.curr = t
end
-- pop container
function pop ()
--print("name",classContainer.curr.name)
--foreach(classContainer.curr.usertypes,print)
--print("______________")
classContainer.curr = classContainer.curr.prox
end
-- get current namespace
function getcurrnamespace ()
return getnamespace(classContainer.curr)
end
-- append to current container
function append (t)
return classContainer.curr:append(t)
end
-- append typedef to current container
function appendtypedef (t)
return classContainer.curr:appendtypedef(t)
end
-- append usertype to current container
function appendusertype (t)
return classContainer.curr:appendusertype(t)
end
-- append enum to current container
function appendenum (t)
return classContainer.curr:appendenum(t)
end
-- substitute typedef
function applytypedef (mod,type)
return classContainer.curr:applytypedef(mod,type)
end
-- check if is type
function findtype (type)
local t = classContainer.curr:findtype(type)
return t
end
-- check if is typedef
function istypedef (type)
return classContainer.curr:istypedef(type)
end
-- get fulltype (with namespace)
function fulltype (t)
local curr = classContainer.curr
while curr do
if curr then
if curr.typedefs and curr.typedefs[t] then
return curr.typedefs[t]
elseif curr.usertypes and curr.usertypes[t] then
return curr.usertypes[t]
end
end
curr = curr.prox
end
return t
end
-- checks if it requires collection
function classContainer:requirecollection (t)
push(self)
local i=1
local r = false
while self[i] do
r = self[i]:requirecollection(t) or r
i = i+1
end
pop()
return r
end
-- get namesapce
function getnamespace (curr)
local namespace = ''
while curr do
if curr and
( curr.classtype == 'class' or curr.classtype == 'namespace')
then
namespace = (curr.original_name or curr.name) .. '::' .. namespace
--namespace = curr.name .. '::' .. namespace
end
curr = curr.prox
end
return namespace
end
-- get namespace (only namespace)
function getonlynamespace ()
local curr = classContainer.curr
local namespace = ''
while curr do
if curr.classtype == 'class' then
return namespace
elseif curr.classtype == 'namespace' then
namespace = curr.name .. '::' .. namespace
end
curr = curr.prox
end
return namespace
end
-- check if is enum
function isenum (type)
return classContainer.curr:isenum(type)
end
-- append feature to container
function classContainer:append (t)
self.n = self.n + 1
self[self.n] = t
t.parent = self
end
-- append typedef
function classContainer:appendtypedef (t)
local namespace = getnamespace(classContainer.curr)
self.typedefs.tolua_n = self.typedefs.tolua_n + 1
self.typedefs[self.typedefs.tolua_n] = t
self.typedefs[t.utype] = namespace .. t.utype
global_typedefs[namespace..t.utype] = t
t.ftype = findtype(t.type) or t.type
--print("appending typedef "..t.utype.." as "..namespace..t.utype.." with ftype "..t.ftype)
append_global_type(namespace..t.utype)
if t.ftype and isenum(t.ftype) then
global_enums[namespace..t.utype] = true
end
end
-- append usertype: return full type
function classContainer:appendusertype (t)
local container
if t == (self.original_name or self.name) then
container = self.prox
else
container = self
end
local ft = getnamespace(container) .. t
container.usertypes[t] = ft
_usertype[ft] = ft
return ft
end
-- append enum
function classContainer:appendenum (t)
local namespace = getnamespace(classContainer.curr)
self.enums.tolua_n = self.enums.tolua_n + 1
self.enums[self.enums.tolua_n] = t
global_enums[namespace..t.name] = t
end
-- determine lua function name overload
function classContainer:overload (lname)
if not self.lnames[lname] then
self.lnames[lname] = 0
else
self.lnames[lname] = self.lnames[lname] + 1
end
return format("%02d",self.lnames[lname])
end
-- applies typedef: returns the 'the facto' modifier and type
function classContainer:applytypedef (mod,type)
if global_typedefs[type] then
--print("found typedef "..global_typedefs[type].type)
local mod1, type1 = global_typedefs[type].mod, global_typedefs[type].ftype
local mod2, type2 = applytypedef(mod.." "..mod1, type1)
--return mod2 .. ' ' .. mod1, type2
return mod2, type2
end
do return mod,type end
end
-- check if it is a typedef
function classContainer:istypedef (type)
local env = self
while env do
if env.typedefs then
local i=1
while env.typedefs[i] do
if env.typedefs[i].utype == type then
return type
end
i = i+1
end
end
env = env.parent
end
return nil
end
function find_enum_var(var)
if tonumber(var) then return var end
local c = classContainer.curr
while c do
local ns = getnamespace(c)
for k,v in pairs(_global_enums) do
if match_type(var, v, ns) then
return v
end
end
if c.base and c.base ~= '' then
c = _global_classes[c:findtype(c.base)]
else
c = nil
end
end
return var
end
-- check if is a registered type: return full type or nil
function classContainer:findtype (t)
t = string.gsub(t, "=.*", "")
if _basic[t] then
return t
end
local _,_,em = string.find(t, "([&%*])%s*$")
t = string.gsub(t, "%s*([&%*])%s*$", "")
p = self
while p and type(p)=='table' do
local st = getnamespace(p)
for i=_global_types.n,1,-1 do -- in reverse order
if match_type(t, _global_types[i], st) then
return _global_types[i]..(em or "")
end
end
if p.base and p.base ~= '' and p.base ~= t then
--print("type is "..t..", p is "..p.base.." self.type is "..self.type.." self.name is "..self.name)
p = _global_classes[p:findtype(p.base)]
else
p = nil
end
end
return nil
end
function append_global_type(t, class)
_global_types.n = _global_types.n +1
_global_types[_global_types.n] = t
_global_types_hash[t] = 1
if class then append_class_type(t, class) end
end
function append_class_type(t,class)
if _global_classes[t] then
class.flags = _global_classes[t].flags
class.lnames = _global_classes[t].lnames
if _global_classes[t].base and (_global_classes[t].base ~= '') then
class.base = _global_classes[t].base or class.base
end
end
_global_classes[t] = class
class.flags = class.flags or {}
end
function match_type(childtype, regtype, st)
--print("findtype "..childtype..", "..regtype..", "..st)
local b,e = string.find(regtype, childtype, -string.len(childtype), true)
if b then
if e == string.len(regtype) and
(b == 1 or (string.sub(regtype, b-1, b-1) == ':' and
string.sub(regtype, 1, b-1) == string.sub(st, 1, b-1))) then
return true
end
end
return false
end
function findtype_on_childs(self, t)
local tchild
if self.classtype == 'class' or self.classtype == 'namespace' then
for k,v in ipairs(self) do
if v.classtype == 'class' or v.classtype == 'namespace' then
if v.typedefs and v.typedefs[t] then
return v.typedefs[t]
elseif v.usertypes and v.usertypes[t] then
return v.usertypes[t]
end
tchild = findtype_on_childs(v, t)
if tchild then return tchild end
end
end
end
return nil
end
function classContainer:isenum (type)
if global_enums[type] then
return type
else
return false
end
local basetype = gsub(type,"^.*::","")
local env = self
while env do
if env.enums then
local i=1
while env.enums[i] do
if env.enums[i].name == basetype then
return true
end
i = i+1
end
end
env = env.parent
end
return false
end
methodisvirtual = false -- a global
-- parse chunk
function classContainer:doparse (s)
--print ("parse "..s)
-- try the parser hook
do
local sub = parser_hook(s)
if sub then
return sub
end
end
-- try the null statement
do
local b,e,code = string.find(s, "^%s*;")
if b then
return strsub(s,e+1)
end
end
-- try empty verbatim line
do
local b,e,code = string.find(s, "^%s*$\n")
if b then
return strsub(s,e+1)
end
end
-- try Lua code
do
local b,e,code = strfind(s,"^%s*(%b\1\2)")
if b then
Code(strsub(code,2,-2))
return strsub(s,e+1)
end
end
-- try C code
do
local b,e,code = strfind(s,"^%s*(%b\3\4)")
if b then
code = '{'..strsub(code,2,-2)..'\n}\n'
Verbatim(code,'r') -- verbatim code for 'r'egister fragment
return strsub(s,e+1)
end
end
-- try C code for preamble section
do
local b,e,code = string.find(s, "^%s*(%b\5\6)")
if b then
code = string.sub(code, 2, -2).."\n"
Verbatim(code, '')
return string.sub(s, e+1)
end
end
-- try default_property directive
do
local b,e,ptype = strfind(s, "^%s*TOLUA_PROPERTY_TYPE%s*%(+%s*([^%)%s]*)%s*%)+%s*;?")
if b then
if not ptype or ptype == "" then
ptype = "default"
end
self:set_property_type(ptype)
return strsub(s, e+1)
end
end
-- try protected_destructor directive
do
local b,e = string.find(s, "^%s*TOLUA_PROTECTED_DESTRUCTOR%s*;?")
if b then
if self.set_protected_destructor then
self:set_protected_destructor(true)
end
return strsub(s, e+1)
end
end
-- try 'extern' keyword
do
local b,e = string.find(s, "^%s*extern%s+")
if b then
-- do nothing
return strsub(s, e+1)
end
end
-- try 'virtual' keyworkd
do
local b,e = string.find(s, "^%s*virtual%s+")
if b then
methodisvirtual = true
return strsub(s, e+1)
end
end
-- try labels (public, private, etc)
do
local b,e = string.find(s, "^%s*%w*%s*:[^:]")
if b then
return strsub(s, e) -- preserve the [^:]
end
end
-- try module
do
local b,e,name,body = strfind(s,"^%s*module%s%s*([_%w][_%w]*)%s*(%b{})%s*")
if b then
_curr_code = strsub(s,b,e)
Module(name,body)
return strsub(s,e+1)
end
end
-- try namesapce
do
local b,e,name,body = strfind(s,"^%s*namespace%s%s*([_%w][_%w]*)%s*(%b{})%s*;?")
if b then
_curr_code = strsub(s,b,e)
Namespace(name,body)
return strsub(s,e+1)
end
end
-- try define
do
local b,e,name = strfind(s,"^%s*#define%s%s*([^%s]*)[^\n]*\n%s*")
if b then
_curr_code = strsub(s,b,e)
Define(name)
return strsub(s,e+1)
end
end
-- try enumerates
do
local b,e,name,body,varname = strfind(s,"^%s*enum%s+(%S*)%s*(%b{})%s*([^%s;]*)%s*;?%s*")
if b then
--error("#Sorry, declaration of enums and variables on the same statement is not supported.\nDeclare your variable separately (example: '"..name.." "..varname..";')")
_curr_code = strsub(s,b,e)
Enumerate(name,body,varname)
return strsub(s,e+1)
end
end
-- do
-- local b,e,name,body = strfind(s,"^%s*enum%s+(%S*)%s*(%b{})%s*;?%s*")
-- if b then
-- _curr_code = strsub(s,b,e)
-- Enumerate(name,body)
-- return strsub(s,e+1)
-- end
-- end
do
local b,e,body,name = strfind(s,"^%s*typedef%s+enum[^{]*(%b{})%s*([%w_][^%s]*)%s*;%s*")
if b then
_curr_code = strsub(s,b,e)
Enumerate(name,body)
return strsub(s,e+1)
end
end
-- try operator
do
local b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&:<>,]-%s+operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
if not b then
-- try inline
b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&:<>,]-%s+operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)[%s\n]*%b{}%s*;?%s*")
end
if not b then
-- try cast operator
b,e,decl,kind,arg,const = strfind(s, "^%s*(operator)%s+([%w_:%d<>%*%&%s]+)%s*(%b())%s*(c?o?n?s?t?)");
if b then
local _,ie = string.find(s, "^%s*%b{}", e+1)
if ie then
e = ie
end
end
end
if b then
_curr_code = strsub(s,b,e)
Operator(decl,kind,arg,const)
return strsub(s,e+1)
end
end
-- try function
do
--local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w])%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
local b,e,decl,arg,const,virt = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)%s*(=?%s*0?)%s*;%s*")
if not b then
-- try function with template
b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w]%b<>)%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
end
if not b then
-- try a single letter function name
b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
end
if b then
if virt and string.find(virt, "[=0]") then
if self.flags then
self.flags.pure_virtual = true
end
end
_curr_code = strsub(s,b,e)
Function(decl,arg,const)
return strsub(s,e+1)
end
end
-- try inline function
do
local b,e,decl,arg,const = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)[^;{]*%b{}%s*;?%s*")
--local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w>])%s*(%b())%s*(c?o?n?s?t?)[^;]*%b{}%s*;?%s*")
if not b then
-- try a single letter function name
b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?).-%b{}%s*;?%s*")
end
if b then
_curr_code = strsub(s,b,e)
Function(decl,arg,const)
return strsub(s,e+1)
end
end
-- try class
do
local b,e,name,base,body
base = '' body = ''
b,e,name = strfind(s,"^%s*class%s*([_%w][_%w@]*)%s*;") -- dummy class
if not b then
b,e,name = strfind(s,"^%s*struct%s*([_%w][_%w@]*)%s*;") -- dummy struct
if not b then
b,e,name,base,body = strfind(s,"^%s*class%s*([_%w][_%w@]*)%s*(.-)%s*(%b{})%s*;%s*")
if not b then
b,e,name,base,body = strfind(s,"^%s*struct%s*([_%w][_%w@]*)%s*(.-)%s*(%b{})%s*;%s*")
if not b then
b,e,name,base,body = strfind(s,"^%s*union%s*([_%w][_%w@]*)%s*(.-)%s*(%b{})%s*;%s*")
if not b then
base = ''
b,e,body,name = strfind(s,"^%s*typedef%s%s*struct%s%s*[_%w]*%s*(%b{})%s*([_%w][_%w@]*)%s*;%s*")
end
end
end
end
end
if b then
if base ~= '' then
base = string.gsub(base, "^%s*:%s*", "")
base = string.gsub(base, "%s*public%s*", "")
base = split(base, ",")
--local b,e
--b,e,base = strfind(base,".-([_%w][_%w<>,:]*)$")
else
base = {}
end
_curr_code = strsub(s,b,e)
Class(name,base,body)
return strsub(s,e+1)
end
end
-- try typedef
do
local b,e,types = strfind(s,"^%s*typedef%s%s*(.-)%s*;%s*")
if b then
_curr_code = strsub(s,b,e)
Typedef(types)
return strsub(s,e+1)
end
end
-- try variable
do
local b,e,decl = strfind(s,"^%s*([_%w][_@%s%w%d%*&:<>,]*[_%w%d])%s*;%s*")
if b then
_curr_code = strsub(s,b,e)
local list = split_c_tokens(decl, ",")
Variable(list[1])
if list.n > 1 then
local _,_,type = strfind(list[1], "(.-)%s+([^%s]*)$");
local i =2;
while list[i] do
Variable(type.." "..list[i])
i=i+1
end
end
--Variable(decl)
return strsub(s,e+1)
end
end
-- try string
do
local b,e,decl = strfind(s,"^%s*([_%w]?[_%s%w%d]-char%s+[_@%w%d]*%s*%[%s*%S+%s*%])%s*;%s*")
if b then
_curr_code = strsub(s,b,e)
Variable(decl)
return strsub(s,e+1)
end
end
-- try array
do
local b,e,decl = strfind(s,"^%s*([_%w][][_@%s%w%d%*&:]*[]_%w%d])%s*;%s*")
if b then
_curr_code = strsub(s,b,e)
Array(decl)
return strsub(s,e+1)
end
end
-- no matching
if gsub(s,"%s%s*","") ~= "" then
_curr_code = s
error("#parse error")
else
return ""
end
end
function classContainer:parse (s)
self.curr_member_access = nil
while s ~= '' do
s = self:doparse(s)
methodisvirtual = false
end
end
-- property types
function get_property_type()
return classContainer.curr:get_property_type()
end
function classContainer:set_property_type(ptype)
ptype = string.gsub(ptype, "^%s*", "")
ptype = string.gsub(ptype, "%s*$", "")
self.property_type = ptype
end
function classContainer:get_property_type()
return self.property_type or (self.parent and self.parent:get_property_type()) or "default"
end

View File

@@ -0,0 +1,45 @@
function extract_code(fn,s)
local code = ""
if fn then
code = '\n$#include "'..fn..'"\n'
end
s= "\n" .. s .. "\n" -- add blank lines as sentinels
local _,e,c,t = strfind(s, "\n([^\n]-)SCRIPT_([%w_]*)[^\n]*\n")
while e do
t = strlower(t)
if t == "bind_begin" then
_,e,c = strfind(s,"(.-)\n[^\n]*SCRIPT_BIND_END[^\n]*\n",e)
if not e then
tolua_error("Unbalanced 'SCRIPT_BIND_BEGIN' directive in header file")
end
end
if t == "bind_class" or t == "bind_block" then
local b
_,e,c,b = string.find(s, "([^{]-)(%b{})", e)
c = c..'{\n'..extract_code(nil, b)..'\n};\n'
end
code = code .. c .. "\n"
_,e,c,t = strfind(s, "\n([^\n]-)SCRIPT_([%w_]*)[^\n]*\n",e)
end
return code
end
function preprocess_hook(p)
end
function preparse_hook(p)
end
function include_file_hook(p, filename)
do return end
--print("FILENAME is "..filename)
p.code = string.gsub(p.code, "\n%s*SigC::Signal", "\n\ttolua_readonly SigC::Signal")
p.code = string.gsub(p.code, "#ifdef __cplusplus\nextern \"C\" {\n#endif", "")
p.code = string.gsub(p.code, "#ifdef __cplusplus\n};?\n#endif", "")
p.code = string.gsub(p.code, "DECLSPEC", "")
p.code = string.gsub(p.code, "SDLCALL", "")
p.code = string.gsub(p.code, "DLLINTERFACE", "")
p.code = string.gsub(p.code, "#define[^\n]*_[hH]_?%s*\n", "\n")
--print("code is "..p.code)
end

View File

@@ -0,0 +1,21 @@
-- extract code with tolua_hide, and also
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)
if not e then
tolua_error("Unbalanced 'tolua_begin' directive in header file")
end
end
c = c.."\n"
c = string.gsub(c, "\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[hH][iI][Dd][eE][^\n]*\n", "\n");
c = string.gsub(c, "#define[^%(\n]*%(.-\n", "\n")
code = code .. c
_,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n",e)
end
return code
end

View File

@@ -0,0 +1,571 @@
-- tolua: declaration class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: declaration.lua 1141 2006-05-18 23:58:45Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Declaration class
-- Represents variable, function, or argument declaration.
-- Stores the following fields:
-- mod = type modifiers
-- type = type
-- ptr = "*" or "&", if representing a pointer or a reference
-- name = name
-- dim = dimension, if a vector
-- def = default value, if any (only for arguments)
-- ret = "*" or "&", if value is to be returned (only for arguments)
classDeclaration = {
mod = '',
type = '',
ptr = '',
name = '',
dim = '',
ret = '',
def = ''
}
classDeclaration.__index = classDeclaration
setmetatable(classDeclaration,classFeature)
-- Create an unique variable name
function create_varname ()
if not _varnumber then _varnumber = 0 end
_varnumber = _varnumber + 1
return "tolua_var_".._varnumber
end
-- Check declaration name
-- It also identifies default values
function classDeclaration:checkname ()
if strsub(self.name,1,1) == '[' and not findtype(self.type) then
self.name = self.type..self.name
local m = split(self.mod,'%s%s*')
self.type = m[m.n]
self.mod = concat(m,1,m.n-1)
end
local t = split(self.name,'=')
if t.n==2 then
self.name = t[1]
self.def = find_enum_var(t[t.n])
end
local b,e,d = strfind(self.name,"%[(.-)%]")
if b then
self.name = strsub(self.name,1,b-1)
self.dim = find_enum_var(d)
end
if self.type ~= '' and self.type ~= 'void' and self.name == '' then
self.name = create_varname()
elseif self.kind=='var' then
if self.type=='' and self.name~='' then
self.type = self.type..self.name
self.name = create_varname()
elseif findtype(self.name) then
if self.type=='' then self.type = self.name
else self.type = self.type..' '..self.name end
self.name = create_varname()
end
end
-- adjust type of string
if self.type == 'char' and self.dim ~= '' then
self.type = 'char*'
end
if self.kind and self.kind == 'var' then
self.name = string.gsub(self.name, ":.*$", "") -- ???
end
end
-- Check declaration type
-- Substitutes typedef's.
function classDeclaration:checktype ()
-- check if there is a pointer to basic type
local basic = isbasic(self.type)
if self.kind == 'func' and basic=='number' and string.find(self.ptr, "%*") then
self.type = '_userdata'
self.ptr = ""
end
if basic and self.ptr~='' then
self.ret = self.ptr
self.ptr = nil
if isbasic(self.type) == 'number' then
self.return_userdata = true
end
end
-- check if there is array to be returned
if self.dim~='' and self.ret~='' then
error('#invalid parameter: cannot return an array of values')
end
-- restore 'void*' and 'string*'
if self.type == '_userdata' then self.type = 'void*'
elseif self.type == '_cstring' then self.type = 'char*'
elseif self.type == '_lstate' then self.type = 'lua_State*'
end
-- resolve types inside the templates
if self.type then
self.type = resolve_template_types(self.type)
end
--
-- -- if returning value, automatically set default value
-- if self.ret ~= '' and self.def == '' then
-- self.def = '0'
-- end
--
end
function resolve_template_types(type)
if isbasic(type) then
return type
end
local b,_,m = string.find(type, "(%b<>)")
if b then
m = split_c_tokens(string.sub(m, 2, -2), ",")
for i=1, table.getn(m) do
m[i] = string.gsub(m[i],"%s*([%*&])", "%1")
m[i] = findtype(m[i]) or m[i]
m[i] = resolve_template_types(m[i])
end
local b,i
type,b,i = break_template(type)
local template_part = "<"..string.gsub(concat(m, 1, m.n), " ", ",")..">"
type = rebuild_template(type, b, template_part)
type = string.gsub(type, ">>", "> >")
end
return type
end
function break_template(s)
local b,e,timpl = string.find(s, "(%b<>)")
if timpl then
s = string.gsub(s, "%b<>", "")
return s, b, timpl
else
return s, 0, nil
end
end
function rebuild_template(s, b, timpl)
if b == 0 then
return s
end
return string.sub(s, 1, b-1)..timpl..string.sub(s, b, -1)
end
-- Print method
function classDeclaration:print (ident,close)
print(ident.."Declaration{")
print(ident.." mod = '"..self.mod.."',")
print(ident.." type = '"..self.type.."',")
print(ident.." ptr = '"..self.ptr.."',")
print(ident.." name = '"..self.name.."',")
print(ident.." dim = '"..self.dim.."',")
print(ident.." def = '"..self.def.."',")
print(ident.." ret = '"..self.ret.."',")
print(ident.."}"..close)
end
-- check if array of values are returned to Lua
function classDeclaration:requirecollection (t)
if self.mod ~= 'const' and
self.dim and self.dim ~= '' and
not isbasic(self.type) and
self.ptr == '' then
local type = gsub(self.type,"%s*const%s+","")
t[type] = "tolua_collect_" .. clean_template(type)
return true
end
return false
end
-- declare tag
function classDeclaration:decltype ()
self.type = typevar(self.type)
if strfind(self.mod,'const') then
self.type = 'const '..self.type
self.mod = gsub(self.mod,'const%s*','')
end
end
-- output type checking
function classDeclaration:outchecktype (narg)
local def
local t = isbasic(self.type)
if self.def~='' then
def = 1
else
def = 0
end
if self.dim ~= '' then
--if t=='string' then
-- return 'tolua_isstringarray(tolua_S,'..narg..','..def..',&tolua_err)'
--else
return 'tolua_istable(tolua_S,'..narg..',0,&tolua_err)'
--end
elseif t then
return 'tolua_is'..t..'(tolua_S,'..narg..','..def..',&tolua_err)'
else
return 'tolua_isusertype(tolua_S,'..narg..',"'..self.type..'",'..def..',&tolua_err)'
end
end
function classDeclaration:builddeclaration (narg, cplusplus)
local array = self.dim ~= '' and tonumber(self.dim)==nil
local line = ""
local ptr = ''
local mod
local type = self.type
if self.dim ~= '' then
type = gsub(self.type,'const%s+','') -- eliminates const modifier for arrays
end
if self.ptr~='' and not isbasic(type) then ptr = '*' end
line = concatparam(line," ",self.mod,type,ptr)
if array then
line = concatparam(line,'*')
end
line = concatparam(line,self.name)
if self.dim ~= '' then
if tonumber(self.dim)~=nil then
line = concatparam(line,'[',self.dim,'];')
else
if cplusplus then
line = concatparam(line,' = new',type,ptr,'['..self.dim..'];')
else
line = concatparam(line,' = (',type,ptr,'*)',
'malloc((',self.dim,')*sizeof(',type,ptr,'));')
end
end
else
local t = isbasic(type)
line = concatparam(line,' = ')
if t == 'state' then
line = concatparam(line, 'tolua_S;')
else
--print("t is "..tostring(t)..", ptr is "..tostring(self.ptr))
if t == 'number' and string.find(self.ptr, "%*") then
t = 'userdata'
end
if not t and ptr=='' then line = concatparam(line,'*') end
line = concatparam(line,'((',self.mod,type)
if not t then
line = concatparam(line,'*')
end
line = concatparam(line,') ')
if isenum(type) then
line = concatparam(line,'(int) ')
end
local def = 0
if self.def ~= '' then
def = self.def
if (ptr == '' or self.ptr == '&') and not t then
def = "(void*)&(const "..type..")"..def
end
end
if t then
if t == "boolean" then
line = concatparam(line,'(tolua_toboolean','(tolua_S,',narg,',',def,')!=0));')
else
line = concatparam(line,'tolua_to'..t,'(tolua_S,',narg,',',def,'));')
end
else
line = concatparam(line,'tolua_tousertype(tolua_S,',narg,',',def,'));')
end
end
end
return line
end
-- Declare variable
function classDeclaration:declare (narg)
if self.dim ~= '' and tonumber(self.dim)==nil then
output('#ifdef __cplusplus\n')
output(self:builddeclaration(narg,true))
output('#else\n')
output(self:builddeclaration(narg,false))
output('#endif\n')
else
output(self:builddeclaration(narg,false))
end
end
-- Get parameter value
function classDeclaration:getarray (narg)
if self.dim ~= '' then
local type = gsub(self.type,'const ','')
output(' {')
output('#ifndef TOLUA_RELEASE\n')
local def; if self.def~='' then def=1 else def=0 end
local t = isbasic(type)
if (t) then
output(' if (!tolua_is'..t..'array(tolua_S,',narg,',',self.dim,',',def,',&tolua_err))')
else
output(' if (!tolua_isusertypearray(tolua_S,',narg,',"',type,'",',self.dim,',',def,',&tolua_err))')
end
output(' goto tolua_lerror;')
output(' else\n')
output('#endif\n')
output(' {')
output(' int i;')
output(' for(i=0; i<'..self.dim..';i++)')
local t = isbasic(type)
local ptr = ''
if self.ptr~='' then ptr = '*' end
output(' ',self.name..'[i] = ')
if not t and ptr=='' then output('*') end
output('((',type)
if not t then
output('*')
end
output(') ')
local def = 0
if self.def ~= '' then def = self.def end
if t then
output('tolua_tofield'..t..'(tolua_S,',narg,',i+1,',def,'));')
else
output('tolua_tofieldusertype(tolua_S,',narg,',i+1,',def,'));')
end
output(' }')
output(' }')
end
end
-- Get parameter value
function classDeclaration:setarray (narg)
if not strfind(self.type,'const%s+') and self.dim ~= '' then
local type = gsub(self.type,'const ','')
output(' {')
output(' int i;')
output(' for(i=0; i<'..self.dim..';i++)')
local t,ct = isbasic(type)
if t then
output(' tolua_pushfield'..t..'(tolua_S,',narg,',i+1,(',ct,')',self.name,'[i]);')
else
if self.ptr == '' then
output(' {')
output('#ifdef __cplusplus\n')
output(' void* tolua_obj = new',type,'(',self.name,'[i]);')
output(' tolua_pushfieldusertype_and_takeownership(tolua_S,',narg,',i+1,tolua_obj,"',type,'");')
output('#else\n')
output(' void* tolua_obj = tolua_copy(tolua_S,(void*)&',self.name,'[i],sizeof(',type,'));')
output(' tolua_pushfieldusertype(tolua_S,',narg,',i+1,tolua_obj,"',type,'");')
output('#endif\n')
output(' }')
else
output(' tolua_pushfieldusertype(tolua_S,',narg,',i+1,(void*)',self.name,'[i],"',type,'");')
end
end
output(' }')
end
end
-- Free dynamically allocated array
function classDeclaration:freearray ()
if self.dim ~= '' and tonumber(self.dim)==nil then
output('#ifdef __cplusplus\n')
output(' delete []',self.name,';')
output('#else\n')
output(' free(',self.name,');')
output('#endif\n')
end
end
-- Pass parameter
function classDeclaration:passpar ()
if self.ptr=='&' and not isbasic(self.type) then
output('*'..self.name)
elseif self.ret=='*' then
output('&'..self.name)
else
output(self.name)
end
end
-- Return parameter value
function classDeclaration:retvalue ()
if self.ret ~= '' then
local t,ct = isbasic(self.type)
if t and t~='' then
output(' tolua_push'..t..'(tolua_S,(',ct,')'..self.name..');')
else
output(' tolua_pushusertype(tolua_S,(void*)'..self.name..',"',self.type,'");')
end
return 1
end
return 0
end
-- Internal constructor
function _Declaration (t)
setmetatable(t,classDeclaration)
t:buildnames()
t:checkname()
t:checktype()
local ft = findtype(t.type) or t.type
if not isenum(ft) then
t.mod, t.type = applytypedef(t.mod, ft)
end
if t.kind=="var" and (string.find(t.mod, "tolua_property%s") or string.find(t.mod, "tolua_property$")) then
t.mod = string.gsub(t.mod, "tolua_property", "tolua_property__"..get_property_type())
end
return t
end
-- Constructor
-- Expects the string declaration.
-- The kind of declaration can be "var" or "func".
function Declaration (s,kind,is_parameter)
-- eliminate spaces if default value is provided
s = gsub(s,"%s*=%s*","=")
s = gsub(s, "%s*<", "<")
local defb,tmpdef
defb,_,tmpdef = string.find(s, "(=.*)$")
if defb then
s = string.gsub(s, "=.*$", "")
else
tmpdef = ''
end
if kind == "var" then
-- check the form: void
if s == '' or s == 'void' then
return _Declaration{type = 'void', kind = kind, is_parameter = is_parameter}
end
end
-- check the form: mod type*& name
local t = split_c_tokens(s,'%*%s*&')
if t.n == 2 then
if kind == 'func' then
error("#invalid function return type: "..s)
end
--local m = split(t[1],'%s%s*')
local m = split_c_tokens(t[1],'%s+')
return _Declaration{
name = t[2]..tmpdef,
ptr = '*',
ret = '&',
--type = rebuild_template(m[m.n], tb, timpl),
type = m[m.n],
mod = concat(m,1,m.n-1),
is_parameter = is_parameter,
kind = kind
}
end
-- check the form: mod type** name
t = split_c_tokens(s,'%*%s*%*')
if t.n == 2 then
if kind == 'func' then
error("#invalid function return type: "..s)
end
--local m = split(t[1],'%s%s*')
local m = split_c_tokens(t[1],'%s+')
return _Declaration{
name = t[2]..tmpdef,
ptr = '*',
ret = '*',
--type = rebuild_template(m[m.n], tb, timpl),
type = m[m.n],
mod = concat(m,1,m.n-1),
is_parameter = is_parameter,
kind = kind
}
end
-- check the form: mod type& name
t = split_c_tokens(s,'&')
if t.n == 2 then
--local m = split(t[1],'%s%s*')
local m = split_c_tokens(t[1],'%s+')
return _Declaration{
name = t[2]..tmpdef,
ptr = '&',
--type = rebuild_template(m[m.n], tb, timpl),
type = m[m.n],
mod = concat(m,1,m.n-1),
is_parameter = is_parameter,
kind = kind
}
end
-- check the form: mod type* name
local s1 = gsub(s,"(%b\[\])",function (n) return gsub(n,'%*','\1') end)
t = split_c_tokens(s1,'%*')
if t.n == 2 then
t[2] = gsub(t[2],'\1','%*') -- restore * in dimension expression
--local m = split(t[1],'%s%s*')
local m = split_c_tokens(t[1],'%s+')
return _Declaration{
name = t[2]..tmpdef,
ptr = '*',
type = m[m.n],
--type = rebuild_template(m[m.n], tb, timpl),
mod = concat(m,1,m.n-1) ,
is_parameter = is_parameter,
kind = kind
}
end
if kind == 'var' then
-- check the form: mod type name
--t = split(s,'%s%s*')
t = split_c_tokens(s,'%s+')
local v
if findtype(t[t.n]) then v = create_varname() else v = t[t.n]; t.n = t.n-1 end
return _Declaration{
name = v..tmpdef,
--type = rebuild_template(t[t.n], tb, timpl),
type = t[t.n],
mod = concat(t,1,t.n-1),
is_parameter = is_parameter,
kind = kind
}
else -- kind == "func"
-- check the form: mod type name
--t = split(s,'%s%s*')
t = split_c_tokens(s,'%s+')
local v = t[t.n] -- last word is the function name
local tp,md
if t.n>1 then
tp = t[t.n-1]
md = concat(t,1,t.n-2)
end
--if tp then tp = rebuild_template(tp, tb, timpl) end
return _Declaration{
name = v,
type = tp,
mod = md,
is_parameter = is_parameter,
kind = kind
}
end
end

View File

@@ -0,0 +1,63 @@
-- tolua: define class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: define.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Define class
-- Represents a numeric const definition
-- The following filds are stored:
-- name = constant name
classDefine = {
name = '',
}
classDefine.__index = classDefine
setmetatable(classDefine,classFeature)
-- register define
function classDefine:register (pre)
if not self:check_public_access() then
return
end
pre = pre or ''
output(pre..'tolua_constant(tolua_S,(char*)"'..self.lname..'",'..self.name..');')
end
-- Print method
function classDefine:print (ident,close)
print(ident.."Define{")
print(ident.." name = '"..self.name.."',")
print(ident.." lname = '"..self.lname.."',")
print(ident.."}"..close)
end
-- Internal constructor
function _Define (t)
setmetatable(t,classDefine)
t:buildnames()
if t.name == '' then
error("#invalid define")
end
append(t)
return t
end
-- Constructor
-- Expects a string representing the constant name
function Define (n)
return _Define{
name = n
}
end

View File

@@ -0,0 +1,95 @@
-- Generate binding code
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- Last update: Apr 2003
-- $Id: doit.lua 1141 2006-05-18 23:58:45Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
function parse_extra()
for k,v in ipairs(_extra_parameters or {}) do
local b,e,name,value = string.find(v, "^([^=])=(.*)$")
if b then
_extra_parameters[name] = value
else
_extra_parameters[v] = true
end
end
end
function doit ()
-- define package name, if not provided
if not flags.n then
if flags.f then
flags.n = gsub(flags.f,"%..*$","")
_,_,flags.n = string.find(flags.n, "([^/\\]*)$")
else
error("#no package name nor input file provided")
end
end
-- parse table with extra paramters
parse_extra()
-- do this after setting the package name
if flags['L'] then
dofile(flags['L'])
end
-- add cppstring
if not flags['S'] then
_basic['string'] = 'cppstring'
_basic['std::string'] = 'cppstring'
_basic_ctype.cppstring = 'const char*'
end
-- proccess package
local p = Package(flags.n,flags.f)
if flags.p then
return -- only parse
end
if flags.o then
local st,msg = writeto(flags.o)
if not st then
error('#'..msg)
end
end
p:decltype()
if flags.P then
p:print()
else
p:preamble()
p:supcode()
p:register()
push(p)
post_output_hook(p)
pop()
end
if flags.o then
writeto()
end
-- write header file
if not flags.P then
if flags.H then
local st,msg = writeto(flags.H)
if not st then
error('#'..msg)
end
p:header()
writeto()
end
end
end

View File

@@ -0,0 +1,95 @@
-- tolua: enumerate class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: enumerate.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Enumerate class
-- Represents enumeration
-- The following fields are stored:
-- {i} = list of constant names
classEnumerate = {
}
classEnumerate.__index = classEnumerate
setmetatable(classEnumerate,classFeature)
-- register enumeration
function classEnumerate:register (pre)
pre = pre or ''
local nspace = getnamespace(classContainer.curr)
local i=1
while self[i] do
output(pre..'tolua_constant(tolua_S,(char*)"'..self.lnames[i]..'",'..nspace..self[i]..');')
i = i+1
end
end
-- Print method
function classEnumerate:print (ident,close)
print(ident.."Enumerate{")
print(ident.." name = "..self.name)
local i=1
while self[i] do
print(ident.." '"..self[i].."'("..self.lnames[i].."),")
i = i+1
end
print(ident.."}"..close)
end
-- Internal constructor
function _Enumerate (t,varname)
setmetatable(t,classEnumerate)
append(t)
appendenum(t)
if varname and varname ~= "" then
if t.name ~= "" then
Variable(t.name.." "..varname)
else
local ns = getcurrnamespace()
warning("Variable "..ns..varname.." of type <anonymous enum> is declared as read-only")
Variable("tolua_readonly int "..varname)
end
end
return t
end
-- Constructor
-- Expects a string representing the enumerate body
function Enumerate (n,b,varname)
b = string.gsub(b, ",[%s\n]*}", "\n}") -- eliminate last ','
local t = split(strsub(b,2,-2),',') -- eliminate braces
local i = 1
local e = {n=0}
while t[i] do
local tt = split(t[i],'=') -- discard initial value
e.n = e.n + 1
e[e.n] = tt[1]
i = i+1
end
-- set lua names
i = 1
e.lnames = {}
local ns = getcurrnamespace()
while e[i] do
local t = split(e[i],'@')
e[i] = t[1]
if not t[2] then
t[2] = applyrenaming(t[1])
end
e.lnames[i] = t[2] or t[1]
_global_enums[ ns..e[i] ] = (ns..e[i])
i = i+1
end
e.name = n
if n ~= "" then
Typedef("int "..n)
end
return _Enumerate(e, varname)
end

View File

@@ -0,0 +1,128 @@
-- tolua: abstract feature class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: feature.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Feature class
-- Represents the base class of all mapped feature.
classFeature = {
}
classFeature.__index = classFeature
-- write support code
function classFeature:supcode ()
end
-- output tag
function classFeature:decltype ()
end
-- register feature
function classFeature:register (pre)
end
-- translate verbatim
function classFeature:preamble ()
end
-- check if it is a variable
function classFeature:isvariable ()
return false
end
-- check if it requires collection
function classFeature:requirecollection (t)
return false
end
-- build names
function classFeature:buildnames ()
if self.name and self.name~='' then
local n = split(self.name,'@')
self.name = n[1]
if not n[2] then
n[2] = applyrenaming(n[1])
end
self.lname = n[2] or gsub(n[1],"%[.-%]","")
self.original_name = self.name
self.lname = clean_template(self.lname)
end
if not self.is_parameter then
self.name = getonlynamespace() .. self.name
end
local parent = classContainer.curr
if parent then
self.access = parent.curr_member_access
else
end
end
function classFeature:check_public_access()
if self.access and self.access ~= 0 then
return false
end
local parent = classContainer.curr
while parent do
if parent.access and parent.access ~= 0 then
return false
end
parent = parent.prox
end
return true
end
function clean_template(t)
return string.gsub(t, "[<>:, %*]", "_")
end
-- check if feature is inside a container definition
-- it returns the container class name or nil.
function classFeature:incontainer (which)
if self.parent then
local parent = self.parent
while parent do
if parent.classtype == which then
return parent.name
end
parent = parent.parent
end
end
return nil
end
function classFeature:inclass ()
return self:incontainer('class')
end
function classFeature:inmodule ()
return self:incontainer('module')
end
function classFeature:innamespace ()
return self:incontainer('namespace')
end
-- return C binding function name based on name
-- the client specifies a prefix
function classFeature:cfuncname (n)
if self.parent then
n = self.parent:cfuncname(n)
end
n = string.gsub(n..'_'.. (self.lname or self.name), "[<>:, \.%*&]", "_")
return n
end

View File

@@ -0,0 +1,745 @@
-- tolua: function class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: function.lua 997 2006-02-23 19:12:50Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- CEGUILua mod
-- exception handling
-- patch from Tov
-- modded by Lindquist
exceptionDefs = exceptionDefs or {}
exceptionDefs["std::exception"] = {}
exceptionDefs["std::exception"]["var"] = "&e"
exceptionDefs["std::exception"]["c_str"] = "e.what()"
exceptionDefs["any"] = {}
exceptionDefs["any"]["var"] = ""
exceptionDefs["any"]["c_str"] = '"Unknown"'
exceptionMessageBufferSize = 512
function outputExceptionError(f,e,errBuf)
-- if the exception is not "..." then use the "c_str" info the get a real exception message
local messageC_str = true
if e.name == "any" then
messageC_str = false
end
-- make a default e.ret if empty
if not e.ret or e.ret == "" then
e.ret = "nil,message"
end
-- create a default exceptionDef if we dont have one
if not exceptionDefs[e.name] then
exceptionDefs[e.name] = {}
exceptionDefs[e.name].var = "&e"
exceptionDefs[e.name].c_str = '"Unknown"'
end
-- print catch header
local nameToEcho = e.name
if nameToEcho == "any" then
nameToEcho = "..."
end
output("catch(",nameToEcho,exceptionDefs[e.name].var,")\n{\n")
-- if just a nil
if e.ret == "nil" then
output("return 0;\n")
-- if error should be raised
elseif string.find(e.ret,"error") then
if messageC_str then
output("snprintf(errorBuffer,"..exceptionMessageBufferSize..",\"Exception of type '"..e.name.."' was thrown by function '"..f.."'\\nMessage: %s\","..exceptionDefs[e.name].c_str..");\n")
else
output("snprintf(errorBuffer,"..exceptionMessageBufferSize..",\"Unknown exception thrown by function '"..f.."'\");\n")
end
output("errorDoIt = true;\n")
-- else go through the returns
else
-- buffer for message
if string.find(e.ret,"message") and messageC_str and errBuf == false then
output("char errorBuffer["..exceptionMessageBufferSize.."];\n")
end
local numrets = 0
local retpat = "(%w+),?"
local i,j,retval = string.find(e.ret,retpat)
while i do
local code = ""
-- NIL
if retval == "nil" then
code = "tolua_pushnil(tolua_S);\n"
-- MESSAGE
elseif retval == "message" then
if messageC_str then
code = "snprintf(errorBuffer,"..exceptionMessageBufferSize..",\"Exception of type '"..e.name.."' was thrown by function '"..f.."'\\nMessage: %s\","..exceptionDefs[e.name].c_str..");\ntolua_pushstring(tolua_S,errorBuffer);\n"
else
code = "tolua_pushstring(tolua_S,\"Unknown exception thrown by function '"..f.."'\");\n"
end
-- TRUE
elseif retval == "true" then
code = "tolua_pushboolean(tolua_S, 1);\n"
-- FALSE
elseif retval == "false" then
code = "tolua_pushboolean(tolua_S, 0);\n"
end
-- print code for this return value
if code ~= "" then
output(code)
numrets = numrets + 1
end
-- next return value
i,j,retval = string.find(e.ret,retpat,j+1)
end
output("return ",numrets,";\n")
end
-- print catch footer
output("}\n")
end
function outputExceptionCatchBlocks(func,throws,err)
for i=1,table.getn(throws) do
outputExceptionError(func, throws[i], err)
end
-- if an error should be raised, we do it here
if err then
output("if (errorDoIt) {\n")
output("luaL_error(tolua_S,errorBuffer);\n")
output("}\n")
end
end
-- Function class
-- Represents a function or a class method.
-- The following fields are stored:
-- mod = type modifiers
-- type = type
-- ptr = "*" or "&", if representing a pointer or a reference
-- name = name
-- lname = lua name
-- args = list of argument declarations
-- const = if it is a method receiving a const "this".
classFunction = {
mod = '',
type = '',
ptr = '',
name = '',
args = {n=0},
const = '',
}
classFunction.__index = classFunction
setmetatable(classFunction,classFeature)
-- declare tags
function classFunction:decltype ()
self.type = typevar(self.type)
if strfind(self.mod,'const') then
self.type = 'const '..self.type
self.mod = gsub(self.mod,'const','')
end
local i=1
while self.args[i] do
self.args[i]:decltype()
i = i+1
end
end
-- Write binding function
-- Outputs C/C++ binding function.
function classFunction:supcode (local_constructor)
local overload = strsub(self.cname,-2,-1) - 1 -- indicate overloaded func
local nret = 0 -- number of returned values
local class = self:inclass()
local _,_,static = strfind(self.mod,'^%s*(static)')
if class then
if self.name == 'new' and self.parent.flags.pure_virtual then
-- no constructor for classes with pure virtual methods
return
end
if local_constructor then
output("/* method: new_local of class ",class," */")
else
output("/* method:",self.name," of class ",class," */")
end
else
output("/* function:",self.name," */")
end
if local_constructor then
output("#ifndef TOLUA_DISABLE_"..self.cname.."_local")
output("\nstatic int",self.cname.."_local","(lua_State* tolua_S)")
else
output("#ifndef TOLUA_DISABLE_"..self.cname)
output("\nstatic int",self.cname,"(lua_State* tolua_S)")
end
--
-- modify tolua++, miros 2011-03-04
-- suport function raw export directly
--
if #self.args == 1 and self.type == "int" and self.args[1].type == "lua_State*" then
output("{\n\treturn "..self.name.."(tolua_S);\n}\n#endif //#ifndef TOLUA_DISABLE\n\n")
return
end
--
-- end modify
--
output("{")
-- check types
if overload < 0 then
output('#ifndef TOLUA_RELEASE\n')
end
output(' tolua_Error tolua_err;')
output(' if (\n')
-- check self
local narg
if class then narg=2 else narg=1 end
if class then
local func = 'tolua_isusertype'
local type = self.parent.type
if self.name=='new' or static~=nil then
func = 'tolua_isusertable'
type = self.parent.type
end
if self.const ~= '' then
type = "const "..type
end
output(' !'..func..'(tolua_S,1,"'..type..'",0,&tolua_err) ||\n')
end
-- check args
if self.args[1].type ~= 'void' then
local i=1
while self.args[i] do
local btype = isbasic(self.args[i].type)
if btype ~= 'value' and btype ~= 'state' then
output(' !'..self.args[i]:outchecktype(narg)..' ||\n')
end
if btype ~= 'state' then
narg = narg+1
end
i = i+1
end
end
-- check end of list
output(' !tolua_isnoobj(tolua_S,'..narg..',&tolua_err)\n )')
output(' goto tolua_lerror;')
output(' else\n')
if overload < 0 then
output('#endif\n')
end
output(' {')
-- declare self, if the case
local narg
if class then narg=2 else narg=1 end
if class and self.name~='new' and static==nil then
output(' ',self.const,self.parent.type,'*','self = ')
output('(',self.const,self.parent.type,'*) ')
output('tolua_tousertype(tolua_S,1,0);')
elseif static then
_,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
end
-- declare parameters
if self.args[1].type ~= 'void' then
local i=1
while self.args[i] do
self.args[i]:declare(narg)
if isbasic(self.args[i].type) ~= "state" then
narg = narg+1
end
i = i+1
end
end
-- check self
if class and self.name~='new' and static==nil then
output('#ifndef TOLUA_RELEASE\n')
output(' if (!self) tolua_error(tolua_S,(char*)"invalid \'self\' in function \''..self.name..'\'",NULL);');
output('#endif\n')
end
-- get array element values
if class then narg=2 else narg=1 end
if self.args[1].type ~= 'void' then
local i=1
while self.args[i] do
self.args[i]:getarray(narg)
narg = narg+1
i = i+1
end
end
--------------------------------------------------
-- CEGUILua mod
-- init exception handling
local throws = false
do
local pattern = "tolua_throws|.*|"
local i,j = string.find(self.mod, pattern)
if i then
throws = {}
table.setn(throws,0)
local excepts = string.sub(self.mod, i+12,j)
local epattern = "|.-|"
local i,j = string.find(excepts, epattern)
while i do
local e = string.sub(excepts,i+1,j-1)
local _,_,name,rest = string.find(e, "([%w:_]+),?(.*)")
table.insert(throws,{name=name, ret=rest})
i,j = string.find(excepts, epattern, j)
end
self.mod = string.gsub(self.mod, pattern, "")
end
end
local exRaiseError = false
--------------------------------------------------
local out = string.find(self.mod, "tolua_outside")
---------------
-- CEGUILua mod
-- remove "tolua_outside" from self.mod
if out then
self.mod = string.gsub(self.mod, "tolua_outside", "")
end
-- call function
if class and self.name=='delete' then
output(' delete self;')
elseif class and self.name == 'operator&[]' then
if flags['1'] then -- for compatibility with tolua5 ?
output(' self->operator[](',self.args[1].name,'-1) = ',self.args[2].name,';')
else
output(' self->operator[](',self.args[1].name,') = ',self.args[2].name,';')
end
else
-- CEGUILua mod begin- throws
if throws then
for i=1,table.getn(throws) do
if string.find(throws[i].ret, "error") then
output("char errorBuffer["..exceptionMessageBufferSize.."];\n")
output("bool errorDoIt = false;\n")
exRaiseError = true
break
end
end
output("try\n")
end
-- CEGUILua mod end - throws
output(' {')
if self.type ~= '' and self.type ~= 'void' then
output(' ',self.mod,self.type,self.ptr,'tolua_ret = ')
output('(',self.mod,self.type,self.ptr,') ')
else
output(' ')
end
if class and self.name=='new' then
output('new',self.type,'(')
elseif class and static then
if out then
output(self.name,'(')
else
output(class..'::'..self.name,'(')
end
elseif class then
if out then
output(self.name,'(')
else
if self.cast_operator then
output('static_cast<',self.mod,self.type,self.ptr,'>(*self')
else
output('self->'..self.name,'(')
end
end
else
output(self.name,'(')
end
if out and not static then
output('self')
if self.args[1] and self.args[1].name ~= '' then
output(',')
end
end
-- write parameters
local i=1
while self.args[i] do
self.args[i]:passpar()
i = i+1
if self.args[i] then
output(',')
end
end
if class and self.name == 'operator[]' and flags['1'] then
output('-1);')
else
output(');')
end
-- return values
if self.type ~= '' and self.type ~= 'void' then
nret = nret + 1
local t,ct = isbasic(self.type)
if t then
if self.cast_operator and _basic_raw_push[t] then
output(' ',_basic_raw_push[t],'(tolua_S,(',ct,')tolua_ret);')
elseif self.type == 'String' then
output(' tolua_push'..t..'(tolua_S,(',ct,')tolua_ret.to_char());')
else
output(' tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
end
else
t = self.type
new_t = string.gsub(t, "const%s+", "")
if self.ptr == '' then
output(' {')
output('#ifdef __cplusplus\n')
output(' void* tolua_obj = new',new_t,'(tolua_ret);')
output(' tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
output('#else\n')
output(' void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
output(' tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
output('#endif\n')
output(' }')
elseif self.ptr == '&' then
output(' tolua_pushusertype(tolua_S,(void*)&tolua_ret,"',t,'");')
else
if local_constructor then
output(' tolua_pushusertype_and_takeownership(tolua_S,(void *)tolua_ret,"',t,'");')
else
output(' tolua_pushusertype(tolua_S,(void*)tolua_ret,"',t,'");')
end
end
end
end
local i=1
while self.args[i] do
nret = nret + self.args[i]:retvalue()
i = i+1
end
output(' }')
------------------------------------------
-- CEGUILua mod
-- finish exception handling
-- catch
if throws then
outputExceptionCatchBlocks(self.name, throws, exRaiseError)
end
------------------------------------------
-- set array element values
if class then narg=2 else narg=1 end
if self.args[1].type ~= 'void' then
local i=1
while self.args[i] do
self.args[i]:setarray(narg)
narg = narg+1
i = i+1
end
end
-- free dynamically allocated array
if self.args[1].type ~= 'void' then
local i=1
while self.args[i] do
self.args[i]:freearray()
i = i+1
end
end
end
output(' }')
output(' return '..nret..';')
-- call overloaded function or generate error
if overload < 0 then
output('#ifndef TOLUA_RELEASE\n')
output('tolua_lerror:\n')
output(' tolua_error(tolua_S,(char*)"#ferror in function \''..self.lname..'\'.",&tolua_err);')
output(' return 0;')
output('#endif\n')
else
local _local = ""
if local_constructor then
_local = "_local"
end
output('tolua_lerror:\n')
output(' return '..strsub(self.cname,1,-3)..format("%02d",overload).._local..'(tolua_S);')
end
output('}')
output('#endif //#ifndef TOLUA_DISABLE\n')
output('\n')
-- recursive call to write local constructor
if class and self.name=='new' and not local_constructor then
self:supcode(1)
end
end
-- register function
function classFunction:register (pre)
if not self:check_public_access() then
return
end
if self.name == 'new' and self.parent.flags.pure_virtual then
-- no constructor for classes with pure virtual methods
return
end
output(pre..'tolua_function(tolua_S,(char*)"'..self.lname..'",'..self.cname..');')
if self.name == 'new' then
output(pre..'tolua_function(tolua_S,(char*)"new_local",'..self.cname..'_local);')
output(pre..'tolua_function(tolua_S,".call",'..self.cname..'_local);')
--output(' tolua_set_call_event(tolua_S,'..self.cname..'_local, "'..self.parent.type..'");')
end
end
-- Print method
function classFunction:print (ident,close)
print(ident.."Function{")
print(ident.." mod = '"..self.mod.."',")
print(ident.." type = '"..self.type.."',")
print(ident.." ptr = '"..self.ptr.."',")
print(ident.." name = '"..self.name.."',")
print(ident.." lname = '"..self.lname.."',")
print(ident.." const = '"..self.const.."',")
print(ident.." cname = '"..self.cname.."',")
print(ident.." lname = '"..self.lname.."',")
print(ident.." args = {")
local i=1
while self.args[i] do
self.args[i]:print(ident.." ",",")
i = i+1
end
print(ident.." }")
print(ident.."}"..close)
end
-- check if it returns an object by value
function classFunction:requirecollection (t)
local r = false
if self.type ~= '' and not isbasic(self.type) and self.ptr=='' then
local type = gsub(self.type,"%s*const%s+","")
t[type] = "tolua_collect_" .. clean_template(type)
r = true
end
local i=1
while self.args[i] do
r = self.args[i]:requirecollection(t) or r
i = i+1
end
return r
end
-- determine lua function name overload
function classFunction:overload ()
return self.parent:overload(self.lname)
end
function param_object(par) -- returns true if the parameter has an object as its default value
if not string.find(par, '=') then return false end -- it has no default value
local _,_,def = string.find(par, "=(.*)$")
if string.find(par, "|") then -- a list of flags
return true
end
if string.find(par, "%*") then -- it's a pointer with a default value
if string.find(par, '=%s*new') then -- it's a pointer with an instance as default parameter.. is that valid?
return true
end
return false -- default value is 'NULL' or something
end
if string.find(par, "[%(&]") then
return true
end -- default value is a constructor call (most likely for a const reference)
--if string.find(par, "&") then
-- if string.find(def, ":") or string.find(def, "^%s*new%s+") then
-- -- it's a reference with default to something like Class::member, or 'new Class'
-- return true
-- end
--end
return false -- ?
end
function strip_last_arg(all_args, last_arg) -- strips the default value from the last argument
local _,_,s_arg = string.find(last_arg, "^([^=]+)")
last_arg = string.gsub(last_arg, "([%%%(%)])", "%%%1");
all_args = string.gsub(all_args, "%s*,%s*"..last_arg.."%s*%)%s*$", ")")
return all_args, s_arg
end
-- Internal constructor
function _Function (t)
setmetatable(t,classFunction)
if t.const ~= 'const' and t.const ~= '' then
error("#invalid 'const' specification")
end
append(t)
if t:inclass() then
--print ('t.name is '..t.name..', parent.name is '..t.parent.name)
if string.gsub(t.name, "%b<>", "") == string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
t.name = 'new'
t.lname = 'new'
t.parent._new = true
t.type = t.parent.name
t.ptr = '*'
elseif string.gsub(t.name, "%b<>", "") == '~'..string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
t.name = 'delete'
t.lname = 'delete'
t.parent._delete = true
end
end
t.cname = t:cfuncname("tolua")..t:overload(t)
return t
end
-- Constructor
-- Expects three strings: one representing the function declaration,
-- another representing the argument list, and the third representing
-- the "const" or empty string.
function Function (d,a,c)
--local t = split(strsub(a,2,-2),',') -- eliminate braces
--local t = split_params(strsub(a,2,-2))
if not flags['W'] and string.find(a, "%.%.%.%s*%)") then
warning("Functions with variable arguments (`...') are not supported. Ignoring "..d..a..c)
return nil
end
local i=1
local l = {n=0}
a = string.gsub(a, "%s*([%(%)])%s*", "%1")
local t,strip,last = strip_pars(strsub(a,2,-2));
if strip then
--local ns = string.sub(strsub(a,1,-2), 1, -(string.len(last)+1))
local ns = join(t, ",", 1, last-1)
ns = "("..string.gsub(ns, "%s*,%s*$", "")..')'
--ns = strip_defaults(ns)
Function(d, ns, c)
for i=1,last do
t[i] = string.gsub(t[i], "=.*$", "")
end
end
while t[i] do
l.n = l.n+1
l[l.n] = Declaration(t[i],'var',true)
i = i+1
end
local f = Declaration(d,'func')
f.args = l
f.const = c
return _Function(f)
end
function join(t, sep, first, last)
first = first or 1
last = last or table.getn(t)
local lsep = ""
local ret = ""
local loop = false
for i = first,last do
ret = ret..lsep..t[i]
lsep = sep
loop = true
end
if not loop then
return ""
end
return ret
end
function strip_pars(s)
local t = split_c_tokens(s, ',')
local strip = false
local last
for i=t.n,1,-1 do
if not strip and param_object(t[i]) then
last = i
strip = true
end
--if strip then
-- t[i] = string.gsub(t[i], "=.*$", "")
--end
end
return t,strip,last
end
function strip_defaults(s)
s = string.gsub(s, "^%(", "")
s = string.gsub(s, "%)$", "")
local t = split_c_tokens(s, ",")
local sep, ret = "",""
for i=1,t.n do
t[i] = string.gsub(t[i], "=.*$", "")
ret = ret..sep..t[i]
sep = ","
end
return "("..ret..")"
end

View File

@@ -0,0 +1,68 @@
-- tolua: module class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: module.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Module class
-- Represents module.
-- The following fields are stored:
-- {i} = list of objects in the module.
classModule = {
classtype = 'module'
}
classModule.__index = classModule
setmetatable(classModule,classContainer)
-- register module
function classModule:register (pre)
pre = pre or ''
push(self)
output(pre..'tolua_module(tolua_S,(char*)"'..self.name..'",',self:hasvar(),');')
output(pre..'tolua_beginmodule(tolua_S,(char*)"'..self.name..'");')
local i=1
while self[i] do
self[i]:register(pre..' ')
i = i+1
end
output(pre..'tolua_endmodule(tolua_S);')
pop()
end
-- Print method
function classModule:print (ident,close)
print(ident.."Module{")
print(ident.." name = '"..self.name.."';")
local i=1
while self[i] do
self[i]:print(ident.." ",",")
i = i+1
end
print(ident.."}"..close)
end
-- Internal constructor
function _Module (t)
setmetatable(t,classModule)
append(t)
return t
end
-- Constructor
-- Expects two string representing the module name and body.
function Module (n,b)
local t = _Module(_Container{name=n})
push(t)
t:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
pop()
return t
end

View File

@@ -0,0 +1,52 @@
-- tolua: namespace class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 2003
-- $Id: namespace.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Namespace class
-- Represents a namesapce definition.
-- Stores the following fields:
-- name = class name
-- {i} = list of members
classNamespace = {
classtype = 'namespace',
name = '',
}
classNamespace.__index = classNamespace
setmetatable(classNamespace,classModule)
-- Print method
function classNamespace:print (ident,close)
print(ident.."Namespace{")
print(ident.." name = '"..self.name.."',")
local i=1
while self[i] do
self[i]:print(ident.." ",",")
i = i+1
end
print(ident.."}"..close)
end
-- Internal constructor
function _Namespace (t)
setmetatable(t,classNamespace)
append(t)
return t
end
-- Constructor
-- Expects the name and the body of the namespace.
function Namespace (n,b)
local c = _Namespace(_Container{name=n})
push(c)
c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
pop()
end

View File

@@ -0,0 +1,214 @@
-- tolua: operator class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: operator.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Operator class
-- Represents an operator function or a class operator method.
-- It stores the same fields as functions do plus:
-- kind = set of character representing the operator (as it appers in C++ code)
classOperator = {
kind = '',
}
classOperator.__index = classOperator
setmetatable(classOperator,classFunction)
-- table to transform operator kind into the appropriate tag method name
_TM = {['+'] = 'add',
['-'] = 'sub',
['*'] = 'mul',
['/'] = 'div',
['<'] = 'lt',
['<='] = 'le',
['=='] = 'eq',
['[]'] = 'geti',
['&[]'] = 'seti',
--['->'] = 'flechita',
}
-- Print method
function classOperator:print (ident,close)
print(ident.."Operator{")
print(ident.." kind = '"..self.kind.."',")
print(ident.." mod = '"..self.mod.."',")
print(ident.." type = '"..self.type.."',")
print(ident.." ptr = '"..self.ptr.."',")
print(ident.." name = '"..self.name.."',")
print(ident.." const = '"..self.const.."',")
print(ident.." cname = '"..self.cname.."',")
print(ident.." lname = '"..self.lname.."',")
print(ident.." args = {")
local i=1
while self.args[i] do
self.args[i]:print(ident.." ",",")
i = i+1
end
print(ident.." }")
print(ident.."}"..close)
end
function classOperator:supcode_tmp()
if not _TM[self.kind] then
return classFunction.supcode(self)
end
-- no overload, no parameters, always inclass
output("/* method:",self.name," of class ",self:inclass()," */")
output("#ifndef TOLUA_DISABLE_"..self.cname)
output("\nstatic int",self.cname,"(lua_State* tolua_S)")
if overload < 0 then
output('#ifndef TOLUA_RELEASE\n')
end
output(' tolua_Error tolua_err;')
output(' if (\n')
-- check self
output(' !'..'tolua_isusertype(tolua_S,1,"'..self.parent.type..'",0,&tolua_err) ||\n')
output(' !tolua_isnoobj(tolua_S,2,&tolua_err)\n )')
output(' goto tolua_lerror;')
output(' else\n')
output('#endif\n') -- tolua_release
output(' {')
-- declare self
output(' ',self.const,self.parent.type,'*','self = ')
output('(',self.const,self.parent.type,'*) ')
output('tolua_tousertype(tolua_S,1,0);')
-- check self
output('#ifndef TOLUA_RELEASE\n')
output(' if (!self) tolua_error(tolua_S,(char*)"invalid \'self\' in function \''..self.name..'\'",NULL);');
output('#endif\n')
-- cast self
output(' ',self.mod,self.type,self.ptr,'tolua_ret = ')
output('(',self.mod,self.type,self.ptr,')(*self);')
-- return value
local t,ct = isbasic(self.type)
if t then
output(' tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
else
t = self.type
new_t = string.gsub(t, "const%s+", "")
if self.ptr == '' then
output(' {')
output('#ifdef __cplusplus\n')
output(' void* tolua_obj = new',new_t,'(tolua_ret);')
output(' tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
output('#else\n')
output(' void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
output(' tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
output('#endif\n')
output(' }')
elseif self.ptr == '&' then
output(' tolua_pushusertype(tolua_S,(void*)&tolua_ret,"',t,'");')
else
if local_constructor then
output(' tolua_pushusertype_and_takeownership(tolua_S,(void *)tolua_ret,"',t,'");')
else
output(' tolua_pushusertype(tolua_S,(void*)tolua_ret,"',t,'");')
end
end
end
output(' }')
output(' return 1;')
output('#ifndef TOLUA_RELEASE\n')
output('tolua_lerror:\n')
output(' tolua_error(tolua_S,(char*)"#ferror in function \''..self.lname..'\'.",&tolua_err);')
output(' return 0;')
output('#endif\n')
output('}')
output('#endif //#ifndef TOLUA_DISABLE\n')
output('\n')
end
-- Internal constructor
function _Operator (t)
setmetatable(t,classOperator)
if t.const ~= 'const' and t.const ~= '' then
error("#invalid 'const' specification")
end
append(t)
if not t:inclass() then
error("#operator can only be defined as class member")
end
--t.name = t.name .. "_" .. (_TM[t.kind] or t.kind)
t.cname = t:cfuncname("tolua")..t:overload(t)
t.name = "operator" .. t.kind -- set appropriate calling name
return t
end
-- Constructor
function Operator (d,k,a,c)
local op_k = string.gsub(k, "^%s*", "")
op_k = string.gsub(k, "%s*$", "")
--if string.find(k, "^[%w_:%d<>%*%&]+$") then
if d == "operator" and k ~= '' then
d = k.." operator"
elseif not _TM[op_k] then
if flags['W'] then
error("tolua: no support for operator" .. f.kind)
else
warning("No support for operator "..op_k..", ignoring")
return nil
end
end
local ref = ''
local t = split_c_tokens(strsub(a,2,strlen(a)-1),',') -- eliminate braces
local i=1
local l = {n=0}
while t[i] do
l.n = l.n+1
l[l.n] = Declaration(t[i],'var')
i = i+1
end
if k == '[]' then
local _
_, _, ref = strfind(d,'(&)')
d = gsub(d,'&','')
elseif k=='&[]' then
l.n = l.n+1
l[l.n] = Declaration(d,'var')
l[l.n].name = 'tolua_value'
end
local f = Declaration(d,'func')
if k == '[]' and (l[1]==nil or isbasic(l[1].type)~='number') then
error('operator[] can only be defined for numeric index.')
end
f.args = l
f.const = c
f.kind = op_k
f.lname = "."..(_TM[f.kind] or f.kind)
if not _TM[f.kind] then
f.cast_operator = true
end
if f.kind == '[]' and ref=='&' and f.const~='const' then
Operator(d,'&'..k,a,c) -- create correspoding set operator
end
return _Operator(f)
end

View File

@@ -0,0 +1,302 @@
-- tolua: package class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: package.lua 1143 2006-05-19 02:43:42Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Package class
-- Represents the whole package being bound.
-- The following fields are stored:
-- {i} = list of objects in the package.
classPackage = {
classtype = 'package'
}
classPackage.__index = classPackage
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
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#["..getn(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#<"..getn(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#<"..getn(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#"..getn(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..' on '..date()..'.\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')
if not flags.h then
output('/* Exported function */')
output('int tolua_'..self.name..'_open (lua_State* tolua_S);')
--output('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
if self:requirecollection(_collect) then
output('\n')
output('/* function to release collected object via destructor */')
output('#ifdef __cplusplus\n')
for i,v in pairs(_collect) do
output('\nstatic int '..v..' (lua_State* tolua_S)')
output('{')
output(' '..i..'* self = ('..i..'*) tolua_tousertype(tolua_S,1,0);')
output(' delete self;')
output(' return 0;')
output('}')
end
output('#endif\n\n')
end
output('\n')
output('/* function to register type */')
output('static void tolua_reg_types (lua_State* tolua_S)')
output('{')
foreach(_usertype,function(n,v) output(' tolua_usertype(tolua_S,"',v,'");') end)
if flags.t then
output("#ifndef Mtolua_typeid\n#define Mtolua_typeid(L,TI,T)\n#endif\n")
foreach(_usertype,function(n,v) output(' Mtolua_typeid(tolua_S,typeid(',v,'), "',v,'");') end)
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.."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.."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('int tolua_'..self.name..'_open (lua_State* tolua_S);')
output('\n')
end
end
-- Internal constructor
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")
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)
if not e then
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)
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
if fn then
local st, msg = readfrom(flags.f)
if not st then
error('#'..msg)
end
local _; _, _, ext = strfind(fn,".*%.(.*)$")
end
local code = "\n" .. read('*a')
if ext == 'h' or ext == 'hpp' then
code = extract_code(fn,code)
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
local s = read(fp,'*a')
closefile(fp)
if kind == 'c' or kind == 'h' then
return extract_code(fn,s)
elseif kind == 'p' then
return "\n\n" .. 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, 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
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

View File

@@ -0,0 +1,71 @@
-- tolua: typedef class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: typedef.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Typedef class
-- Represents a type synonym.
-- The 'de facto' type replaces the typedef before the
-- remaining code is parsed.
-- The following fields are stored:
-- utype = typedef name
-- type = 'the facto' type
-- mod = modifiers to the 'de facto' type
classTypedef = {
utype = '',
mod = '',
type = ''
}
classTypedef.__index = classTypedef
-- Print method
function classTypedef:print (ident,close)
print(ident.."Typedef{")
print(ident.." utype = '"..self.utype.."',")
print(ident.." mod = '"..self.mod.."',")
print(ident.." type = '"..self.type.."',")
print(ident.."}"..close)
end
-- Return it's not a variable
function classTypedef:isvariable ()
return false
end
-- Internal constructor
function _Typedef (t)
setmetatable(t,classTypedef)
t.type = resolve_template_types(t.type)
appendtypedef(t)
return t
end
-- Constructor
-- Expects one string representing the type definition.
function Typedef (s)
if strfind(string.gsub(s, '%b<>', ''),'[%*&]') then
tolua_error("#invalid typedef: pointers (and references) are not supported")
end
local o = {mod = ''}
if string.find(s, "[<>]") then
_,_,o.type,o.utype = string.find(s, "^%s*([^<>]+%b<>[^%s]*)%s+(.-)$")
else
local t = split(gsub(s,"%s%s*"," ")," ")
o = {
utype = t[t.n],
type = t[t.n-1],
mod = concat(t,1,t.n-2),
}
end
return _Typedef(o)
end

View File

@@ -0,0 +1,295 @@
-- tolua: variable class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: variable.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Variable class
-- Represents a extern variable or a public member of a class.
-- Stores all fields present in a declaration.
classVariable = {
_get = {}, -- mapped get functions
_set = {}, -- mapped set functions
}
classVariable.__index = classVariable
setmetatable(classVariable,classDeclaration)
-- Print method
function classVariable:print (ident,close)
print(ident.."Variable{")
print(ident.." mod = '"..self.mod.."',")
print(ident.." type = '"..self.type.."',")
print(ident.." ptr = '"..self.ptr.."',")
print(ident.." name = '"..self.name.."',")
if self.dim then print(ident.." dim = '"..self.dim.."',") end
print(ident.." def = '"..self.def.."',")
print(ident.." ret = '"..self.ret.."',")
print(ident.."}"..close)
end
-- Generates C function name
function classVariable:cfuncname (prefix)
local parent = ""
local unsigned = ""
local ptr = ""
local p = self:inmodule() or self:innamespace() or self:inclass()
if p then
if self.parent.classtype == 'class' then
parent = "_" .. self.parent.type
else
parent = "_" .. p
end
end
if strfind(self.mod,"(unsigned)") then
unsigned = "_unsigned"
end
if self.ptr == "*" then ptr = "_ptr"
elseif self.ptr == "&" then ptr = "_ref"
end
local name = prefix .. parent .. unsigned .. "_" .. gsub(self.lname or self.name,".*::","") .. ptr
name = clean_template(name)
return name
end
-- check if it is a variable
function classVariable:isvariable ()
return true
end
-- get variable value
function classVariable:getvalue (class,static, prop_get)
local name
if prop_get then
name = prop_get.."()"
else
name = self.name
end
if class and static then
return self.parent.type..'::'..name
elseif class then
return 'self->'..name
else
return name
end
end
-- get variable pointer value
function classVariable:getpointervalue (class,static)
if class and static then
return class..'::p'
elseif class then
return 'self->p'
else
return 'p'
end
end
-- Write binding functions
function classVariable:supcode ()
local class = self:inclass()
local prop_get,prop_set
if string.find(self.mod, 'tolua_property') then
_,_,type = string.find(self.mod, "tolua_property__([^%s]*)")
type = type or "default"
prop_get,prop_set = get_property_methods(type, self.name)
self.mod = string.gsub(self.mod, "tolua_property[^%s]*", "")
end
-- get function ------------------------------------------------
if class then
output("/* get function:",self.name," of class ",class," */")
else
output("/* get function:",self.name," */")
end
self.cgetname = self:cfuncname("tolua_get")
output("#ifndef TOLUA_DISABLE_"..self.cgetname)
output("\nstatic int",self.cgetname,"(lua_State* tolua_S)")
output("{")
-- declare self, if the case
local _,_,static = strfind(self.mod,'^%s*(static)')
if class and static==nil then
output(' ',self.parent.type,'*','self = ')
output('(',self.parent.type,'*) ')
output('tolua_tousertype(tolua_S,1,0);')
elseif static then
_,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
end
-- check self value
if class and static==nil then
output('#ifndef TOLUA_RELEASE\n')
output(' if (!self) tolua_error(tolua_S,(char*)"invalid \'self\' in accessing variable \''..self.name..'\'",NULL);');
output('#endif\n')
end
-- return value
if string.find(self.mod, 'tolua_inherits') then
output('#ifdef __cplusplus\n')
output(' tolua_pushusertype(tolua_S,(void*)static_cast<'..self.type..'*>(self), "',self.type,'");')
output('#else\n')
output(' tolua_pushusertype(tolua_S,(void*)(('..self.type..'*)self), "',self.type,'");')
output('#endif\n')
else
local t,ct = isbasic(self.type)
if t then
output(' tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static,prop_get)..');')
else
t = self.type
if self.ptr == '&' or self.ptr == '' then
output(' tolua_pushusertype(tolua_S,(void*)&'..self:getvalue(class,static,prop_get)..',"',t,'");')
else
output(' tolua_pushusertype(tolua_S,(void*)'..self:getvalue(class,static,prop_get)..',"',t,'");')
end
end
end
output(' return 1;')
output('}')
output('#endif //#ifndef TOLUA_DISABLE\n')
output('\n')
-- set function ------------------------------------------------
if not (strfind(self.type,'const%s+') or string.find(self.mod, 'tolua_readonly') or string.find(self.mod, 'tolua_inherits')) then
if class then
output("/* set function:",self.name," of class ",class," */")
else
output("/* set function:",self.name," */")
end
self.csetname = self:cfuncname("tolua_set")
output("#ifndef TOLUA_DISABLE_"..self.csetname)
output("\nstatic int",self.csetname,"(lua_State* tolua_S)")
output("{")
-- declare self, if the case
if class and static==nil then
output(' ',self.parent.type,'*','self = ')
output('(',self.parent.type,'*) ')
output('tolua_tousertype(tolua_S,1,0);')
-- check self value
end
-- check types
output('#ifndef TOLUA_RELEASE\n')
output(' tolua_Error tolua_err;')
if class and static==nil then
output(' if (!self) tolua_error(tolua_S,(char*)"invalid \'self\' in accessing variable \''..self.name..'\'",NULL);');
elseif static then
_,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
end
-- check variable type
output(' if (!'..self:outchecktype(2)..')')
output(' tolua_error(tolua_S,(char*)"#vinvalid type in variable assignment.",&tolua_err);')
output('#endif\n')
-- assign value
local def = 0
if self.def ~= '' then def = self.def end
if self.type == 'char*' and self.dim ~= '' then -- is string
output(' strncpy(')
if class and static then
output(self.parent.type..'::'..self.name)
elseif class then
output('self->'..self.name)
else
output(self.name)
end
output(',tolua_tostring(tolua_S,2,',def,'),',self.dim,'-1);')
else
local ptr = ''
if self.ptr~='' then ptr = '*' end
output(' ')
local name = prop_set or self.name
if class and static then
output(self.parent.type..'::'..name)
elseif class then
output('self->'..name)
else
output(name)
end
local t = isbasic(self.type)
if prop_set then
output('(')
else
output(' = ')
end
if not t and ptr=='' then output('*') end
output('((',self.mod,self.type)
if not t then
output('*')
end
output(') ')
if t then
if isenum(self.type) then
output('(int) ')
end
output('tolua_to'..t,'(tolua_S,2,',def,'))')
else
output('tolua_tousertype(tolua_S,2,',def,'))')
end
if prop_set then
output(")")
end
output(";")
end
output(' return 0;')
output('}')
output('#endif //#ifndef TOLUA_DISABLE\n')
output('\n')
end
end
function classVariable:register (pre)
if not self:check_public_access() then
return
end
pre = pre or ''
local parent = self:inmodule() or self:innamespace() or self:inclass()
if not parent then
if classVariable._warning==nil then
warning("Mapping variable to global may degrade performance")
classVariable._warning = 1
end
end
if self.csetname then
output(pre..'tolua_variable(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');')
else
output(pre..'tolua_variable(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);')
end
end
-- Internal constructor
function _Variable (t)
setmetatable(t,classVariable)
append(t)
return t
end
-- Constructor
-- Expects a string representing the variable declaration.
function Variable (s)
return _Variable (Declaration(s,'var'))
end

View File

@@ -0,0 +1,78 @@
-- tolua: verbatim class
-- Written by Waldemar Celes
-- TeCGraf/PUC-Rio
-- Jul 1998
-- $Id: verbatim.lua 1004 2006-02-27 13:03:20Z lindquist $
-- This code is free software; you can redistribute it and/or modify it.
-- The software provided hereunder is on an "as is" basis, and
-- the author has no obligation to provide maintenance, support, updates,
-- enhancements, or modifications.
-- Verbatim class
-- Represents a line translated directed to the binding file.
-- The following filds are stored:
-- line = line text
classVerbatim = {
line = '',
cond = nil, -- condition: where to generate the code (s=suport, r=register)
}
classVerbatim.__index = classVerbatim
setmetatable(classVerbatim,classFeature)
-- preamble verbatim
function classVerbatim:preamble ()
if self.cond == '' then
write(self.line)
end
end
-- support code
function classVerbatim:supcode ()
if strfind(self.cond,'s') then
write(self.line)
write('\n')
end
end
-- register code
function classVerbatim:register (pre)
if strfind(self.cond,'r') then
write(self.line)
end
end
-- Print method
function classVerbatim:print (ident,close)
print(ident.."Verbatim{")
print(ident.." line = '"..self.line.."',")
print(ident.."}"..close)
end
-- Internal constructor
function _Verbatim (t)
setmetatable(t,classVerbatim)
append(t)
return t
end
-- Constructor
-- Expects a string representing the text line
function Verbatim (l,cond)
if strsub(l,1,1) == "'" then
l = strsub(l,2)
elseif strsub(l,1,1) == '$' then
cond = 'sr' -- generates in both suport and register fragments
l = strsub(l,2)
end
return _Verbatim {
line = l,
cond = cond or '',
}
end

Binary file not shown.