xemu/scripts/codeconverter/converter.py
Eduardo Habkost 4a15e5bef8 scripts/codeconverter: Update to latest version
I'm not documenting every single change in the codeconverter
script because most of that code will be deleted once we finish
the QOM code conversion.  This patch updates the script to the
latest version that was used to perform changes in the QOM code.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20200916182519.415636-2-ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2020-09-18 14:12:32 -04:00

123 lines
4.3 KiB
Python
Executable File

#!/usr/bin/env python3
# QEMU library
#
# Copyright (C) 2020 Red Hat Inc.
#
# Authors:
# Eduardo Habkost <ehabkost@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
#
import sys
import argparse
import os
import os.path
import re
from typing import *
from codeconverter.patching import FileInfo, match_class_dict, FileList
import codeconverter.qom_macros
from codeconverter.qom_type_info import TI_FIELDS, type_infos, TypeInfoVar
import logging
logger = logging.getLogger(__name__)
DBG = logger.debug
INFO = logger.info
WARN = logger.warning
def process_all_files(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None:
DBG("filenames: %r", args.filenames)
files = FileList()
files.extend(FileInfo(files, fn, args.force) for fn in args.filenames)
for f in files:
DBG('opening %s', f.filename)
f.load()
if args.table:
fields = ['filename', 'variable_name'] + TI_FIELDS
print('\t'.join(fields))
for f in files:
for t in f.matches_of_type(TypeInfoVar):
assert isinstance(t, TypeInfoVar)
values = [f.filename, t.name] + \
[t.get_raw_initializer_value(f)
for f in TI_FIELDS]
DBG('values: %r', values)
assert all('\t' not in v for v in values)
values = [v.replace('\n', ' ').replace('"', '') for v in values]
print('\t'.join(values))
return
match_classes = match_class_dict()
if not args.patterns:
parser.error("--pattern is required")
classes = [p for arg in args.patterns
for p in re.split(r'[\s,]', arg)
if p.strip()]
for c in classes:
if c not in match_classes \
or not match_classes[c].regexp:
print("Invalid pattern name: %s" % (c), file=sys.stderr)
print("Valid patterns:", file=sys.stderr)
print(PATTERN_HELP, file=sys.stderr)
sys.exit(1)
DBG("classes: %r", classes)
files.patch_content(max_passes=args.passes, class_names=classes)
for f in files:
#alltypes.extend(f.type_infos)
#full_types.extend(f.full_types())
if not args.dry_run:
if args.inplace:
f.patch_inplace()
if args.diff:
f.show_diff()
if not args.diff and not args.inplace:
f.write_to_file(sys.stdout)
sys.stdout.flush()
PATTERN_HELP = ('\n'.join(" %s: %s" % (n, str(c.__doc__).strip())
for (n,c) in sorted(match_class_dict().items())
if c.has_replacement_rule()))
def main() -> None:
p = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
p.add_argument('filenames', nargs='+')
p.add_argument('--passes', type=int, default=1,
help="Number of passes (0 means unlimited)")
p.add_argument('--pattern', required=True, action='append',
default=[], dest='patterns',
help="Pattern to scan for")
p.add_argument('--inplace', '-i', action='store_true',
help="Patch file in place")
p.add_argument('--dry-run', action='store_true',
help="Don't patch files or print patching results")
p.add_argument('--force', '-f', action='store_true',
help="Perform changes even if not completely safe")
p.add_argument('--diff', action='store_true',
help="Print diff output on stdout")
p.add_argument('--debug', '-d', action='store_true',
help="Enable debugging")
p.add_argument('--verbose', '-v', action='store_true',
help="Verbose logging on stderr")
p.add_argument('--table', action='store_true',
help="Print CSV table of type information")
p.add_argument_group("Valid pattern names",
PATTERN_HELP)
args = p.parse_args()
loglevel = (logging.DEBUG if args.debug
else logging.INFO if args.verbose
else logging.WARN)
logging.basicConfig(format='%(levelname)s: %(message)s', level=loglevel)
DBG("args: %r", args)
process_all_files(p, args)
if __name__ == '__main__':
main()