4 # Copyright IBM, Corp. 2011
5 # Copyright (c) 2013-2016 Red Hat Inc.
8 # Anthony Liguori <aliguori@us.ibm.com>
9 # Markus Armbruster <armbru@redhat.com>
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 possible, actually
37 'QType': 'QTYPE_QSTRING',
40 # Whitelist of commands allowed to return a non-dictionary
43 'human-monitor-command',
45 'query-migrate-cache-size',
52 'guest-fsfreeze-freeze',
53 'guest-fsfreeze-freeze-list',
54 'guest-fsfreeze-status',
55 'guest-fsfreeze-thaw',
59 'guest-sync-delimited',
62 # Whitelist of entities allowed to violate case conventions
65 'ACPISlotType', # DIMM, visible through query-acpi-ospm-status
66 'CpuInfoBase', # CPU, visible through query-cpu
67 'CpuInfoMIPS', # PC, visible through query-cpu
68 'CpuInfoTricore', # PC, visible through query-cpu
69 'QapiErrorClass', # all members, visible through errors
70 'UuidInfo', # UUID, visible through query-uuid
71 'X86CPURegister32', # all members, visible indirectly through qom-get
81 # Parsing the schema into expressions
85 def error_path(parent
):
88 res
= ("In file included from %s:%d:\n" % (parent
['file'],
89 parent
['line'])) + res
90 parent
= parent
['parent']
94 class QAPISchemaError(Exception):
95 def __init__(self
, schema
, msg
):
96 Exception.__init
__(self
)
97 self
.fname
= schema
.fname
100 self
.line
= schema
.line
101 for ch
in schema
.src
[schema
.line_pos
:schema
.pos
]:
103 self
.col
= (self
.col
+ 7) % 8 + 1
106 self
.info
= schema
.incl_info
109 return error_path(self
.info
) + \
110 "%s:%d:%d: %s" % (self
.fname
, self
.line
, self
.col
, self
.msg
)
113 class QAPIExprError(Exception):
114 def __init__(self
, expr_info
, msg
):
115 Exception.__init
__(self
)
117 self
.info
= expr_info
121 return error_path(self
.info
['parent']) + \
122 "%s:%d: %s" % (self
.info
['file'], self
.info
['line'], self
.msg
)
125 class QAPISchemaParser(object):
127 def __init__(self
, fp
, previously_included
=[], incl_info
=None):
128 abs_fname
= os
.path
.abspath(fp
.name
)
131 previously_included
.append(abs_fname
)
132 self
.incl_info
= incl_info
134 if self
.src
== '' or self
.src
[-1] != '\n':
142 while self
.tok
is not None:
143 expr_info
= {'file': fname
, 'line': self
.line
,
144 'parent': self
.incl_info
}
145 expr
= self
.get_expr(False)
146 if isinstance(expr
, dict) and "include" in expr
:
148 raise QAPIExprError(expr_info
,
149 "Invalid 'include' directive")
150 include
= expr
["include"]
151 if not isinstance(include
, str):
152 raise QAPIExprError(expr_info
,
153 "Value of 'include' must be a string")
154 incl_abs_fname
= os
.path
.join(os
.path
.dirname(abs_fname
),
156 # catch inclusion cycle
159 if incl_abs_fname
== os
.path
.abspath(inf
['file']):
160 raise QAPIExprError(expr_info
, "Inclusion loop for %s"
163 # skip multiple include of the same file
164 if incl_abs_fname
in previously_included
:
167 fobj
= open(incl_abs_fname
, 'r')
169 raise QAPIExprError(expr_info
,
170 '%s: %s' % (e
.strerror
, include
))
171 exprs_include
= QAPISchemaParser(fobj
, previously_included
,
173 self
.exprs
.extend(exprs_include
.exprs
)
175 expr_elem
= {'expr': expr
,
177 self
.exprs
.append(expr_elem
)
181 self
.tok
= self
.src
[self
.cursor
]
182 self
.pos
= self
.cursor
187 self
.cursor
= self
.src
.find('\n', self
.cursor
)
188 elif self
.tok
in "{}:,[]":
190 elif self
.tok
== "'":
194 ch
= self
.src
[self
.cursor
]
197 raise QAPISchemaError(self
,
198 'Missing terminating "\'"')
212 for _
in range(0, 4):
213 ch
= self
.src
[self
.cursor
]
215 if ch
not in "0123456789abcdefABCDEF":
216 raise QAPISchemaError(self
,
217 '\\u escape needs 4 '
219 value
= (value
<< 4) + int(ch
, 16)
220 # If Python 2 and 3 didn't disagree so much on
221 # how to handle Unicode, then we could allow
222 # Unicode string defaults. But most of QAPI is
223 # ASCII-only, so we aren't losing much for now.
224 if not value
or value
> 0x7f:
225 raise QAPISchemaError(self
,
226 'For now, \\u escape '
227 'only supports non-zero '
228 'values up to \\u007f')
233 raise QAPISchemaError(self
,
234 "Unknown escape \\%s" % ch
)
243 elif self
.src
.startswith("true", self
.pos
):
247 elif self
.src
.startswith("false", self
.pos
):
251 elif self
.src
.startswith("null", self
.pos
):
255 elif self
.tok
== '\n':
256 if self
.cursor
== len(self
.src
):
260 self
.line_pos
= self
.cursor
261 elif not self
.tok
.isspace():
262 raise QAPISchemaError(self
, 'Stray "%s"' % self
.tok
)
264 def get_members(self
):
270 raise QAPISchemaError(self
, 'Expected string or "}"')
275 raise QAPISchemaError(self
, 'Expected ":"')
278 raise QAPISchemaError(self
, 'Duplicate key "%s"' % key
)
279 expr
[key
] = self
.get_expr(True)
284 raise QAPISchemaError(self
, 'Expected "," or "}"')
287 raise QAPISchemaError(self
, 'Expected string')
289 def get_values(self
):
294 if self
.tok
not in "{['tfn":
295 raise QAPISchemaError(self
, 'Expected "{", "[", "]", string, '
298 expr
.append(self
.get_expr(True))
303 raise QAPISchemaError(self
, 'Expected "," or "]"')
306 def get_expr(self
, nested
):
307 if self
.tok
!= '{' and not nested
:
308 raise QAPISchemaError(self
, 'Expected "{"')
311 expr
= self
.get_members()
312 elif self
.tok
== '[':
314 expr
= self
.get_values()
315 elif self
.tok
in "'tfn":
319 raise QAPISchemaError(self
, 'Expected "{", "[" or string')
323 # Semantic analysis of schema expressions
324 # TODO fold into QAPISchema
325 # TODO catching name collisions in generated code would be nice
329 def find_base_members(base
):
330 base_struct_define
= find_struct(base
)
331 if not base_struct_define
:
333 return base_struct_define
['data']
336 # Return the qtype of an alternate branch, or None on error.
337 def find_alternate_member_qtype(qapi_type
):
338 if qapi_type
in builtin_types
:
339 return builtin_types
[qapi_type
]
340 elif find_struct(qapi_type
):
342 elif find_enum(qapi_type
):
343 return "QTYPE_QSTRING"
344 elif find_union(qapi_type
):
349 # Return the discriminator enum define if discriminator is specified as an
350 # enum type, otherwise return None.
351 def discriminator_find_enum_define(expr
):
352 base
= expr
.get('base')
353 discriminator
= expr
.get('discriminator')
355 if not (discriminator
and base
):
358 base_members
= find_base_members(base
)
362 discriminator_type
= base_members
.get(discriminator
)
363 if not discriminator_type
:
366 return find_enum(discriminator_type
)
369 # Names must be letters, numbers, -, and _. They must start with letter,
370 # except for downstream extensions which must start with __RFQDN_.
371 # Dots are only valid in the downstream extension prefix.
372 valid_name
= re
.compile('^(__[a-zA-Z0-9.-]+_)?'
373 '[a-zA-Z][a-zA-Z0-9_-]*$')
376 def check_name(expr_info
, source
, name
, allow_optional
=False,
381 if not isinstance(name
, str):
382 raise QAPIExprError(expr_info
,
383 "%s requires a string name" % source
)
384 if name
.startswith('*'):
385 membername
= name
[1:]
386 if not allow_optional
:
387 raise QAPIExprError(expr_info
,
388 "%s does not allow optional name '%s'"
390 # Enum members can start with a digit, because the generated C
391 # code always prefixes it with the enum name
392 if enum_member
and membername
[0].isdigit():
393 membername
= 'D' + membername
394 # Reserve the entire 'q_' namespace for c_name()
395 if not valid_name
.match(membername
) or \
396 c_name(membername
, False).startswith('q_'):
397 raise QAPIExprError(expr_info
,
398 "%s uses invalid name '%s'" % (source
, name
))
401 def add_name(name
, info
, meta
, implicit
=False):
403 check_name(info
, "'%s'" % meta
, name
)
404 # FIXME should reject names that differ only in '_' vs. '.'
405 # vs. '-', because they're liable to clash in generated C.
406 if name
in all_names
:
407 raise QAPIExprError(info
,
408 "%s '%s' is already defined"
409 % (all_names
[name
], name
))
410 if not implicit
and (name
.endswith('Kind') or name
.endswith('List')):
411 raise QAPIExprError(info
,
412 "%s '%s' should not end in '%s'"
413 % (meta
, name
, name
[-4:]))
414 all_names
[name
] = meta
417 def add_struct(definition
, info
):
419 name
= definition
['struct']
420 add_name(name
, info
, 'struct')
421 struct_types
.append(definition
)
424 def find_struct(name
):
426 for struct
in struct_types
:
427 if struct
['struct'] == name
:
432 def add_union(definition
, info
):
434 name
= definition
['union']
435 add_name(name
, info
, 'union')
436 union_types
.append(definition
)
439 def find_union(name
):
441 for union
in union_types
:
442 if union
['union'] == name
:
447 def add_enum(name
, info
, enum_values
=None, implicit
=False):
449 add_name(name
, info
, 'enum', implicit
)
450 enum_types
.append({"enum_name": name
, "enum_values": enum_values
})
455 for enum
in enum_types
:
456 if enum
['enum_name'] == name
:
462 return find_enum(name
) is not None
465 def check_type(expr_info
, source
, value
, allow_array
=False,
466 allow_dict
=False, allow_optional
=False,
473 # Check if array type for value is okay
474 if isinstance(value
, list):
476 raise QAPIExprError(expr_info
,
477 "%s cannot be an array" % source
)
478 if len(value
) != 1 or not isinstance(value
[0], str):
479 raise QAPIExprError(expr_info
,
480 "%s: array type must contain single type name"
484 # Check if type name for value is okay
485 if isinstance(value
, str):
486 if value
not in all_names
:
487 raise QAPIExprError(expr_info
,
488 "%s uses unknown type '%s'"
490 if not all_names
[value
] in allow_metas
:
491 raise QAPIExprError(expr_info
,
492 "%s cannot use %s type '%s'"
493 % (source
, all_names
[value
], value
))
497 raise QAPIExprError(expr_info
,
498 "%s should be a type name" % source
)
500 if not isinstance(value
, OrderedDict
):
501 raise QAPIExprError(expr_info
,
502 "%s should be a dictionary or type name" % source
)
504 # value is a dictionary, check that each member is okay
505 for (key
, arg
) in value
.items():
506 check_name(expr_info
, "Member of %s" % source
, key
,
507 allow_optional
=allow_optional
)
508 if c_name(key
, False) == 'u' or c_name(key
, False).startswith('has_'):
509 raise QAPIExprError(expr_info
,
510 "Member of %s uses reserved name '%s'"
512 # Todo: allow dictionaries to represent default values of
513 # an optional argument.
514 check_type(expr_info
, "Member '%s' of %s" % (key
, source
), arg
,
516 allow_metas
=['built-in', 'union', 'alternate', 'struct',
520 def check_command(expr
, expr_info
):
521 name
= expr
['command']
523 check_type(expr_info
, "'data' for command '%s'" % name
,
524 expr
.get('data'), allow_dict
=True, allow_optional
=True,
525 allow_metas
=['struct'])
526 returns_meta
= ['union', 'struct']
527 if name
in returns_whitelist
:
528 returns_meta
+= ['built-in', 'alternate', 'enum']
529 check_type(expr_info
, "'returns' for command '%s'" % name
,
530 expr
.get('returns'), allow_array
=True,
531 allow_optional
=True, allow_metas
=returns_meta
)
534 def check_event(expr
, expr_info
):
539 check_type(expr_info
, "'data' for event '%s'" % name
,
540 expr
.get('data'), allow_dict
=True, allow_optional
=True,
541 allow_metas
=['struct'])
544 def check_union(expr
, expr_info
):
546 base
= expr
.get('base')
547 discriminator
= expr
.get('discriminator')
548 members
= expr
['data']
550 # Two types of unions, determined by discriminator.
552 # With no discriminator it is a simple union.
553 if discriminator
is None:
555 allow_metas
= ['built-in', 'union', 'alternate', 'struct', 'enum']
557 raise QAPIExprError(expr_info
,
558 "Simple union '%s' must not have a base"
561 # Else, it's a flat union.
563 # The object must have a string member 'base'.
564 check_type(expr_info
, "'base' for union '%s'" % name
,
565 base
, allow_metas
=['struct'])
567 raise QAPIExprError(expr_info
,
568 "Flat union '%s' must have a base"
570 base_members
= find_base_members(base
)
573 # The value of member 'discriminator' must name a non-optional
574 # member of the base struct.
575 check_name(expr_info
, "Discriminator of flat union '%s'" % name
,
577 discriminator_type
= base_members
.get(discriminator
)
578 if not discriminator_type
:
579 raise QAPIExprError(expr_info
,
580 "Discriminator '%s' is not a member of base "
582 % (discriminator
, base
))
583 enum_define
= find_enum(discriminator_type
)
584 allow_metas
= ['struct']
585 # Do not allow string discriminator
587 raise QAPIExprError(expr_info
,
588 "Discriminator '%s' must be of enumeration "
589 "type" % discriminator
)
591 # Check every branch; don't allow an empty union
592 if len(members
) == 0:
593 raise QAPIExprError(expr_info
,
594 "Union '%s' cannot have empty 'data'" % name
)
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
599 check_type(expr_info
, "Member '%s' of union '%s'" % (key
, name
),
600 value
, allow_array
=not base
, allow_metas
=allow_metas
)
602 # If the discriminator names an enum type, then all members
603 # of 'data' must also be members of the enum type.
605 if key
not in enum_define
['enum_values']:
606 raise QAPIExprError(expr_info
,
607 "Discriminator value '%s' is not found in "
609 (key
, enum_define
["enum_name"]))
612 def check_alternate(expr
, expr_info
):
613 name
= expr
['alternate']
614 members
= expr
['data']
617 # Check every branch; require at least two branches
619 raise QAPIExprError(expr_info
,
620 "Alternate '%s' should have at least two branches "
622 for (key
, value
) in members
.items():
623 check_name(expr_info
, "Member of alternate '%s'" % name
, key
)
625 # Ensure alternates have no type conflicts.
626 check_type(expr_info
, "Member '%s' of alternate '%s'" % (key
, name
),
628 allow_metas
=['built-in', 'union', 'struct', 'enum'])
629 qtype
= find_alternate_member_qtype(value
)
631 raise QAPIExprError(expr_info
,
632 "Alternate '%s' member '%s' cannot use "
633 "type '%s'" % (name
, key
, value
))
634 if qtype
in types_seen
:
635 raise QAPIExprError(expr_info
,
636 "Alternate '%s' member '%s' can't "
637 "be distinguished from member '%s'"
638 % (name
, key
, types_seen
[qtype
]))
639 types_seen
[qtype
] = key
642 def check_enum(expr
, expr_info
):
644 members
= expr
.get('data')
645 prefix
= expr
.get('prefix')
647 if not isinstance(members
, list):
648 raise QAPIExprError(expr_info
,
649 "Enum '%s' requires an array for 'data'" % name
)
650 if prefix
is not None and not isinstance(prefix
, str):
651 raise QAPIExprError(expr_info
,
652 "Enum '%s' requires a string for 'prefix'" % name
)
653 for member
in members
:
654 check_name(expr_info
, "Member of enum '%s'" % name
, member
,
658 def check_struct(expr
, expr_info
):
659 name
= expr
['struct']
660 members
= expr
['data']
662 check_type(expr_info
, "'data' for struct '%s'" % name
, members
,
663 allow_dict
=True, allow_optional
=True)
664 check_type(expr_info
, "'base' for struct '%s'" % name
, expr
.get('base'),
665 allow_metas
=['struct'])
668 def check_keys(expr_elem
, meta
, required
, optional
=[]):
669 expr
= expr_elem
['expr']
670 info
= expr_elem
['info']
672 if not isinstance(name
, str):
673 raise QAPIExprError(info
,
674 "'%s' key must have a string value" % meta
)
675 required
= required
+ [meta
]
676 for (key
, value
) in expr
.items():
677 if key
not in required
and key
not in optional
:
678 raise QAPIExprError(info
,
679 "Unknown key '%s' in %s '%s'"
681 if (key
== 'gen' or key
== 'success-response') and value
is not False:
682 raise QAPIExprError(info
,
683 "'%s' of %s '%s' should only use false value"
687 raise QAPIExprError(info
,
688 "Key '%s' is missing from %s '%s'"
692 def check_exprs(exprs
):
695 # Learn the types and check for valid expression keys
696 for builtin
in builtin_types
.keys():
697 all_names
[builtin
] = 'built-in'
698 for expr_elem
in exprs
:
699 expr
= expr_elem
['expr']
700 info
= expr_elem
['info']
702 check_keys(expr_elem
, 'enum', ['data'], ['prefix'])
703 add_enum(expr
['enum'], info
, expr
['data'])
704 elif 'union' in expr
:
705 check_keys(expr_elem
, 'union', ['data'],
706 ['base', 'discriminator'])
707 add_union(expr
, info
)
708 elif 'alternate' in expr
:
709 check_keys(expr_elem
, 'alternate', ['data'])
710 add_name(expr
['alternate'], info
, 'alternate')
711 elif 'struct' in expr
:
712 check_keys(expr_elem
, 'struct', ['data'], ['base'])
713 add_struct(expr
, info
)
714 elif 'command' in expr
:
715 check_keys(expr_elem
, 'command', [],
716 ['data', 'returns', 'gen', 'success-response'])
717 add_name(expr
['command'], info
, 'command')
718 elif 'event' in expr
:
719 check_keys(expr_elem
, 'event', [], ['data'])
720 add_name(expr
['event'], info
, 'event')
722 raise QAPIExprError(expr_elem
['info'],
723 "Expression is missing metatype")
725 # Try again for hidden UnionKind enum
726 for expr_elem
in exprs
:
727 expr
= expr_elem
['expr']
729 if not discriminator_find_enum_define(expr
):
730 add_enum('%sKind' % expr
['union'], expr_elem
['info'],
732 elif 'alternate' in expr
:
733 add_enum('%sKind' % expr
['alternate'], expr_elem
['info'],
736 # Validate that exprs make sense
737 for expr_elem
in exprs
:
738 expr
= expr_elem
['expr']
739 info
= expr_elem
['info']
742 check_enum(expr
, info
)
743 elif 'union' in expr
:
744 check_union(expr
, info
)
745 elif 'alternate' in expr
:
746 check_alternate(expr
, info
)
747 elif 'struct' in expr
:
748 check_struct(expr
, info
)
749 elif 'command' in expr
:
750 check_command(expr
, info
)
751 elif 'event' in expr
:
752 check_event(expr
, info
)
754 assert False, 'unexpected meta type'
760 # Schema compiler frontend
763 class QAPISchemaEntity(object):
764 def __init__(self
, name
, info
):
765 assert isinstance(name
, str)
767 # For explicitly defined entities, info points to the (explicit)
768 # definition. For builtins (and their arrays), info is None.
769 # For implicitly defined entities, info points to a place that
770 # triggered the implicit definition (there may be more than one
775 return c_name(self
.name
)
777 def check(self
, schema
):
780 def is_implicit(self
):
783 def visit(self
, visitor
):
787 class QAPISchemaVisitor(object):
788 def visit_begin(self
, schema
):
794 def visit_needed(self
, entity
):
795 # Default to visiting everything
798 def visit_builtin_type(self
, name
, info
, json_type
):
801 def visit_enum_type(self
, name
, info
, values
, prefix
):
804 def visit_array_type(self
, name
, info
, element_type
):
807 def visit_object_type(self
, name
, info
, base
, members
, variants
):
810 def visit_object_type_flat(self
, name
, info
, members
, variants
):
813 def visit_alternate_type(self
, name
, info
, variants
):
816 def visit_command(self
, name
, info
, arg_type
, ret_type
,
817 gen
, success_response
):
820 def visit_event(self
, name
, info
, arg_type
):
824 class QAPISchemaType(QAPISchemaEntity
):
825 def c_type(self
, is_param
=False, is_unboxed
=False):
826 return c_name(self
.name
) + pointer_suffix
834 def alternate_qtype(self
):
836 'string': 'QTYPE_QSTRING',
837 'number': 'QTYPE_QFLOAT',
839 'boolean': 'QTYPE_QBOOL',
840 'object': 'QTYPE_QDICT'
842 return json2qtype
.get(self
.json_type())
845 class QAPISchemaBuiltinType(QAPISchemaType
):
846 def __init__(self
, name
, json_type
, c_type
, c_null
):
847 QAPISchemaType
.__init
__(self
, name
, None)
848 assert not c_type
or isinstance(c_type
, str)
849 assert json_type
in ('string', 'number', 'int', 'boolean', 'null',
851 self
._json
_type
_name
= json_type
852 self
._c
_type
_name
= c_type
853 self
._c
_null
_val
= c_null
858 def c_type(self
, is_param
=False, is_unboxed
=False):
859 if is_param
and self
.name
== 'str':
860 return 'const ' + self
._c
_type
_name
861 return self
._c
_type
_name
864 return self
._c
_null
_val
867 return self
._json
_type
_name
869 def visit(self
, visitor
):
870 visitor
.visit_builtin_type(self
.name
, self
.info
, self
.json_type())
873 class QAPISchemaEnumType(QAPISchemaType
):
874 def __init__(self
, name
, info
, values
, prefix
):
875 QAPISchemaType
.__init
__(self
, name
, info
)
877 assert isinstance(v
, QAPISchemaMember
)
879 assert prefix
is None or isinstance(prefix
, str)
883 def check(self
, schema
):
885 for v
in self
.values
:
886 v
.check_clash(self
.info
, seen
)
888 def is_implicit(self
):
889 # See QAPISchema._make_implicit_enum_type()
890 return self
.name
.endswith('Kind')
892 def c_type(self
, is_param
=False, is_unboxed
=False):
893 return c_name(self
.name
)
895 def member_names(self
):
896 return [v
.name
for v
in self
.values
]
899 return c_enum_const(self
.name
, (self
.member_names() + ['_MAX'])[0],
905 def visit(self
, visitor
):
906 visitor
.visit_enum_type(self
.name
, self
.info
,
907 self
.member_names(), self
.prefix
)
910 class QAPISchemaArrayType(QAPISchemaType
):
911 def __init__(self
, name
, info
, element_type
):
912 QAPISchemaType
.__init
__(self
, name
, info
)
913 assert isinstance(element_type
, str)
914 self
._element
_type
_name
= element_type
915 self
.element_type
= None
917 def check(self
, schema
):
918 self
.element_type
= schema
.lookup_type(self
._element
_type
_name
)
919 assert self
.element_type
921 def is_implicit(self
):
927 def visit(self
, visitor
):
928 visitor
.visit_array_type(self
.name
, self
.info
, self
.element_type
)
931 class QAPISchemaObjectType(QAPISchemaType
):
932 def __init__(self
, name
, info
, base
, local_members
, variants
):
933 # struct has local_members, optional base, and no variants
934 # flat union has base, variants, and no local_members
935 # simple union has local_members, variants, and no base
936 QAPISchemaType
.__init
__(self
, name
, info
)
937 assert base
is None or isinstance(base
, str)
938 for m
in local_members
:
939 assert isinstance(m
, QAPISchemaObjectTypeMember
)
941 if variants
is not None:
942 assert isinstance(variants
, QAPISchemaObjectTypeVariants
)
943 variants
.set_owner(name
)
944 self
._base
_name
= base
946 self
.local_members
= local_members
947 self
.variants
= variants
950 def check(self
, schema
):
951 if self
.members
is False: # check for cycles
952 raise QAPIExprError(self
.info
,
953 "Object %s contains itself" % self
.name
)
956 self
.members
= False # mark as being checked
959 self
.base
= schema
.lookup_type(self
._base
_name
)
960 assert isinstance(self
.base
, QAPISchemaObjectType
)
961 self
.base
.check(schema
)
962 self
.base
.check_clash(schema
, self
.info
, seen
)
963 for m
in self
.local_members
:
965 m
.check_clash(self
.info
, seen
)
966 self
.members
= seen
.values()
968 self
.variants
.check(schema
, seen
)
969 assert self
.variants
.tag_member
in self
.members
970 self
.variants
.check_clash(schema
, self
.info
, seen
)
972 # Check that the members of this type do not cause duplicate JSON members,
973 # and update seen to track the members seen so far. Report any errors
974 # on behalf of info, which is not necessarily self.info
975 def check_clash(self
, schema
, info
, seen
):
976 assert not self
.variants
# not implemented
977 for m
in self
.members
:
978 m
.check_clash(info
, seen
)
980 def is_implicit(self
):
981 # See QAPISchema._make_implicit_object_type()
982 return self
.name
[0] == ':'
985 assert not self
.is_implicit()
986 return QAPISchemaType
.c_name(self
)
988 def c_type(self
, is_param
=False, is_unboxed
=False):
989 assert not self
.is_implicit()
991 return c_name(self
.name
)
992 return c_name(self
.name
) + pointer_suffix
997 def visit(self
, visitor
):
998 visitor
.visit_object_type(self
.name
, self
.info
,
999 self
.base
, self
.local_members
, self
.variants
)
1000 visitor
.visit_object_type_flat(self
.name
, self
.info
,
1001 self
.members
, self
.variants
)
1004 class QAPISchemaMember(object):
1007 def __init__(self
, name
):
1008 assert isinstance(name
, str)
1012 def set_owner(self
, name
):
1013 assert not self
.owner
1016 def check_clash(self
, info
, seen
):
1017 cname
= c_name(self
.name
)
1018 if cname
.lower() != cname
and self
.owner
not in case_whitelist
:
1019 raise QAPIExprError(info
,
1020 "%s should not use uppercase" % self
.describe())
1022 raise QAPIExprError(info
,
1023 "%s collides with %s"
1024 % (self
.describe(), seen
[cname
].describe()))
1027 def _pretty_owner(self
):
1029 if owner
.startswith(':obj-'):
1030 # See QAPISchema._make_implicit_object_type() - reverse the
1031 # mapping there to create a nice human-readable description
1033 if owner
.endswith('-arg'):
1034 return '(parameter of %s)' % owner
[:-4]
1036 assert owner
.endswith('-wrapper')
1037 # Unreachable and not implemented
1039 if owner
.endswith('Kind'):
1040 # See QAPISchema._make_implicit_enum_type()
1041 return '(branch of %s)' % owner
[:-4]
1042 return '(%s of %s)' % (self
.role
, owner
)
1045 return "'%s' %s" % (self
.name
, self
._pretty
_owner
())
1048 class QAPISchemaObjectTypeMember(QAPISchemaMember
):
1049 def __init__(self
, name
, typ
, optional
):
1050 QAPISchemaMember
.__init
__(self
, name
)
1051 assert isinstance(typ
, str)
1052 assert isinstance(optional
, bool)
1053 self
._type
_name
= typ
1055 self
.optional
= optional
1057 def check(self
, schema
):
1059 self
.type = schema
.lookup_type(self
._type
_name
)
1063 class QAPISchemaObjectTypeVariants(object):
1064 def __init__(self
, tag_name
, tag_member
, variants
):
1065 # Flat unions pass tag_name but not tag_member.
1066 # Simple unions and alternates pass tag_member but not tag_name.
1067 # After check(), tag_member is always set, and tag_name remains
1068 # a reliable witness of being used by a flat union.
1069 assert bool(tag_member
) != bool(tag_name
)
1070 assert (isinstance(tag_name
, str) or
1071 isinstance(tag_member
, QAPISchemaObjectTypeMember
))
1072 assert len(variants
) > 0
1074 assert isinstance(v
, QAPISchemaObjectTypeVariant
)
1075 self
.tag_name
= tag_name
1076 self
.tag_member
= tag_member
1077 self
.variants
= variants
1079 def set_owner(self
, name
):
1080 for v
in self
.variants
:
1083 def check(self
, schema
, seen
):
1084 if not self
.tag_member
: # flat union
1085 self
.tag_member
= seen
[c_name(self
.tag_name
)]
1086 assert self
.tag_name
== self
.tag_member
.name
1087 assert isinstance(self
.tag_member
.type, QAPISchemaEnumType
)
1088 for v
in self
.variants
:
1090 # Union names must match enum values; alternate names are
1091 # checked separately. Use 'seen' to tell the two apart.
1093 assert v
.name
in self
.tag_member
.type.member_names()
1094 assert isinstance(v
.type, QAPISchemaObjectType
)
1095 v
.type.check(schema
)
1097 def check_clash(self
, schema
, info
, seen
):
1098 for v
in self
.variants
:
1099 # Reset seen map for each variant, since qapi names from one
1100 # branch do not affect another branch
1101 assert isinstance(v
.type, QAPISchemaObjectType
)
1102 v
.type.check_clash(schema
, info
, dict(seen
))
1105 class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember
):
1108 def __init__(self
, name
, typ
):
1109 QAPISchemaObjectTypeMember
.__init
__(self
, name
, typ
, False)
1111 # This function exists to support ugly simple union special cases
1112 # TODO get rid of them, and drop the function
1113 def simple_union_type(self
):
1114 if (self
.type.is_implicit() and
1115 isinstance(self
.type, QAPISchemaObjectType
)):
1116 assert len(self
.type.members
) == 1
1117 assert not self
.type.variants
1118 return self
.type.members
[0].type
1122 class QAPISchemaAlternateType(QAPISchemaType
):
1123 def __init__(self
, name
, info
, variants
):
1124 QAPISchemaType
.__init
__(self
, name
, info
)
1125 assert isinstance(variants
, QAPISchemaObjectTypeVariants
)
1126 assert not variants
.tag_name
1127 variants
.set_owner(name
)
1128 variants
.tag_member
.set_owner(self
.name
)
1129 self
.variants
= variants
1131 def check(self
, schema
):
1132 self
.variants
.tag_member
.check(schema
)
1133 # Not calling self.variants.check_clash(), because there's nothing
1135 self
.variants
.check(schema
, {})
1136 # Alternate branch names have no relation to the tag enum values;
1137 # so we have to check for potential name collisions ourselves.
1139 for v
in self
.variants
.variants
:
1140 v
.check_clash(self
.info
, seen
)
1142 def json_type(self
):
1145 def visit(self
, visitor
):
1146 visitor
.visit_alternate_type(self
.name
, self
.info
, self
.variants
)
1149 class QAPISchemaCommand(QAPISchemaEntity
):
1150 def __init__(self
, name
, info
, arg_type
, ret_type
, gen
, success_response
):
1151 QAPISchemaEntity
.__init
__(self
, name
, info
)
1152 assert not arg_type
or isinstance(arg_type
, str)
1153 assert not ret_type
or isinstance(ret_type
, str)
1154 self
._arg
_type
_name
= arg_type
1155 self
.arg_type
= None
1156 self
._ret
_type
_name
= ret_type
1157 self
.ret_type
= None
1159 self
.success_response
= success_response
1161 def check(self
, schema
):
1162 if self
._arg
_type
_name
:
1163 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1164 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1165 assert not self
.arg_type
.variants
# not implemented
1166 if self
._ret
_type
_name
:
1167 self
.ret_type
= schema
.lookup_type(self
._ret
_type
_name
)
1168 assert isinstance(self
.ret_type
, QAPISchemaType
)
1170 def visit(self
, visitor
):
1171 visitor
.visit_command(self
.name
, self
.info
,
1172 self
.arg_type
, self
.ret_type
,
1173 self
.gen
, self
.success_response
)
1176 class QAPISchemaEvent(QAPISchemaEntity
):
1177 def __init__(self
, name
, info
, arg_type
):
1178 QAPISchemaEntity
.__init
__(self
, name
, info
)
1179 assert not arg_type
or isinstance(arg_type
, str)
1180 self
._arg
_type
_name
= arg_type
1181 self
.arg_type
= None
1183 def check(self
, schema
):
1184 if self
._arg
_type
_name
:
1185 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1186 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1187 assert not self
.arg_type
.variants
# not implemented
1189 def visit(self
, visitor
):
1190 visitor
.visit_event(self
.name
, self
.info
, self
.arg_type
)
1193 class QAPISchema(object):
1194 def __init__(self
, fname
):
1196 self
.exprs
= check_exprs(QAPISchemaParser(open(fname
, "r")).exprs
)
1197 self
._entity
_dict
= {}
1198 self
._predefining
= True
1199 self
._def
_predefineds
()
1200 self
._predefining
= False
1203 except (QAPISchemaError
, QAPIExprError
) as err
:
1204 print >>sys
.stderr
, err
1207 def _def_entity(self
, ent
):
1208 # Only the predefined types are allowed to not have info
1209 assert ent
.info
or self
._predefining
1210 assert ent
.name
not in self
._entity
_dict
1211 self
._entity
_dict
[ent
.name
] = ent
1213 def lookup_entity(self
, name
, typ
=None):
1214 ent
= self
._entity
_dict
.get(name
)
1215 if typ
and not isinstance(ent
, typ
):
1219 def lookup_type(self
, name
):
1220 return self
.lookup_entity(name
, QAPISchemaType
)
1222 def _def_builtin_type(self
, name
, json_type
, c_type
, c_null
):
1223 self
._def
_entity
(QAPISchemaBuiltinType(name
, json_type
,
1225 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1226 # qapi-types.h from a single .c, all arrays of builtins must be
1227 # declared in the first file whether or not they are used. Nicer
1228 # would be to use lazy instantiation, while figuring out how to
1229 # avoid compilation issues with multiple qapi-types.h.
1230 self
._make
_array
_type
(name
, None)
1232 def _def_predefineds(self
):
1233 for t
in [('str', 'string', 'char' + pointer_suffix
, 'NULL'),
1234 ('number', 'number', 'double', '0'),
1235 ('int', 'int', 'int64_t', '0'),
1236 ('int8', 'int', 'int8_t', '0'),
1237 ('int16', 'int', 'int16_t', '0'),
1238 ('int32', 'int', 'int32_t', '0'),
1239 ('int64', 'int', 'int64_t', '0'),
1240 ('uint8', 'int', 'uint8_t', '0'),
1241 ('uint16', 'int', 'uint16_t', '0'),
1242 ('uint32', 'int', 'uint32_t', '0'),
1243 ('uint64', 'int', 'uint64_t', '0'),
1244 ('size', 'int', 'uint64_t', '0'),
1245 ('bool', 'boolean', 'bool', 'false'),
1246 ('any', 'value', 'QObject' + pointer_suffix
, 'NULL')]:
1247 self
._def
_builtin
_type
(*t
)
1248 self
.the_empty_object_type
= QAPISchemaObjectType(':empty', None, None,
1250 self
._def
_entity
(self
.the_empty_object_type
)
1251 qtype_values
= self
._make
_enum
_members
(['none', 'qnull', 'qint',
1252 'qstring', 'qdict', 'qlist',
1254 self
._def
_entity
(QAPISchemaEnumType('QType', None, qtype_values
,
1257 def _make_enum_members(self
, values
):
1258 return [QAPISchemaMember(v
) for v
in values
]
1260 def _make_implicit_enum_type(self
, name
, info
, values
):
1261 # See also QAPISchemaObjectTypeMember._pretty_owner()
1262 name
= name
+ 'Kind' # Use namespace reserved by add_name()
1263 self
._def
_entity
(QAPISchemaEnumType(
1264 name
, info
, self
._make
_enum
_members
(values
), None))
1267 def _make_array_type(self
, element_type
, info
):
1268 name
= element_type
+ 'List' # Use namespace reserved by add_name()
1269 if not self
.lookup_type(name
):
1270 self
._def
_entity
(QAPISchemaArrayType(name
, info
, element_type
))
1273 def _make_implicit_object_type(self
, name
, info
, role
, members
):
1276 # See also QAPISchemaObjectTypeMember._pretty_owner()
1277 name
= ':obj-%s-%s' % (name
, role
)
1278 if not self
.lookup_entity(name
, QAPISchemaObjectType
):
1279 self
._def
_entity
(QAPISchemaObjectType(name
, info
, None,
1283 def _def_enum_type(self
, expr
, info
):
1286 prefix
= expr
.get('prefix')
1287 self
._def
_entity
(QAPISchemaEnumType(
1288 name
, info
, self
._make
_enum
_members
(data
), prefix
))
1290 def _make_member(self
, name
, typ
, info
):
1292 if name
.startswith('*'):
1295 if isinstance(typ
, list):
1296 assert len(typ
) == 1
1297 typ
= self
._make
_array
_type
(typ
[0], info
)
1298 return QAPISchemaObjectTypeMember(name
, typ
, optional
)
1300 def _make_members(self
, data
, info
):
1301 return [self
._make
_member
(key
, value
, info
)
1302 for (key
, value
) in data
.iteritems()]
1304 def _def_struct_type(self
, expr
, info
):
1305 name
= expr
['struct']
1306 base
= expr
.get('base')
1308 self
._def
_entity
(QAPISchemaObjectType(name
, info
, base
,
1309 self
._make
_members
(data
, info
),
1312 def _make_variant(self
, case
, typ
):
1313 return QAPISchemaObjectTypeVariant(case
, typ
)
1315 def _make_simple_variant(self
, case
, typ
, info
):
1316 if isinstance(typ
, list):
1317 assert len(typ
) == 1
1318 typ
= self
._make
_array
_type
(typ
[0], info
)
1319 typ
= self
._make
_implicit
_object
_type
(
1320 typ
, info
, 'wrapper', [self
._make
_member
('data', typ
, info
)])
1321 return QAPISchemaObjectTypeVariant(case
, typ
)
1323 def _def_union_type(self
, expr
, info
):
1324 name
= expr
['union']
1326 base
= expr
.get('base')
1327 tag_name
= expr
.get('discriminator')
1330 variants
= [self
._make
_variant
(key
, value
)
1331 for (key
, value
) in data
.iteritems()]
1334 variants
= [self
._make
_simple
_variant
(key
, value
, info
)
1335 for (key
, value
) in data
.iteritems()]
1336 typ
= self
._make
_implicit
_enum
_type
(name
, info
,
1337 [v
.name
for v
in variants
])
1338 tag_member
= QAPISchemaObjectTypeMember('type', typ
, False)
1339 members
= [tag_member
]
1341 QAPISchemaObjectType(name
, info
, base
, members
,
1342 QAPISchemaObjectTypeVariants(tag_name
,
1346 def _def_alternate_type(self
, expr
, info
):
1347 name
= expr
['alternate']
1349 variants
= [self
._make
_variant
(key
, value
)
1350 for (key
, value
) in data
.iteritems()]
1351 tag_member
= QAPISchemaObjectTypeMember('type', 'QType', False)
1353 QAPISchemaAlternateType(name
, info
,
1354 QAPISchemaObjectTypeVariants(None,
1358 def _def_command(self
, expr
, info
):
1359 name
= expr
['command']
1360 data
= expr
.get('data')
1361 rets
= expr
.get('returns')
1362 gen
= expr
.get('gen', True)
1363 success_response
= expr
.get('success-response', True)
1364 if isinstance(data
, OrderedDict
):
1365 data
= self
._make
_implicit
_object
_type
(
1366 name
, info
, 'arg', self
._make
_members
(data
, info
))
1367 if isinstance(rets
, list):
1368 assert len(rets
) == 1
1369 rets
= self
._make
_array
_type
(rets
[0], info
)
1370 self
._def
_entity
(QAPISchemaCommand(name
, info
, data
, rets
, gen
,
1373 def _def_event(self
, expr
, info
):
1374 name
= expr
['event']
1375 data
= expr
.get('data')
1376 if isinstance(data
, OrderedDict
):
1377 data
= self
._make
_implicit
_object
_type
(
1378 name
, info
, 'arg', self
._make
_members
(data
, info
))
1379 self
._def
_entity
(QAPISchemaEvent(name
, info
, data
))
1381 def _def_exprs(self
):
1382 for expr_elem
in self
.exprs
:
1383 expr
= expr_elem
['expr']
1384 info
= expr_elem
['info']
1386 self
._def
_enum
_type
(expr
, info
)
1387 elif 'struct' in expr
:
1388 self
._def
_struct
_type
(expr
, info
)
1389 elif 'union' in expr
:
1390 self
._def
_union
_type
(expr
, info
)
1391 elif 'alternate' in expr
:
1392 self
._def
_alternate
_type
(expr
, info
)
1393 elif 'command' in expr
:
1394 self
._def
_command
(expr
, info
)
1395 elif 'event' in expr
:
1396 self
._def
_event
(expr
, info
)
1401 for ent
in self
._entity
_dict
.values():
1404 def visit(self
, visitor
):
1405 visitor
.visit_begin(self
)
1406 for (name
, entity
) in sorted(self
._entity
_dict
.items()):
1407 if visitor
.visit_needed(entity
):
1408 entity
.visit(visitor
)
1413 # Code generation helpers
1416 def camel_case(name
):
1420 if ch
in ['_', '-']:
1423 new_name
+= ch
.upper()
1426 new_name
+= ch
.lower()
1430 # ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1431 # ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1432 # ENUM24_Name -> ENUM24_NAME
1433 def camel_to_upper(value
):
1434 c_fun_str
= c_name(value
, False)
1442 # When c is upper and no "_" appears before, do more checks
1443 if c
.isupper() and (i
> 0) and c_fun_str
[i
- 1] != "_":
1444 if i
< l
- 1 and c_fun_str
[i
+ 1].islower():
1446 elif c_fun_str
[i
- 1].isdigit():
1449 return new_name
.lstrip('_').upper()
1452 def c_enum_const(type_name
, const_name
, prefix
=None):
1453 if prefix
is not None:
1455 return camel_to_upper(type_name
) + '_' + c_name(const_name
, False).upper()
1457 c_name_trans
= string
.maketrans('.-', '__')
1460 # Map @name to a valid C identifier.
1461 # If @protect, avoid returning certain ticklish identifiers (like
1462 # C keywords) by prepending "q_".
1464 # Used for converting 'name' from a 'name':'type' qapi definition
1465 # into a generated struct member, as well as converting type names
1466 # into substrings of a generated C function name.
1467 # '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1468 # protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
1469 def c_name(name
, protect
=True):
1470 # ANSI X3J11/88-090, 3.1.1
1471 c89_words
= set(['auto', 'break', 'case', 'char', 'const', 'continue',
1472 'default', 'do', 'double', 'else', 'enum', 'extern',
1473 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1474 'return', 'short', 'signed', 'sizeof', 'static',
1475 'struct', 'switch', 'typedef', 'union', 'unsigned',
1476 'void', 'volatile', 'while'])
1477 # ISO/IEC 9899:1999, 6.4.1
1478 c99_words
= set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1479 # ISO/IEC 9899:2011, 6.4.1
1480 c11_words
= set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1481 '_Noreturn', '_Static_assert', '_Thread_local'])
1482 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1484 gcc_words
= set(['asm', 'typeof'])
1485 # C++ ISO/IEC 14882:2003 2.11
1486 cpp_words
= set(['bool', 'catch', 'class', 'const_cast', 'delete',
1487 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1488 'namespace', 'new', 'operator', 'private', 'protected',
1489 'public', 'reinterpret_cast', 'static_cast', 'template',
1490 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1491 'using', 'virtual', 'wchar_t',
1492 # alternative representations
1493 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1494 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
1495 # namespace pollution:
1496 polluted_words
= set(['unix', 'errno', 'mips', 'sparc'])
1497 name
= name
.translate(c_name_trans
)
1498 if protect
and (name
in c89_words | c99_words | c11_words | gcc_words
1499 | cpp_words | polluted_words
):
1503 eatspace
= '\033EATSPACE.'
1504 pointer_suffix
= ' *' + eatspace
1507 def genindent(count
):
1509 for _
in range(count
):
1516 def push_indent(indent_amount
=4):
1518 indent_level
+= indent_amount
1521 def pop_indent(indent_amount
=4):
1523 indent_level
-= indent_amount
1526 # Generate @code with @kwds interpolated.
1527 # Obey indent_level, and strip eatspace.
1528 def cgen(code
, **kwds
):
1531 indent
= genindent(indent_level
)
1532 # re.subn() lacks flags support before Python 2.7, use re.compile()
1533 raw
= re
.subn(re
.compile("^.", re
.MULTILINE
),
1534 indent
+ r
'\g<0>', raw
)
1536 return re
.sub(re
.escape(eatspace
) + ' *', '', raw
)
1539 def mcgen(code
, **kwds
):
1542 return cgen(code
, **kwds
)
1545 def guardname(filename
):
1546 return c_name(filename
, protect
=False).upper()
1549 def guardstart(name
):
1556 name
=guardname(name
))
1562 #endif /* %(name)s */
1565 name
=guardname(name
))
1568 def gen_enum_lookup(name
, values
, prefix
=None):
1571 const char *const %(c_name)s_lookup[] = {
1573 c_name
=c_name(name
))
1574 for value
in values
:
1575 index
= c_enum_const(name
, value
, prefix
)
1577 [%(index)s] = "%(value)s",
1579 index
=index
, value
=value
)
1581 max_index
= c_enum_const(name
, '_MAX', prefix
)
1583 [%(max_index)s] = NULL,
1586 max_index
=max_index
)
1590 def gen_enum(name
, values
, prefix
=None):
1591 # append automatically generated _MAX value
1592 enum_values
= values
+ ['_MAX']
1596 typedef enum %(c_name)s {
1598 c_name
=c_name(name
))
1601 for value
in enum_values
:
1605 c_enum
=c_enum_const(name
, value
, prefix
),
1612 c_name
=c_name(name
))
1616 extern const char *const %(c_name)s_lookup[];
1618 c_name
=c_name(name
))
1622 def gen_params(arg_type
, extra
):
1625 assert not arg_type
.variants
1628 for memb
in arg_type
.members
:
1632 ret
+= 'bool has_%s, ' % c_name(memb
.name
)
1633 ret
+= '%s %s' % (memb
.type.c_type(is_param
=True), c_name(memb
.name
))
1639 def gen_err_check(label
='out', skiperr
=False):
1650 def gen_visit_members(members
, prefix
='', need_cast
=False, skiperr
=False,
1658 for memb
in members
:
1661 if (visit_optional(v, "%(name)s", &%(prefix)shas_%(c_name)s)) {
1663 prefix
=prefix
, c_name
=c_name(memb
.name
),
1667 # Ugly: sometimes we need to cast away const
1668 if need_cast
and memb
.type.name
== 'str':
1674 visit_type_%(c_type)s(v, "%(name)s", %(cast)s&%(prefix)s%(c_name)s, %(errp)s);
1676 c_type
=memb
.type.c_name(), prefix
=prefix
, cast
=cast
,
1677 c_name
=c_name(memb
.name
), name
=memb
.name
,
1679 ret
+= gen_err_check(skiperr
=skiperr
, label
=label
)
1690 # Common command line parsing
1694 def parse_command_line(extra_options
="", extra_long_options
=[]):
1697 opts
, args
= getopt
.gnu_getopt(sys
.argv
[1:],
1698 "chp:o:" + extra_options
,
1699 ["source", "header", "prefix=",
1700 "output-dir="] + extra_long_options
)
1701 except getopt
.GetoptError
as err
:
1702 print >>sys
.stderr
, "%s: %s" % (sys
.argv
[0], str(err
))
1713 if o
in ("-p", "--prefix"):
1714 match
= re
.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a
)
1715 if match
.end() != len(a
):
1716 print >>sys
.stderr
, \
1717 "%s: 'funny character '%s' in argument of --prefix" \
1718 % (sys
.argv
[0], a
[match
.end()])
1721 elif o
in ("-o", "--output-dir"):
1722 output_dir
= a
+ "/"
1723 elif o
in ("-c", "--source"):
1725 elif o
in ("-h", "--header"):
1728 extra_opts
.append(oa
)
1730 if not do_c
and not do_h
:
1735 print >>sys
.stderr
, "%s: need exactly one argument" % sys
.argv
[0]
1739 return (fname
, output_dir
, do_c
, do_h
, prefix
, extra_opts
)
1742 # Generate output files with boilerplate
1746 def open_output(output_dir
, do_c
, do_h
, prefix
, c_file
, h_file
,
1747 c_comment
, h_comment
):
1748 guard
= guardname(prefix
+ h_file
)
1749 c_file
= output_dir
+ prefix
+ c_file
1750 h_file
= output_dir
+ prefix
+ h_file
1754 os
.makedirs(output_dir
)
1755 except os
.error
as e
:
1756 if e
.errno
!= errno
.EEXIST
:
1759 def maybe_open(really
, name
, opt
):
1761 return open(name
, opt
)
1764 return StringIO
.StringIO()
1766 fdef
= maybe_open(do_c
, c_file
, 'w')
1767 fdecl
= maybe_open(do_h
, h_file
, 'w')
1769 fdef
.write(mcgen('''
1770 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1775 fdecl
.write(mcgen('''
1776 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1782 comment
=h_comment
, guard
=guard
))
1784 return (fdef
, fdecl
)
1787 def close_output(fdef
, fdecl
):