qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

converter.py (4378B)


      1 #!/usr/bin/env python3
      2 # QEMU library
      3 #
      4 # Copyright (C) 2020 Red Hat Inc.
      5 #
      6 # Authors:
      7 #  Eduardo Habkost <ehabkost@redhat.com>
      8 #
      9 # This work is licensed under the terms of the GNU GPL, version 2.  See
     10 # the COPYING file in the top-level directory.
     11 #
     12 import sys
     13 import argparse
     14 import os
     15 import os.path
     16 import re
     17 from typing import *
     18 
     19 from codeconverter.patching import FileInfo, match_class_dict, FileList
     20 import codeconverter.qom_macros
     21 from codeconverter.qom_type_info import TI_FIELDS, type_infos, TypeInfoVar
     22 
     23 import logging
     24 logger = logging.getLogger(__name__)
     25 DBG = logger.debug
     26 INFO = logger.info
     27 WARN = logger.warning
     28 
     29 def process_all_files(parser: argparse.ArgumentParser, args: argparse.Namespace) -> None:
     30     DBG("filenames: %r", args.filenames)
     31 
     32     files = FileList()
     33     files.extend(FileInfo(files, fn, args.force) for fn in args.filenames)
     34     for f in files:
     35         DBG('opening %s', f.filename)
     36         f.load()
     37 
     38     if args.table:
     39         fields = ['filename', 'variable_name'] + TI_FIELDS
     40         print('\t'.join(fields))
     41         for f in files:
     42             for t in f.matches_of_type(TypeInfoVar):
     43                 assert isinstance(t, TypeInfoVar)
     44                 values = [f.filename, t.name] + \
     45                          [t.get_raw_initializer_value(f)
     46                           for f in TI_FIELDS]
     47                 DBG('values: %r', values)
     48                 assert all('\t' not in v for v in values)
     49                 values = [v.replace('\n', ' ').replace('"', '') for v in values]
     50                 print('\t'.join(values))
     51         return
     52 
     53     match_classes = match_class_dict()
     54     if not args.patterns:
     55         parser.error("--pattern is required")
     56 
     57     classes = [p for arg in args.patterns
     58                for p in re.split(r'[\s,]', arg)
     59                if p.strip()]
     60     for c in classes:
     61         if c not in match_classes \
     62            or not match_classes[c].regexp:
     63             print("Invalid pattern name: %s" % (c), file=sys.stderr)
     64             print("Valid patterns:", file=sys.stderr)
     65             print(PATTERN_HELP, file=sys.stderr)
     66             sys.exit(1)
     67 
     68     DBG("classes: %r", classes)
     69     files.patch_content(max_passes=args.passes, class_names=classes)
     70 
     71     for f in files:
     72         #alltypes.extend(f.type_infos)
     73         #full_types.extend(f.full_types())
     74 
     75         if not args.dry_run:
     76             if args.inplace:
     77                 f.patch_inplace()
     78             if args.diff:
     79                 f.show_diff()
     80             if not args.diff and not args.inplace:
     81                 f.write_to_file(sys.stdout)
     82                 sys.stdout.flush()
     83 
     84 
     85 PATTERN_HELP = ('\n'.join("  %s: %s" % (n, str(c.__doc__).strip())
     86                 for (n,c) in sorted(match_class_dict().items())
     87                 if c.has_replacement_rule()))
     88 
     89 def main() -> None:
     90     p = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
     91     p.add_argument('filenames', nargs='+')
     92     p.add_argument('--passes', type=int, default=1,
     93                    help="Number of passes (0 means unlimited)")
     94     p.add_argument('--pattern', required=True, action='append',
     95                    default=[], dest='patterns',
     96                    help="Pattern to scan for")
     97     p.add_argument('--inplace', '-i', action='store_true',
     98                    help="Patch file in place")
     99     p.add_argument('--dry-run', action='store_true',
    100                    help="Don't patch files or print patching results")
    101     p.add_argument('--force', '-f', action='store_true',
    102                    help="Perform changes even if not completely safe")
    103     p.add_argument('--diff', action='store_true',
    104                    help="Print diff output on stdout")
    105     p.add_argument('--debug', '-d', action='store_true',
    106                    help="Enable debugging")
    107     p.add_argument('--verbose', '-v', action='store_true',
    108                    help="Verbose logging on stderr")
    109     p.add_argument('--table', action='store_true',
    110                    help="Print CSV table of type information")
    111     p.add_argument_group("Valid pattern names",
    112                          PATTERN_HELP)
    113     args = p.parse_args()
    114 
    115     loglevel = (logging.DEBUG if args.debug
    116              else logging.INFO if args.verbose
    117              else logging.WARN)
    118     logging.basicConfig(format='%(levelname)s: %(message)s', level=loglevel)
    119     DBG("args: %r", args)
    120     process_all_files(p, args)
    121 
    122 if __name__ == '__main__':
    123     main()