4 # Copyright IBM, Corp. 2011
5 # Copyright (c) 2013-2015 Red Hat Inc.
11 # This work is licensed under the terms of the GNU GPL, version 2.
12 # See the COPYING file in the top-level directory.
15 from ordereddict import OrderedDict
23 'str': 'QTYPE_QSTRING',
25 'number': 'QTYPE_QFLOAT',
26 'bool': 'QTYPE_QBOOL',
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',
36 'any': None, # any qtype_code possible, actually
39 # Whitelist of commands allowed to return a non-dictionary
42 'human-monitor-command',
44 'query-migrate-cache-size',
51 'guest-fsfreeze-freeze',
52 'guest-fsfreeze-freeze-list',
53 'guest-fsfreeze-status',
54 'guest-fsfreeze-thaw',
58 'guest-sync-delimited',
68 # Parsing the schema into expressions
72 def error_path(parent):
75 res = ("In file included from %s:%d:\n" % (parent['file'],
76 parent['line'])) + res
77 parent = parent['parent']
81 class QAPISchemaError(Exception):
82 def __init__(self, schema, msg):
83 Exception.__init__(self)
84 self.fname = schema.fname
87 self.line = schema.line
88 for ch in schema.src[schema.line_pos:schema.pos]:
90 self.col = (self.col + 7) % 8 + 1
93 self.info = schema.incl_info
96 return error_path(self.info) + \
97 "%s:%d:%d: %s" % (self.fname, self.line, self.col, self.msg)
100 class QAPIExprError(Exception):
101 def __init__(self, expr_info, msg):
102 Exception.__init__(self)
104 self.info = expr_info
108 return error_path(self.info['parent']) + \
109 "%s:%d: %s" % (self.info['file'], self.info['line'], self.msg)
112 class QAPISchemaParser(object):
114 def __init__(self, fp, previously_included=[], incl_info=None):
115 abs_fname = os.path.abspath(fp.name)
118 previously_included.append(abs_fname)
119 self.incl_info = incl_info
121 if self.src == '' or self.src[-1] != '\n':
129 while self.tok is not None:
130 expr_info = {'file': fname, 'line': self.line,
131 'parent': self.incl_info}
132 expr = self.get_expr(False)
133 if isinstance(expr, dict) and "include" in expr:
135 raise QAPIExprError(expr_info,
136 "Invalid 'include' directive")
137 include = expr["include"]
138 if not isinstance(include, str):
139 raise QAPIExprError(expr_info,
140 "Value of 'include' must be a string")
141 incl_abs_fname = os.path.join(os.path.dirname(abs_fname),
143 # catch inclusion cycle
146 if incl_abs_fname == os.path.abspath(inf['file']):
147 raise QAPIExprError(expr_info, "Inclusion loop for %s"
150 # skip multiple include of the same file
151 if incl_abs_fname in previously_included:
154 fobj = open(incl_abs_fname, 'r')
156 raise QAPIExprError(expr_info,
157 '%s: %s' % (e.strerror, include))
158 exprs_include = QAPISchemaParser(fobj, previously_included,
160 self.exprs.extend(exprs_include.exprs)
162 expr_elem = {'expr': expr,
164 self.exprs.append(expr_elem)
168 self.tok = self.src[self.cursor]
169 self.pos = self.cursor
174 self.cursor = self.src.find('\n', self.cursor)
175 elif self.tok in "{}:,[]":
177 elif self.tok == "'":
181 ch = self.src[self.cursor]
184 raise QAPISchemaError(self,
185 'Missing terminating "\'"')
199 for _ in range(0, 4):
200 ch = self.src[self.cursor]
202 if ch not in "0123456789abcdefABCDEF":
203 raise QAPISchemaError(self,
204 '\\u escape needs 4 '
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')
220 raise QAPISchemaError(self,
221 "Unknown escape \\%s" % ch)
230 elif self.src.startswith("true", self.pos):
234 elif self.src.startswith("false", self.pos):
238 elif self.src.startswith("null", self.pos):
242 elif self.tok == '\n':
243 if self.cursor == len(self.src):
247 self.line_pos = self.cursor
248 elif not self.tok.isspace():
249 raise QAPISchemaError(self, 'Stray "%s"' % self.tok)
251 def get_members(self):
257 raise QAPISchemaError(self, 'Expected string or "}"')
262 raise QAPISchemaError(self, 'Expected ":"')
265 raise QAPISchemaError(self, 'Duplicate key "%s"' % key)
266 expr[key] = self.get_expr(True)
271 raise QAPISchemaError(self, 'Expected "," or "}"')
274 raise QAPISchemaError(self, 'Expected string')
276 def get_values(self):
281 if self.tok not in "{['tfn":
282 raise QAPISchemaError(self, 'Expected "{", "[", "]", string, '
285 expr.append(self.get_expr(True))
290 raise QAPISchemaError(self, 'Expected "," or "]"')
293 def get_expr(self, nested):
294 if self.tok != '{' and not nested:
295 raise QAPISchemaError(self, 'Expected "{"')
298 expr = self.get_members()
299 elif self.tok == '[':
301 expr = self.get_values()
302 elif self.tok in "'tfn":
306 raise QAPISchemaError(self, 'Expected "{", "[" or string')
310 # Semantic analysis of schema expressions
311 # TODO fold into QAPISchema
312 # TODO catching name collisions in generated code would be nice
316 def find_base_fields(base):
317 base_struct_define = find_struct(base)
318 if not base_struct_define:
320 return base_struct_define['data']
323 # Return the qtype of an alternate branch, or None on error.
324 def find_alternate_member_qtype(qapi_type):
325 if qapi_type in builtin_types:
326 return builtin_types[qapi_type]
327 elif find_struct(qapi_type):
329 elif find_enum(qapi_type):
330 return "QTYPE_QSTRING"
331 elif find_union(qapi_type):
336 # Return the discriminator enum define if discriminator is specified as an
337 # enum type, otherwise return None.
338 def discriminator_find_enum_define(expr):
339 base = expr.get('base')
340 discriminator = expr.get('discriminator')
342 if not (discriminator and base):
345 base_fields = find_base_fields(base)
349 discriminator_type = base_fields.get(discriminator)
350 if not discriminator_type:
353 return find_enum(discriminator_type)
356 # Names must be letters, numbers, -, and _. They must start with letter,
357 # except for downstream extensions which must start with __RFQDN_.
358 # Dots are only valid in the downstream extension prefix.
359 valid_name = re.compile('^(__[a-zA-Z0-9.-]+_)?'
360 '[a-zA-Z][a-zA-Z0-9_-]*$')
363 def check_name(expr_info, source, name, allow_optional=False,
368 if not isinstance(name, str):
369 raise QAPIExprError(expr_info,
370 "%s requires a string name" % source)
371 if name.startswith('*'):
372 membername = name[1:]
373 if not allow_optional:
374 raise QAPIExprError(expr_info,
375 "%s does not allow optional name '%s'"
377 # Enum members can start with a digit, because the generated C
378 # code always prefixes it with the enum name
379 if enum_member and membername[0].isdigit():
380 membername = 'D' + membername
381 # Reserve the entire 'q_' namespace for c_name()
382 if not valid_name.match(membername) or \
383 c_name(membername, False).startswith('q_'):
384 raise QAPIExprError(expr_info,
385 "%s uses invalid name '%s'" % (source, name))
388 def add_name(name, info, meta, implicit=False):
390 check_name(info, "'%s'" % meta, name)
391 # FIXME should reject names that differ only in '_' vs. '.'
392 # vs. '-', because they're liable to clash in generated C.
393 if name in all_names:
394 raise QAPIExprError(info,
395 "%s '%s' is already defined"
396 % (all_names[name], name))
397 if not implicit and (name.endswith('Kind') or name.endswith('List')):
398 raise QAPIExprError(info,
399 "%s '%s' should not end in '%s'"
400 % (meta, name, name[-4:]))
401 all_names[name] = meta
404 def add_struct(definition, info):
406 name = definition['struct']
407 add_name(name, info, 'struct')
408 struct_types.append(definition)
411 def find_struct(name):
413 for struct in struct_types:
414 if struct['struct'] == name:
419 def add_union(definition, info):
421 name = definition['union']
422 add_name(name, info, 'union')
423 union_types.append(definition)
426 def find_union(name):
428 for union in union_types:
429 if union['union'] == name:
434 def add_enum(name, info, enum_values=None, implicit=False):
436 add_name(name, info, 'enum', implicit)
437 enum_types.append({"enum_name": name, "enum_values": enum_values})
442 for enum in enum_types:
443 if enum['enum_name'] == name:
449 return find_enum(name) is not None
452 def check_type(expr_info, source, value, allow_array=False,
453 allow_dict=False, allow_optional=False,
460 # Check if array type for value is okay
461 if isinstance(value, list):
463 raise QAPIExprError(expr_info,
464 "%s cannot be an array" % source)
465 if len(value) != 1 or not isinstance(value[0], str):
466 raise QAPIExprError(expr_info,
467 "%s: array type must contain single type name"
471 # Check if type name for value is okay
472 if isinstance(value, str):
473 if value not in all_names:
474 raise QAPIExprError(expr_info,
475 "%s uses unknown type '%s'"
477 if not all_names[value] in allow_metas:
478 raise QAPIExprError(expr_info,
479 "%s cannot use %s type '%s'"
480 % (source, all_names[value], value))
484 raise QAPIExprError(expr_info,
485 "%s should be a type name" % source)
487 if not isinstance(value, OrderedDict):
488 raise QAPIExprError(expr_info,
489 "%s should be a dictionary or type name" % source)
491 # value is a dictionary, check that each member is okay
492 for (key, arg) in value.items():
493 check_name(expr_info, "Member of %s" % source, key,
494 allow_optional=allow_optional)
495 if c_name(key, False) == 'u' or c_name(key, False).startswith('has_'):
496 raise QAPIExprError(expr_info,
497 "Member of %s uses reserved name '%s'"
499 # Todo: allow dictionaries to represent default values of
500 # an optional argument.
501 check_type(expr_info, "Member '%s' of %s" % (key, source), arg,
503 allow_metas=['built-in', 'union', 'alternate', 'struct',
507 def check_member_clash(expr_info, base_name, data, source=""):
508 base = find_struct(base_name)
510 base_members = base['data']
511 for key in data.keys():
512 if key.startswith('*'):
514 if key in base_members or "*" + key in base_members:
515 raise QAPIExprError(expr_info,
516 "Member name '%s'%s clashes with base '%s'"
517 % (key, source, base_name))
519 check_member_clash(expr_info, base['base'], data, source)
522 def check_command(expr, expr_info):
523 name = expr['command']
525 check_type(expr_info, "'data' for command '%s'" % name,
526 expr.get('data'), allow_dict=True, allow_optional=True,
527 allow_metas=['struct'])
528 returns_meta = ['union', 'struct']
529 if name in returns_whitelist:
530 returns_meta += ['built-in', 'alternate', 'enum']
531 check_type(expr_info, "'returns' for command '%s'" % name,
532 expr.get('returns'), allow_array=True,
533 allow_optional=True, allow_metas=returns_meta)
536 def check_event(expr, expr_info):
541 check_type(expr_info, "'data' for event '%s'" % name,
542 expr.get('data'), allow_dict=True, allow_optional=True,
543 allow_metas=['struct'])
546 def check_union(expr, expr_info):
548 base = expr.get('base')
549 discriminator = expr.get('discriminator')
550 members = expr['data']
553 # Two types of unions, determined by discriminator.
555 # With no discriminator it is a simple union.
556 if discriminator is None:
558 allow_metas = ['built-in', 'union', 'alternate', 'struct', 'enum']
560 raise QAPIExprError(expr_info,
561 "Simple union '%s' must not have a base"
564 # Else, it's a flat union.
566 # The object must have a string member 'base'.
567 check_type(expr_info, "'base' for union '%s'" % name,
568 base, allow_metas=['struct'])
570 raise QAPIExprError(expr_info,
571 "Flat union '%s' must have a base"
573 base_fields = find_base_fields(base)
576 # The value of member 'discriminator' must name a non-optional
577 # member of the base struct.
578 check_name(expr_info, "Discriminator of flat union '%s'" % name,
580 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 "
585 % (discriminator, base))
586 enum_define = find_enum(discriminator_type)
587 allow_metas = ['struct']
588 # Do not allow string discriminator
590 raise QAPIExprError(expr_info,
591 "Discriminator '%s' must be of enumeration "
592 "type" % discriminator)
595 for (key, value) in members.items():
596 check_name(expr_info, "Member of union '%s'" % name, key)
598 # Each value must name a known type; furthermore, in flat unions,
599 # branches must be a struct with no overlapping member names
600 check_type(expr_info, "Member '%s' of union '%s'" % (key, name),
601 value, allow_array=not base, allow_metas=allow_metas)
603 branch_struct = find_struct(value)
605 check_member_clash(expr_info, base, branch_struct['data'],
606 " of branch '%s'" % key)
608 # If the discriminator names an enum type, then all members
609 # of 'data' must also be members of the enum type.
611 if key not in enum_define['enum_values']:
612 raise QAPIExprError(expr_info,
613 "Discriminator value '%s' is not found in "
615 (key, enum_define["enum_name"]))
617 # Otherwise, check for conflicts in the generated enum
619 c_key = camel_to_upper(key)
621 raise QAPIExprError(expr_info,
622 "Union '%s' member '%s' clashes with '%s'"
623 % (name, key, values[c_key]))
627 def check_alternate(expr, expr_info):
628 name = expr['alternate']
629 members = expr['data']
634 for (key, value) in members.items():
635 check_name(expr_info, "Member of alternate '%s'" % name, key)
637 # Check for conflicts in the generated enum
638 c_key = camel_to_upper(key)
640 raise QAPIExprError(expr_info,
641 "Alternate '%s' member '%s' clashes with '%s'"
642 % (name, key, values[c_key]))
645 # Ensure alternates have no type conflicts.
646 check_type(expr_info, "Member '%s' of alternate '%s'" % (key, name),
648 allow_metas=['built-in', 'union', 'struct', 'enum'])
649 qtype = find_alternate_member_qtype(value)
651 if qtype in types_seen:
652 raise QAPIExprError(expr_info,
653 "Alternate '%s' member '%s' can't "
654 "be distinguished from member '%s'"
655 % (name, key, types_seen[qtype]))
656 types_seen[qtype] = key
659 def check_enum(expr, expr_info):
661 members = expr.get('data')
662 prefix = expr.get('prefix')
665 if not isinstance(members, list):
666 raise QAPIExprError(expr_info,
667 "Enum '%s' requires an array for 'data'" % name)
668 if prefix is not None and not isinstance(prefix, str):
669 raise QAPIExprError(expr_info,
670 "Enum '%s' requires a string for 'prefix'" % name)
671 for member in members:
672 check_name(expr_info, "Member of enum '%s'" % name, member,
674 key = camel_to_upper(member)
676 raise QAPIExprError(expr_info,
677 "Enum '%s' member '%s' clashes with '%s'"
678 % (name, member, values[key]))
682 def check_struct(expr, expr_info):
683 name = expr['struct']
684 members = expr['data']
686 check_type(expr_info, "'data' for struct '%s'" % name, members,
687 allow_dict=True, allow_optional=True)
688 check_type(expr_info, "'base' for struct '%s'" % name, expr.get('base'),
689 allow_metas=['struct'])
691 check_member_clash(expr_info, expr['base'], expr['data'])
694 def check_keys(expr_elem, meta, required, optional=[]):
695 expr = expr_elem['expr']
696 info = expr_elem['info']
698 if not isinstance(name, str):
699 raise QAPIExprError(info,
700 "'%s' key must have a string value" % meta)
701 required = required + [meta]
702 for (key, value) in expr.items():
703 if key not in required and key not in optional:
704 raise QAPIExprError(info,
705 "Unknown key '%s' in %s '%s'"
707 if (key == 'gen' or key == 'success-response') and value is not False:
708 raise QAPIExprError(info,
709 "'%s' of %s '%s' should only use false value"
713 raise QAPIExprError(info,
714 "Key '%s' is missing from %s '%s'"
718 def check_exprs(exprs):
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']
728 check_keys(expr_elem, 'enum', ['data'], ['prefix'])
729 add_enum(expr['enum'], info, expr['data'])
730 elif 'union' in expr:
731 check_keys(expr_elem, 'union', ['data'],
732 ['base', 'discriminator'])
733 add_union(expr, info)
734 elif 'alternate' in expr:
735 check_keys(expr_elem, 'alternate', ['data'])
736 add_name(expr['alternate'], info, 'alternate')
737 elif 'struct' in expr:
738 check_keys(expr_elem, 'struct', ['data'], ['base'])
739 add_struct(expr, info)
740 elif 'command' in expr:
741 check_keys(expr_elem, 'command', [],
742 ['data', 'returns', 'gen', 'success-response'])
743 add_name(expr['command'], info, 'command')
744 elif 'event' in expr:
745 check_keys(expr_elem, 'event', [], ['data'])
746 add_name(expr['event'], info, 'event')
748 raise QAPIExprError(expr_elem['info'],
749 "Expression is missing metatype")
751 # Try again for hidden UnionKind enum
752 for expr_elem in exprs:
753 expr = expr_elem['expr']
755 if not discriminator_find_enum_define(expr):
756 add_enum('%sKind' % expr['union'], expr_elem['info'],
758 elif 'alternate' in expr:
759 add_enum('%sKind' % expr['alternate'], expr_elem['info'],
762 # Validate that exprs make sense
763 for expr_elem in exprs:
764 expr = expr_elem['expr']
765 info = expr_elem['info']
768 check_enum(expr, info)
769 elif 'union' in expr:
770 check_union(expr, info)
771 elif 'alternate' in expr:
772 check_alternate(expr, info)
773 elif 'struct' in expr:
774 check_struct(expr, info)
775 elif 'command' in expr:
776 check_command(expr, info)
777 elif 'event' in expr:
778 check_event(expr, info)
780 assert False, 'unexpected meta type'
786 # Schema compiler frontend
789 class QAPISchemaEntity(object):
790 def __init__(self, name, info):
791 assert isinstance(name, str)
793 # For explicitly defined entities, info points to the (explicit)
794 # definition. For builtins (and their arrays), info is None.
795 # For implicitly defined entities, info points to a place that
796 # triggered the implicit definition (there may be more than one
801 return c_name(self.name)
803 def check(self, schema):
806 def is_implicit(self):
809 def visit(self, visitor):
813 class QAPISchemaVisitor(object):
814 def visit_begin(self, schema):
820 def visit_needed(self, entity):
821 # Default to visiting everything
824 def visit_builtin_type(self, name, info, json_type):
827 def visit_enum_type(self, name, info, values, prefix):
830 def visit_array_type(self, name, info, element_type):
833 def visit_object_type(self, name, info, base, members, variants):
836 def visit_object_type_flat(self, name, info, members, variants):
839 def visit_alternate_type(self, name, info, variants):
842 def visit_command(self, name, info, arg_type, ret_type,
843 gen, success_response):
846 def visit_event(self, name, info, arg_type):
850 class QAPISchemaType(QAPISchemaEntity):
851 def c_type(self, is_param=False):
852 return c_name(self.name) + pointer_suffix
860 def alternate_qtype(self):
862 'string': 'QTYPE_QSTRING',
863 'number': 'QTYPE_QFLOAT',
865 'boolean': 'QTYPE_QBOOL',
866 'object': 'QTYPE_QDICT'
868 return json2qtype.get(self.json_type())
871 class QAPISchemaBuiltinType(QAPISchemaType):
872 def __init__(self, name, json_type, c_type, c_null):
873 QAPISchemaType.__init__(self, name, None)
874 assert not c_type or isinstance(c_type, str)
875 assert json_type in ('string', 'number', 'int', 'boolean', 'null',
877 self._json_type_name = json_type
878 self._c_type_name = c_type
879 self._c_null_val = c_null
884 def c_type(self, is_param=False):
885 if is_param and self.name == 'str':
886 return 'const ' + self._c_type_name
887 return self._c_type_name
890 return self._c_null_val
893 return self._json_type_name
895 def visit(self, visitor):
896 visitor.visit_builtin_type(self.name, self.info, self.json_type())
899 class QAPISchemaEnumType(QAPISchemaType):
900 def __init__(self, name, info, values, prefix):
901 QAPISchemaType.__init__(self, name, info)
903 assert isinstance(v, str)
904 assert prefix is None or isinstance(prefix, str)
908 def check(self, schema):
909 assert len(set(self.values)) == len(self.values)
911 def is_implicit(self):
912 # See QAPISchema._make_implicit_enum_type()
913 return self.name.endswith('Kind')
915 def c_type(self, is_param=False):
916 return c_name(self.name)
919 return c_enum_const(self.name, (self.values + ['_MAX'])[0],
925 def visit(self, visitor):
926 visitor.visit_enum_type(self.name, self.info,
927 self.values, self.prefix)
930 class QAPISchemaArrayType(QAPISchemaType):
931 def __init__(self, name, info, element_type):
932 QAPISchemaType.__init__(self, name, info)
933 assert isinstance(element_type, str)
934 self._element_type_name = element_type
935 self.element_type = None
937 def check(self, schema):
938 self.element_type = schema.lookup_type(self._element_type_name)
939 assert self.element_type
941 def is_implicit(self):
947 def visit(self, visitor):
948 visitor.visit_array_type(self.name, self.info, self.element_type)
951 class QAPISchemaObjectType(QAPISchemaType):
952 def __init__(self, name, info, base, local_members, variants):
953 # struct has local_members, optional base, and no variants
954 # flat union has base, variants, and no local_members
955 # simple union has local_members, variants, and no base
956 QAPISchemaType.__init__(self, name, info)
957 assert base is None or isinstance(base, str)
958 for m in local_members:
959 assert isinstance(m, QAPISchemaObjectTypeMember)
961 if variants is not None:
962 assert isinstance(variants, QAPISchemaObjectTypeVariants)
963 variants.set_owner(name)
964 self._base_name = base
966 self.local_members = local_members
967 self.variants = variants
970 def check(self, schema):
971 assert self.members is not False # not running in cycles
974 self.members = False # mark as being checked
977 self.base = schema.lookup_type(self._base_name)
978 assert isinstance(self.base, QAPISchemaObjectType)
979 self.base.check(schema)
980 self.base.check_clash(schema, self.info, seen)
981 for m in self.local_members:
983 m.check_clash(self.info, seen)
984 self.members = seen.values()
986 self.variants.check(schema, seen)
987 assert self.variants.tag_member in self.members
988 self.variants.check_clash(schema, self.info, seen)
990 # Check that the members of this type do not cause duplicate JSON fields,
991 # and update seen to track the members seen so far. Report any errors
992 # on behalf of info, which is not necessarily self.info
993 def check_clash(self, schema, info, seen):
994 assert not self.variants # not implemented
995 for m in self.members:
996 m.check_clash(info, seen)
998 def is_implicit(self):
999 # See QAPISchema._make_implicit_object_type()
1000 return self.name[0] == ':'
1003 assert not self.is_implicit()
1004 return QAPISchemaType.c_name(self)
1006 def c_type(self, is_param=False):
1007 assert not self.is_implicit()
1008 return QAPISchemaType.c_type(self)
1010 def json_type(self):
1013 def visit(self, visitor):
1014 visitor.visit_object_type(self.name, self.info,
1015 self.base, self.local_members, self.variants)
1016 visitor.visit_object_type_flat(self.name, self.info,
1017 self.members, self.variants)
1020 class QAPISchemaObjectTypeMember(object):
1023 def __init__(self, name, typ, optional):
1024 assert isinstance(name, str)
1025 assert isinstance(typ, str)
1026 assert isinstance(optional, bool)
1028 self._type_name = typ
1030 self.optional = optional
1033 def set_owner(self, name):
1034 assert not self.owner
1037 def check(self, schema):
1039 self.type = schema.lookup_type(self._type_name)
1042 def check_clash(self, info, seen):
1043 cname = c_name(self.name)
1045 raise QAPIExprError(info,
1046 "%s collides with %s"
1047 % (self.describe(), seen[cname].describe()))
1050 def _pretty_owner(self):
1052 if owner.startswith(':obj-'):
1053 # See QAPISchema._make_implicit_object_type() - reverse the
1054 # mapping there to create a nice human-readable description
1056 if owner.endswith('-arg'):
1057 return '(parameter of %s)' % owner[:-4]
1059 assert owner.endswith('-wrapper')
1060 # Unreachable and not implemented
1062 return '(%s of %s)' % (self.role, owner)
1065 return "'%s' %s" % (self.name, self._pretty_owner())
1068 class QAPISchemaObjectTypeVariants(object):
1069 def __init__(self, tag_name, tag_member, variants):
1070 # Flat unions pass tag_name but not tag_member.
1071 # Simple unions and alternates pass tag_member but not tag_name.
1072 # After check(), tag_member is always set, and tag_name remains
1073 # a reliable witness of being used by a flat union.
1074 assert bool(tag_member) != bool(tag_name)
1075 assert (isinstance(tag_name, str) or
1076 isinstance(tag_member, QAPISchemaObjectTypeMember))
1078 assert isinstance(v, QAPISchemaObjectTypeVariant)
1079 self.tag_name = tag_name
1080 self.tag_member = tag_member
1081 self.variants = variants
1083 def set_owner(self, name):
1084 for v in self.variants:
1087 def check(self, schema, seen):
1088 if not self.tag_member: # flat union
1089 self.tag_member = seen[c_name(self.tag_name)]
1090 assert self.tag_name == self.tag_member.name
1091 assert isinstance(self.tag_member.type, QAPISchemaEnumType)
1092 for v in self.variants:
1094 assert v.name in self.tag_member.type.values
1095 if isinstance(v.type, QAPISchemaObjectType):
1096 v.type.check(schema)
1098 def check_clash(self, schema, info, seen):
1099 for v in self.variants:
1100 # Reset seen map for each variant, since qapi names from one
1101 # branch do not affect another branch
1102 assert isinstance(v.type, QAPISchemaObjectType)
1103 v.type.check_clash(schema, info, dict(seen))
1106 class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
1109 def __init__(self, name, typ):
1110 QAPISchemaObjectTypeMember.__init__(self, name, typ, False)
1112 # This function exists to support ugly simple union special cases
1113 # TODO get rid of them, and drop the function
1114 def simple_union_type(self):
1115 if (self.type.is_implicit() and
1116 isinstance(self.type, QAPISchemaObjectType)):
1117 assert len(self.type.members) == 1
1118 assert not self.type.variants
1119 return self.type.members[0].type
1123 class QAPISchemaAlternateType(QAPISchemaType):
1124 def __init__(self, name, info, variants):
1125 QAPISchemaType.__init__(self, name, info)
1126 assert isinstance(variants, QAPISchemaObjectTypeVariants)
1127 assert not variants.tag_name
1128 variants.set_owner(name)
1129 variants.tag_member.set_owner(self.name)
1130 self.variants = variants
1132 def check(self, schema):
1133 self.variants.tag_member.check(schema)
1134 # Not calling self.variants.check_clash(), because there's nothing
1136 self.variants.check(schema, {})
1138 def json_type(self):
1141 def visit(self, visitor):
1142 visitor.visit_alternate_type(self.name, self.info, self.variants)
1145 class QAPISchemaCommand(QAPISchemaEntity):
1146 def __init__(self, name, info, arg_type, ret_type, gen, success_response):
1147 QAPISchemaEntity.__init__(self, name, info)
1148 assert not arg_type or isinstance(arg_type, str)
1149 assert not ret_type or isinstance(ret_type, str)
1150 self._arg_type_name = arg_type
1151 self.arg_type = None
1152 self._ret_type_name = ret_type
1153 self.ret_type = None
1155 self.success_response = success_response
1157 def check(self, schema):
1158 if self._arg_type_name:
1159 self.arg_type = schema.lookup_type(self._arg_type_name)
1160 assert isinstance(self.arg_type, QAPISchemaObjectType)
1161 assert not self.arg_type.variants # not implemented
1162 if self._ret_type_name:
1163 self.ret_type = schema.lookup_type(self._ret_type_name)
1164 assert isinstance(self.ret_type, QAPISchemaType)
1166 def visit(self, visitor):
1167 visitor.visit_command(self.name, self.info,
1168 self.arg_type, self.ret_type,
1169 self.gen, self.success_response)
1172 class QAPISchemaEvent(QAPISchemaEntity):
1173 def __init__(self, name, info, arg_type):
1174 QAPISchemaEntity.__init__(self, name, info)
1175 assert not arg_type or isinstance(arg_type, str)
1176 self._arg_type_name = arg_type
1177 self.arg_type = None
1179 def check(self, schema):
1180 if self._arg_type_name:
1181 self.arg_type = schema.lookup_type(self._arg_type_name)
1182 assert isinstance(self.arg_type, QAPISchemaObjectType)
1183 assert not self.arg_type.variants # not implemented
1185 def visit(self, visitor):
1186 visitor.visit_event(self.name, self.info, self.arg_type)
1189 class QAPISchema(object):
1190 def __init__(self, fname):
1192 self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs)
1193 self._entity_dict = {}
1194 self._predefining = True
1195 self._def_predefineds()
1196 self._predefining = False
1199 except (QAPISchemaError, QAPIExprError), err:
1200 print >>sys.stderr, err
1203 def _def_entity(self, ent):
1204 # Only the predefined types are allowed to not have info
1205 assert ent.info or self._predefining
1206 assert ent.name not in self._entity_dict
1207 self._entity_dict[ent.name] = ent
1209 def lookup_entity(self, name, typ=None):
1210 ent = self._entity_dict.get(name)
1211 if typ and not isinstance(ent, typ):
1215 def lookup_type(self, name):
1216 return self.lookup_entity(name, QAPISchemaType)
1218 def _def_builtin_type(self, name, json_type, c_type, c_null):
1219 self._def_entity(QAPISchemaBuiltinType(name, json_type,
1221 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1222 # qapi-types.h from a single .c, all arrays of builtins must be
1223 # declared in the first file whether or not they are used. Nicer
1224 # would be to use lazy instantiation, while figuring out how to
1225 # avoid compilation issues with multiple qapi-types.h.
1226 self._make_array_type(name, None)
1228 def _def_predefineds(self):
1229 for t in [('str', 'string', 'char' + pointer_suffix, 'NULL'),
1230 ('number', 'number', 'double', '0'),
1231 ('int', 'int', 'int64_t', '0'),
1232 ('int8', 'int', 'int8_t', '0'),
1233 ('int16', 'int', 'int16_t', '0'),
1234 ('int32', 'int', 'int32_t', '0'),
1235 ('int64', 'int', 'int64_t', '0'),
1236 ('uint8', 'int', 'uint8_t', '0'),
1237 ('uint16', 'int', 'uint16_t', '0'),
1238 ('uint32', 'int', 'uint32_t', '0'),
1239 ('uint64', 'int', 'uint64_t', '0'),
1240 ('size', 'int', 'uint64_t', '0'),
1241 ('bool', 'boolean', 'bool', 'false'),
1242 ('any', 'value', 'QObject' + pointer_suffix, 'NULL')]:
1243 self._def_builtin_type(*t)
1244 self.the_empty_object_type = QAPISchemaObjectType(':empty', None, None,
1246 self._def_entity(self.the_empty_object_type)
1248 def _make_implicit_enum_type(self, name, info, values):
1249 name = name + 'Kind' # Use namespace reserved by add_name()
1250 self._def_entity(QAPISchemaEnumType(name, info, values, None))
1253 def _make_array_type(self, element_type, info):
1254 name = element_type + 'List' # Use namespace reserved by add_name()
1255 if not self.lookup_type(name):
1256 self._def_entity(QAPISchemaArrayType(name, info, element_type))
1259 def _make_implicit_object_type(self, name, info, role, members):
1262 # See also QAPISchemaObjectTypeMember._pretty_owner()
1263 name = ':obj-%s-%s' % (name, role)
1264 if not self.lookup_entity(name, QAPISchemaObjectType):
1265 self._def_entity(QAPISchemaObjectType(name, info, None,
1269 def _def_enum_type(self, expr, info):
1272 prefix = expr.get('prefix')
1273 self._def_entity(QAPISchemaEnumType(name, info, data, prefix))
1275 def _make_member(self, name, typ, info):
1277 if name.startswith('*'):
1280 if isinstance(typ, list):
1281 assert len(typ) == 1
1282 typ = self._make_array_type(typ[0], info)
1283 return QAPISchemaObjectTypeMember(name, typ, optional)
1285 def _make_members(self, data, info):
1286 return [self._make_member(key, value, info)
1287 for (key, value) in data.iteritems()]
1289 def _def_struct_type(self, expr, info):
1290 name = expr['struct']
1291 base = expr.get('base')
1293 self._def_entity(QAPISchemaObjectType(name, info, base,
1294 self._make_members(data, info),
1297 def _make_variant(self, case, typ):
1298 return QAPISchemaObjectTypeVariant(case, typ)
1300 def _make_simple_variant(self, case, typ, info):
1301 if isinstance(typ, list):
1302 assert len(typ) == 1
1303 typ = self._make_array_type(typ[0], info)
1304 typ = self._make_implicit_object_type(
1305 typ, info, 'wrapper', [self._make_member('data', typ, info)])
1306 return QAPISchemaObjectTypeVariant(case, typ)
1308 def _make_implicit_tag(self, type_name, info, variants):
1309 typ = self._make_implicit_enum_type(type_name, info,
1310 [v.name for v in variants])
1311 return QAPISchemaObjectTypeMember('type', typ, False)
1313 def _def_union_type(self, expr, info):
1314 name = expr['union']
1316 base = expr.get('base')
1317 tag_name = expr.get('discriminator')
1320 variants = [self._make_variant(key, value)
1321 for (key, value) in data.iteritems()]
1324 variants = [self._make_simple_variant(key, value, info)
1325 for (key, value) in data.iteritems()]
1326 tag_member = self._make_implicit_tag(name, info, variants)
1327 members = [tag_member]
1329 QAPISchemaObjectType(name, info, base, members,
1330 QAPISchemaObjectTypeVariants(tag_name,
1334 def _def_alternate_type(self, expr, info):
1335 name = expr['alternate']
1337 variants = [self._make_variant(key, value)
1338 for (key, value) in data.iteritems()]
1339 tag_member = self._make_implicit_tag(name, info, variants)
1341 QAPISchemaAlternateType(name, info,
1342 QAPISchemaObjectTypeVariants(None,
1346 def _def_command(self, expr, info):
1347 name = expr['command']
1348 data = expr.get('data')
1349 rets = expr.get('returns')
1350 gen = expr.get('gen', True)
1351 success_response = expr.get('success-response', True)
1352 if isinstance(data, OrderedDict):
1353 data = self._make_implicit_object_type(
1354 name, info, 'arg', self._make_members(data, info))
1355 if isinstance(rets, list):
1356 assert len(rets) == 1
1357 rets = self._make_array_type(rets[0], info)
1358 self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
1361 def _def_event(self, expr, info):
1362 name = expr['event']
1363 data = expr.get('data')
1364 if isinstance(data, OrderedDict):
1365 data = self._make_implicit_object_type(
1366 name, info, 'arg', self._make_members(data, info))
1367 self._def_entity(QAPISchemaEvent(name, info, data))
1369 def _def_exprs(self):
1370 for expr_elem in self.exprs:
1371 expr = expr_elem['expr']
1372 info = expr_elem['info']
1374 self._def_enum_type(expr, info)
1375 elif 'struct' in expr:
1376 self._def_struct_type(expr, info)
1377 elif 'union' in expr:
1378 self._def_union_type(expr, info)
1379 elif 'alternate' in expr:
1380 self._def_alternate_type(expr, info)
1381 elif 'command' in expr:
1382 self._def_command(expr, info)
1383 elif 'event' in expr:
1384 self._def_event(expr, info)
1389 for ent in self._entity_dict.values():
1392 def visit(self, visitor):
1393 visitor.visit_begin(self)
1394 for (name, entity) in sorted(self._entity_dict.items()):
1395 if visitor.visit_needed(entity):
1396 entity.visit(visitor)
1401 # Code generation helpers
1404 def camel_case(name):
1408 if ch in ['_', '-']:
1411 new_name += ch.upper()
1414 new_name += ch.lower()
1418 # ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1419 # ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1420 # ENUM24_Name -> ENUM24_NAME
1421 def camel_to_upper(value):
1422 c_fun_str = c_name(value, False)
1430 # When c is upper and no "_" appears before, do more checks
1431 if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
1432 if i < l - 1 and c_fun_str[i + 1].islower():
1434 elif c_fun_str[i - 1].isdigit():
1437 return new_name.lstrip('_').upper()
1440 def c_enum_const(type_name, const_name, prefix=None):
1441 if prefix is not None:
1443 return camel_to_upper(type_name) + '_' + c_name(const_name, False).upper()
1445 c_name_trans = string.maketrans('.-', '__')
1448 # Map @name to a valid C identifier.
1449 # If @protect, avoid returning certain ticklish identifiers (like
1450 # C keywords) by prepending "q_".
1452 # Used for converting 'name' from a 'name':'type' qapi definition
1453 # into a generated struct member, as well as converting type names
1454 # into substrings of a generated C function name.
1455 # '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1456 # protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
1457 def c_name(name, protect=True):
1458 # ANSI X3J11/88-090, 3.1.1
1459 c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
1460 'default', 'do', 'double', 'else', 'enum', 'extern',
1461 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1462 'return', 'short', 'signed', 'sizeof', 'static',
1463 'struct', 'switch', 'typedef', 'union', 'unsigned',
1464 'void', 'volatile', 'while'])
1465 # ISO/IEC 9899:1999, 6.4.1
1466 c99_words = set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1467 # ISO/IEC 9899:2011, 6.4.1
1468 c11_words = set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1469 '_Noreturn', '_Static_assert', '_Thread_local'])
1470 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1472 gcc_words = set(['asm', 'typeof'])
1473 # C++ ISO/IEC 14882:2003 2.11
1474 cpp_words = set(['bool', 'catch', 'class', 'const_cast', 'delete',
1475 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1476 'namespace', 'new', 'operator', 'private', 'protected',
1477 'public', 'reinterpret_cast', 'static_cast', 'template',
1478 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1479 'using', 'virtual', 'wchar_t',
1480 # alternative representations
1481 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1482 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
1483 # namespace pollution:
1484 polluted_words = set(['unix', 'errno'])
1485 name = name.translate(c_name_trans)
1486 if protect and (name in c89_words | c99_words | c11_words | gcc_words
1487 | cpp_words | polluted_words):
1491 eatspace = '\033EATSPACE.'
1492 pointer_suffix = ' *' + eatspace
1495 def genindent(count):
1497 for _ in range(count):
1504 def push_indent(indent_amount=4):
1506 indent_level += indent_amount
1509 def pop_indent(indent_amount=4):
1511 indent_level -= indent_amount
1514 # Generate @code with @kwds interpolated.
1515 # Obey indent_level, and strip eatspace.
1516 def cgen(code, **kwds):
1519 indent = genindent(indent_level)
1520 # re.subn() lacks flags support before Python 2.7, use re.compile()
1521 raw = re.subn(re.compile("^.", re.MULTILINE),
1522 indent + r'\g<0>', raw)
1524 return re.sub(re.escape(eatspace) + ' *', '', raw)
1527 def mcgen(code, **kwds):
1530 return cgen(code, **kwds)
1533 def guardname(filename):
1534 return c_name(filename, protect=False).upper()
1537 def guardstart(name):
1544 name=guardname(name))
1550 #endif /* %(name)s */
1553 name=guardname(name))
1556 def gen_enum_lookup(name, values, prefix=None):
1559 const char *const %(c_name)s_lookup[] = {
1561 c_name=c_name(name))
1562 for value in values:
1563 index = c_enum_const(name, value, prefix)
1565 [%(index)s] = "%(value)s",
1567 index=index, value=value)
1569 max_index = c_enum_const(name, '_MAX', prefix)
1571 [%(max_index)s] = NULL,
1574 max_index=max_index)
1578 def gen_enum(name, values, prefix=None):
1579 # append automatically generated _MAX value
1580 enum_values = values + ['_MAX']
1584 typedef enum %(c_name)s {
1586 c_name=c_name(name))
1589 for value in enum_values:
1593 c_enum=c_enum_const(name, value, prefix),
1600 c_name=c_name(name))
1604 extern const char *const %(c_name)s_lookup[];
1606 c_name=c_name(name))
1610 def gen_params(arg_type, extra):
1613 assert not arg_type.variants
1616 for memb in arg_type.members:
1620 ret += 'bool has_%s, ' % c_name(memb.name)
1621 ret += '%s %s' % (memb.type.c_type(is_param=True), c_name(memb.name))
1627 def gen_err_check(label='out', skiperr=False):
1638 def gen_visit_fields(members, prefix='', need_cast=False, skiperr=False):
1645 for memb in members:
1648 visit_optional(v, &%(prefix)shas_%(c_name)s, "%(name)s", %(errp)s);
1650 prefix=prefix, c_name=c_name(memb.name),
1651 name=memb.name, errp=errparg)
1652 ret += gen_err_check(skiperr=skiperr)
1654 if (%(prefix)shas_%(c_name)s) {
1656 prefix=prefix, c_name=c_name(memb.name))
1659 # Ugly: sometimes we need to cast away const
1660 if need_cast and memb.type.name == 'str':
1666 visit_type_%(c_type)s(v, %(cast)s&%(prefix)s%(c_name)s, "%(name)s", %(errp)s);
1668 c_type=memb.type.c_name(), prefix=prefix, cast=cast,
1669 c_name=c_name(memb.name), name=memb.name,
1671 ret += gen_err_check(skiperr=skiperr)
1682 # Common command line parsing
1686 def parse_command_line(extra_options="", extra_long_options=[]):
1689 opts, args = getopt.gnu_getopt(sys.argv[1:],
1690 "chp:o:" + extra_options,
1691 ["source", "header", "prefix=",
1692 "output-dir="] + extra_long_options)
1693 except getopt.GetoptError, err:
1694 print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err))
1705 if o in ("-p", "--prefix"):
1706 match = re.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
1707 if match.end() != len(a):
1708 print >>sys.stderr, \
1709 "%s: 'funny character '%s' in argument of --prefix" \
1710 % (sys.argv[0], a[match.end()])
1713 elif o in ("-o", "--output-dir"):
1714 output_dir = a + "/"
1715 elif o in ("-c", "--source"):
1717 elif o in ("-h", "--header"):
1720 extra_opts.append(oa)
1722 if not do_c and not do_h:
1727 print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
1731 return (fname, output_dir, do_c, do_h, prefix, extra_opts)
1734 # Generate output files with boilerplate
1738 def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
1739 c_comment, h_comment):
1740 guard = guardname(prefix + h_file)
1741 c_file = output_dir + prefix + c_file
1742 h_file = output_dir + prefix + h_file
1746 os.makedirs(output_dir)
1748 if e.errno != errno.EEXIST:
1751 def maybe_open(really, name, opt):
1753 return open(name, opt)
1756 return StringIO.StringIO()
1758 fdef = maybe_open(do_c, c_file, 'w')
1759 fdecl = maybe_open(do_h, h_file, 'w')
1761 fdef.write(mcgen('''
1762 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1767 fdecl.write(mcgen('''
1768 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1774 comment=h_comment, guard=guard))
1776 return (fdef, fdecl)
1779 def close_output(fdef, fdecl):