common.py 88 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626
  1. #
  2. # QAPI helper library
  3. #
  4. # Copyright IBM, Corp. 2011
  5. # Copyright (c) 2013-2018 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 __future__ import print_function
  14. from contextlib import contextmanager
  15. import copy
  16. import errno
  17. import os
  18. import re
  19. import string
  20. import sys
  21. from collections import OrderedDict
  22. builtin_types = {
  23. 'null': 'QTYPE_QNULL',
  24. 'str': 'QTYPE_QSTRING',
  25. 'int': 'QTYPE_QNUM',
  26. 'number': 'QTYPE_QNUM',
  27. 'bool': 'QTYPE_QBOOL',
  28. 'int8': 'QTYPE_QNUM',
  29. 'int16': 'QTYPE_QNUM',
  30. 'int32': 'QTYPE_QNUM',
  31. 'int64': 'QTYPE_QNUM',
  32. 'uint8': 'QTYPE_QNUM',
  33. 'uint16': 'QTYPE_QNUM',
  34. 'uint32': 'QTYPE_QNUM',
  35. 'uint64': 'QTYPE_QNUM',
  36. 'size': 'QTYPE_QNUM',
  37. 'any': None, # any QType possible, actually
  38. 'QType': 'QTYPE_QSTRING',
  39. }
  40. # Are documentation comments required?
  41. doc_required = False
  42. # Whitelist of commands allowed to return a non-dictionary
  43. returns_whitelist = []
  44. # Whitelist of entities allowed to violate case conventions
  45. name_case_whitelist = []
  46. enum_types = {}
  47. struct_types = {}
  48. union_types = {}
  49. all_names = {}
  50. #
  51. # Parsing the schema into expressions
  52. #
  53. class QAPISourceInfo(object):
  54. def __init__(self, fname, line, parent):
  55. self.fname = fname
  56. self.line = line
  57. self.parent = parent
  58. self.defn_meta = None
  59. self.defn_name = None
  60. def set_defn(self, meta, name):
  61. self.defn_meta = meta
  62. self.defn_name = name
  63. def next_line(self):
  64. info = copy.copy(self)
  65. info.line += 1
  66. return info
  67. def loc(self):
  68. return '%s:%d' % (self.fname, self.line)
  69. def in_defn(self):
  70. if self.defn_name:
  71. return "%s: In %s '%s':\n" % (self.fname,
  72. self.defn_meta, self.defn_name)
  73. return ''
  74. def include_path(self):
  75. ret = ''
  76. parent = self.parent
  77. while parent:
  78. ret = 'In file included from %s:\n' % parent.loc() + ret
  79. parent = parent.parent
  80. return ret
  81. def __str__(self):
  82. return self.include_path() + self.in_defn() + self.loc()
  83. class QAPIError(Exception):
  84. def __init__(self, info, col, msg):
  85. Exception.__init__(self)
  86. self.info = info
  87. self.col = col
  88. self.msg = msg
  89. def __str__(self):
  90. loc = str(self.info)
  91. if self.col is not None:
  92. assert self.info.line is not None
  93. loc += ':%s' % self.col
  94. return loc + ': ' + self.msg
  95. class QAPIParseError(QAPIError):
  96. def __init__(self, parser, msg):
  97. col = 1
  98. for ch in parser.src[parser.line_pos:parser.pos]:
  99. if ch == '\t':
  100. col = (col + 7) % 8 + 1
  101. else:
  102. col += 1
  103. QAPIError.__init__(self, parser.info, col, msg)
  104. class QAPISemError(QAPIError):
  105. def __init__(self, info, msg):
  106. QAPIError.__init__(self, info, None, msg)
  107. class QAPIDoc(object):
  108. """
  109. A documentation comment block, either definition or free-form
  110. Definition documentation blocks consist of
  111. * a body section: one line naming the definition, followed by an
  112. overview (any number of lines)
  113. * argument sections: a description of each argument (for commands
  114. and events) or member (for structs, unions and alternates)
  115. * features sections: a description of each feature flag
  116. * additional (non-argument) sections, possibly tagged
  117. Free-form documentation blocks consist only of a body section.
  118. """
  119. class Section(object):
  120. def __init__(self, name=None):
  121. # optional section name (argument/member or section name)
  122. self.name = name
  123. # the list of lines for this section
  124. self.text = ''
  125. def append(self, line):
  126. self.text += line.rstrip() + '\n'
  127. class ArgSection(Section):
  128. def __init__(self, name):
  129. QAPIDoc.Section.__init__(self, name)
  130. self.member = None
  131. def connect(self, member):
  132. self.member = member
  133. def __init__(self, parser, info):
  134. # self._parser is used to report errors with QAPIParseError. The
  135. # resulting error position depends on the state of the parser.
  136. # It happens to be the beginning of the comment. More or less
  137. # servicable, but action at a distance.
  138. self._parser = parser
  139. self.info = info
  140. self.symbol = None
  141. self.body = QAPIDoc.Section()
  142. # dict mapping parameter name to ArgSection
  143. self.args = OrderedDict()
  144. self.features = OrderedDict()
  145. # a list of Section
  146. self.sections = []
  147. # the current section
  148. self._section = self.body
  149. self._append_line = self._append_body_line
  150. def has_section(self, name):
  151. """Return True if we have a section with this name."""
  152. for i in self.sections:
  153. if i.name == name:
  154. return True
  155. return False
  156. def append(self, line):
  157. """
  158. Parse a comment line and add it to the documentation.
  159. The way that the line is dealt with depends on which part of
  160. the documentation we're parsing right now:
  161. * The body section: ._append_line is ._append_body_line
  162. * An argument section: ._append_line is ._append_args_line
  163. * A features section: ._append_line is ._append_features_line
  164. * An additional section: ._append_line is ._append_various_line
  165. """
  166. line = line[1:]
  167. if not line:
  168. self._append_freeform(line)
  169. return
  170. if line[0] != ' ':
  171. raise QAPIParseError(self._parser, "missing space after #")
  172. line = line[1:]
  173. self._append_line(line)
  174. def end_comment(self):
  175. self._end_section()
  176. @staticmethod
  177. def _is_section_tag(name):
  178. return name in ('Returns:', 'Since:',
  179. # those are often singular or plural
  180. 'Note:', 'Notes:',
  181. 'Example:', 'Examples:',
  182. 'TODO:')
  183. def _append_body_line(self, line):
  184. """
  185. Process a line of documentation text in the body section.
  186. If this a symbol line and it is the section's first line, this
  187. is a definition documentation block for that symbol.
  188. If it's a definition documentation block, another symbol line
  189. begins the argument section for the argument named by it, and
  190. a section tag begins an additional section. Start that
  191. section and append the line to it.
  192. Else, append the line to the current section.
  193. """
  194. name = line.split(' ', 1)[0]
  195. # FIXME not nice: things like '# @foo:' and '# @foo: ' aren't
  196. # recognized, and get silently treated as ordinary text
  197. if not self.symbol and not self.body.text and line.startswith('@'):
  198. if not line.endswith(':'):
  199. raise QAPIParseError(self._parser, "line should end with ':'")
  200. self.symbol = line[1:-1]
  201. # FIXME invalid names other than the empty string aren't flagged
  202. if not self.symbol:
  203. raise QAPIParseError(self._parser, "invalid name")
  204. elif self.symbol:
  205. # This is a definition documentation block
  206. if name.startswith('@') and name.endswith(':'):
  207. self._append_line = self._append_args_line
  208. self._append_args_line(line)
  209. elif line == 'Features:':
  210. self._append_line = self._append_features_line
  211. elif self._is_section_tag(name):
  212. self._append_line = self._append_various_line
  213. self._append_various_line(line)
  214. else:
  215. self._append_freeform(line.strip())
  216. else:
  217. # This is a free-form documentation block
  218. self._append_freeform(line.strip())
  219. def _append_args_line(self, line):
  220. """
  221. Process a line of documentation text in an argument section.
  222. A symbol line begins the next argument section, a section tag
  223. section or a non-indented line after a blank line begins an
  224. additional section. Start that section and append the line to
  225. it.
  226. Else, append the line to the current section.
  227. """
  228. name = line.split(' ', 1)[0]
  229. if name.startswith('@') and name.endswith(':'):
  230. line = line[len(name)+1:]
  231. self._start_args_section(name[1:-1])
  232. elif self._is_section_tag(name):
  233. self._append_line = self._append_various_line
  234. self._append_various_line(line)
  235. return
  236. elif (self._section.text.endswith('\n\n')
  237. and line and not line[0].isspace()):
  238. if line == 'Features:':
  239. self._append_line = self._append_features_line
  240. else:
  241. self._start_section()
  242. self._append_line = self._append_various_line
  243. self._append_various_line(line)
  244. return
  245. self._append_freeform(line.strip())
  246. def _append_features_line(self, line):
  247. name = line.split(' ', 1)[0]
  248. if name.startswith('@') and name.endswith(':'):
  249. line = line[len(name)+1:]
  250. self._start_features_section(name[1:-1])
  251. elif self._is_section_tag(name):
  252. self._append_line = self._append_various_line
  253. self._append_various_line(line)
  254. return
  255. elif (self._section.text.endswith('\n\n')
  256. and line and not line[0].isspace()):
  257. self._start_section()
  258. self._append_line = self._append_various_line
  259. self._append_various_line(line)
  260. return
  261. self._append_freeform(line.strip())
  262. def _append_various_line(self, line):
  263. """
  264. Process a line of documentation text in an additional section.
  265. A symbol line is an error.
  266. A section tag begins an additional section. Start that
  267. section and append the line to it.
  268. Else, append the line to the current section.
  269. """
  270. name = line.split(' ', 1)[0]
  271. if name.startswith('@') and name.endswith(':'):
  272. raise QAPIParseError(self._parser,
  273. "'%s' can't follow '%s' section"
  274. % (name, self.sections[0].name))
  275. elif self._is_section_tag(name):
  276. line = line[len(name)+1:]
  277. self._start_section(name[:-1])
  278. if (not self._section.name or
  279. not self._section.name.startswith('Example')):
  280. line = line.strip()
  281. self._append_freeform(line)
  282. def _start_symbol_section(self, symbols_dict, name):
  283. # FIXME invalid names other than the empty string aren't flagged
  284. if not name:
  285. raise QAPIParseError(self._parser, "invalid parameter name")
  286. if name in symbols_dict:
  287. raise QAPIParseError(self._parser,
  288. "'%s' parameter name duplicated" % name)
  289. assert not self.sections
  290. self._end_section()
  291. self._section = QAPIDoc.ArgSection(name)
  292. symbols_dict[name] = self._section
  293. def _start_args_section(self, name):
  294. self._start_symbol_section(self.args, name)
  295. def _start_features_section(self, name):
  296. self._start_symbol_section(self.features, name)
  297. def _start_section(self, name=None):
  298. if name in ('Returns', 'Since') and self.has_section(name):
  299. raise QAPIParseError(self._parser,
  300. "duplicated '%s' section" % name)
  301. self._end_section()
  302. self._section = QAPIDoc.Section(name)
  303. self.sections.append(self._section)
  304. def _end_section(self):
  305. if self._section:
  306. text = self._section.text = self._section.text.strip()
  307. if self._section.name and (not text or text.isspace()):
  308. raise QAPIParseError(
  309. self._parser,
  310. "empty doc section '%s'" % self._section.name)
  311. self._section = None
  312. def _append_freeform(self, line):
  313. match = re.match(r'(@\S+:)', line)
  314. if match:
  315. raise QAPIParseError(self._parser,
  316. "'%s' not allowed in free-form documentation"
  317. % match.group(1))
  318. self._section.append(line)
  319. def connect_member(self, member):
  320. if member.name not in self.args:
  321. # Undocumented TODO outlaw
  322. self.args[member.name] = QAPIDoc.ArgSection(member.name)
  323. self.args[member.name].connect(member)
  324. def check_expr(self, expr):
  325. if self.has_section('Returns') and 'command' not in expr:
  326. raise QAPISemError(self.info,
  327. "'Returns:' is only valid for commands")
  328. def check(self):
  329. bogus = [name for name, section in self.args.items()
  330. if not section.member]
  331. if bogus:
  332. raise QAPISemError(
  333. self.info,
  334. "the following documented members are not in "
  335. "the declaration: %s" % ", ".join(bogus))
  336. class QAPISchemaParser(object):
  337. def __init__(self, fp, previously_included=[], incl_info=None):
  338. self.fname = fp.name
  339. previously_included.append(os.path.abspath(fp.name))
  340. self.src = fp.read()
  341. if self.src == '' or self.src[-1] != '\n':
  342. self.src += '\n'
  343. self.cursor = 0
  344. self.info = QAPISourceInfo(self.fname, 1, incl_info)
  345. self.line_pos = 0
  346. self.exprs = []
  347. self.docs = []
  348. self.accept()
  349. cur_doc = None
  350. while self.tok is not None:
  351. info = self.info
  352. if self.tok == '#':
  353. self.reject_expr_doc(cur_doc)
  354. cur_doc = self.get_doc(info)
  355. self.docs.append(cur_doc)
  356. continue
  357. expr = self.get_expr(False)
  358. if 'include' in expr:
  359. self.reject_expr_doc(cur_doc)
  360. if len(expr) != 1:
  361. raise QAPISemError(info, "invalid 'include' directive")
  362. include = expr['include']
  363. if not isinstance(include, str):
  364. raise QAPISemError(info,
  365. "value of 'include' must be a string")
  366. incl_fname = os.path.join(os.path.dirname(self.fname),
  367. include)
  368. self.exprs.append({'expr': {'include': incl_fname},
  369. 'info': info})
  370. exprs_include = self._include(include, info, incl_fname,
  371. previously_included)
  372. if exprs_include:
  373. self.exprs.extend(exprs_include.exprs)
  374. self.docs.extend(exprs_include.docs)
  375. elif "pragma" in expr:
  376. self.reject_expr_doc(cur_doc)
  377. if len(expr) != 1:
  378. raise QAPISemError(info, "invalid 'pragma' directive")
  379. pragma = expr['pragma']
  380. if not isinstance(pragma, dict):
  381. raise QAPISemError(
  382. info, "value of 'pragma' must be an object")
  383. for name, value in pragma.items():
  384. self._pragma(name, value, info)
  385. else:
  386. expr_elem = {'expr': expr,
  387. 'info': info}
  388. if cur_doc:
  389. if not cur_doc.symbol:
  390. raise QAPISemError(
  391. cur_doc.info, "definition documentation required")
  392. expr_elem['doc'] = cur_doc
  393. self.exprs.append(expr_elem)
  394. cur_doc = None
  395. self.reject_expr_doc(cur_doc)
  396. @staticmethod
  397. def reject_expr_doc(doc):
  398. if doc and doc.symbol:
  399. raise QAPISemError(
  400. doc.info,
  401. "documentation for '%s' is not followed by the definition"
  402. % doc.symbol)
  403. def _include(self, include, info, incl_fname, previously_included):
  404. incl_abs_fname = os.path.abspath(incl_fname)
  405. # catch inclusion cycle
  406. inf = info
  407. while inf:
  408. if incl_abs_fname == os.path.abspath(inf.fname):
  409. raise QAPISemError(info, "inclusion loop for %s" % include)
  410. inf = inf.parent
  411. # skip multiple include of the same file
  412. if incl_abs_fname in previously_included:
  413. return None
  414. try:
  415. if sys.version_info[0] >= 3:
  416. fobj = open(incl_fname, 'r', encoding='utf-8')
  417. else:
  418. fobj = open(incl_fname, 'r')
  419. except IOError as e:
  420. raise QAPISemError(info, "%s: %s" % (e.strerror, incl_fname))
  421. return QAPISchemaParser(fobj, previously_included, info)
  422. def _pragma(self, name, value, info):
  423. global doc_required, returns_whitelist, name_case_whitelist
  424. if name == 'doc-required':
  425. if not isinstance(value, bool):
  426. raise QAPISemError(info,
  427. "pragma 'doc-required' must be boolean")
  428. doc_required = value
  429. elif name == 'returns-whitelist':
  430. if (not isinstance(value, list)
  431. or any([not isinstance(elt, str) for elt in value])):
  432. raise QAPISemError(
  433. info,
  434. "pragma returns-whitelist must be a list of strings")
  435. returns_whitelist = value
  436. elif name == 'name-case-whitelist':
  437. if (not isinstance(value, list)
  438. or any([not isinstance(elt, str) for elt in value])):
  439. raise QAPISemError(
  440. info,
  441. "pragma name-case-whitelist must be a list of strings")
  442. name_case_whitelist = value
  443. else:
  444. raise QAPISemError(info, "unknown pragma '%s'" % name)
  445. def accept(self, skip_comment=True):
  446. while True:
  447. self.tok = self.src[self.cursor]
  448. self.pos = self.cursor
  449. self.cursor += 1
  450. self.val = None
  451. if self.tok == '#':
  452. if self.src[self.cursor] == '#':
  453. # Start of doc comment
  454. skip_comment = False
  455. self.cursor = self.src.find('\n', self.cursor)
  456. if not skip_comment:
  457. self.val = self.src[self.pos:self.cursor]
  458. return
  459. elif self.tok in '{}:,[]':
  460. return
  461. elif self.tok == "'":
  462. # Note: we accept only printable ASCII
  463. string = ''
  464. esc = False
  465. while True:
  466. ch = self.src[self.cursor]
  467. self.cursor += 1
  468. if ch == '\n':
  469. raise QAPIParseError(self, "missing terminating \"'\"")
  470. if esc:
  471. # Note: we recognize only \\ because we have
  472. # no use for funny characters in strings
  473. if ch != '\\':
  474. raise QAPIParseError(self,
  475. "unknown escape \\%s" % ch)
  476. esc = False
  477. elif ch == '\\':
  478. esc = True
  479. continue
  480. elif ch == "'":
  481. self.val = string
  482. return
  483. if ord(ch) < 32 or ord(ch) >= 127:
  484. raise QAPIParseError(
  485. self, "funny character in string")
  486. string += ch
  487. elif self.src.startswith('true', self.pos):
  488. self.val = True
  489. self.cursor += 3
  490. return
  491. elif self.src.startswith('false', self.pos):
  492. self.val = False
  493. self.cursor += 4
  494. return
  495. elif self.tok == '\n':
  496. if self.cursor == len(self.src):
  497. self.tok = None
  498. return
  499. self.info = self.info.next_line()
  500. self.line_pos = self.cursor
  501. elif not self.tok.isspace():
  502. # Show up to next structural, whitespace or quote
  503. # character
  504. match = re.match('[^[\\]{}:,\\s\'"]+',
  505. self.src[self.cursor-1:])
  506. raise QAPIParseError(self, "stray '%s'" % match.group(0))
  507. def get_members(self):
  508. expr = OrderedDict()
  509. if self.tok == '}':
  510. self.accept()
  511. return expr
  512. if self.tok != "'":
  513. raise QAPIParseError(self, "expected string or '}'")
  514. while True:
  515. key = self.val
  516. self.accept()
  517. if self.tok != ':':
  518. raise QAPIParseError(self, "expected ':'")
  519. self.accept()
  520. if key in expr:
  521. raise QAPIParseError(self, "duplicate key '%s'" % key)
  522. expr[key] = self.get_expr(True)
  523. if self.tok == '}':
  524. self.accept()
  525. return expr
  526. if self.tok != ',':
  527. raise QAPIParseError(self, "expected ',' or '}'")
  528. self.accept()
  529. if self.tok != "'":
  530. raise QAPIParseError(self, "expected string")
  531. def get_values(self):
  532. expr = []
  533. if self.tok == ']':
  534. self.accept()
  535. return expr
  536. if self.tok not in "{['tfn":
  537. raise QAPIParseError(
  538. self, "expected '{', '[', ']', string, boolean or 'null'")
  539. while True:
  540. expr.append(self.get_expr(True))
  541. if self.tok == ']':
  542. self.accept()
  543. return expr
  544. if self.tok != ',':
  545. raise QAPIParseError(self, "expected ',' or ']'")
  546. self.accept()
  547. def get_expr(self, nested):
  548. if self.tok != '{' and not nested:
  549. raise QAPIParseError(self, "expected '{'")
  550. if self.tok == '{':
  551. self.accept()
  552. expr = self.get_members()
  553. elif self.tok == '[':
  554. self.accept()
  555. expr = self.get_values()
  556. elif self.tok in "'tfn":
  557. expr = self.val
  558. self.accept()
  559. else:
  560. raise QAPIParseError(
  561. self, "expected '{', '[', string, boolean or 'null'")
  562. return expr
  563. def get_doc(self, info):
  564. if self.val != '##':
  565. raise QAPIParseError(
  566. self, "junk after '##' at start of documentation comment")
  567. doc = QAPIDoc(self, info)
  568. self.accept(False)
  569. while self.tok == '#':
  570. if self.val.startswith('##'):
  571. # End of doc comment
  572. if self.val != '##':
  573. raise QAPIParseError(
  574. self,
  575. "junk after '##' at end of documentation comment")
  576. doc.end_comment()
  577. self.accept()
  578. return doc
  579. else:
  580. doc.append(self.val)
  581. self.accept(False)
  582. raise QAPIParseError(self, "documentation comment must end with '##'")
  583. #
  584. # Semantic analysis of schema expressions
  585. # TODO fold into QAPISchema
  586. # TODO catching name collisions in generated code would be nice
  587. #
  588. def find_base_members(base):
  589. if isinstance(base, dict):
  590. return base
  591. base_struct_define = struct_types.get(base)
  592. if not base_struct_define:
  593. return None
  594. return base_struct_define['data']
  595. # Return the qtype of an alternate branch, or None on error.
  596. def find_alternate_member_qtype(qapi_type):
  597. if qapi_type in builtin_types:
  598. return builtin_types[qapi_type]
  599. elif qapi_type in struct_types:
  600. return 'QTYPE_QDICT'
  601. elif qapi_type in enum_types:
  602. return 'QTYPE_QSTRING'
  603. elif qapi_type in union_types:
  604. return 'QTYPE_QDICT'
  605. return None
  606. # Names must be letters, numbers, -, and _. They must start with letter,
  607. # except for downstream extensions which must start with __RFQDN_.
  608. # Dots are only valid in the downstream extension prefix.
  609. valid_name = re.compile(r'^(__[a-zA-Z0-9.-]+_)?'
  610. '[a-zA-Z][a-zA-Z0-9_-]*$')
  611. def check_name(name, info, source,
  612. allow_optional=False, enum_member=False, permit_upper=False):
  613. check_name_is_str(name, info, source)
  614. check_name_str(name, info, source,
  615. allow_optional, enum_member, permit_upper)
  616. def check_name_is_str(name, info, source):
  617. if not isinstance(name, str):
  618. raise QAPISemError(info, "%s requires a string name" % source)
  619. def check_name_str(name, info, source,
  620. allow_optional=False, enum_member=False,
  621. permit_upper=False):
  622. global valid_name
  623. membername = name
  624. if allow_optional and name.startswith('*'):
  625. membername = name[1:]
  626. # Enum members can start with a digit, because the generated C
  627. # code always prefixes it with the enum name
  628. if enum_member and membername[0].isdigit():
  629. membername = 'D' + membername
  630. # Reserve the entire 'q_' namespace for c_name(), and for 'q_empty'
  631. # and 'q_obj_*' implicit type names.
  632. if not valid_name.match(membername) or \
  633. c_name(membername, False).startswith('q_'):
  634. raise QAPISemError(info, "%s uses invalid name '%s'" % (source, name))
  635. if not permit_upper and name.lower() != name:
  636. raise QAPISemError(
  637. info, "%s uses uppercase in name '%s'" % (source, name))
  638. assert not membername.startswith('*')
  639. def check_defn_name_str(name, info, meta):
  640. check_name_str(name, info, meta, permit_upper=True)
  641. if name.endswith('Kind') or name.endswith('List'):
  642. raise QAPISemError(
  643. info, "%s '%s' should not end in '%s'" % (meta, name, name[-4:]))
  644. def add_name(name, info, meta):
  645. global all_names
  646. # FIXME should reject names that differ only in '_' vs. '.'
  647. # vs. '-', because they're liable to clash in generated C.
  648. if name in all_names:
  649. raise QAPISemError(info, "%s '%s' is already defined"
  650. % (all_names[name], name))
  651. all_names[name] = meta
  652. def check_if(expr, info):
  653. def check_if_str(ifcond, info):
  654. if not isinstance(ifcond, str):
  655. raise QAPISemError(
  656. info, "'if' condition must be a string or a list of strings")
  657. if ifcond.strip() == '':
  658. raise QAPISemError(info, "'if' condition '%s' makes no sense"
  659. % ifcond)
  660. ifcond = expr.get('if')
  661. if ifcond is None:
  662. return
  663. if isinstance(ifcond, list):
  664. if ifcond == []:
  665. raise QAPISemError(info, "'if' condition [] is useless")
  666. for elt in ifcond:
  667. check_if_str(elt, info)
  668. else:
  669. check_if_str(ifcond, info)
  670. def check_type(value, info, source,
  671. allow_array=False, allow_dict=False, allow_metas=[]):
  672. global all_names
  673. if value is None:
  674. return
  675. # Check if array type for value is okay
  676. if isinstance(value, list):
  677. if not allow_array:
  678. raise QAPISemError(info, "%s cannot be an array" % source)
  679. if len(value) != 1 or not isinstance(value[0], str):
  680. raise QAPISemError(info,
  681. "%s: array type must contain single type name" %
  682. source)
  683. check_type(value[0], info, source, allow_metas=allow_metas)
  684. return
  685. # Check if type name for value is okay
  686. if isinstance(value, str):
  687. if value not in all_names:
  688. raise QAPISemError(info, "%s uses unknown type '%s'"
  689. % (source, value))
  690. if not all_names[value] in allow_metas:
  691. raise QAPISemError(info, "%s cannot use %s type '%s'" %
  692. (source, all_names[value], value))
  693. return
  694. if not allow_dict:
  695. raise QAPISemError(info, "%s should be a type name" % source)
  696. if not isinstance(value, OrderedDict):
  697. raise QAPISemError(info,
  698. "%s should be an object or type name" % source)
  699. permit_upper = allow_dict in name_case_whitelist
  700. # value is a dictionary, check that each member is okay
  701. for (key, arg) in value.items():
  702. check_name_str(key, info, "member of %s" % source,
  703. allow_optional=True, permit_upper=permit_upper)
  704. if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
  705. raise QAPISemError(
  706. info, "member of %s uses reserved name '%s'" % (source, key))
  707. check_known_keys(arg, info, "member '%s' of %s" % (key, source),
  708. ['type'], ['if'])
  709. check_if(arg, info)
  710. normalize_if(arg)
  711. check_type(arg['type'], info, "member '%s' of %s" % (key, source),
  712. allow_array=True,
  713. allow_metas=['built-in', 'union', 'alternate', 'struct',
  714. 'enum'])
  715. def check_command(expr, info):
  716. name = expr['command']
  717. boxed = expr.get('boxed', False)
  718. args_meta = ['struct']
  719. if boxed:
  720. args_meta += ['union']
  721. check_type(expr.get('data'), info,
  722. "'data' for command '%s'" % name,
  723. allow_dict=not boxed, allow_metas=args_meta)
  724. returns_meta = ['union', 'struct']
  725. if name in returns_whitelist:
  726. returns_meta += ['built-in', 'alternate', 'enum']
  727. check_type(expr.get('returns'), info,
  728. "'returns' for command '%s'" % name,
  729. allow_array=True, allow_metas=returns_meta)
  730. def check_event(expr, info):
  731. name = expr['event']
  732. boxed = expr.get('boxed', False)
  733. meta = ['struct']
  734. if boxed:
  735. meta += ['union']
  736. check_type(expr.get('data'), info,
  737. "'data' for event '%s'" % name,
  738. allow_dict=not boxed, allow_metas=meta)
  739. def enum_get_names(expr):
  740. return [e['name'] for e in expr['data']]
  741. def check_union(expr, info):
  742. name = expr['union']
  743. base = expr.get('base')
  744. discriminator = expr.get('discriminator')
  745. members = expr['data']
  746. # Two types of unions, determined by discriminator.
  747. # With no discriminator it is a simple union.
  748. if discriminator is None:
  749. enum_values = members.keys()
  750. allow_metas = ['built-in', 'union', 'alternate', 'struct', 'enum']
  751. if base is not None:
  752. raise QAPISemError(
  753. info, "simple union '%s' must not have a base" % name)
  754. # Else, it's a flat union.
  755. else:
  756. # The object must have a string or dictionary 'base'.
  757. check_type(base, info, "'base' for union '%s'" % name,
  758. allow_dict=name, allow_metas=['struct'])
  759. if not base:
  760. raise QAPISemError(
  761. info, "flat union '%s' must have a base" % name)
  762. base_members = find_base_members(base)
  763. assert base_members is not None
  764. # The value of member 'discriminator' must name a non-optional
  765. # member of the base struct.
  766. check_name_is_str(discriminator, info,
  767. "discriminator of flat union '%s'" % name)
  768. check_name_str(discriminator, info,
  769. "discriminator of flat union '%s'" % name)
  770. discriminator_value = base_members.get(discriminator)
  771. if not discriminator_value:
  772. raise QAPISemError(info,
  773. "discriminator '%s' is not a member of 'base'"
  774. % discriminator)
  775. if discriminator_value.get('if'):
  776. raise QAPISemError(
  777. info,
  778. "the discriminator '%s' for union %s must not be conditional"
  779. % (discriminator, name))
  780. enum_define = enum_types.get(discriminator_value['type'])
  781. # Do not allow string discriminator
  782. if not enum_define:
  783. raise QAPISemError(
  784. info,
  785. "discriminator '%s' must be of enumeration type"
  786. % discriminator)
  787. enum_values = enum_get_names(enum_define)
  788. allow_metas = ['struct']
  789. if (len(enum_values) == 0):
  790. raise QAPISemError(info, "union '%s' has no branches" % name)
  791. for (key, value) in members.items():
  792. check_name_str(key, info, "member of union '%s'" % name)
  793. check_known_keys(value, info,
  794. "member '%s' of union '%s'" % (key, name),
  795. ['type'], ['if'])
  796. check_if(value, info)
  797. normalize_if(value)
  798. # Each value must name a known type
  799. check_type(value['type'], info,
  800. "member '%s' of union '%s'" % (key, name),
  801. allow_array=not base, allow_metas=allow_metas)
  802. # If the discriminator names an enum type, then all members
  803. # of 'data' must also be members of the enum type.
  804. if discriminator is not None:
  805. if key not in enum_values:
  806. raise QAPISemError(
  807. info,
  808. "discriminator value '%s' is not found in enum '%s'"
  809. % (key, enum_define['enum']))
  810. def check_alternate(expr, info):
  811. name = expr['alternate']
  812. members = expr['data']
  813. types_seen = {}
  814. if len(members) == 0:
  815. raise QAPISemError(info,
  816. "alternate '%s' cannot have empty 'data'" % name)
  817. for (key, value) in members.items():
  818. check_name_str(key, info, "member of alternate '%s'" % name)
  819. check_known_keys(value, info,
  820. "member '%s' of alternate '%s'" % (key, name),
  821. ['type'], ['if'])
  822. check_if(value, info)
  823. normalize_if(value)
  824. typ = value['type']
  825. # Ensure alternates have no type conflicts.
  826. check_type(typ, info, "member '%s' of alternate '%s'" % (key, name),
  827. allow_metas=['built-in', 'union', 'struct', 'enum'])
  828. qtype = find_alternate_member_qtype(typ)
  829. if not qtype:
  830. raise QAPISemError(
  831. info,
  832. "alternate '%s' member '%s' cannot use type '%s'"
  833. % (name, key, typ))
  834. conflicting = set([qtype])
  835. if qtype == 'QTYPE_QSTRING':
  836. enum_expr = enum_types.get(typ)
  837. if enum_expr:
  838. for v in enum_get_names(enum_expr):
  839. if v in ['on', 'off']:
  840. conflicting.add('QTYPE_QBOOL')
  841. if re.match(r'[-+0-9.]', v): # lazy, could be tightened
  842. conflicting.add('QTYPE_QNUM')
  843. else:
  844. conflicting.add('QTYPE_QNUM')
  845. conflicting.add('QTYPE_QBOOL')
  846. for qt in conflicting:
  847. if qt in types_seen:
  848. raise QAPISemError(
  849. info,
  850. "alternate '%s' member '%s' can't be distinguished "
  851. "from member '%s'"
  852. % (name, key, types_seen[qt]))
  853. types_seen[qt] = key
  854. def check_enum(expr, info):
  855. name = expr['enum']
  856. members = expr['data']
  857. prefix = expr.get('prefix')
  858. if not isinstance(members, list):
  859. raise QAPISemError(info,
  860. "enum '%s' requires an array for 'data'" % name)
  861. if prefix is not None and not isinstance(prefix, str):
  862. raise QAPISemError(info,
  863. "enum '%s' requires a string for 'prefix'" % name)
  864. permit_upper = name in name_case_whitelist
  865. for member in members:
  866. check_known_keys(member, info, "member of enum '%s'" % name,
  867. ['name'], ['if'])
  868. check_if(member, info)
  869. normalize_if(member)
  870. check_name(member['name'], info, "member of enum '%s'" % name,
  871. enum_member=True, permit_upper=permit_upper)
  872. def check_struct(expr, info):
  873. name = expr['struct']
  874. members = expr['data']
  875. features = expr.get('features')
  876. check_type(members, info, "'data' for struct '%s'" % name,
  877. allow_dict=name)
  878. check_type(expr.get('base'), info, "'base' for struct '%s'" % name,
  879. allow_metas=['struct'])
  880. if features:
  881. if not isinstance(features, list):
  882. raise QAPISemError(
  883. info, "struct '%s' requires an array for 'features'" % name)
  884. for f in features:
  885. assert isinstance(f, dict)
  886. check_known_keys(f, info, "feature of struct %s" % name,
  887. ['name'], ['if'])
  888. check_if(f, info)
  889. normalize_if(f)
  890. check_name(f['name'], info, "feature of struct %s" % name)
  891. def check_known_keys(value, info, source, required, optional):
  892. def pprint(elems):
  893. return ', '.join("'" + e + "'" for e in sorted(elems))
  894. missing = set(required) - set(value)
  895. if missing:
  896. raise QAPISemError(
  897. info,
  898. "key%s %s %s missing from %s"
  899. % ('s' if len(missing) > 1 else '', pprint(missing),
  900. 'are' if len(missing) > 1 else 'is', source))
  901. allowed = set(required + optional)
  902. unknown = set(value) - allowed
  903. if unknown:
  904. raise QAPISemError(
  905. info,
  906. "unknown key%s %s in %s\nValid keys are %s."
  907. % ('s' if len(unknown) > 1 else '', pprint(unknown),
  908. source, pprint(allowed)))
  909. def check_keys(expr, info, meta, required, optional=[]):
  910. name = expr[meta]
  911. if not isinstance(name, str):
  912. raise QAPISemError(info, "'%s' key must have a string value" % meta)
  913. required = required + [meta]
  914. source = "%s '%s'" % (meta, name)
  915. check_known_keys(expr, info, source, required, optional)
  916. for (key, value) in expr.items():
  917. if key in ['gen', 'success-response'] and value is not False:
  918. raise QAPISemError(info,
  919. "'%s' of %s '%s' should only use false value"
  920. % (key, meta, name))
  921. if (key in ['boxed', 'allow-oob', 'allow-preconfig']
  922. and value is not True):
  923. raise QAPISemError(info,
  924. "'%s' of %s '%s' should only use true value"
  925. % (key, meta, name))
  926. if key == 'if':
  927. check_if(expr, info)
  928. def normalize_enum(expr):
  929. if isinstance(expr['data'], list):
  930. expr['data'] = [m if isinstance(m, dict) else {'name': m}
  931. for m in expr['data']]
  932. def normalize_members(members):
  933. if isinstance(members, OrderedDict):
  934. for key, arg in members.items():
  935. if isinstance(arg, dict):
  936. continue
  937. members[key] = {'type': arg}
  938. def normalize_features(features):
  939. if isinstance(features, list):
  940. features[:] = [f if isinstance(f, dict) else {'name': f}
  941. for f in features]
  942. def normalize_if(expr):
  943. ifcond = expr.get('if')
  944. if isinstance(ifcond, str):
  945. expr['if'] = [ifcond]
  946. def check_exprs(exprs):
  947. global all_names
  948. # Populate name table with names of built-in types
  949. for builtin in builtin_types.keys():
  950. all_names[builtin] = 'built-in'
  951. # Learn the types and check for valid expression keys
  952. for expr_elem in exprs:
  953. expr = expr_elem['expr']
  954. info = expr_elem['info']
  955. doc = expr_elem.get('doc')
  956. if 'include' in expr:
  957. continue
  958. if not doc and doc_required:
  959. raise QAPISemError(info,
  960. "definition missing documentation comment")
  961. if 'enum' in expr:
  962. meta = 'enum'
  963. check_keys(expr, info, 'enum', ['data'], ['if', 'prefix'])
  964. normalize_enum(expr)
  965. enum_types[expr[meta]] = expr
  966. elif 'union' in expr:
  967. meta = 'union'
  968. check_keys(expr, info, 'union', ['data'],
  969. ['base', 'discriminator', 'if'])
  970. normalize_members(expr.get('base'))
  971. normalize_members(expr['data'])
  972. union_types[expr[meta]] = expr
  973. elif 'alternate' in expr:
  974. meta = 'alternate'
  975. check_keys(expr, info, 'alternate', ['data'], ['if'])
  976. normalize_members(expr['data'])
  977. elif 'struct' in expr:
  978. meta = 'struct'
  979. check_keys(expr, info, 'struct', ['data'],
  980. ['base', 'if', 'features'])
  981. normalize_members(expr['data'])
  982. normalize_features(expr.get('features'))
  983. struct_types[expr[meta]] = expr
  984. elif 'command' in expr:
  985. meta = 'command'
  986. check_keys(expr, info, 'command', [],
  987. ['data', 'returns', 'gen', 'success-response',
  988. 'boxed', 'allow-oob', 'allow-preconfig', 'if'])
  989. normalize_members(expr.get('data'))
  990. elif 'event' in expr:
  991. meta = 'event'
  992. check_keys(expr, info, 'event', [], ['data', 'boxed', 'if'])
  993. normalize_members(expr.get('data'))
  994. else:
  995. raise QAPISemError(info, "expression is missing metatype")
  996. normalize_if(expr)
  997. name = expr[meta]
  998. check_name_is_str(name, info, "'%s'" % meta)
  999. info.set_defn(meta, name)
  1000. check_defn_name_str(name, info, meta)
  1001. add_name(name, info, meta)
  1002. if doc and doc.symbol != name:
  1003. raise QAPISemError(
  1004. info,
  1005. "definition of '%s' follows documentation for '%s'"
  1006. % (name, doc.symbol))
  1007. # Validate that exprs make sense
  1008. for expr_elem in exprs:
  1009. expr = expr_elem['expr']
  1010. info = expr_elem['info']
  1011. doc = expr_elem.get('doc')
  1012. if 'include' in expr:
  1013. continue
  1014. if 'enum' in expr:
  1015. check_enum(expr, info)
  1016. elif 'union' in expr:
  1017. check_union(expr, info)
  1018. elif 'alternate' in expr:
  1019. check_alternate(expr, info)
  1020. elif 'struct' in expr:
  1021. check_struct(expr, info)
  1022. elif 'command' in expr:
  1023. check_command(expr, info)
  1024. elif 'event' in expr:
  1025. check_event(expr, info)
  1026. else:
  1027. assert False, 'unexpected meta type'
  1028. if doc:
  1029. doc.check_expr(expr)
  1030. return exprs
  1031. #
  1032. # Schema compiler frontend
  1033. #
  1034. class QAPISchemaEntity(object):
  1035. def __init__(self, name, info, doc, ifcond=None):
  1036. assert name is None or isinstance(name, str)
  1037. self.name = name
  1038. self._module = None
  1039. # For explicitly defined entities, info points to the (explicit)
  1040. # definition. For builtins (and their arrays), info is None.
  1041. # For implicitly defined entities, info points to a place that
  1042. # triggered the implicit definition (there may be more than one
  1043. # such place).
  1044. self.info = info
  1045. self.doc = doc
  1046. self._ifcond = ifcond or []
  1047. self._checked = False
  1048. def c_name(self):
  1049. return c_name(self.name)
  1050. def check(self, schema):
  1051. assert not self._checked
  1052. if self.info:
  1053. self._module = os.path.relpath(self.info.fname,
  1054. os.path.dirname(schema.fname))
  1055. self._checked = True
  1056. @property
  1057. def ifcond(self):
  1058. assert self._checked
  1059. return self._ifcond
  1060. @property
  1061. def module(self):
  1062. assert self._checked
  1063. return self._module
  1064. def is_implicit(self):
  1065. return not self.info
  1066. def visit(self, visitor):
  1067. assert self._checked
  1068. class QAPISchemaVisitor(object):
  1069. def visit_begin(self, schema):
  1070. pass
  1071. def visit_end(self):
  1072. pass
  1073. def visit_module(self, fname):
  1074. pass
  1075. def visit_needed(self, entity):
  1076. # Default to visiting everything
  1077. return True
  1078. def visit_include(self, fname, info):
  1079. pass
  1080. def visit_builtin_type(self, name, info, json_type):
  1081. pass
  1082. def visit_enum_type(self, name, info, ifcond, members, prefix):
  1083. pass
  1084. def visit_array_type(self, name, info, ifcond, element_type):
  1085. pass
  1086. def visit_object_type(self, name, info, ifcond, base, members, variants,
  1087. features):
  1088. pass
  1089. def visit_object_type_flat(self, name, info, ifcond, members, variants,
  1090. features):
  1091. pass
  1092. def visit_alternate_type(self, name, info, ifcond, variants):
  1093. pass
  1094. def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
  1095. success_response, boxed, allow_oob, allow_preconfig):
  1096. pass
  1097. def visit_event(self, name, info, ifcond, arg_type, boxed):
  1098. pass
  1099. class QAPISchemaInclude(QAPISchemaEntity):
  1100. def __init__(self, fname, info):
  1101. QAPISchemaEntity.__init__(self, None, info, None)
  1102. self.fname = fname
  1103. def visit(self, visitor):
  1104. QAPISchemaEntity.visit(self, visitor)
  1105. visitor.visit_include(self.fname, self.info)
  1106. class QAPISchemaType(QAPISchemaEntity):
  1107. # Return the C type for common use.
  1108. # For the types we commonly box, this is a pointer type.
  1109. def c_type(self):
  1110. pass
  1111. # Return the C type to be used in a parameter list.
  1112. def c_param_type(self):
  1113. return self.c_type()
  1114. # Return the C type to be used where we suppress boxing.
  1115. def c_unboxed_type(self):
  1116. return self.c_type()
  1117. def json_type(self):
  1118. pass
  1119. def alternate_qtype(self):
  1120. json2qtype = {
  1121. 'null': 'QTYPE_QNULL',
  1122. 'string': 'QTYPE_QSTRING',
  1123. 'number': 'QTYPE_QNUM',
  1124. 'int': 'QTYPE_QNUM',
  1125. 'boolean': 'QTYPE_QBOOL',
  1126. 'object': 'QTYPE_QDICT'
  1127. }
  1128. return json2qtype.get(self.json_type())
  1129. def doc_type(self):
  1130. if self.is_implicit():
  1131. return None
  1132. return self.name
  1133. class QAPISchemaBuiltinType(QAPISchemaType):
  1134. def __init__(self, name, json_type, c_type):
  1135. QAPISchemaType.__init__(self, name, None, None)
  1136. assert not c_type or isinstance(c_type, str)
  1137. assert json_type in ('string', 'number', 'int', 'boolean', 'null',
  1138. 'value')
  1139. self._json_type_name = json_type
  1140. self._c_type_name = c_type
  1141. def c_name(self):
  1142. return self.name
  1143. def c_type(self):
  1144. return self._c_type_name
  1145. def c_param_type(self):
  1146. if self.name == 'str':
  1147. return 'const ' + self._c_type_name
  1148. return self._c_type_name
  1149. def json_type(self):
  1150. return self._json_type_name
  1151. def doc_type(self):
  1152. return self.json_type()
  1153. def visit(self, visitor):
  1154. QAPISchemaType.visit(self, visitor)
  1155. visitor.visit_builtin_type(self.name, self.info, self.json_type())
  1156. class QAPISchemaEnumType(QAPISchemaType):
  1157. def __init__(self, name, info, doc, ifcond, members, prefix):
  1158. QAPISchemaType.__init__(self, name, info, doc, ifcond)
  1159. for m in members:
  1160. assert isinstance(m, QAPISchemaEnumMember)
  1161. m.set_defined_in(name)
  1162. assert prefix is None or isinstance(prefix, str)
  1163. self.members = members
  1164. self.prefix = prefix
  1165. def check(self, schema):
  1166. QAPISchemaType.check(self, schema)
  1167. seen = {}
  1168. for m in self.members:
  1169. m.check_clash(self.info, seen)
  1170. if self.doc:
  1171. self.doc.connect_member(m)
  1172. def is_implicit(self):
  1173. # See QAPISchema._make_implicit_enum_type() and ._def_predefineds()
  1174. return self.name.endswith('Kind') or self.name == 'QType'
  1175. def c_type(self):
  1176. return c_name(self.name)
  1177. def member_names(self):
  1178. return [m.name for m in self.members]
  1179. def json_type(self):
  1180. return 'string'
  1181. def visit(self, visitor):
  1182. QAPISchemaType.visit(self, visitor)
  1183. visitor.visit_enum_type(self.name, self.info, self.ifcond,
  1184. self.members, self.prefix)
  1185. class QAPISchemaArrayType(QAPISchemaType):
  1186. def __init__(self, name, info, element_type):
  1187. QAPISchemaType.__init__(self, name, info, None, None)
  1188. assert isinstance(element_type, str)
  1189. self._element_type_name = element_type
  1190. self.element_type = None
  1191. def check(self, schema):
  1192. QAPISchemaType.check(self, schema)
  1193. self.element_type = schema.lookup_type(self._element_type_name)
  1194. assert self.element_type
  1195. assert not isinstance(self.element_type, QAPISchemaArrayType)
  1196. @property
  1197. def ifcond(self):
  1198. assert self._checked
  1199. return self.element_type.ifcond
  1200. @property
  1201. def module(self):
  1202. assert self._checked
  1203. return self.element_type.module
  1204. def is_implicit(self):
  1205. return True
  1206. def c_type(self):
  1207. return c_name(self.name) + pointer_suffix
  1208. def json_type(self):
  1209. return 'array'
  1210. def doc_type(self):
  1211. elt_doc_type = self.element_type.doc_type()
  1212. if not elt_doc_type:
  1213. return None
  1214. return 'array of ' + elt_doc_type
  1215. def visit(self, visitor):
  1216. QAPISchemaType.visit(self, visitor)
  1217. visitor.visit_array_type(self.name, self.info, self.ifcond,
  1218. self.element_type)
  1219. class QAPISchemaObjectType(QAPISchemaType):
  1220. def __init__(self, name, info, doc, ifcond,
  1221. base, local_members, variants, features):
  1222. # struct has local_members, optional base, and no variants
  1223. # flat union has base, variants, and no local_members
  1224. # simple union has local_members, variants, and no base
  1225. QAPISchemaType.__init__(self, name, info, doc, ifcond)
  1226. assert base is None or isinstance(base, str)
  1227. for m in local_members:
  1228. assert isinstance(m, QAPISchemaObjectTypeMember)
  1229. m.set_defined_in(name)
  1230. if variants is not None:
  1231. assert isinstance(variants, QAPISchemaObjectTypeVariants)
  1232. variants.set_defined_in(name)
  1233. for f in features:
  1234. assert isinstance(f, QAPISchemaFeature)
  1235. f.set_defined_in(name)
  1236. self._base_name = base
  1237. self.base = None
  1238. self.local_members = local_members
  1239. self.variants = variants
  1240. self.members = None
  1241. self.features = features
  1242. def check(self, schema):
  1243. # This calls another type T's .check() exactly when the C
  1244. # struct emitted by gen_object() contains that T's C struct
  1245. # (pointers don't count).
  1246. if self.members is not None:
  1247. # A previous .check() completed: nothing to do
  1248. return
  1249. if self._checked:
  1250. # Recursed: C struct contains itself
  1251. raise QAPISemError(self.info,
  1252. "object %s contains itself" % self.name)
  1253. QAPISchemaType.check(self, schema)
  1254. assert self._checked and self.members is None
  1255. seen = OrderedDict()
  1256. if self._base_name:
  1257. self.base = schema.lookup_type(self._base_name)
  1258. assert isinstance(self.base, QAPISchemaObjectType)
  1259. self.base.check(schema)
  1260. self.base.check_clash(self.info, seen)
  1261. for m in self.local_members:
  1262. m.check(schema)
  1263. m.check_clash(self.info, seen)
  1264. if self.doc:
  1265. self.doc.connect_member(m)
  1266. members = seen.values()
  1267. if self.variants:
  1268. self.variants.check(schema, seen)
  1269. assert self.variants.tag_member in members
  1270. self.variants.check_clash(self.info, seen)
  1271. # Features are in a name space separate from members
  1272. seen = {}
  1273. for f in self.features:
  1274. f.check_clash(self.info, seen)
  1275. if self.doc:
  1276. self.doc.check()
  1277. self.members = members # mark completed
  1278. # Check that the members of this type do not cause duplicate JSON members,
  1279. # and update seen to track the members seen so far. Report any errors
  1280. # on behalf of info, which is not necessarily self.info
  1281. def check_clash(self, info, seen):
  1282. assert self._checked
  1283. assert not self.variants # not implemented
  1284. for m in self.members:
  1285. m.check_clash(info, seen)
  1286. @property
  1287. def ifcond(self):
  1288. assert self._checked
  1289. if isinstance(self._ifcond, QAPISchemaType):
  1290. # Simple union wrapper type inherits from wrapped type;
  1291. # see _make_implicit_object_type()
  1292. return self._ifcond.ifcond
  1293. return self._ifcond
  1294. def is_implicit(self):
  1295. # See QAPISchema._make_implicit_object_type(), as well as
  1296. # _def_predefineds()
  1297. return self.name.startswith('q_')
  1298. def is_empty(self):
  1299. assert self.members is not None
  1300. return not self.members and not self.variants
  1301. def c_name(self):
  1302. assert self.name != 'q_empty'
  1303. return QAPISchemaType.c_name(self)
  1304. def c_type(self):
  1305. assert not self.is_implicit()
  1306. return c_name(self.name) + pointer_suffix
  1307. def c_unboxed_type(self):
  1308. return c_name(self.name)
  1309. def json_type(self):
  1310. return 'object'
  1311. def visit(self, visitor):
  1312. QAPISchemaType.visit(self, visitor)
  1313. visitor.visit_object_type(self.name, self.info, self.ifcond,
  1314. self.base, self.local_members, self.variants,
  1315. self.features)
  1316. visitor.visit_object_type_flat(self.name, self.info, self.ifcond,
  1317. self.members, self.variants,
  1318. self.features)
  1319. class QAPISchemaMember(object):
  1320. """ Represents object members, enum members and features """
  1321. role = 'member'
  1322. def __init__(self, name, info, ifcond=None):
  1323. assert isinstance(name, str)
  1324. self.name = name
  1325. self.info = info
  1326. self.ifcond = ifcond or []
  1327. self.defined_in = None
  1328. def set_defined_in(self, name):
  1329. assert not self.defined_in
  1330. self.defined_in = name
  1331. def check_clash(self, info, seen):
  1332. cname = c_name(self.name)
  1333. if cname in seen:
  1334. raise QAPISemError(
  1335. info,
  1336. "%s collides with %s"
  1337. % (self.describe(info), seen[cname].describe(info)))
  1338. seen[cname] = self
  1339. def describe(self, info):
  1340. role = self.role
  1341. defined_in = self.defined_in
  1342. assert defined_in
  1343. if defined_in.startswith('q_obj_'):
  1344. # See QAPISchema._make_implicit_object_type() - reverse the
  1345. # mapping there to create a nice human-readable description
  1346. defined_in = defined_in[6:]
  1347. if defined_in.endswith('-arg'):
  1348. # Implicit type created for a command's dict 'data'
  1349. assert role == 'member'
  1350. role = 'parameter'
  1351. elif defined_in.endswith('-base'):
  1352. # Implicit type created for a flat union's dict 'base'
  1353. role = 'base ' + role
  1354. else:
  1355. # Implicit type created for a simple union's branch
  1356. assert defined_in.endswith('-wrapper')
  1357. # Unreachable and not implemented
  1358. assert False
  1359. elif defined_in.endswith('Kind'):
  1360. # See QAPISchema._make_implicit_enum_type()
  1361. # Implicit enum created for simple union's branches
  1362. assert role == 'value'
  1363. role = 'branch'
  1364. elif defined_in != info.defn_name:
  1365. return "%s '%s' of type '%s'" % (role, self.name, defined_in)
  1366. return "%s '%s'" % (role, self.name)
  1367. class QAPISchemaEnumMember(QAPISchemaMember):
  1368. role = 'value'
  1369. class QAPISchemaFeature(QAPISchemaMember):
  1370. role = 'feature'
  1371. class QAPISchemaObjectTypeMember(QAPISchemaMember):
  1372. def __init__(self, name, info, typ, optional, ifcond=None):
  1373. QAPISchemaMember.__init__(self, name, info, ifcond)
  1374. assert isinstance(typ, str)
  1375. assert isinstance(optional, bool)
  1376. self._type_name = typ
  1377. self.type = None
  1378. self.optional = optional
  1379. def check(self, schema):
  1380. assert self.defined_in
  1381. self.type = schema.lookup_type(self._type_name)
  1382. assert self.type
  1383. class QAPISchemaObjectTypeVariants(object):
  1384. def __init__(self, tag_name, info, tag_member, variants):
  1385. # Flat unions pass tag_name but not tag_member.
  1386. # Simple unions and alternates pass tag_member but not tag_name.
  1387. # After check(), tag_member is always set, and tag_name remains
  1388. # a reliable witness of being used by a flat union.
  1389. assert bool(tag_member) != bool(tag_name)
  1390. assert (isinstance(tag_name, str) or
  1391. isinstance(tag_member, QAPISchemaObjectTypeMember))
  1392. for v in variants:
  1393. assert isinstance(v, QAPISchemaObjectTypeVariant)
  1394. self._tag_name = tag_name
  1395. self.info = info
  1396. self.tag_member = tag_member
  1397. self.variants = variants
  1398. def set_defined_in(self, name):
  1399. for v in self.variants:
  1400. v.set_defined_in(name)
  1401. def check(self, schema, seen):
  1402. if not self.tag_member: # flat union
  1403. self.tag_member = seen[c_name(self._tag_name)]
  1404. assert self._tag_name == self.tag_member.name
  1405. assert isinstance(self.tag_member.type, QAPISchemaEnumType)
  1406. assert not self.tag_member.optional
  1407. assert self.tag_member.ifcond == []
  1408. if self._tag_name: # flat union
  1409. # branches that are not explicitly covered get an empty type
  1410. cases = set([v.name for v in self.variants])
  1411. for m in self.tag_member.type.members:
  1412. if m.name not in cases:
  1413. v = QAPISchemaObjectTypeVariant(m.name, self.info,
  1414. 'q_empty', m.ifcond)
  1415. v.set_defined_in(self.tag_member.defined_in)
  1416. self.variants.append(v)
  1417. assert self.variants
  1418. for v in self.variants:
  1419. v.check(schema)
  1420. # Union names must match enum values; alternate names are
  1421. # checked separately. Use 'seen' to tell the two apart.
  1422. if seen:
  1423. assert v.name in self.tag_member.type.member_names()
  1424. assert (isinstance(v.type, QAPISchemaObjectType)
  1425. and not v.type.variants)
  1426. v.type.check(schema)
  1427. def check_clash(self, info, seen):
  1428. for v in self.variants:
  1429. # Reset seen map for each variant, since qapi names from one
  1430. # branch do not affect another branch
  1431. v.type.check_clash(info, dict(seen))
  1432. class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
  1433. role = 'branch'
  1434. def __init__(self, name, info, typ, ifcond=None):
  1435. QAPISchemaObjectTypeMember.__init__(self, name, info, typ,
  1436. False, ifcond)
  1437. class QAPISchemaAlternateType(QAPISchemaType):
  1438. def __init__(self, name, info, doc, ifcond, variants):
  1439. QAPISchemaType.__init__(self, name, info, doc, ifcond)
  1440. assert isinstance(variants, QAPISchemaObjectTypeVariants)
  1441. assert variants.tag_member
  1442. variants.set_defined_in(name)
  1443. variants.tag_member.set_defined_in(self.name)
  1444. self.variants = variants
  1445. def check(self, schema):
  1446. QAPISchemaType.check(self, schema)
  1447. self.variants.tag_member.check(schema)
  1448. # Not calling self.variants.check_clash(), because there's nothing
  1449. # to clash with
  1450. self.variants.check(schema, {})
  1451. # Alternate branch names have no relation to the tag enum values;
  1452. # so we have to check for potential name collisions ourselves.
  1453. seen = {}
  1454. for v in self.variants.variants:
  1455. v.check_clash(self.info, seen)
  1456. # TODO check conflicting qtypes
  1457. if self.doc:
  1458. self.doc.connect_member(v)
  1459. if self.doc:
  1460. self.doc.check()
  1461. def c_type(self):
  1462. return c_name(self.name) + pointer_suffix
  1463. def json_type(self):
  1464. return 'value'
  1465. def visit(self, visitor):
  1466. QAPISchemaType.visit(self, visitor)
  1467. visitor.visit_alternate_type(self.name, self.info, self.ifcond,
  1468. self.variants)
  1469. class QAPISchemaCommand(QAPISchemaEntity):
  1470. def __init__(self, name, info, doc, ifcond, arg_type, ret_type,
  1471. gen, success_response, boxed, allow_oob, allow_preconfig):
  1472. QAPISchemaEntity.__init__(self, name, info, doc, ifcond)
  1473. assert not arg_type or isinstance(arg_type, str)
  1474. assert not ret_type or isinstance(ret_type, str)
  1475. self._arg_type_name = arg_type
  1476. self.arg_type = None
  1477. self._ret_type_name = ret_type
  1478. self.ret_type = None
  1479. self.gen = gen
  1480. self.success_response = success_response
  1481. self.boxed = boxed
  1482. self.allow_oob = allow_oob
  1483. self.allow_preconfig = allow_preconfig
  1484. def check(self, schema):
  1485. QAPISchemaEntity.check(self, schema)
  1486. if self._arg_type_name:
  1487. self.arg_type = schema.lookup_type(self._arg_type_name)
  1488. assert isinstance(self.arg_type, QAPISchemaObjectType)
  1489. assert not self.arg_type.variants or self.boxed
  1490. elif self.boxed:
  1491. raise QAPISemError(self.info, "use of 'boxed' requires 'data'")
  1492. if self._ret_type_name:
  1493. self.ret_type = schema.lookup_type(self._ret_type_name)
  1494. assert isinstance(self.ret_type, QAPISchemaType)
  1495. def visit(self, visitor):
  1496. QAPISchemaEntity.visit(self, visitor)
  1497. visitor.visit_command(self.name, self.info, self.ifcond,
  1498. self.arg_type, self.ret_type,
  1499. self.gen, self.success_response,
  1500. self.boxed, self.allow_oob,
  1501. self.allow_preconfig)
  1502. class QAPISchemaEvent(QAPISchemaEntity):
  1503. def __init__(self, name, info, doc, ifcond, arg_type, boxed):
  1504. QAPISchemaEntity.__init__(self, name, info, doc, ifcond)
  1505. assert not arg_type or isinstance(arg_type, str)
  1506. self._arg_type_name = arg_type
  1507. self.arg_type = None
  1508. self.boxed = boxed
  1509. def check(self, schema):
  1510. QAPISchemaEntity.check(self, schema)
  1511. if self._arg_type_name:
  1512. self.arg_type = schema.lookup_type(self._arg_type_name)
  1513. assert isinstance(self.arg_type, QAPISchemaObjectType)
  1514. assert not self.arg_type.variants or self.boxed
  1515. elif self.boxed:
  1516. raise QAPISemError(self.info, "use of 'boxed' requires 'data'")
  1517. def visit(self, visitor):
  1518. QAPISchemaEntity.visit(self, visitor)
  1519. visitor.visit_event(self.name, self.info, self.ifcond,
  1520. self.arg_type, self.boxed)
  1521. class QAPISchema(object):
  1522. def __init__(self, fname):
  1523. self.fname = fname
  1524. if sys.version_info[0] >= 3:
  1525. f = open(fname, 'r', encoding='utf-8')
  1526. else:
  1527. f = open(fname, 'r')
  1528. parser = QAPISchemaParser(f)
  1529. exprs = check_exprs(parser.exprs)
  1530. self.docs = parser.docs
  1531. self._entity_list = []
  1532. self._entity_dict = {}
  1533. self._predefining = True
  1534. self._def_predefineds()
  1535. self._predefining = False
  1536. self._def_exprs(exprs)
  1537. self.check()
  1538. def _def_entity(self, ent):
  1539. # Only the predefined types are allowed to not have info
  1540. assert ent.info or self._predefining
  1541. assert ent.name is None or ent.name not in self._entity_dict
  1542. self._entity_list.append(ent)
  1543. if ent.name is not None:
  1544. self._entity_dict[ent.name] = ent
  1545. def lookup_entity(self, name, typ=None):
  1546. ent = self._entity_dict.get(name)
  1547. if typ and not isinstance(ent, typ):
  1548. return None
  1549. return ent
  1550. def lookup_type(self, name):
  1551. return self.lookup_entity(name, QAPISchemaType)
  1552. def _def_include(self, expr, info, doc):
  1553. include = expr['include']
  1554. assert doc is None
  1555. main_info = info
  1556. while main_info.parent:
  1557. main_info = main_info.parent
  1558. fname = os.path.relpath(include, os.path.dirname(main_info.fname))
  1559. self._def_entity(QAPISchemaInclude(fname, info))
  1560. def _def_builtin_type(self, name, json_type, c_type):
  1561. self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type))
  1562. # Instantiating only the arrays that are actually used would
  1563. # be nice, but we can't as long as their generated code
  1564. # (qapi-builtin-types.[ch]) may be shared by some other
  1565. # schema.
  1566. self._make_array_type(name, None)
  1567. def _def_predefineds(self):
  1568. for t in [('str', 'string', 'char' + pointer_suffix),
  1569. ('number', 'number', 'double'),
  1570. ('int', 'int', 'int64_t'),
  1571. ('int8', 'int', 'int8_t'),
  1572. ('int16', 'int', 'int16_t'),
  1573. ('int32', 'int', 'int32_t'),
  1574. ('int64', 'int', 'int64_t'),
  1575. ('uint8', 'int', 'uint8_t'),
  1576. ('uint16', 'int', 'uint16_t'),
  1577. ('uint32', 'int', 'uint32_t'),
  1578. ('uint64', 'int', 'uint64_t'),
  1579. ('size', 'int', 'uint64_t'),
  1580. ('bool', 'boolean', 'bool'),
  1581. ('any', 'value', 'QObject' + pointer_suffix),
  1582. ('null', 'null', 'QNull' + pointer_suffix)]:
  1583. self._def_builtin_type(*t)
  1584. self.the_empty_object_type = QAPISchemaObjectType(
  1585. 'q_empty', None, None, None, None, [], None, [])
  1586. self._def_entity(self.the_empty_object_type)
  1587. qtypes = ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist',
  1588. 'qbool']
  1589. qtype_values = self._make_enum_members(
  1590. [{'name': n} for n in qtypes], None)
  1591. self._def_entity(QAPISchemaEnumType('QType', None, None, None,
  1592. qtype_values, 'QTYPE'))
  1593. def _make_features(self, features, info):
  1594. return [QAPISchemaFeature(f['name'], info, f.get('if'))
  1595. for f in features]
  1596. def _make_enum_members(self, values, info):
  1597. return [QAPISchemaEnumMember(v['name'], info, v.get('if'))
  1598. for v in values]
  1599. def _make_implicit_enum_type(self, name, info, ifcond, values):
  1600. # See also QAPISchemaObjectTypeMember.describe()
  1601. name = name + 'Kind' # reserved by check_defn_name_str()
  1602. self._def_entity(QAPISchemaEnumType(
  1603. name, info, None, ifcond, self._make_enum_members(values, info),
  1604. None))
  1605. return name
  1606. def _make_array_type(self, element_type, info):
  1607. name = element_type + 'List' # reserved by check_defn_name_str()
  1608. if not self.lookup_type(name):
  1609. self._def_entity(QAPISchemaArrayType(name, info, element_type))
  1610. return name
  1611. def _make_implicit_object_type(self, name, info, doc, ifcond,
  1612. role, members):
  1613. if not members:
  1614. return None
  1615. # See also QAPISchemaObjectTypeMember.describe()
  1616. name = 'q_obj_%s-%s' % (name, role)
  1617. typ = self.lookup_entity(name, QAPISchemaObjectType)
  1618. if typ:
  1619. # The implicit object type has multiple users. This can
  1620. # happen only for simple unions' implicit wrapper types.
  1621. # Its ifcond should be the disjunction of its user's
  1622. # ifconds. Not implemented. Instead, we always pass the
  1623. # wrapped type's ifcond, which is trivially the same for all
  1624. # users. It's also necessary for the wrapper to compile.
  1625. # But it's not tight: the disjunction need not imply it. We
  1626. # may end up compiling useless wrapper types.
  1627. # TODO kill simple unions or implement the disjunction
  1628. assert ifcond == typ._ifcond # pylint: disable=protected-access
  1629. else:
  1630. self._def_entity(QAPISchemaObjectType(name, info, doc, ifcond,
  1631. None, members, None, []))
  1632. return name
  1633. def _def_enum_type(self, expr, info, doc):
  1634. name = expr['enum']
  1635. data = expr['data']
  1636. prefix = expr.get('prefix')
  1637. ifcond = expr.get('if')
  1638. self._def_entity(QAPISchemaEnumType(
  1639. name, info, doc, ifcond,
  1640. self._make_enum_members(data, info), prefix))
  1641. def _make_member(self, name, typ, ifcond, info):
  1642. optional = False
  1643. if name.startswith('*'):
  1644. name = name[1:]
  1645. optional = True
  1646. if isinstance(typ, list):
  1647. assert len(typ) == 1
  1648. typ = self._make_array_type(typ[0], info)
  1649. return QAPISchemaObjectTypeMember(name, info, typ, optional, ifcond)
  1650. def _make_members(self, data, info):
  1651. return [self._make_member(key, value['type'], value.get('if'), info)
  1652. for (key, value) in data.items()]
  1653. def _def_struct_type(self, expr, info, doc):
  1654. name = expr['struct']
  1655. base = expr.get('base')
  1656. data = expr['data']
  1657. ifcond = expr.get('if')
  1658. features = expr.get('features', [])
  1659. self._def_entity(QAPISchemaObjectType(
  1660. name, info, doc, ifcond, base,
  1661. self._make_members(data, info),
  1662. None,
  1663. self._make_features(features, info)))
  1664. def _make_variant(self, case, typ, ifcond, info):
  1665. return QAPISchemaObjectTypeVariant(case, info, typ, ifcond)
  1666. def _make_simple_variant(self, case, typ, ifcond, info):
  1667. if isinstance(typ, list):
  1668. assert len(typ) == 1
  1669. typ = self._make_array_type(typ[0], info)
  1670. typ = self._make_implicit_object_type(
  1671. typ, info, None, self.lookup_type(typ),
  1672. 'wrapper', [self._make_member('data', typ, None, info)])
  1673. return QAPISchemaObjectTypeVariant(case, info, typ, ifcond)
  1674. def _def_union_type(self, expr, info, doc):
  1675. name = expr['union']
  1676. data = expr['data']
  1677. base = expr.get('base')
  1678. ifcond = expr.get('if')
  1679. tag_name = expr.get('discriminator')
  1680. tag_member = None
  1681. if isinstance(base, dict):
  1682. base = self._make_implicit_object_type(
  1683. name, info, doc, ifcond,
  1684. 'base', self._make_members(base, info))
  1685. if tag_name:
  1686. variants = [self._make_variant(key, value['type'],
  1687. value.get('if'), info)
  1688. for (key, value) in data.items()]
  1689. members = []
  1690. else:
  1691. variants = [self._make_simple_variant(key, value['type'],
  1692. value.get('if'), info)
  1693. for (key, value) in data.items()]
  1694. enum = [{'name': v.name, 'if': v.ifcond} for v in variants]
  1695. typ = self._make_implicit_enum_type(name, info, ifcond, enum)
  1696. tag_member = QAPISchemaObjectTypeMember('type', info, typ, False)
  1697. members = [tag_member]
  1698. self._def_entity(
  1699. QAPISchemaObjectType(name, info, doc, ifcond, base, members,
  1700. QAPISchemaObjectTypeVariants(
  1701. tag_name, info, tag_member, variants),
  1702. []))
  1703. def _def_alternate_type(self, expr, info, doc):
  1704. name = expr['alternate']
  1705. data = expr['data']
  1706. ifcond = expr.get('if')
  1707. variants = [self._make_variant(key, value['type'], value.get('if'),
  1708. info)
  1709. for (key, value) in data.items()]
  1710. tag_member = QAPISchemaObjectTypeMember('type', info, 'QType', False)
  1711. self._def_entity(
  1712. QAPISchemaAlternateType(name, info, doc, ifcond,
  1713. QAPISchemaObjectTypeVariants(
  1714. None, info, tag_member, variants)))
  1715. def _def_command(self, expr, info, doc):
  1716. name = expr['command']
  1717. data = expr.get('data')
  1718. rets = expr.get('returns')
  1719. gen = expr.get('gen', True)
  1720. success_response = expr.get('success-response', True)
  1721. boxed = expr.get('boxed', False)
  1722. allow_oob = expr.get('allow-oob', False)
  1723. allow_preconfig = expr.get('allow-preconfig', False)
  1724. ifcond = expr.get('if')
  1725. if isinstance(data, OrderedDict):
  1726. data = self._make_implicit_object_type(
  1727. name, info, doc, ifcond, 'arg', self._make_members(data, info))
  1728. if isinstance(rets, list):
  1729. assert len(rets) == 1
  1730. rets = self._make_array_type(rets[0], info)
  1731. self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, data, rets,
  1732. gen, success_response,
  1733. boxed, allow_oob, allow_preconfig))
  1734. def _def_event(self, expr, info, doc):
  1735. name = expr['event']
  1736. data = expr.get('data')
  1737. boxed = expr.get('boxed', False)
  1738. ifcond = expr.get('if')
  1739. if isinstance(data, OrderedDict):
  1740. data = self._make_implicit_object_type(
  1741. name, info, doc, ifcond, 'arg', self._make_members(data, info))
  1742. self._def_entity(QAPISchemaEvent(name, info, doc, ifcond, data, boxed))
  1743. def _def_exprs(self, exprs):
  1744. for expr_elem in exprs:
  1745. expr = expr_elem['expr']
  1746. info = expr_elem['info']
  1747. doc = expr_elem.get('doc')
  1748. if 'enum' in expr:
  1749. self._def_enum_type(expr, info, doc)
  1750. elif 'struct' in expr:
  1751. self._def_struct_type(expr, info, doc)
  1752. elif 'union' in expr:
  1753. self._def_union_type(expr, info, doc)
  1754. elif 'alternate' in expr:
  1755. self._def_alternate_type(expr, info, doc)
  1756. elif 'command' in expr:
  1757. self._def_command(expr, info, doc)
  1758. elif 'event' in expr:
  1759. self._def_event(expr, info, doc)
  1760. elif 'include' in expr:
  1761. self._def_include(expr, info, doc)
  1762. else:
  1763. assert False
  1764. def check(self):
  1765. for ent in self._entity_list:
  1766. ent.check(self)
  1767. def visit(self, visitor):
  1768. visitor.visit_begin(self)
  1769. module = None
  1770. visitor.visit_module(module)
  1771. for entity in self._entity_list:
  1772. if visitor.visit_needed(entity):
  1773. if entity.module != module:
  1774. module = entity.module
  1775. visitor.visit_module(module)
  1776. entity.visit(visitor)
  1777. visitor.visit_end()
  1778. #
  1779. # Code generation helpers
  1780. #
  1781. def camel_case(name):
  1782. new_name = ''
  1783. first = True
  1784. for ch in name:
  1785. if ch in ['_', '-']:
  1786. first = True
  1787. elif first:
  1788. new_name += ch.upper()
  1789. first = False
  1790. else:
  1791. new_name += ch.lower()
  1792. return new_name
  1793. # ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
  1794. # ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
  1795. # ENUM24_Name -> ENUM24_NAME
  1796. def camel_to_upper(value):
  1797. c_fun_str = c_name(value, False)
  1798. if value.isupper():
  1799. return c_fun_str
  1800. new_name = ''
  1801. length = len(c_fun_str)
  1802. for i in range(length):
  1803. c = c_fun_str[i]
  1804. # When c is upper and no '_' appears before, do more checks
  1805. if c.isupper() and (i > 0) and c_fun_str[i - 1] != '_':
  1806. if i < length - 1 and c_fun_str[i + 1].islower():
  1807. new_name += '_'
  1808. elif c_fun_str[i - 1].isdigit():
  1809. new_name += '_'
  1810. new_name += c
  1811. return new_name.lstrip('_').upper()
  1812. def c_enum_const(type_name, const_name, prefix=None):
  1813. if prefix is not None:
  1814. type_name = prefix
  1815. return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper()
  1816. if hasattr(str, 'maketrans'):
  1817. c_name_trans = str.maketrans('.-', '__')
  1818. else:
  1819. c_name_trans = string.maketrans('.-', '__')
  1820. # Map @name to a valid C identifier.
  1821. # If @protect, avoid returning certain ticklish identifiers (like
  1822. # C keywords) by prepending 'q_'.
  1823. #
  1824. # Used for converting 'name' from a 'name':'type' qapi definition
  1825. # into a generated struct member, as well as converting type names
  1826. # into substrings of a generated C function name.
  1827. # '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
  1828. # protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
  1829. def c_name(name, protect=True):
  1830. # ANSI X3J11/88-090, 3.1.1
  1831. c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
  1832. 'default', 'do', 'double', 'else', 'enum', 'extern',
  1833. 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
  1834. 'return', 'short', 'signed', 'sizeof', 'static',
  1835. 'struct', 'switch', 'typedef', 'union', 'unsigned',
  1836. 'void', 'volatile', 'while'])
  1837. # ISO/IEC 9899:1999, 6.4.1
  1838. c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
  1839. # ISO/IEC 9899:2011, 6.4.1
  1840. c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
  1841. '_Noreturn', '_Static_assert', '_Thread_local'])
  1842. # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
  1843. # excluding _.*
  1844. gcc_words = set(['asm', 'typeof'])
  1845. # C++ ISO/IEC 14882:2003 2.11
  1846. cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
  1847. 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
  1848. 'namespace', 'new', 'operator', 'private', 'protected',
  1849. 'public', 'reinterpret_cast', 'static_cast', 'template',
  1850. 'this', 'throw', 'true', 'try', 'typeid', 'typename',
  1851. 'using', 'virtual', 'wchar_t',
  1852. # alternative representations
  1853. 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
  1854. 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
  1855. # namespace pollution:
  1856. polluted_words = set(['unix', 'errno', 'mips', 'sparc', 'i386'])
  1857. name = name.translate(c_name_trans)
  1858. if protect and (name in c89_words | c99_words | c11_words | gcc_words
  1859. | cpp_words | polluted_words):
  1860. return 'q_' + name
  1861. return name
  1862. eatspace = '\033EATSPACE.'
  1863. pointer_suffix = ' *' + eatspace
  1864. def genindent(count):
  1865. ret = ''
  1866. for _ in range(count):
  1867. ret += ' '
  1868. return ret
  1869. indent_level = 0
  1870. def push_indent(indent_amount=4):
  1871. global indent_level
  1872. indent_level += indent_amount
  1873. def pop_indent(indent_amount=4):
  1874. global indent_level
  1875. indent_level -= indent_amount
  1876. # Generate @code with @kwds interpolated.
  1877. # Obey indent_level, and strip eatspace.
  1878. def cgen(code, **kwds):
  1879. raw = code % kwds
  1880. if indent_level:
  1881. indent = genindent(indent_level)
  1882. # re.subn() lacks flags support before Python 2.7, use re.compile()
  1883. raw = re.subn(re.compile(r'^(?!(#|$))', re.MULTILINE),
  1884. indent, raw)
  1885. raw = raw[0]
  1886. return re.sub(re.escape(eatspace) + r' *', '', raw)
  1887. def mcgen(code, **kwds):
  1888. if code[0] == '\n':
  1889. code = code[1:]
  1890. return cgen(code, **kwds)
  1891. def c_fname(filename):
  1892. return re.sub(r'[^A-Za-z0-9_]', '_', filename)
  1893. def guardstart(name):
  1894. return mcgen('''
  1895. #ifndef %(name)s
  1896. #define %(name)s
  1897. ''',
  1898. name=c_fname(name).upper())
  1899. def guardend(name):
  1900. return mcgen('''
  1901. #endif /* %(name)s */
  1902. ''',
  1903. name=c_fname(name).upper())
  1904. def gen_if(ifcond):
  1905. ret = ''
  1906. for ifc in ifcond:
  1907. ret += mcgen('''
  1908. #if %(cond)s
  1909. ''', cond=ifc)
  1910. return ret
  1911. def gen_endif(ifcond):
  1912. ret = ''
  1913. for ifc in reversed(ifcond):
  1914. ret += mcgen('''
  1915. #endif /* %(cond)s */
  1916. ''', cond=ifc)
  1917. return ret
  1918. def _wrap_ifcond(ifcond, before, after):
  1919. if before == after:
  1920. return after # suppress empty #if ... #endif
  1921. assert after.startswith(before)
  1922. out = before
  1923. added = after[len(before):]
  1924. if added[0] == '\n':
  1925. out += '\n'
  1926. added = added[1:]
  1927. out += gen_if(ifcond)
  1928. out += added
  1929. out += gen_endif(ifcond)
  1930. return out
  1931. def gen_enum_lookup(name, members, prefix=None):
  1932. ret = mcgen('''
  1933. const QEnumLookup %(c_name)s_lookup = {
  1934. .array = (const char *const[]) {
  1935. ''',
  1936. c_name=c_name(name))
  1937. for m in members:
  1938. ret += gen_if(m.ifcond)
  1939. index = c_enum_const(name, m.name, prefix)
  1940. ret += mcgen('''
  1941. [%(index)s] = "%(name)s",
  1942. ''',
  1943. index=index, name=m.name)
  1944. ret += gen_endif(m.ifcond)
  1945. ret += mcgen('''
  1946. },
  1947. .size = %(max_index)s
  1948. };
  1949. ''',
  1950. max_index=c_enum_const(name, '_MAX', prefix))
  1951. return ret
  1952. def gen_enum(name, members, prefix=None):
  1953. # append automatically generated _MAX value
  1954. enum_members = members + [QAPISchemaEnumMember('_MAX', None)]
  1955. ret = mcgen('''
  1956. typedef enum %(c_name)s {
  1957. ''',
  1958. c_name=c_name(name))
  1959. for m in enum_members:
  1960. ret += gen_if(m.ifcond)
  1961. ret += mcgen('''
  1962. %(c_enum)s,
  1963. ''',
  1964. c_enum=c_enum_const(name, m.name, prefix))
  1965. ret += gen_endif(m.ifcond)
  1966. ret += mcgen('''
  1967. } %(c_name)s;
  1968. ''',
  1969. c_name=c_name(name))
  1970. ret += mcgen('''
  1971. #define %(c_name)s_str(val) \\
  1972. qapi_enum_lookup(&%(c_name)s_lookup, (val))
  1973. extern const QEnumLookup %(c_name)s_lookup;
  1974. ''',
  1975. c_name=c_name(name))
  1976. return ret
  1977. def build_params(arg_type, boxed, extra=None):
  1978. ret = ''
  1979. sep = ''
  1980. if boxed:
  1981. assert arg_type
  1982. ret += '%s arg' % arg_type.c_param_type()
  1983. sep = ', '
  1984. elif arg_type:
  1985. assert not arg_type.variants
  1986. for memb in arg_type.members:
  1987. ret += sep
  1988. sep = ', '
  1989. if memb.optional:
  1990. ret += 'bool has_%s, ' % c_name(memb.name)
  1991. ret += '%s %s' % (memb.type.c_param_type(),
  1992. c_name(memb.name))
  1993. if extra:
  1994. ret += sep + extra
  1995. return ret if ret else 'void'
  1996. #
  1997. # Accumulate and write output
  1998. #
  1999. class QAPIGen(object):
  2000. def __init__(self, fname):
  2001. self.fname = fname
  2002. self._preamble = ''
  2003. self._body = ''
  2004. def preamble_add(self, text):
  2005. self._preamble += text
  2006. def add(self, text):
  2007. self._body += text
  2008. def get_content(self):
  2009. return self._top() + self._preamble + self._body + self._bottom()
  2010. def _top(self):
  2011. return ''
  2012. def _bottom(self):
  2013. return ''
  2014. def write(self, output_dir):
  2015. pathname = os.path.join(output_dir, self.fname)
  2016. dir = os.path.dirname(pathname)
  2017. if dir:
  2018. try:
  2019. os.makedirs(dir)
  2020. except os.error as e:
  2021. if e.errno != errno.EEXIST:
  2022. raise
  2023. fd = os.open(pathname, os.O_RDWR | os.O_CREAT, 0o666)
  2024. if sys.version_info[0] >= 3:
  2025. f = open(fd, 'r+', encoding='utf-8')
  2026. else:
  2027. f = os.fdopen(fd, 'r+')
  2028. text = self.get_content()
  2029. oldtext = f.read(len(text) + 1)
  2030. if text != oldtext:
  2031. f.seek(0)
  2032. f.truncate(0)
  2033. f.write(text)
  2034. f.close()
  2035. @contextmanager
  2036. def ifcontext(ifcond, *args):
  2037. """A 'with' statement context manager to wrap with start_if()/end_if()
  2038. *args: any number of QAPIGenCCode
  2039. Example::
  2040. with ifcontext(ifcond, self._genh, self._genc):
  2041. modify self._genh and self._genc ...
  2042. Is equivalent to calling::
  2043. self._genh.start_if(ifcond)
  2044. self._genc.start_if(ifcond)
  2045. modify self._genh and self._genc ...
  2046. self._genh.end_if()
  2047. self._genc.end_if()
  2048. """
  2049. for arg in args:
  2050. arg.start_if(ifcond)
  2051. yield
  2052. for arg in args:
  2053. arg.end_if()
  2054. class QAPIGenCCode(QAPIGen):
  2055. def __init__(self, fname):
  2056. QAPIGen.__init__(self, fname)
  2057. self._start_if = None
  2058. def start_if(self, ifcond):
  2059. assert self._start_if is None
  2060. self._start_if = (ifcond, self._body, self._preamble)
  2061. def end_if(self):
  2062. assert self._start_if
  2063. self._wrap_ifcond()
  2064. self._start_if = None
  2065. def _wrap_ifcond(self):
  2066. self._body = _wrap_ifcond(self._start_if[0],
  2067. self._start_if[1], self._body)
  2068. self._preamble = _wrap_ifcond(self._start_if[0],
  2069. self._start_if[2], self._preamble)
  2070. def get_content(self):
  2071. assert self._start_if is None
  2072. return QAPIGen.get_content(self)
  2073. class QAPIGenC(QAPIGenCCode):
  2074. def __init__(self, fname, blurb, pydoc):
  2075. QAPIGenCCode.__init__(self, fname)
  2076. self._blurb = blurb
  2077. self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
  2078. re.MULTILINE))
  2079. def _top(self):
  2080. return mcgen('''
  2081. /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
  2082. /*
  2083. %(blurb)s
  2084. *
  2085. * %(copyright)s
  2086. *
  2087. * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
  2088. * See the COPYING.LIB file in the top-level directory.
  2089. */
  2090. ''',
  2091. blurb=self._blurb, copyright=self._copyright)
  2092. def _bottom(self):
  2093. return mcgen('''
  2094. /* Dummy declaration to prevent empty .o file */
  2095. char qapi_dummy_%(name)s;
  2096. ''',
  2097. name=c_fname(self.fname))
  2098. class QAPIGenH(QAPIGenC):
  2099. def _top(self):
  2100. return QAPIGenC._top(self) + guardstart(self.fname)
  2101. def _bottom(self):
  2102. return guardend(self.fname)
  2103. class QAPIGenDoc(QAPIGen):
  2104. def _top(self):
  2105. return (QAPIGen._top(self)
  2106. + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
  2107. class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
  2108. def __init__(self, prefix, what, blurb, pydoc):
  2109. self._prefix = prefix
  2110. self._what = what
  2111. self._genc = QAPIGenC(self._prefix + self._what + '.c',
  2112. blurb, pydoc)
  2113. self._genh = QAPIGenH(self._prefix + self._what + '.h',
  2114. blurb, pydoc)
  2115. def write(self, output_dir):
  2116. self._genc.write(output_dir)
  2117. self._genh.write(output_dir)
  2118. class QAPISchemaModularCVisitor(QAPISchemaVisitor):
  2119. def __init__(self, prefix, what, blurb, pydoc):
  2120. self._prefix = prefix
  2121. self._what = what
  2122. self._blurb = blurb
  2123. self._pydoc = pydoc
  2124. self._genc = None
  2125. self._genh = None
  2126. self._module = {}
  2127. self._main_module = None
  2128. @staticmethod
  2129. def _is_user_module(name):
  2130. return name and not name.startswith('./')
  2131. @staticmethod
  2132. def _is_builtin_module(name):
  2133. return not name
  2134. def _module_dirname(self, what, name):
  2135. if self._is_user_module(name):
  2136. return os.path.dirname(name)
  2137. return ''
  2138. def _module_basename(self, what, name):
  2139. ret = '' if self._is_builtin_module(name) else self._prefix
  2140. if self._is_user_module(name):
  2141. basename = os.path.basename(name)
  2142. ret += what
  2143. if name != self._main_module:
  2144. ret += '-' + os.path.splitext(basename)[0]
  2145. else:
  2146. name = name[2:] if name else 'builtin'
  2147. ret += re.sub(r'-', '-' + name + '-', what)
  2148. return ret
  2149. def _module_filename(self, what, name):
  2150. return os.path.join(self._module_dirname(what, name),
  2151. self._module_basename(what, name))
  2152. def _add_module(self, name, blurb):
  2153. basename = self._module_filename(self._what, name)
  2154. genc = QAPIGenC(basename + '.c', blurb, self._pydoc)
  2155. genh = QAPIGenH(basename + '.h', blurb, self._pydoc)
  2156. self._module[name] = (genc, genh)
  2157. self._set_module(name)
  2158. def _add_user_module(self, name, blurb):
  2159. assert self._is_user_module(name)
  2160. if self._main_module is None:
  2161. self._main_module = name
  2162. self._add_module(name, blurb)
  2163. def _add_system_module(self, name, blurb):
  2164. self._add_module(name and './' + name, blurb)
  2165. def _set_module(self, name):
  2166. self._genc, self._genh = self._module[name]
  2167. def write(self, output_dir, opt_builtins=False):
  2168. for name in self._module:
  2169. if self._is_builtin_module(name) and not opt_builtins:
  2170. continue
  2171. (genc, genh) = self._module[name]
  2172. genc.write(output_dir)
  2173. genh.write(output_dir)
  2174. def _begin_user_module(self, name):
  2175. pass
  2176. def visit_module(self, name):
  2177. if name in self._module:
  2178. self._set_module(name)
  2179. elif self._is_builtin_module(name):
  2180. # The built-in module has not been created. No code may
  2181. # be generated.
  2182. self._genc = None
  2183. self._genh = None
  2184. else:
  2185. self._add_user_module(name, self._blurb)
  2186. self._begin_user_module(name)
  2187. def visit_include(self, name, info):
  2188. relname = os.path.relpath(self._module_filename(self._what, name),
  2189. os.path.dirname(self._genh.fname))
  2190. self._genh.preamble_add(mcgen('''
  2191. #include "%(relname)s.h"
  2192. ''',
  2193. relname=relname))