⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 function.lua

📁 cegui界面库
💻 LUA
📖 第 1 页 / 共 2 页
字号:
-- 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 + -