local debugger_stackInfo = nillocal coro_debugger = nillocal debugger_require = requirelocal debugger_exeLuaString = nillocal loadstring = loadstringlocal getinfo = debug.getinfolocal function createSocket()local base = _Glocal string = require("string")local math = require("math")local socket = require("socket")--require("socket.core")local _M = socket------------------------------------------------------------------------------- Exported auxiliar functions-----------------------------------------------------------------------------function _M.connect4(address, port, laddress, lport)return socket.connect(address, port, laddress, lport, "inet")endfunction _M.connect6(address, port, laddress, lport)return socket.connect(address, port, laddress, lport, "inet6")endfunction _M.bind(host, port, backlog)if host == "*" then host = "0.0.0.0" endlocal addrinfo, err = socket.dns.getaddrinfo(host);if not addrinfo then return nil, err endlocal sock, reserr = "no info on address"for i, alt in base.ipairs(addrinfo) doif alt.family == "inet" thensock, err = socket.tcp4()elsesock, err = socket.tcp6()endif not sock then return nil, err endsock:setoption("reuseaddr", true)res, err = sock:bind(alt.addr, port)if not res thensock:close()elseres, err = sock:listen(backlog)if not res thensock:close()elsereturn sockendendendreturn nil, errend_M.try = _M.newtry()function _M.choose(table)return function(name, opt1, opt2)if base.type(name) ~= "string" thenname, opt1, opt2 = "default", name, opt1endlocal f = table[name or "nil"]if not f then base.error("unknown key (" .. base.tostring(name) .. ")", 3)else return f(opt1, opt2) endendend------------------------------------------------------------------------------- Socket sources and sinks, conforming to LTN12------------------------------------------------------------------------------- create namespaces inside LuaSocket namespacelocal sourcet, sinkt = {}, {}_M.sourcet = sourcet_M.sinkt = sinkt_M.BLOCKSIZE = 2048sinkt["close-when-done"] = function(sock)return base.setmetatable({getfd = function() return sock:getfd() end,dirty = function() return sock:dirty() end}, {__call = function(self, chunk, err)if not chunk thensock:close()return 1else return sock:send(chunk) endend})endsinkt["keep-open"] = function(sock)return base.setmetatable({getfd = function() return sock:getfd() end,dirty = function() return sock:dirty() end}, {__call = function(self, chunk, err)if chunk then return sock:send(chunk)else return 1 endend})endsinkt["default"] = sinkt["keep-open"]_M.sink = _M.choose(sinkt)sourcet["by-length"] = function(sock, length)return base.setmetatable({getfd = function() return sock:getfd() end,dirty = function() return sock:dirty() end}, {__call = function()if length <= 0 then return nil endlocal size = math.min(socket.BLOCKSIZE, length)local chunk, err = sock:receive(size)if err then return nil, err endlength = length - string.len(chunk)return chunkend})endsourcet["until-closed"] = function(sock)local donereturn base.setmetatable({getfd = function() return sock:getfd() end,dirty = function() return sock:dirty() end}, {__call = function()if done then return nil endlocal chunk, err, partial = sock:receive(socket.BLOCKSIZE)if not err then return chunkelseif err == "closed" thensock:close()done = 1return partialelse return nil, err endend})endsourcet["default"] = sourcet["until-closed"]_M.source = _M.choose(sourcet)print("_CreateSocketEnd222 .. " .. tostring(_M));return _Mendlocal function createJson()local math = require('math')local string = require("string")local table = require("table")local object = nil------------------------------------------------------------------------------- Module declaration-----------------------------------------------------------------------------local json = {} -- Public namespacelocal json_private = {} -- Private namespace-- Public constantsjson.EMPTY_ARRAY = {}json.EMPTY_OBJECT = {}-- Public functions-- Private functionslocal decode_scanArraylocal decode_scanCommentlocal decode_scanConstantlocal decode_scanNumberlocal decode_scanObjectlocal decode_scanStringlocal decode_scanWhitespacelocal encodeStringlocal isArraylocal isEncodable------------------------------------------------------------------------------- PUBLIC FUNCTIONS-------------------------------------------------------------------------------- Encodes an arbitrary Lua object / variable.-- @param v The Lua object / variable to be JSON encoded.-- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode)function json.encode(v)-- Handle nil valuesif v == nil thenreturn "null"endlocal vtype = type(v)-- Handle stringsif vtype == 'string' thenreturn "\"" .. json_private.encodeString(v) .. "\"" -- Need to handle encoding in stringend-- Handle booleansif vtype == 'number' or vtype == 'boolean' thenreturn tostring(v)end-- Handle tablesif vtype == 'table' thenlocal rval = {}-- Consider arrays separatelylocal bArray, maxCount = isArray(v)if bArray thenfor i = 1, maxCount dotable.insert(rval, json.encode(v[i]))endelse -- An object, not an arrayfor i, j in pairs(v) doif isEncodable(i) and isEncodable(j) thentable.insert(rval, "\"" .. json_private.encodeString(i) .. '\":' .. json.encode(j))endendendif bArray thenreturn '[' .. table.concat(rval, ',') .. ']'elsereturn '{' .. table.concat(rval, ',') .. '}'endend-- Handle null valuesif vtype == 'function' and v == json.null thenreturn 'null'endassert(false, 'encode attempt to encode unsupported type ' .. vtype .. ':' .. tostring(v))end--- Decodes a JSON string and returns the decoded value as a Lua data structure / value.-- @param s The string to scan.-- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1.-- @param Lua object, number The object that was scanned, as a Lua table / string / number / boolean or nil,-- and the position of the first character after-- the scanned JSON object.function json.decode(s, startPos)startPos = startPos and startPos or 1startPos = decode_scanWhitespace(s, startPos)assert(startPos <= string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']')local curChar = string.sub(s, startPos, startPos)-- Objectif curChar == '{' thenreturn decode_scanObject(s, startPos)end-- Arrayif curChar == '[' thenreturn decode_scanArray(s, startPos)end-- Numberif string.find("+-0123456789.e", curChar, 1, true) thenreturn decode_scanNumber(s, startPos)end-- Stringif curChar == "\"" or curChar == [[']] thenreturn decode_scanString(s, startPos)endif string.sub(s, startPos, startPos + 1) == '/*' thenreturn json.decode(s, decode_scanComment(s, startPos))end-- Otherwise, it must be a constantreturn decode_scanConstant(s, startPos)end--- The null function allows one to specify a null value in an associative array (which is otherwise-- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null }function json.null()return json.null -- so json.null() will also return null ;-)end------------------------------------------------------------------------------- Internal, PRIVATE functions.-- Following a Python-like convention, I have prefixed all these 'PRIVATE'-- functions with an underscore.-------------------------------------------------------------------------------- Scans an array from JSON into a Lua object-- startPos begins at the start of the array.-- Returns the array and the next starting position-- @param s The string being scanned.-- @param startPos The starting position for the scan.-- @return table, int The scanned array as a table, and the position of the next character to scan.function decode_scanArray(s, startPos)local array = {} -- The return valuelocal stringLen = string.len(s)assert(string.sub(s, startPos, startPos) == '[', 'decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n' .. s)startPos = startPos + 1-- Infinite loop for array elementsrepeatstartPos = decode_scanWhitespace(s, startPos)assert(startPos <= stringLen, 'JSON String ended unexpectedly scanning array.')local curChar = string.sub(s, startPos, startPos)if(curChar == ']') thenreturn array, startPos + 1endif(curChar == ',') thenstartPos = decode_scanWhitespace(s, startPos + 1)endassert(startPos <= stringLen, 'JSON String ended unexpectedly scanning array.')object, startPos = json.decode(s, startPos)table.insert(array, object)until falseend--- Scans a comment and discards the comment.-- Returns the position of the next character following the comment.-- @param string s The JSON string to scan.-- @param int startPos The starting position of the commentfunction decode_scanComment(s, startPos)assert(string.sub(s, startPos, startPos + 1) == '/*', "decode_scanComment called but comment does not start at position " .. startPos)local endPos = string.find(s, '*/', startPos + 2)assert(endPos ~= nil, "Unterminated comment in string at " .. startPos)return endPos + 2end--- Scans for given constants: true, false or null-- Returns the appropriate Lua type, and the position of the next character to read.-- @param s The string being scanned.-- @param startPos The position in the string at which to start scanning.-- @return object, int The object (true, false or nil) and the position at which the next character should be-- scanned.function decode_scanConstant(s, startPos)local consts = {["true"] = true, ["false"] = false, ["null"] = nil}local constNames = {"true", "false", "null"}for i, k in pairs(constNames) doif string.sub(s, startPos, startPos + string.len(k) - 1) == k thenreturn consts[k], startPos + string.len(k)endendassert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos)end--- Scans a number from the JSON encoded string.-- (in fact, also is able to scan numeric +- eqns, which is not-- in the JSON spec.)-- Returns the number, and the position of the next character-- after the number.-- @param s The string being scanned.-- @param startPos The position at which to start scanning.-- @return number, int The extracted number and the position of the next character to scan.function decode_scanNumber(s, startPos)local endPos = startPos + 1local stringLen = string.len(s)local acceptableChars = "+-0123456789.e"while(string.find(acceptableChars, string.sub(s, endPos, endPos), 1, true)and endPos <= stringLen) doendPos = endPos + 1endlocal stringValue = 'return ' .. string.sub(s, startPos, endPos - 1)local stringEval = loadstring(stringValue)assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos)return stringEval(), endPosend--- Scans a JSON object into a Lua object.-- startPos begins at the start of the object.-- Returns the object and the next starting position.-- @param s The string being scanned.-- @param startPos The starting position of the scan.-- @return table, int The scanned object as a table and the position of the next character to scan.function decode_scanObject(s, startPos)local object = {}local stringLen = string.len(s)local key, valueassert(string.sub(s, startPos, startPos) == '{', 'decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s)startPos = startPos + 1repeatstartPos = decode_scanWhitespace(s, startPos)assert(startPos <= stringLen, 'JSON string ended unexpectedly while scanning object.')local curChar = string.sub(s, startPos, startPos)if(curChar == '}') thenreturn object, startPos + 1endif(curChar == ',') thenstartPos = decode_scanWhitespace(s, startPos + 1)endassert(startPos <= stringLen, 'JSON string ended unexpectedly scanning object.')-- Scan the keykey, startPos = json.decode(s, startPos)assert(startPos <= stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)startPos = decode_scanWhitespace(s, startPos)assert(startPos <= stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)assert(string.sub(s, startPos, startPos) == ':', 'JSON object key-value assignment mal-formed at ' .. startPos)startPos = decode_scanWhitespace(s, startPos + 1)assert(startPos <= stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key)value, startPos = json.decode(s, startPos)object[key] = valueuntil false -- infinite loop while key-value pairs are foundend-- START SoniEx2-- Initialize some things used by decode_scanString-- You know, for efficiencylocal escapeSequences = {["\\t"] = "\t",["\\f"] = "\f",["\\r"] = "\r",["\\n"] = "\n",["\\b"] = ""}setmetatable(escapeSequences, {__index = function(t, k)-- skip "\" aka strip escapereturn string.sub(k, 2)end})-- END SoniEx2--- Scans a JSON string from the opening inverted comma or single quote to the-- end of the string.-- Returns the string extracted as a Lua string,-- and the position of the next non-string character-- (after the closing inverted comma or single quote).-- @param s The string being scanned.-- @param startPos The starting position of the scan.-- @return string, int The extracted string as a Lua string, and the next character to parse.function decode_scanString(s, startPos)assert(startPos, 'decode_scanString(..) called without start position')local startChar = string.sub(s, startPos, startPos)-- START SoniEx2-- PS: I don't think single quotes are valid JSONassert(startChar == "\"" or startChar == [[']], 'decode_scanString called for a non-string')--assert(startPos, "String decoding failed: missing closing " .. startChar .. " for string at position " .. oldStart)local t = {}local i, j = startPos, startPoswhile string.find(s, startChar, j + 1) ~= j + 1 dolocal oldj = ji, j = string.find(s, "\\.", j + 1)local x, y = string.find(s, startChar, oldj + 1)if not i or x < i theni, j = x, y - 1endtable.insert(t, string.sub(s, oldj + 1, i - 1))if string.sub(s, i, j) == "\\u" thenlocal a = string.sub(s, j + 1, j + 4)j = j + 4local n = tonumber(a, 16)assert(n, "String decoding failed: bad Unicode escape " .. a .. " at position " .. i .. " : " .. j)-- math.floor(x/2^y) == lazy right shift-- a % 2^b == bitwise_and(a, (2^b)-1)-- 64 = 2^6-- 4096 = 2^12 (or 2^6 * 2^6)local xif n < 128 thenx = string.char(n % 128)elseif n < 2048 then-- [110x xxxx] [10xx xxxx]x = string.char(192 +(math.floor(n / 64) % 32), 128 +(n % 64))else-- [1110 xxxx] [10xx xxxx] [10xx xxxx]x = string.char(224 +(math.floor(n / 4096) % 16), 128 +(math.floor(n / 64) % 64), 128 +(n % 64))endtable.insert(t, x)elsetable.insert(t, escapeSequences[string.sub(s, i, j)])endendtable.insert(t, string.sub(j, j + 1))assert(string.find(s, startChar, j + 1), "String decoding failed: missing closing " .. startChar .. " at position " .. j .. "(for string at position " .. startPos .. ")")return table.concat(t, ""), j + 2-- END SoniEx2end--- Scans a JSON string skipping all whitespace from the current start position.-- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached.-- @param s The string being scanned-- @param startPos The starting position where we should begin removing whitespace.-- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string-- was reached.function decode_scanWhitespace(s, startPos)local whitespace = " \n\r\t"local stringLen = string.len(s)while(string.find(whitespace, string.sub(s, startPos, startPos), 1, true) and startPos <= stringLen) dostartPos = startPos + 1endreturn startPosend--- Encodes a string to be JSON-compatible.-- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-)-- @param s The string to return as a JSON encoded (i.e. backquoted string)-- @return The string appropriately escaped.local escapeList = {["\""] = '\\\"',['\\'] = '\\\\',['/'] = '\\/',[''] = '\\b',['\f'] = '\\f',['\n'] = '\\n',['\r'] = '\\r',['\t'] = '\\t'}function json_private.encodeString(s)local s = tostring(s)return s:gsub(".", function(c) return escapeList[c] end) -- SoniEx2: 5.0 compatend-- Determines whether the given Lua type is an array or a table / dictionary.-- We consider any table an array if it has indexes 1..n for its n items, and no-- other data in the table.-- I think this method is currently a little 'flaky', but can't think of a good way around it yet...-- @param t The table to evaluate as an array-- @return boolean, number True if the table can be represented as an array, false otherwise. If true,-- the second returned value is the maximum-- number of indexed elements in the array.function isArray(t)-- Next we count all the elements, ensuring that any non-indexed elements are not-encodable-- (with the possible exception of 'n')if(t == json.EMPTY_ARRAY) then return true, 0 endif(t == json.EMPTY_OBJECT) then return false endlocal maxIndex = 0for k, v in pairs(t) doif(type(k) == 'number' and math.floor(k) == k and 1 <= k) then -- k,v is an indexed pairif(not isEncodable(v)) then return false end -- All array elements must be encodablemaxIndex = math.max(maxIndex, k)elseif(k == 'n') thenif v ~=(t.n or # t) then return false end -- False if n does not hold the number of elementselse -- Else of (k=='n')if isEncodable(v) then return false endend -- End of (k~='n')end -- End of k,v not an indexed pairend -- End of loop across all pairsreturn true, maxIndexend--- Determines whether the given Lua object / table / variable can be JSON encoded. The only-- types that are JSON encodable are: string, boolean, number, nil, table and json.null.-- In this implementation, all other types are ignored.-- @param o The object to examine.-- @return boolean True if the object should be JSON encoded, false if it should be ignored.function isEncodable(o)local t = type(o)return(t == 'string' or t == 'boolean' or t == 'number' or t == 'nil' or t == 'table') or(t == 'function' and o == json.null)endreturn jsonendlocal debugger_print = printlocal debug_server = nillocal breakInfoSocket = nillocal json = createJson()local LuaDebugger = {fileMaps = {},Run = true, --表示正常运行只检测断点StepIn = false,StepInLevel = 0,StepNext = false,StepNextLevel = 0, --表示当前堆栈深度0为第一层StepOut = false,breakInfos = {},runTimeType = nil,isHook = true,pathCachePaths = {},isProntToConsole = 1,isDebugPrint = true,hookType = "lrc",currentFileName = "",currentTempFunc = nil,--分割字符串缓存splitFilePaths = {},DebugLuaFie="",}LuaDebugger.event = {S2C_SetBreakPoints = 1,C2S_SetBreakPoints = 2,S2C_RUN = 3,C2S_HITBreakPoint = 4,S2C_ReqVar = 5,C2S_ReqVar = 6,--单步跳过请求S2C_NextRequest = 7,--单步跳过反馈C2S_NextResponse = 8,-- 单步跳过 结束 没有下一步C2S_NextResponseOver = 9,--单步跳入S2C_StepInRequest = 10,C2S_StepInResponse = 11,--单步跳出S2C_StepOutRequest = 12,--单步跳出返回C2S_StepOutResponse = 13,--打印C2S_LuaPrint = 14,S2C_LoadLuaScript = 16,C2S_SetSocketName = 17,C2S_LoadLuaScript = 18,C2S_DebugXpCall = 20,}--Description:重定向print到调试窗口--Params:--Return:--Last Modify: Zahidle.PFfunction print( msg )print1(msg);endfunction debuglog( msg )print1("debug:" .. msg);endfunction dumpTableToString( _table , _callnum)if( type(_table) ~= "table" ) thenreturn _table;end--标记递归层级,初始为0local callNum = 0;if( _callnum ) thencallNum = _callnum;end--返回当前层级缩进信息local printIndentation = function()local str = "";if( callNum ) thenfor i=1,callNum,1 dostr = str .. " ";endendreturn str;endlocal strIndentation = printIndentation();local retstr = "[\n";for k,v in pairs(_table) doretstr = retstr .. strIndentation .. tostring(k) .. " = " .. dumpTableToString(v,callNum+1) .. ";\n";endretstr = retstr .. strIndentation .. "]";return retstr;endfunction print1(...)if(LuaDebugger.isProntToConsole == 1 or LuaDebugger.isProntToConsole == 3) thendebugger_print(...)endif(LuaDebugger.isProntToConsole == 1 or LuaDebugger.isProntToConsole == 2) thenif(debug_server) thenlocal arg = { ... } --这里的...和{}符号中间需要有空格号,否则会出错local str = ""for k, v in pairs(arg) dostr = str .. tostring(v) .. "\t"endlocal sendMsg = {event = LuaDebugger.event.C2S_LuaPrint,data = {msg = str}}local sendStr = json.encode(sendMsg)debug_server:send(sendStr .. "__debugger_k0204__")endendend----=============================工具方法=============================================local debug_hook = nillocal function debugger_strSplit(input, delimiter)input = tostring(input)delimiter = tostring(delimiter)if(delimiter == '') then return false endlocal pos, arr = 0, {}-- for each divider foundfor st, sp in function() return string.find(input, delimiter, pos, true) end dotable.insert(arr, string.sub(input, pos, st - 1))pos = sp + 1endtable.insert(arr, string.sub(input, pos))return arrendlocal function debugger_strTrim(input)input = string.gsub(input, "^[ \t\n\r]+", "")return string.gsub(input, "[ \t\n\r]+$", "")endlocal function debugger_dump(value, desciption, nesting)if type(nesting) ~= "number" then nesting = 3 endlocal lookupTable = {}local result = {}local function _v(v)if type(v) == "string" thenv = "\"" .. v .. "\""endreturn tostring(v)endlocal traceback = debugger_strSplit(debug.traceback("", 2), "\n")debuglog("dump from: " .. debugger_strTrim(traceback[3]))local function _dump(value, desciption, indent, nest, keylen)desciption = desciption or "<var>"spc = ""if type(keylen) == "number" thenspc = string.rep(" ", keylen - string.len(_v(desciption)))endif type(value) ~= "table" thenresult[# result + 1] = string.format("%s%s%s = %s", indent, _v(desciption), spc, _v(value))elseif lookupTable[value] thenresult[# result + 1] = string.format("%s%s%s = *REF*", indent, desciption, spc)elselookupTable[value] = trueif nest > nesting thenresult[# result + 1] = string.format("%s%s = *MAX NESTING*", indent, desciption)elseresult[# result + 1] = string.format("%s%s = {", indent, _v(desciption))local indent2 = indent .. " "local keys = {}local keylen = 0local values = {}for k, v in pairs(value) dokeys[# keys + 1] = klocal vk = _v(k)local vkl = string.len(vk)if vkl > keylen then keylen = vkl endvalues[k] = vendtable.sort(keys, function(a, b)if type(a) == "number" and type(b) == "number" thenreturn a < belsereturn tostring(a) < tostring(b)endend)for i, k in ipairs(keys) do_dump(values[k], k, indent2, nest + 1, keylen)endresult[# result + 1] = string.format("%s}", indent)endendend_dump(value, desciption, "-- ", 1)for i, line in ipairs(result) dodebuglog(line)endendlocal function ToBase64(source_str)local b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'local s64 = ''local str = source_strwhile # str > 0 dolocal bytes_num = 0local buf = 0for byte_cnt = 1, 3 dobuf =(buf * 256)if # str > 0 thenbuf = buf + string.byte(str, 1, 1)str = string.sub(str, 2)bytes_num = bytes_num + 1endendfor group_cnt = 1,(bytes_num + 1) dolocal b64char = math.fmod(math.floor(buf / 262144), 64) + 1s64 = s64 .. string.sub(b64chars, b64char, b64char)buf = buf * 64endfor fill_cnt = 1,(3 - bytes_num) dos64 = s64 .. '='endendreturn s64endlocal function debugger_setVarInfo(name, value)local vt = type(value)local valueStr = ""if(vt ~= "table") thenvalueStr = tostring(value)valueStr = ToBase64(valueStr)else-- valueStr = topointer(value)endlocal valueInfo = {name = name,valueType = vt,valueStr = valueStr}return valueInfo;endlocal function debugger_getvalue(f)local i = 1local locals = {}-- get localswhile true dolocal name, value = debug.getlocal(f, i)if not name then break endif(name ~= "(*temporary)") thenlocals[name] = valueendi = i + 1endlocal func = getinfo(f, "f").funci = 1local ups = {}while func do -- check for func as it may be nil for tail callslocal name, value = debug.getupvalue(func, i)if not name then break endups[name] = valuei = i + 1endreturn {locals = locals, ups = ups}end--获取堆栈數據-- data{-- stack = {1:{-- src =-- scoreName =-- currentline =-- linedefined =-- what =-- nameWhat =-- };-- vars = {-- 1:var1;-- 2:var2;-- }-- funcs = {-- 1:func1;-- 2:func2;-- }-- event = "C2S_HITBreakPoint"-- funcsLength = #funcs-- }--返回当前堆栈信息debugger_stackInfo = function(ignoreCount, event)local datas = {}local stack = {}local varInfos = {}local funcs = {}local index = 0;for i = ignoreCount, 100 dolocal source = getinfo(i)local isadd = trueif(i == ignoreCount) thenlocal file = source.sourceif(file:find(LuaDebugger.DebugLuaFie)) thenreturnendif(file == "=[C]") thenisadd = falseendendif not source thenbreak;endif(isadd) thenlocal file = source.sourcelocal info ={src = file,scoreName = source.name,currentline = source.currentline,linedefined = source.linedefined,what = source.what,nameWhat = source.namewhat}index = ilocal vars = debugger_getvalue(i + 1)table.insert(stack, info)table.insert(varInfos, vars)table.insert(funcs, source.func)endif source.what == 'main' then break endendlocal stackInfo = {stack = stack, vars = varInfos, funcs = funcs}local data = {stack = stackInfo.stack,vars = stackInfo.vars,funcs = stackInfo.funcs,event = event,funcsLength = #stackInfo.funcs}LuaDebugger.currentTempFunc = data.funcs[1]return dataend--==============================工具方法 end======================================================--===========================点断信息==================================================--根据不同的游戏引擎进行定时获取断点信息--CCDirector:sharedDirector():getScheduler()local debugger_setBreak = nillocal function debugger_receiveDebugBreakInfo()print1("debugger_receiveDebugBreakInfo.." .. tostring(breakInfoSocket));if(breakInfoSocket) thenlocal msg, status = breakInfoSocket:receive()if(msg) thenlocal netData = json.decode(msg)if netData.event == LuaDebugger.event.S2C_SetBreakPoints thendebugger_setBreak(netData.data)elseif netData.event == LuaDebugger.event.S2C_LoadLuaScript thenprint("获取数据")debugger_exeLuaString(netData.data, false)endendendendlocal function splitFilePath(path)if(LuaDebugger.splitFilePaths[path]) thenreturn LuaDebugger.splitFilePaths[path]endlocal pos, arr = 0, {}-- for each divider foundfor st, sp in function() return string.find(path, '/', pos, true) end dotable.insert(arr, string.sub(path, pos, st - 1))pos = sp + 1endtable.insert(arr, string.sub(path, pos))LuaDebugger.splitFilePaths[path] = arrreturn arrend-- 断点信息数据结构:-- LuaDebugger.breakInfo[-- filename = breakInfo[-- serverpath = {-- pathName = "";-- lines = [-- linenum1 = true,-- linenum4 = true,-- linenum6 = true-- ...-- ]-- }-- ...-- ]-- ...-- ]--设置断点信息debugger_setBreak = function(datas)local breakInfos = LuaDebugger.breakInfosfor i, data in ipairs(datas) dolocal breakInfo = breakInfos[data.fileName]if(not breakInfo) thenbreakInfos[data.fileName] = {}breakInfo = breakInfos[data.fileName]endif(not data.lines or # data.lines == 0) thenbreakInfo[data.serverPath] = nilelselocal lineInfos = {}for li, line in ipairs(data.lines) dolineInfos[line] = trueendbreakInfo[data.serverPath] = {pathNames = splitFilePath(data.serverPath),lines = lineInfos}endlocal count = 0for i, linesInfo in pairs(breakInfo) docount = count + 1endif(count == 0) thenbreakInfos[data.fileName] = nilendend--debugger_dump(breakInfos, "breakInfos", 6)--检查是否需要断点local isHook = falsefor k, v in pairs(breakInfos) doisHook = truebreakend--这样做的原因是为了最大限度的使手机调试更加流畅 注意这里会连续的进行n次if(isHook) thenif(not LuaDebugger.isHook) thendebug.sethook(debug_hook, "lrc")endLuaDebugger.isHook = true--print("isHook=>true")else--print("isHook=>false")if(LuaDebugger.isHook) thendebug.sethook()endLuaDebugger.isHook = falseendendlocal function debugger_checkFileIsBreak(fileName)return LuaDebugger.breakInfos[fileName]endlocal function debugger_checkIsBreak(fileName, line)local breakInfo = LuaDebugger.breakInfos[fileName]if(breakInfo) thenlocal ischeck = falsefor k, lineInfo in pairs(breakInfo) dolocal lines = lineInfo.linesif(lines and lines[line]) thenischeck = truebreakendendif(not ischeck) then return end--并且在断点中local info = getinfo(3)local source = info.sourcesource = source:gsub("\\", "/")if source:find("@") == 1 thensource = source:sub(2);endlocal index = source:find("%.lua")if not index thensource = source .. ".lua"endlocal hitPathNames = splitFilePath(source)local isHit = truelocal hitCounts = {}for k, lineInfo in pairs(breakInfo) dolocal lines = lineInfo.lineslocal pathNames = lineInfo.pathNamesif(lines and lines[line]) then--判断路径hitCounts[k] = 0local hitPathNamesCount = # hitPathNameslocal pathNamesCount = # pathNameswhile(true) doif(pathNames[pathNamesCount] ~= hitPathNames[hitPathNamesCount]) thenisHit = falsebreakelsehitCounts[k] = hitCounts[k] + 1endpathNamesCount = pathNamesCount - 1hitPathNamesCount = hitPathNamesCount - 1if(pathNamesCount <= 0 or hitPathNamesCount <= 0) thenbreak;endendendendlocal hitFieName = ""local maxCount = 0for k, v in pairs(hitCounts) doif(v > maxCount) thenmaxCount = vhitFieName = k;endendif(# hitPathNames == 1 or(# hitPathNames > 1 and maxCount > 1)) thenif(hitFieName ~= "") thenreturn hitFieNameendendendreturn falseend--=====================================断点信息 end ----------------------------------------------local controller_host = "192.168.1.102"local controller_port = 7003local function debugger_sendMsg(serverSocket, eventName, data)local sendMsg = {event = eventName,data = data}local sendStr = json.encode(sendMsg)serverSocket:send(sendStr .. "__debugger_k0204__")end--执行lua字符串debugger_exeLuaString = function(data, isBreakPoint)local function loadScript()local luastr = data.luastrif(isBreakPoint) thenlocal currentTabble = {_G = _G}local frameId = data.frameIdframeId = frameId + 1local func = LuaDebugger.currentDebuggerData.funcs[frameId];local vars = LuaDebugger.currentDebuggerData.vars[frameId]local locals = vars.locals;local ups = vars.upsfor k, v in pairs(ups) docurrentTabble[k] = vendfor k, v in pairs(locals) docurrentTabble[k] = vendsetmetatable(currentTabble, {__index = _G})local fun = loadstring(luastr)setfenv(fun, currentTabble)fun()elselocal fun = loadstring(luastr)fun()endendlocal status, msg = xpcall(loadScript, function(error)print(error)end)if(status) thendebugger_sendMsg(debug_server, LuaDebugger.event.C2S_LoadLuaScript, {msg = "执行代码成功"})if(isBreakPoint) thenprint1("xxx22222") ;debugger_sendMsg(debug_server, LuaDebugger.event.C2S_HITBreakPoint, LuaDebugger.currentDebuggerData.stack)endelsedebugger_sendMsg(debug_server, LuaDebugger.event.C2S_LoadLuaScript, {msg = "加载代码失败"})endendlocal function getLuaFileName(str)local pos = 0local fileName = "";-- for each divider foundfor st, sp in function() return string.find(str, '/', pos, true) end dopos = sp + 1endfileName = string.sub(str, pos)return fileName;endlocal function getSource(source)if(LuaDebugger.pathCachePaths[source]) thenreturn LuaDebugger.pathCachePaths[source]endlocal file = sourcefile = file:gsub("\\", "/")if file:find("@") == 1 thenfile = file:sub(2);endlocal index = file:find("%.lua")if not index thenfile = file .. ".lua"endfile = getLuaFileName(file)LuaDebugger.pathCachePaths[source] = filereturn file;end--获取lua 变量的方法local function debugger_getBreakVar(body, server)local function exe()local variablesReference = body.variablesReferencelocal debugSpeedIndex = body.debugSpeedIndexlocal frameId = body.frameId;local type_ = body.type;local keys = body.keys;--找到对应的varlocal vars = nilif(type_ == 1) thenvars = LuaDebugger.currentDebuggerData.vars[frameId + 1]vars = vars.localselseif(type_ == 2) thenvars = LuaDebugger.currentDebuggerData.vars[frameId + 1]vars = vars.upselseif(type_ == 3) thenvars = _Gend--特殊处理下for i, v in ipairs(keys) dovars = vars[v]if(type(vars) == "userdata") thenvars = tolua.getpeer(vars)endif(vars == nil) thenbreak;endendlocal vinfos = {}-- local varinfos ={}local count = 0;if(vars ~= nil) thenfor k, v in pairs(vars) dolocal vinfo = debugger_setVarInfo(k, v)table.insert(vinfos, vinfo)if(# vinfos > 10) thendebugger_sendMsg(server,LuaDebugger.event.C2S_ReqVar,{variablesReference = variablesReference,debugSpeedIndex = debugSpeedIndex,vars = vinfos,isComplete = 0})vinfos = {}endendenddebugger_sendMsg(server, LuaDebugger.event.C2S_ReqVar, {variablesReference = variablesReference,debugSpeedIndex = debugSpeedIndex,vars = vinfos,isComplete = 1})endxpcall(exe, function(error)print("获取变量错误 错误消息-----------------")print(error)print(debug.traceback("", 2))end)endlocal function ResetDebugInfo()LuaDebugger.Run = falseLuaDebugger.StepIn = falseLuaDebugger.StepNext = falseLuaDebugger.StepOut = falseLuaDebugger.StepNextLevel = 0--debuglog("ResetDebugResetDebugResetDebugResetDebug")endlocal function debugger_loop(server)debuglog("debugger_loop start..........");server = debug_server--命令local commandlocal eval_env = {}local argwhile true do--debuglog("recv...");local line, status = server:receive()if(line) thenlocal netData = json.decode(line)local event = netData.event;local body = netData.data;if event == LuaDebugger.event.S2C_SetBreakPoints then--设置断点信息local function setB()debugger_setBreak(body)endxpcall(setB, function(error)print(error)end)elseif event == LuaDebugger.event.S2C_RUN then--debuglog("-->S2C_RUN?" .. tostring(body.runTimeType) .. '|' .. tostring(body.isProntToConsole) .. '|' .. LuaDebugger.isProntToConsole);LuaDebugger.runTimeType = body.runTimeType--LuaDebugger.isProntToConsole = body.isProntToConsoleResetDebugInfo()LuaDebugger.Run = true--debuglog("停止S2C_RUN" );local data = coroutine.yield()--debuglog("继续S2C_RUN" );LuaDebugger.currentDebuggerData = data;debugger_sendMsg(server, data.event, {stack = data.stack})elseif event == LuaDebugger.event.S2C_ReqVar then--请求数据信息debugger_getBreakVar(body, server)elseif event == LuaDebugger.event.S2C_NextRequest thenResetDebugInfo()LuaDebugger.StepNext = trueLuaDebugger.StepInLevel = 0--设置当前文件名和当前行数--debuglog("停止S2C_NextRequest" );local data = coroutine.yield()--local aaa = dumpTableToString(data);--debuglog("继续S2C_NextRequest" );--重置调试信息LuaDebugger.currentDebuggerData = data;debugger_sendMsg(server, data.event, {stack = data.stack})elseif(event == LuaDebugger.event.S2C_StepInRequest) then--单步跳入ResetDebugInfo()LuaDebugger.StepIn = true--debuglog("停止S2C_StepInRequest" );local data = coroutine.yield()--debuglog("继续S2C_StepInRequest" );--重置调试信息LuaDebugger.currentDebuggerData = data;debugger_sendMsg(server, data.event, {stack = data.stack,eventType = data.eventType})elseif(event == LuaDebugger.event.S2C_StepOutRequest) then--单步跳出ResetDebugInfo()LuaDebugger.StepOut = true--debuglog("停止S2C_StepOutRequest" );local data = coroutine.yield()--debuglog("继续S2C_StepOutRequest" );--重置调试信息LuaDebugger.currentDebuggerData = data;debugger_sendMsg(server, data.event, {stack = data.stack,eventType = data.eventType})elseif event == LuaDebugger.event.S2C_LoadLuaScript thendebugger_exeLuaString(body, true)endendendendcoro_debugger = coroutine.create(debugger_loop)debug_hook = function(event, line)--print("***hook:" .. tostring(event) );if(not LuaDebugger.isHook) thenreturnendif(LuaDebugger.Run) thenif(event == "line") then--print("***:" .. line);local isCheck = falsefor k, breakInfo in pairs(LuaDebugger.breakInfos) dofor bk, linesInfo in pairs(breakInfo) doif(linesInfo.lines[line]) thenisCheck = truebreakendendif(isCheck) thenbreakendendif(not isCheck) thenreturnendelseLuaDebugger.currentFileName = nilLuaDebugger.currentTempFunc = nilreturnendend--跳出if(LuaDebugger.StepOut) thenif(event == "line" or event == "call") thenreturnendlocal tempFun = getinfo(2,"f").funcif(LuaDebugger.currentDebuggerData.funcsLength == 1) thenResetDebugInfo();LuaDebugger.Run = trueelseif(LuaDebugger.currentDebuggerData.funcs[2] == tempFun) thenlocal data = debugger_stackInfo(3, LuaDebugger.event.C2S_StepInResponse)--挂起等待调试器作出反应coroutine.resume(coro_debugger, data)endendreturnendlocal file = nilif(event == "call") then-- if(not LuaDebugger.StepOut) thenif(LuaDebugger.StepNext) thenLuaDebugger.StepNextLevel = LuaDebugger.StepNextLevel+1endlocal stepInfo = getinfo(2,"nS")local source = stepInfo.source--print1("call...................." .. tostring(stepInfo.name));if(source:find(LuaDebugger.DebugLuaFie) or source == "=[C]") thenreturnendfile = getSource(source);LuaDebugger.currentFileName = file--print1("callfile:" .. file .. " stepNext:" .. LuaDebugger.StepNextLevel);-- endelseif(event == "return" or event == "tail return") then--print1( event .. "...........");-- if(not LuaDebugger.StepOut) thenif(LuaDebugger.StepNext) thenLuaDebugger.StepNextLevel = LuaDebugger.StepNextLevel-1endLuaDebugger.currentFileName = nil-- endelseif(event == "line") then--print1("line.............................");if(LuaDebugger.StepIn) thenlocal data = debugger_stackInfo(3, LuaDebugger.event.C2S_NextResponse)--挂起等待调试器作出反应LuaDebugger.currentTempFunc = data.funcs[1]coroutine.resume(coro_debugger, data)endif(LuaDebugger.StepNext ) then--print1("stepNext:" .. LuaDebugger.StepNextLevel);if( LuaDebugger.StepNextLevel == 0) thenlocal data = debugger_stackInfo(3, LuaDebugger.event.C2S_NextResponse)--挂起等待调试器作出反应LuaDebugger.currentTempFunc = data.funcs[1]coroutine.resume(coro_debugger, data)returnelseif( LuaDebugger.StepNextLevel < 0) thenResetDebugInfo();LuaDebugger.Run = trueendendlocal stepInfo = nilif(not LuaDebugger.currentFileName) thenstepInfo = getinfo(2,"S")local source = stepInfo.sourceif(source == "=[C]" or source:find(LuaDebugger.DebugLuaFie)) then return endfile = getSource(source);LuaDebugger.currentFileName = fileendfile = LuaDebugger.currentFileName--判断断点local breakInfo = LuaDebugger.breakInfos[file]if(breakInfo) thenprint(">>>有断点信息...")local ischeck = falsefor k, lineInfo in pairs(breakInfo) dolocal lines = lineInfo.linesif(lines and lines[line]) thenischeck = truebreakendendif(not ischeck) then return end--并且在断点中local info = stepInfoif(not info) theninfo = getinfo(2)endlocal hitPathNames = splitFilePath(file)local hitCounts = {}for k, lineInfo in pairs(breakInfo) dolocal lines = lineInfo.lineslocal pathNames = lineInfo.pathNamesif(lines and lines[line]) then--判断路径hitCounts[k] = 0local hitPathNamesCount = # hitPathNameslocal pathNamesCount = # pathNameswhile(true) doif(pathNames[pathNamesCount] ~= hitPathNames[hitPathNamesCount]) thenbreakelsehitCounts[k] = hitCounts[k] + 1endpathNamesCount = pathNamesCount - 1hitPathNamesCount = hitPathNamesCount - 1if(pathNamesCount <= 0 or hitPathNamesCount <= 0) thenbreak;endendendendlocal hitFieName = ""local maxCount = 0for k, v in pairs(hitCounts) doif(v > maxCount) thenmaxCount = vhitFieName = k;endendlocal hitPathNamesLength = #hitPathNamesif(hitPathNamesLength == 1 or(hitPathNamesLength > 1 and maxCount > 1)) thenif(hitFieName ~= "") thenlocal data = debugger_stackInfo(3, LuaDebugger.event.C2S_HITBreakPoint)--挂起等待调试器作出反应coroutine.resume(coro_debugger, data)endendendendendlocal function debugger_xpcall()print1("debugger_xpcall..") ;--调用 coro_debugger 并传入 参数local data = debugger_stackInfo(4, LuaDebugger.event.C2S_HITBreakPoint)--挂起等待调试器作出反应coroutine.resume(coro_debugger, data)end--调试开始local function start()LuaDebugger.DebugLuaFie = getLuaFileName(getinfo(1).source)local socket = createSocket()print(controller_host)print(controller_port)print("controller_host:" .. controller_host);local server = socket.connect(controller_host, controller_port)debug_server = server;if server then--创建breakInfo socketsocket = createSocket()breakInfoSocket = socket.connect(controller_host, controller_port)if(breakInfoSocket) thenbreakInfoSocket:settimeout(0)debugger_sendMsg(breakInfoSocket, LuaDebugger.event.C2S_SetSocketName, {name = "breakPointSocket"})debugger_sendMsg(server, LuaDebugger.event.C2S_SetSocketName, {name = "mainSocket"})xpcall(function()debug.sethook(debug_hook, "lrc")end, function(error)print("error:", error)end)debuglog("sethook and debuger starting.....");local cortRet,errMsg = coroutine.resume(coro_debugger, server)if( not cortRet ) thendebuglog("coroutine excption......:" .. errMsg);else--debuglog("coroutine end......");endendendendfunction StartDebug(host, port)if(not host) thenprint("error host nil")endif(not port) thenprint("error prot nil")endif(type(host) ~= "string") thenprint("error host not string")endif(type(port) ~= "number") thenprint("error host not number")endcontroller_host = hostcontroller_port = portxpcall(start, function(error)-- bodyprint(error)end)return debugger_receiveDebugBreakInfo, debugger_xpcallendreturn StartDebug
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。