qapi.py 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. #
  2. # QAPI helper library
  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. import re
  14. from ordereddict import OrderedDict
  15. import errno
  16. import getopt
  17. import os
  18. import sys
  19. import string
  20. builtin_types = {
  21. 'str': 'QTYPE_QSTRING',
  22. 'int': 'QTYPE_QINT',
  23. 'number': 'QTYPE_QFLOAT',
  24. 'bool': 'QTYPE_QBOOL',
  25. 'int8': 'QTYPE_QINT',
  26. 'int16': 'QTYPE_QINT',
  27. 'int32': 'QTYPE_QINT',
  28. 'int64': 'QTYPE_QINT',
  29. 'uint8': 'QTYPE_QINT',
  30. 'uint16': 'QTYPE_QINT',
  31. 'uint32': 'QTYPE_QINT',
  32. 'uint64': 'QTYPE_QINT',
  33. 'size': 'QTYPE_QINT',
  34. }
  35. # Whitelist of commands allowed to return a non-dictionary
  36. returns_whitelist = [
  37. # From QMP:
  38. 'human-monitor-command',
  39. 'query-migrate-cache-size',
  40. 'query-tpm-models',
  41. 'query-tpm-types',
  42. 'ringbuf-read',
  43. # From QGA:
  44. 'guest-file-open',
  45. 'guest-fsfreeze-freeze',
  46. 'guest-fsfreeze-freeze-list',
  47. 'guest-fsfreeze-status',
  48. 'guest-fsfreeze-thaw',
  49. 'guest-get-time',
  50. 'guest-set-vcpus',
  51. 'guest-sync',
  52. 'guest-sync-delimited',
  53. # From qapi-schema-test:
  54. 'user_def_cmd3',
  55. ]
  56. enum_types = []
  57. struct_types = []
  58. union_types = []
  59. events = []
  60. all_names = {}
  61. def error_path(parent):
  62. res = ""
  63. while parent:
  64. res = ("In file included from %s:%d:\n" % (parent['file'],
  65. parent['line'])) + res
  66. parent = parent['parent']
  67. return res
  68. class QAPISchemaError(Exception):
  69. def __init__(self, schema, msg):
  70. self.input_file = schema.input_file
  71. self.msg = msg
  72. self.col = 1
  73. self.line = schema.line
  74. for ch in schema.src[schema.line_pos:schema.pos]:
  75. if ch == '\t':
  76. self.col = (self.col + 7) % 8 + 1
  77. else:
  78. self.col += 1
  79. self.info = schema.parent_info
  80. def __str__(self):
  81. return error_path(self.info) + \
  82. "%s:%d:%d: %s" % (self.input_file, self.line, self.col, self.msg)
  83. class QAPIExprError(Exception):
  84. def __init__(self, expr_info, msg):
  85. self.info = expr_info
  86. self.msg = msg
  87. def __str__(self):
  88. return error_path(self.info['parent']) + \
  89. "%s:%d: %s" % (self.info['file'], self.info['line'], self.msg)
  90. class QAPISchema:
  91. def __init__(self, fp, input_relname=None, include_hist=[],
  92. previously_included=[], parent_info=None):
  93. """ include_hist is a stack used to detect inclusion cycles
  94. previously_included is a global state used to avoid multiple
  95. inclusions of the same file"""
  96. input_fname = os.path.abspath(fp.name)
  97. if input_relname is None:
  98. input_relname = fp.name
  99. self.input_dir = os.path.dirname(input_fname)
  100. self.input_file = input_relname
  101. self.include_hist = include_hist + [(input_relname, input_fname)]
  102. previously_included.append(input_fname)
  103. self.parent_info = parent_info
  104. self.src = fp.read()
  105. if self.src == '' or self.src[-1] != '\n':
  106. self.src += '\n'
  107. self.cursor = 0
  108. self.line = 1
  109. self.line_pos = 0
  110. self.exprs = []
  111. self.accept()
  112. while self.tok != None:
  113. expr_info = {'file': input_relname, 'line': self.line, 'parent': self.parent_info}
  114. expr = self.get_expr(False)
  115. if isinstance(expr, dict) and "include" in expr:
  116. if len(expr) != 1:
  117. raise QAPIExprError(expr_info, "Invalid 'include' directive")
  118. include = expr["include"]
  119. if not isinstance(include, str):
  120. raise QAPIExprError(expr_info,
  121. 'Expected a file name (string), got: %s'
  122. % include)
  123. include_path = os.path.join(self.input_dir, include)
  124. for elem in self.include_hist:
  125. if include_path == elem[1]:
  126. raise QAPIExprError(expr_info, "Inclusion loop for %s"
  127. % include)
  128. # skip multiple include of the same file
  129. if include_path in previously_included:
  130. continue
  131. try:
  132. fobj = open(include_path, 'r')
  133. except IOError, e:
  134. raise QAPIExprError(expr_info,
  135. '%s: %s' % (e.strerror, include))
  136. exprs_include = QAPISchema(fobj, include, self.include_hist,
  137. previously_included, expr_info)
  138. self.exprs.extend(exprs_include.exprs)
  139. else:
  140. expr_elem = {'expr': expr,
  141. 'info': expr_info}
  142. self.exprs.append(expr_elem)
  143. def accept(self):
  144. while True:
  145. self.tok = self.src[self.cursor]
  146. self.pos = self.cursor
  147. self.cursor += 1
  148. self.val = None
  149. if self.tok == '#':
  150. self.cursor = self.src.find('\n', self.cursor)
  151. elif self.tok in ['{', '}', ':', ',', '[', ']']:
  152. return
  153. elif self.tok == "'":
  154. string = ''
  155. esc = False
  156. while True:
  157. ch = self.src[self.cursor]
  158. self.cursor += 1
  159. if ch == '\n':
  160. raise QAPISchemaError(self,
  161. 'Missing terminating "\'"')
  162. if esc:
  163. if ch == 'b':
  164. string += '\b'
  165. elif ch == 'f':
  166. string += '\f'
  167. elif ch == 'n':
  168. string += '\n'
  169. elif ch == 'r':
  170. string += '\r'
  171. elif ch == 't':
  172. string += '\t'
  173. elif ch == 'u':
  174. value = 0
  175. for x in range(0, 4):
  176. ch = self.src[self.cursor]
  177. self.cursor += 1
  178. if ch not in "0123456789abcdefABCDEF":
  179. raise QAPISchemaError(self,
  180. '\\u escape needs 4 '
  181. 'hex digits')
  182. value = (value << 4) + int(ch, 16)
  183. # If Python 2 and 3 didn't disagree so much on
  184. # how to handle Unicode, then we could allow
  185. # Unicode string defaults. But most of QAPI is
  186. # ASCII-only, so we aren't losing much for now.
  187. if not value or value > 0x7f:
  188. raise QAPISchemaError(self,
  189. 'For now, \\u escape '
  190. 'only supports non-zero '
  191. 'values up to \\u007f')
  192. string += chr(value)
  193. elif ch in "\\/'\"":
  194. string += ch
  195. else:
  196. raise QAPISchemaError(self,
  197. "Unknown escape \\%s" %ch)
  198. esc = False
  199. elif ch == "\\":
  200. esc = True
  201. elif ch == "'":
  202. self.val = string
  203. return
  204. else:
  205. string += ch
  206. elif self.tok in "tfn":
  207. val = self.src[self.cursor - 1:]
  208. if val.startswith("true"):
  209. self.val = True
  210. self.cursor += 3
  211. return
  212. elif val.startswith("false"):
  213. self.val = False
  214. self.cursor += 4
  215. return
  216. elif val.startswith("null"):
  217. self.val = None
  218. self.cursor += 3
  219. return
  220. elif self.tok == '\n':
  221. if self.cursor == len(self.src):
  222. self.tok = None
  223. return
  224. self.line += 1
  225. self.line_pos = self.cursor
  226. elif not self.tok.isspace():
  227. raise QAPISchemaError(self, 'Stray "%s"' % self.tok)
  228. def get_members(self):
  229. expr = OrderedDict()
  230. if self.tok == '}':
  231. self.accept()
  232. return expr
  233. if self.tok != "'":
  234. raise QAPISchemaError(self, 'Expected string or "}"')
  235. while True:
  236. key = self.val
  237. self.accept()
  238. if self.tok != ':':
  239. raise QAPISchemaError(self, 'Expected ":"')
  240. self.accept()
  241. if key in expr:
  242. raise QAPISchemaError(self, 'Duplicate key "%s"' % key)
  243. expr[key] = self.get_expr(True)
  244. if self.tok == '}':
  245. self.accept()
  246. return expr
  247. if self.tok != ',':
  248. raise QAPISchemaError(self, 'Expected "," or "}"')
  249. self.accept()
  250. if self.tok != "'":
  251. raise QAPISchemaError(self, 'Expected string')
  252. def get_values(self):
  253. expr = []
  254. if self.tok == ']':
  255. self.accept()
  256. return expr
  257. if not self.tok in "{['tfn":
  258. raise QAPISchemaError(self, 'Expected "{", "[", "]", string, '
  259. 'boolean or "null"')
  260. while True:
  261. expr.append(self.get_expr(True))
  262. if self.tok == ']':
  263. self.accept()
  264. return expr
  265. if self.tok != ',':
  266. raise QAPISchemaError(self, 'Expected "," or "]"')
  267. self.accept()
  268. def get_expr(self, nested):
  269. if self.tok != '{' and not nested:
  270. raise QAPISchemaError(self, 'Expected "{"')
  271. if self.tok == '{':
  272. self.accept()
  273. expr = self.get_members()
  274. elif self.tok == '[':
  275. self.accept()
  276. expr = self.get_values()
  277. elif self.tok in "'tfn":
  278. expr = self.val
  279. self.accept()
  280. else:
  281. raise QAPISchemaError(self, 'Expected "{", "[" or string')
  282. return expr
  283. def find_base_fields(base):
  284. base_struct_define = find_struct(base)
  285. if not base_struct_define:
  286. return None
  287. return base_struct_define['data']
  288. # Return the qtype of an alternate branch, or None on error.
  289. def find_alternate_member_qtype(qapi_type):
  290. if builtin_types.has_key(qapi_type):
  291. return builtin_types[qapi_type]
  292. elif find_struct(qapi_type):
  293. return "QTYPE_QDICT"
  294. elif find_enum(qapi_type):
  295. return "QTYPE_QSTRING"
  296. elif find_union(qapi_type):
  297. return "QTYPE_QDICT"
  298. return None
  299. # Return the discriminator enum define if discriminator is specified as an
  300. # enum type, otherwise return None.
  301. def discriminator_find_enum_define(expr):
  302. base = expr.get('base')
  303. discriminator = expr.get('discriminator')
  304. if not (discriminator and base):
  305. return None
  306. base_fields = find_base_fields(base)
  307. if not base_fields:
  308. return None
  309. discriminator_type = base_fields.get(discriminator)
  310. if not discriminator_type:
  311. return None
  312. return find_enum(discriminator_type)
  313. valid_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$')
  314. def check_name(expr_info, source, name, allow_optional = False,
  315. enum_member = False):
  316. global valid_name
  317. membername = name
  318. if not isinstance(name, str):
  319. raise QAPIExprError(expr_info,
  320. "%s requires a string name" % source)
  321. if name.startswith('*'):
  322. membername = name[1:]
  323. if not allow_optional:
  324. raise QAPIExprError(expr_info,
  325. "%s does not allow optional name '%s'"
  326. % (source, name))
  327. # Enum members can start with a digit, because the generated C
  328. # code always prefixes it with the enum name
  329. if enum_member:
  330. membername = '_' + membername
  331. if not valid_name.match(membername):
  332. raise QAPIExprError(expr_info,
  333. "%s uses invalid name '%s'" % (source, name))
  334. def check_type(expr_info, source, value, allow_array = False,
  335. allow_dict = False, allow_optional = False,
  336. allow_star = False, allow_metas = []):
  337. global all_names
  338. orig_value = value
  339. if value is None:
  340. return
  341. if allow_star and value == '**':
  342. return
  343. # Check if array type for value is okay
  344. if isinstance(value, list):
  345. if not allow_array:
  346. raise QAPIExprError(expr_info,
  347. "%s cannot be an array" % source)
  348. if len(value) != 1 or not isinstance(value[0], str):
  349. raise QAPIExprError(expr_info,
  350. "%s: array type must contain single type name"
  351. % source)
  352. value = value[0]
  353. orig_value = "array of %s" %value
  354. # Check if type name for value is okay
  355. if isinstance(value, str):
  356. if value == '**':
  357. raise QAPIExprError(expr_info,
  358. "%s uses '**' but did not request 'gen':false"
  359. % source)
  360. if not value in all_names:
  361. raise QAPIExprError(expr_info,
  362. "%s uses unknown type '%s'"
  363. % (source, orig_value))
  364. if not all_names[value] in allow_metas:
  365. raise QAPIExprError(expr_info,
  366. "%s cannot use %s type '%s'"
  367. % (source, all_names[value], orig_value))
  368. return
  369. # value is a dictionary, check that each member is okay
  370. if not isinstance(value, OrderedDict):
  371. raise QAPIExprError(expr_info,
  372. "%s should be a dictionary" % source)
  373. if not allow_dict:
  374. raise QAPIExprError(expr_info,
  375. "%s should be a type name" % source)
  376. for (key, arg) in value.items():
  377. check_name(expr_info, "Member of %s" % source, key,
  378. allow_optional=allow_optional)
  379. # Todo: allow dictionaries to represent default values of
  380. # an optional argument.
  381. check_type(expr_info, "Member '%s' of %s" % (key, source), arg,
  382. allow_array=True, allow_star=allow_star,
  383. allow_metas=['built-in', 'union', 'alternate', 'struct',
  384. 'enum'])
  385. def check_member_clash(expr_info, base_name, data, source = ""):
  386. base = find_struct(base_name)
  387. assert base
  388. base_members = base['data']
  389. for key in data.keys():
  390. if key.startswith('*'):
  391. key = key[1:]
  392. if key in base_members or "*" + key in base_members:
  393. raise QAPIExprError(expr_info,
  394. "Member name '%s'%s clashes with base '%s'"
  395. % (key, source, base_name))
  396. if base.get('base'):
  397. check_member_clash(expr_info, base['base'], data, source)
  398. def check_command(expr, expr_info):
  399. name = expr['command']
  400. allow_star = expr.has_key('gen')
  401. check_type(expr_info, "'data' for command '%s'" % name,
  402. expr.get('data'), allow_dict=True, allow_optional=True,
  403. allow_metas=['union', 'struct'], allow_star=allow_star)
  404. returns_meta = ['union', 'struct']
  405. if name in returns_whitelist:
  406. returns_meta += ['built-in', 'alternate', 'enum']
  407. check_type(expr_info, "'returns' for command '%s'" % name,
  408. expr.get('returns'), allow_array=True, allow_dict=True,
  409. allow_optional=True, allow_metas=returns_meta,
  410. allow_star=allow_star)
  411. def check_event(expr, expr_info):
  412. global events
  413. name = expr['event']
  414. params = expr.get('data')
  415. if name.upper() == 'MAX':
  416. raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created")
  417. events.append(name)
  418. check_type(expr_info, "'data' for event '%s'" % name,
  419. expr.get('data'), allow_dict=True, allow_optional=True,
  420. allow_metas=['union', 'struct'])
  421. def check_union(expr, expr_info):
  422. name = expr['union']
  423. base = expr.get('base')
  424. discriminator = expr.get('discriminator')
  425. members = expr['data']
  426. values = { 'MAX': '(automatic)' }
  427. # If the object has a member 'base', its value must name a struct,
  428. # and there must be a discriminator.
  429. if base is not None:
  430. if discriminator is None:
  431. raise QAPIExprError(expr_info,
  432. "Union '%s' requires a discriminator to go "
  433. "along with base" %name)
  434. # Two types of unions, determined by discriminator.
  435. # With no discriminator it is a simple union.
  436. if discriminator is None:
  437. enum_define = None
  438. allow_metas=['built-in', 'union', 'alternate', 'struct', 'enum']
  439. if base is not None:
  440. raise QAPIExprError(expr_info,
  441. "Simple union '%s' must not have a base"
  442. % name)
  443. # Else, it's a flat union.
  444. else:
  445. # The object must have a string member 'base'.
  446. if not isinstance(base, str):
  447. raise QAPIExprError(expr_info,
  448. "Flat union '%s' must have a string base field"
  449. % name)
  450. base_fields = find_base_fields(base)
  451. if not base_fields:
  452. raise QAPIExprError(expr_info,
  453. "Base '%s' is not a valid struct"
  454. % base)
  455. # The value of member 'discriminator' must name a non-optional
  456. # member of the base struct.
  457. check_name(expr_info, "Discriminator of flat union '%s'" % name,
  458. discriminator)
  459. discriminator_type = base_fields.get(discriminator)
  460. if not discriminator_type:
  461. raise QAPIExprError(expr_info,
  462. "Discriminator '%s' is not a member of base "
  463. "struct '%s'"
  464. % (discriminator, base))
  465. enum_define = find_enum(discriminator_type)
  466. allow_metas=['struct']
  467. # Do not allow string discriminator
  468. if not enum_define:
  469. raise QAPIExprError(expr_info,
  470. "Discriminator '%s' must be of enumeration "
  471. "type" % discriminator)
  472. # Check every branch
  473. for (key, value) in members.items():
  474. check_name(expr_info, "Member of union '%s'" % name, key)
  475. # Each value must name a known type; furthermore, in flat unions,
  476. # branches must be a struct with no overlapping member names
  477. check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
  478. value, allow_array=True, allow_metas=allow_metas)
  479. if base:
  480. branch_struct = find_struct(value)
  481. assert branch_struct
  482. check_member_clash(expr_info, base, branch_struct['data'],
  483. " of branch '%s'" % key)
  484. # If the discriminator names an enum type, then all members
  485. # of 'data' must also be members of the enum type.
  486. if enum_define:
  487. if not key in enum_define['enum_values']:
  488. raise QAPIExprError(expr_info,
  489. "Discriminator value '%s' is not found in "
  490. "enum '%s'" %
  491. (key, enum_define["enum_name"]))
  492. # Otherwise, check for conflicts in the generated enum
  493. else:
  494. c_key = camel_to_upper(key)
  495. if c_key in values:
  496. raise QAPIExprError(expr_info,
  497. "Union '%s' member '%s' clashes with '%s'"
  498. % (name, key, values[c_key]))
  499. values[c_key] = key
  500. def check_alternate(expr, expr_info):
  501. name = expr['alternate']
  502. members = expr['data']
  503. values = { 'MAX': '(automatic)' }
  504. types_seen = {}
  505. # Check every branch
  506. for (key, value) in members.items():
  507. check_name(expr_info, "Member of alternate '%s'" % name, key)
  508. # Check for conflicts in the generated enum
  509. c_key = camel_to_upper(key)
  510. if c_key in values:
  511. raise QAPIExprError(expr_info,
  512. "Alternate '%s' member '%s' clashes with '%s'"
  513. % (name, key, values[c_key]))
  514. values[c_key] = key
  515. # Ensure alternates have no type conflicts.
  516. check_type(expr_info, "Member '%s' of alternate '%s'" % (key, name),
  517. value,
  518. allow_metas=['built-in', 'union', 'struct', 'enum'])
  519. qtype = find_alternate_member_qtype(value)
  520. assert qtype
  521. if qtype in types_seen:
  522. raise QAPIExprError(expr_info,
  523. "Alternate '%s' member '%s' can't "
  524. "be distinguished from member '%s'"
  525. % (name, key, types_seen[qtype]))
  526. types_seen[qtype] = key
  527. def check_enum(expr, expr_info):
  528. name = expr['enum']
  529. members = expr.get('data')
  530. values = { 'MAX': '(automatic)' }
  531. if not isinstance(members, list):
  532. raise QAPIExprError(expr_info,
  533. "Enum '%s' requires an array for 'data'" % name)
  534. for member in members:
  535. check_name(expr_info, "Member of enum '%s'" %name, member,
  536. enum_member=True)
  537. key = camel_to_upper(member)
  538. if key in values:
  539. raise QAPIExprError(expr_info,
  540. "Enum '%s' member '%s' clashes with '%s'"
  541. % (name, member, values[key]))
  542. values[key] = member
  543. def check_struct(expr, expr_info):
  544. name = expr['struct']
  545. members = expr['data']
  546. check_type(expr_info, "'data' for struct '%s'" % name, members,
  547. allow_dict=True, allow_optional=True)
  548. check_type(expr_info, "'base' for struct '%s'" % name, expr.get('base'),
  549. allow_metas=['struct'])
  550. if expr.get('base'):
  551. check_member_clash(expr_info, expr['base'], expr['data'])
  552. def check_exprs(schema):
  553. for expr_elem in schema.exprs:
  554. expr = expr_elem['expr']
  555. info = expr_elem['info']
  556. if expr.has_key('enum'):
  557. check_enum(expr, info)
  558. elif expr.has_key('union'):
  559. check_union(expr, info)
  560. elif expr.has_key('alternate'):
  561. check_alternate(expr, info)
  562. elif expr.has_key('struct'):
  563. check_struct(expr, info)
  564. elif expr.has_key('command'):
  565. check_command(expr, info)
  566. elif expr.has_key('event'):
  567. check_event(expr, info)
  568. else:
  569. assert False, 'unexpected meta type'
  570. def check_keys(expr_elem, meta, required, optional=[]):
  571. expr = expr_elem['expr']
  572. info = expr_elem['info']
  573. name = expr[meta]
  574. if not isinstance(name, str):
  575. raise QAPIExprError(info,
  576. "'%s' key must have a string value" % meta)
  577. required = required + [ meta ]
  578. for (key, value) in expr.items():
  579. if not key in required and not key in optional:
  580. raise QAPIExprError(info,
  581. "Unknown key '%s' in %s '%s'"
  582. % (key, meta, name))
  583. if (key == 'gen' or key == 'success-response') and value != False:
  584. raise QAPIExprError(info,
  585. "'%s' of %s '%s' should only use false value"
  586. % (key, meta, name))
  587. for key in required:
  588. if not expr.has_key(key):
  589. raise QAPIExprError(info,
  590. "Key '%s' is missing from %s '%s'"
  591. % (key, meta, name))
  592. def parse_schema(input_file):
  593. global all_names
  594. exprs = []
  595. # First pass: read entire file into memory
  596. try:
  597. schema = QAPISchema(open(input_file, "r"))
  598. except (QAPISchemaError, QAPIExprError), e:
  599. print >>sys.stderr, e
  600. exit(1)
  601. try:
  602. # Next pass: learn the types and check for valid expression keys. At
  603. # this point, top-level 'include' has already been flattened.
  604. for builtin in builtin_types.keys():
  605. all_names[builtin] = 'built-in'
  606. for expr_elem in schema.exprs:
  607. expr = expr_elem['expr']
  608. info = expr_elem['info']
  609. if expr.has_key('enum'):
  610. check_keys(expr_elem, 'enum', ['data'])
  611. add_enum(expr['enum'], info, expr['data'])
  612. elif expr.has_key('union'):
  613. check_keys(expr_elem, 'union', ['data'],
  614. ['base', 'discriminator'])
  615. add_union(expr, info)
  616. elif expr.has_key('alternate'):
  617. check_keys(expr_elem, 'alternate', ['data'])
  618. add_name(expr['alternate'], info, 'alternate')
  619. elif expr.has_key('struct'):
  620. check_keys(expr_elem, 'struct', ['data'], ['base'])
  621. add_struct(expr, info)
  622. elif expr.has_key('command'):
  623. check_keys(expr_elem, 'command', [],
  624. ['data', 'returns', 'gen', 'success-response'])
  625. add_name(expr['command'], info, 'command')
  626. elif expr.has_key('event'):
  627. check_keys(expr_elem, 'event', [], ['data'])
  628. add_name(expr['event'], info, 'event')
  629. else:
  630. raise QAPIExprError(expr_elem['info'],
  631. "Expression is missing metatype")
  632. exprs.append(expr)
  633. # Try again for hidden UnionKind enum
  634. for expr_elem in schema.exprs:
  635. expr = expr_elem['expr']
  636. if expr.has_key('union'):
  637. if not discriminator_find_enum_define(expr):
  638. add_enum('%sKind' % expr['union'], expr_elem['info'],
  639. implicit=True)
  640. elif expr.has_key('alternate'):
  641. add_enum('%sKind' % expr['alternate'], expr_elem['info'],
  642. implicit=True)
  643. # Final pass - validate that exprs make sense
  644. check_exprs(schema)
  645. except QAPIExprError, e:
  646. print >>sys.stderr, e
  647. exit(1)
  648. return exprs
  649. def parse_args(typeinfo):
  650. if isinstance(typeinfo, str):
  651. struct = find_struct(typeinfo)
  652. assert struct != None
  653. typeinfo = struct['data']
  654. for member in typeinfo:
  655. argname = member
  656. argentry = typeinfo[member]
  657. optional = False
  658. if member.startswith('*'):
  659. argname = member[1:]
  660. optional = True
  661. # Todo: allow argentry to be OrderedDict, for providing the
  662. # value of an optional argument.
  663. yield (argname, argentry, optional)
  664. def camel_case(name):
  665. new_name = ''
  666. first = True
  667. for ch in name:
  668. if ch in ['_', '-']:
  669. first = True
  670. elif first:
  671. new_name += ch.upper()
  672. first = False
  673. else:
  674. new_name += ch.lower()
  675. return new_name
  676. # ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
  677. # ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
  678. # ENUM24_Name -> ENUM24_NAME
  679. def camel_to_upper(value):
  680. c_fun_str = c_name(value, False)
  681. if value.isupper():
  682. return c_fun_str
  683. new_name = ''
  684. l = len(c_fun_str)
  685. for i in range(l):
  686. c = c_fun_str[i]
  687. # When c is upper and no "_" appears before, do more checks
  688. if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
  689. # Case 1: next string is lower
  690. # Case 2: previous string is digit
  691. if (i < (l - 1) and c_fun_str[i + 1].islower()) or \
  692. c_fun_str[i - 1].isdigit():
  693. new_name += '_'
  694. new_name += c
  695. return new_name.lstrip('_').upper()
  696. def c_enum_const(type_name, const_name):
  697. return camel_to_upper(type_name + '_' + const_name)
  698. c_name_trans = string.maketrans('.-', '__')
  699. # Map @name to a valid C identifier.
  700. # If @protect, avoid returning certain ticklish identifiers (like
  701. # C keywords) by prepending "q_".
  702. #
  703. # Used for converting 'name' from a 'name':'type' qapi definition
  704. # into a generated struct member, as well as converting type names
  705. # into substrings of a generated C function name.
  706. # '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
  707. # protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
  708. def c_name(name, protect=True):
  709. # ANSI X3J11/88-090, 3.1.1
  710. c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
  711. 'default', 'do', 'double', 'else', 'enum', 'extern', 'float',
  712. 'for', 'goto', 'if', 'int', 'long', 'register', 'return',
  713. 'short', 'signed', 'sizeof', 'static', 'struct', 'switch',
  714. 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while'])
  715. # ISO/IEC 9899:1999, 6.4.1
  716. c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
  717. # ISO/IEC 9899:2011, 6.4.1
  718. c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic', '_Noreturn',
  719. '_Static_assert', '_Thread_local'])
  720. # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
  721. # excluding _.*
  722. gcc_words = set(['asm', 'typeof'])
  723. # C++ ISO/IEC 14882:2003 2.11
  724. cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
  725. 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
  726. 'namespace', 'new', 'operator', 'private', 'protected',
  727. 'public', 'reinterpret_cast', 'static_cast', 'template',
  728. 'this', 'throw', 'true', 'try', 'typeid', 'typename',
  729. 'using', 'virtual', 'wchar_t',
  730. # alternative representations
  731. 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
  732. 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
  733. # namespace pollution:
  734. polluted_words = set(['unix', 'errno'])
  735. if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words):
  736. return "q_" + name
  737. return name.translate(c_name_trans)
  738. # Map type @name to the C typedef name for the list form.
  739. #
  740. # ['Name'] -> 'NameList', ['x-Foo'] -> 'x_FooList', ['int'] -> 'intList'
  741. def c_list_type(name):
  742. return type_name(name) + 'List'
  743. # Map type @value to the C typedef form.
  744. #
  745. # Used for converting 'type' from a 'member':'type' qapi definition
  746. # into the alphanumeric portion of the type for a generated C parameter,
  747. # as well as generated C function names. See c_type() for the rest of
  748. # the conversion such as adding '*' on pointer types.
  749. # 'int' -> 'int', '[x-Foo]' -> 'x_FooList', '__a.b_c' -> '__a_b_c'
  750. def type_name(value):
  751. if type(value) == list:
  752. return c_list_type(value[0])
  753. if value in builtin_types.keys():
  754. return value
  755. return c_name(value)
  756. def add_name(name, info, meta, implicit = False):
  757. global all_names
  758. check_name(info, "'%s'" % meta, name)
  759. if name in all_names:
  760. raise QAPIExprError(info,
  761. "%s '%s' is already defined"
  762. % (all_names[name], name))
  763. if not implicit and name[-4:] == 'Kind':
  764. raise QAPIExprError(info,
  765. "%s '%s' should not end in 'Kind'"
  766. % (meta, name))
  767. all_names[name] = meta
  768. def add_struct(definition, info):
  769. global struct_types
  770. name = definition['struct']
  771. add_name(name, info, 'struct')
  772. struct_types.append(definition)
  773. def find_struct(name):
  774. global struct_types
  775. for struct in struct_types:
  776. if struct['struct'] == name:
  777. return struct
  778. return None
  779. def add_union(definition, info):
  780. global union_types
  781. name = definition['union']
  782. add_name(name, info, 'union')
  783. union_types.append(definition)
  784. def find_union(name):
  785. global union_types
  786. for union in union_types:
  787. if union['union'] == name:
  788. return union
  789. return None
  790. def add_enum(name, info, enum_values = None, implicit = False):
  791. global enum_types
  792. add_name(name, info, 'enum', implicit)
  793. enum_types.append({"enum_name": name, "enum_values": enum_values})
  794. def find_enum(name):
  795. global enum_types
  796. for enum in enum_types:
  797. if enum['enum_name'] == name:
  798. return enum
  799. return None
  800. def is_enum(name):
  801. return find_enum(name) != None
  802. eatspace = '\033EATSPACE.'
  803. pointer_suffix = ' *' + eatspace
  804. # Map type @name to its C type expression.
  805. # If @is_param, const-qualify the string type.
  806. #
  807. # This function is used for computing the full C type of 'member':'name'.
  808. # A special suffix is added in c_type() for pointer types, and it's
  809. # stripped in mcgen(). So please notice this when you check the return
  810. # value of c_type() outside mcgen().
  811. def c_type(value, is_param=False):
  812. if value == 'str':
  813. if is_param:
  814. return 'const char' + pointer_suffix
  815. return 'char' + pointer_suffix
  816. elif value == 'int':
  817. return 'int64_t'
  818. elif (value == 'int8' or value == 'int16' or value == 'int32' or
  819. value == 'int64' or value == 'uint8' or value == 'uint16' or
  820. value == 'uint32' or value == 'uint64'):
  821. return value + '_t'
  822. elif value == 'size':
  823. return 'uint64_t'
  824. elif value == 'bool':
  825. return 'bool'
  826. elif value == 'number':
  827. return 'double'
  828. elif type(value) == list:
  829. return c_list_type(value[0]) + pointer_suffix
  830. elif is_enum(value):
  831. return c_name(value)
  832. elif value == None:
  833. return 'void'
  834. elif value in events:
  835. return camel_case(value) + 'Event' + pointer_suffix
  836. else:
  837. # complex type name
  838. assert isinstance(value, str) and value != ""
  839. return c_name(value) + pointer_suffix
  840. def is_c_ptr(value):
  841. return c_type(value).endswith(pointer_suffix)
  842. def genindent(count):
  843. ret = ""
  844. for i in range(count):
  845. ret += " "
  846. return ret
  847. indent_level = 0
  848. def push_indent(indent_amount=4):
  849. global indent_level
  850. indent_level += indent_amount
  851. def pop_indent(indent_amount=4):
  852. global indent_level
  853. indent_level -= indent_amount
  854. def cgen(code, **kwds):
  855. indent = genindent(indent_level)
  856. lines = code.split('\n')
  857. lines = map(lambda x: indent + x, lines)
  858. return '\n'.join(lines) % kwds + '\n'
  859. def mcgen(code, **kwds):
  860. raw = cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
  861. return re.sub(re.escape(eatspace) + ' *', '', raw)
  862. def basename(filename):
  863. return filename.split("/")[-1]
  864. def guardname(filename):
  865. guard = basename(filename).rsplit(".", 1)[0]
  866. for substr in [".", " ", "-"]:
  867. guard = guard.replace(substr, "_")
  868. return guard.upper() + '_H'
  869. def guardstart(name):
  870. return mcgen('''
  871. #ifndef %(name)s
  872. #define %(name)s
  873. ''',
  874. name=guardname(name))
  875. def guardend(name):
  876. return mcgen('''
  877. #endif /* %(name)s */
  878. ''',
  879. name=guardname(name))
  880. def parse_command_line(extra_options = "", extra_long_options = []):
  881. try:
  882. opts, args = getopt.gnu_getopt(sys.argv[1:],
  883. "chp:o:" + extra_options,
  884. ["source", "header", "prefix=",
  885. "output-dir="] + extra_long_options)
  886. except getopt.GetoptError, err:
  887. print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err))
  888. sys.exit(1)
  889. output_dir = ""
  890. prefix = ""
  891. do_c = False
  892. do_h = False
  893. extra_opts = []
  894. for oa in opts:
  895. o, a = oa
  896. if o in ("-p", "--prefix"):
  897. prefix = a
  898. elif o in ("-o", "--output-dir"):
  899. output_dir = a + "/"
  900. elif o in ("-c", "--source"):
  901. do_c = True
  902. elif o in ("-h", "--header"):
  903. do_h = True
  904. else:
  905. extra_opts.append(oa)
  906. if not do_c and not do_h:
  907. do_c = True
  908. do_h = True
  909. if len(args) != 1:
  910. print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
  911. sys.exit(1)
  912. input_file = args[0]
  913. return (input_file, output_dir, do_c, do_h, prefix, extra_opts)
  914. def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
  915. c_comment, h_comment):
  916. c_file = output_dir + prefix + c_file
  917. h_file = output_dir + prefix + h_file
  918. try:
  919. os.makedirs(output_dir)
  920. except os.error, e:
  921. if e.errno != errno.EEXIST:
  922. raise
  923. def maybe_open(really, name, opt):
  924. if really:
  925. return open(name, opt)
  926. else:
  927. import StringIO
  928. return StringIO.StringIO()
  929. fdef = maybe_open(do_c, c_file, 'w')
  930. fdecl = maybe_open(do_h, h_file, 'w')
  931. fdef.write(mcgen('''
  932. /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
  933. %(comment)s
  934. ''',
  935. comment = c_comment))
  936. fdecl.write(mcgen('''
  937. /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
  938. %(comment)s
  939. #ifndef %(guard)s
  940. #define %(guard)s
  941. ''',
  942. comment = h_comment, guard = guardname(h_file)))
  943. return (fdef, fdecl)
  944. def close_output(fdef, fdecl):
  945. fdecl.write('''
  946. #endif
  947. ''')
  948. fdecl.close()
  949. fdef.close()