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 |