📄 function.lua
字号:
-- 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
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,"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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -