|
|
@@ -0,0 +1,505 @@
|
|
|
+--
|
|
|
+-- Copyright (c) 2008-2014 the Urho3D project.
|
|
|
+--
|
|
|
+-- Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
+-- of this software and associated documentation files (the "Software"), to deal
|
|
|
+-- in the Software without restriction, including without limitation the rights
|
|
|
+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
+-- copies of the Software, and to permit persons to whom the Software is
|
|
|
+-- furnished to do so, subject to the following conditions:
|
|
|
+--
|
|
|
+-- The above copyright notice and this permission notice shall be included in
|
|
|
+-- all copies or substantial portions of the Software.
|
|
|
+--
|
|
|
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
+-- THE SOFTWARE.
|
|
|
+--
|
|
|
+
|
|
|
+-- Highly based on "ToDoxHook.lua", adjusted for Zerobrane Studio API format.
|
|
|
+-- Compatible with Zerobrane Studio 0.41+ (Zerobrane Studio 0.40 and below may have issues)
|
|
|
+
|
|
|
+--[[ Copy result in your Zerobrane Studio's folder "api/lua" and set it in your
|
|
|
+ "interpreters" file with the filename (excluding it's lua extension) into the
|
|
|
+ "api" table variable. ]]--
|
|
|
+
|
|
|
+local classes = {}
|
|
|
+local enumerates = {}
|
|
|
+local globalConstants = {}
|
|
|
+local globalFunctions = {}
|
|
|
+local globalProperties = {}
|
|
|
+local currentClass = nil
|
|
|
+local currentFunction = nil
|
|
|
+
|
|
|
+function classClass:print(ident,close)
|
|
|
+ local class = {}
|
|
|
+ class.name = self.name
|
|
|
+ class.base = self.base
|
|
|
+ class.lname = self.lname
|
|
|
+ class.type = self.type
|
|
|
+ class.btype = self.btype
|
|
|
+ class.ctype = self.ctype
|
|
|
+
|
|
|
+ currentClass = class
|
|
|
+ local i = 1
|
|
|
+ while self[i] do
|
|
|
+ self[i]:print(ident.." ",",")
|
|
|
+ i = i + 1
|
|
|
+ end
|
|
|
+ currentClass = nil
|
|
|
+
|
|
|
+ table.insert(classes, class)
|
|
|
+end
|
|
|
+
|
|
|
+function classCode:print(ident,close)
|
|
|
+end
|
|
|
+
|
|
|
+function classDeclaration:print(ident,close)
|
|
|
+ local declaration = {}
|
|
|
+ declaration.mod = self.mod
|
|
|
+ declaration.type = self.type
|
|
|
+ declaration.ptr = self.ptr
|
|
|
+ declaration.name = self.name
|
|
|
+ declaration.dim = self.dim
|
|
|
+ declaration.def = self.def
|
|
|
+ declaration.ret = self.ret
|
|
|
+
|
|
|
+ if currentFunction ~= nil then
|
|
|
+ if currentFunction.declarations == nil then
|
|
|
+ currentFunction.declarations = { declaration }
|
|
|
+ else
|
|
|
+ table.insert(currentFunction.declarations, declaration)
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function classEnumerate:print(ident,close)
|
|
|
+ local enumerate = {}
|
|
|
+ enumerate.name = self.name
|
|
|
+
|
|
|
+ local i = 1
|
|
|
+ while self[i] do
|
|
|
+ if self[i] ~= "" then
|
|
|
+ if enumerate.values == nil then
|
|
|
+ enumerate.values = { self[i] }
|
|
|
+ else
|
|
|
+ table.insert(enumerate.values, self[i])
|
|
|
+ end
|
|
|
+ end
|
|
|
+ i = i + 1
|
|
|
+ end
|
|
|
+
|
|
|
+ if enumerate.values ~= nil then
|
|
|
+ table.insert(enumerates, enumerate)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function deepCopy(t)
|
|
|
+ if type(t) ~= "table" then
|
|
|
+ return t
|
|
|
+ end
|
|
|
+
|
|
|
+ local mt = getmetatable(t)
|
|
|
+ local ret = {}
|
|
|
+ for k, v in pairs(t) do
|
|
|
+ if type(v) == "table" then
|
|
|
+ v = deepCopy(v)
|
|
|
+ end
|
|
|
+ ret[k] = v
|
|
|
+ end
|
|
|
+ setmetatable(ret, mt)
|
|
|
+
|
|
|
+ return ret
|
|
|
+end
|
|
|
+
|
|
|
+function printFunction(self,ident,close,isfunc)
|
|
|
+ local func = {}
|
|
|
+ func.mod = self.mod
|
|
|
+ func.type = self.type
|
|
|
+ func.ptr = self.ptr
|
|
|
+ func.name = self.name
|
|
|
+ func.lname = self.lname
|
|
|
+ func.const = self.const
|
|
|
+ func.cname = self.cname
|
|
|
+ func.lname = self.lname
|
|
|
+
|
|
|
+ if isfunc then
|
|
|
+ func.name = func.lname
|
|
|
+ end
|
|
|
+
|
|
|
+ currentFunction = func
|
|
|
+ local i = 1
|
|
|
+ while self.args[i] do
|
|
|
+ self.args[i]:print(ident.." ",",")
|
|
|
+ i = i + 1
|
|
|
+ end
|
|
|
+ currentFunction = nil
|
|
|
+
|
|
|
+ if currentClass == nil then
|
|
|
+ table.insert(globalFunctions, func)
|
|
|
+ else
|
|
|
+ if func.name == "delete" then
|
|
|
+ func.type = "void"
|
|
|
+ end
|
|
|
+
|
|
|
+ if currentClass.functions == nil then
|
|
|
+ currentClass.functions = { func }
|
|
|
+ else
|
|
|
+ table.insert(currentClass.functions, func)
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function classFunction:print(ident,close)
|
|
|
+ printFunction(self,ident,close, true)
|
|
|
+end
|
|
|
+
|
|
|
+function classOperator:print(ident,close)
|
|
|
+ printFunction(self,ident,close, false)
|
|
|
+end
|
|
|
+
|
|
|
+function classVariable:print(ident,close)
|
|
|
+ local property = {}
|
|
|
+ property.mod = self.mod
|
|
|
+ property.type = self.type
|
|
|
+ property.ptr = self.ptr
|
|
|
+ property.name = self.lname
|
|
|
+ property.def = self.def
|
|
|
+ property.ret = self.ret
|
|
|
+
|
|
|
+ if currentClass == nil then
|
|
|
+ if property.mod:find("tolua_property__") == nil then
|
|
|
+ table.insert(globalConstants, property)
|
|
|
+ else
|
|
|
+ table.insert(globalProperties, property)
|
|
|
+ end
|
|
|
+ else
|
|
|
+ if currentClass.properties == nil then
|
|
|
+ currentClass.properties = { property }
|
|
|
+ else
|
|
|
+ table.insert(currentClass.properties, property)
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function classVerbatim:print(ident,close)
|
|
|
+end
|
|
|
+
|
|
|
+function sortByName(t)
|
|
|
+ table.sort(t, function(a, b) return a.name < b.name end)
|
|
|
+end
|
|
|
+
|
|
|
+-- Workaround for Zerobrane Studio's tool-tip with overloaded functions
|
|
|
+function adjustClassesOverloadFuncs()
|
|
|
+ for i, class in ipairs(classes) do
|
|
|
+ if classes[i].functions ~= nil then
|
|
|
+ for j, func in ipairs(classes[i].functions) do
|
|
|
+ for k, searchfunc in ipairs(classes[i].functions) do
|
|
|
+ -- don't apply on same
|
|
|
+ if k ~= j and func.name == searchfunc.name then
|
|
|
+ if classes[i].functions[j].overloads == nil then
|
|
|
+ classes[i].functions[j].overloads = {}
|
|
|
+ end
|
|
|
+ table.insert(classes[i].functions[j].overloads, searchfunc)
|
|
|
+ table.remove(classes[i].functions, k)
|
|
|
+ adjustClassesOverloadFuncs()
|
|
|
+ return
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeFunctionArgs(file, declarations)
|
|
|
+ local count = table.maxn(declarations)
|
|
|
+ for i = 1, count do
|
|
|
+ local declaration = declarations[i]
|
|
|
+ if declaration.type ~= "void" then
|
|
|
+ -- add paramter type
|
|
|
+ local param_str = declaration.type
|
|
|
+ -- add pointer or reference
|
|
|
+ if declaration.ptr ~= "" then
|
|
|
+ param_str = param_str .. declaration.ptr
|
|
|
+ end
|
|
|
+ -- add paramter name
|
|
|
+ param_str = param_str .. " " .. declaration.name
|
|
|
+ -- add paramter default value
|
|
|
+ if declaration.def ~= "" then
|
|
|
+ param_str = param_str .. " = " .. declaration.def
|
|
|
+ end
|
|
|
+ file:write(param_str)
|
|
|
+ end
|
|
|
+ if i ~= count then
|
|
|
+ file:write(", ")
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeFunctionReturn(file, func)
|
|
|
+ local return_str = ""
|
|
|
+ if func.type ~= "" and func.type ~= "void" then
|
|
|
+ return_str = return_str .. func.type
|
|
|
+ end
|
|
|
+ if func.ptr ~= "" then
|
|
|
+ if func.type == "" and classname ~= nil then
|
|
|
+ return_str = return_str .. classname
|
|
|
+ end
|
|
|
+ return_str = return_str .. func.ptr
|
|
|
+ end
|
|
|
+ file:write(return_str)
|
|
|
+end
|
|
|
+
|
|
|
+function writeInheritances(file, classname)
|
|
|
+ for i, inheritance in ipairs(classes) do
|
|
|
+ if inheritance.name == classname then
|
|
|
+ if inheritance.functions ~= nil then
|
|
|
+ for j, func in ipairs(inheritance.functions) do
|
|
|
+ writeFunction(file, func, classname, true)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ if inheritance.properties ~= nil then
|
|
|
+ for j, property in ipairs(inheritance.properties) do
|
|
|
+ writeProperty(file, property)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ -- append inheritance functions & properties
|
|
|
+ if inheritance.base ~= "" then
|
|
|
+ writeInheritances(file, inheritance.base)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeClasses(file)
|
|
|
+ sortByName(classes)
|
|
|
+ adjustClassesOverloadFuncs()
|
|
|
+
|
|
|
+ file:write("\n\n -- Classes")
|
|
|
+ for i, class in ipairs(classes) do
|
|
|
+ file:write("\n " .. class.name .. " = {")
|
|
|
+
|
|
|
+ if class.functions ~= nil or class.properties ~= nil then
|
|
|
+ file:write("\n childs = {")
|
|
|
+ end
|
|
|
+
|
|
|
+ if class.functions ~= nil then
|
|
|
+ for i, func in ipairs(class.functions) do
|
|
|
+ writeFunction(file, func, class.name)
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ if class.properties ~= nil then
|
|
|
+ for i, property in ipairs(class.properties) do
|
|
|
+ writeProperty(file, property)
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ -- append inheritance functions & properties
|
|
|
+ if class.base ~= "" then
|
|
|
+ writeInheritances(file, class.base)
|
|
|
+ end
|
|
|
+
|
|
|
+ if class.functions ~= nil or class.properties ~= nil then
|
|
|
+ file:write("\n },")
|
|
|
+ end
|
|
|
+
|
|
|
+ file:write("\n type = \"class\"")
|
|
|
+ file:write("\n },")
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeEnumerates(file)
|
|
|
+ sortByName(enumerates)
|
|
|
+ file:write("\n\n -- Enumerations\n")
|
|
|
+
|
|
|
+ for i, enumerate in ipairs(enumerates) do
|
|
|
+ for i, value in ipairs(enumerate.values) do
|
|
|
+ file:write("\n " .. value .. " = {")
|
|
|
+ file:write("\n description = \"(Readonly) int for '" .. enumerate.name .. "'\",")
|
|
|
+ file:write("\n type = \"value\"")
|
|
|
+ file:write("\n },")
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeFunction(file, func, classname, isInheritance, asFunc)
|
|
|
+ -- ignore operators
|
|
|
+ if func.name:find("^operator[=%+%-%*%(%)\\</]") == nil then
|
|
|
+
|
|
|
+ -- ignore new/delete object if from inheritance
|
|
|
+ if not ((func.name == classname or func.name == "new" or func.name == "delete") and isInheritance == true) then
|
|
|
+
|
|
|
+ -- write function begin
|
|
|
+ file:write("\n " .. func.name .. " = {")
|
|
|
+
|
|
|
+ -- write parameters
|
|
|
+ file:write("\n args = \"(")
|
|
|
+ if func.declarations ~= nil then
|
|
|
+ writeFunctionArgs(file, func.declarations)
|
|
|
+ end
|
|
|
+ file:write(")\",")
|
|
|
+
|
|
|
+ -- write description
|
|
|
+ -- write overloaded parameters in description, if any
|
|
|
+ if func.overloads ~= nil then
|
|
|
+ file:write("\n description = \"")
|
|
|
+ local firstOverload = true
|
|
|
+ for i, overload in ipairs(func.overloads) do
|
|
|
+ if firstOverload == false then
|
|
|
+ file:write(",\\n")
|
|
|
+ else
|
|
|
+ firstOverload = false
|
|
|
+ end
|
|
|
+ file:write("(")
|
|
|
+ writeFunctionReturn(file, overload)
|
|
|
+ file:write(") "..overload.name.." (")
|
|
|
+ writeFunctionArgs(file, overload.declarations)
|
|
|
+ file:write(")")
|
|
|
+ end
|
|
|
+ file:write("\",")
|
|
|
+ end
|
|
|
+ -- [TODO] Read package file with "flags.f" and link functions from headers' doxygen comments (///)
|
|
|
+
|
|
|
+ -- write returns
|
|
|
+ if func.type ~= "" or func.ptr ~= "" then
|
|
|
+ file:write("\n returns = \"(")
|
|
|
+ writeFunctionReturn(file, func)
|
|
|
+ file:write(")\",")
|
|
|
+ end
|
|
|
+
|
|
|
+ -- write valuetype
|
|
|
+ if func.ptr ~= "" then
|
|
|
+ if func.type ~= "" then
|
|
|
+ file:write("\n valuetype = \"" .. func.type:gsub("(const%s+)","") .. "\",")
|
|
|
+ elseif classname ~= nil then
|
|
|
+ file:write("\n valuetype = \"" .. classname .. "\",")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ -- write function end
|
|
|
+ if asFunc == true then
|
|
|
+ file:write("\n type = \"function\"") -- accepts auto-completion with ".", ":" and global
|
|
|
+ else
|
|
|
+ file:write("\n type = \"method\"") -- accepts auto-completion only with ":"
|
|
|
+ end
|
|
|
+ file:write("\n },")
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeGlobalConstants(file)
|
|
|
+ sortByName(globalConstants)
|
|
|
+
|
|
|
+ file:write("\n\n -- Global Constants\n")
|
|
|
+ for i, constant in ipairs(globalConstants) do
|
|
|
+ file:write("\n " .. constant.name .. " = {")
|
|
|
+
|
|
|
+ -- write valuetype
|
|
|
+ if constant.ptr ~= "" then
|
|
|
+ if constant.type ~= "" then
|
|
|
+ file:write("\n valuetype = \"" .. constant.type:gsub("(const%s+)","") .. "\",")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ -- write description (type)
|
|
|
+ file:write("\n description = \"" .. constant.type .. constant.ptr .. "\",")
|
|
|
+
|
|
|
+ -- write constant end
|
|
|
+ file:write("\n type = \"value\"")
|
|
|
+ file:write("\n },")
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeGlobalConstants(file)
|
|
|
+ sortByName(globalConstants)
|
|
|
+
|
|
|
+ file:write("\n\n -- Global Constants\n")
|
|
|
+ for i, constant in ipairs(globalConstants) do
|
|
|
+ file:write("\n " .. constant.name .. " = {")
|
|
|
+
|
|
|
+ -- write valuetype
|
|
|
+ if constant.ptr ~= "" then
|
|
|
+ if constant.type ~= "" then
|
|
|
+ file:write("\n valuetype = \"" .. constant.type:gsub("(const%s+)","") .. "\",")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ -- write description (type)
|
|
|
+ file:write("\n description = \"" .. constant.type .. constant.ptr .. "\",")
|
|
|
+
|
|
|
+ -- write constant end
|
|
|
+ file:write("\n type = \"value\"")
|
|
|
+ file:write("\n },")
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeGlobalFunctions(file)
|
|
|
+ sortByName(globalFunctions)
|
|
|
+
|
|
|
+ file:write("\n\n -- Global Functions\n")
|
|
|
+ for i, func in ipairs(globalFunctions) do
|
|
|
+ writeFunction(file, func, nil, nil, true)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeGLobalProperties(file)
|
|
|
+ file:write("\n")
|
|
|
+ for i, property in ipairs(globalProperties) do
|
|
|
+ writeProperty(file, property)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+function writeProperty(file, property)
|
|
|
+ file:write("\n " .. property.name .. " = {")
|
|
|
+
|
|
|
+ -- write valuetype
|
|
|
+ if property.ptr ~= "" then
|
|
|
+ if property.type ~= "" then
|
|
|
+ file:write("\n valuetype = \"" .. property.type:gsub("(const%s+)","") .. "\",")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ -- write description (type)
|
|
|
+ if property.mod:find("tolua_readonly") == nil then
|
|
|
+ file:write("\n description = \"" .. property.type .. property.ptr .. "\",")
|
|
|
+ else
|
|
|
+ file:write("\n description = \"(Readonly) " .. property.type .. property.ptr .. "\",")
|
|
|
+ end
|
|
|
+ -- write property end
|
|
|
+ file:write("\n type = \"value\"")
|
|
|
+ file:write("\n },")
|
|
|
+end
|
|
|
+
|
|
|
+function classPackage:print()
|
|
|
+ if flags.o == nil then
|
|
|
+ print("Invalid output filename");
|
|
|
+ return
|
|
|
+ end
|
|
|
+
|
|
|
+ local filename = flags.o
|
|
|
+ local file = io.open(filename, "wt")
|
|
|
+
|
|
|
+ file:write("-- Urho3D API generated on "..os.date('%Y-%m-%d'))
|
|
|
+ file:write("\n\nlocal api = {")
|
|
|
+
|
|
|
+ local i = 1
|
|
|
+ while self[i] do
|
|
|
+ self[i]:print("","")
|
|
|
+ i = i + 1
|
|
|
+ end
|
|
|
+
|
|
|
+ writeClasses(file)
|
|
|
+ writeEnumerates(file)
|
|
|
+ writeGlobalFunctions(file)
|
|
|
+ writeGLobalProperties(file)
|
|
|
+ writeGlobalConstants(file)
|
|
|
+
|
|
|
+ file:write("\n}\nreturn api\n")
|
|
|
+
|
|
|
+ file:close()
|
|
|
+end
|