leakcheck.lua (1647B)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#! /usr/bin/lua
local lpeg = require( "lpeg" )
local json = require( "cjson.safe" )
-- b_ = begin
-- e_ = end
-- ne_ = not end
-- slc = single line comment
-- mlc = multiline comment
local b_slc = lpeg.P( "//" )
local e_slc = lpeg.P( "\n" )
local ne_slc = ( 1 - e_slc ) ^ 0
local slc = b_slc * ne_slc
local b_mlc = lpeg.P( "/*" )
local e_mlc = lpeg.P( "*/" )
local ne_mlc = ( 1 - e_mlc ) ^ 0
local mlc = b_mlc * ne_mlc * e_mlc
local quote = lpeg.P( "\"" )
local escaped = lpeg.P( "\\" ) * 1
local string = quote * ( escaped + ( 1 - quote ) ) ^ 0 * quote
local comments = slc + mlc
local none = 1 - ( string + comments )
local just_code = ( comments + string + lpeg.C( none ^ 1 ) ) ^ 0
local f = io.open( arg[ 1 ] )
local contents = f:read( "*all" )
local stripped = table.concat( { just_code:match( contents ) } )
local function check_leaks( leaks, levels, depth, body )
for code, block in ( body .. "{}" ):gmatch( "(.-)(%b{})" ) do
if code == "" and block == "{}" then
break
end
for line in code:gmatch( "([^\n]+)" ) do
if line:find( "memarena_push" ) then
if not levels[ depth ] then
table.insert( leaks, line )
end
end
if line:find( "MEMARENA_SCOPED_CHECKPOINT" ) then
levels[ depth ] = true
end
end
if not cp then
levels[ depth + 1 ] = false
check_leaks( leaks, levels, depth + 1, block:sub( 2, -2 ) )
levels[ depth + 1 ] = nil
end
end
end
for ret, name, args, body in stripped:gmatch( "([^\n]-)%s*([^%s]+)(%b())\n? *(%b{})" ) do
local leaks = { }
check_leaks( leaks, { false }, 1, body )
if #leaks > 0 then
print( name )
print( table.concat( leaks, "\n" ) )
end
end
|