436 lines
10 KiB
Lua
436 lines
10 KiB
Lua
|
|
-- 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") -- ע<>ͺ<EFBFBD><CDBA><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
p.code = gsub(p.code, "#define%s*[%w_]+%s*%c*\n", "") -- ע<><D7A2>ͷ<EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD>ΰ<EFBFBD><CEB0><EFBFBD><EFBFBD>ĺ<EFBFBD>
|
|||
|
|
p.code = gsub(p.code, "%s*class%s*[%w_]+%s*;", "") -- ɾ<><C9BE>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
p.code = gsub(p.code, "%s*struct%s*[%w_]+%s*;", "") -- ɾ<><C9BE>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľṹ
|
|||
|
|
|
|||
|
|
--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
|
|||
|
|
|
|||
|
|
|