1#!/usr/bin/env python3
2#
3# This library is free software; you can redistribute it and/or
4# modify it under the terms of the GNU Lesser General Public
5# License as published by the Free Software Foundation; either
6# version 2.1 of the License, or (at your option) any later version.
7#
8# This library is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11# Lesser General Public License for more details.
12#
13# You should have received a copy of the GNU Lesser General Public
14# License along with this library.  If not, see
15# <http://www.gnu.org/licenses/>.
16#
17#
18# Regroup array values into smaller groups separated by numbered comments.
19#
20# If --check is the first parameter, the script will return
21# a non-zero value if a file is not grouped correctly.
22# Otherwise the files are regrouped in place.
23
24import argparse
25import re
26import subprocess
27import sys
28
29
30def load_caps_flags(filename, start_regex, end_regex):
31    capsflags = []
32    game_on = False
33
34    with open(filename, "r") as fh:
35        for line in fh:
36            line = line.rstrip("\n")
37            if game_on:
38                if re.search(r'''.*/\* [0-9]+ \*/.*''', line):
39                    continue
40                if re.search(r'''^\s*$''', line):
41                    continue
42                match = re.search(r'''[ ]+([A-Z0-9_]+)''', line)
43
44                if match:
45                    capsflags.append(match[1])
46
47            if re.search(start_regex, line):
48                game_on = True
49            elif game_on and re.search(end_regex, line):
50                game_on = False
51
52    return capsflags
53
54
55def regroup_caps(check, filename, start_regex, end_regex,
56                 trailing_newline, counter_prefix, capsflags):
57    step = 5
58
59    original = []
60    with open(filename, "r") as fh:
61        for line in fh:
62            original.append(line)
63
64    fixed = []
65    game_on = False
66    counter = 0
67    for line in original:
68        line = line.rstrip("\n")
69        if game_on:
70            if re.search(r'''.*/\* [0-9]+ \*/.*''', line):
71                continue
72            if re.search(r'''^\s*$''', line):
73                continue
74            if counter % step == 0:
75                if counter != 0:
76                    fixed.append("\n")
77                fixed.append("%s/* %d */\n" % (counter_prefix, counter))
78
79            if not (line.find("/*") != -1 and line.find("*/") == -1):
80                # count two-line comments as one line
81                counter = counter + 1
82
83        if re.search(start_regex, line):
84            game_on = True
85        elif game_on and re.search(end_regex, line):
86            if (counter - 1) % step == 0:
87                fixed = fixed[:-1]  # /* $counter */
88                if counter != 1:
89                    fixed = fixed[:-1]  # \n
90
91            if trailing_newline:
92                fixed.append("\n")
93
94            game_on = False
95
96        # ensure that flag names in the .c file have the correct flag in the comment
97        if game_on and capsflags:
98            flagname = re.search(r'''.*".*",''', line)
99            if flagname:
100                line = flagname[0] + " /* %s */" % capsflags[counter - 1]
101
102        fixed.append(line + "\n")
103
104    if check:
105        orig = "".join(original)
106        new = "".join(fixed)
107        if new != orig:
108            diff = subprocess.Popen(["diff", "-u", filename, "-"],
109                                    stdin=subprocess.PIPE)
110            diff.communicate(input=new.encode('utf-8'))
111
112            print("Incorrect line wrapping in '%s'" %
113                  filename, file=sys.stderr)
114            print("Use group-qemu-caps.py to generate data files",
115                  file=sys.stderr)
116            return False
117    else:
118        with open(filename, "w") as fh:
119            for line in fixed:
120                print(line, file=fh, end='')
121
122    return True
123
124
125parser = argparse.ArgumentParser(description='QEMU capabilities group formatter')
126parser.add_argument('--check', action="store_true",
127                    help='check existing files only')
128parser.add_argument('--prefix', default='',
129                    help='source code tree prefix')
130args = parser.parse_args()
131
132errs = False
133
134capsflags = load_caps_flags(args.prefix + 'src/qemu/qemu_capabilities.h',
135                            r'virQEMUCapsFlags grouping marker',
136                            r'QEMU_CAPS_LAST \/\* this must')
137
138if not regroup_caps(args.check,
139                    args.prefix + 'src/qemu/qemu_capabilities.c',
140                    r'virQEMUCaps grouping marker',
141                    r'\);',
142                    0,
143                    "              ",
144                    capsflags):
145    errs = True
146
147if not regroup_caps(args.check,
148                    args.prefix + 'src/qemu/qemu_capabilities.h',
149                    r'virQEMUCapsFlags grouping marker',
150                    r'QEMU_CAPS_LAST \/\* this must',
151                    1,
152                    "    ",
153                    None):
154    errs = True
155
156if errs:
157    sys.exit(1)
158sys.exit(0)
159