qapi-types.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. #
  2. # QAPI types generator
  3. #
  4. # Copyright IBM, Corp. 2011
  5. # Copyright (c) 2013-2015 Red Hat Inc.
  6. #
  7. # Authors:
  8. # Anthony Liguori <aliguori@us.ibm.com>
  9. # Markus Armbruster <armbru@redhat.com>
  10. #
  11. # This work is licensed under the terms of the GNU GPL, version 2.
  12. # See the COPYING file in the top-level directory.
  13. from qapi import *
  14. def gen_fwd_object_or_array(name):
  15. return mcgen('''
  16. typedef struct %(name)s %(name)s;
  17. ''',
  18. name=c_name(name))
  19. def gen_array(name, element_type):
  20. return mcgen('''
  21. struct %(name)s {
  22. union {
  23. %(c_type)s value;
  24. uint64_t padding;
  25. };
  26. struct %(name)s *next;
  27. };
  28. ''',
  29. name=c_name(name), c_type=element_type.c_type())
  30. def gen_struct_field(name, typ, optional):
  31. ret = ''
  32. if optional:
  33. ret += mcgen('''
  34. bool has_%(c_name)s;
  35. ''',
  36. c_name=c_name(name))
  37. ret += mcgen('''
  38. %(c_type)s %(c_name)s;
  39. ''',
  40. c_type=typ.c_type(), c_name=c_name(name))
  41. return ret
  42. def generate_struct_fields(members):
  43. ret = ''
  44. for memb in members:
  45. ret += gen_struct_field(memb.name, memb.type, memb.optional)
  46. return ret
  47. def gen_struct(name, base, members):
  48. ret = mcgen('''
  49. struct %(name)s {
  50. ''',
  51. name=c_name(name))
  52. if base:
  53. ret += gen_struct_field('base', base, False)
  54. ret += generate_struct_fields(members)
  55. # Make sure that all structs have at least one field; this avoids
  56. # potential issues with attempting to malloc space for zero-length structs
  57. # in C, and also incompatibility with C++ (where an empty struct is size 1).
  58. if not base and not members:
  59. ret += mcgen('''
  60. char qapi_dummy_field_for_empty_struct;
  61. ''')
  62. ret += mcgen('''
  63. };
  64. ''')
  65. return ret
  66. def generate_enum_lookup(name, values, prefix=None):
  67. ret = mcgen('''
  68. const char *const %(name)s_lookup[] = {
  69. ''',
  70. name=c_name(name))
  71. for value in values:
  72. index = c_enum_const(name, value, prefix)
  73. ret += mcgen('''
  74. [%(index)s] = "%(value)s",
  75. ''',
  76. index = index, value = value)
  77. max_index = c_enum_const(name, 'MAX', prefix)
  78. ret += mcgen('''
  79. [%(max_index)s] = NULL,
  80. };
  81. ''',
  82. max_index=max_index)
  83. return ret
  84. def generate_enum(name, values, prefix=None):
  85. name = c_name(name)
  86. lookup_decl = mcgen('''
  87. extern const char *const %(name)s_lookup[];
  88. ''',
  89. name=name)
  90. enum_decl = mcgen('''
  91. typedef enum %(name)s {
  92. ''',
  93. name=name)
  94. # append automatically generated _MAX value
  95. enum_values = values + [ 'MAX' ]
  96. i = 0
  97. for value in enum_values:
  98. enum_full_value = c_enum_const(name, value, prefix)
  99. enum_decl += mcgen('''
  100. %(enum_full_value)s = %(i)d,
  101. ''',
  102. enum_full_value = enum_full_value,
  103. i=i)
  104. i += 1
  105. enum_decl += mcgen('''
  106. } %(name)s;
  107. ''',
  108. name=name)
  109. return enum_decl + lookup_decl
  110. def gen_alternate_qtypes_decl(name):
  111. return mcgen('''
  112. extern const int %(c_name)s_qtypes[];
  113. ''',
  114. c_name=c_name(name))
  115. def gen_alternate_qtypes(name, variants):
  116. ret = mcgen('''
  117. const int %(name)s_qtypes[QTYPE_MAX] = {
  118. ''',
  119. name=c_name(name))
  120. for var in variants.variants:
  121. qtype = var.type.alternate_qtype()
  122. assert qtype
  123. ret += mcgen('''
  124. [%(qtype)s] = %(enum_const)s,
  125. ''',
  126. qtype = qtype,
  127. enum_const=c_enum_const(variants.tag_member.type.name,
  128. var.name))
  129. ret += mcgen('''
  130. };
  131. ''')
  132. return ret
  133. def gen_union(name, base, variants):
  134. name = c_name(name)
  135. ret = mcgen('''
  136. struct %(name)s {
  137. ''',
  138. name=name)
  139. if base:
  140. ret += mcgen('''
  141. /* Members inherited from %(c_name)s: */
  142. ''',
  143. c_name=c_name(base.name))
  144. ret += generate_struct_fields(base.members)
  145. ret += mcgen('''
  146. /* Own members: */
  147. ''')
  148. else:
  149. ret += mcgen('''
  150. %(discriminator_type_name)s kind;
  151. ''',
  152. discriminator_type_name=c_name(variants.tag_member.type.name))
  153. # FIXME: What purpose does data serve, besides preventing a union that
  154. # has a branch named 'data'? We use it in qapi-visit.py to decide
  155. # whether to bypass the switch statement if visiting the discriminator
  156. # failed; but since we 0-initialize structs, and cannot tell what
  157. # branch of the union is in use if the discriminator is invalid, there
  158. # should not be any data leaks even without a data pointer. Or, if
  159. # 'data' is merely added to guarantee we don't have an empty union,
  160. # shouldn't we enforce that at .json parse time?
  161. ret += mcgen('''
  162. union { /* union tag is @%(c_name)s */
  163. void *data;
  164. ''',
  165. # TODO ugly special case for simple union
  166. # Use same tag name in C as on the wire to get rid of
  167. # it, then: c_name=c_name(variants.tag_member.name)
  168. c_name=c_name(variants.tag_name or 'kind'))
  169. for var in variants.variants:
  170. # Ugly special case for simple union TODO get rid of it
  171. typ = var.simple_union_type() or var.type
  172. ret += mcgen('''
  173. %(c_type)s %(c_name)s;
  174. ''',
  175. c_type=typ.c_type(),
  176. c_name=c_name(var.name))
  177. ret += mcgen('''
  178. };
  179. };
  180. ''')
  181. return ret
  182. def generate_type_cleanup_decl(name):
  183. ret = mcgen('''
  184. void qapi_free_%(name)s(%(name)s *obj);
  185. ''',
  186. name=c_name(name))
  187. return ret
  188. def generate_type_cleanup(name):
  189. ret = mcgen('''
  190. void qapi_free_%(name)s(%(name)s *obj)
  191. {
  192. QapiDeallocVisitor *md;
  193. Visitor *v;
  194. if (!obj) {
  195. return;
  196. }
  197. md = qapi_dealloc_visitor_new();
  198. v = qapi_dealloc_get_visitor(md);
  199. visit_type_%(name)s(v, &obj, NULL, NULL);
  200. qapi_dealloc_visitor_cleanup(md);
  201. }
  202. ''',
  203. name=c_name(name))
  204. return ret
  205. class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
  206. def __init__(self):
  207. self.decl = None
  208. self.defn = None
  209. self._fwdecl = None
  210. self._fwdefn = None
  211. self._btin = None
  212. def visit_begin(self, schema):
  213. self.decl = ''
  214. self.defn = ''
  215. self._fwdecl = ''
  216. self._fwdefn = ''
  217. self._btin = guardstart('QAPI_TYPES_BUILTIN')
  218. def visit_end(self):
  219. self.decl = self._fwdecl + self.decl
  220. self._fwdecl = None
  221. self.defn = self._fwdefn + self.defn
  222. self._fwdefn = None
  223. # To avoid header dependency hell, we always generate
  224. # declarations for built-in types in our header files and
  225. # simply guard them. See also do_builtins (command line
  226. # option -b).
  227. self._btin += guardend('QAPI_TYPES_BUILTIN')
  228. self.decl = self._btin + self.decl
  229. self._btin = None
  230. def _gen_type_cleanup(self, name):
  231. self.decl += generate_type_cleanup_decl(name)
  232. self.defn += generate_type_cleanup(name)
  233. def visit_enum_type(self, name, info, values, prefix):
  234. self._fwdecl += generate_enum(name, values, prefix)
  235. self._fwdefn += generate_enum_lookup(name, values, prefix)
  236. def visit_array_type(self, name, info, element_type):
  237. if isinstance(element_type, QAPISchemaBuiltinType):
  238. self._btin += gen_fwd_object_or_array(name)
  239. self._btin += gen_array(name, element_type)
  240. self._btin += generate_type_cleanup_decl(name)
  241. if do_builtins:
  242. self.defn += generate_type_cleanup(name)
  243. else:
  244. self._fwdecl += gen_fwd_object_or_array(name)
  245. self.decl += gen_array(name, element_type)
  246. self._gen_type_cleanup(name)
  247. def visit_object_type(self, name, info, base, members, variants):
  248. if info:
  249. self._fwdecl += gen_fwd_object_or_array(name)
  250. if variants:
  251. assert not members # not implemented
  252. self.decl += gen_union(name, base, variants)
  253. else:
  254. self.decl += gen_struct(name, base, members)
  255. self._gen_type_cleanup(name)
  256. def visit_alternate_type(self, name, info, variants):
  257. self._fwdecl += gen_fwd_object_or_array(name)
  258. self._fwdefn += gen_alternate_qtypes(name, variants)
  259. self.decl += gen_union(name, None, variants)
  260. self.decl += gen_alternate_qtypes_decl(name)
  261. self._gen_type_cleanup(name)
  262. # If you link code generated from multiple schemata, you want only one
  263. # instance of the code for built-in types. Generate it only when
  264. # do_builtins, enabled by command line option -b. See also
  265. # QAPISchemaGenTypeVisitor.visit_end().
  266. do_builtins = False
  267. (input_file, output_dir, do_c, do_h, prefix, opts) = \
  268. parse_command_line("b", ["builtins"])
  269. for o, a in opts:
  270. if o in ("-b", "--builtins"):
  271. do_builtins = True
  272. c_comment = '''
  273. /*
  274. * deallocation functions for schema-defined QAPI types
  275. *
  276. * Copyright IBM, Corp. 2011
  277. *
  278. * Authors:
  279. * Anthony Liguori <aliguori@us.ibm.com>
  280. * Michael Roth <mdroth@linux.vnet.ibm.com>
  281. *
  282. * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  283. * See the COPYING.LIB file in the top-level directory.
  284. *
  285. */
  286. '''
  287. h_comment = '''
  288. /*
  289. * schema-defined QAPI types
  290. *
  291. * Copyright IBM, Corp. 2011
  292. *
  293. * Authors:
  294. * Anthony Liguori <aliguori@us.ibm.com>
  295. *
  296. * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  297. * See the COPYING.LIB file in the top-level directory.
  298. *
  299. */
  300. '''
  301. (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
  302. 'qapi-types.c', 'qapi-types.h',
  303. c_comment, h_comment)
  304. fdef.write(mcgen('''
  305. #include "qapi/dealloc-visitor.h"
  306. #include "%(prefix)sqapi-types.h"
  307. #include "%(prefix)sqapi-visit.h"
  308. ''',
  309. prefix=prefix))
  310. fdecl.write(mcgen('''
  311. #include <stdbool.h>
  312. #include <stdint.h>
  313. '''))
  314. schema = QAPISchema(input_file)
  315. gen = QAPISchemaGenTypeVisitor()
  316. schema.visit(gen)
  317. fdef.write(gen.defn)
  318. fdecl.write(gen.decl)
  319. close_output(fdef, fdecl)