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
 | ||
| 
 | ||
| 
 |