1import subprocess
2import sys
3import shlex
4import os
5import re
6
7os.environ['LC_ALL'] = 'C'
8os.environ['LANG'] = 'C'
9for k in list(os.environ.keys()):
10    if k.startswith('LC_'):
11        os.environ.pop(k)
12
13if len(sys.argv) < 2:
14    sys.stderr.write('start as format-test.py gcc-123.45 [-options ...]\n')
15    sys.exit(1)
16
17c_re = re.compile(r'//\s+(NO)?WARN')
18expect = {}
19lines = {}
20
21with open('format-test.c', 'r') as fd:
22    for lno, line in enumerate(fd.readlines(), 1):
23        lines[lno] = line.strip()
24        m = c_re.search(line)
25        if m is None:
26            continue
27        if m.group(1) is None:
28            expect[lno] = 'warn'
29        else:
30            expect[lno] = 'nowarn'
31
32cmd = shlex.split('-Wall -Wextra -Wno-unused -fplugin=./frr-format.so -fno-diagnostics-show-caret -c -o format-test.o format-test.c')
33
34gcc = subprocess.Popen(sys.argv[1:] + cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
35sout, serr = gcc.communicate()
36gcc.wait()
37
38gcclines = serr.decode('UTF-8').splitlines()
39line_re = re.compile(r'^format-test\.c:(\d+):(.*)$')
40gcc_warns = {}
41
42for line in gcclines:
43    if line.find('In function') >= 0:
44        continue
45    m = line_re.match(line)
46    if m is None:
47        sys.stderr.write('cannot process GCC output: %s\n' % line)
48        continue
49
50    lno = int(m.group(1))
51    gcc_warns.setdefault(lno, []).append(line)
52
53for lno, val in expect.items():
54    if val == 'nowarn' and lno in gcc_warns:
55        sys.stderr.write('unexpected gcc warning on line %d:\n\t%s\n\t%s\n' % (lno, lines[lno], '\n\t'.join(gcc_warns[lno])))
56    if val == 'warn' and lno not in gcc_warns:
57        sys.stderr.write('expected warning on line %d but did not get one\n\t%s\n' % (lno, lines[lno]))
58
59leftover = set(gcc_warns.keys()) - set(expect.keys())
60for lno in sorted(leftover):
61    sys.stderr.write('unmarked gcc warning on line %d:\n\t%s\n\t%s\n' % (lno, lines[lno], '\n\t'.join(gcc_warns[lno])))
62