blob: b2d071f92d94c98789ec7a9ed8f7bdb8816a2a3e [file] [log] [blame]
Michael Roth0f923be2011-07-19 14:50:39 -05001#
2# QAPI helper library
3#
4# Copyright IBM, Corp. 2011
Eric Blakefe2a9302015-05-04 09:05:02 -06005# Copyright (c) 2013-2015 Red Hat Inc.
Michael Roth0f923be2011-07-19 14:50:39 -05006#
7# Authors:
8# Anthony Liguori <aliguori@us.ibm.com>
Markus Armbrusterc7a3f252013-07-27 17:41:55 +02009# Markus Armbruster <armbru@redhat.com>
Michael Roth0f923be2011-07-19 14:50:39 -050010#
Markus Armbruster678e48a2014-03-01 08:40:34 +010011# This work is licensed under the terms of the GNU GPL, version 2.
12# See the COPYING file in the top-level directory.
Michael Roth0f923be2011-07-19 14:50:39 -050013
Lluís Vilanovaa719a272014-05-07 20:46:15 +020014import re
Michael Roth0f923be2011-07-19 14:50:39 -050015from ordereddict import OrderedDict
Markus Armbruster12f8e1b2015-04-02 14:46:39 +020016import errno
Markus Armbruster2114f5a2015-04-02 13:12:21 +020017import getopt
Lluís Vilanova33aaad52014-05-02 15:52:35 +020018import os
Markus Armbruster2caba362013-07-27 17:41:56 +020019import sys
Markus Armbruster47299262015-05-14 06:50:47 -060020import string
Michael Roth0f923be2011-07-19 14:50:39 -050021
Eric Blakeb52c4b92015-05-04 09:05:00 -060022builtin_types = {
Kevin Wolf69dd62d2013-07-08 16:14:21 +020023 'str': 'QTYPE_QSTRING',
24 'int': 'QTYPE_QINT',
25 'number': 'QTYPE_QFLOAT',
26 'bool': 'QTYPE_QBOOL',
27 'int8': 'QTYPE_QINT',
28 'int16': 'QTYPE_QINT',
29 'int32': 'QTYPE_QINT',
30 'int64': 'QTYPE_QINT',
31 'uint8': 'QTYPE_QINT',
32 'uint16': 'QTYPE_QINT',
33 'uint32': 'QTYPE_QINT',
34 'uint64': 'QTYPE_QINT',
Eric Blakecb17f792015-05-04 09:05:01 -060035 'size': 'QTYPE_QINT',
Markus Armbruster28770e02015-09-16 13:06:24 +020036 'any': None, # any qtype_code possible, actually
Kevin Wolf69dd62d2013-07-08 16:14:21 +020037}
38
Eric Blake10d4d992015-05-04 09:05:23 -060039# Whitelist of commands allowed to return a non-dictionary
40returns_whitelist = [
41 # From QMP:
42 'human-monitor-command',
Markus Armbruster6eb39372015-09-16 13:06:25 +020043 'qom-get',
Eric Blake10d4d992015-05-04 09:05:23 -060044 'query-migrate-cache-size',
45 'query-tpm-models',
46 'query-tpm-types',
47 'ringbuf-read',
48
49 # From QGA:
50 'guest-file-open',
51 'guest-fsfreeze-freeze',
52 'guest-fsfreeze-freeze-list',
53 'guest-fsfreeze-status',
54 'guest-fsfreeze-thaw',
55 'guest-get-time',
56 'guest-set-vcpus',
57 'guest-sync',
58 'guest-sync-delimited',
Eric Blake10d4d992015-05-04 09:05:23 -060059]
60
Eric Blake4dc2e692015-05-04 09:05:17 -060061enum_types = []
62struct_types = []
63union_types = []
64events = []
65all_names = {}
66
Markus Armbruster00e4b282015-06-10 10:04:36 +020067#
68# Parsing the schema into expressions
69#
70
Eric Blake437db252015-09-29 16:21:02 -060071
Lluís Vilanovaa719a272014-05-07 20:46:15 +020072def error_path(parent):
73 res = ""
74 while parent:
75 res = ("In file included from %s:%d:\n" % (parent['file'],
76 parent['line'])) + res
77 parent = parent['parent']
78 return res
79
Eric Blake437db252015-09-29 16:21:02 -060080
Markus Armbruster2caba362013-07-27 17:41:56 +020081class QAPISchemaError(Exception):
82 def __init__(self, schema, msg):
Eric Blake59b00542015-09-29 16:21:01 -060083 Exception.__init__(self)
Markus Armbruster54414042015-06-09 16:22:45 +020084 self.fname = schema.fname
Markus Armbruster2caba362013-07-27 17:41:56 +020085 self.msg = msg
Wenchao Xia515b9432014-03-04 18:44:33 -080086 self.col = 1
87 self.line = schema.line
88 for ch in schema.src[schema.line_pos:schema.pos]:
89 if ch == '\t':
Markus Armbruster2caba362013-07-27 17:41:56 +020090 self.col = (self.col + 7) % 8 + 1
91 else:
92 self.col += 1
Markus Armbruster54414042015-06-09 16:22:45 +020093 self.info = schema.incl_info
Markus Armbruster2caba362013-07-27 17:41:56 +020094
95 def __str__(self):
Lluís Vilanovaa719a272014-05-07 20:46:15 +020096 return error_path(self.info) + \
Markus Armbruster54414042015-06-09 16:22:45 +020097 "%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
Markus Armbruster2caba362013-07-27 17:41:56 +020098
Eric Blake437db252015-09-29 16:21:02 -060099
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800100class QAPIExprError(Exception):
101 def __init__(self, expr_info, msg):
Eric Blake59b00542015-09-29 16:21:01 -0600102 Exception.__init__(self)
Eric Blake7618b912015-10-12 22:22:22 -0600103 assert expr_info
Lluís Vilanovaa719a272014-05-07 20:46:15 +0200104 self.info = expr_info
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800105 self.msg = msg
106
107 def __str__(self):
Lluís Vilanovaa719a272014-05-07 20:46:15 +0200108 return error_path(self.info['parent']) + \
109 "%s:%d: %s" % (self.info['file'], self.info['line'], self.msg)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800110
Eric Blake437db252015-09-29 16:21:02 -0600111
Markus Armbrustera4bcb202015-09-16 13:06:04 +0200112class QAPISchemaParser(object):
Michael Roth0f923be2011-07-19 14:50:39 -0500113
Eric Blake437db252015-09-29 16:21:02 -0600114 def __init__(self, fp, previously_included=[], incl_info=None):
Markus Armbruster54414042015-06-09 16:22:45 +0200115 abs_fname = os.path.abspath(fp.name)
Markus Armbruster8608d252015-06-09 18:32:29 +0200116 fname = fp.name
Markus Armbruster54414042015-06-09 16:22:45 +0200117 self.fname = fname
Markus Armbruster54414042015-06-09 16:22:45 +0200118 previously_included.append(abs_fname)
119 self.incl_info = incl_info
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200120 self.src = fp.read()
121 if self.src == '' or self.src[-1] != '\n':
122 self.src += '\n'
123 self.cursor = 0
Wenchao Xia515b9432014-03-04 18:44:33 -0800124 self.line = 1
125 self.line_pos = 0
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200126 self.exprs = []
127 self.accept()
Michael Roth0f923be2011-07-19 14:50:39 -0500128
Eric Blake437db252015-09-29 16:21:02 -0600129 while self.tok is not None:
Markus Armbruster54414042015-06-09 16:22:45 +0200130 expr_info = {'file': fname, 'line': self.line,
131 'parent': self.incl_info}
Lluís Vilanovaa719a272014-05-07 20:46:15 +0200132 expr = self.get_expr(False)
133 if isinstance(expr, dict) and "include" in expr:
134 if len(expr) != 1:
Eric Blake437db252015-09-29 16:21:02 -0600135 raise QAPIExprError(expr_info,
136 "Invalid 'include' directive")
Lluís Vilanovaa719a272014-05-07 20:46:15 +0200137 include = expr["include"]
138 if not isinstance(include, str):
139 raise QAPIExprError(expr_info,
Eric Blake7408fb62015-09-29 16:21:00 -0600140 "Value of 'include' must be a string")
Markus Armbruster54414042015-06-09 16:22:45 +0200141 incl_abs_fname = os.path.join(os.path.dirname(abs_fname),
142 include)
Markus Armbrustera1366082015-06-09 16:54:09 +0200143 # catch inclusion cycle
144 inf = expr_info
145 while inf:
146 if incl_abs_fname == os.path.abspath(inf['file']):
Stefan Hajnoczi7ac9a9d2014-08-27 12:08:51 +0100147 raise QAPIExprError(expr_info, "Inclusion loop for %s"
148 % include)
Markus Armbrustera1366082015-06-09 16:54:09 +0200149 inf = inf['parent']
Benoît Canet24fd8482014-05-16 12:51:56 +0200150 # skip multiple include of the same file
Markus Armbruster54414042015-06-09 16:22:45 +0200151 if incl_abs_fname in previously_included:
Benoît Canet24fd8482014-05-16 12:51:56 +0200152 continue
Lluís Vilanovaa719a272014-05-07 20:46:15 +0200153 try:
Markus Armbruster54414042015-06-09 16:22:45 +0200154 fobj = open(incl_abs_fname, 'r')
Luiz Capitulino34788812014-05-20 13:50:19 -0400155 except IOError, e:
Lluís Vilanovaa719a272014-05-07 20:46:15 +0200156 raise QAPIExprError(expr_info,
157 '%s: %s' % (e.strerror, include))
Markus Armbrustera4bcb202015-09-16 13:06:04 +0200158 exprs_include = QAPISchemaParser(fobj, previously_included,
159 expr_info)
Lluís Vilanovaa719a272014-05-07 20:46:15 +0200160 self.exprs.extend(exprs_include.exprs)
161 else:
162 expr_elem = {'expr': expr,
163 'info': expr_info}
164 self.exprs.append(expr_elem)
Michael Roth0f923be2011-07-19 14:50:39 -0500165
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200166 def accept(self):
167 while True:
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200168 self.tok = self.src[self.cursor]
Markus Armbruster2caba362013-07-27 17:41:56 +0200169 self.pos = self.cursor
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200170 self.cursor += 1
171 self.val = None
Michael Roth0f923be2011-07-19 14:50:39 -0500172
Markus Armbrusterf1a145e2013-07-27 17:42:01 +0200173 if self.tok == '#':
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200174 self.cursor = self.src.find('\n', self.cursor)
Eric Blake8712fa52015-10-26 16:34:41 -0600175 elif self.tok in "{}:,[]":
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200176 return
177 elif self.tok == "'":
178 string = ''
179 esc = False
180 while True:
181 ch = self.src[self.cursor]
182 self.cursor += 1
183 if ch == '\n':
Markus Armbruster2caba362013-07-27 17:41:56 +0200184 raise QAPISchemaError(self,
185 'Missing terminating "\'"')
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200186 if esc:
Eric Blakea7f59662015-05-04 09:05:36 -0600187 if ch == 'b':
188 string += '\b'
189 elif ch == 'f':
190 string += '\f'
191 elif ch == 'n':
192 string += '\n'
193 elif ch == 'r':
194 string += '\r'
195 elif ch == 't':
196 string += '\t'
197 elif ch == 'u':
198 value = 0
Eric Blake437db252015-09-29 16:21:02 -0600199 for _ in range(0, 4):
Eric Blakea7f59662015-05-04 09:05:36 -0600200 ch = self.src[self.cursor]
201 self.cursor += 1
202 if ch not in "0123456789abcdefABCDEF":
203 raise QAPISchemaError(self,
204 '\\u escape needs 4 '
205 'hex digits')
206 value = (value << 4) + int(ch, 16)
207 # If Python 2 and 3 didn't disagree so much on
208 # how to handle Unicode, then we could allow
209 # Unicode string defaults. But most of QAPI is
210 # ASCII-only, so we aren't losing much for now.
211 if not value or value > 0x7f:
212 raise QAPISchemaError(self,
213 'For now, \\u escape '
214 'only supports non-zero '
215 'values up to \\u007f')
216 string += chr(value)
217 elif ch in "\\/'\"":
218 string += ch
219 else:
220 raise QAPISchemaError(self,
Eric Blake437db252015-09-29 16:21:02 -0600221 "Unknown escape \\%s" % ch)
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200222 esc = False
223 elif ch == "\\":
224 esc = True
225 elif ch == "'":
226 self.val = string
227 return
228 else:
229 string += ch
Markus Armbrustere565d932015-06-10 08:24:58 +0200230 elif self.src.startswith("true", self.pos):
231 self.val = True
232 self.cursor += 3
233 return
234 elif self.src.startswith("false", self.pos):
235 self.val = False
236 self.cursor += 4
237 return
238 elif self.src.startswith("null", self.pos):
239 self.val = None
240 self.cursor += 3
241 return
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200242 elif self.tok == '\n':
243 if self.cursor == len(self.src):
244 self.tok = None
245 return
Wenchao Xia515b9432014-03-04 18:44:33 -0800246 self.line += 1
247 self.line_pos = self.cursor
Markus Armbruster9213aa52013-07-27 17:41:57 +0200248 elif not self.tok.isspace():
249 raise QAPISchemaError(self, 'Stray "%s"' % self.tok)
Michael Roth0f923be2011-07-19 14:50:39 -0500250
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200251 def get_members(self):
252 expr = OrderedDict()
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200253 if self.tok == '}':
254 self.accept()
255 return expr
256 if self.tok != "'":
257 raise QAPISchemaError(self, 'Expected string or "}"')
258 while True:
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200259 key = self.val
260 self.accept()
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200261 if self.tok != ':':
262 raise QAPISchemaError(self, 'Expected ":"')
263 self.accept()
Wenchao Xia4b359912014-03-04 18:44:32 -0800264 if key in expr:
265 raise QAPISchemaError(self, 'Duplicate key "%s"' % key)
Markus Armbruster5f3cd2b2013-07-27 17:41:59 +0200266 expr[key] = self.get_expr(True)
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200267 if self.tok == '}':
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200268 self.accept()
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200269 return expr
270 if self.tok != ',':
271 raise QAPISchemaError(self, 'Expected "," or "}"')
272 self.accept()
273 if self.tok != "'":
274 raise QAPISchemaError(self, 'Expected string')
Michael Roth0f923be2011-07-19 14:50:39 -0500275
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200276 def get_values(self):
277 expr = []
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200278 if self.tok == ']':
279 self.accept()
280 return expr
Eric Blake437db252015-09-29 16:21:02 -0600281 if self.tok not in "{['tfn":
Fam Zhenge53188a2015-05-04 09:05:18 -0600282 raise QAPISchemaError(self, 'Expected "{", "[", "]", string, '
283 'boolean or "null"')
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200284 while True:
Markus Armbruster5f3cd2b2013-07-27 17:41:59 +0200285 expr.append(self.get_expr(True))
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200286 if self.tok == ']':
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200287 self.accept()
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200288 return expr
289 if self.tok != ',':
290 raise QAPISchemaError(self, 'Expected "," or "]"')
291 self.accept()
Michael Roth0f923be2011-07-19 14:50:39 -0500292
Markus Armbruster5f3cd2b2013-07-27 17:41:59 +0200293 def get_expr(self, nested):
294 if self.tok != '{' and not nested:
295 raise QAPISchemaError(self, 'Expected "{"')
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200296 if self.tok == '{':
297 self.accept()
298 expr = self.get_members()
299 elif self.tok == '[':
300 self.accept()
301 expr = self.get_values()
Fam Zhenge53188a2015-05-04 09:05:18 -0600302 elif self.tok in "'tfn":
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200303 expr = self.val
304 self.accept()
Markus Armbruster6974ccd2013-07-27 17:41:58 +0200305 else:
306 raise QAPISchemaError(self, 'Expected "{", "[" or string')
Markus Armbrusterc7a3f252013-07-27 17:41:55 +0200307 return expr
Kevin Wolfbd9927f2013-07-01 16:31:50 +0200308
Markus Armbruster00e4b282015-06-10 10:04:36 +0200309#
310# Semantic analysis of schema expressions
Markus Armbrusterac882192015-09-16 13:06:05 +0200311# TODO fold into QAPISchema
312# TODO catching name collisions in generated code would be nice
Markus Armbruster00e4b282015-06-10 10:04:36 +0200313#
314
Eric Blake437db252015-09-29 16:21:02 -0600315
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800316def find_base_fields(base):
317 base_struct_define = find_struct(base)
318 if not base_struct_define:
319 return None
320 return base_struct_define['data']
321
Eric Blake437db252015-09-29 16:21:02 -0600322
Eric Blake811d04f2015-05-04 09:05:10 -0600323# Return the qtype of an alternate branch, or None on error.
324def find_alternate_member_qtype(qapi_type):
Eric Blake437db252015-09-29 16:21:02 -0600325 if qapi_type in builtin_types:
Eric Blake44bd1272015-05-04 09:05:08 -0600326 return builtin_types[qapi_type]
327 elif find_struct(qapi_type):
328 return "QTYPE_QDICT"
329 elif find_enum(qapi_type):
330 return "QTYPE_QSTRING"
Eric Blake811d04f2015-05-04 09:05:10 -0600331 elif find_union(qapi_type):
332 return "QTYPE_QDICT"
Eric Blake44bd1272015-05-04 09:05:08 -0600333 return None
334
Eric Blake437db252015-09-29 16:21:02 -0600335
Wenchao Xiabceae762014-03-06 17:08:56 -0800336# Return the discriminator enum define if discriminator is specified as an
337# enum type, otherwise return None.
338def discriminator_find_enum_define(expr):
339 base = expr.get('base')
340 discriminator = expr.get('discriminator')
341
342 if not (discriminator and base):
343 return None
344
345 base_fields = find_base_fields(base)
346 if not base_fields:
347 return None
348
349 discriminator_type = base_fields.get(discriminator)
350 if not discriminator_type:
351 return None
352
353 return find_enum(discriminator_type)
354
Eric Blake437db252015-09-29 16:21:02 -0600355
Markus Armbrusterd90675f2015-07-31 11:33:52 +0200356# FIXME should enforce "other than downstream extensions [...], all
357# names should begin with a letter".
Eric Blakec9e0a792015-05-04 09:05:22 -0600358valid_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$')
Eric Blake437db252015-09-29 16:21:02 -0600359
360
361def check_name(expr_info, source, name, allow_optional=False,
362 enum_member=False):
Eric Blakec9e0a792015-05-04 09:05:22 -0600363 global valid_name
364 membername = name
365
366 if not isinstance(name, str):
367 raise QAPIExprError(expr_info,
368 "%s requires a string name" % source)
369 if name.startswith('*'):
370 membername = name[1:]
371 if not allow_optional:
372 raise QAPIExprError(expr_info,
373 "%s does not allow optional name '%s'"
374 % (source, name))
375 # Enum members can start with a digit, because the generated C
376 # code always prefixes it with the enum name
377 if enum_member:
378 membername = '_' + membername
Eric Blake9fb081e2015-10-26 16:34:44 -0600379 # Reserve the entire 'q_' namespace for c_name()
380 if not valid_name.match(membername) or \
381 c_name(membername, False).startswith('q_'):
Eric Blakec9e0a792015-05-04 09:05:22 -0600382 raise QAPIExprError(expr_info,
383 "%s uses invalid name '%s'" % (source, name))
384
Eric Blake437db252015-09-29 16:21:02 -0600385
386def add_name(name, info, meta, implicit=False):
Markus Armbruster00e4b282015-06-10 10:04:36 +0200387 global all_names
388 check_name(info, "'%s'" % meta, name)
Markus Armbrusterd90675f2015-07-31 11:33:52 +0200389 # FIXME should reject names that differ only in '_' vs. '.'
390 # vs. '-', because they're liable to clash in generated C.
Markus Armbruster00e4b282015-06-10 10:04:36 +0200391 if name in all_names:
392 raise QAPIExprError(info,
393 "%s '%s' is already defined"
394 % (all_names[name], name))
Eric Blake255960d2015-10-26 16:34:43 -0600395 if not implicit and (name.endswith('Kind') or name.endswith('List')):
Markus Armbruster00e4b282015-06-10 10:04:36 +0200396 raise QAPIExprError(info,
Eric Blake255960d2015-10-26 16:34:43 -0600397 "%s '%s' should not end in '%s'"
398 % (meta, name, name[-4:]))
Markus Armbruster00e4b282015-06-10 10:04:36 +0200399 all_names[name] = meta
400
Eric Blake437db252015-09-29 16:21:02 -0600401
Markus Armbruster00e4b282015-06-10 10:04:36 +0200402def add_struct(definition, info):
403 global struct_types
404 name = definition['struct']
405 add_name(name, info, 'struct')
406 struct_types.append(definition)
407
Eric Blake437db252015-09-29 16:21:02 -0600408
Markus Armbruster00e4b282015-06-10 10:04:36 +0200409def find_struct(name):
410 global struct_types
411 for struct in struct_types:
412 if struct['struct'] == name:
413 return struct
414 return None
415
Eric Blake437db252015-09-29 16:21:02 -0600416
Markus Armbruster00e4b282015-06-10 10:04:36 +0200417def add_union(definition, info):
418 global union_types
419 name = definition['union']
420 add_name(name, info, 'union')
421 union_types.append(definition)
422
Eric Blake437db252015-09-29 16:21:02 -0600423
Markus Armbruster00e4b282015-06-10 10:04:36 +0200424def find_union(name):
425 global union_types
426 for union in union_types:
427 if union['union'] == name:
428 return union
429 return None
430
Eric Blake437db252015-09-29 16:21:02 -0600431
432def add_enum(name, info, enum_values=None, implicit=False):
Markus Armbruster00e4b282015-06-10 10:04:36 +0200433 global enum_types
434 add_name(name, info, 'enum', implicit)
435 enum_types.append({"enum_name": name, "enum_values": enum_values})
436
Eric Blake437db252015-09-29 16:21:02 -0600437
Markus Armbruster00e4b282015-06-10 10:04:36 +0200438def find_enum(name):
439 global enum_types
440 for enum in enum_types:
441 if enum['enum_name'] == name:
442 return enum
443 return None
444
Markus Armbruster00e4b282015-06-10 10:04:36 +0200445
Eric Blake437db252015-09-29 16:21:02 -0600446def is_enum(name):
447 return find_enum(name) is not None
448
449
450def check_type(expr_info, source, value, allow_array=False,
451 allow_dict=False, allow_optional=False,
452 allow_metas=[]):
Eric Blakedd883c62015-05-04 09:05:21 -0600453 global all_names
Eric Blakedd883c62015-05-04 09:05:21 -0600454
455 if value is None:
456 return
457
Eric Blakedd883c62015-05-04 09:05:21 -0600458 # Check if array type for value is okay
459 if isinstance(value, list):
460 if not allow_array:
461 raise QAPIExprError(expr_info,
462 "%s cannot be an array" % source)
463 if len(value) != 1 or not isinstance(value[0], str):
464 raise QAPIExprError(expr_info,
465 "%s: array type must contain single type name"
466 % source)
467 value = value[0]
Eric Blakedd883c62015-05-04 09:05:21 -0600468
469 # Check if type name for value is okay
470 if isinstance(value, str):
Eric Blake437db252015-09-29 16:21:02 -0600471 if value not in all_names:
Eric Blakedd883c62015-05-04 09:05:21 -0600472 raise QAPIExprError(expr_info,
473 "%s uses unknown type '%s'"
Markus Armbrustereddf8172015-08-31 13:54:39 +0200474 % (source, value))
Eric Blakedd883c62015-05-04 09:05:21 -0600475 if not all_names[value] in allow_metas:
476 raise QAPIExprError(expr_info,
477 "%s cannot use %s type '%s'"
Markus Armbrustereddf8172015-08-31 13:54:39 +0200478 % (source, all_names[value], value))
Eric Blakedd883c62015-05-04 09:05:21 -0600479 return
480
Eric Blakedd883c62015-05-04 09:05:21 -0600481 if not allow_dict:
482 raise QAPIExprError(expr_info,
483 "%s should be a type name" % source)
Markus Armbrusterc6b71e52015-08-31 17:28:52 +0200484
485 if not isinstance(value, OrderedDict):
486 raise QAPIExprError(expr_info,
487 "%s should be a dictionary or type name" % source)
488
489 # value is a dictionary, check that each member is okay
Eric Blakedd883c62015-05-04 09:05:21 -0600490 for (key, arg) in value.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600491 check_name(expr_info, "Member of %s" % source, key,
492 allow_optional=allow_optional)
Eric Blake5e59baf2015-10-26 16:35:02 -0600493 if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
Eric Blake9fb081e2015-10-26 16:34:44 -0600494 raise QAPIExprError(expr_info,
495 "Member of %s uses reserved name '%s'"
496 % (source, key))
Eric Blake6b5abc72015-05-04 09:05:33 -0600497 # Todo: allow dictionaries to represent default values of
498 # an optional argument.
Eric Blakedd883c62015-05-04 09:05:21 -0600499 check_type(expr_info, "Member '%s' of %s" % (key, source), arg,
Markus Armbruster2d212912015-09-16 13:06:27 +0200500 allow_array=True,
Eric Blakedd883c62015-05-04 09:05:21 -0600501 allow_metas=['built-in', 'union', 'alternate', 'struct',
Eric Blake6b5abc72015-05-04 09:05:33 -0600502 'enum'])
Eric Blakedd883c62015-05-04 09:05:21 -0600503
Eric Blake437db252015-09-29 16:21:02 -0600504
505def check_member_clash(expr_info, base_name, data, source=""):
Eric Blakeff55d722015-05-04 09:05:37 -0600506 base = find_struct(base_name)
507 assert base
508 base_members = base['data']
509 for key in data.keys():
510 if key.startswith('*'):
511 key = key[1:]
512 if key in base_members or "*" + key in base_members:
513 raise QAPIExprError(expr_info,
514 "Member name '%s'%s clashes with base '%s'"
515 % (key, source, base_name))
516 if base.get('base'):
517 check_member_clash(expr_info, base['base'], data, source)
518
Eric Blake437db252015-09-29 16:21:02 -0600519
Eric Blakedd883c62015-05-04 09:05:21 -0600520def check_command(expr, expr_info):
521 name = expr['command']
Eric Blake2cbf0992015-05-04 09:05:24 -0600522
Eric Blakedd883c62015-05-04 09:05:21 -0600523 check_type(expr_info, "'data' for command '%s'" % name,
Eric Blakec9e0a792015-05-04 09:05:22 -0600524 expr.get('data'), allow_dict=True, allow_optional=True,
Markus Armbruster2d212912015-09-16 13:06:27 +0200525 allow_metas=['struct'])
Eric Blake10d4d992015-05-04 09:05:23 -0600526 returns_meta = ['union', 'struct']
527 if name in returns_whitelist:
528 returns_meta += ['built-in', 'alternate', 'enum']
Eric Blakedd883c62015-05-04 09:05:21 -0600529 check_type(expr_info, "'returns' for command '%s'" % name,
Markus Armbruster9b090d42015-07-31 17:59:38 +0200530 expr.get('returns'), allow_array=True,
Markus Armbruster2d212912015-09-16 13:06:27 +0200531 allow_optional=True, allow_metas=returns_meta)
Eric Blakedd883c62015-05-04 09:05:21 -0600532
Eric Blake437db252015-09-29 16:21:02 -0600533
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200534def check_event(expr, expr_info):
Eric Blake4dc2e692015-05-04 09:05:17 -0600535 global events
536 name = expr['event']
Eric Blake4dc2e692015-05-04 09:05:17 -0600537
538 if name.upper() == 'MAX':
539 raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created")
540 events.append(name)
Eric Blakedd883c62015-05-04 09:05:21 -0600541 check_type(expr_info, "'data' for event '%s'" % name,
Eric Blakec9e0a792015-05-04 09:05:22 -0600542 expr.get('data'), allow_dict=True, allow_optional=True,
Markus Armbruster315932b2015-07-01 10:12:24 +0200543 allow_metas=['struct'])
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200544
Eric Blake437db252015-09-29 16:21:02 -0600545
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800546def check_union(expr, expr_info):
547 name = expr['union']
548 base = expr.get('base')
549 discriminator = expr.get('discriminator')
550 members = expr['data']
Eric Blakef51d8fa2015-10-26 16:34:51 -0600551 values = {'MAX': '(automatic)', 'KIND': '(automatic)',
552 'TYPE': '(automatic)'}
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800553
Eric Blake811d04f2015-05-04 09:05:10 -0600554 # Two types of unions, determined by discriminator.
Eric Blake811d04f2015-05-04 09:05:10 -0600555
556 # With no discriminator it is a simple union.
557 if discriminator is None:
Eric Blake44bd1272015-05-04 09:05:08 -0600558 enum_define = None
Eric Blake437db252015-09-29 16:21:02 -0600559 allow_metas = ['built-in', 'union', 'alternate', 'struct', 'enum']
Eric Blake44bd1272015-05-04 09:05:08 -0600560 if base is not None:
561 raise QAPIExprError(expr_info,
Eric Blake811d04f2015-05-04 09:05:10 -0600562 "Simple union '%s' must not have a base"
Eric Blake44bd1272015-05-04 09:05:08 -0600563 % name)
564
565 # Else, it's a flat union.
566 else:
567 # The object must have a string member 'base'.
Eric Blake376863e2015-09-29 16:21:07 -0600568 check_type(expr_info, "'base' for union '%s'" % name,
569 base, allow_metas=['struct'])
570 if not base:
Eric Blake44bd1272015-05-04 09:05:08 -0600571 raise QAPIExprError(expr_info,
Eric Blake376863e2015-09-29 16:21:07 -0600572 "Flat union '%s' must have a base"
Eric Blake44bd1272015-05-04 09:05:08 -0600573 % name)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800574 base_fields = find_base_fields(base)
Eric Blake376863e2015-09-29 16:21:07 -0600575 assert base_fields
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800576
Eric Blakec9e0a792015-05-04 09:05:22 -0600577 # The value of member 'discriminator' must name a non-optional
Eric Blakefd41dd42015-05-04 09:05:25 -0600578 # member of the base struct.
Eric Blakec9e0a792015-05-04 09:05:22 -0600579 check_name(expr_info, "Discriminator of flat union '%s'" % name,
580 discriminator)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800581 discriminator_type = base_fields.get(discriminator)
582 if not discriminator_type:
583 raise QAPIExprError(expr_info,
584 "Discriminator '%s' is not a member of base "
Eric Blakefd41dd42015-05-04 09:05:25 -0600585 "struct '%s'"
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800586 % (discriminator, base))
587 enum_define = find_enum(discriminator_type)
Eric Blake437db252015-09-29 16:21:02 -0600588 allow_metas = ['struct']
Wenchao Xia52230702014-03-04 18:44:39 -0800589 # Do not allow string discriminator
590 if not enum_define:
591 raise QAPIExprError(expr_info,
592 "Discriminator '%s' must be of enumeration "
593 "type" % discriminator)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800594
595 # Check every branch
596 for (key, value) in members.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600597 check_name(expr_info, "Member of union '%s'" % name, key)
598
Eric Blakedd883c62015-05-04 09:05:21 -0600599 # Each value must name a known type; furthermore, in flat unions,
Eric Blakeff55d722015-05-04 09:05:37 -0600600 # branches must be a struct with no overlapping member names
Eric Blakedd883c62015-05-04 09:05:21 -0600601 check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
Markus Armbrusterf9a14272015-06-10 13:07:43 +0200602 value, allow_array=not base, allow_metas=allow_metas)
Eric Blakeff55d722015-05-04 09:05:37 -0600603 if base:
604 branch_struct = find_struct(value)
605 assert branch_struct
606 check_member_clash(expr_info, base, branch_struct['data'],
607 " of branch '%s'" % key)
Eric Blakedd883c62015-05-04 09:05:21 -0600608
Eric Blake44bd1272015-05-04 09:05:08 -0600609 # If the discriminator names an enum type, then all members
Eric Blake7b2a5c22015-09-29 16:21:04 -0600610 # of 'data' must also be members of the enum type, which in turn
611 # must not collide with the discriminator name.
Eric Blake44bd1272015-05-04 09:05:08 -0600612 if enum_define:
Eric Blake437db252015-09-29 16:21:02 -0600613 if key not in enum_define['enum_values']:
Eric Blake44bd1272015-05-04 09:05:08 -0600614 raise QAPIExprError(expr_info,
615 "Discriminator value '%s' is not found in "
616 "enum '%s'" %
617 (key, enum_define["enum_name"]))
Eric Blake7b2a5c22015-09-29 16:21:04 -0600618 if discriminator in enum_define['enum_values']:
619 raise QAPIExprError(expr_info,
620 "Discriminator name '%s' collides with "
621 "enum value in '%s'" %
622 (discriminator, enum_define["enum_name"]))
Eric Blake44bd1272015-05-04 09:05:08 -0600623
624 # Otherwise, check for conflicts in the generated enum
625 else:
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600626 c_key = camel_to_upper(key)
Eric Blake44bd1272015-05-04 09:05:08 -0600627 if c_key in values:
628 raise QAPIExprError(expr_info,
629 "Union '%s' member '%s' clashes with '%s'"
630 % (name, key, values[c_key]))
631 values[c_key] = key
632
Eric Blake437db252015-09-29 16:21:02 -0600633
Eric Blake811d04f2015-05-04 09:05:10 -0600634def check_alternate(expr, expr_info):
Eric Blakeab916fa2015-05-04 09:05:13 -0600635 name = expr['alternate']
Eric Blake811d04f2015-05-04 09:05:10 -0600636 members = expr['data']
Eric Blake437db252015-09-29 16:21:02 -0600637 values = {'MAX': '(automatic)'}
Eric Blake811d04f2015-05-04 09:05:10 -0600638 types_seen = {}
Eric Blake44bd1272015-05-04 09:05:08 -0600639
Eric Blake811d04f2015-05-04 09:05:10 -0600640 # Check every branch
641 for (key, value) in members.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600642 check_name(expr_info, "Member of alternate '%s'" % name, key)
643
Eric Blake811d04f2015-05-04 09:05:10 -0600644 # Check for conflicts in the generated enum
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600645 c_key = camel_to_upper(key)
Eric Blake811d04f2015-05-04 09:05:10 -0600646 if c_key in values:
647 raise QAPIExprError(expr_info,
Eric Blakeab916fa2015-05-04 09:05:13 -0600648 "Alternate '%s' member '%s' clashes with '%s'"
649 % (name, key, values[c_key]))
Eric Blake811d04f2015-05-04 09:05:10 -0600650 values[c_key] = key
651
652 # Ensure alternates have no type conflicts.
Eric Blakedd883c62015-05-04 09:05:21 -0600653 check_type(expr_info, "Member '%s' of alternate '%s'" % (key, name),
654 value,
655 allow_metas=['built-in', 'union', 'struct', 'enum'])
Eric Blake811d04f2015-05-04 09:05:10 -0600656 qtype = find_alternate_member_qtype(value)
Eric Blakedd883c62015-05-04 09:05:21 -0600657 assert qtype
Eric Blake811d04f2015-05-04 09:05:10 -0600658 if qtype in types_seen:
659 raise QAPIExprError(expr_info,
Eric Blakeab916fa2015-05-04 09:05:13 -0600660 "Alternate '%s' member '%s' can't "
Eric Blake811d04f2015-05-04 09:05:10 -0600661 "be distinguished from member '%s'"
662 % (name, key, types_seen[qtype]))
663 types_seen[qtype] = key
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800664
Eric Blake437db252015-09-29 16:21:02 -0600665
Eric Blakecf393592015-05-04 09:05:04 -0600666def check_enum(expr, expr_info):
667 name = expr['enum']
668 members = expr.get('data')
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100669 prefix = expr.get('prefix')
Eric Blake437db252015-09-29 16:21:02 -0600670 values = {'MAX': '(automatic)'}
Eric Blakecf393592015-05-04 09:05:04 -0600671
672 if not isinstance(members, list):
673 raise QAPIExprError(expr_info,
674 "Enum '%s' requires an array for 'data'" % name)
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100675 if prefix is not None and not isinstance(prefix, str):
676 raise QAPIExprError(expr_info,
677 "Enum '%s' requires a string for 'prefix'" % name)
Eric Blakecf393592015-05-04 09:05:04 -0600678 for member in members:
Eric Blake437db252015-09-29 16:21:02 -0600679 check_name(expr_info, "Member of enum '%s'" % name, member,
Eric Blakec9e0a792015-05-04 09:05:22 -0600680 enum_member=True)
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600681 key = camel_to_upper(member)
Eric Blakecf393592015-05-04 09:05:04 -0600682 if key in values:
683 raise QAPIExprError(expr_info,
684 "Enum '%s' member '%s' clashes with '%s'"
685 % (name, member, values[key]))
686 values[key] = member
687
Eric Blake437db252015-09-29 16:21:02 -0600688
Eric Blakedd883c62015-05-04 09:05:21 -0600689def check_struct(expr, expr_info):
Eric Blakefd41dd42015-05-04 09:05:25 -0600690 name = expr['struct']
Eric Blakedd883c62015-05-04 09:05:21 -0600691 members = expr['data']
692
Eric Blakefd41dd42015-05-04 09:05:25 -0600693 check_type(expr_info, "'data' for struct '%s'" % name, members,
Eric Blakec9e0a792015-05-04 09:05:22 -0600694 allow_dict=True, allow_optional=True)
Eric Blakefd41dd42015-05-04 09:05:25 -0600695 check_type(expr_info, "'base' for struct '%s'" % name, expr.get('base'),
Eric Blakedd883c62015-05-04 09:05:21 -0600696 allow_metas=['struct'])
Eric Blakeff55d722015-05-04 09:05:37 -0600697 if expr.get('base'):
698 check_member_clash(expr_info, expr['base'], expr['data'])
Eric Blakedd883c62015-05-04 09:05:21 -0600699
Eric Blake437db252015-09-29 16:21:02 -0600700
Eric Blake0545f6b2015-05-04 09:05:15 -0600701def check_keys(expr_elem, meta, required, optional=[]):
702 expr = expr_elem['expr']
703 info = expr_elem['info']
704 name = expr[meta]
705 if not isinstance(name, str):
706 raise QAPIExprError(info,
707 "'%s' key must have a string value" % meta)
Eric Blake437db252015-09-29 16:21:02 -0600708 required = required + [meta]
Eric Blake0545f6b2015-05-04 09:05:15 -0600709 for (key, value) in expr.items():
Eric Blake437db252015-09-29 16:21:02 -0600710 if key not in required and key not in optional:
Eric Blake0545f6b2015-05-04 09:05:15 -0600711 raise QAPIExprError(info,
712 "Unknown key '%s' in %s '%s'"
713 % (key, meta, name))
Eric Blake437db252015-09-29 16:21:02 -0600714 if (key == 'gen' or key == 'success-response') and value is not False:
Eric Blake2cbf0992015-05-04 09:05:24 -0600715 raise QAPIExprError(info,
716 "'%s' of %s '%s' should only use false value"
717 % (key, meta, name))
Eric Blake0545f6b2015-05-04 09:05:15 -0600718 for key in required:
Eric Blake437db252015-09-29 16:21:02 -0600719 if key not in expr:
Eric Blake0545f6b2015-05-04 09:05:15 -0600720 raise QAPIExprError(info,
721 "Key '%s' is missing from %s '%s'"
722 % (key, meta, name))
723
Eric Blake437db252015-09-29 16:21:02 -0600724
Markus Armbruster4d076d62015-06-10 08:55:21 +0200725def check_exprs(exprs):
726 global all_names
727
728 # Learn the types and check for valid expression keys
729 for builtin in builtin_types.keys():
730 all_names[builtin] = 'built-in'
731 for expr_elem in exprs:
732 expr = expr_elem['expr']
733 info = expr_elem['info']
Eric Blake437db252015-09-29 16:21:02 -0600734 if 'enum' in expr:
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100735 check_keys(expr_elem, 'enum', ['data'], ['prefix'])
Markus Armbruster4d076d62015-06-10 08:55:21 +0200736 add_enum(expr['enum'], info, expr['data'])
Eric Blake437db252015-09-29 16:21:02 -0600737 elif 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200738 check_keys(expr_elem, 'union', ['data'],
739 ['base', 'discriminator'])
740 add_union(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600741 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200742 check_keys(expr_elem, 'alternate', ['data'])
743 add_name(expr['alternate'], info, 'alternate')
Eric Blake437db252015-09-29 16:21:02 -0600744 elif 'struct' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200745 check_keys(expr_elem, 'struct', ['data'], ['base'])
746 add_struct(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600747 elif 'command' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200748 check_keys(expr_elem, 'command', [],
749 ['data', 'returns', 'gen', 'success-response'])
750 add_name(expr['command'], info, 'command')
Eric Blake437db252015-09-29 16:21:02 -0600751 elif 'event' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200752 check_keys(expr_elem, 'event', [], ['data'])
753 add_name(expr['event'], info, 'event')
754 else:
755 raise QAPIExprError(expr_elem['info'],
756 "Expression is missing metatype")
757
758 # Try again for hidden UnionKind enum
759 for expr_elem in exprs:
760 expr = expr_elem['expr']
Eric Blake437db252015-09-29 16:21:02 -0600761 if 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200762 if not discriminator_find_enum_define(expr):
763 add_enum('%sKind' % expr['union'], expr_elem['info'],
764 implicit=True)
Eric Blake437db252015-09-29 16:21:02 -0600765 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200766 add_enum('%sKind' % expr['alternate'], expr_elem['info'],
767 implicit=True)
768
769 # Validate that exprs make sense
770 for expr_elem in exprs:
771 expr = expr_elem['expr']
772 info = expr_elem['info']
773
Eric Blake437db252015-09-29 16:21:02 -0600774 if 'enum' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200775 check_enum(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600776 elif 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200777 check_union(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600778 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200779 check_alternate(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600780 elif 'struct' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200781 check_struct(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600782 elif 'command' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200783 check_command(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600784 elif 'event' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200785 check_event(expr, info)
786 else:
787 assert False, 'unexpected meta type'
788
Markus Armbrusterac882192015-09-16 13:06:05 +0200789 return exprs
Eric Blake0545f6b2015-05-04 09:05:15 -0600790
Markus Armbrusterac882192015-09-16 13:06:05 +0200791
792#
793# Schema compiler frontend
794#
795
796class QAPISchemaEntity(object):
797 def __init__(self, name, info):
798 assert isinstance(name, str)
799 self.name = name
Eric Blake99df5282015-10-12 22:22:32 -0600800 # For explicitly defined entities, info points to the (explicit)
801 # definition. For builtins (and their arrays), info is None.
802 # For implicitly defined entities, info points to a place that
803 # triggered the implicit definition (there may be more than one
804 # such place).
Markus Armbrusterac882192015-09-16 13:06:05 +0200805 self.info = info
806
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200807 def c_name(self):
808 return c_name(self.name)
809
Markus Armbrusterac882192015-09-16 13:06:05 +0200810 def check(self, schema):
811 pass
812
Eric Blake49823c42015-10-12 22:22:27 -0600813 def is_implicit(self):
814 return not self.info
815
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200816 def visit(self, visitor):
817 pass
818
819
820class QAPISchemaVisitor(object):
821 def visit_begin(self, schema):
822 pass
823
824 def visit_end(self):
825 pass
826
Eric Blake25a0d9c2015-10-12 22:22:21 -0600827 def visit_needed(self, entity):
828 # Default to visiting everything
829 return True
830
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200831 def visit_builtin_type(self, name, info, json_type):
832 pass
833
834 def visit_enum_type(self, name, info, values, prefix):
835 pass
836
837 def visit_array_type(self, name, info, element_type):
838 pass
839
840 def visit_object_type(self, name, info, base, members, variants):
841 pass
842
Markus Armbruster39a18152015-09-16 13:06:28 +0200843 def visit_object_type_flat(self, name, info, members, variants):
844 pass
845
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200846 def visit_alternate_type(self, name, info, variants):
847 pass
848
849 def visit_command(self, name, info, arg_type, ret_type,
850 gen, success_response):
851 pass
852
853 def visit_event(self, name, info, arg_type):
854 pass
855
Markus Armbrusterac882192015-09-16 13:06:05 +0200856
857class QAPISchemaType(QAPISchemaEntity):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200858 def c_type(self, is_param=False):
859 return c_name(self.name) + pointer_suffix
860
861 def c_null(self):
862 return 'NULL'
863
864 def json_type(self):
865 pass
866
867 def alternate_qtype(self):
868 json2qtype = {
869 'string': 'QTYPE_QSTRING',
870 'number': 'QTYPE_QFLOAT',
871 'int': 'QTYPE_QINT',
872 'boolean': 'QTYPE_QBOOL',
873 'object': 'QTYPE_QDICT'
874 }
875 return json2qtype.get(self.json_type())
Markus Armbrusterac882192015-09-16 13:06:05 +0200876
877
878class QAPISchemaBuiltinType(QAPISchemaType):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200879 def __init__(self, name, json_type, c_type, c_null):
Markus Armbrusterac882192015-09-16 13:06:05 +0200880 QAPISchemaType.__init__(self, name, None)
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200881 assert not c_type or isinstance(c_type, str)
882 assert json_type in ('string', 'number', 'int', 'boolean', 'null',
883 'value')
884 self._json_type_name = json_type
885 self._c_type_name = c_type
886 self._c_null_val = c_null
887
888 def c_name(self):
889 return self.name
890
891 def c_type(self, is_param=False):
892 if is_param and self.name == 'str':
893 return 'const ' + self._c_type_name
894 return self._c_type_name
895
896 def c_null(self):
897 return self._c_null_val
898
899 def json_type(self):
900 return self._json_type_name
Markus Armbrusterac882192015-09-16 13:06:05 +0200901
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200902 def visit(self, visitor):
903 visitor.visit_builtin_type(self.name, self.info, self.json_type())
904
Markus Armbrusterac882192015-09-16 13:06:05 +0200905
906class QAPISchemaEnumType(QAPISchemaType):
907 def __init__(self, name, info, values, prefix):
908 QAPISchemaType.__init__(self, name, info)
909 for v in values:
910 assert isinstance(v, str)
911 assert prefix is None or isinstance(prefix, str)
912 self.values = values
913 self.prefix = prefix
914
915 def check(self, schema):
916 assert len(set(self.values)) == len(self.values)
917
Eric Blake99df5282015-10-12 22:22:32 -0600918 def is_implicit(self):
919 # See QAPISchema._make_implicit_enum_type()
Eric Blake8712fa52015-10-26 16:34:41 -0600920 return self.name.endswith('Kind')
Eric Blake99df5282015-10-12 22:22:32 -0600921
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200922 def c_type(self, is_param=False):
923 return c_name(self.name)
924
925 def c_null(self):
926 return c_enum_const(self.name, (self.values + ['MAX'])[0],
927 self.prefix)
928
929 def json_type(self):
930 return 'string'
931
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200932 def visit(self, visitor):
933 visitor.visit_enum_type(self.name, self.info,
934 self.values, self.prefix)
935
Markus Armbrusterac882192015-09-16 13:06:05 +0200936
937class QAPISchemaArrayType(QAPISchemaType):
938 def __init__(self, name, info, element_type):
939 QAPISchemaType.__init__(self, name, info)
940 assert isinstance(element_type, str)
941 self._element_type_name = element_type
942 self.element_type = None
943
944 def check(self, schema):
945 self.element_type = schema.lookup_type(self._element_type_name)
946 assert self.element_type
947
Eric Blake99df5282015-10-12 22:22:32 -0600948 def is_implicit(self):
949 return True
950
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200951 def json_type(self):
952 return 'array'
953
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200954 def visit(self, visitor):
955 visitor.visit_array_type(self.name, self.info, self.element_type)
956
Markus Armbrusterac882192015-09-16 13:06:05 +0200957
958class QAPISchemaObjectType(QAPISchemaType):
959 def __init__(self, name, info, base, local_members, variants):
Eric Blakeda34a9b2015-11-18 01:52:36 -0700960 # struct has local_members, optional base, and no variants
961 # flat union has base, variants, and no local_members
962 # simple union has local_members, variants, and no base
Markus Armbrusterac882192015-09-16 13:06:05 +0200963 QAPISchemaType.__init__(self, name, info)
964 assert base is None or isinstance(base, str)
965 for m in local_members:
966 assert isinstance(m, QAPISchemaObjectTypeMember)
967 assert (variants is None or
968 isinstance(variants, QAPISchemaObjectTypeVariants))
969 self._base_name = base
970 self.base = None
971 self.local_members = local_members
972 self.variants = variants
973 self.members = None
974
975 def check(self, schema):
976 assert self.members is not False # not running in cycles
977 if self.members:
978 return
979 self.members = False # mark as being checked
Markus Armbruster23a4b2c2015-11-18 01:52:43 -0700980 seen = OrderedDict()
Markus Armbrusterac882192015-09-16 13:06:05 +0200981 if self._base_name:
982 self.base = schema.lookup_type(self._base_name)
983 assert isinstance(self.base, QAPISchemaObjectType)
984 assert not self.base.variants # not implemented
985 self.base.check(schema)
Markus Armbruster23a4b2c2015-11-18 01:52:43 -0700986 for m in self.base.members:
Markus Armbruster577de122015-11-18 01:52:44 -0700987 m.check_clash(seen)
Markus Armbrusterac882192015-09-16 13:06:05 +0200988 for m in self.local_members:
Markus Armbrustere564e2d2015-11-18 01:52:40 -0700989 m.check(schema)
Markus Armbruster577de122015-11-18 01:52:44 -0700990 m.check_clash(seen)
Markus Armbruster14ff8462015-11-18 01:52:45 -0700991 self.members = seen.values()
Markus Armbrusterac882192015-09-16 13:06:05 +0200992 if self.variants:
Markus Armbrustercdc5fa32015-11-18 01:52:41 -0700993 self.variants.check(schema, seen)
Markus Armbruster14ff8462015-11-18 01:52:45 -0700994 assert self.variants.tag_member in self.members
Eric Blakeb807a1e2015-11-18 01:52:46 -0700995 self.variants.check_clash(schema, seen)
Markus Armbrusterac882192015-09-16 13:06:05 +0200996
Eric Blake99df5282015-10-12 22:22:32 -0600997 def is_implicit(self):
998 # See QAPISchema._make_implicit_object_type()
999 return self.name[0] == ':'
1000
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001001 def c_name(self):
Eric Blake49823c42015-10-12 22:22:27 -06001002 assert not self.is_implicit()
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001003 return QAPISchemaType.c_name(self)
1004
1005 def c_type(self, is_param=False):
Eric Blake49823c42015-10-12 22:22:27 -06001006 assert not self.is_implicit()
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001007 return QAPISchemaType.c_type(self)
1008
1009 def json_type(self):
1010 return 'object'
1011
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001012 def visit(self, visitor):
1013 visitor.visit_object_type(self.name, self.info,
1014 self.base, self.local_members, self.variants)
Markus Armbruster39a18152015-09-16 13:06:28 +02001015 visitor.visit_object_type_flat(self.name, self.info,
1016 self.members, self.variants)
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001017
Markus Armbrusterac882192015-09-16 13:06:05 +02001018
1019class QAPISchemaObjectTypeMember(object):
1020 def __init__(self, name, typ, optional):
1021 assert isinstance(name, str)
1022 assert isinstance(typ, str)
1023 assert isinstance(optional, bool)
1024 self.name = name
1025 self._type_name = typ
1026 self.type = None
1027 self.optional = optional
1028
Markus Armbrustere564e2d2015-11-18 01:52:40 -07001029 def check(self, schema):
Markus Armbrusterac882192015-09-16 13:06:05 +02001030 self.type = schema.lookup_type(self._type_name)
1031 assert self.type
Markus Armbrusterac882192015-09-16 13:06:05 +02001032
Markus Armbruster577de122015-11-18 01:52:44 -07001033 def check_clash(self, seen):
1034 # TODO change key of seen from QAPI name to C name
1035 assert self.name not in seen
1036 seen[self.name] = self
1037
Markus Armbrusterac882192015-09-16 13:06:05 +02001038
1039class QAPISchemaObjectTypeVariants(object):
Eric Blake46292ba2015-10-12 22:22:29 -06001040 def __init__(self, tag_name, tag_member, variants):
1041 # Flat unions pass tag_name but not tag_member.
1042 # Simple unions and alternates pass tag_member but not tag_name.
1043 # After check(), tag_member is always set, and tag_name remains
1044 # a reliable witness of being used by a flat union.
1045 assert bool(tag_member) != bool(tag_name)
1046 assert (isinstance(tag_name, str) or
1047 isinstance(tag_member, QAPISchemaObjectTypeMember))
Markus Armbrusterac882192015-09-16 13:06:05 +02001048 for v in variants:
1049 assert isinstance(v, QAPISchemaObjectTypeVariant)
1050 self.tag_name = tag_name
Eric Blake46292ba2015-10-12 22:22:29 -06001051 self.tag_member = tag_member
Markus Armbrusterac882192015-09-16 13:06:05 +02001052 self.variants = variants
1053
Markus Armbrustercdc5fa32015-11-18 01:52:41 -07001054 def check(self, schema, seen):
Markus Armbruster14ff8462015-11-18 01:52:45 -07001055 if not self.tag_member: # flat union
Markus Armbrusterac882192015-09-16 13:06:05 +02001056 self.tag_member = seen[self.tag_name]
Markus Armbrusterac882192015-09-16 13:06:05 +02001057 assert isinstance(self.tag_member.type, QAPISchemaEnumType)
1058 for v in self.variants:
Markus Armbrustercdc5fa32015-11-18 01:52:41 -07001059 v.check(schema, self.tag_member.type)
Eric Blakeb807a1e2015-11-18 01:52:46 -07001060 if isinstance(v.type, QAPISchemaObjectType):
1061 v.type.check(schema)
1062
1063 def check_clash(self, schema, seen):
1064 for v in self.variants:
1065 # Reset seen map for each variant, since qapi names from one
1066 # branch do not affect another branch
1067 vseen = dict(seen)
1068 assert isinstance(v.type, QAPISchemaObjectType)
1069 assert not v.type.variants # not implemented
1070 for m in v.type.members:
1071 m.check_clash(vseen)
Markus Armbrusterac882192015-09-16 13:06:05 +02001072
Eric Blake437db252015-09-29 16:21:02 -06001073
Markus Armbrusterac882192015-09-16 13:06:05 +02001074class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
1075 def __init__(self, name, typ):
1076 QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
1077
Markus Armbrustercdc5fa32015-11-18 01:52:41 -07001078 def check(self, schema, tag_type):
Markus Armbrustere564e2d2015-11-18 01:52:40 -07001079 QAPISchemaObjectTypeMember.check(self, schema)
Markus Armbrusterac882192015-09-16 13:06:05 +02001080 assert self.name in tag_type.values
1081
Markus Armbruster2b162cc2015-09-16 13:06:09 +02001082 # This function exists to support ugly simple union special cases
1083 # TODO get rid of them, and drop the function
1084 def simple_union_type(self):
Eric Blake49823c42015-10-12 22:22:27 -06001085 if (self.type.is_implicit() and
1086 isinstance(self.type, QAPISchemaObjectType)):
Markus Armbruster2b162cc2015-09-16 13:06:09 +02001087 assert len(self.type.members) == 1
1088 assert not self.type.variants
1089 return self.type.members[0].type
1090 return None
1091
Markus Armbrusterac882192015-09-16 13:06:05 +02001092
1093class QAPISchemaAlternateType(QAPISchemaType):
1094 def __init__(self, name, info, variants):
1095 QAPISchemaType.__init__(self, name, info)
1096 assert isinstance(variants, QAPISchemaObjectTypeVariants)
1097 assert not variants.tag_name
1098 self.variants = variants
1099
1100 def check(self, schema):
Markus Armbrustere564e2d2015-11-18 01:52:40 -07001101 self.variants.tag_member.check(schema)
Eric Blakeb807a1e2015-11-18 01:52:46 -07001102 # Not calling self.variants.check_clash(), because there's nothing
1103 # to clash with
Markus Armbrustercdc5fa32015-11-18 01:52:41 -07001104 self.variants.check(schema, {})
Markus Armbrusterac882192015-09-16 13:06:05 +02001105
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001106 def json_type(self):
1107 return 'value'
1108
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001109 def visit(self, visitor):
1110 visitor.visit_alternate_type(self.name, self.info, self.variants)
1111
Markus Armbrusterac882192015-09-16 13:06:05 +02001112
1113class QAPISchemaCommand(QAPISchemaEntity):
1114 def __init__(self, name, info, arg_type, ret_type, gen, success_response):
1115 QAPISchemaEntity.__init__(self, name, info)
1116 assert not arg_type or isinstance(arg_type, str)
1117 assert not ret_type or isinstance(ret_type, str)
1118 self._arg_type_name = arg_type
1119 self.arg_type = None
1120 self._ret_type_name = ret_type
1121 self.ret_type = None
1122 self.gen = gen
1123 self.success_response = success_response
1124
1125 def check(self, schema):
1126 if self._arg_type_name:
1127 self.arg_type = schema.lookup_type(self._arg_type_name)
1128 assert isinstance(self.arg_type, QAPISchemaObjectType)
1129 assert not self.arg_type.variants # not implemented
1130 if self._ret_type_name:
1131 self.ret_type = schema.lookup_type(self._ret_type_name)
1132 assert isinstance(self.ret_type, QAPISchemaType)
1133
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001134 def visit(self, visitor):
1135 visitor.visit_command(self.name, self.info,
1136 self.arg_type, self.ret_type,
1137 self.gen, self.success_response)
1138
Markus Armbrusterac882192015-09-16 13:06:05 +02001139
1140class QAPISchemaEvent(QAPISchemaEntity):
1141 def __init__(self, name, info, arg_type):
1142 QAPISchemaEntity.__init__(self, name, info)
1143 assert not arg_type or isinstance(arg_type, str)
1144 self._arg_type_name = arg_type
1145 self.arg_type = None
1146
1147 def check(self, schema):
1148 if self._arg_type_name:
1149 self.arg_type = schema.lookup_type(self._arg_type_name)
1150 assert isinstance(self.arg_type, QAPISchemaObjectType)
1151 assert not self.arg_type.variants # not implemented
1152
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001153 def visit(self, visitor):
1154 visitor.visit_event(self.name, self.info, self.arg_type)
1155
Markus Armbrusterac882192015-09-16 13:06:05 +02001156
1157class QAPISchema(object):
1158 def __init__(self, fname):
1159 try:
1160 self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs)
Eric Blake7618b912015-10-12 22:22:22 -06001161 self._entity_dict = {}
Eric Blake99df5282015-10-12 22:22:32 -06001162 self._predefining = True
Eric Blake7618b912015-10-12 22:22:22 -06001163 self._def_predefineds()
Eric Blake99df5282015-10-12 22:22:32 -06001164 self._predefining = False
Eric Blake7618b912015-10-12 22:22:22 -06001165 self._def_exprs()
1166 self.check()
Markus Armbrusterac882192015-09-16 13:06:05 +02001167 except (QAPISchemaError, QAPIExprError), err:
1168 print >>sys.stderr, err
1169 exit(1)
Markus Armbrusterac882192015-09-16 13:06:05 +02001170
Markus Armbrusterac882192015-09-16 13:06:05 +02001171 def _def_entity(self, ent):
Eric Blake99df5282015-10-12 22:22:32 -06001172 # Only the predefined types are allowed to not have info
1173 assert ent.info or self._predefining
Markus Armbrusterac882192015-09-16 13:06:05 +02001174 assert ent.name not in self._entity_dict
1175 self._entity_dict[ent.name] = ent
1176
1177 def lookup_entity(self, name, typ=None):
1178 ent = self._entity_dict.get(name)
1179 if typ and not isinstance(ent, typ):
1180 return None
1181 return ent
1182
1183 def lookup_type(self, name):
1184 return self.lookup_entity(name, QAPISchemaType)
1185
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001186 def _def_builtin_type(self, name, json_type, c_type, c_null):
1187 self._def_entity(QAPISchemaBuiltinType(name, json_type,
1188 c_type, c_null))
Eric Blake9f08c8e2015-10-12 22:22:28 -06001189 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1190 # qapi-types.h from a single .c, all arrays of builtins must be
1191 # declared in the first file whether or not they are used. Nicer
1192 # would be to use lazy instantiation, while figuring out how to
1193 # avoid compilation issues with multiple qapi-types.h.
Eric Blake99df5282015-10-12 22:22:32 -06001194 self._make_array_type(name, None)
Markus Armbrusterac882192015-09-16 13:06:05 +02001195
1196 def _def_predefineds(self):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001197 for t in [('str', 'string', 'char' + pointer_suffix, 'NULL'),
1198 ('number', 'number', 'double', '0'),
1199 ('int', 'int', 'int64_t', '0'),
1200 ('int8', 'int', 'int8_t', '0'),
1201 ('int16', 'int', 'int16_t', '0'),
1202 ('int32', 'int', 'int32_t', '0'),
1203 ('int64', 'int', 'int64_t', '0'),
1204 ('uint8', 'int', 'uint8_t', '0'),
1205 ('uint16', 'int', 'uint16_t', '0'),
1206 ('uint32', 'int', 'uint32_t', '0'),
1207 ('uint64', 'int', 'uint64_t', '0'),
1208 ('size', 'int', 'uint64_t', '0'),
1209 ('bool', 'boolean', 'bool', 'false'),
Markus Armbruster28770e02015-09-16 13:06:24 +02001210 ('any', 'value', 'QObject' + pointer_suffix, 'NULL')]:
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001211 self._def_builtin_type(*t)
Markus Armbruster39a18152015-09-16 13:06:28 +02001212 self.the_empty_object_type = QAPISchemaObjectType(':empty', None, None,
1213 [], None)
1214 self._def_entity(self.the_empty_object_type)
Markus Armbrusterac882192015-09-16 13:06:05 +02001215
Eric Blake99df5282015-10-12 22:22:32 -06001216 def _make_implicit_enum_type(self, name, info, values):
Eric Blake49823c42015-10-12 22:22:27 -06001217 name = name + 'Kind' # Use namespace reserved by add_name()
Eric Blake99df5282015-10-12 22:22:32 -06001218 self._def_entity(QAPISchemaEnumType(name, info, values, None))
Markus Armbrusterac882192015-09-16 13:06:05 +02001219 return name
1220
Eric Blake99df5282015-10-12 22:22:32 -06001221 def _make_array_type(self, element_type, info):
Eric Blake255960d2015-10-26 16:34:43 -06001222 name = element_type + 'List' # Use namespace reserved by add_name()
Markus Armbrusterac882192015-09-16 13:06:05 +02001223 if not self.lookup_type(name):
Eric Blake99df5282015-10-12 22:22:32 -06001224 self._def_entity(QAPISchemaArrayType(name, info, element_type))
Markus Armbrusterac882192015-09-16 13:06:05 +02001225 return name
1226
Eric Blake99df5282015-10-12 22:22:32 -06001227 def _make_implicit_object_type(self, name, info, role, members):
Markus Armbrusterac882192015-09-16 13:06:05 +02001228 if not members:
1229 return None
1230 name = ':obj-%s-%s' % (name, role)
1231 if not self.lookup_entity(name, QAPISchemaObjectType):
Eric Blake99df5282015-10-12 22:22:32 -06001232 self._def_entity(QAPISchemaObjectType(name, info, None,
Markus Armbrusterac882192015-09-16 13:06:05 +02001233 members, None))
1234 return name
1235
1236 def _def_enum_type(self, expr, info):
1237 name = expr['enum']
1238 data = expr['data']
1239 prefix = expr.get('prefix')
1240 self._def_entity(QAPISchemaEnumType(name, info, data, prefix))
Markus Armbrusterac882192015-09-16 13:06:05 +02001241
Eric Blake99df5282015-10-12 22:22:32 -06001242 def _make_member(self, name, typ, info):
Markus Armbrusterac882192015-09-16 13:06:05 +02001243 optional = False
1244 if name.startswith('*'):
1245 name = name[1:]
1246 optional = True
1247 if isinstance(typ, list):
1248 assert len(typ) == 1
Eric Blake99df5282015-10-12 22:22:32 -06001249 typ = self._make_array_type(typ[0], info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001250 return QAPISchemaObjectTypeMember(name, typ, optional)
1251
Eric Blake99df5282015-10-12 22:22:32 -06001252 def _make_members(self, data, info):
1253 return [self._make_member(key, value, info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001254 for (key, value) in data.iteritems()]
1255
1256 def _def_struct_type(self, expr, info):
1257 name = expr['struct']
1258 base = expr.get('base')
1259 data = expr['data']
1260 self._def_entity(QAPISchemaObjectType(name, info, base,
Eric Blake99df5282015-10-12 22:22:32 -06001261 self._make_members(data, info),
Markus Armbrusterac882192015-09-16 13:06:05 +02001262 None))
Markus Armbrusterac882192015-09-16 13:06:05 +02001263
1264 def _make_variant(self, case, typ):
1265 return QAPISchemaObjectTypeVariant(case, typ)
1266
Eric Blake99df5282015-10-12 22:22:32 -06001267 def _make_simple_variant(self, case, typ, info):
Markus Armbrusterac882192015-09-16 13:06:05 +02001268 if isinstance(typ, list):
1269 assert len(typ) == 1
Eric Blake99df5282015-10-12 22:22:32 -06001270 typ = self._make_array_type(typ[0], info)
1271 typ = self._make_implicit_object_type(
1272 typ, info, 'wrapper', [self._make_member('data', typ, info)])
Markus Armbrusterac882192015-09-16 13:06:05 +02001273 return QAPISchemaObjectTypeVariant(case, typ)
1274
Eric Blake99df5282015-10-12 22:22:32 -06001275 def _make_implicit_tag(self, type_name, info, variants):
1276 typ = self._make_implicit_enum_type(type_name, info,
Eric Blake46292ba2015-10-12 22:22:29 -06001277 [v.name for v in variants])
1278 return QAPISchemaObjectTypeMember('type', typ, False)
Markus Armbrusterac882192015-09-16 13:06:05 +02001279
1280 def _def_union_type(self, expr, info):
1281 name = expr['union']
1282 data = expr['data']
1283 base = expr.get('base')
1284 tag_name = expr.get('discriminator')
Eric Blake46292ba2015-10-12 22:22:29 -06001285 tag_member = None
Markus Armbrusterac882192015-09-16 13:06:05 +02001286 if tag_name:
1287 variants = [self._make_variant(key, value)
1288 for (key, value) in data.iteritems()]
Eric Blakeda34a9b2015-11-18 01:52:36 -07001289 members = []
Markus Armbrusterac882192015-09-16 13:06:05 +02001290 else:
Eric Blake99df5282015-10-12 22:22:32 -06001291 variants = [self._make_simple_variant(key, value, info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001292 for (key, value) in data.iteritems()]
Eric Blake99df5282015-10-12 22:22:32 -06001293 tag_member = self._make_implicit_tag(name, info, variants)
Eric Blakeda34a9b2015-11-18 01:52:36 -07001294 members = [tag_member]
Markus Armbrusterac882192015-09-16 13:06:05 +02001295 self._def_entity(
Eric Blakeda34a9b2015-11-18 01:52:36 -07001296 QAPISchemaObjectType(name, info, base, members,
Markus Armbrusterac882192015-09-16 13:06:05 +02001297 QAPISchemaObjectTypeVariants(tag_name,
Eric Blake46292ba2015-10-12 22:22:29 -06001298 tag_member,
Markus Armbrusterac882192015-09-16 13:06:05 +02001299 variants)))
Markus Armbrusterac882192015-09-16 13:06:05 +02001300
1301 def _def_alternate_type(self, expr, info):
1302 name = expr['alternate']
1303 data = expr['data']
1304 variants = [self._make_variant(key, value)
1305 for (key, value) in data.iteritems()]
Eric Blake99df5282015-10-12 22:22:32 -06001306 tag_member = self._make_implicit_tag(name, info, variants)
Markus Armbrusterac882192015-09-16 13:06:05 +02001307 self._def_entity(
1308 QAPISchemaAlternateType(name, info,
1309 QAPISchemaObjectTypeVariants(None,
Eric Blake46292ba2015-10-12 22:22:29 -06001310 tag_member,
Markus Armbrusterac882192015-09-16 13:06:05 +02001311 variants)))
Markus Armbrusterac882192015-09-16 13:06:05 +02001312
1313 def _def_command(self, expr, info):
1314 name = expr['command']
1315 data = expr.get('data')
1316 rets = expr.get('returns')
1317 gen = expr.get('gen', True)
1318 success_response = expr.get('success-response', True)
1319 if isinstance(data, OrderedDict):
Eric Blake99df5282015-10-12 22:22:32 -06001320 data = self._make_implicit_object_type(
1321 name, info, 'arg', self._make_members(data, info))
Markus Armbrusterac882192015-09-16 13:06:05 +02001322 if isinstance(rets, list):
1323 assert len(rets) == 1
Eric Blake99df5282015-10-12 22:22:32 -06001324 rets = self._make_array_type(rets[0], info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001325 self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
1326 success_response))
1327
1328 def _def_event(self, expr, info):
1329 name = expr['event']
1330 data = expr.get('data')
1331 if isinstance(data, OrderedDict):
Eric Blake99df5282015-10-12 22:22:32 -06001332 data = self._make_implicit_object_type(
1333 name, info, 'arg', self._make_members(data, info))
Markus Armbrusterac882192015-09-16 13:06:05 +02001334 self._def_entity(QAPISchemaEvent(name, info, data))
1335
1336 def _def_exprs(self):
1337 for expr_elem in self.exprs:
1338 expr = expr_elem['expr']
1339 info = expr_elem['info']
1340 if 'enum' in expr:
1341 self._def_enum_type(expr, info)
1342 elif 'struct' in expr:
1343 self._def_struct_type(expr, info)
1344 elif 'union' in expr:
1345 self._def_union_type(expr, info)
1346 elif 'alternate' in expr:
1347 self._def_alternate_type(expr, info)
1348 elif 'command' in expr:
1349 self._def_command(expr, info)
1350 elif 'event' in expr:
1351 self._def_event(expr, info)
1352 else:
1353 assert False
1354
1355 def check(self):
1356 for ent in self._entity_dict.values():
1357 ent.check(self)
1358
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001359 def visit(self, visitor):
Eric Blake25a0d9c2015-10-12 22:22:21 -06001360 visitor.visit_begin(self)
1361 for (name, entity) in sorted(self._entity_dict.items()):
1362 if visitor.visit_needed(entity):
1363 entity.visit(visitor)
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001364 visitor.visit_end()
1365
Markus Armbruster2caba362013-07-27 17:41:56 +02001366
Markus Armbruster00e4b282015-06-10 10:04:36 +02001367#
1368# Code generation helpers
1369#
1370
Michael Roth0f923be2011-07-19 14:50:39 -05001371def camel_case(name):
1372 new_name = ''
1373 first = True
1374 for ch in name:
1375 if ch in ['_', '-']:
1376 first = True
1377 elif first:
1378 new_name += ch.upper()
1379 first = False
1380 else:
1381 new_name += ch.lower()
1382 return new_name
1383
Eric Blake437db252015-09-29 16:21:02 -06001384
Markus Armbruster849bc532015-05-14 06:50:53 -06001385# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1386# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1387# ENUM24_Name -> ENUM24_NAME
1388def camel_to_upper(value):
1389 c_fun_str = c_name(value, False)
1390 if value.isupper():
1391 return c_fun_str
1392
1393 new_name = ''
1394 l = len(c_fun_str)
1395 for i in range(l):
1396 c = c_fun_str[i]
1397 # When c is upper and no "_" appears before, do more checks
1398 if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
Eric Blake437db252015-09-29 16:21:02 -06001399 if i < l - 1 and c_fun_str[i + 1].islower():
1400 new_name += '_'
1401 elif c_fun_str[i - 1].isdigit():
Markus Armbruster849bc532015-05-14 06:50:53 -06001402 new_name += '_'
1403 new_name += c
1404 return new_name.lstrip('_').upper()
1405
Eric Blake437db252015-09-29 16:21:02 -06001406
Daniel P. Berrange351d36e2015-08-26 14:21:20 +01001407def c_enum_const(type_name, const_name, prefix=None):
1408 if prefix is not None:
1409 type_name = prefix
Markus Armbruster849bc532015-05-14 06:50:53 -06001410 return camel_to_upper(type_name + '_' + const_name)
1411
Eric Blake18df5152015-05-14 06:50:48 -06001412c_name_trans = string.maketrans('.-', '__')
Markus Armbruster47299262015-05-14 06:50:47 -06001413
Eric Blake437db252015-09-29 16:21:02 -06001414
Eric Blakec6405b52015-05-14 06:50:55 -06001415# Map @name to a valid C identifier.
1416# If @protect, avoid returning certain ticklish identifiers (like
1417# C keywords) by prepending "q_".
1418#
1419# Used for converting 'name' from a 'name':'type' qapi definition
1420# into a generated struct member, as well as converting type names
1421# into substrings of a generated C function name.
1422# '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1423# protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
Eric Blake18df5152015-05-14 06:50:48 -06001424def c_name(name, protect=True):
Blue Swirl427a1a22012-07-30 15:46:55 +00001425 # ANSI X3J11/88-090, 3.1.1
1426 c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
Eric Blake437db252015-09-29 16:21:02 -06001427 'default', 'do', 'double', 'else', 'enum', 'extern',
1428 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1429 'return', 'short', 'signed', 'sizeof', 'static',
1430 'struct', 'switch', 'typedef', 'union', 'unsigned',
1431 'void', 'volatile', 'while'])
Blue Swirl427a1a22012-07-30 15:46:55 +00001432 # ISO/IEC 9899:1999, 6.4.1
1433 c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1434 # ISO/IEC 9899:2011, 6.4.1
Eric Blake437db252015-09-29 16:21:02 -06001435 c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1436 '_Noreturn', '_Static_assert', '_Thread_local'])
Blue Swirl427a1a22012-07-30 15:46:55 +00001437 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1438 # excluding _.*
1439 gcc_words = set(['asm', 'typeof'])
Tomoki Sekiyama6f880092013-08-07 11:39:43 -04001440 # C++ ISO/IEC 14882:2003 2.11
1441 cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
1442 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1443 'namespace', 'new', 'operator', 'private', 'protected',
1444 'public', 'reinterpret_cast', 'static_cast', 'template',
1445 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1446 'using', 'virtual', 'wchar_t',
1447 # alternative representations
1448 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1449 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
Paolo Bonzini10577252012-09-19 16:31:07 +02001450 # namespace pollution:
Max Reitz8592a542013-12-20 19:28:18 +01001451 polluted_words = set(['unix', 'errno'])
Eric Blake437db252015-09-29 16:21:02 -06001452 if protect and (name in c89_words | c99_words | c11_words | gcc_words
1453 | cpp_words | polluted_words):
Blue Swirl427a1a22012-07-30 15:46:55 +00001454 return "q_" + name
Eric Blake18df5152015-05-14 06:50:48 -06001455 return name.translate(c_name_trans)
Michael Roth0f923be2011-07-19 14:50:39 -05001456
Amos Kong05dfb262014-06-10 19:25:53 +08001457eatspace = '\033EATSPACE.'
Eric Blaked5573442015-05-14 06:50:54 -06001458pointer_suffix = ' *' + eatspace
Amos Kong05dfb262014-06-10 19:25:53 +08001459
Eric Blake437db252015-09-29 16:21:02 -06001460
Michael Roth0f923be2011-07-19 14:50:39 -05001461def genindent(count):
1462 ret = ""
Eric Blake437db252015-09-29 16:21:02 -06001463 for _ in range(count):
Michael Roth0f923be2011-07-19 14:50:39 -05001464 ret += " "
1465 return ret
1466
1467indent_level = 0
1468
Eric Blake437db252015-09-29 16:21:02 -06001469
Michael Roth0f923be2011-07-19 14:50:39 -05001470def push_indent(indent_amount=4):
1471 global indent_level
1472 indent_level += indent_amount
1473
Eric Blake437db252015-09-29 16:21:02 -06001474
Michael Roth0f923be2011-07-19 14:50:39 -05001475def pop_indent(indent_amount=4):
1476 global indent_level
1477 indent_level -= indent_amount
1478
Eric Blake437db252015-09-29 16:21:02 -06001479
Markus Armbruster77e703b2015-06-24 19:27:32 +02001480# Generate @code with @kwds interpolated.
1481# Obey indent_level, and strip eatspace.
Michael Roth0f923be2011-07-19 14:50:39 -05001482def cgen(code, **kwds):
Markus Armbruster77e703b2015-06-24 19:27:32 +02001483 raw = code % kwds
1484 if indent_level:
1485 indent = genindent(indent_level)
Markus Armbruster2752e5b2015-09-07 17:45:55 +02001486 # re.subn() lacks flags support before Python 2.7, use re.compile()
1487 raw = re.subn(re.compile("^.", re.MULTILINE),
1488 indent + r'\g<0>', raw)
Markus Armbruster77e703b2015-06-24 19:27:32 +02001489 raw = raw[0]
1490 return re.sub(re.escape(eatspace) + ' *', '', raw)
Michael Roth0f923be2011-07-19 14:50:39 -05001491
Eric Blake437db252015-09-29 16:21:02 -06001492
Michael Roth0f923be2011-07-19 14:50:39 -05001493def mcgen(code, **kwds):
Markus Armbruster77e703b2015-06-24 19:27:32 +02001494 if code[0] == '\n':
1495 code = code[1:]
1496 return cgen(code, **kwds)
Michael Roth0f923be2011-07-19 14:50:39 -05001497
Michael Roth0f923be2011-07-19 14:50:39 -05001498
1499def guardname(filename):
Markus Armbruster00dfc3b2015-06-27 07:27:21 +02001500 return c_name(filename, protect=False).upper()
Michael Rothc0afa9c2013-05-10 17:46:00 -05001501
Eric Blake437db252015-09-29 16:21:02 -06001502
Michael Rothc0afa9c2013-05-10 17:46:00 -05001503def guardstart(name):
1504 return mcgen('''
1505
1506#ifndef %(name)s
1507#define %(name)s
1508
1509''',
1510 name=guardname(name))
1511
Eric Blake437db252015-09-29 16:21:02 -06001512
Michael Rothc0afa9c2013-05-10 17:46:00 -05001513def guardend(name):
1514 return mcgen('''
1515
1516#endif /* %(name)s */
1517
1518''',
1519 name=guardname(name))
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001520
Eric Blake437db252015-09-29 16:21:02 -06001521
Markus Armbrustere98859a2015-09-16 13:06:16 +02001522def gen_enum_lookup(name, values, prefix=None):
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001523 ret = mcgen('''
1524
Markus Armbrustere98859a2015-09-16 13:06:16 +02001525const char *const %(c_name)s_lookup[] = {
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001526''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001527 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001528 for value in values:
1529 index = c_enum_const(name, value, prefix)
1530 ret += mcgen('''
1531 [%(index)s] = "%(value)s",
1532''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001533 index=index, value=value)
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001534
1535 max_index = c_enum_const(name, 'MAX', prefix)
1536 ret += mcgen('''
1537 [%(max_index)s] = NULL,
1538};
1539''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001540 max_index=max_index)
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001541 return ret
1542
Eric Blake437db252015-09-29 16:21:02 -06001543
Markus Armbrustere98859a2015-09-16 13:06:16 +02001544def gen_enum(name, values, prefix=None):
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001545 # append automatically generated _MAX value
Markus Armbrustere98859a2015-09-16 13:06:16 +02001546 enum_values = values + ['MAX']
1547
1548 ret = mcgen('''
1549
1550typedef enum %(c_name)s {
1551''',
1552 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001553
1554 i = 0
1555 for value in enum_values:
Markus Armbrustere98859a2015-09-16 13:06:16 +02001556 ret += mcgen('''
1557 %(c_enum)s = %(i)d,
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001558''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001559 c_enum=c_enum_const(name, value, prefix),
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001560 i=i)
1561 i += 1
1562
Markus Armbrustere98859a2015-09-16 13:06:16 +02001563 ret += mcgen('''
1564} %(c_name)s;
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001565''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001566 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001567
Markus Armbrustere98859a2015-09-16 13:06:16 +02001568 ret += mcgen('''
1569
1570extern const char *const %(c_name)s_lookup[];
1571''',
1572 c_name=c_name(name))
1573 return ret
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001574
Eric Blake437db252015-09-29 16:21:02 -06001575
Markus Armbruster03b43672015-09-16 13:06:20 +02001576def gen_params(arg_type, extra):
1577 if not arg_type:
1578 return extra
1579 assert not arg_type.variants
1580 ret = ''
1581 sep = ''
1582 for memb in arg_type.members:
1583 ret += sep
1584 sep = ', '
1585 if memb.optional:
1586 ret += 'bool has_%s, ' % c_name(memb.name)
1587 ret += '%s %s' % (memb.type.c_type(is_param=True), c_name(memb.name))
1588 if extra:
1589 ret += sep + extra
1590 return ret
1591
Eric Blake1f353342015-09-29 16:21:13 -06001592
Eric Blake18bdbc32015-09-29 16:21:15 -06001593def gen_err_check(label='out', skiperr=False):
1594 if skiperr:
Eric Blake1f353342015-09-29 16:21:13 -06001595 return ''
1596 return mcgen('''
Eric Blake18bdbc32015-09-29 16:21:15 -06001597 if (err) {
Eric Blake1f353342015-09-29 16:21:13 -06001598 goto %(label)s;
1599 }
1600''',
Eric Blake18bdbc32015-09-29 16:21:15 -06001601 label=label)
Eric Blake1f353342015-09-29 16:21:13 -06001602
1603
Eric Blake18bdbc32015-09-29 16:21:15 -06001604def gen_visit_fields(members, prefix='', need_cast=False, skiperr=False):
Eric Blake82ca8e42015-09-29 16:21:14 -06001605 ret = ''
Eric Blake18bdbc32015-09-29 16:21:15 -06001606 if skiperr:
Eric Blake82ca8e42015-09-29 16:21:14 -06001607 errparg = 'NULL'
Eric Blake18bdbc32015-09-29 16:21:15 -06001608 else:
1609 errparg = '&err'
Eric Blake82ca8e42015-09-29 16:21:14 -06001610
1611 for memb in members:
1612 if memb.optional:
1613 ret += mcgen('''
1614 visit_optional(v, &%(prefix)shas_%(c_name)s, "%(name)s", %(errp)s);
1615''',
1616 prefix=prefix, c_name=c_name(memb.name),
1617 name=memb.name, errp=errparg)
Eric Blake18bdbc32015-09-29 16:21:15 -06001618 ret += gen_err_check(skiperr=skiperr)
Eric Blake82ca8e42015-09-29 16:21:14 -06001619 ret += mcgen('''
1620 if (%(prefix)shas_%(c_name)s) {
1621''',
1622 prefix=prefix, c_name=c_name(memb.name))
1623 push_indent()
1624
1625 # Ugly: sometimes we need to cast away const
1626 if need_cast and memb.type.name == 'str':
1627 cast = '(char **)'
1628 else:
1629 cast = ''
1630
1631 ret += mcgen('''
1632 visit_type_%(c_type)s(v, %(cast)s&%(prefix)s%(c_name)s, "%(name)s", %(errp)s);
1633''',
1634 c_type=memb.type.c_name(), prefix=prefix, cast=cast,
1635 c_name=c_name(memb.name), name=memb.name,
1636 errp=errparg)
Eric Blake18bdbc32015-09-29 16:21:15 -06001637 ret += gen_err_check(skiperr=skiperr)
Eric Blake82ca8e42015-09-29 16:21:14 -06001638
1639 if memb.optional:
1640 pop_indent()
1641 ret += mcgen('''
1642 }
1643''')
1644 return ret
1645
1646
Markus Armbruster00e4b282015-06-10 10:04:36 +02001647#
1648# Common command line parsing
1649#
1650
Eric Blake437db252015-09-29 16:21:02 -06001651
1652def parse_command_line(extra_options="", extra_long_options=[]):
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001653
1654 try:
1655 opts, args = getopt.gnu_getopt(sys.argv[1:],
Markus Armbruster16d80f62015-04-02 13:32:16 +02001656 "chp:o:" + extra_options,
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001657 ["source", "header", "prefix=",
Markus Armbruster16d80f62015-04-02 13:32:16 +02001658 "output-dir="] + extra_long_options)
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001659 except getopt.GetoptError, err:
Markus Armbrusterb4540962015-04-02 13:17:34 +02001660 print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err))
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001661 sys.exit(1)
1662
1663 output_dir = ""
1664 prefix = ""
1665 do_c = False
1666 do_h = False
1667 extra_opts = []
1668
1669 for oa in opts:
1670 o, a = oa
1671 if o in ("-p", "--prefix"):
Markus Armbruster1cf47a12015-07-01 13:13:54 +02001672 match = re.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
1673 if match.end() != len(a):
1674 print >>sys.stderr, \
1675 "%s: 'funny character '%s' in argument of --prefix" \
1676 % (sys.argv[0], a[match.end()])
1677 sys.exit(1)
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001678 prefix = a
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001679 elif o in ("-o", "--output-dir"):
1680 output_dir = a + "/"
1681 elif o in ("-c", "--source"):
1682 do_c = True
1683 elif o in ("-h", "--header"):
1684 do_h = True
1685 else:
1686 extra_opts.append(oa)
1687
1688 if not do_c and not do_h:
1689 do_c = True
1690 do_h = True
1691
Markus Armbruster16d80f62015-04-02 13:32:16 +02001692 if len(args) != 1:
1693 print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
Markus Armbrusterb4540962015-04-02 13:17:34 +02001694 sys.exit(1)
Markus Armbruster54414042015-06-09 16:22:45 +02001695 fname = args[0]
Markus Armbrusterb4540962015-04-02 13:17:34 +02001696
Markus Armbruster54414042015-06-09 16:22:45 +02001697 return (fname, output_dir, do_c, do_h, prefix, extra_opts)
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001698
Markus Armbruster00e4b282015-06-10 10:04:36 +02001699#
1700# Generate output files with boilerplate
1701#
1702
Eric Blake437db252015-09-29 16:21:02 -06001703
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001704def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
1705 c_comment, h_comment):
Markus Armbruster00dfc3b2015-06-27 07:27:21 +02001706 guard = guardname(prefix + h_file)
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001707 c_file = output_dir + prefix + c_file
1708 h_file = output_dir + prefix + h_file
1709
Markus Armbrusterc4f498f2015-09-03 10:24:25 +02001710 if output_dir:
1711 try:
1712 os.makedirs(output_dir)
1713 except os.error, e:
1714 if e.errno != errno.EEXIST:
1715 raise
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001716
1717 def maybe_open(really, name, opt):
1718 if really:
1719 return open(name, opt)
1720 else:
1721 import StringIO
1722 return StringIO.StringIO()
1723
1724 fdef = maybe_open(do_c, c_file, 'w')
1725 fdecl = maybe_open(do_h, h_file, 'w')
1726
1727 fdef.write(mcgen('''
1728/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1729%(comment)s
1730''',
Eric Blake437db252015-09-29 16:21:02 -06001731 comment=c_comment))
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001732
1733 fdecl.write(mcgen('''
1734/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1735%(comment)s
1736#ifndef %(guard)s
1737#define %(guard)s
1738
1739''',
Eric Blake437db252015-09-29 16:21:02 -06001740 comment=h_comment, guard=guard))
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001741
1742 return (fdef, fdecl)
1743
Eric Blake437db252015-09-29 16:21:02 -06001744
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001745def close_output(fdef, fdecl):
1746 fdecl.write('''
1747#endif
1748''')
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001749 fdecl.close()
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001750 fdef.close()