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 'CpuInfoMIPS', # PC, visible through query-cpu
67 'CpuInfoTricore', # PC, visible through query-cpu
68 'QapiErrorClass', # all members, visible through errors
69 'UuidInfo', # UUID, visible through query-uuid
70 'X86CPURegister32', # all members, visible indirectly through qom-get
71 'q_obj_CpuInfo-base', # CPU, visible through query-cpu
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 if isinstance(base
, dict):
332 base_struct_define
= find_struct(base
)
333 if not base_struct_define
:
335 return base_struct_define
['data']
338 # Return the qtype of an alternate branch, or None on error.
339 def find_alternate_member_qtype(qapi_type
):
340 if qapi_type
in builtin_types
:
341 return builtin_types
[qapi_type
]
342 elif find_struct(qapi_type
):
344 elif find_enum(qapi_type
):
345 return "QTYPE_QSTRING"
346 elif find_union(qapi_type
):
351 # Return the discriminator enum define if discriminator is specified as an
352 # enum type, otherwise return None.
353 def discriminator_find_enum_define(expr
):
354 base
= expr
.get('base')
355 discriminator
= expr
.get('discriminator')
357 if not (discriminator
and base
):
360 base_members
= find_base_members(base
)
364 discriminator_type
= base_members
.get(discriminator
)
365 if not discriminator_type
:
368 return find_enum(discriminator_type
)
371 # Names must be letters, numbers, -, and _. They must start with letter,
372 # except for downstream extensions which must start with __RFQDN_.
373 # Dots are only valid in the downstream extension prefix.
374 valid_name
= re
.compile('^(__[a-zA-Z0-9.-]+_)?'
375 '[a-zA-Z][a-zA-Z0-9_-]*$')
378 def check_name(expr_info
, source
, name
, allow_optional
=False,
383 if not isinstance(name
, str):
384 raise QAPIExprError(expr_info
,
385 "%s requires a string name" % source
)
386 if name
.startswith('*'):
387 membername
= name
[1:]
388 if not allow_optional
:
389 raise QAPIExprError(expr_info
,
390 "%s does not allow optional name '%s'"
392 # Enum members can start with a digit, because the generated C
393 # code always prefixes it with the enum name
394 if enum_member
and membername
[0].isdigit():
395 membername
= 'D' + membername
396 # Reserve the entire 'q_' namespace for c_name(), and for 'q_empty'
397 # and 'q_obj_*' implicit type names.
398 if not valid_name
.match(membername
) or \
399 c_name(membername
, False).startswith('q_'):
400 raise QAPIExprError(expr_info
,
401 "%s uses invalid name '%s'" % (source
, name
))
404 def add_name(name
, info
, meta
, implicit
=False):
406 check_name(info
, "'%s'" % meta
, name
)
407 # FIXME should reject names that differ only in '_' vs. '.'
408 # vs. '-', because they're liable to clash in generated C.
409 if name
in all_names
:
410 raise QAPIExprError(info
,
411 "%s '%s' is already defined"
412 % (all_names
[name
], name
))
413 if not implicit
and (name
.endswith('Kind') or name
.endswith('List')):
414 raise QAPIExprError(info
,
415 "%s '%s' should not end in '%s'"
416 % (meta
, name
, name
[-4:]))
417 all_names
[name
] = meta
420 def add_struct(definition
, info
):
422 name
= definition
['struct']
423 add_name(name
, info
, 'struct')
424 struct_types
.append(definition
)
427 def find_struct(name
):
429 for struct
in struct_types
:
430 if struct
['struct'] == name
:
435 def add_union(definition
, info
):
437 name
= definition
['union']
438 add_name(name
, info
, 'union')
439 union_types
.append(definition
)
442 def find_union(name
):
444 for union
in union_types
:
445 if union
['union'] == name
:
450 def add_enum(name
, info
, enum_values
=None, implicit
=False):
452 add_name(name
, info
, 'enum', implicit
)
453 enum_types
.append({"enum_name": name
, "enum_values": enum_values
})
458 for enum
in enum_types
:
459 if enum
['enum_name'] == name
:
465 return find_enum(name
) is not None
468 def check_type(expr_info
, source
, value
, allow_array
=False,
469 allow_dict
=False, allow_optional
=False,
476 # Check if array type for value is okay
477 if isinstance(value
, list):
479 raise QAPIExprError(expr_info
,
480 "%s cannot be an array" % source
)
481 if len(value
) != 1 or not isinstance(value
[0], str):
482 raise QAPIExprError(expr_info
,
483 "%s: array type must contain single type name"
487 # Check if type name for value is okay
488 if isinstance(value
, str):
489 if value
not in all_names
:
490 raise QAPIExprError(expr_info
,
491 "%s uses unknown type '%s'"
493 if not all_names
[value
] in allow_metas
:
494 raise QAPIExprError(expr_info
,
495 "%s cannot use %s type '%s'"
496 % (source
, all_names
[value
], value
))
500 raise QAPIExprError(expr_info
,
501 "%s should be a type name" % source
)
503 if not isinstance(value
, OrderedDict
):
504 raise QAPIExprError(expr_info
,
505 "%s should be a dictionary or type name" % source
)
507 # value is a dictionary, check that each member is okay
508 for (key
, arg
) in value
.items():
509 check_name(expr_info
, "Member of %s" % source
, key
,
510 allow_optional
=allow_optional
)
511 if c_name(key
, False) == 'u' or c_name(key
, False).startswith('has_'):
512 raise QAPIExprError(expr_info
,
513 "Member of %s uses reserved name '%s'"
515 # Todo: allow dictionaries to represent default values of
516 # an optional argument.
517 check_type(expr_info
, "Member '%s' of %s" % (key
, source
), arg
,
519 allow_metas
=['built-in', 'union', 'alternate', 'struct',
523 def check_command(expr
, expr_info
):
524 name
= expr
['command']
526 check_type(expr_info
, "'data' for command '%s'" % name
,
527 expr
.get('data'), allow_dict
=True, allow_optional
=True,
528 allow_metas
=['struct'])
529 returns_meta
= ['union', 'struct']
530 if name
in returns_whitelist
:
531 returns_meta
+= ['built-in', 'alternate', 'enum']
532 check_type(expr_info
, "'returns' for command '%s'" % name
,
533 expr
.get('returns'), allow_array
=True,
534 allow_optional
=True, allow_metas
=returns_meta
)
537 def check_event(expr
, expr_info
):
542 check_type(expr_info
, "'data' for event '%s'" % name
,
543 expr
.get('data'), allow_dict
=True, allow_optional
=True,
544 allow_metas
=['struct'])
547 def check_union(expr
, expr_info
):
549 base
= expr
.get('base')
550 discriminator
= expr
.get('discriminator')
551 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 or dictionary 'base'.
567 check_type(expr_info
, "'base' for union '%s'" % name
,
568 base
, allow_dict
=True, allow_optional
=True,
569 allow_metas
=['struct'])
571 raise QAPIExprError(expr_info
,
572 "Flat union '%s' must have a base"
574 base_members
= find_base_members(base
)
577 # The value of member 'discriminator' must name a non-optional
578 # member of the base struct.
579 check_name(expr_info
, "Discriminator of flat union '%s'" % name
,
581 discriminator_type
= base_members
.get(discriminator
)
582 if not discriminator_type
:
583 raise QAPIExprError(expr_info
,
584 "Discriminator '%s' is not a member of base "
586 % (discriminator
, base
))
587 enum_define
= find_enum(discriminator_type
)
588 allow_metas
= ['struct']
589 # Do not allow string discriminator
591 raise QAPIExprError(expr_info
,
592 "Discriminator '%s' must be of enumeration "
593 "type" % discriminator
)
595 # Check every branch; don't allow an empty union
596 if len(members
) == 0:
597 raise QAPIExprError(expr_info
,
598 "Union '%s' cannot have empty 'data'" % name
)
599 for (key
, value
) in members
.items():
600 check_name(expr_info
, "Member of union '%s'" % name
, key
)
602 # Each value must name a known type
603 check_type(expr_info
, "Member '%s' of union '%s'" % (key
, name
),
604 value
, allow_array
=not base
, allow_metas
=allow_metas
)
606 # If the discriminator names an enum type, then all members
607 # of 'data' must also be members of the enum type.
609 if key
not in enum_define
['enum_values']:
610 raise QAPIExprError(expr_info
,
611 "Discriminator value '%s' is not found in "
613 (key
, enum_define
["enum_name"]))
616 def check_alternate(expr
, expr_info
):
617 name
= expr
['alternate']
618 members
= expr
['data']
621 # Check every branch; require at least two branches
623 raise QAPIExprError(expr_info
,
624 "Alternate '%s' should have at least two branches "
626 for (key
, value
) in members
.items():
627 check_name(expr_info
, "Member of alternate '%s'" % name
, key
)
629 # Ensure alternates have no type conflicts.
630 check_type(expr_info
, "Member '%s' of alternate '%s'" % (key
, name
),
632 allow_metas
=['built-in', 'union', 'struct', 'enum'])
633 qtype
= find_alternate_member_qtype(value
)
635 raise QAPIExprError(expr_info
,
636 "Alternate '%s' member '%s' cannot use "
637 "type '%s'" % (name
, key
, value
))
638 if qtype
in types_seen
:
639 raise QAPIExprError(expr_info
,
640 "Alternate '%s' member '%s' can't "
641 "be distinguished from member '%s'"
642 % (name
, key
, types_seen
[qtype
]))
643 types_seen
[qtype
] = key
646 def check_enum(expr
, expr_info
):
648 members
= expr
.get('data')
649 prefix
= expr
.get('prefix')
651 if not isinstance(members
, list):
652 raise QAPIExprError(expr_info
,
653 "Enum '%s' requires an array for 'data'" % name
)
654 if prefix
is not None and not isinstance(prefix
, str):
655 raise QAPIExprError(expr_info
,
656 "Enum '%s' requires a string for 'prefix'" % name
)
657 for member
in members
:
658 check_name(expr_info
, "Member of enum '%s'" % name
, member
,
662 def check_struct(expr
, expr_info
):
663 name
= expr
['struct']
664 members
= expr
['data']
666 check_type(expr_info
, "'data' for struct '%s'" % name
, members
,
667 allow_dict
=True, allow_optional
=True)
668 check_type(expr_info
, "'base' for struct '%s'" % name
, expr
.get('base'),
669 allow_metas
=['struct'])
672 def check_keys(expr_elem
, meta
, required
, optional
=[]):
673 expr
= expr_elem
['expr']
674 info
= expr_elem
['info']
676 if not isinstance(name
, str):
677 raise QAPIExprError(info
,
678 "'%s' key must have a string value" % meta
)
679 required
= required
+ [meta
]
680 for (key
, value
) in expr
.items():
681 if key
not in required
and key
not in optional
:
682 raise QAPIExprError(info
,
683 "Unknown key '%s' in %s '%s'"
685 if (key
== 'gen' or key
== 'success-response') and value
is not False:
686 raise QAPIExprError(info
,
687 "'%s' of %s '%s' should only use false value"
691 raise QAPIExprError(info
,
692 "Key '%s' is missing from %s '%s'"
696 def check_exprs(exprs
):
699 # Learn the types and check for valid expression keys
700 for builtin
in builtin_types
.keys():
701 all_names
[builtin
] = 'built-in'
702 for expr_elem
in exprs
:
703 expr
= expr_elem
['expr']
704 info
= expr_elem
['info']
706 check_keys(expr_elem
, 'enum', ['data'], ['prefix'])
707 add_enum(expr
['enum'], info
, expr
['data'])
708 elif 'union' in expr
:
709 check_keys(expr_elem
, 'union', ['data'],
710 ['base', 'discriminator'])
711 add_union(expr
, info
)
712 elif 'alternate' in expr
:
713 check_keys(expr_elem
, 'alternate', ['data'])
714 add_name(expr
['alternate'], info
, 'alternate')
715 elif 'struct' in expr
:
716 check_keys(expr_elem
, 'struct', ['data'], ['base'])
717 add_struct(expr
, info
)
718 elif 'command' in expr
:
719 check_keys(expr_elem
, 'command', [],
720 ['data', 'returns', 'gen', 'success-response'])
721 add_name(expr
['command'], info
, 'command')
722 elif 'event' in expr
:
723 check_keys(expr_elem
, 'event', [], ['data'])
724 add_name(expr
['event'], info
, 'event')
726 raise QAPIExprError(expr_elem
['info'],
727 "Expression is missing metatype")
729 # Try again for hidden UnionKind enum
730 for expr_elem
in exprs
:
731 expr
= expr_elem
['expr']
733 if not discriminator_find_enum_define(expr
):
734 add_enum('%sKind' % expr
['union'], expr_elem
['info'],
736 elif 'alternate' in expr
:
737 add_enum('%sKind' % expr
['alternate'], expr_elem
['info'],
740 # Validate that exprs make sense
741 for expr_elem
in exprs
:
742 expr
= expr_elem
['expr']
743 info
= expr_elem
['info']
746 check_enum(expr
, info
)
747 elif 'union' in expr
:
748 check_union(expr
, info
)
749 elif 'alternate' in expr
:
750 check_alternate(expr
, info
)
751 elif 'struct' in expr
:
752 check_struct(expr
, info
)
753 elif 'command' in expr
:
754 check_command(expr
, info
)
755 elif 'event' in expr
:
756 check_event(expr
, info
)
758 assert False, 'unexpected meta type'
764 # Schema compiler frontend
767 class QAPISchemaEntity(object):
768 def __init__(self
, name
, info
):
769 assert isinstance(name
, str)
771 # For explicitly defined entities, info points to the (explicit)
772 # definition. For builtins (and their arrays), info is None.
773 # For implicitly defined entities, info points to a place that
774 # triggered the implicit definition (there may be more than one
779 return c_name(self
.name
)
781 def check(self
, schema
):
784 def is_implicit(self
):
787 def visit(self
, visitor
):
791 class QAPISchemaVisitor(object):
792 def visit_begin(self
, schema
):
798 def visit_needed(self
, entity
):
799 # Default to visiting everything
802 def visit_builtin_type(self
, name
, info
, json_type
):
805 def visit_enum_type(self
, name
, info
, values
, prefix
):
808 def visit_array_type(self
, name
, info
, element_type
):
811 def visit_object_type(self
, name
, info
, base
, members
, variants
):
814 def visit_object_type_flat(self
, name
, info
, members
, variants
):
817 def visit_alternate_type(self
, name
, info
, variants
):
820 def visit_command(self
, name
, info
, arg_type
, ret_type
,
821 gen
, success_response
):
824 def visit_event(self
, name
, info
, arg_type
):
828 class QAPISchemaType(QAPISchemaEntity
):
829 # Return the C type for common use.
830 # For the types we commonly box, this is a pointer type.
834 # Return the C type to be used in a parameter list.
835 def c_param_type(self
):
838 # Return the C type to be used where we suppress boxing.
839 def c_unboxed_type(self
):
845 def alternate_qtype(self
):
847 'string': 'QTYPE_QSTRING',
848 'number': 'QTYPE_QFLOAT',
850 'boolean': 'QTYPE_QBOOL',
851 'object': 'QTYPE_QDICT'
853 return json2qtype
.get(self
.json_type())
856 class QAPISchemaBuiltinType(QAPISchemaType
):
857 def __init__(self
, name
, json_type
, c_type
):
858 QAPISchemaType
.__init
__(self
, name
, None)
859 assert not c_type
or isinstance(c_type
, str)
860 assert json_type
in ('string', 'number', 'int', 'boolean', 'null',
862 self
._json
_type
_name
= json_type
863 self
._c
_type
_name
= c_type
869 return self
._c
_type
_name
871 def c_param_type(self
):
872 if self
.name
== 'str':
873 return 'const ' + self
._c
_type
_name
874 return self
._c
_type
_name
877 return self
._json
_type
_name
879 def visit(self
, visitor
):
880 visitor
.visit_builtin_type(self
.name
, self
.info
, self
.json_type())
883 class QAPISchemaEnumType(QAPISchemaType
):
884 def __init__(self
, name
, info
, values
, prefix
):
885 QAPISchemaType
.__init
__(self
, name
, info
)
887 assert isinstance(v
, QAPISchemaMember
)
889 assert prefix
is None or isinstance(prefix
, str)
893 def check(self
, schema
):
895 for v
in self
.values
:
896 v
.check_clash(self
.info
, seen
)
898 def is_implicit(self
):
899 # See QAPISchema._make_implicit_enum_type()
900 return self
.name
.endswith('Kind')
903 return c_name(self
.name
)
905 def member_names(self
):
906 return [v
.name
for v
in self
.values
]
911 def visit(self
, visitor
):
912 visitor
.visit_enum_type(self
.name
, self
.info
,
913 self
.member_names(), self
.prefix
)
916 class QAPISchemaArrayType(QAPISchemaType
):
917 def __init__(self
, name
, info
, element_type
):
918 QAPISchemaType
.__init
__(self
, name
, info
)
919 assert isinstance(element_type
, str)
920 self
._element
_type
_name
= element_type
921 self
.element_type
= None
923 def check(self
, schema
):
924 self
.element_type
= schema
.lookup_type(self
._element
_type
_name
)
925 assert self
.element_type
927 def is_implicit(self
):
931 return c_name(self
.name
) + pointer_suffix
936 def visit(self
, visitor
):
937 visitor
.visit_array_type(self
.name
, self
.info
, self
.element_type
)
940 class QAPISchemaObjectType(QAPISchemaType
):
941 def __init__(self
, name
, info
, base
, local_members
, variants
):
942 # struct has local_members, optional base, and no variants
943 # flat union has base, variants, and no local_members
944 # simple union has local_members, variants, and no base
945 QAPISchemaType
.__init
__(self
, name
, info
)
946 assert base
is None or isinstance(base
, str)
947 for m
in local_members
:
948 assert isinstance(m
, QAPISchemaObjectTypeMember
)
950 if variants
is not None:
951 assert isinstance(variants
, QAPISchemaObjectTypeVariants
)
952 variants
.set_owner(name
)
953 self
._base
_name
= base
955 self
.local_members
= local_members
956 self
.variants
= variants
959 def check(self
, schema
):
960 if self
.members
is False: # check for cycles
961 raise QAPIExprError(self
.info
,
962 "Object %s contains itself" % self
.name
)
965 self
.members
= False # mark as being checked
968 self
.base
= schema
.lookup_type(self
._base
_name
)
969 assert isinstance(self
.base
, QAPISchemaObjectType
)
970 self
.base
.check(schema
)
971 self
.base
.check_clash(schema
, self
.info
, seen
)
972 for m
in self
.local_members
:
974 m
.check_clash(self
.info
, seen
)
975 self
.members
= seen
.values()
977 self
.variants
.check(schema
, seen
)
978 assert self
.variants
.tag_member
in self
.members
979 self
.variants
.check_clash(schema
, self
.info
, seen
)
981 # Check that the members of this type do not cause duplicate JSON members,
982 # and update seen to track the members seen so far. Report any errors
983 # on behalf of info, which is not necessarily self.info
984 def check_clash(self
, schema
, info
, seen
):
985 assert not self
.variants
# not implemented
986 for m
in self
.members
:
987 m
.check_clash(info
, seen
)
989 def is_implicit(self
):
990 # See QAPISchema._make_implicit_object_type(), as well as
992 return self
.name
.startswith('q_')
995 return QAPISchemaType
.c_name(self
)
998 assert not self
.is_implicit()
999 return c_name(self
.name
) + pointer_suffix
1001 def c_unboxed_type(self
):
1002 return c_name(self
.name
)
1004 def json_type(self
):
1007 def visit(self
, visitor
):
1008 visitor
.visit_object_type(self
.name
, self
.info
,
1009 self
.base
, self
.local_members
, self
.variants
)
1010 visitor
.visit_object_type_flat(self
.name
, self
.info
,
1011 self
.members
, self
.variants
)
1014 class QAPISchemaMember(object):
1017 def __init__(self
, name
):
1018 assert isinstance(name
, str)
1022 def set_owner(self
, name
):
1023 assert not self
.owner
1026 def check_clash(self
, info
, seen
):
1027 cname
= c_name(self
.name
)
1028 if cname
.lower() != cname
and self
.owner
not in case_whitelist
:
1029 raise QAPIExprError(info
,
1030 "%s should not use uppercase" % self
.describe())
1032 raise QAPIExprError(info
,
1033 "%s collides with %s"
1034 % (self
.describe(), seen
[cname
].describe()))
1037 def _pretty_owner(self
):
1039 if owner
.startswith('q_obj_'):
1040 # See QAPISchema._make_implicit_object_type() - reverse the
1041 # mapping there to create a nice human-readable description
1043 if owner
.endswith('-arg'):
1044 return '(parameter of %s)' % owner
[:-4]
1045 elif owner
.endswith('-base'):
1046 return '(base of %s)' % owner
[:-5]
1048 assert owner
.endswith('-wrapper')
1049 # Unreachable and not implemented
1051 if owner
.endswith('Kind'):
1052 # See QAPISchema._make_implicit_enum_type()
1053 return '(branch of %s)' % owner
[:-4]
1054 return '(%s of %s)' % (self
.role
, owner
)
1057 return "'%s' %s" % (self
.name
, self
._pretty
_owner
())
1060 class QAPISchemaObjectTypeMember(QAPISchemaMember
):
1061 def __init__(self
, name
, typ
, optional
):
1062 QAPISchemaMember
.__init
__(self
, name
)
1063 assert isinstance(typ
, str)
1064 assert isinstance(optional
, bool)
1065 self
._type
_name
= typ
1067 self
.optional
= optional
1069 def check(self
, schema
):
1071 self
.type = schema
.lookup_type(self
._type
_name
)
1075 class QAPISchemaObjectTypeVariants(object):
1076 def __init__(self
, tag_name
, tag_member
, variants
):
1077 # Flat unions pass tag_name but not tag_member.
1078 # Simple unions and alternates pass tag_member but not tag_name.
1079 # After check(), tag_member is always set, and tag_name remains
1080 # a reliable witness of being used by a flat union.
1081 assert bool(tag_member
) != bool(tag_name
)
1082 assert (isinstance(tag_name
, str) or
1083 isinstance(tag_member
, QAPISchemaObjectTypeMember
))
1084 assert len(variants
) > 0
1086 assert isinstance(v
, QAPISchemaObjectTypeVariant
)
1087 self
.tag_name
= tag_name
1088 self
.tag_member
= tag_member
1089 self
.variants
= variants
1091 def set_owner(self
, name
):
1092 for v
in self
.variants
:
1095 def check(self
, schema
, seen
):
1096 if not self
.tag_member
: # flat union
1097 self
.tag_member
= seen
[c_name(self
.tag_name
)]
1098 assert self
.tag_name
== self
.tag_member
.name
1099 assert isinstance(self
.tag_member
.type, QAPISchemaEnumType
)
1100 for v
in self
.variants
:
1102 # Union names must match enum values; alternate names are
1103 # checked separately. Use 'seen' to tell the two apart.
1105 assert v
.name
in self
.tag_member
.type.member_names()
1106 assert isinstance(v
.type, QAPISchemaObjectType
)
1107 v
.type.check(schema
)
1109 def check_clash(self
, schema
, info
, seen
):
1110 for v
in self
.variants
:
1111 # Reset seen map for each variant, since qapi names from one
1112 # branch do not affect another branch
1113 assert isinstance(v
.type, QAPISchemaObjectType
)
1114 v
.type.check_clash(schema
, info
, dict(seen
))
1117 class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember
):
1120 def __init__(self
, name
, typ
):
1121 QAPISchemaObjectTypeMember
.__init
__(self
, name
, typ
, False)
1124 class QAPISchemaAlternateType(QAPISchemaType
):
1125 def __init__(self
, name
, info
, variants
):
1126 QAPISchemaType
.__init
__(self
, name
, info
)
1127 assert isinstance(variants
, QAPISchemaObjectTypeVariants
)
1128 assert not variants
.tag_name
1129 variants
.set_owner(name
)
1130 variants
.tag_member
.set_owner(self
.name
)
1131 self
.variants
= variants
1133 def check(self
, schema
):
1134 self
.variants
.tag_member
.check(schema
)
1135 # Not calling self.variants.check_clash(), because there's nothing
1137 self
.variants
.check(schema
, {})
1138 # Alternate branch names have no relation to the tag enum values;
1139 # so we have to check for potential name collisions ourselves.
1141 for v
in self
.variants
.variants
:
1142 v
.check_clash(self
.info
, seen
)
1145 return c_name(self
.name
) + pointer_suffix
1147 def json_type(self
):
1150 def visit(self
, visitor
):
1151 visitor
.visit_alternate_type(self
.name
, self
.info
, self
.variants
)
1154 class QAPISchemaCommand(QAPISchemaEntity
):
1155 def __init__(self
, name
, info
, arg_type
, ret_type
, gen
, success_response
):
1156 QAPISchemaEntity
.__init
__(self
, name
, info
)
1157 assert not arg_type
or isinstance(arg_type
, str)
1158 assert not ret_type
or isinstance(ret_type
, str)
1159 self
._arg
_type
_name
= arg_type
1160 self
.arg_type
= None
1161 self
._ret
_type
_name
= ret_type
1162 self
.ret_type
= None
1164 self
.success_response
= success_response
1166 def check(self
, schema
):
1167 if self
._arg
_type
_name
:
1168 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1169 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1170 assert not self
.arg_type
.variants
# not implemented
1171 if self
._ret
_type
_name
:
1172 self
.ret_type
= schema
.lookup_type(self
._ret
_type
_name
)
1173 assert isinstance(self
.ret_type
, QAPISchemaType
)
1175 def visit(self
, visitor
):
1176 visitor
.visit_command(self
.name
, self
.info
,
1177 self
.arg_type
, self
.ret_type
,
1178 self
.gen
, self
.success_response
)
1181 class QAPISchemaEvent(QAPISchemaEntity
):
1182 def __init__(self
, name
, info
, arg_type
):
1183 QAPISchemaEntity
.__init
__(self
, name
, info
)
1184 assert not arg_type
or isinstance(arg_type
, str)
1185 self
._arg
_type
_name
= arg_type
1186 self
.arg_type
= None
1188 def check(self
, schema
):
1189 if self
._arg
_type
_name
:
1190 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1191 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1192 assert not self
.arg_type
.variants
# not implemented
1194 def visit(self
, visitor
):
1195 visitor
.visit_event(self
.name
, self
.info
, self
.arg_type
)
1198 class QAPISchema(object):
1199 def __init__(self
, fname
):
1201 self
.exprs
= check_exprs(QAPISchemaParser(open(fname
, "r")).exprs
)
1202 self
._entity
_dict
= {}
1203 self
._predefining
= True
1204 self
._def
_predefineds
()
1205 self
._predefining
= False
1208 except (QAPISchemaError
, QAPIExprError
) as err
:
1209 print >>sys
.stderr
, err
1212 def _def_entity(self
, ent
):
1213 # Only the predefined types are allowed to not have info
1214 assert ent
.info
or self
._predefining
1215 assert ent
.name
not in self
._entity
_dict
1216 self
._entity
_dict
[ent
.name
] = ent
1218 def lookup_entity(self
, name
, typ
=None):
1219 ent
= self
._entity
_dict
.get(name
)
1220 if typ
and not isinstance(ent
, typ
):
1224 def lookup_type(self
, name
):
1225 return self
.lookup_entity(name
, QAPISchemaType
)
1227 def _def_builtin_type(self
, name
, json_type
, c_type
):
1228 self
._def
_entity
(QAPISchemaBuiltinType(name
, json_type
, c_type
))
1229 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1230 # qapi-types.h from a single .c, all arrays of builtins must be
1231 # declared in the first file whether or not they are used. Nicer
1232 # would be to use lazy instantiation, while figuring out how to
1233 # avoid compilation issues with multiple qapi-types.h.
1234 self
._make
_array
_type
(name
, None)
1236 def _def_predefineds(self
):
1237 for t
in [('str', 'string', 'char' + pointer_suffix
),
1238 ('number', 'number', 'double'),
1239 ('int', 'int', 'int64_t'),
1240 ('int8', 'int', 'int8_t'),
1241 ('int16', 'int', 'int16_t'),
1242 ('int32', 'int', 'int32_t'),
1243 ('int64', 'int', 'int64_t'),
1244 ('uint8', 'int', 'uint8_t'),
1245 ('uint16', 'int', 'uint16_t'),
1246 ('uint32', 'int', 'uint32_t'),
1247 ('uint64', 'int', 'uint64_t'),
1248 ('size', 'int', 'uint64_t'),
1249 ('bool', 'boolean', 'bool'),
1250 ('any', 'value', 'QObject' + pointer_suffix
)]:
1251 self
._def
_builtin
_type
(*t
)
1252 self
.the_empty_object_type
= QAPISchemaObjectType('q_empty', None,
1254 self
._def
_entity
(self
.the_empty_object_type
)
1255 qtype_values
= self
._make
_enum
_members
(['none', 'qnull', 'qint',
1256 'qstring', 'qdict', 'qlist',
1258 self
._def
_entity
(QAPISchemaEnumType('QType', None, qtype_values
,
1261 def _make_enum_members(self
, values
):
1262 return [QAPISchemaMember(v
) for v
in values
]
1264 def _make_implicit_enum_type(self
, name
, info
, values
):
1265 # See also QAPISchemaObjectTypeMember._pretty_owner()
1266 name
= name
+ 'Kind' # Use namespace reserved by add_name()
1267 self
._def
_entity
(QAPISchemaEnumType(
1268 name
, info
, self
._make
_enum
_members
(values
), None))
1271 def _make_array_type(self
, element_type
, info
):
1272 name
= element_type
+ 'List' # Use namespace reserved by add_name()
1273 if not self
.lookup_type(name
):
1274 self
._def
_entity
(QAPISchemaArrayType(name
, info
, element_type
))
1277 def _make_implicit_object_type(self
, name
, info
, role
, members
):
1280 # See also QAPISchemaObjectTypeMember._pretty_owner()
1281 name
= 'q_obj_%s-%s' % (name
, role
)
1282 if not self
.lookup_entity(name
, QAPISchemaObjectType
):
1283 self
._def
_entity
(QAPISchemaObjectType(name
, info
, None,
1287 def _def_enum_type(self
, expr
, info
):
1290 prefix
= expr
.get('prefix')
1291 self
._def
_entity
(QAPISchemaEnumType(
1292 name
, info
, self
._make
_enum
_members
(data
), prefix
))
1294 def _make_member(self
, name
, typ
, info
):
1296 if name
.startswith('*'):
1299 if isinstance(typ
, list):
1300 assert len(typ
) == 1
1301 typ
= self
._make
_array
_type
(typ
[0], info
)
1302 return QAPISchemaObjectTypeMember(name
, typ
, optional
)
1304 def _make_members(self
, data
, info
):
1305 return [self
._make
_member
(key
, value
, info
)
1306 for (key
, value
) in data
.iteritems()]
1308 def _def_struct_type(self
, expr
, info
):
1309 name
= expr
['struct']
1310 base
= expr
.get('base')
1312 self
._def
_entity
(QAPISchemaObjectType(name
, info
, base
,
1313 self
._make
_members
(data
, info
),
1316 def _make_variant(self
, case
, typ
):
1317 return QAPISchemaObjectTypeVariant(case
, typ
)
1319 def _make_simple_variant(self
, case
, typ
, info
):
1320 if isinstance(typ
, list):
1321 assert len(typ
) == 1
1322 typ
= self
._make
_array
_type
(typ
[0], info
)
1323 typ
= self
._make
_implicit
_object
_type
(
1324 typ
, info
, 'wrapper', [self
._make
_member
('data', typ
, info
)])
1325 return QAPISchemaObjectTypeVariant(case
, typ
)
1327 def _def_union_type(self
, expr
, info
):
1328 name
= expr
['union']
1330 base
= expr
.get('base')
1331 tag_name
= expr
.get('discriminator')
1333 if isinstance(base
, dict):
1334 base
= (self
._make
_implicit
_object
_type
(
1335 name
, info
, 'base', self
._make
_members
(base
, info
)))
1337 variants
= [self
._make
_variant
(key
, value
)
1338 for (key
, value
) in data
.iteritems()]
1341 variants
= [self
._make
_simple
_variant
(key
, value
, info
)
1342 for (key
, value
) in data
.iteritems()]
1343 typ
= self
._make
_implicit
_enum
_type
(name
, info
,
1344 [v
.name
for v
in variants
])
1345 tag_member
= QAPISchemaObjectTypeMember('type', typ
, False)
1346 members
= [tag_member
]
1348 QAPISchemaObjectType(name
, info
, base
, members
,
1349 QAPISchemaObjectTypeVariants(tag_name
,
1353 def _def_alternate_type(self
, expr
, info
):
1354 name
= expr
['alternate']
1356 variants
= [self
._make
_variant
(key
, value
)
1357 for (key
, value
) in data
.iteritems()]
1358 tag_member
= QAPISchemaObjectTypeMember('type', 'QType', False)
1360 QAPISchemaAlternateType(name
, info
,
1361 QAPISchemaObjectTypeVariants(None,
1365 def _def_command(self
, expr
, info
):
1366 name
= expr
['command']
1367 data
= expr
.get('data')
1368 rets
= expr
.get('returns')
1369 gen
= expr
.get('gen', True)
1370 success_response
= expr
.get('success-response', True)
1371 if isinstance(data
, OrderedDict
):
1372 data
= self
._make
_implicit
_object
_type
(
1373 name
, info
, 'arg', self
._make
_members
(data
, info
))
1374 if isinstance(rets
, list):
1375 assert len(rets
) == 1
1376 rets
= self
._make
_array
_type
(rets
[0], info
)
1377 self
._def
_entity
(QAPISchemaCommand(name
, info
, data
, rets
, gen
,
1380 def _def_event(self
, expr
, info
):
1381 name
= expr
['event']
1382 data
= expr
.get('data')
1383 if isinstance(data
, OrderedDict
):
1384 data
= self
._make
_implicit
_object
_type
(
1385 name
, info
, 'arg', self
._make
_members
(data
, info
))
1386 self
._def
_entity
(QAPISchemaEvent(name
, info
, data
))
1388 def _def_exprs(self
):
1389 for expr_elem
in self
.exprs
:
1390 expr
= expr_elem
['expr']
1391 info
= expr_elem
['info']
1393 self
._def
_enum
_type
(expr
, info
)
1394 elif 'struct' in expr
:
1395 self
._def
_struct
_type
(expr
, info
)
1396 elif 'union' in expr
:
1397 self
._def
_union
_type
(expr
, info
)
1398 elif 'alternate' in expr
:
1399 self
._def
_alternate
_type
(expr
, info
)
1400 elif 'command' in expr
:
1401 self
._def
_command
(expr
, info
)
1402 elif 'event' in expr
:
1403 self
._def
_event
(expr
, info
)
1408 for ent
in self
._entity
_dict
.values():
1411 def visit(self
, visitor
):
1412 visitor
.visit_begin(self
)
1413 for (name
, entity
) in sorted(self
._entity
_dict
.items()):
1414 if visitor
.visit_needed(entity
):
1415 entity
.visit(visitor
)
1420 # Code generation helpers
1423 def camel_case(name
):
1427 if ch
in ['_', '-']:
1430 new_name
+= ch
.upper()
1433 new_name
+= ch
.lower()
1437 # ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1438 # ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1439 # ENUM24_Name -> ENUM24_NAME
1440 def camel_to_upper(value
):
1441 c_fun_str
= c_name(value
, False)
1449 # When c is upper and no "_" appears before, do more checks
1450 if c
.isupper() and (i
> 0) and c_fun_str
[i
- 1] != "_":
1451 if i
< l
- 1 and c_fun_str
[i
+ 1].islower():
1453 elif c_fun_str
[i
- 1].isdigit():
1456 return new_name
.lstrip('_').upper()
1459 def c_enum_const(type_name
, const_name
, prefix
=None):
1460 if prefix
is not None:
1462 return camel_to_upper(type_name
) + '_' + c_name(const_name
, False).upper()
1464 c_name_trans
= string
.maketrans('.-', '__')
1467 # Map @name to a valid C identifier.
1468 # If @protect, avoid returning certain ticklish identifiers (like
1469 # C keywords) by prepending "q_".
1471 # Used for converting 'name' from a 'name':'type' qapi definition
1472 # into a generated struct member, as well as converting type names
1473 # into substrings of a generated C function name.
1474 # '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1475 # protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
1476 def c_name(name
, protect
=True):
1477 # ANSI X3J11/88-090, 3.1.1
1478 c89_words
= set(['auto', 'break', 'case', 'char', 'const', 'continue',
1479 'default', 'do', 'double', 'else', 'enum', 'extern',
1480 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1481 'return', 'short', 'signed', 'sizeof', 'static',
1482 'struct', 'switch', 'typedef', 'union', 'unsigned',
1483 'void', 'volatile', 'while'])
1484 # ISO/IEC 9899:1999, 6.4.1
1485 c99_words
= set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1486 # ISO/IEC 9899:2011, 6.4.1
1487 c11_words
= set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1488 '_Noreturn', '_Static_assert', '_Thread_local'])
1489 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1491 gcc_words
= set(['asm', 'typeof'])
1492 # C++ ISO/IEC 14882:2003 2.11
1493 cpp_words
= set(['bool', 'catch', 'class', 'const_cast', 'delete',
1494 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1495 'namespace', 'new', 'operator', 'private', 'protected',
1496 'public', 'reinterpret_cast', 'static_cast', 'template',
1497 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1498 'using', 'virtual', 'wchar_t',
1499 # alternative representations
1500 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1501 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
1502 # namespace pollution:
1503 polluted_words
= set(['unix', 'errno', 'mips', 'sparc'])
1504 name
= name
.translate(c_name_trans
)
1505 if protect
and (name
in c89_words | c99_words | c11_words | gcc_words
1506 | cpp_words | polluted_words
):
1510 eatspace
= '\033EATSPACE.'
1511 pointer_suffix
= ' *' + eatspace
1514 def genindent(count
):
1516 for _
in range(count
):
1523 def push_indent(indent_amount
=4):
1525 indent_level
+= indent_amount
1528 def pop_indent(indent_amount
=4):
1530 indent_level
-= indent_amount
1533 # Generate @code with @kwds interpolated.
1534 # Obey indent_level, and strip eatspace.
1535 def cgen(code
, **kwds
):
1538 indent
= genindent(indent_level
)
1539 # re.subn() lacks flags support before Python 2.7, use re.compile()
1540 raw
= re
.subn(re
.compile("^.", re
.MULTILINE
),
1541 indent
+ r
'\g<0>', raw
)
1543 return re
.sub(re
.escape(eatspace
) + ' *', '', raw
)
1546 def mcgen(code
, **kwds
):
1549 return cgen(code
, **kwds
)
1552 def guardname(filename
):
1553 return c_name(filename
, protect
=False).upper()
1556 def guardstart(name
):
1563 name
=guardname(name
))
1569 #endif /* %(name)s */
1572 name
=guardname(name
))
1575 def gen_enum_lookup(name
, values
, prefix
=None):
1578 const char *const %(c_name)s_lookup[] = {
1580 c_name
=c_name(name
))
1581 for value
in values
:
1582 index
= c_enum_const(name
, value
, prefix
)
1584 [%(index)s] = "%(value)s",
1586 index
=index
, value
=value
)
1588 max_index
= c_enum_const(name
, '_MAX', prefix
)
1590 [%(max_index)s] = NULL,
1593 max_index
=max_index
)
1597 def gen_enum(name
, values
, prefix
=None):
1598 # append automatically generated _MAX value
1599 enum_values
= values
+ ['_MAX']
1603 typedef enum %(c_name)s {
1605 c_name
=c_name(name
))
1608 for value
in enum_values
:
1612 c_enum
=c_enum_const(name
, value
, prefix
),
1619 c_name
=c_name(name
))
1623 extern const char *const %(c_name)s_lookup[];
1625 c_name
=c_name(name
))
1629 def gen_params(arg_type
, extra
):
1632 assert not arg_type
.variants
1635 for memb
in arg_type
.members
:
1639 ret
+= 'bool has_%s, ' % c_name(memb
.name
)
1640 ret
+= '%s %s' % (memb
.type.c_param_type(), c_name(memb
.name
))
1646 def gen_err_check():
1655 # Common command line parsing
1659 def parse_command_line(extra_options
="", extra_long_options
=[]):
1662 opts
, args
= getopt
.gnu_getopt(sys
.argv
[1:],
1663 "chp:o:" + extra_options
,
1664 ["source", "header", "prefix=",
1665 "output-dir="] + extra_long_options
)
1666 except getopt
.GetoptError
as err
:
1667 print >>sys
.stderr
, "%s: %s" % (sys
.argv
[0], str(err
))
1678 if o
in ("-p", "--prefix"):
1679 match
= re
.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a
)
1680 if match
.end() != len(a
):
1681 print >>sys
.stderr
, \
1682 "%s: 'funny character '%s' in argument of --prefix" \
1683 % (sys
.argv
[0], a
[match
.end()])
1686 elif o
in ("-o", "--output-dir"):
1687 output_dir
= a
+ "/"
1688 elif o
in ("-c", "--source"):
1690 elif o
in ("-h", "--header"):
1693 extra_opts
.append(oa
)
1695 if not do_c
and not do_h
:
1700 print >>sys
.stderr
, "%s: need exactly one argument" % sys
.argv
[0]
1704 return (fname
, output_dir
, do_c
, do_h
, prefix
, extra_opts
)
1707 # Generate output files with boilerplate
1711 def open_output(output_dir
, do_c
, do_h
, prefix
, c_file
, h_file
,
1712 c_comment
, h_comment
):
1713 guard
= guardname(prefix
+ h_file
)
1714 c_file
= output_dir
+ prefix
+ c_file
1715 h_file
= output_dir
+ prefix
+ h_file
1719 os
.makedirs(output_dir
)
1720 except os
.error
as e
:
1721 if e
.errno
!= errno
.EEXIST
:
1724 def maybe_open(really
, name
, opt
):
1726 return open(name
, opt
)
1729 return StringIO
.StringIO()
1731 fdef
= maybe_open(do_c
, c_file
, 'w')
1732 fdecl
= maybe_open(do_h
, h_file
, 'w')
1734 fdef
.write(mcgen('''
1735 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1740 fdecl
.write(mcgen('''
1741 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1747 comment
=h_comment
, guard
=guard
))
1749 return (fdef
, fdecl
)
1752 def close_output(fdef
, fdecl
):