1#!/usr/bin/env python3 2 3# 2017, Georg Sauthoff <mail@gms.tf>, GPLv3 4 5import sys 6 7def skip_comments(lines): 8 state = 0 9 for line in lines: 10 n = len(line) 11 l = '' 12 p = 0 13 while p < n: 14 if state == 0: 15 a = line.find('//', p) 16 b = line.find('/*', p) 17 if a > -1 and (a < b or b == -1): 18 l += line[p:a] 19 p = n 20 elif b > -1 and (b < a or a == -1): 21 l += line[p:b] 22 p = b+2 23 state = 1 24 else: 25 l += line[p:] 26 p = n 27 elif state == 1: 28 a = line.rfind('*/', p) 29 if a == -1: 30 p = n 31 else: 32 p = a + 2 33 state = 0 34 yield l 35 36def cond_lines(lines): 37 state = 0 38 pcnt = 0 39 for nr, line in enumerate(lines, 1): 40 if not line: 41 continue 42 n = len(line) 43 p = 0 44 do_yield = False 45 while p < n: 46 if state == 0: 47 p = line.find('if', p) 48 if p == -1: 49 p = n 50 continue 51 if (p == 0 or not line[p-1].isalpha()) \ 52 and (p+2 == len(line) or not line[p+2].isalpha()): 53 do_yield = True 54 state = 1 55 p += 2 56 elif state == 1: 57 do_yield = True 58 p = line.find('(', p) 59 if p == -1: 60 p = n 61 else: 62 p += 1 63 state = 2 64 pcnt = 1 65 elif state == 2: 66 do_yield = True 67 for p in range(p, n): 68 if line[p] == '(': 69 pcnt += 1 70 elif line[p] == ')': 71 pcnt -= 1 72 if not pcnt: 73 state = 0 74 break 75 p += 1 76 if do_yield: 77 yield nr 78 79def cond_lines_from_file(filename): 80 with open(filename) as f: 81 yield from cond_lines(skip_comments(f)) 82 83def filter_lcov_trace(lines): 84 nrs = set() 85 for line in lines: 86 if line.startswith('SF:'): 87 nrs = set(cond_lines_from_file(line[3:-1])) 88 elif line.startswith('BRDA:'): 89 xs = line[5:].split(',') 90 nr = int(xs[0]) if xs else 0 91 if nr not in nrs: 92 continue 93 yield line 94 95def filter_lcov_trace_file(s_filename, d_file): 96 with open(s_filename) as f: 97 for l in filter_lcov_trace(f): 98 print(l, end='', file=d_file) 99 100if __name__ == '__main__': 101 #for l in cond_lines_from_file(sys.argv[1]): 102 # print(l) 103 104 filter_lcov_trace_file(sys.argv[1], sys.stdout) 105 106 #with open(sys.argv[1]) as f: 107 # for l in skip_comments(f): 108 # print(l) 109 110