]>
Commit | Line | Data |
---|---|---|
a76ab215 JS |
1 | # This work is licensed under the terms of the GNU GPL, version 2 or later. |
2 | # See the COPYING file in the top-level directory. | |
3 | ||
4 | """ | |
5 | QAPI Generator | |
6 | ||
7 | This is the main entry point for generating C code from the QAPI schema. | |
8 | """ | |
9 | ||
10 | import argparse | |
a76ab215 JS |
11 | import sys |
12 | from typing import Optional | |
13 | ||
7137a960 | 14 | from .commands import gen_commands |
e0e8a0ac | 15 | from .common import must_match |
7137a960 JS |
16 | from .error import QAPIError |
17 | from .events import gen_events | |
18 | from .introspect import gen_introspect | |
19 | from .schema import QAPISchema | |
20 | from .types import gen_types | |
21 | from .visit import gen_visit | |
a76ab215 JS |
22 | |
23 | ||
24 | def invalid_prefix_char(prefix: str) -> Optional[str]: | |
e0e8a0ac | 25 | match = must_match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', prefix) |
a76ab215 JS |
26 | if match.end() != len(prefix): |
27 | return prefix[match.end()] | |
28 | return None | |
29 | ||
30 | ||
31 | def generate(schema_file: str, | |
32 | output_dir: str, | |
33 | prefix: str, | |
34 | unmask: bool = False, | |
35 | builtins: bool = False) -> None: | |
36 | """ | |
37 | Generate C code for the given schema into the target directory. | |
38 | ||
39 | :param schema_file: The primary QAPI schema file. | |
40 | :param output_dir: The output directory to store generated code. | |
41 | :param prefix: Optional C-code prefix for symbol names. | |
42 | :param unmask: Expose non-ABI names through introspection? | |
43 | :param builtins: Generate code for built-in types? | |
44 | ||
45 | :raise QAPIError: On failures. | |
46 | """ | |
47 | assert invalid_prefix_char(prefix) is None | |
48 | ||
49 | schema = QAPISchema(schema_file) | |
50 | gen_types(schema, output_dir, prefix, builtins) | |
51 | gen_visit(schema, output_dir, prefix, builtins) | |
52 | gen_commands(schema, output_dir, prefix) | |
53 | gen_events(schema, output_dir, prefix) | |
54 | gen_introspect(schema, output_dir, prefix, unmask) | |
55 | ||
56 | ||
57 | def main() -> int: | |
58 | """ | |
59 | gapi-gen executable entry point. | |
60 | Expects arguments via sys.argv, see --help for details. | |
61 | ||
62 | :return: int, 0 on success, 1 on failure. | |
63 | """ | |
64 | parser = argparse.ArgumentParser( | |
65 | description='Generate code from a QAPI schema') | |
66 | parser.add_argument('-b', '--builtins', action='store_true', | |
67 | help="generate code for built-in types") | |
68 | parser.add_argument('-o', '--output-dir', action='store', | |
69 | default='', | |
70 | help="write output to directory OUTPUT_DIR") | |
71 | parser.add_argument('-p', '--prefix', action='store', | |
72 | default='', | |
73 | help="prefix for symbols") | |
74 | parser.add_argument('-u', '--unmask-non-abi-names', action='store_true', | |
75 | dest='unmask', | |
76 | help="expose non-ABI names in introspection") | |
77 | parser.add_argument('schema', action='store') | |
78 | args = parser.parse_args() | |
79 | ||
80 | funny_char = invalid_prefix_char(args.prefix) | |
81 | if funny_char: | |
82 | msg = f"funny character '{funny_char}' in argument of --prefix" | |
83 | print(f"{sys.argv[0]}: {msg}", file=sys.stderr) | |
84 | return 1 | |
85 | ||
86 | try: | |
87 | generate(args.schema, | |
88 | output_dir=args.output_dir, | |
89 | prefix=args.prefix, | |
90 | unmask=args.unmask, | |
91 | builtins=args.builtins) | |
92 | except QAPIError as err: | |
93 | print(f"{sys.argv[0]}: {str(err)}", file=sys.stderr) | |
94 | return 1 | |
95 | return 0 |