blob: 471bbfc40696f0203370b02177eee5b7c26a579a [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)
175 elif self.tok in ['{', '}', ':', ',', '[', ']']:
176 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
379 if not valid_name.match(membername):
380 raise QAPIExprError(expr_info,
381 "%s uses invalid name '%s'" % (source, name))
382
Eric Blake437db252015-09-29 16:21:02 -0600383
384def add_name(name, info, meta, implicit=False):
Markus Armbruster00e4b282015-06-10 10:04:36 +0200385 global all_names
386 check_name(info, "'%s'" % meta, name)
Markus Armbrusterd90675f2015-07-31 11:33:52 +0200387 # FIXME should reject names that differ only in '_' vs. '.'
388 # vs. '-', because they're liable to clash in generated C.
Markus Armbruster00e4b282015-06-10 10:04:36 +0200389 if name in all_names:
390 raise QAPIExprError(info,
391 "%s '%s' is already defined"
392 % (all_names[name], name))
393 if not implicit and name[-4:] == 'Kind':
394 raise QAPIExprError(info,
395 "%s '%s' should not end in 'Kind'"
396 % (meta, name))
397 all_names[name] = meta
398
Eric Blake437db252015-09-29 16:21:02 -0600399
Markus Armbruster00e4b282015-06-10 10:04:36 +0200400def add_struct(definition, info):
401 global struct_types
402 name = definition['struct']
403 add_name(name, info, 'struct')
404 struct_types.append(definition)
405
Eric Blake437db252015-09-29 16:21:02 -0600406
Markus Armbruster00e4b282015-06-10 10:04:36 +0200407def find_struct(name):
408 global struct_types
409 for struct in struct_types:
410 if struct['struct'] == name:
411 return struct
412 return None
413
Eric Blake437db252015-09-29 16:21:02 -0600414
Markus Armbruster00e4b282015-06-10 10:04:36 +0200415def add_union(definition, info):
416 global union_types
417 name = definition['union']
418 add_name(name, info, 'union')
419 union_types.append(definition)
420
Eric Blake437db252015-09-29 16:21:02 -0600421
Markus Armbruster00e4b282015-06-10 10:04:36 +0200422def find_union(name):
423 global union_types
424 for union in union_types:
425 if union['union'] == name:
426 return union
427 return None
428
Eric Blake437db252015-09-29 16:21:02 -0600429
430def add_enum(name, info, enum_values=None, implicit=False):
Markus Armbruster00e4b282015-06-10 10:04:36 +0200431 global enum_types
432 add_name(name, info, 'enum', implicit)
433 enum_types.append({"enum_name": name, "enum_values": enum_values})
434
Eric Blake437db252015-09-29 16:21:02 -0600435
Markus Armbruster00e4b282015-06-10 10:04:36 +0200436def find_enum(name):
437 global enum_types
438 for enum in enum_types:
439 if enum['enum_name'] == name:
440 return enum
441 return None
442
Markus Armbruster00e4b282015-06-10 10:04:36 +0200443
Eric Blake437db252015-09-29 16:21:02 -0600444def is_enum(name):
445 return find_enum(name) is not None
446
447
448def check_type(expr_info, source, value, allow_array=False,
449 allow_dict=False, allow_optional=False,
450 allow_metas=[]):
Eric Blakedd883c62015-05-04 09:05:21 -0600451 global all_names
Eric Blakedd883c62015-05-04 09:05:21 -0600452
453 if value is None:
454 return
455
Eric Blakedd883c62015-05-04 09:05:21 -0600456 # Check if array type for value is okay
457 if isinstance(value, list):
458 if not allow_array:
459 raise QAPIExprError(expr_info,
460 "%s cannot be an array" % source)
461 if len(value) != 1 or not isinstance(value[0], str):
462 raise QAPIExprError(expr_info,
463 "%s: array type must contain single type name"
464 % source)
465 value = value[0]
Eric Blakedd883c62015-05-04 09:05:21 -0600466
467 # Check if type name for value is okay
468 if isinstance(value, str):
Eric Blake437db252015-09-29 16:21:02 -0600469 if value not in all_names:
Eric Blakedd883c62015-05-04 09:05:21 -0600470 raise QAPIExprError(expr_info,
471 "%s uses unknown type '%s'"
Markus Armbrustereddf8172015-08-31 13:54:39 +0200472 % (source, value))
Eric Blakedd883c62015-05-04 09:05:21 -0600473 if not all_names[value] in allow_metas:
474 raise QAPIExprError(expr_info,
475 "%s cannot use %s type '%s'"
Markus Armbrustereddf8172015-08-31 13:54:39 +0200476 % (source, all_names[value], value))
Eric Blakedd883c62015-05-04 09:05:21 -0600477 return
478
Eric Blakedd883c62015-05-04 09:05:21 -0600479 if not allow_dict:
480 raise QAPIExprError(expr_info,
481 "%s should be a type name" % source)
Markus Armbrusterc6b71e52015-08-31 17:28:52 +0200482
483 if not isinstance(value, OrderedDict):
484 raise QAPIExprError(expr_info,
485 "%s should be a dictionary or type name" % source)
486
487 # value is a dictionary, check that each member is okay
Eric Blakedd883c62015-05-04 09:05:21 -0600488 for (key, arg) in value.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600489 check_name(expr_info, "Member of %s" % source, key,
490 allow_optional=allow_optional)
Eric Blake6b5abc72015-05-04 09:05:33 -0600491 # Todo: allow dictionaries to represent default values of
492 # an optional argument.
Eric Blakedd883c62015-05-04 09:05:21 -0600493 check_type(expr_info, "Member '%s' of %s" % (key, source), arg,
Markus Armbruster2d212912015-09-16 13:06:27 +0200494 allow_array=True,
Eric Blakedd883c62015-05-04 09:05:21 -0600495 allow_metas=['built-in', 'union', 'alternate', 'struct',
Eric Blake6b5abc72015-05-04 09:05:33 -0600496 'enum'])
Eric Blakedd883c62015-05-04 09:05:21 -0600497
Eric Blake437db252015-09-29 16:21:02 -0600498
499def check_member_clash(expr_info, base_name, data, source=""):
Eric Blakeff55d722015-05-04 09:05:37 -0600500 base = find_struct(base_name)
501 assert base
502 base_members = base['data']
503 for key in data.keys():
504 if key.startswith('*'):
505 key = key[1:]
506 if key in base_members or "*" + key in base_members:
507 raise QAPIExprError(expr_info,
508 "Member name '%s'%s clashes with base '%s'"
509 % (key, source, base_name))
510 if base.get('base'):
511 check_member_clash(expr_info, base['base'], data, source)
512
Eric Blake437db252015-09-29 16:21:02 -0600513
Eric Blakedd883c62015-05-04 09:05:21 -0600514def check_command(expr, expr_info):
515 name = expr['command']
Eric Blake2cbf0992015-05-04 09:05:24 -0600516
Eric Blakedd883c62015-05-04 09:05:21 -0600517 check_type(expr_info, "'data' for command '%s'" % name,
Eric Blakec9e0a792015-05-04 09:05:22 -0600518 expr.get('data'), allow_dict=True, allow_optional=True,
Markus Armbruster2d212912015-09-16 13:06:27 +0200519 allow_metas=['struct'])
Eric Blake10d4d992015-05-04 09:05:23 -0600520 returns_meta = ['union', 'struct']
521 if name in returns_whitelist:
522 returns_meta += ['built-in', 'alternate', 'enum']
Eric Blakedd883c62015-05-04 09:05:21 -0600523 check_type(expr_info, "'returns' for command '%s'" % name,
Markus Armbruster9b090d42015-07-31 17:59:38 +0200524 expr.get('returns'), allow_array=True,
Markus Armbruster2d212912015-09-16 13:06:27 +0200525 allow_optional=True, allow_metas=returns_meta)
Eric Blakedd883c62015-05-04 09:05:21 -0600526
Eric Blake437db252015-09-29 16:21:02 -0600527
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200528def check_event(expr, expr_info):
Eric Blake4dc2e692015-05-04 09:05:17 -0600529 global events
530 name = expr['event']
Eric Blake4dc2e692015-05-04 09:05:17 -0600531
532 if name.upper() == 'MAX':
533 raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created")
534 events.append(name)
Eric Blakedd883c62015-05-04 09:05:21 -0600535 check_type(expr_info, "'data' for event '%s'" % name,
Eric Blakec9e0a792015-05-04 09:05:22 -0600536 expr.get('data'), allow_dict=True, allow_optional=True,
Markus Armbruster315932b2015-07-01 10:12:24 +0200537 allow_metas=['struct'])
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200538
Eric Blake437db252015-09-29 16:21:02 -0600539
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800540def check_union(expr, expr_info):
541 name = expr['union']
542 base = expr.get('base')
543 discriminator = expr.get('discriminator')
544 members = expr['data']
Eric Blake7b2a5c22015-09-29 16:21:04 -0600545 values = {'MAX': '(automatic)', 'KIND': '(automatic)'}
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800546
Eric Blake811d04f2015-05-04 09:05:10 -0600547 # Two types of unions, determined by discriminator.
Eric Blake811d04f2015-05-04 09:05:10 -0600548
549 # With no discriminator it is a simple union.
550 if discriminator is None:
Eric Blake44bd1272015-05-04 09:05:08 -0600551 enum_define = None
Eric Blake437db252015-09-29 16:21:02 -0600552 allow_metas = ['built-in', 'union', 'alternate', 'struct', 'enum']
Eric Blake44bd1272015-05-04 09:05:08 -0600553 if base is not None:
554 raise QAPIExprError(expr_info,
Eric Blake811d04f2015-05-04 09:05:10 -0600555 "Simple union '%s' must not have a base"
Eric Blake44bd1272015-05-04 09:05:08 -0600556 % name)
557
558 # Else, it's a flat union.
559 else:
560 # The object must have a string member 'base'.
Eric Blake376863e2015-09-29 16:21:07 -0600561 check_type(expr_info, "'base' for union '%s'" % name,
562 base, allow_metas=['struct'])
563 if not base:
Eric Blake44bd1272015-05-04 09:05:08 -0600564 raise QAPIExprError(expr_info,
Eric Blake376863e2015-09-29 16:21:07 -0600565 "Flat union '%s' must have a base"
Eric Blake44bd1272015-05-04 09:05:08 -0600566 % name)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800567 base_fields = find_base_fields(base)
Eric Blake376863e2015-09-29 16:21:07 -0600568 assert base_fields
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800569
Eric Blakec9e0a792015-05-04 09:05:22 -0600570 # The value of member 'discriminator' must name a non-optional
Eric Blakefd41dd42015-05-04 09:05:25 -0600571 # member of the base struct.
Eric Blakec9e0a792015-05-04 09:05:22 -0600572 check_name(expr_info, "Discriminator of flat union '%s'" % name,
573 discriminator)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800574 discriminator_type = base_fields.get(discriminator)
575 if not discriminator_type:
576 raise QAPIExprError(expr_info,
577 "Discriminator '%s' is not a member of base "
Eric Blakefd41dd42015-05-04 09:05:25 -0600578 "struct '%s'"
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800579 % (discriminator, base))
580 enum_define = find_enum(discriminator_type)
Eric Blake437db252015-09-29 16:21:02 -0600581 allow_metas = ['struct']
Wenchao Xia52230702014-03-04 18:44:39 -0800582 # Do not allow string discriminator
583 if not enum_define:
584 raise QAPIExprError(expr_info,
585 "Discriminator '%s' must be of enumeration "
586 "type" % discriminator)
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800587
588 # Check every branch
589 for (key, value) in members.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600590 check_name(expr_info, "Member of union '%s'" % name, key)
591
Eric Blakedd883c62015-05-04 09:05:21 -0600592 # Each value must name a known type; furthermore, in flat unions,
Eric Blakeff55d722015-05-04 09:05:37 -0600593 # branches must be a struct with no overlapping member names
Eric Blakedd883c62015-05-04 09:05:21 -0600594 check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
Markus Armbrusterf9a14272015-06-10 13:07:43 +0200595 value, allow_array=not base, allow_metas=allow_metas)
Eric Blakeff55d722015-05-04 09:05:37 -0600596 if base:
597 branch_struct = find_struct(value)
598 assert branch_struct
599 check_member_clash(expr_info, base, branch_struct['data'],
600 " of branch '%s'" % key)
Eric Blakedd883c62015-05-04 09:05:21 -0600601
Eric Blake44bd1272015-05-04 09:05:08 -0600602 # If the discriminator names an enum type, then all members
Eric Blake7b2a5c22015-09-29 16:21:04 -0600603 # of 'data' must also be members of the enum type, which in turn
604 # must not collide with the discriminator name.
Eric Blake44bd1272015-05-04 09:05:08 -0600605 if enum_define:
Eric Blake437db252015-09-29 16:21:02 -0600606 if key not in enum_define['enum_values']:
Eric Blake44bd1272015-05-04 09:05:08 -0600607 raise QAPIExprError(expr_info,
608 "Discriminator value '%s' is not found in "
609 "enum '%s'" %
610 (key, enum_define["enum_name"]))
Eric Blake7b2a5c22015-09-29 16:21:04 -0600611 if discriminator in enum_define['enum_values']:
612 raise QAPIExprError(expr_info,
613 "Discriminator name '%s' collides with "
614 "enum value in '%s'" %
615 (discriminator, enum_define["enum_name"]))
Eric Blake44bd1272015-05-04 09:05:08 -0600616
617 # Otherwise, check for conflicts in the generated enum
618 else:
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600619 c_key = camel_to_upper(key)
Eric Blake44bd1272015-05-04 09:05:08 -0600620 if c_key in values:
621 raise QAPIExprError(expr_info,
622 "Union '%s' member '%s' clashes with '%s'"
623 % (name, key, values[c_key]))
624 values[c_key] = key
625
Eric Blake437db252015-09-29 16:21:02 -0600626
Eric Blake811d04f2015-05-04 09:05:10 -0600627def check_alternate(expr, expr_info):
Eric Blakeab916fa2015-05-04 09:05:13 -0600628 name = expr['alternate']
Eric Blake811d04f2015-05-04 09:05:10 -0600629 members = expr['data']
Eric Blake437db252015-09-29 16:21:02 -0600630 values = {'MAX': '(automatic)'}
Eric Blake811d04f2015-05-04 09:05:10 -0600631 types_seen = {}
Eric Blake44bd1272015-05-04 09:05:08 -0600632
Eric Blake811d04f2015-05-04 09:05:10 -0600633 # Check every branch
634 for (key, value) in members.items():
Eric Blakec9e0a792015-05-04 09:05:22 -0600635 check_name(expr_info, "Member of alternate '%s'" % name, key)
636
Eric Blake811d04f2015-05-04 09:05:10 -0600637 # Check for conflicts in the generated enum
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600638 c_key = camel_to_upper(key)
Eric Blake811d04f2015-05-04 09:05:10 -0600639 if c_key in values:
640 raise QAPIExprError(expr_info,
Eric Blakeab916fa2015-05-04 09:05:13 -0600641 "Alternate '%s' member '%s' clashes with '%s'"
642 % (name, key, values[c_key]))
Eric Blake811d04f2015-05-04 09:05:10 -0600643 values[c_key] = key
644
645 # Ensure alternates have no type conflicts.
Eric Blakedd883c62015-05-04 09:05:21 -0600646 check_type(expr_info, "Member '%s' of alternate '%s'" % (key, name),
647 value,
648 allow_metas=['built-in', 'union', 'struct', 'enum'])
Eric Blake811d04f2015-05-04 09:05:10 -0600649 qtype = find_alternate_member_qtype(value)
Eric Blakedd883c62015-05-04 09:05:21 -0600650 assert qtype
Eric Blake811d04f2015-05-04 09:05:10 -0600651 if qtype in types_seen:
652 raise QAPIExprError(expr_info,
Eric Blakeab916fa2015-05-04 09:05:13 -0600653 "Alternate '%s' member '%s' can't "
Eric Blake811d04f2015-05-04 09:05:10 -0600654 "be distinguished from member '%s'"
655 % (name, key, types_seen[qtype]))
656 types_seen[qtype] = key
Wenchao Xiab86b05e2014-03-04 18:44:34 -0800657
Eric Blake437db252015-09-29 16:21:02 -0600658
Eric Blakecf393592015-05-04 09:05:04 -0600659def check_enum(expr, expr_info):
660 name = expr['enum']
661 members = expr.get('data')
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100662 prefix = expr.get('prefix')
Eric Blake437db252015-09-29 16:21:02 -0600663 values = {'MAX': '(automatic)'}
Eric Blakecf393592015-05-04 09:05:04 -0600664
665 if not isinstance(members, list):
666 raise QAPIExprError(expr_info,
667 "Enum '%s' requires an array for 'data'" % name)
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100668 if prefix is not None and not isinstance(prefix, str):
669 raise QAPIExprError(expr_info,
670 "Enum '%s' requires a string for 'prefix'" % name)
Eric Blakecf393592015-05-04 09:05:04 -0600671 for member in members:
Eric Blake437db252015-09-29 16:21:02 -0600672 check_name(expr_info, "Member of enum '%s'" % name, member,
Eric Blakec9e0a792015-05-04 09:05:22 -0600673 enum_member=True)
Markus Armbrusterfa6068a2015-05-14 06:50:49 -0600674 key = camel_to_upper(member)
Eric Blakecf393592015-05-04 09:05:04 -0600675 if key in values:
676 raise QAPIExprError(expr_info,
677 "Enum '%s' member '%s' clashes with '%s'"
678 % (name, member, values[key]))
679 values[key] = member
680
Eric Blake437db252015-09-29 16:21:02 -0600681
Eric Blakedd883c62015-05-04 09:05:21 -0600682def check_struct(expr, expr_info):
Eric Blakefd41dd42015-05-04 09:05:25 -0600683 name = expr['struct']
Eric Blakedd883c62015-05-04 09:05:21 -0600684 members = expr['data']
685
Eric Blakefd41dd42015-05-04 09:05:25 -0600686 check_type(expr_info, "'data' for struct '%s'" % name, members,
Eric Blakec9e0a792015-05-04 09:05:22 -0600687 allow_dict=True, allow_optional=True)
Eric Blakefd41dd42015-05-04 09:05:25 -0600688 check_type(expr_info, "'base' for struct '%s'" % name, expr.get('base'),
Eric Blakedd883c62015-05-04 09:05:21 -0600689 allow_metas=['struct'])
Eric Blakeff55d722015-05-04 09:05:37 -0600690 if expr.get('base'):
691 check_member_clash(expr_info, expr['base'], expr['data'])
Eric Blakedd883c62015-05-04 09:05:21 -0600692
Eric Blake437db252015-09-29 16:21:02 -0600693
Eric Blake0545f6b2015-05-04 09:05:15 -0600694def check_keys(expr_elem, meta, required, optional=[]):
695 expr = expr_elem['expr']
696 info = expr_elem['info']
697 name = expr[meta]
698 if not isinstance(name, str):
699 raise QAPIExprError(info,
700 "'%s' key must have a string value" % meta)
Eric Blake437db252015-09-29 16:21:02 -0600701 required = required + [meta]
Eric Blake0545f6b2015-05-04 09:05:15 -0600702 for (key, value) in expr.items():
Eric Blake437db252015-09-29 16:21:02 -0600703 if key not in required and key not in optional:
Eric Blake0545f6b2015-05-04 09:05:15 -0600704 raise QAPIExprError(info,
705 "Unknown key '%s' in %s '%s'"
706 % (key, meta, name))
Eric Blake437db252015-09-29 16:21:02 -0600707 if (key == 'gen' or key == 'success-response') and value is not False:
Eric Blake2cbf0992015-05-04 09:05:24 -0600708 raise QAPIExprError(info,
709 "'%s' of %s '%s' should only use false value"
710 % (key, meta, name))
Eric Blake0545f6b2015-05-04 09:05:15 -0600711 for key in required:
Eric Blake437db252015-09-29 16:21:02 -0600712 if key not in expr:
Eric Blake0545f6b2015-05-04 09:05:15 -0600713 raise QAPIExprError(info,
714 "Key '%s' is missing from %s '%s'"
715 % (key, meta, name))
716
Eric Blake437db252015-09-29 16:21:02 -0600717
Markus Armbruster4d076d62015-06-10 08:55:21 +0200718def check_exprs(exprs):
719 global all_names
720
721 # Learn the types and check for valid expression keys
722 for builtin in builtin_types.keys():
723 all_names[builtin] = 'built-in'
724 for expr_elem in exprs:
725 expr = expr_elem['expr']
726 info = expr_elem['info']
Eric Blake437db252015-09-29 16:21:02 -0600727 if 'enum' in expr:
Daniel P. Berrange351d36e2015-08-26 14:21:20 +0100728 check_keys(expr_elem, 'enum', ['data'], ['prefix'])
Markus Armbruster4d076d62015-06-10 08:55:21 +0200729 add_enum(expr['enum'], info, expr['data'])
Eric Blake437db252015-09-29 16:21:02 -0600730 elif 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200731 check_keys(expr_elem, 'union', ['data'],
732 ['base', 'discriminator'])
733 add_union(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600734 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200735 check_keys(expr_elem, 'alternate', ['data'])
736 add_name(expr['alternate'], info, 'alternate')
Eric Blake437db252015-09-29 16:21:02 -0600737 elif 'struct' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200738 check_keys(expr_elem, 'struct', ['data'], ['base'])
739 add_struct(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600740 elif 'command' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200741 check_keys(expr_elem, 'command', [],
742 ['data', 'returns', 'gen', 'success-response'])
743 add_name(expr['command'], info, 'command')
Eric Blake437db252015-09-29 16:21:02 -0600744 elif 'event' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200745 check_keys(expr_elem, 'event', [], ['data'])
746 add_name(expr['event'], info, 'event')
747 else:
748 raise QAPIExprError(expr_elem['info'],
749 "Expression is missing metatype")
750
751 # Try again for hidden UnionKind enum
752 for expr_elem in exprs:
753 expr = expr_elem['expr']
Eric Blake437db252015-09-29 16:21:02 -0600754 if 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200755 if not discriminator_find_enum_define(expr):
756 add_enum('%sKind' % expr['union'], expr_elem['info'],
757 implicit=True)
Eric Blake437db252015-09-29 16:21:02 -0600758 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200759 add_enum('%sKind' % expr['alternate'], expr_elem['info'],
760 implicit=True)
761
762 # Validate that exprs make sense
763 for expr_elem in exprs:
764 expr = expr_elem['expr']
765 info = expr_elem['info']
766
Eric Blake437db252015-09-29 16:21:02 -0600767 if 'enum' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200768 check_enum(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600769 elif 'union' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200770 check_union(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600771 elif 'alternate' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200772 check_alternate(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600773 elif 'struct' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200774 check_struct(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600775 elif 'command' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200776 check_command(expr, info)
Eric Blake437db252015-09-29 16:21:02 -0600777 elif 'event' in expr:
Markus Armbruster4d076d62015-06-10 08:55:21 +0200778 check_event(expr, info)
779 else:
780 assert False, 'unexpected meta type'
781
Markus Armbrusterac882192015-09-16 13:06:05 +0200782 return exprs
Eric Blake0545f6b2015-05-04 09:05:15 -0600783
Markus Armbrusterac882192015-09-16 13:06:05 +0200784
785#
786# Schema compiler frontend
787#
788
789class QAPISchemaEntity(object):
790 def __init__(self, name, info):
791 assert isinstance(name, str)
792 self.name = name
793 self.info = info
794
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200795 def c_name(self):
796 return c_name(self.name)
797
Markus Armbrusterac882192015-09-16 13:06:05 +0200798 def check(self, schema):
799 pass
800
Eric Blake49823c42015-10-12 22:22:27 -0600801 def is_implicit(self):
802 return not self.info
803
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200804 def visit(self, visitor):
805 pass
806
807
808class QAPISchemaVisitor(object):
809 def visit_begin(self, schema):
810 pass
811
812 def visit_end(self):
813 pass
814
Eric Blake25a0d9c2015-10-12 22:22:21 -0600815 def visit_needed(self, entity):
816 # Default to visiting everything
817 return True
818
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200819 def visit_builtin_type(self, name, info, json_type):
820 pass
821
822 def visit_enum_type(self, name, info, values, prefix):
823 pass
824
825 def visit_array_type(self, name, info, element_type):
826 pass
827
828 def visit_object_type(self, name, info, base, members, variants):
829 pass
830
Markus Armbruster39a18152015-09-16 13:06:28 +0200831 def visit_object_type_flat(self, name, info, members, variants):
832 pass
833
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200834 def visit_alternate_type(self, name, info, variants):
835 pass
836
837 def visit_command(self, name, info, arg_type, ret_type,
838 gen, success_response):
839 pass
840
841 def visit_event(self, name, info, arg_type):
842 pass
843
Markus Armbrusterac882192015-09-16 13:06:05 +0200844
845class QAPISchemaType(QAPISchemaEntity):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200846 def c_type(self, is_param=False):
847 return c_name(self.name) + pointer_suffix
848
849 def c_null(self):
850 return 'NULL'
851
852 def json_type(self):
853 pass
854
855 def alternate_qtype(self):
856 json2qtype = {
857 'string': 'QTYPE_QSTRING',
858 'number': 'QTYPE_QFLOAT',
859 'int': 'QTYPE_QINT',
860 'boolean': 'QTYPE_QBOOL',
861 'object': 'QTYPE_QDICT'
862 }
863 return json2qtype.get(self.json_type())
Markus Armbrusterac882192015-09-16 13:06:05 +0200864
865
866class QAPISchemaBuiltinType(QAPISchemaType):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200867 def __init__(self, name, json_type, c_type, c_null):
Markus Armbrusterac882192015-09-16 13:06:05 +0200868 QAPISchemaType.__init__(self, name, None)
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200869 assert not c_type or isinstance(c_type, str)
870 assert json_type in ('string', 'number', 'int', 'boolean', 'null',
871 'value')
872 self._json_type_name = json_type
873 self._c_type_name = c_type
874 self._c_null_val = c_null
875
876 def c_name(self):
877 return self.name
878
879 def c_type(self, is_param=False):
880 if is_param and self.name == 'str':
881 return 'const ' + self._c_type_name
882 return self._c_type_name
883
884 def c_null(self):
885 return self._c_null_val
886
887 def json_type(self):
888 return self._json_type_name
Markus Armbrusterac882192015-09-16 13:06:05 +0200889
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200890 def visit(self, visitor):
891 visitor.visit_builtin_type(self.name, self.info, self.json_type())
892
Markus Armbrusterac882192015-09-16 13:06:05 +0200893
894class QAPISchemaEnumType(QAPISchemaType):
895 def __init__(self, name, info, values, prefix):
896 QAPISchemaType.__init__(self, name, info)
897 for v in values:
898 assert isinstance(v, str)
899 assert prefix is None or isinstance(prefix, str)
900 self.values = values
901 self.prefix = prefix
902
903 def check(self, schema):
904 assert len(set(self.values)) == len(self.values)
905
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200906 def c_type(self, is_param=False):
907 return c_name(self.name)
908
909 def c_null(self):
910 return c_enum_const(self.name, (self.values + ['MAX'])[0],
911 self.prefix)
912
913 def json_type(self):
914 return 'string'
915
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200916 def visit(self, visitor):
917 visitor.visit_enum_type(self.name, self.info,
918 self.values, self.prefix)
919
Markus Armbrusterac882192015-09-16 13:06:05 +0200920
921class QAPISchemaArrayType(QAPISchemaType):
922 def __init__(self, name, info, element_type):
923 QAPISchemaType.__init__(self, name, info)
924 assert isinstance(element_type, str)
925 self._element_type_name = element_type
926 self.element_type = None
927
928 def check(self, schema):
929 self.element_type = schema.lookup_type(self._element_type_name)
930 assert self.element_type
931
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200932 def json_type(self):
933 return 'array'
934
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200935 def visit(self, visitor):
936 visitor.visit_array_type(self.name, self.info, self.element_type)
937
Markus Armbrusterac882192015-09-16 13:06:05 +0200938
939class QAPISchemaObjectType(QAPISchemaType):
940 def __init__(self, name, info, base, local_members, variants):
941 QAPISchemaType.__init__(self, name, info)
942 assert base is None or isinstance(base, str)
943 for m in local_members:
944 assert isinstance(m, QAPISchemaObjectTypeMember)
945 assert (variants is None or
946 isinstance(variants, QAPISchemaObjectTypeVariants))
947 self._base_name = base
948 self.base = None
949 self.local_members = local_members
950 self.variants = variants
951 self.members = None
952
953 def check(self, schema):
954 assert self.members is not False # not running in cycles
955 if self.members:
956 return
957 self.members = False # mark as being checked
958 if self._base_name:
959 self.base = schema.lookup_type(self._base_name)
960 assert isinstance(self.base, QAPISchemaObjectType)
961 assert not self.base.variants # not implemented
962 self.base.check(schema)
963 members = list(self.base.members)
964 else:
965 members = []
966 seen = {}
967 for m in members:
Eric Blake7618b912015-10-12 22:22:22 -0600968 assert c_name(m.name) not in seen
Markus Armbrusterac882192015-09-16 13:06:05 +0200969 seen[m.name] = m
970 for m in self.local_members:
971 m.check(schema, members, seen)
972 if self.variants:
973 self.variants.check(schema, members, seen)
974 self.members = members
975
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200976 def c_name(self):
Eric Blake49823c42015-10-12 22:22:27 -0600977 assert not self.is_implicit()
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200978 return QAPISchemaType.c_name(self)
979
980 def c_type(self, is_param=False):
Eric Blake49823c42015-10-12 22:22:27 -0600981 assert not self.is_implicit()
Markus Armbrusterf51d8c32015-09-16 13:06:06 +0200982 return QAPISchemaType.c_type(self)
983
984 def json_type(self):
985 return 'object'
986
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200987 def visit(self, visitor):
988 visitor.visit_object_type(self.name, self.info,
989 self.base, self.local_members, self.variants)
Markus Armbruster39a18152015-09-16 13:06:28 +0200990 visitor.visit_object_type_flat(self.name, self.info,
991 self.members, self.variants)
Markus Armbruster3f7dc212015-09-16 13:06:07 +0200992
Markus Armbrusterac882192015-09-16 13:06:05 +0200993
994class QAPISchemaObjectTypeMember(object):
995 def __init__(self, name, typ, optional):
996 assert isinstance(name, str)
997 assert isinstance(typ, str)
998 assert isinstance(optional, bool)
999 self.name = name
1000 self._type_name = typ
1001 self.type = None
1002 self.optional = optional
1003
1004 def check(self, schema, all_members, seen):
1005 assert self.name not in seen
1006 self.type = schema.lookup_type(self._type_name)
1007 assert self.type
1008 all_members.append(self)
1009 seen[self.name] = self
1010
1011
1012class QAPISchemaObjectTypeVariants(object):
Eric Blake46292ba2015-10-12 22:22:29 -06001013 def __init__(self, tag_name, tag_member, variants):
1014 # Flat unions pass tag_name but not tag_member.
1015 # Simple unions and alternates pass tag_member but not tag_name.
1016 # After check(), tag_member is always set, and tag_name remains
1017 # a reliable witness of being used by a flat union.
1018 assert bool(tag_member) != bool(tag_name)
1019 assert (isinstance(tag_name, str) or
1020 isinstance(tag_member, QAPISchemaObjectTypeMember))
Markus Armbrusterac882192015-09-16 13:06:05 +02001021 for v in variants:
1022 assert isinstance(v, QAPISchemaObjectTypeVariant)
1023 self.tag_name = tag_name
Eric Blake46292ba2015-10-12 22:22:29 -06001024 self.tag_member = tag_member
Markus Armbrusterac882192015-09-16 13:06:05 +02001025 self.variants = variants
1026
1027 def check(self, schema, members, seen):
1028 if self.tag_name:
1029 self.tag_member = seen[self.tag_name]
1030 else:
1031 self.tag_member.check(schema, members, seen)
1032 assert isinstance(self.tag_member.type, QAPISchemaEnumType)
1033 for v in self.variants:
1034 vseen = dict(seen)
1035 v.check(schema, self.tag_member.type, vseen)
1036
Eric Blake437db252015-09-29 16:21:02 -06001037
Markus Armbrusterac882192015-09-16 13:06:05 +02001038class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
1039 def __init__(self, name, typ):
1040 QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
1041
1042 def check(self, schema, tag_type, seen):
1043 QAPISchemaObjectTypeMember.check(self, schema, [], seen)
1044 assert self.name in tag_type.values
1045
Markus Armbruster2b162cc2015-09-16 13:06:09 +02001046 # This function exists to support ugly simple union special cases
1047 # TODO get rid of them, and drop the function
1048 def simple_union_type(self):
Eric Blake49823c42015-10-12 22:22:27 -06001049 if (self.type.is_implicit() and
1050 isinstance(self.type, QAPISchemaObjectType)):
Markus Armbruster2b162cc2015-09-16 13:06:09 +02001051 assert len(self.type.members) == 1
1052 assert not self.type.variants
1053 return self.type.members[0].type
1054 return None
1055
Markus Armbrusterac882192015-09-16 13:06:05 +02001056
1057class QAPISchemaAlternateType(QAPISchemaType):
1058 def __init__(self, name, info, variants):
1059 QAPISchemaType.__init__(self, name, info)
1060 assert isinstance(variants, QAPISchemaObjectTypeVariants)
1061 assert not variants.tag_name
1062 self.variants = variants
1063
1064 def check(self, schema):
1065 self.variants.check(schema, [], {})
1066
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001067 def json_type(self):
1068 return 'value'
1069
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001070 def visit(self, visitor):
1071 visitor.visit_alternate_type(self.name, self.info, self.variants)
1072
Markus Armbrusterac882192015-09-16 13:06:05 +02001073
1074class QAPISchemaCommand(QAPISchemaEntity):
1075 def __init__(self, name, info, arg_type, ret_type, gen, success_response):
1076 QAPISchemaEntity.__init__(self, name, info)
1077 assert not arg_type or isinstance(arg_type, str)
1078 assert not ret_type or isinstance(ret_type, str)
1079 self._arg_type_name = arg_type
1080 self.arg_type = None
1081 self._ret_type_name = ret_type
1082 self.ret_type = None
1083 self.gen = gen
1084 self.success_response = success_response
1085
1086 def check(self, schema):
1087 if self._arg_type_name:
1088 self.arg_type = schema.lookup_type(self._arg_type_name)
1089 assert isinstance(self.arg_type, QAPISchemaObjectType)
1090 assert not self.arg_type.variants # not implemented
1091 if self._ret_type_name:
1092 self.ret_type = schema.lookup_type(self._ret_type_name)
1093 assert isinstance(self.ret_type, QAPISchemaType)
1094
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001095 def visit(self, visitor):
1096 visitor.visit_command(self.name, self.info,
1097 self.arg_type, self.ret_type,
1098 self.gen, self.success_response)
1099
Markus Armbrusterac882192015-09-16 13:06:05 +02001100
1101class QAPISchemaEvent(QAPISchemaEntity):
1102 def __init__(self, name, info, arg_type):
1103 QAPISchemaEntity.__init__(self, name, info)
1104 assert not arg_type or isinstance(arg_type, str)
1105 self._arg_type_name = arg_type
1106 self.arg_type = None
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
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001114 def visit(self, visitor):
1115 visitor.visit_event(self.name, self.info, self.arg_type)
1116
Markus Armbrusterac882192015-09-16 13:06:05 +02001117
1118class QAPISchema(object):
1119 def __init__(self, fname):
1120 try:
1121 self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs)
Eric Blake7618b912015-10-12 22:22:22 -06001122 self._entity_dict = {}
1123 self._def_predefineds()
1124 self._def_exprs()
1125 self.check()
Markus Armbrusterac882192015-09-16 13:06:05 +02001126 except (QAPISchemaError, QAPIExprError), err:
1127 print >>sys.stderr, err
1128 exit(1)
Markus Armbrusterac882192015-09-16 13:06:05 +02001129
Markus Armbrusterac882192015-09-16 13:06:05 +02001130 def _def_entity(self, ent):
1131 assert ent.name not in self._entity_dict
1132 self._entity_dict[ent.name] = ent
1133
1134 def lookup_entity(self, name, typ=None):
1135 ent = self._entity_dict.get(name)
1136 if typ and not isinstance(ent, typ):
1137 return None
1138 return ent
1139
1140 def lookup_type(self, name):
1141 return self.lookup_entity(name, QAPISchemaType)
1142
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001143 def _def_builtin_type(self, name, json_type, c_type, c_null):
1144 self._def_entity(QAPISchemaBuiltinType(name, json_type,
1145 c_type, c_null))
Eric Blake9f08c8e2015-10-12 22:22:28 -06001146 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1147 # qapi-types.h from a single .c, all arrays of builtins must be
1148 # declared in the first file whether or not they are used. Nicer
1149 # would be to use lazy instantiation, while figuring out how to
1150 # avoid compilation issues with multiple qapi-types.h.
1151 self._make_array_type(name)
Markus Armbrusterac882192015-09-16 13:06:05 +02001152
1153 def _def_predefineds(self):
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001154 for t in [('str', 'string', 'char' + pointer_suffix, 'NULL'),
1155 ('number', 'number', 'double', '0'),
1156 ('int', 'int', 'int64_t', '0'),
1157 ('int8', 'int', 'int8_t', '0'),
1158 ('int16', 'int', 'int16_t', '0'),
1159 ('int32', 'int', 'int32_t', '0'),
1160 ('int64', 'int', 'int64_t', '0'),
1161 ('uint8', 'int', 'uint8_t', '0'),
1162 ('uint16', 'int', 'uint16_t', '0'),
1163 ('uint32', 'int', 'uint32_t', '0'),
1164 ('uint64', 'int', 'uint64_t', '0'),
1165 ('size', 'int', 'uint64_t', '0'),
1166 ('bool', 'boolean', 'bool', 'false'),
Markus Armbruster28770e02015-09-16 13:06:24 +02001167 ('any', 'value', 'QObject' + pointer_suffix, 'NULL')]:
Markus Armbrusterf51d8c32015-09-16 13:06:06 +02001168 self._def_builtin_type(*t)
Markus Armbruster39a18152015-09-16 13:06:28 +02001169 self.the_empty_object_type = QAPISchemaObjectType(':empty', None, None,
1170 [], None)
1171 self._def_entity(self.the_empty_object_type)
Markus Armbrusterac882192015-09-16 13:06:05 +02001172
1173 def _make_implicit_enum_type(self, name, values):
Eric Blake49823c42015-10-12 22:22:27 -06001174 name = name + 'Kind' # Use namespace reserved by add_name()
Markus Armbrusterac882192015-09-16 13:06:05 +02001175 self._def_entity(QAPISchemaEnumType(name, None, values, None))
1176 return name
1177
1178 def _make_array_type(self, element_type):
Eric Blake49823c42015-10-12 22:22:27 -06001179 # TODO fooList namespace is not reserved; user can create collisions,
1180 # or abuse our type system with ['fooList'] for 2D array
Markus Armbrusterac882192015-09-16 13:06:05 +02001181 name = element_type + 'List'
1182 if not self.lookup_type(name):
1183 self._def_entity(QAPISchemaArrayType(name, None, element_type))
1184 return name
1185
1186 def _make_implicit_object_type(self, name, role, members):
1187 if not members:
1188 return None
1189 name = ':obj-%s-%s' % (name, role)
1190 if not self.lookup_entity(name, QAPISchemaObjectType):
1191 self._def_entity(QAPISchemaObjectType(name, None, None,
1192 members, None))
1193 return name
1194
1195 def _def_enum_type(self, expr, info):
1196 name = expr['enum']
1197 data = expr['data']
1198 prefix = expr.get('prefix')
1199 self._def_entity(QAPISchemaEnumType(name, info, data, prefix))
Markus Armbrusterac882192015-09-16 13:06:05 +02001200
1201 def _make_member(self, name, typ):
1202 optional = False
1203 if name.startswith('*'):
1204 name = name[1:]
1205 optional = True
1206 if isinstance(typ, list):
1207 assert len(typ) == 1
1208 typ = self._make_array_type(typ[0])
1209 return QAPISchemaObjectTypeMember(name, typ, optional)
1210
1211 def _make_members(self, data):
1212 return [self._make_member(key, value)
1213 for (key, value) in data.iteritems()]
1214
1215 def _def_struct_type(self, expr, info):
1216 name = expr['struct']
1217 base = expr.get('base')
1218 data = expr['data']
1219 self._def_entity(QAPISchemaObjectType(name, info, base,
1220 self._make_members(data),
1221 None))
Markus Armbrusterac882192015-09-16 13:06:05 +02001222
1223 def _make_variant(self, case, typ):
1224 return QAPISchemaObjectTypeVariant(case, typ)
1225
1226 def _make_simple_variant(self, case, typ):
1227 if isinstance(typ, list):
1228 assert len(typ) == 1
1229 typ = self._make_array_type(typ[0])
1230 typ = self._make_implicit_object_type(typ, 'wrapper',
1231 [self._make_member('data', typ)])
1232 return QAPISchemaObjectTypeVariant(case, typ)
1233
Eric Blake46292ba2015-10-12 22:22:29 -06001234 def _make_implicit_tag(self, type_name, variants):
1235 typ = self._make_implicit_enum_type(type_name,
1236 [v.name for v in variants])
1237 return QAPISchemaObjectTypeMember('type', typ, False)
Markus Armbrusterac882192015-09-16 13:06:05 +02001238
1239 def _def_union_type(self, expr, info):
1240 name = expr['union']
1241 data = expr['data']
1242 base = expr.get('base')
1243 tag_name = expr.get('discriminator')
Eric Blake46292ba2015-10-12 22:22:29 -06001244 tag_member = None
Markus Armbrusterac882192015-09-16 13:06:05 +02001245 if tag_name:
1246 variants = [self._make_variant(key, value)
1247 for (key, value) in data.iteritems()]
1248 else:
1249 variants = [self._make_simple_variant(key, value)
1250 for (key, value) in data.iteritems()]
Eric Blake46292ba2015-10-12 22:22:29 -06001251 tag_member = self._make_implicit_tag(name, variants)
Markus Armbrusterac882192015-09-16 13:06:05 +02001252 self._def_entity(
1253 QAPISchemaObjectType(name, info, base,
1254 self._make_members(OrderedDict()),
1255 QAPISchemaObjectTypeVariants(tag_name,
Eric Blake46292ba2015-10-12 22:22:29 -06001256 tag_member,
Markus Armbrusterac882192015-09-16 13:06:05 +02001257 variants)))
Markus Armbrusterac882192015-09-16 13:06:05 +02001258
1259 def _def_alternate_type(self, expr, info):
1260 name = expr['alternate']
1261 data = expr['data']
1262 variants = [self._make_variant(key, value)
1263 for (key, value) in data.iteritems()]
Eric Blake46292ba2015-10-12 22:22:29 -06001264 tag_member = self._make_implicit_tag(name, variants)
Markus Armbrusterac882192015-09-16 13:06:05 +02001265 self._def_entity(
1266 QAPISchemaAlternateType(name, info,
1267 QAPISchemaObjectTypeVariants(None,
Eric Blake46292ba2015-10-12 22:22:29 -06001268 tag_member,
Markus Armbrusterac882192015-09-16 13:06:05 +02001269 variants)))
Markus Armbrusterac882192015-09-16 13:06:05 +02001270
1271 def _def_command(self, expr, info):
1272 name = expr['command']
1273 data = expr.get('data')
1274 rets = expr.get('returns')
1275 gen = expr.get('gen', True)
1276 success_response = expr.get('success-response', True)
1277 if isinstance(data, OrderedDict):
1278 data = self._make_implicit_object_type(name, 'arg',
1279 self._make_members(data))
1280 if isinstance(rets, list):
1281 assert len(rets) == 1
1282 rets = self._make_array_type(rets[0])
1283 self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
1284 success_response))
1285
1286 def _def_event(self, expr, info):
1287 name = expr['event']
1288 data = expr.get('data')
1289 if isinstance(data, OrderedDict):
1290 data = self._make_implicit_object_type(name, 'arg',
1291 self._make_members(data))
1292 self._def_entity(QAPISchemaEvent(name, info, data))
1293
1294 def _def_exprs(self):
1295 for expr_elem in self.exprs:
1296 expr = expr_elem['expr']
1297 info = expr_elem['info']
1298 if 'enum' in expr:
1299 self._def_enum_type(expr, info)
1300 elif 'struct' in expr:
1301 self._def_struct_type(expr, info)
1302 elif 'union' in expr:
1303 self._def_union_type(expr, info)
1304 elif 'alternate' in expr:
1305 self._def_alternate_type(expr, info)
1306 elif 'command' in expr:
1307 self._def_command(expr, info)
1308 elif 'event' in expr:
1309 self._def_event(expr, info)
1310 else:
1311 assert False
1312
1313 def check(self):
1314 for ent in self._entity_dict.values():
1315 ent.check(self)
1316
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001317 def visit(self, visitor):
Eric Blake25a0d9c2015-10-12 22:22:21 -06001318 visitor.visit_begin(self)
1319 for (name, entity) in sorted(self._entity_dict.items()):
1320 if visitor.visit_needed(entity):
1321 entity.visit(visitor)
Markus Armbruster3f7dc212015-09-16 13:06:07 +02001322 visitor.visit_end()
1323
Markus Armbruster2caba362013-07-27 17:41:56 +02001324
Markus Armbruster00e4b282015-06-10 10:04:36 +02001325#
1326# Code generation helpers
1327#
1328
Michael Roth0f923be2011-07-19 14:50:39 -05001329def camel_case(name):
1330 new_name = ''
1331 first = True
1332 for ch in name:
1333 if ch in ['_', '-']:
1334 first = True
1335 elif first:
1336 new_name += ch.upper()
1337 first = False
1338 else:
1339 new_name += ch.lower()
1340 return new_name
1341
Eric Blake437db252015-09-29 16:21:02 -06001342
Markus Armbruster849bc532015-05-14 06:50:53 -06001343# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1344# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1345# ENUM24_Name -> ENUM24_NAME
1346def camel_to_upper(value):
1347 c_fun_str = c_name(value, False)
1348 if value.isupper():
1349 return c_fun_str
1350
1351 new_name = ''
1352 l = len(c_fun_str)
1353 for i in range(l):
1354 c = c_fun_str[i]
1355 # When c is upper and no "_" appears before, do more checks
1356 if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
Eric Blake437db252015-09-29 16:21:02 -06001357 if i < l - 1 and c_fun_str[i + 1].islower():
1358 new_name += '_'
1359 elif c_fun_str[i - 1].isdigit():
Markus Armbruster849bc532015-05-14 06:50:53 -06001360 new_name += '_'
1361 new_name += c
1362 return new_name.lstrip('_').upper()
1363
Eric Blake437db252015-09-29 16:21:02 -06001364
Daniel P. Berrange351d36e2015-08-26 14:21:20 +01001365def c_enum_const(type_name, const_name, prefix=None):
1366 if prefix is not None:
1367 type_name = prefix
Markus Armbruster849bc532015-05-14 06:50:53 -06001368 return camel_to_upper(type_name + '_' + const_name)
1369
Eric Blake18df5152015-05-14 06:50:48 -06001370c_name_trans = string.maketrans('.-', '__')
Markus Armbruster47299262015-05-14 06:50:47 -06001371
Eric Blake437db252015-09-29 16:21:02 -06001372
Eric Blakec6405b52015-05-14 06:50:55 -06001373# Map @name to a valid C identifier.
1374# If @protect, avoid returning certain ticklish identifiers (like
1375# C keywords) by prepending "q_".
1376#
1377# Used for converting 'name' from a 'name':'type' qapi definition
1378# into a generated struct member, as well as converting type names
1379# into substrings of a generated C function name.
1380# '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1381# protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
Eric Blake18df5152015-05-14 06:50:48 -06001382def c_name(name, protect=True):
Blue Swirl427a1a22012-07-30 15:46:55 +00001383 # ANSI X3J11/88-090, 3.1.1
1384 c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
Eric Blake437db252015-09-29 16:21:02 -06001385 'default', 'do', 'double', 'else', 'enum', 'extern',
1386 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1387 'return', 'short', 'signed', 'sizeof', 'static',
1388 'struct', 'switch', 'typedef', 'union', 'unsigned',
1389 'void', 'volatile', 'while'])
Blue Swirl427a1a22012-07-30 15:46:55 +00001390 # ISO/IEC 9899:1999, 6.4.1
1391 c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1392 # ISO/IEC 9899:2011, 6.4.1
Eric Blake437db252015-09-29 16:21:02 -06001393 c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1394 '_Noreturn', '_Static_assert', '_Thread_local'])
Blue Swirl427a1a22012-07-30 15:46:55 +00001395 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1396 # excluding _.*
1397 gcc_words = set(['asm', 'typeof'])
Tomoki Sekiyama6f880092013-08-07 11:39:43 -04001398 # C++ ISO/IEC 14882:2003 2.11
1399 cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
1400 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1401 'namespace', 'new', 'operator', 'private', 'protected',
1402 'public', 'reinterpret_cast', 'static_cast', 'template',
1403 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1404 'using', 'virtual', 'wchar_t',
1405 # alternative representations
1406 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1407 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
Paolo Bonzini10577252012-09-19 16:31:07 +02001408 # namespace pollution:
Max Reitz8592a542013-12-20 19:28:18 +01001409 polluted_words = set(['unix', 'errno'])
Eric Blake437db252015-09-29 16:21:02 -06001410 if protect and (name in c89_words | c99_words | c11_words | gcc_words
1411 | cpp_words | polluted_words):
Blue Swirl427a1a22012-07-30 15:46:55 +00001412 return "q_" + name
Eric Blake18df5152015-05-14 06:50:48 -06001413 return name.translate(c_name_trans)
Michael Roth0f923be2011-07-19 14:50:39 -05001414
Amos Kong05dfb262014-06-10 19:25:53 +08001415eatspace = '\033EATSPACE.'
Eric Blaked5573442015-05-14 06:50:54 -06001416pointer_suffix = ' *' + eatspace
Amos Kong05dfb262014-06-10 19:25:53 +08001417
Eric Blake437db252015-09-29 16:21:02 -06001418
Michael Roth0f923be2011-07-19 14:50:39 -05001419def genindent(count):
1420 ret = ""
Eric Blake437db252015-09-29 16:21:02 -06001421 for _ in range(count):
Michael Roth0f923be2011-07-19 14:50:39 -05001422 ret += " "
1423 return ret
1424
1425indent_level = 0
1426
Eric Blake437db252015-09-29 16:21:02 -06001427
Michael Roth0f923be2011-07-19 14:50:39 -05001428def push_indent(indent_amount=4):
1429 global indent_level
1430 indent_level += indent_amount
1431
Eric Blake437db252015-09-29 16:21:02 -06001432
Michael Roth0f923be2011-07-19 14:50:39 -05001433def pop_indent(indent_amount=4):
1434 global indent_level
1435 indent_level -= indent_amount
1436
Eric Blake437db252015-09-29 16:21:02 -06001437
Markus Armbruster77e703b2015-06-24 19:27:32 +02001438# Generate @code with @kwds interpolated.
1439# Obey indent_level, and strip eatspace.
Michael Roth0f923be2011-07-19 14:50:39 -05001440def cgen(code, **kwds):
Markus Armbruster77e703b2015-06-24 19:27:32 +02001441 raw = code % kwds
1442 if indent_level:
1443 indent = genindent(indent_level)
Markus Armbruster2752e5b2015-09-07 17:45:55 +02001444 # re.subn() lacks flags support before Python 2.7, use re.compile()
1445 raw = re.subn(re.compile("^.", re.MULTILINE),
1446 indent + r'\g<0>', raw)
Markus Armbruster77e703b2015-06-24 19:27:32 +02001447 raw = raw[0]
1448 return re.sub(re.escape(eatspace) + ' *', '', raw)
Michael Roth0f923be2011-07-19 14:50:39 -05001449
Eric Blake437db252015-09-29 16:21:02 -06001450
Michael Roth0f923be2011-07-19 14:50:39 -05001451def mcgen(code, **kwds):
Markus Armbruster77e703b2015-06-24 19:27:32 +02001452 if code[0] == '\n':
1453 code = code[1:]
1454 return cgen(code, **kwds)
Michael Roth0f923be2011-07-19 14:50:39 -05001455
Michael Roth0f923be2011-07-19 14:50:39 -05001456
1457def guardname(filename):
Markus Armbruster00dfc3b2015-06-27 07:27:21 +02001458 return c_name(filename, protect=False).upper()
Michael Rothc0afa9c2013-05-10 17:46:00 -05001459
Eric Blake437db252015-09-29 16:21:02 -06001460
Michael Rothc0afa9c2013-05-10 17:46:00 -05001461def guardstart(name):
1462 return mcgen('''
1463
1464#ifndef %(name)s
1465#define %(name)s
1466
1467''',
1468 name=guardname(name))
1469
Eric Blake437db252015-09-29 16:21:02 -06001470
Michael Rothc0afa9c2013-05-10 17:46:00 -05001471def guardend(name):
1472 return mcgen('''
1473
1474#endif /* %(name)s */
1475
1476''',
1477 name=guardname(name))
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001478
Eric Blake437db252015-09-29 16:21:02 -06001479
Markus Armbrustere98859a2015-09-16 13:06:16 +02001480def gen_enum_lookup(name, values, prefix=None):
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001481 ret = mcgen('''
1482
Markus Armbrustere98859a2015-09-16 13:06:16 +02001483const char *const %(c_name)s_lookup[] = {
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001484''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001485 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001486 for value in values:
1487 index = c_enum_const(name, value, prefix)
1488 ret += mcgen('''
1489 [%(index)s] = "%(value)s",
1490''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001491 index=index, value=value)
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001492
1493 max_index = c_enum_const(name, 'MAX', prefix)
1494 ret += mcgen('''
1495 [%(max_index)s] = NULL,
1496};
1497''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001498 max_index=max_index)
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001499 return ret
1500
Eric Blake437db252015-09-29 16:21:02 -06001501
Markus Armbrustere98859a2015-09-16 13:06:16 +02001502def gen_enum(name, values, prefix=None):
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001503 # append automatically generated _MAX value
Markus Armbrustere98859a2015-09-16 13:06:16 +02001504 enum_values = values + ['MAX']
1505
1506 ret = mcgen('''
1507
1508typedef enum %(c_name)s {
1509''',
1510 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001511
1512 i = 0
1513 for value in enum_values:
Markus Armbrustere98859a2015-09-16 13:06:16 +02001514 ret += mcgen('''
1515 %(c_enum)s = %(i)d,
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001516''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001517 c_enum=c_enum_const(name, value, prefix),
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001518 i=i)
1519 i += 1
1520
Markus Armbrustere98859a2015-09-16 13:06:16 +02001521 ret += mcgen('''
1522} %(c_name)s;
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001523''',
Markus Armbrustere98859a2015-09-16 13:06:16 +02001524 c_name=c_name(name))
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001525
Markus Armbrustere98859a2015-09-16 13:06:16 +02001526 ret += mcgen('''
1527
1528extern const char *const %(c_name)s_lookup[];
1529''',
1530 c_name=c_name(name))
1531 return ret
Markus Armbrusterefd2eaa2015-09-16 13:06:12 +02001532
Eric Blake437db252015-09-29 16:21:02 -06001533
Markus Armbruster03b43672015-09-16 13:06:20 +02001534def gen_params(arg_type, extra):
1535 if not arg_type:
1536 return extra
1537 assert not arg_type.variants
1538 ret = ''
1539 sep = ''
1540 for memb in arg_type.members:
1541 ret += sep
1542 sep = ', '
1543 if memb.optional:
1544 ret += 'bool has_%s, ' % c_name(memb.name)
1545 ret += '%s %s' % (memb.type.c_type(is_param=True), c_name(memb.name))
1546 if extra:
1547 ret += sep + extra
1548 return ret
1549
Eric Blake1f353342015-09-29 16:21:13 -06001550
Eric Blake18bdbc32015-09-29 16:21:15 -06001551def gen_err_check(label='out', skiperr=False):
1552 if skiperr:
Eric Blake1f353342015-09-29 16:21:13 -06001553 return ''
1554 return mcgen('''
Eric Blake18bdbc32015-09-29 16:21:15 -06001555 if (err) {
Eric Blake1f353342015-09-29 16:21:13 -06001556 goto %(label)s;
1557 }
1558''',
Eric Blake18bdbc32015-09-29 16:21:15 -06001559 label=label)
Eric Blake1f353342015-09-29 16:21:13 -06001560
1561
Eric Blake18bdbc32015-09-29 16:21:15 -06001562def gen_visit_fields(members, prefix='', need_cast=False, skiperr=False):
Eric Blake82ca8e42015-09-29 16:21:14 -06001563 ret = ''
Eric Blake18bdbc32015-09-29 16:21:15 -06001564 if skiperr:
Eric Blake82ca8e42015-09-29 16:21:14 -06001565 errparg = 'NULL'
Eric Blake18bdbc32015-09-29 16:21:15 -06001566 else:
1567 errparg = '&err'
Eric Blake82ca8e42015-09-29 16:21:14 -06001568
1569 for memb in members:
1570 if memb.optional:
1571 ret += mcgen('''
1572 visit_optional(v, &%(prefix)shas_%(c_name)s, "%(name)s", %(errp)s);
1573''',
1574 prefix=prefix, c_name=c_name(memb.name),
1575 name=memb.name, errp=errparg)
Eric Blake18bdbc32015-09-29 16:21:15 -06001576 ret += gen_err_check(skiperr=skiperr)
Eric Blake82ca8e42015-09-29 16:21:14 -06001577 ret += mcgen('''
1578 if (%(prefix)shas_%(c_name)s) {
1579''',
1580 prefix=prefix, c_name=c_name(memb.name))
1581 push_indent()
1582
1583 # Ugly: sometimes we need to cast away const
1584 if need_cast and memb.type.name == 'str':
1585 cast = '(char **)'
1586 else:
1587 cast = ''
1588
1589 ret += mcgen('''
1590 visit_type_%(c_type)s(v, %(cast)s&%(prefix)s%(c_name)s, "%(name)s", %(errp)s);
1591''',
1592 c_type=memb.type.c_name(), prefix=prefix, cast=cast,
1593 c_name=c_name(memb.name), name=memb.name,
1594 errp=errparg)
Eric Blake18bdbc32015-09-29 16:21:15 -06001595 ret += gen_err_check(skiperr=skiperr)
Eric Blake82ca8e42015-09-29 16:21:14 -06001596
1597 if memb.optional:
1598 pop_indent()
1599 ret += mcgen('''
1600 }
1601''')
1602 return ret
1603
1604
Markus Armbruster00e4b282015-06-10 10:04:36 +02001605#
1606# Common command line parsing
1607#
1608
Eric Blake437db252015-09-29 16:21:02 -06001609
1610def parse_command_line(extra_options="", extra_long_options=[]):
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001611
1612 try:
1613 opts, args = getopt.gnu_getopt(sys.argv[1:],
Markus Armbruster16d80f62015-04-02 13:32:16 +02001614 "chp:o:" + extra_options,
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001615 ["source", "header", "prefix=",
Markus Armbruster16d80f62015-04-02 13:32:16 +02001616 "output-dir="] + extra_long_options)
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001617 except getopt.GetoptError, err:
Markus Armbrusterb4540962015-04-02 13:17:34 +02001618 print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err))
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001619 sys.exit(1)
1620
1621 output_dir = ""
1622 prefix = ""
1623 do_c = False
1624 do_h = False
1625 extra_opts = []
1626
1627 for oa in opts:
1628 o, a = oa
1629 if o in ("-p", "--prefix"):
Markus Armbruster1cf47a12015-07-01 13:13:54 +02001630 match = re.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
1631 if match.end() != len(a):
1632 print >>sys.stderr, \
1633 "%s: 'funny character '%s' in argument of --prefix" \
1634 % (sys.argv[0], a[match.end()])
1635 sys.exit(1)
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001636 prefix = a
Markus Armbruster2114f5a2015-04-02 13:12:21 +02001637 elif o in ("-o", "--output-dir"):
1638 output_dir = a + "/"
1639 elif o in ("-c", "--source"):
1640 do_c = True
1641 elif o in ("-h", "--header"):
1642 do_h = True
1643 else:
1644 extra_opts.append(oa)
1645
1646 if not do_c and not do_h:
1647 do_c = True
1648 do_h = True
1649
Markus Armbruster16d80f62015-04-02 13:32:16 +02001650 if len(args) != 1:
1651 print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
Markus Armbrusterb4540962015-04-02 13:17:34 +02001652 sys.exit(1)
Markus Armbruster54414042015-06-09 16:22:45 +02001653 fname = args[0]
Markus Armbrusterb4540962015-04-02 13:17:34 +02001654
Markus Armbruster54414042015-06-09 16:22:45 +02001655 return (fname, output_dir, do_c, do_h, prefix, extra_opts)
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001656
Markus Armbruster00e4b282015-06-10 10:04:36 +02001657#
1658# Generate output files with boilerplate
1659#
1660
Eric Blake437db252015-09-29 16:21:02 -06001661
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001662def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
1663 c_comment, h_comment):
Markus Armbruster00dfc3b2015-06-27 07:27:21 +02001664 guard = guardname(prefix + h_file)
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001665 c_file = output_dir + prefix + c_file
1666 h_file = output_dir + prefix + h_file
1667
Markus Armbrusterc4f498f2015-09-03 10:24:25 +02001668 if output_dir:
1669 try:
1670 os.makedirs(output_dir)
1671 except os.error, e:
1672 if e.errno != errno.EEXIST:
1673 raise
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001674
1675 def maybe_open(really, name, opt):
1676 if really:
1677 return open(name, opt)
1678 else:
1679 import StringIO
1680 return StringIO.StringIO()
1681
1682 fdef = maybe_open(do_c, c_file, 'w')
1683 fdecl = maybe_open(do_h, h_file, 'w')
1684
1685 fdef.write(mcgen('''
1686/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1687%(comment)s
1688''',
Eric Blake437db252015-09-29 16:21:02 -06001689 comment=c_comment))
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001690
1691 fdecl.write(mcgen('''
1692/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1693%(comment)s
1694#ifndef %(guard)s
1695#define %(guard)s
1696
1697''',
Eric Blake437db252015-09-29 16:21:02 -06001698 comment=h_comment, guard=guard))
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001699
1700 return (fdef, fdecl)
1701
Eric Blake437db252015-09-29 16:21:02 -06001702
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001703def close_output(fdef, fdecl):
1704 fdecl.write('''
1705#endif
1706''')
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001707 fdecl.close()
Markus Armbruster12f8e1b2015-04-02 14:46:39 +02001708 fdef.close()