Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
qapi-gen: Separate arg-parsing from generation
This is a minor re-work of the entrypoint script. It isolates a generate() method from the actual command-line mechanism. Signed-off-by: John Snow <jsnow@redhat.com> Reviewed-by: Eduardo Habkost <ehabkost@redhat.com> Reviewed-by: Cleber Rosa <crosa@redhat.com> Tested-by: Cleber Rosa <crosa@redhat.com> Message-Id: <20201009161558.107041-4-jsnow@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [invalid_char() renamed to invalid_prefix_char()] Signed-off-by: Markus Armbruster <armbru@redhat.com>
- Loading branch information
Showing
1 changed file
with
67 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,101 @@ | ||
#!/usr/bin/env python3 | ||
# QAPI generator | ||
# | ||
|
||
# This work is licensed under the terms of the GNU GPL, version 2 or later. | ||
# See the COPYING file in the top-level directory. | ||
|
||
""" | ||
QAPI Generator | ||
This is the main entry point for generating C code from the QAPI schema. | ||
""" | ||
|
||
import argparse | ||
import re | ||
import sys | ||
from typing import Optional | ||
|
||
from qapi.commands import gen_commands | ||
from qapi.error import QAPIError | ||
from qapi.events import gen_events | ||
from qapi.introspect import gen_introspect | ||
from qapi.schema import QAPIError, QAPISchema | ||
from qapi.schema import QAPISchema | ||
from qapi.types import gen_types | ||
from qapi.visit import gen_visit | ||
|
||
|
||
def main(argv): | ||
def invalid_prefix_char(prefix: str) -> Optional[str]: | ||
match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', prefix) | ||
if match.end() != len(prefix): | ||
return prefix[match.end()] | ||
return None | ||
|
||
|
||
def generate(schema_file: str, | ||
output_dir: str, | ||
prefix: str, | ||
unmask: bool = False, | ||
builtins: bool = False) -> None: | ||
""" | ||
Generate C code for the given schema into the target directory. | ||
:param schema_file: The primary QAPI schema file. | ||
:param output_dir: The output directory to store generated code. | ||
:param prefix: Optional C-code prefix for symbol names. | ||
:param unmask: Expose non-ABI names through introspection? | ||
:param builtins: Generate code for built-in types? | ||
:raise QAPIError: On failures. | ||
""" | ||
assert invalid_prefix_char(prefix) is None | ||
|
||
schema = QAPISchema(schema_file) | ||
gen_types(schema, output_dir, prefix, builtins) | ||
gen_visit(schema, output_dir, prefix, builtins) | ||
gen_commands(schema, output_dir, prefix) | ||
gen_events(schema, output_dir, prefix) | ||
gen_introspect(schema, output_dir, prefix, unmask) | ||
|
||
|
||
def main() -> int: | ||
""" | ||
gapi-gen executable entry point. | ||
Expects arguments via sys.argv, see --help for details. | ||
:return: int, 0 on success, 1 on failure. | ||
""" | ||
parser = argparse.ArgumentParser( | ||
description='Generate code from a QAPI schema') | ||
parser.add_argument('-b', '--builtins', action='store_true', | ||
help="generate code for built-in types") | ||
parser.add_argument('-o', '--output-dir', action='store', default='', | ||
parser.add_argument('-o', '--output-dir', action='store', | ||
default='', | ||
help="write output to directory OUTPUT_DIR") | ||
parser.add_argument('-p', '--prefix', action='store', default='', | ||
parser.add_argument('-p', '--prefix', action='store', | ||
default='', | ||
help="prefix for symbols") | ||
parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', | ||
dest='unmask', | ||
help="expose non-ABI names in introspection") | ||
parser.add_argument('schema', action='store') | ||
args = parser.parse_args() | ||
|
||
match = re.match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', args.prefix) | ||
if match.end() != len(args.prefix): | ||
print("%s: 'funny character '%s' in argument of --prefix" | ||
% (sys.argv[0], args.prefix[match.end()]), | ||
file=sys.stderr) | ||
sys.exit(1) | ||
funny_char = invalid_prefix_char(args.prefix) | ||
if funny_char: | ||
msg = f"funny character '{funny_char}' in argument of --prefix" | ||
print(f"{sys.argv[0]}: {msg}", file=sys.stderr) | ||
return 1 | ||
|
||
try: | ||
schema = QAPISchema(args.schema) | ||
generate(args.schema, | ||
output_dir=args.output_dir, | ||
prefix=args.prefix, | ||
unmask=args.unmask, | ||
builtins=args.builtins) | ||
except QAPIError as err: | ||
print(err, file=sys.stderr) | ||
exit(1) | ||
|
||
gen_types(schema, args.output_dir, args.prefix, args.builtins) | ||
gen_visit(schema, args.output_dir, args.prefix, args.builtins) | ||
gen_commands(schema, args.output_dir, args.prefix) | ||
gen_events(schema, args.output_dir, args.prefix) | ||
gen_introspect(schema, args.output_dir, args.prefix, args.unmask) | ||
print(f"{sys.argv[0]}: {str(err)}", file=sys.stderr) | ||
return 1 | ||
return 0 | ||
|
||
|
||
if __name__ == '__main__': | ||
main(sys.argv) | ||
sys.exit(main()) |