xref: /qemu/scripts/feature_to_c.py (revision 19f9c044)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0-or-later
3
4import os, sys, xml.etree.ElementTree
5
6def writeliteral(indent, bytes):
7    sys.stdout.write(' ' * indent)
8    sys.stdout.write('"')
9    quoted = True
10
11    for c in bytes:
12        if not quoted:
13            sys.stdout.write('\n')
14            sys.stdout.write(' ' * indent)
15            sys.stdout.write('"')
16            quoted = True
17
18        if c == b'"'[0]:
19            sys.stdout.write('\\"')
20        elif c == b'\\'[0]:
21            sys.stdout.write('\\\\')
22        elif c == b'\n'[0]:
23            sys.stdout.write('\\n"')
24            quoted = False
25        elif c >= 32 and c < 127:
26            sys.stdout.write(c.to_bytes(1, 'big').decode())
27        else:
28            sys.stdout.write(f'\{c:03o}')
29
30    if quoted:
31        sys.stdout.write('"')
32
33sys.stdout.write('#include "qemu/osdep.h"\n' \
34                 '#include "exec/gdbstub.h"\n' \
35                 '\n'
36                 'const GDBFeature gdb_static_features[] = {\n')
37
38for input in sys.argv[1:]:
39    with open(input, 'rb') as file:
40        read = file.read()
41
42    parser = xml.etree.ElementTree.XMLPullParser(['start', 'end'])
43    parser.feed(read)
44    events = parser.read_events()
45    event, element = next(events)
46    if event != 'start':
47        sys.stderr.write(f'unexpected event: {event}\n')
48        exit(1)
49    if element.tag != 'feature':
50        sys.stderr.write(f'unexpected start tag: {element.tag}\n')
51        exit(1)
52
53    feature_name = element.attrib['name']
54    regnum = 0
55    regnames = []
56    regnums = []
57    tags = ['feature']
58    for event, element in events:
59        if event == 'end':
60            if element.tag != tags[len(tags) - 1]:
61                sys.stderr.write(f'unexpected end tag: {element.tag}\n')
62                exit(1)
63
64            tags.pop()
65            if element.tag == 'feature':
66                break
67        elif event == 'start':
68            if len(tags) < 2 and element.tag == 'reg':
69                if 'regnum' in element.attrib:
70                    regnum = int(element.attrib['regnum'])
71
72                regnames.append(element.attrib['name'])
73                regnums.append(regnum)
74                regnum += 1
75
76            tags.append(element.tag)
77        else:
78            raise Exception(f'unexpected event: {event}\n')
79
80    if len(tags):
81        sys.stderr.write('unterminated feature tag\n')
82        exit(1)
83
84    base_reg = min(regnums)
85    num_regs = max(regnums) - base_reg + 1 if len(regnums) else 0
86
87    sys.stdout.write('    {\n')
88    writeliteral(8, bytes(os.path.basename(input), 'utf-8'))
89    sys.stdout.write(',\n')
90    writeliteral(8, read)
91    sys.stdout.write(',\n')
92    writeliteral(8, bytes(feature_name, 'utf-8'))
93    sys.stdout.write(',\n        (const char * const []) {\n')
94
95    for index, regname in enumerate(regnames):
96        sys.stdout.write(f'            [{regnums[index] - base_reg}] =\n')
97        writeliteral(16, bytes(regname, 'utf-8'))
98        sys.stdout.write(',\n')
99
100    sys.stdout.write(f'        }},\n        {num_regs},\n    }},\n')
101
102sys.stdout.write('    { NULL }\n};\n')
103