2
0

main.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. QAPI Generator
  5. This is the main entry point for generating C code from the QAPI schema.
  6. """
  7. import argparse
  8. import sys
  9. from typing import Optional
  10. from .commands import gen_commands
  11. from .common import must_match
  12. from .error import QAPIError
  13. from .events import gen_events
  14. from .features import gen_features
  15. from .introspect import gen_introspect
  16. from .schema import QAPISchema
  17. from .types import gen_types
  18. from .visit import gen_visit
  19. def invalid_prefix_char(prefix: str) -> Optional[str]:
  20. match = must_match(r'([A-Za-z_.-][A-Za-z0-9_.-]*)?', prefix)
  21. if match.end() != len(prefix):
  22. return prefix[match.end()]
  23. return None
  24. def generate(schema_file: str,
  25. output_dir: str,
  26. prefix: str,
  27. unmask: bool = False,
  28. builtins: bool = False,
  29. gen_tracing: bool = False) -> None:
  30. """
  31. Generate C code for the given schema into the target directory.
  32. :param schema_file: The primary QAPI schema file.
  33. :param output_dir: The output directory to store generated code.
  34. :param prefix: Optional C-code prefix for symbol names.
  35. :param unmask: Expose non-ABI names through introspection?
  36. :param builtins: Generate code for built-in types?
  37. :raise QAPIError: On failures.
  38. """
  39. assert invalid_prefix_char(prefix) is None
  40. schema = QAPISchema(schema_file)
  41. gen_types(schema, output_dir, prefix, builtins)
  42. gen_features(schema, output_dir, prefix)
  43. gen_visit(schema, output_dir, prefix, builtins)
  44. gen_commands(schema, output_dir, prefix, gen_tracing)
  45. gen_events(schema, output_dir, prefix)
  46. gen_introspect(schema, output_dir, prefix, unmask)
  47. def main() -> int:
  48. """
  49. gapi-gen executable entry point.
  50. Expects arguments via sys.argv, see --help for details.
  51. :return: int, 0 on success, 1 on failure.
  52. """
  53. parser = argparse.ArgumentParser(
  54. description='Generate code from a QAPI schema')
  55. parser.add_argument('-b', '--builtins', action='store_true',
  56. help="generate code for built-in types")
  57. parser.add_argument('-o', '--output-dir', action='store',
  58. default='',
  59. help="write output to directory OUTPUT_DIR")
  60. parser.add_argument('-p', '--prefix', action='store',
  61. default='',
  62. help="prefix for symbols")
  63. parser.add_argument('-u', '--unmask-non-abi-names', action='store_true',
  64. dest='unmask',
  65. help="expose non-ABI names in introspection")
  66. # Option --suppress-tracing exists so we can avoid solving build system
  67. # problems. TODO Drop it when we no longer need it.
  68. parser.add_argument('--suppress-tracing', action='store_true',
  69. help="suppress adding trace events to qmp marshals")
  70. parser.add_argument('schema', action='store')
  71. args = parser.parse_args()
  72. funny_char = invalid_prefix_char(args.prefix)
  73. if funny_char:
  74. msg = f"funny character '{funny_char}' in argument of --prefix"
  75. print(f"{sys.argv[0]}: {msg}", file=sys.stderr)
  76. return 1
  77. try:
  78. generate(args.schema,
  79. output_dir=args.output_dir,
  80. prefix=args.prefix,
  81. unmask=args.unmask,
  82. builtins=args.builtins,
  83. gen_tracing=not args.suppress_tracing)
  84. except QAPIError as err:
  85. print(err, file=sys.stderr)
  86. return 1
  87. return 0