summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2018-07-19 19:48:26 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2018-07-19 19:48:26 +0200
commit7ae9791c59ab4037c9c16a86fe998ef116e0dd10 (patch)
tree53859394e2711cb1458ae2664bf0185bf704fa51 /scripts
parent16515ddc78fce017f3b577f0a58e0f0288d1512e (diff)
scripts/verify_log_statements.py: figure out line numbers
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/verify_log_statements.py74
1 files changed, 61 insertions, 13 deletions
diff --git a/scripts/verify_log_statements.py b/scripts/verify_log_statements.py
index 48f406b..6108c23 100755
--- a/scripts/verify_log_statements.py
+++ b/scripts/verify_log_statements.py
@@ -22,26 +22,57 @@ log_statement_re = re.compile(r'^[ \t]*LOG[_A-Z]+\(([^";,]*,)*[ \t\r\n]*(("[^"]*
re.MULTILINE | re.DOTALL)
fmt_re = re.compile(r'("[^"]*".*)*fmt')
-errors_found = 0
debug = ('-d' in sys.argv) or ('--debug' in sys.argv)
args = [x for x in sys.argv[1:] if not (x == '-d' or x == '--debug')]
if not args:
args = ['.']
+class error_found:
+ def __init__(self, f, charpos, msg, text):
+ self.f = f
+ self.charpos = charpos
+ self.msg = msg
+ self.text = text
+ self.line = None
+
+def make_line_idx(file_content):
+ line_idx = []
+ pos = 0
+ line_nr = 1
+ line_idx.append((pos, line_nr))
+ for line in file_content.split('\n'):
+ pos += len(line)
+ line_nr += 1
+ line_idx.append((pos, line_nr))
+ pos += 1 # newline char
+ return line_idx
+
+def char_pos_2_line(line_idx, sorted_char_positions):
+ r = []
+ line_i = 0
+ next_line_i = 1
+ for char_pos in sorted_char_positions:
+ while (line_i+1) < len(line_idx) and char_pos > line_idx[line_i+1][0]:
+ line_i += 1
+ r.append(line_idx[line_i][1])
+ return r
def check_file(f):
- global errors_found
if not (f.endswith('.h') or f.endswith('.c') or f.endswith('.cpp')):
- return
+ return []
- for log in log_statement_re.finditer(codecs.open(f, "r", "utf-8").read()):
+ errors_found = []
+
+ file_content = codecs.open(f, "r", "utf-8").read()
+
+ for log in log_statement_re.finditer(file_content):
quoted = log.group(2)
# Skip 'LOG("bla" fmt )' strings that typically appear as #defines.
if fmt_re.match(quoted):
if debug:
- print('Skipping define:', f, '\n'+log.group(0))
+ errors_found.append(error_found(f, log.start(), 'Skipping define', log.group(0)))
continue
# Drop PRI* parts of 'LOG("bla %"PRIu64" foo")'
@@ -56,15 +87,14 @@ def check_file(f):
except:
# hopefully eval broke because of some '## args' macro def
if debug:
- print('Ignoring:', f, '\n'+log.group(0))
+ ignored.append(error_found(f, log.start(), 'Ignoring', log.group(0)))
continue
# check for errors...
# final newline
if not quoted.endswith('\n'):
- print('Missing final newline:', f, '\n'+log.group(0))
- errors_found += 1
+ errors_found.append(error_found(f, log.start(), 'Missing final newline', log.group(0)))
# disallowed chars and extra newlines
for c in quoted[:-1]:
@@ -73,15 +103,33 @@ def check_file(f):
msg = 'Extraneous newline'
else:
msg = 'Illegal char'
- print('%s %r in' % (msg, c), f, '\n' + log.group(0))
- errors_found += 1
+ errors_found.append(error_found(f, log.start(), msg + ' %r' % c, log.group(0)))
+
+ if not error_found:
+ return []
+
+ line_idx = make_line_idx(file_content)
+ for r, line in zip(errors_found, char_pos_2_line(line_idx, [rr.charpos for rr in errors_found])):
+ r.line = line
+
+ return errors_found
+
+all_errors_found = []
for f in args:
if os.path.isdir(f):
for parent_path, subdirs, files in os.walk(f, None, None):
for ff in files:
- check_file(os.path.join(parent_path, ff))
+ all_errors_found.extend(check_file(os.path.join(parent_path, ff)))
else:
- check_file(f)
+ all_errors_found.extend(check_file(f))
+
+def print_errors(errs):
+ for err in errs:
+ print('%s: %s:%d\n%s\n' % (err.msg, err.f, err.line or 0, err.text))
+
+print_errors(all_errors_found)
+
+sys.exit(len(all_errors_found))
-sys.exit(errors_found)
+# vim: tabstop=2 shiftwidth=2 expandtab