blob: 3ff7b11e619c36ca5ed8a6576fce695c69c9e42e [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 Blake9fb081e2015-10-26 16:34:44 -0600493 if c_name(key, False).startswith('has_'):
494 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 Blake7b2a5c22015-09-29 16:21:04 -0600551 values = {'MAX': '(automatic)', 'KIND': '(automatic)'}
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800552
Eric Blake811d04f2015-05-04 09:05:10 -0600553 # Two types of unions, determined by discriminator.
Eric Blake811d04f2015-05-04 09:05:10 -0600554
555 # With no discriminator it is a simple union.
556 if discriminator is None:
Eric Blake44bd1272015-05-04 09:05:08 -0600557 enum_define = None
Eric Blake437db252015-09-29 16:21:02 -0600558 allow_metas = ['built-in', 'union', 'alternate', 'struct', 'enum']
Eric Blake44bd1272015-05-04 09:05:08 -0600559 if base is not None:
560 raise QAPIExprError(expr_info,
Eric Blake811d04f2015-05-04 09:05:10 -0600561 "Simple union '%s' must not have a base"
Eric Blake44bd1272015-05-04 09:05:08 -0600562 % name)
563
564 # Else, it's a flat union.
565 else:
566 # The object must have a string member 'base'.
Eric Blake376863e2015-09-29 16:21:07 -0600567 check_type(expr_info, "'base' for union '%s'" % name,
568 base, allow_metas=['struct'])
569 if not base:
Eric Blake44bd1272015-05-04 09:05:08 -0600570 raise QAPIExprError(expr_info,
Eric Blake376863e2015-09-29 16:21:07 -0600571 "Flat union '%s' must have a base"
Eric Blake44bd1272015-05-04 09:05:08 -0600572 % name)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800573 base_fields = find_base_fields(base)
Eric Blake376863e2015-09-29 16:21:07 -0600574 assert base_fields
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800575
Eric Blakec9e0a792015-05-04 09:05:22 -0600576 # The value of member 'discriminator' must name a non-optional
Eric Blakefd41dd42015-05-04 09:05:25 -0600577 # member of the base struct.
Eric Blakec9e0a792015-05-04 09:05:22 -0600578 check_name(expr_info, "Discriminator of flat union '%s'" % name,
579 discriminator)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800580 discriminator_type = base_fields.get(discriminator)
581 if not discriminator_type:
582 raise QAPIExprError(expr_info,
583 "Discriminator '%s' is not a member of base "
Eric Blakefd41dd42015-05-04 09:05:25 -0600584 "struct '%s'"
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800585 % (discriminator, base))
586 enum_define = find_enum(discriminator_type)
Eric Blake437db252015-09-29 16:21:02 -0600587 allow_metas = ['struct']
Wenchao Xia52230702014-03-04 18:44:39 -0800588 # Do not allow string discriminator
589 if not enum_define:
590 raise QAPIExprError(expr_info,
591 "Discriminator '%s' must be of enumeration "
592 "type" % discriminator)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800593
594 # Check every branch
595 for (key, value) in members.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600596 check_name(expr_info, "Member of union '%s'" % name, key)
597
Eric Blakedd883c62015-05-04 09:05:21 -0600598 # Each value must name a known type; furthermore, in flat unions,
Eric Blakeff55d722015-05-04 09:05:37 -0600599 # branches must be a struct with no overlapping member names
Eric Blakedd883c62015-05-04 09:05:21 -0600600 check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
Markus Armbrusterf9a14272015-06-10 13:07:43 +0200601 value, allow_array=not base, allow_metas=allow_metas)
Eric Blakeff55d722015-05-04 09:05:37 -0600602 if base:
603 branch_struct = find_struct(value)
604 assert branch_struct
605 check_member_clash(expr_info, base, branch_struct['data'],
606 " of branch '%s'" % key)
Eric Blakedd883c62015-05-04 09:05:21 -0600607
Eric Blake44bd1272015-05-04 09:05:08 -0600608 # If the discriminator names an enum type, then all members
Eric Blake7b2a5c22015-09-29 16:21:04 -0600609 # of 'data' must also be members of the enum type, which in turn
610 # must not collide with the discriminator name.
Eric Blake44bd1272015-05-04 09:05:08 -0600611 if enum_define:
Eric Blake437db252015-09-29 16:21:02 -0600612 if key not in enum_define['enum_values']:
Eric Blake44bd1272015-05-04 09:05:08 -0600613 raise QAPIExprError(expr_info,
614 "Discriminator value '%s' is not found in "
615 "enum '%s'" %
616 (key, enum_define["enum_name"]))
Eric Blake7b2a5c22015-09-29 16:21:04 -0600617 if discriminator in enum_define['enum_values']:
618 raise QAPIExprError(expr_info,
619 "Discriminator name '%s' collides with "
620 "enum value in '%s'" %
621 (discriminator, enum_define["enum_name"]))
Eric Blake44bd1272015-05-04 09:05:08 -0600622
623 # Otherwise, check for conflicts in the generated enum
624 else:
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600625 c_key = camel_to_upper(key)
Eric Blake44bd1272015-05-04 09:05:08 -0600626 if c_key in values:
627 raise QAPIExprError(expr_info,
628 "Union '%s' member '%s' clashes with '%s'"
629 % (name, key, values[c_key]))
630 values[c_key] = key
631
Eric Blake437db252015-09-29 16:21:02 -0600632
Eric Blake811d04f2015-05-04 09:05:10 -0600633def check_alternate(expr, expr_info):
Eric Blakeab916fa2015-05-04 09:05:13 -0600634 name = expr['alternate']
Eric Blake811d04f2015-05-04 09:05:10 -0600635 members = expr['data']
Eric Blake437db252015-09-29 16:21:02 -0600636 values = {'MAX': '(automatic)'}
Eric Blake811d04f2015-05-04 09:05:10 -0600637 types_seen = {}
Eric Blake44bd1272015-05-04 09:05:08 -0600638
Eric Blake811d04f2015-05-04 09:05:10 -0600639 # Check every branch
640 for (key, value) in members.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600641 check_name(expr_info, "Member of alternate '%s'" % name, key)
642
Eric Blake811d04f2015-05-04 09:05:10 -0600643 # Check for conflicts in the generated enum
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600644 c_key = camel_to_upper(key)
Eric Blake811d04f2015-05-04 09:05:10 -0600645 if c_key in values:
646 raise QAPIExprError(expr_info,
Eric Blakeab916fa2015-05-04 09:05:13 -0600647 "Alternate '%s' member '%s' clashes with '%s'"
648 % (name, key, values[c_key]))
Eric Blake811d04f2015-05-04 09:05:10 -0600649 values[c_key] = key
650
651 # Ensure alternates have no type conflicts.
Eric Blakedd883c62015-05-04 09:05:21 -0600652 check_type(expr_info, "Member '%s' of alternate '%s'" % (key, name),
653 value,
654 allow_metas=['built-in', 'union', 'struct', 'enum'])
Eric Blake811d04f2015-05-04 09:05:10 -0600655 qtype = find_alternate_member_qtype(value)
Eric Blakedd883c62015-05-04 09:05:21 -0600656 assert qtype
Eric Blake811d04f2015-05-04 09:05:10 -0600657 if qtype in types_seen:
658 raise QAPIExprError(expr_info,
Eric Blakeab916fa2015-05-04 09:05:13 -0600659 "Alternate '%s' member '%s' can't "
Eric Blake811d04f2015-05-04 09:05:10 -0600660 "be distinguished from member '%s'"
661 % (name, key, types_seen[qtype]))
662 types_seen[qtype] = key
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800663
Eric Blake437db252015-09-29 16:21:02 -0600664
Eric Blakecf393592015-05-04 09:05:04 -0600665def check_enum(expr, expr_info):
666 name = expr['enum']
667 members = expr.get('data')
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100668 prefix = expr.get('prefix')
Eric Blake437db252015-09-29 16:21:02 -0600669 values = {'MAX': '(automatic)'}
Eric Blakecf393592015-05-04 09:05:04 -0600670
671 if not isinstance(members, list):
672 raise QAPIExprError(expr_info,
673 "Enum '%s' requires an array for 'data'" % name)
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100674 if prefix is not None and not isinstance(prefix, str):
675 raise QAPIExprError(expr_info,
676 "Enum '%s' requires a string for 'prefix'" % name)
Eric Blakecf393592015-05-04 09:05:04 -0600677 for member in members:
Eric Blake437db252015-09-29 16:21:02 -0600678 check_name(expr_info, "Member of enum '%s'" % name, member,
Eric Blakec9e0a792015-05-04 09:05:22 -0600679 enum_member=True)
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600680 key = camel_to_upper(member)
Eric Blakecf393592015-05-04 09:05:04 -0600681 if key in values:
682 raise QAPIExprError(expr_info,
683 "Enum '%s' member '%s' clashes with '%s'"
684 % (name, member, values[key]))
685 values[key] = member
686
Eric Blake437db252015-09-29 16:21:02 -0600687
Eric Blakedd883c62015-05-04 09:05:21 -0600688def check_struct(expr, expr_info):
Eric Blakefd41dd42015-05-04 09:05:25 -0600689 name = expr['struct']
Eric Blakedd883c62015-05-04 09:05:21 -0600690 members = expr['data']
691
Eric Blakefd41dd42015-05-04 09:05:25 -0600692 check_type(expr_info, "'data' for struct '%s'" % name, members,
Eric Blakec9e0a792015-05-04 09:05:22 -0600693 allow_dict=True, allow_optional=True)
Eric Blakefd41dd42015-05-04 09:05:25 -0600694 check_type(expr_info, "'base' for struct '%s'" % name, expr.get('base'),
Eric Blakedd883c62015-05-04 09:05:21 -0600695 allow_metas=['struct'])
Eric Blakeff55d722015-05-04 09:05:37 -0600696 if expr.get('base'):
697 check_member_clash(expr_info, expr['base'], expr['data'])
Eric Blakedd883c62015-05-04 09:05:21 -0600698
Eric Blake437db252015-09-29 16:21:02 -0600699
Eric Blake0545f6b2015-05-04 09:05:15 -0600700def check_keys(expr_elem, meta, required, optional=[]):
701 expr = expr_elem['expr']
702 info = expr_elem['info']
703 name = expr[meta]
704 if not isinstance(name, str):
705 raise QAPIExprError(info,
706 "'%s' key must have a string value" % meta)
Eric Blake437db252015-09-29 16:21:02 -0600707 required = required + [meta]
Eric Blake0545f6b2015-05-04 09:05:15 -0600708 for (key, value) in expr.items():
Eric Blake437db252015-09-29 16:21:02 -0600709 if key not in required and key not in optional:
Eric Blake0545f6b2015-05-04 09:05:15 -0600710 raise QAPIExprError(info,
711 "Unknown key '%s' in %s '%s'"
712 % (key, meta, name))
Eric Blake437db252015-09-29 16:21:02 -0600713 if (key == 'gen' or key == 'success-response') and value is not False:
Eric Blake2cbf0992015-05-04 09:05:24 -0600714 raise QAPIExprError(info,
715 "'%s' of %s '%s' should only use false value"
716 % (key, meta, name))
Eric Blake0545f6b2015-05-04 09:05:15 -0600717 for key in required:
Eric Blake437db252015-09-29 16:21:02 -0600718 if key not in expr:
Eric Blake0545f6b2015-05-04 09:05:15 -0600719 raise QAPIExprError(info,
720 "Key '%s' is missing from %s '%s'"
721 % (key, meta, name))
722
Eric Blake437db252015-09-29 16:21:02 -0600723
Markus Armbruster4d076d62015-06-10 08:55:21 +0200724def check_exprs(exprs):
725 global all_names
726
727 # Learn the types and check for valid expression keys
728 for builtin in builtin_types.keys():
729 all_names[builtin] = 'built-in'
730 for expr_elem in exprs:
731 expr = expr_elem['expr']
732 info = expr_elem['info']
Eric Blake437db252015-09-29 16:21:02 -0600733 if 'enum' in expr:
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100734 check_keys(expr_elem, 'enum', ['data'], ['prefix'])
Markus Armbruster4d076d62015-06-10 08:55:21 +0200735 add_enum(expr['enum'], info, expr['data'])
Eric Blake437db252015-09-29 16:21:02 -0600736 elif 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200737 check_keys(expr_elem, 'union', ['data'],
738 ['base', 'discriminator'])
739 add_union(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600740 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200741 check_keys(expr_elem, 'alternate', ['data'])
742 add_name(expr['alternate'], info, 'alternate')
Eric Blake437db252015-09-29 16:21:02 -0600743 elif 'struct' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200744 check_keys(expr_elem, 'struct', ['data'], ['base'])
745 add_struct(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600746 elif 'command' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200747 check_keys(expr_elem, 'command', [],
748 ['data', 'returns', 'gen', 'success-response'])
749 add_name(expr['command'], info, 'command')
Eric Blake437db252015-09-29 16:21:02 -0600750 elif 'event' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200751 check_keys(expr_elem, 'event', [], ['data'])
752 add_name(expr['event'], info, 'event')
753 else:
754 raise QAPIExprError(expr_elem['info'],
755 "Expression is missing metatype")
756
757 # Try again for hidden UnionKind enum
758 for expr_elem in exprs:
759 expr = expr_elem['expr']
Eric Blake437db252015-09-29 16:21:02 -0600760 if 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200761 if not discriminator_find_enum_define(expr):
762 add_enum('%sKind' % expr['union'], expr_elem['info'],
763 implicit=True)
Eric Blake437db252015-09-29 16:21:02 -0600764 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200765 add_enum('%sKind' % expr['alternate'], expr_elem['info'],
766 implicit=True)
767
768 # Validate that exprs make sense
769 for expr_elem in exprs:
770 expr = expr_elem['expr']
771 info = expr_elem['info']
772
Eric Blake437db252015-09-29 16:21:02 -0600773 if 'enum' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200774 check_enum(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600775 elif 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200776 check_union(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600777 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200778 check_alternate(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600779 elif 'struct' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200780 check_struct(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600781 elif 'command' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200782 check_command(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600783 elif 'event' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200784 check_event(expr, info)
785 else:
786 assert False, 'unexpected meta type'
787
Markus Armbrusterac882192015-09-16 13:06:05 +0200788 return exprs
Eric Blake0545f6b2015-05-04 09:05:15 -0600789
Markus Armbrusterac882192015-09-16 13:06:05 +0200790
791#
792# Schema compiler frontend
793#
794
795class QAPISchemaEntity(object):
796 def __init__(self, name, info):
797 assert isinstance(name, str)
798 self.name = name
Eric Blake99df5282015-10-12 22:22:32 -0600799 # For explicitly defined entities, info points to the (explicit)
800 # definition. For builtins (and their arrays), info is None.
801 # For implicitly defined entities, info points to a place that
802 # triggered the implicit definition (there may be more than one
803 # such place).
Markus Armbrusterac882192015-09-16 13:06:05 +0200804 self.info = info
805
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200806 def c_name(self):
807 return c_name(self.name)
808
Markus Armbrusterac882192015-09-16 13:06:05 +0200809 def check(self, schema):
810 pass
811
Eric Blake49823c42015-10-12 22:22:27 -0600812 def is_implicit(self):
813 return not self.info
814
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200815 def visit(self, visitor):
816 pass
817
818
819class QAPISchemaVisitor(object):
820 def visit_begin(self, schema):
821 pass
822
823 def visit_end(self):
824 pass
825
Eric Blake25a0d9c2015-10-12 22:22:21 -0600826 def visit_needed(self, entity):
827 # Default to visiting everything
828 return True
829
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200830 def visit_builtin_type(self, name, info, json_type):
831 pass
832
833 def visit_enum_type(self, name, info, values, prefix):
834 pass
835
836 def visit_array_type(self, name, info, element_type):
837 pass
838
839 def visit_object_type(self, name, info, base, members, variants):
840 pass
841
Markus Armbruster39a18152015-09-16 13:06:28 +0200842 def visit_object_type_flat(self, name, info, members, variants):
843 pass
844
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200845 def visit_alternate_type(self, name, info, variants):
846 pass
847
848 def visit_command(self, name, info, arg_type, ret_type,
849 gen, success_response):
850 pass
851
852 def visit_event(self, name, info, arg_type):
853 pass
854
Markus Armbrusterac882192015-09-16 13:06:05 +0200855
856class QAPISchemaType(QAPISchemaEntity):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200857 def c_type(self, is_param=False):
858 return c_name(self.name) + pointer_suffix
859
860 def c_null(self):
861 return 'NULL'
862
863 def json_type(self):
864 pass
865
866 def alternate_qtype(self):
867 json2qtype = {
868 'string': 'QTYPE_QSTRING',
869 'number': 'QTYPE_QFLOAT',
870 'int': 'QTYPE_QINT',
871 'boolean': 'QTYPE_QBOOL',
872 'object': 'QTYPE_QDICT'
873 }
874 return json2qtype.get(self.json_type())
Markus Armbrusterac882192015-09-16 13:06:05 +0200875
876
877class QAPISchemaBuiltinType(QAPISchemaType):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200878 def __init__(self, name, json_type, c_type, c_null):
Markus Armbrusterac882192015-09-16 13:06:05 +0200879 QAPISchemaType.__init__(self, name, None)
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200880 assert not c_type or isinstance(c_type, str)
881 assert json_type in ('string', 'number', 'int', 'boolean', 'null',
882 'value')
883 self._json_type_name = json_type
884 self._c_type_name = c_type
885 self._c_null_val = c_null
886
887 def c_name(self):
888 return self.name
889
890 def c_type(self, is_param=False):
891 if is_param and self.name == 'str':
892 return 'const ' + self._c_type_name
893 return self._c_type_name
894
895 def c_null(self):
896 return self._c_null_val
897
898 def json_type(self):
899 return self._json_type_name
Markus Armbrusterac882192015-09-16 13:06:05 +0200900
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200901 def visit(self, visitor):
902 visitor.visit_builtin_type(self.name, self.info, self.json_type())
903
Markus Armbrusterac882192015-09-16 13:06:05 +0200904
905class QAPISchemaEnumType(QAPISchemaType):
906 def __init__(self, name, info, values, prefix):
907 QAPISchemaType.__init__(self, name, info)
908 for v in values:
909 assert isinstance(v, str)
910 assert prefix is None or isinstance(prefix, str)
911 self.values = values
912 self.prefix = prefix
913
914 def check(self, schema):
915 assert len(set(self.values)) == len(self.values)
916
Eric Blake99df5282015-10-12 22:22:32 -0600917 def is_implicit(self):
918 # See QAPISchema._make_implicit_enum_type()
Eric Blake8712fa52015-10-26 16:34:41 -0600919 return self.name.endswith('Kind')
Eric Blake99df5282015-10-12 22:22:32 -0600920
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200921 def c_type(self, is_param=False):
922 return c_name(self.name)
923
924 def c_null(self):
925 return c_enum_const(self.name, (self.values + ['MAX'])[0],
926 self.prefix)
927
928 def json_type(self):
929 return 'string'
930
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200931 def visit(self, visitor):
932 visitor.visit_enum_type(self.name, self.info,
933 self.values, self.prefix)
934
Markus Armbrusterac882192015-09-16 13:06:05 +0200935
936class QAPISchemaArrayType(QAPISchemaType):
937 def __init__(self, name, info, element_type):
938 QAPISchemaType.__init__(self, name, info)
939 assert isinstance(element_type, str)
940 self._element_type_name = element_type
941 self.element_type = None
942
943 def check(self, schema):
944 self.element_type = schema.lookup_type(self._element_type_name)
945 assert self.element_type
946
Eric Blake99df5282015-10-12 22:22:32 -0600947 def is_implicit(self):
948 return True
949
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200950 def json_type(self):
951 return 'array'
952
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200953 def visit(self, visitor):
954 visitor.visit_array_type(self.name, self.info, self.element_type)
955
Markus Armbrusterac882192015-09-16 13:06:05 +0200956
957class QAPISchemaObjectType(QAPISchemaType):
958 def __init__(self, name, info, base, local_members, variants):
959 QAPISchemaType.__init__(self, name, info)
960 assert base is None or isinstance(base, str)
961 for m in local_members:
962 assert isinstance(m, QAPISchemaObjectTypeMember)
963 assert (variants is None or
964 isinstance(variants, QAPISchemaObjectTypeVariants))
965 self._base_name = base
966 self.base = None
967 self.local_members = local_members
968 self.variants = variants
969 self.members = None
970
971 def check(self, schema):
972 assert self.members is not False # not running in cycles
973 if self.members:
974 return
975 self.members = False # mark as being checked
976 if self._base_name:
977 self.base = schema.lookup_type(self._base_name)
978 assert isinstance(self.base, QAPISchemaObjectType)
979 assert not self.base.variants # not implemented
980 self.base.check(schema)
981 members = list(self.base.members)
982 else:
983 members = []
984 seen = {}
985 for m in members:
Eric Blake7618b912015-10-12 22:22:22 -0600986 assert c_name(m.name) not in seen
Markus Armbrusterac882192015-09-16 13:06:05 +0200987 seen[m.name] = m
988 for m in self.local_members:
989 m.check(schema, members, seen)
990 if self.variants:
991 self.variants.check(schema, members, seen)
992 self.members = members
993
Eric Blake99df5282015-10-12 22:22:32 -0600994 def is_implicit(self):
995 # See QAPISchema._make_implicit_object_type()
996 return self.name[0] == ':'
997
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200998 def c_name(self):
Eric Blake49823c42015-10-12 22:22:27 -0600999 assert not self.is_implicit()
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001000 return QAPISchemaType.c_name(self)
1001
1002 def c_type(self, is_param=False):
Eric Blake49823c42015-10-12 22:22:27 -06001003 assert not self.is_implicit()
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001004 return QAPISchemaType.c_type(self)
1005
1006 def json_type(self):
1007 return 'object'
1008
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001009 def visit(self, visitor):
1010 visitor.visit_object_type(self.name, self.info,
1011 self.base, self.local_members, self.variants)
Markus Armbruster39a18152015-09-16 13:06:28 +02001012 visitor.visit_object_type_flat(self.name, self.info,
1013 self.members, self.variants)
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001014
Markus Armbrusterac882192015-09-16 13:06:05 +02001015
1016class QAPISchemaObjectTypeMember(object):
1017 def __init__(self, name, typ, optional):
1018 assert isinstance(name, str)
1019 assert isinstance(typ, str)
1020 assert isinstance(optional, bool)
1021 self.name = name
1022 self._type_name = typ
1023 self.type = None
1024 self.optional = optional
1025
1026 def check(self, schema, all_members, seen):
1027 assert self.name not in seen
1028 self.type = schema.lookup_type(self._type_name)
1029 assert self.type
1030 all_members.append(self)
1031 seen[self.name] = self
1032
1033
1034class QAPISchemaObjectTypeVariants(object):
Eric Blake46292ba2015-10-12 22:22:29 -06001035 def __init__(self, tag_name, tag_member, variants):
1036 # Flat unions pass tag_name but not tag_member.
1037 # Simple unions and alternates pass tag_member but not tag_name.
1038 # After check(), tag_member is always set, and tag_name remains
1039 # a reliable witness of being used by a flat union.
1040 assert bool(tag_member) != bool(tag_name)
1041 assert (isinstance(tag_name, str) or
1042 isinstance(tag_member, QAPISchemaObjectTypeMember))
Markus Armbrusterac882192015-09-16 13:06:05 +02001043 for v in variants:
1044 assert isinstance(v, QAPISchemaObjectTypeVariant)
1045 self.tag_name = tag_name
Eric Blake46292ba2015-10-12 22:22:29 -06001046 self.tag_member = tag_member
Markus Armbrusterac882192015-09-16 13:06:05 +02001047 self.variants = variants
1048
1049 def check(self, schema, members, seen):
1050 if self.tag_name:
1051 self.tag_member = seen[self.tag_name]
1052 else:
1053 self.tag_member.check(schema, members, seen)
1054 assert isinstance(self.tag_member.type, QAPISchemaEnumType)
1055 for v in self.variants:
1056 vseen = dict(seen)
1057 v.check(schema, self.tag_member.type, vseen)
1058
Eric Blake437db252015-09-29 16:21:02 -06001059
Markus Armbrusterac882192015-09-16 13:06:05 +02001060class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
1061 def __init__(self, name, typ):
1062 QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
1063
1064 def check(self, schema, tag_type, seen):
1065 QAPISchemaObjectTypeMember.check(self, schema, [], seen)
1066 assert self.name in tag_type.values
1067
Markus Armbruster2b162cc2015-09-16 13:06:09 +02001068 # This function exists to support ugly simple union special cases
1069 # TODO get rid of them, and drop the function
1070 def simple_union_type(self):
Eric Blake49823c42015-10-12 22:22:27 -06001071 if (self.type.is_implicit() and
1072 isinstance(self.type, QAPISchemaObjectType)):
Markus Armbruster2b162cc2015-09-16 13:06:09 +02001073 assert len(self.type.members) == 1
1074 assert not self.type.variants
1075 return self.type.members[0].type
1076 return None
1077
Markus Armbrusterac882192015-09-16 13:06:05 +02001078
1079class QAPISchemaAlternateType(QAPISchemaType):
1080 def __init__(self, name, info, variants):
1081 QAPISchemaType.__init__(self, name, info)
1082 assert isinstance(variants, QAPISchemaObjectTypeVariants)
1083 assert not variants.tag_name
1084 self.variants = variants
1085
1086 def check(self, schema):
1087 self.variants.check(schema, [], {})
1088
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001089 def json_type(self):
1090 return 'value'
1091
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001092 def visit(self, visitor):
1093 visitor.visit_alternate_type(self.name, self.info, self.variants)
1094
Markus Armbrusterac882192015-09-16 13:06:05 +02001095
1096class QAPISchemaCommand(QAPISchemaEntity):
1097 def __init__(self, name, info, arg_type, ret_type, gen, success_response):
1098 QAPISchemaEntity.__init__(self, name, info)
1099 assert not arg_type or isinstance(arg_type, str)
1100 assert not ret_type or isinstance(ret_type, str)
1101 self._arg_type_name = arg_type
1102 self.arg_type = None
1103 self._ret_type_name = ret_type
1104 self.ret_type = None
1105 self.gen = gen
1106 self.success_response = success_response
1107
1108 def check(self, schema):
1109 if self._arg_type_name:
1110 self.arg_type = schema.lookup_type(self._arg_type_name)
1111 assert isinstance(self.arg_type, QAPISchemaObjectType)
1112 assert not self.arg_type.variants # not implemented
1113 if self._ret_type_name:
1114 self.ret_type = schema.lookup_type(self._ret_type_name)
1115 assert isinstance(self.ret_type, QAPISchemaType)
1116
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001117 def visit(self, visitor):
1118 visitor.visit_command(self.name, self.info,
1119 self.arg_type, self.ret_type,
1120 self.gen, self.success_response)
1121
Markus Armbrusterac882192015-09-16 13:06:05 +02001122
1123class QAPISchemaEvent(QAPISchemaEntity):
1124 def __init__(self, name, info, arg_type):
1125 QAPISchemaEntity.__init__(self, name, info)
1126 assert not arg_type or isinstance(arg_type, str)
1127 self._arg_type_name = arg_type
1128 self.arg_type = None
1129
1130 def check(self, schema):
1131 if self._arg_type_name:
1132 self.arg_type = schema.lookup_type(self._arg_type_name)
1133 assert isinstance(self.arg_type, QAPISchemaObjectType)
1134 assert not self.arg_type.variants # not implemented
1135
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001136 def visit(self, visitor):
1137 visitor.visit_event(self.name, self.info, self.arg_type)
1138
Markus Armbrusterac882192015-09-16 13:06:05 +02001139
1140class QAPISchema(object):
1141 def __init__(self, fname):
1142 try:
1143 self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs)
Eric Blake7618b912015-10-12 22:22:22 -06001144 self._entity_dict = {}
Eric Blake99df5282015-10-12 22:22:32 -06001145 self._predefining = True
Eric Blake7618b912015-10-12 22:22:22 -06001146 self._def_predefineds()
Eric Blake99df5282015-10-12 22:22:32 -06001147 self._predefining = False
Eric Blake7618b912015-10-12 22:22:22 -06001148 self._def_exprs()
1149 self.check()
Markus Armbrusterac882192015-09-16 13:06:05 +02001150 except (QAPISchemaError, QAPIExprError), err:
1151 print >>sys.stderr, err
1152 exit(1)
Markus Armbrusterac882192015-09-16 13:06:05 +02001153
Markus Armbrusterac882192015-09-16 13:06:05 +02001154 def _def_entity(self, ent):
Eric Blake99df5282015-10-12 22:22:32 -06001155 # Only the predefined types are allowed to not have info
1156 assert ent.info or self._predefining
Markus Armbrusterac882192015-09-16 13:06:05 +02001157 assert ent.name not in self._entity_dict
1158 self._entity_dict[ent.name] = ent
1159
1160 def lookup_entity(self, name, typ=None):
1161 ent = self._entity_dict.get(name)
1162 if typ and not isinstance(ent, typ):
1163 return None
1164 return ent
1165
1166 def lookup_type(self, name):
1167 return self.lookup_entity(name, QAPISchemaType)
1168
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001169 def _def_builtin_type(self, name, json_type, c_type, c_null):
1170 self._def_entity(QAPISchemaBuiltinType(name, json_type,
1171 c_type, c_null))
Eric Blake9f08c8e2015-10-12 22:22:28 -06001172 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1173 # qapi-types.h from a single .c, all arrays of builtins must be
1174 # declared in the first file whether or not they are used. Nicer
1175 # would be to use lazy instantiation, while figuring out how to
1176 # avoid compilation issues with multiple qapi-types.h.
Eric Blake99df5282015-10-12 22:22:32 -06001177 self._make_array_type(name, None)
Markus Armbrusterac882192015-09-16 13:06:05 +02001178
1179 def _def_predefineds(self):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001180 for t in [('str', 'string', 'char' + pointer_suffix, 'NULL'),
1181 ('number', 'number', 'double', '0'),
1182 ('int', 'int', 'int64_t', '0'),
1183 ('int8', 'int', 'int8_t', '0'),
1184 ('int16', 'int', 'int16_t', '0'),
1185 ('int32', 'int', 'int32_t', '0'),
1186 ('int64', 'int', 'int64_t', '0'),
1187 ('uint8', 'int', 'uint8_t', '0'),
1188 ('uint16', 'int', 'uint16_t', '0'),
1189 ('uint32', 'int', 'uint32_t', '0'),
1190 ('uint64', 'int', 'uint64_t', '0'),
1191 ('size', 'int', 'uint64_t', '0'),
1192 ('bool', 'boolean', 'bool', 'false'),
Markus Armbruster28770e02015-09-16 13:06:24 +02001193 ('any', 'value', 'QObject' + pointer_suffix, 'NULL')]:
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001194 self._def_builtin_type(*t)
Markus Armbruster39a18152015-09-16 13:06:28 +02001195 self.the_empty_object_type = QAPISchemaObjectType(':empty', None, None,
1196 [], None)
1197 self._def_entity(self.the_empty_object_type)
Markus Armbrusterac882192015-09-16 13:06:05 +02001198
Eric Blake99df5282015-10-12 22:22:32 -06001199 def _make_implicit_enum_type(self, name, info, values):
Eric Blake49823c42015-10-12 22:22:27 -06001200 name = name + 'Kind' # Use namespace reserved by add_name()
Eric Blake99df5282015-10-12 22:22:32 -06001201 self._def_entity(QAPISchemaEnumType(name, info, values, None))
Markus Armbrusterac882192015-09-16 13:06:05 +02001202 return name
1203
Eric Blake99df5282015-10-12 22:22:32 -06001204 def _make_array_type(self, element_type, info):
Eric Blake255960d2015-10-26 16:34:43 -06001205 name = element_type + 'List' # Use namespace reserved by add_name()
Markus Armbrusterac882192015-09-16 13:06:05 +02001206 if not self.lookup_type(name):
Eric Blake99df5282015-10-12 22:22:32 -06001207 self._def_entity(QAPISchemaArrayType(name, info, element_type))
Markus Armbrusterac882192015-09-16 13:06:05 +02001208 return name
1209
Eric Blake99df5282015-10-12 22:22:32 -06001210 def _make_implicit_object_type(self, name, info, role, members):
Markus Armbrusterac882192015-09-16 13:06:05 +02001211 if not members:
1212 return None
1213 name = ':obj-%s-%s' % (name, role)
1214 if not self.lookup_entity(name, QAPISchemaObjectType):
Eric Blake99df5282015-10-12 22:22:32 -06001215 self._def_entity(QAPISchemaObjectType(name, info, None,
Markus Armbrusterac882192015-09-16 13:06:05 +02001216 members, None))
1217 return name
1218
1219 def _def_enum_type(self, expr, info):
1220 name = expr['enum']
1221 data = expr['data']
1222 prefix = expr.get('prefix')
1223 self._def_entity(QAPISchemaEnumType(name, info, data, prefix))
Markus Armbrusterac882192015-09-16 13:06:05 +02001224
Eric Blake99df5282015-10-12 22:22:32 -06001225 def _make_member(self, name, typ, info):
Markus Armbrusterac882192015-09-16 13:06:05 +02001226 optional = False
1227 if name.startswith('*'):
1228 name = name[1:]
1229 optional = True
1230 if isinstance(typ, list):
1231 assert len(typ) == 1
Eric Blake99df5282015-10-12 22:22:32 -06001232 typ = self._make_array_type(typ[0], info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001233 return QAPISchemaObjectTypeMember(name, typ, optional)
1234
Eric Blake99df5282015-10-12 22:22:32 -06001235 def _make_members(self, data, info):
1236 return [self._make_member(key, value, info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001237 for (key, value) in data.iteritems()]
1238
1239 def _def_struct_type(self, expr, info):
1240 name = expr['struct']
1241 base = expr.get('base')
1242 data = expr['data']
1243 self._def_entity(QAPISchemaObjectType(name, info, base,
Eric Blake99df5282015-10-12 22:22:32 -06001244 self._make_members(data, info),
Markus Armbrusterac882192015-09-16 13:06:05 +02001245 None))
Markus Armbrusterac882192015-09-16 13:06:05 +02001246
1247 def _make_variant(self, case, typ):
1248 return QAPISchemaObjectTypeVariant(case, typ)
1249
Eric Blake99df5282015-10-12 22:22:32 -06001250 def _make_simple_variant(self, case, typ, info):
Markus Armbrusterac882192015-09-16 13:06:05 +02001251 if isinstance(typ, list):
1252 assert len(typ) == 1
Eric Blake99df5282015-10-12 22:22:32 -06001253 typ = self._make_array_type(typ[0], info)
1254 typ = self._make_implicit_object_type(
1255 typ, info, 'wrapper', [self._make_member('data', typ, info)])
Markus Armbrusterac882192015-09-16 13:06:05 +02001256 return QAPISchemaObjectTypeVariant(case, typ)
1257
Eric Blake99df5282015-10-12 22:22:32 -06001258 def _make_implicit_tag(self, type_name, info, variants):
1259 typ = self._make_implicit_enum_type(type_name, info,
Eric Blake46292ba2015-10-12 22:22:29 -06001260 [v.name for v in variants])
1261 return QAPISchemaObjectTypeMember('type', typ, False)
Markus Armbrusterac882192015-09-16 13:06:05 +02001262
1263 def _def_union_type(self, expr, info):
1264 name = expr['union']
1265 data = expr['data']
1266 base = expr.get('base')
1267 tag_name = expr.get('discriminator')
Eric Blake46292ba2015-10-12 22:22:29 -06001268 tag_member = None
Markus Armbrusterac882192015-09-16 13:06:05 +02001269 if tag_name:
1270 variants = [self._make_variant(key, value)
1271 for (key, value) in data.iteritems()]
1272 else:
Eric Blake99df5282015-10-12 22:22:32 -06001273 variants = [self._make_simple_variant(key, value, info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001274 for (key, value) in data.iteritems()]
Eric Blake99df5282015-10-12 22:22:32 -06001275 tag_member = self._make_implicit_tag(name, info, variants)
Markus Armbrusterac882192015-09-16 13:06:05 +02001276 self._def_entity(
1277 QAPISchemaObjectType(name, info, base,
Eric Blake99df5282015-10-12 22:22:32 -06001278 self._make_members(OrderedDict(), info),
Markus Armbrusterac882192015-09-16 13:06:05 +02001279 QAPISchemaObjectTypeVariants(tag_name,
Eric Blake46292ba2015-10-12 22:22:29 -06001280 tag_member,
Markus Armbrusterac882192015-09-16 13:06:05 +02001281 variants)))
Markus Armbrusterac882192015-09-16 13:06:05 +02001282
1283 def _def_alternate_type(self, expr, info):
1284 name = expr['alternate']
1285 data = expr['data']
1286 variants = [self._make_variant(key, value)
1287 for (key, value) in data.iteritems()]
Eric Blake99df5282015-10-12 22:22:32 -06001288 tag_member = self._make_implicit_tag(name, info, variants)
Markus Armbrusterac882192015-09-16 13:06:05 +02001289 self._def_entity(
1290 QAPISchemaAlternateType(name, info,
1291 QAPISchemaObjectTypeVariants(None,
Eric Blake46292ba2015-10-12 22:22:29 -06001292 tag_member,
Markus Armbrusterac882192015-09-16 13:06:05 +02001293 variants)))
Markus Armbrusterac882192015-09-16 13:06:05 +02001294
1295 def _def_command(self, expr, info):
1296 name = expr['command']
1297 data = expr.get('data')
1298 rets = expr.get('returns')
1299 gen = expr.get('gen', True)
1300 success_response = expr.get('success-response', True)
1301 if isinstance(data, OrderedDict):
Eric Blake99df5282015-10-12 22:22:32 -06001302 data = self._make_implicit_object_type(
1303 name, info, 'arg', self._make_members(data, info))
Markus Armbrusterac882192015-09-16 13:06:05 +02001304 if isinstance(rets, list):
1305 assert len(rets) == 1
Eric Blake99df5282015-10-12 22:22:32 -06001306 rets = self._make_array_type(rets[0], info)
Markus Armbrusterac882192015-09-16 13:06:05 +02001307 self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
1308 success_response))
1309
1310 def _def_event(self, expr, info):
1311 name = expr['event']
1312 data = expr.get('data')
1313 if isinstance(data, OrderedDict):
Eric Blake99df5282015-10-12 22:22:32 -06001314 data = self._make_implicit_object_type(
1315 name, info, 'arg', self._make_members(data, info))
Markus Armbrusterac882192015-09-16 13:06:05 +02001316 self._def_entity(QAPISchemaEvent(name, info, data))
1317
1318 def _def_exprs(self):
1319 for expr_elem in self.exprs:
1320 expr = expr_elem['expr']
1321 info = expr_elem['info']
1322 if 'enum' in expr:
1323 self._def_enum_type(expr, info)
1324 elif 'struct' in expr:
1325 self._def_struct_type(expr, info)
1326 elif 'union' in expr:
1327 self._def_union_type(expr, info)
1328 elif 'alternate' in expr:
1329 self._def_alternate_type(expr, info)
1330 elif 'command' in expr:
1331 self._def_command(expr, info)
1332 elif 'event' in expr:
1333 self._def_event(expr, info)
1334 else:
1335 assert False
1336
1337 def check(self):
1338 for ent in self._entity_dict.values():
1339 ent.check(self)
1340
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001341 def visit(self, visitor):
Eric Blake25a0d9c2015-10-12 22:22:21 -06001342 visitor.visit_begin(self)
1343 for (name, entity) in sorted(self._entity_dict.items()):
1344 if visitor.visit_needed(entity):
1345 entity.visit(visitor)
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001346 visitor.visit_end()
1347
Markus Armbruster2caba362013-07-27 17:41:56 +02001348
Markus Armbruster00e4b282015-06-10 10:04:36 +02001349#
1350# Code generation helpers
1351#
1352
Michael Roth0f923be2011-07-19 14:50:39 -05001353def camel_case(name):
1354 new_name = ''
1355 first = True
1356 for ch in name:
1357 if ch in ['_', '-']:
1358 first = True
1359 elif first:
1360 new_name += ch.upper()
1361 first = False
1362 else:
1363 new_name += ch.lower()
1364 return new_name
1365
Eric Blake437db252015-09-29 16:21:02 -06001366
Markus Armbruster849bc532015-05-14 06:50:53 -06001367# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1368# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1369# ENUM24_Name -> ENUM24_NAME
1370def camel_to_upper(value):
1371 c_fun_str = c_name(value, False)
1372 if value.isupper():
1373 return c_fun_str
1374
1375 new_name = ''
1376 l = len(c_fun_str)
1377 for i in range(l):
1378 c = c_fun_str[i]
1379 # When c is upper and no "_" appears before, do more checks
1380 if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
Eric Blake437db252015-09-29 16:21:02 -06001381 if i < l - 1 and c_fun_str[i + 1].islower():
1382 new_name += '_'
1383 elif c_fun_str[i - 1].isdigit():
Markus Armbruster849bc532015-05-14 06:50:53 -06001384 new_name += '_'
1385 new_name += c
1386 return new_name.lstrip('_').upper()
1387
Eric Blake437db252015-09-29 16:21:02 -06001388
Daniel P. Berrange351d36e2015-08-26 14:21:20 +01001389def c_enum_const(type_name, const_name, prefix=None):
1390 if prefix is not None:
1391 type_name = prefix
Markus Armbruster849bc532015-05-14 06:50:53 -06001392 return camel_to_upper(type_name + '_' + const_name)
1393
Eric Blake18df5152015-05-14 06:50:48 -06001394c_name_trans = string.maketrans('.-', '__')
Markus Armbruster47299262015-05-14 06:50:47 -06001395
Eric Blake437db252015-09-29 16:21:02 -06001396
Eric Blakec6405b52015-05-14 06:50:55 -06001397# Map @name to a valid C identifier.
1398# If @protect, avoid returning certain ticklish identifiers (like
1399# C keywords) by prepending "q_".
1400#
1401# Used for converting 'name' from a 'name':'type' qapi definition
1402# into a generated struct member, as well as converting type names
1403# into substrings of a generated C function name.
1404# '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1405# protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
Eric Blake18df5152015-05-14 06:50:48 -06001406def c_name(name, protect=True):
Blue Swirl427a1a22012-07-30 15:46:55 +00001407 # ANSI X3J11/88-090, 3.1.1
1408 c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
Eric Blake437db252015-09-29 16:21:02 -06001409 'default', 'do', 'double', 'else', 'enum', 'extern',
1410 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1411 'return', 'short', 'signed', 'sizeof', 'static',
1412 'struct', 'switch', 'typedef', 'union', 'unsigned',
1413 'void', 'volatile', 'while'])
Blue Swirl427a1a22012-07-30 15:46:55 +00001414 # ISO/IEC 9899:1999, 6.4.1
1415 c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1416 # ISO/IEC 9899:2011, 6.4.1
Eric Blake437db252015-09-29 16:21:02 -06001417 c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1418 '_Noreturn', '_Static_assert', '_Thread_local'])
Blue Swirl427a1a22012-07-30 15:46:55 +00001419 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1420 # excluding _.*
1421 gcc_words = set(['asm', 'typeof'])
Tomoki Sekiyama6f880092013-08-07 11:39:43 -04001422 # C++ ISO/IEC 14882:2003 2.11
1423 cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
1424 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1425 'namespace', 'new', 'operator', 'private', 'protected',
1426 'public', 'reinterpret_cast', 'static_cast', 'template',
1427 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1428 'using', 'virtual', 'wchar_t',
1429 # alternative representations
1430 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1431 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
Paolo Bonzini10577252012-09-19 16:31:07 +02001432 # namespace pollution:
Max Reitz8592a542013-12-20 19:28:18 +01001433 polluted_words = set(['unix', 'errno'])
Eric Blake437db252015-09-29 16:21:02 -06001434 if protect and (name in c89_words | c99_words | c11_words | gcc_words
1435 | cpp_words | polluted_words):
Blue Swirl427a1a22012-07-30 15:46:55 +00001436 return "q_" + name
Eric Blake18df5152015-05-14 06:50:48 -06001437 return name.translate(c_name_trans)
Michael Roth0f923be2011-07-19 14:50:39 -05001438
Amos Kong05dfb262014-06-10 19:25:53 +08001439eatspace = '\033EATSPACE.'
Eric Blaked5573442015-05-14 06:50:54 -06001440pointer_suffix = ' *' + eatspace
Amos Kong05dfb262014-06-10 19:25:53 +08001441
Eric Blake437db252015-09-29 16:21:02 -06001442
Michael Roth0f923be2011-07-19 14:50:39 -05001443def genindent(count):
1444 ret = ""
Eric Blake437db252015-09-29 16:21:02 -06001445 for _ in range(count):
Michael Roth0f923be2011-07-19 14:50:39 -05001446 ret += " "
1447 return ret
1448
1449indent_level = 0
1450
Eric Blake437db252015-09-29 16:21:02 -06001451
Michael Roth0f923be2011-07-19 14:50:39 -05001452def push_indent(indent_amount=4):
1453 global indent_level
1454 indent_level += indent_amount
1455
Eric Blake437db252015-09-29 16:21:02 -06001456
Michael Roth0f923be2011-07-19 14:50:39 -05001457def pop_indent(indent_amount=4):
1458 global indent_level
1459 indent_level -= indent_amount
1460
Eric Blake437db252015-09-29 16:21:02 -06001461
Markus Armbruster77e703b2015-06-24 19:27:32 +02001462# Generate @code with @kwds interpolated.
1463# Obey indent_level, and strip eatspace.
Michael Roth0f923be2011-07-19 14:50:39 -05001464def cgen(code, **kwds):
Markus Armbruster77e703b2015-06-24 19:27:32 +02001465 raw = code % kwds
1466 if indent_level:
1467 indent = genindent(indent_level)
Markus Armbruster2752e5b2015-09-07 17:45:55 +02001468 # re.subn() lacks flags support before Python 2.7, use re.compile()
1469 raw = re.subn(re.compile("^.", re.MULTILINE),
1470 indent + r'\g<0>', raw)
Markus Armbruster77e703b2015-06-24 19:27:32 +02001471 raw = raw[0]
1472 return re.sub(re.escape(eatspace) + ' *', '', raw)
Michael Roth0f923be2011-07-19 14:50:39 -05001473
Eric Blake437db252015-09-29 16:21:02 -06001474
Michael Roth0f923be2011-07-19 14:50:39 -05001475def mcgen(code, **kwds):
Markus Armbruster77e703b2015-06-24 19:27:32 +02001476 if code[0] == '\n':
1477 code = code[1:]
1478 return cgen(code, **kwds)
Michael Roth0f923be2011-07-19 14:50:39 -05001479
Michael Roth0f923be2011-07-19 14:50:39 -05001480
1481def guardname(filename):
Markus Armbruster00dfc3b2015-06-27 07:27:21 +02001482 return c_name(filename, protect=False).upper()
Michael Rothc0afa9c2013-05-10 17:46:00 -05001483
Eric Blake437db252015-09-29 16:21:02 -06001484
Michael Rothc0afa9c2013-05-10 17:46:00 -05001485def guardstart(name):
1486 return mcgen('''
1487
1488#ifndef %(name)s
1489#define %(name)s
1490
1491''',
1492 name=guardname(name))
1493
Eric Blake437db252015-09-29 16:21:02 -06001494
Michael Rothc0afa9c2013-05-10 17:46:00 -05001495def guardend(name):
1496 return mcgen('''
1497
1498#endif /* %(name)s */
1499
1500''',
1501 name=guardname(name))
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001502
Eric Blake437db252015-09-29 16:21:02 -06001503
Markus Armbrustere98859a2015-09-16 13:06:16 +02001504def gen_enum_lookup(name, values, prefix=None):
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001505 ret = mcgen('''
1506
Markus Armbrustere98859a2015-09-16 13:06:16 +02001507const char *const %(c_name)s_lookup[] = {
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001508''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001509 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001510 for value in values:
1511 index = c_enum_const(name, value, prefix)
1512 ret += mcgen('''
1513 [%(index)s] = "%(value)s",
1514''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001515 index=index, value=value)
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001516
1517 max_index = c_enum_const(name, 'MAX', prefix)
1518 ret += mcgen('''
1519 [%(max_index)s] = NULL,
1520};
1521''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001522 max_index=max_index)
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001523 return ret
1524
Eric Blake437db252015-09-29 16:21:02 -06001525
Markus Armbrustere98859a2015-09-16 13:06:16 +02001526def gen_enum(name, values, prefix=None):
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001527 # append automatically generated _MAX value
Markus Armbrustere98859a2015-09-16 13:06:16 +02001528 enum_values = values + ['MAX']
1529
1530 ret = mcgen('''
1531
1532typedef enum %(c_name)s {
1533''',
1534 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001535
1536 i = 0
1537 for value in enum_values:
Markus Armbrustere98859a2015-09-16 13:06:16 +02001538 ret += mcgen('''
1539 %(c_enum)s = %(i)d,
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001540''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001541 c_enum=c_enum_const(name, value, prefix),
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001542 i=i)
1543 i += 1
1544
Markus Armbrustere98859a2015-09-16 13:06:16 +02001545 ret += mcgen('''
1546} %(c_name)s;
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001547''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001548 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001549
Markus Armbrustere98859a2015-09-16 13:06:16 +02001550 ret += mcgen('''
1551
1552extern const char *const %(c_name)s_lookup[];
1553''',
1554 c_name=c_name(name))
1555 return ret
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001556
Eric Blake437db252015-09-29 16:21:02 -06001557
Markus Armbruster03b43672015-09-16 13:06:20 +02001558def gen_params(arg_type, extra):
1559 if not arg_type:
1560 return extra
1561 assert not arg_type.variants
1562 ret = ''
1563 sep = ''
1564 for memb in arg_type.members:
1565 ret += sep
1566 sep = ', '
1567 if memb.optional:
1568 ret += 'bool has_%s, ' % c_name(memb.name)
1569 ret += '%s %s' % (memb.type.c_type(is_param=True), c_name(memb.name))
1570 if extra:
1571 ret += sep + extra
1572 return ret
1573
Eric Blake1f353342015-09-29 16:21:13 -06001574
Eric Blake18bdbc32015-09-29 16:21:15 -06001575def gen_err_check(label='out', skiperr=False):
1576 if skiperr:
Eric Blake1f353342015-09-29 16:21:13 -06001577 return ''
1578 return mcgen('''
Eric Blake18bdbc32015-09-29 16:21:15 -06001579 if (err) {
Eric Blake1f353342015-09-29 16:21:13 -06001580 goto %(label)s;
1581 }
1582''',
Eric Blake18bdbc32015-09-29 16:21:15 -06001583 label=label)
Eric Blake1f353342015-09-29 16:21:13 -06001584
1585
Eric Blake18bdbc32015-09-29 16:21:15 -06001586def gen_visit_fields(members, prefix='', need_cast=False, skiperr=False):
Eric Blake82ca8e42015-09-29 16:21:14 -06001587 ret = ''
Eric Blake18bdbc32015-09-29 16:21:15 -06001588 if skiperr:
Eric Blake82ca8e42015-09-29 16:21:14 -06001589 errparg = 'NULL'
Eric Blake18bdbc32015-09-29 16:21:15 -06001590 else:
1591 errparg = '&err'
Eric Blake82ca8e42015-09-29 16:21:14 -06001592
1593 for memb in members:
1594 if memb.optional:
1595 ret += mcgen('''
1596 visit_optional(v, &%(prefix)shas_%(c_name)s, "%(name)s", %(errp)s);
1597''',
1598 prefix=prefix, c_name=c_name(memb.name),
1599 name=memb.name, errp=errparg)
Eric Blake18bdbc32015-09-29 16:21:15 -06001600 ret += gen_err_check(skiperr=skiperr)
Eric Blake82ca8e42015-09-29 16:21:14 -06001601 ret += mcgen('''
1602 if (%(prefix)shas_%(c_name)s) {
1603''',
1604 prefix=prefix, c_name=c_name(memb.name))
1605 push_indent()
1606
1607 # Ugly: sometimes we need to cast away const
1608 if need_cast and memb.type.name == 'str':
1609 cast = '(char **)'
1610 else:
1611 cast = ''
1612
1613 ret += mcgen('''
1614 visit_type_%(c_type)s(v, %(cast)s&%(prefix)s%(c_name)s, "%(name)s", %(errp)s);
1615''',
1616 c_type=memb.type.c_name(), prefix=prefix, cast=cast,
1617 c_name=c_name(memb.name), name=memb.name,
1618 errp=errparg)
Eric Blake18bdbc32015-09-29 16:21:15 -06001619 ret += gen_err_check(skiperr=skiperr)
Eric Blake82ca8e42015-09-29 16:21:14 -06001620
1621 if memb.optional:
1622 pop_indent()
1623 ret += mcgen('''
1624 }
1625''')
1626 return ret
1627
1628
Markus Armbruster00e4b282015-06-10 10:04:36 +02001629#
1630# Common command line parsing
1631#
1632
Eric Blake437db252015-09-29 16:21:02 -06001633
1634def parse_command_line(extra_options="", extra_long_options=[]):
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001635
1636 try:
1637 opts, args = getopt.gnu_getopt(sys.argv[1:],
Markus Armbruster16d80f62015-04-02 13:32:16 +02001638 "chp:o:" + extra_options,
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001639 ["source", "header", "prefix=",
Markus Armbruster16d80f62015-04-02 13:32:16 +02001640 "output-dir="] + extra_long_options)
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001641 except getopt.GetoptError, err:
Markus Armbrusterb4540962015-04-02 13:17:34 +02001642 print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err))
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001643 sys.exit(1)
1644
1645 output_dir = ""
1646 prefix = ""
1647 do_c = False
1648 do_h = False
1649 extra_opts = []
1650
1651 for oa in opts:
1652 o, a = oa
1653 if o in ("-p", "--prefix"):
Markus Armbruster1cf47a12015-07-01 13:13:54 +02001654 match = re.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
1655 if match.end() != len(a):
1656 print >>sys.stderr, \
1657 "%s: 'funny character '%s' in argument of --prefix" \
1658 % (sys.argv[0], a[match.end()])
1659 sys.exit(1)
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001660 prefix = a
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001661 elif o in ("-o", "--output-dir"):
1662 output_dir = a + "/"
1663 elif o in ("-c", "--source"):
1664 do_c = True
1665 elif o in ("-h", "--header"):
1666 do_h = True
1667 else:
1668 extra_opts.append(oa)
1669
1670 if not do_c and not do_h:
1671 do_c = True
1672 do_h = True
1673
Markus Armbruster16d80f62015-04-02 13:32:16 +02001674 if len(args) != 1:
1675 print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
Markus Armbrusterb4540962015-04-02 13:17:34 +02001676 sys.exit(1)
Markus Armbruster54414042015-06-09 16:22:45 +02001677 fname = args[0]
Markus Armbrusterb4540962015-04-02 13:17:34 +02001678
Markus Armbruster54414042015-06-09 16:22:45 +02001679 return (fname, output_dir, do_c, do_h, prefix, extra_opts)
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001680
Markus Armbruster00e4b282015-06-10 10:04:36 +02001681#
1682# Generate output files with boilerplate
1683#
1684
Eric Blake437db252015-09-29 16:21:02 -06001685
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001686def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
1687 c_comment, h_comment):
Markus Armbruster00dfc3b2015-06-27 07:27:21 +02001688 guard = guardname(prefix + h_file)
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001689 c_file = output_dir + prefix + c_file
1690 h_file = output_dir + prefix + h_file
1691
Markus Armbrusterc4f498f2015-09-03 10:24:25 +02001692 if output_dir:
1693 try:
1694 os.makedirs(output_dir)
1695 except os.error, e:
1696 if e.errno != errno.EEXIST:
1697 raise
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001698
1699 def maybe_open(really, name, opt):
1700 if really:
1701 return open(name, opt)
1702 else:
1703 import StringIO
1704 return StringIO.StringIO()
1705
1706 fdef = maybe_open(do_c, c_file, 'w')
1707 fdecl = maybe_open(do_h, h_file, 'w')
1708
1709 fdef.write(mcgen('''
1710/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1711%(comment)s
1712''',
Eric Blake437db252015-09-29 16:21:02 -06001713 comment=c_comment))
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001714
1715 fdecl.write(mcgen('''
1716/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1717%(comment)s
1718#ifndef %(guard)s
1719#define %(guard)s
1720
1721''',
Eric Blake437db252015-09-29 16:21:02 -06001722 comment=h_comment, guard=guard))
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001723
1724 return (fdef, fdecl)
1725
Eric Blake437db252015-09-29 16:21:02 -06001726
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001727def close_output(fdef, fdecl):
1728 fdecl.write('''
1729#endif
1730''')
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001731 fdecl.close()
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001732 fdef.close()