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"]))
615 # If discriminator is user-defined, ensure all values are covered
617 for value
in enum_define
['enum_values']:
618 if value
not in members
.keys():
619 raise QAPIExprError(expr_info
,
620 "Union '%s' data missing '%s' branch"
624 def check_alternate(expr
, expr_info
):
625 name
= expr
['alternate']
626 members
= expr
['data']
629 # Check every branch; require at least two branches
631 raise QAPIExprError(expr_info
,
632 "Alternate '%s' should have at least two branches "
634 for (key
, value
) in members
.items():
635 check_name(expr_info
, "Member of alternate '%s'" % name
, key
)
637 # Ensure alternates have no type conflicts.
638 check_type(expr_info
, "Member '%s' of alternate '%s'" % (key
, name
),
640 allow_metas
=['built-in', 'union', 'struct', 'enum'])
641 qtype
= find_alternate_member_qtype(value
)
643 raise QAPIExprError(expr_info
,
644 "Alternate '%s' member '%s' cannot use "
645 "type '%s'" % (name
, key
, value
))
646 if qtype
in types_seen
:
647 raise QAPIExprError(expr_info
,
648 "Alternate '%s' member '%s' can't "
649 "be distinguished from member '%s'"
650 % (name
, key
, types_seen
[qtype
]))
651 types_seen
[qtype
] = key
654 def check_enum(expr
, expr_info
):
656 members
= expr
.get('data')
657 prefix
= expr
.get('prefix')
659 if not isinstance(members
, list):
660 raise QAPIExprError(expr_info
,
661 "Enum '%s' requires an array for 'data'" % name
)
662 if prefix
is not None and not isinstance(prefix
, str):
663 raise QAPIExprError(expr_info
,
664 "Enum '%s' requires a string for 'prefix'" % name
)
665 for member
in members
:
666 check_name(expr_info
, "Member of enum '%s'" % name
, member
,
670 def check_struct(expr
, expr_info
):
671 name
= expr
['struct']
672 members
= expr
['data']
674 check_type(expr_info
, "'data' for struct '%s'" % name
, members
,
675 allow_dict
=True, allow_optional
=True)
676 check_type(expr_info
, "'base' for struct '%s'" % name
, expr
.get('base'),
677 allow_metas
=['struct'])
680 def check_keys(expr_elem
, meta
, required
, optional
=[]):
681 expr
= expr_elem
['expr']
682 info
= expr_elem
['info']
684 if not isinstance(name
, str):
685 raise QAPIExprError(info
,
686 "'%s' key must have a string value" % meta
)
687 required
= required
+ [meta
]
688 for (key
, value
) in expr
.items():
689 if key
not in required
and key
not in optional
:
690 raise QAPIExprError(info
,
691 "Unknown key '%s' in %s '%s'"
693 if (key
== 'gen' or key
== 'success-response') and value
is not False:
694 raise QAPIExprError(info
,
695 "'%s' of %s '%s' should only use false value"
699 raise QAPIExprError(info
,
700 "Key '%s' is missing from %s '%s'"
704 def check_exprs(exprs
):
707 # Learn the types and check for valid expression keys
708 for builtin
in builtin_types
.keys():
709 all_names
[builtin
] = 'built-in'
710 for expr_elem
in exprs
:
711 expr
= expr_elem
['expr']
712 info
= expr_elem
['info']
714 check_keys(expr_elem
, 'enum', ['data'], ['prefix'])
715 add_enum(expr
['enum'], info
, expr
['data'])
716 elif 'union' in expr
:
717 check_keys(expr_elem
, 'union', ['data'],
718 ['base', 'discriminator'])
719 add_union(expr
, info
)
720 elif 'alternate' in expr
:
721 check_keys(expr_elem
, 'alternate', ['data'])
722 add_name(expr
['alternate'], info
, 'alternate')
723 elif 'struct' in expr
:
724 check_keys(expr_elem
, 'struct', ['data'], ['base'])
725 add_struct(expr
, info
)
726 elif 'command' in expr
:
727 check_keys(expr_elem
, 'command', [],
728 ['data', 'returns', 'gen', 'success-response'])
729 add_name(expr
['command'], info
, 'command')
730 elif 'event' in expr
:
731 check_keys(expr_elem
, 'event', [], ['data'])
732 add_name(expr
['event'], info
, 'event')
734 raise QAPIExprError(expr_elem
['info'],
735 "Expression is missing metatype")
737 # Try again for hidden UnionKind enum
738 for expr_elem
in exprs
:
739 expr
= expr_elem
['expr']
741 if not discriminator_find_enum_define(expr
):
742 add_enum('%sKind' % expr
['union'], expr_elem
['info'],
744 elif 'alternate' in expr
:
745 add_enum('%sKind' % expr
['alternate'], expr_elem
['info'],
748 # Validate that exprs make sense
749 for expr_elem
in exprs
:
750 expr
= expr_elem
['expr']
751 info
= expr_elem
['info']
754 check_enum(expr
, info
)
755 elif 'union' in expr
:
756 check_union(expr
, info
)
757 elif 'alternate' in expr
:
758 check_alternate(expr
, info
)
759 elif 'struct' in expr
:
760 check_struct(expr
, info
)
761 elif 'command' in expr
:
762 check_command(expr
, info
)
763 elif 'event' in expr
:
764 check_event(expr
, info
)
766 assert False, 'unexpected meta type'
772 # Schema compiler frontend
775 class QAPISchemaEntity(object):
776 def __init__(self
, name
, info
):
777 assert isinstance(name
, str)
779 # For explicitly defined entities, info points to the (explicit)
780 # definition. For builtins (and their arrays), info is None.
781 # For implicitly defined entities, info points to a place that
782 # triggered the implicit definition (there may be more than one
787 return c_name(self
.name
)
789 def check(self
, schema
):
792 def is_implicit(self
):
795 def visit(self
, visitor
):
799 class QAPISchemaVisitor(object):
800 def visit_begin(self
, schema
):
806 def visit_needed(self
, entity
):
807 # Default to visiting everything
810 def visit_builtin_type(self
, name
, info
, json_type
):
813 def visit_enum_type(self
, name
, info
, values
, prefix
):
816 def visit_array_type(self
, name
, info
, element_type
):
819 def visit_object_type(self
, name
, info
, base
, members
, variants
):
822 def visit_object_type_flat(self
, name
, info
, members
, variants
):
825 def visit_alternate_type(self
, name
, info
, variants
):
828 def visit_command(self
, name
, info
, arg_type
, ret_type
,
829 gen
, success_response
):
832 def visit_event(self
, name
, info
, arg_type
):
836 class QAPISchemaType(QAPISchemaEntity
):
837 # Return the C type for common use.
838 # For the types we commonly box, this is a pointer type.
842 # Return the C type to be used in a parameter list.
843 def c_param_type(self
):
846 # Return the C type to be used where we suppress boxing.
847 def c_unboxed_type(self
):
853 def alternate_qtype(self
):
855 'string': 'QTYPE_QSTRING',
856 'number': 'QTYPE_QFLOAT',
858 'boolean': 'QTYPE_QBOOL',
859 'object': 'QTYPE_QDICT'
861 return json2qtype
.get(self
.json_type())
864 class QAPISchemaBuiltinType(QAPISchemaType
):
865 def __init__(self
, name
, json_type
, c_type
):
866 QAPISchemaType
.__init
__(self
, name
, None)
867 assert not c_type
or isinstance(c_type
, str)
868 assert json_type
in ('string', 'number', 'int', 'boolean', 'null',
870 self
._json
_type
_name
= json_type
871 self
._c
_type
_name
= c_type
877 return self
._c
_type
_name
879 def c_param_type(self
):
880 if self
.name
== 'str':
881 return 'const ' + self
._c
_type
_name
882 return self
._c
_type
_name
885 return self
._json
_type
_name
887 def visit(self
, visitor
):
888 visitor
.visit_builtin_type(self
.name
, self
.info
, self
.json_type())
891 class QAPISchemaEnumType(QAPISchemaType
):
892 def __init__(self
, name
, info
, values
, prefix
):
893 QAPISchemaType
.__init
__(self
, name
, info
)
895 assert isinstance(v
, QAPISchemaMember
)
897 assert prefix
is None or isinstance(prefix
, str)
901 def check(self
, schema
):
903 for v
in self
.values
:
904 v
.check_clash(self
.info
, seen
)
906 def is_implicit(self
):
907 # See QAPISchema._make_implicit_enum_type()
908 return self
.name
.endswith('Kind')
911 return c_name(self
.name
)
913 def member_names(self
):
914 return [v
.name
for v
in self
.values
]
919 def visit(self
, visitor
):
920 visitor
.visit_enum_type(self
.name
, self
.info
,
921 self
.member_names(), self
.prefix
)
924 class QAPISchemaArrayType(QAPISchemaType
):
925 def __init__(self
, name
, info
, element_type
):
926 QAPISchemaType
.__init
__(self
, name
, info
)
927 assert isinstance(element_type
, str)
928 self
._element
_type
_name
= element_type
929 self
.element_type
= None
931 def check(self
, schema
):
932 self
.element_type
= schema
.lookup_type(self
._element
_type
_name
)
933 assert self
.element_type
935 def is_implicit(self
):
939 return c_name(self
.name
) + pointer_suffix
944 def visit(self
, visitor
):
945 visitor
.visit_array_type(self
.name
, self
.info
, self
.element_type
)
948 class QAPISchemaObjectType(QAPISchemaType
):
949 def __init__(self
, name
, info
, base
, local_members
, variants
):
950 # struct has local_members, optional base, and no variants
951 # flat union has base, variants, and no local_members
952 # simple union has local_members, variants, and no base
953 QAPISchemaType
.__init
__(self
, name
, info
)
954 assert base
is None or isinstance(base
, str)
955 for m
in local_members
:
956 assert isinstance(m
, QAPISchemaObjectTypeMember
)
958 if variants
is not None:
959 assert isinstance(variants
, QAPISchemaObjectTypeVariants
)
960 variants
.set_owner(name
)
961 self
._base
_name
= base
963 self
.local_members
= local_members
964 self
.variants
= variants
967 def check(self
, schema
):
968 if self
.members
is False: # check for cycles
969 raise QAPIExprError(self
.info
,
970 "Object %s contains itself" % self
.name
)
973 self
.members
= False # mark as being checked
976 self
.base
= schema
.lookup_type(self
._base
_name
)
977 assert isinstance(self
.base
, QAPISchemaObjectType
)
978 self
.base
.check(schema
)
979 self
.base
.check_clash(schema
, self
.info
, seen
)
980 for m
in self
.local_members
:
982 m
.check_clash(self
.info
, seen
)
983 self
.members
= seen
.values()
985 self
.variants
.check(schema
, seen
)
986 assert self
.variants
.tag_member
in self
.members
987 self
.variants
.check_clash(schema
, self
.info
, seen
)
989 # Check that the members of this type do not cause duplicate JSON members,
990 # and update seen to track the members seen so far. Report any errors
991 # on behalf of info, which is not necessarily self.info
992 def check_clash(self
, schema
, info
, seen
):
993 assert not self
.variants
# not implemented
994 for m
in self
.members
:
995 m
.check_clash(info
, seen
)
997 def is_implicit(self
):
998 # See QAPISchema._make_implicit_object_type(), as well as
1000 return self
.name
.startswith('q_')
1003 assert self
.name
!= 'q_empty'
1004 return QAPISchemaType
.c_name(self
)
1007 assert not self
.is_implicit()
1008 return c_name(self
.name
) + pointer_suffix
1010 def c_unboxed_type(self
):
1011 return c_name(self
.name
)
1013 def json_type(self
):
1016 def visit(self
, visitor
):
1017 visitor
.visit_object_type(self
.name
, self
.info
,
1018 self
.base
, self
.local_members
, self
.variants
)
1019 visitor
.visit_object_type_flat(self
.name
, self
.info
,
1020 self
.members
, self
.variants
)
1023 class QAPISchemaMember(object):
1026 def __init__(self
, name
):
1027 assert isinstance(name
, str)
1031 def set_owner(self
, name
):
1032 assert not self
.owner
1035 def check_clash(self
, info
, seen
):
1036 cname
= c_name(self
.name
)
1037 if cname
.lower() != cname
and self
.owner
not in case_whitelist
:
1038 raise QAPIExprError(info
,
1039 "%s should not use uppercase" % self
.describe())
1041 raise QAPIExprError(info
,
1042 "%s collides with %s"
1043 % (self
.describe(), seen
[cname
].describe()))
1046 def _pretty_owner(self
):
1048 if owner
.startswith('q_obj_'):
1049 # See QAPISchema._make_implicit_object_type() - reverse the
1050 # mapping there to create a nice human-readable description
1052 if owner
.endswith('-arg'):
1053 return '(parameter of %s)' % owner
[:-4]
1054 elif owner
.endswith('-base'):
1055 return '(base of %s)' % owner
[:-5]
1057 assert owner
.endswith('-wrapper')
1058 # Unreachable and not implemented
1060 if owner
.endswith('Kind'):
1061 # See QAPISchema._make_implicit_enum_type()
1062 return '(branch of %s)' % owner
[:-4]
1063 return '(%s of %s)' % (self
.role
, owner
)
1066 return "'%s' %s" % (self
.name
, self
._pretty
_owner
())
1069 class QAPISchemaObjectTypeMember(QAPISchemaMember
):
1070 def __init__(self
, name
, typ
, optional
):
1071 QAPISchemaMember
.__init
__(self
, name
)
1072 assert isinstance(typ
, str)
1073 assert isinstance(optional
, bool)
1074 self
._type
_name
= typ
1076 self
.optional
= optional
1078 def check(self
, schema
):
1080 self
.type = schema
.lookup_type(self
._type
_name
)
1084 class QAPISchemaObjectTypeVariants(object):
1085 def __init__(self
, tag_name
, tag_member
, variants
):
1086 # Flat unions pass tag_name but not tag_member.
1087 # Simple unions and alternates pass tag_member but not tag_name.
1088 # After check(), tag_member is always set, and tag_name remains
1089 # a reliable witness of being used by a flat union.
1090 assert bool(tag_member
) != bool(tag_name
)
1091 assert (isinstance(tag_name
, str) or
1092 isinstance(tag_member
, QAPISchemaObjectTypeMember
))
1093 assert len(variants
) > 0
1095 assert isinstance(v
, QAPISchemaObjectTypeVariant
)
1096 self
.tag_name
= tag_name
1097 self
.tag_member
= tag_member
1098 self
.variants
= variants
1100 def set_owner(self
, name
):
1101 for v
in self
.variants
:
1104 def check(self
, schema
, seen
):
1105 if not self
.tag_member
: # flat union
1106 self
.tag_member
= seen
[c_name(self
.tag_name
)]
1107 assert self
.tag_name
== self
.tag_member
.name
1108 assert isinstance(self
.tag_member
.type, QAPISchemaEnumType
)
1109 for v
in self
.variants
:
1111 # Union names must match enum values; alternate names are
1112 # checked separately. Use 'seen' to tell the two apart.
1114 assert v
.name
in self
.tag_member
.type.member_names()
1115 assert isinstance(v
.type, QAPISchemaObjectType
)
1116 v
.type.check(schema
)
1118 def check_clash(self
, schema
, info
, seen
):
1119 for v
in self
.variants
:
1120 # Reset seen map for each variant, since qapi names from one
1121 # branch do not affect another branch
1122 assert isinstance(v
.type, QAPISchemaObjectType
)
1123 v
.type.check_clash(schema
, info
, dict(seen
))
1126 class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember
):
1129 def __init__(self
, name
, typ
):
1130 QAPISchemaObjectTypeMember
.__init
__(self
, name
, typ
, False)
1133 class QAPISchemaAlternateType(QAPISchemaType
):
1134 def __init__(self
, name
, info
, variants
):
1135 QAPISchemaType
.__init
__(self
, name
, info
)
1136 assert isinstance(variants
, QAPISchemaObjectTypeVariants
)
1137 assert not variants
.tag_name
1138 variants
.set_owner(name
)
1139 variants
.tag_member
.set_owner(self
.name
)
1140 self
.variants
= variants
1142 def check(self
, schema
):
1143 self
.variants
.tag_member
.check(schema
)
1144 # Not calling self.variants.check_clash(), because there's nothing
1146 self
.variants
.check(schema
, {})
1147 # Alternate branch names have no relation to the tag enum values;
1148 # so we have to check for potential name collisions ourselves.
1150 for v
in self
.variants
.variants
:
1151 v
.check_clash(self
.info
, seen
)
1154 return c_name(self
.name
) + pointer_suffix
1156 def json_type(self
):
1159 def visit(self
, visitor
):
1160 visitor
.visit_alternate_type(self
.name
, self
.info
, self
.variants
)
1163 class QAPISchemaCommand(QAPISchemaEntity
):
1164 def __init__(self
, name
, info
, arg_type
, ret_type
, gen
, success_response
):
1165 QAPISchemaEntity
.__init
__(self
, name
, info
)
1166 assert not arg_type
or isinstance(arg_type
, str)
1167 assert not ret_type
or isinstance(ret_type
, str)
1168 self
._arg
_type
_name
= arg_type
1169 self
.arg_type
= None
1170 self
._ret
_type
_name
= ret_type
1171 self
.ret_type
= None
1173 self
.success_response
= success_response
1175 def check(self
, schema
):
1176 if self
._arg
_type
_name
:
1177 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1178 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1179 assert not self
.arg_type
.variants
# not implemented
1180 if self
._ret
_type
_name
:
1181 self
.ret_type
= schema
.lookup_type(self
._ret
_type
_name
)
1182 assert isinstance(self
.ret_type
, QAPISchemaType
)
1184 def visit(self
, visitor
):
1185 visitor
.visit_command(self
.name
, self
.info
,
1186 self
.arg_type
, self
.ret_type
,
1187 self
.gen
, self
.success_response
)
1190 class QAPISchemaEvent(QAPISchemaEntity
):
1191 def __init__(self
, name
, info
, arg_type
):
1192 QAPISchemaEntity
.__init
__(self
, name
, info
)
1193 assert not arg_type
or isinstance(arg_type
, str)
1194 self
._arg
_type
_name
= arg_type
1195 self
.arg_type
= None
1197 def check(self
, schema
):
1198 if self
._arg
_type
_name
:
1199 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1200 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1201 assert not self
.arg_type
.variants
# not implemented
1203 def visit(self
, visitor
):
1204 visitor
.visit_event(self
.name
, self
.info
, self
.arg_type
)
1207 class QAPISchema(object):
1208 def __init__(self
, fname
):
1210 self
.exprs
= check_exprs(QAPISchemaParser(open(fname
, "r")).exprs
)
1211 self
._entity
_dict
= {}
1212 self
._predefining
= True
1213 self
._def
_predefineds
()
1214 self
._predefining
= False
1217 except (QAPISchemaError
, QAPIExprError
) as err
:
1218 print >>sys
.stderr
, err
1221 def _def_entity(self
, ent
):
1222 # Only the predefined types are allowed to not have info
1223 assert ent
.info
or self
._predefining
1224 assert ent
.name
not in self
._entity
_dict
1225 self
._entity
_dict
[ent
.name
] = ent
1227 def lookup_entity(self
, name
, typ
=None):
1228 ent
= self
._entity
_dict
.get(name
)
1229 if typ
and not isinstance(ent
, typ
):
1233 def lookup_type(self
, name
):
1234 return self
.lookup_entity(name
, QAPISchemaType
)
1236 def _def_builtin_type(self
, name
, json_type
, c_type
):
1237 self
._def
_entity
(QAPISchemaBuiltinType(name
, json_type
, c_type
))
1238 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1239 # qapi-types.h from a single .c, all arrays of builtins must be
1240 # declared in the first file whether or not they are used. Nicer
1241 # would be to use lazy instantiation, while figuring out how to
1242 # avoid compilation issues with multiple qapi-types.h.
1243 self
._make
_array
_type
(name
, None)
1245 def _def_predefineds(self
):
1246 for t
in [('str', 'string', 'char' + pointer_suffix
),
1247 ('number', 'number', 'double'),
1248 ('int', 'int', 'int64_t'),
1249 ('int8', 'int', 'int8_t'),
1250 ('int16', 'int', 'int16_t'),
1251 ('int32', 'int', 'int32_t'),
1252 ('int64', 'int', 'int64_t'),
1253 ('uint8', 'int', 'uint8_t'),
1254 ('uint16', 'int', 'uint16_t'),
1255 ('uint32', 'int', 'uint32_t'),
1256 ('uint64', 'int', 'uint64_t'),
1257 ('size', 'int', 'uint64_t'),
1258 ('bool', 'boolean', 'bool'),
1259 ('any', 'value', 'QObject' + pointer_suffix
)]:
1260 self
._def
_builtin
_type
(*t
)
1261 self
.the_empty_object_type
= QAPISchemaObjectType('q_empty', None,
1263 self
._def
_entity
(self
.the_empty_object_type
)
1264 qtype_values
= self
._make
_enum
_members
(['none', 'qnull', 'qint',
1265 'qstring', 'qdict', 'qlist',
1267 self
._def
_entity
(QAPISchemaEnumType('QType', None, qtype_values
,
1270 def _make_enum_members(self
, values
):
1271 return [QAPISchemaMember(v
) for v
in values
]
1273 def _make_implicit_enum_type(self
, name
, info
, values
):
1274 # See also QAPISchemaObjectTypeMember._pretty_owner()
1275 name
= name
+ 'Kind' # Use namespace reserved by add_name()
1276 self
._def
_entity
(QAPISchemaEnumType(
1277 name
, info
, self
._make
_enum
_members
(values
), None))
1280 def _make_array_type(self
, element_type
, info
):
1281 name
= element_type
+ 'List' # Use namespace reserved by add_name()
1282 if not self
.lookup_type(name
):
1283 self
._def
_entity
(QAPISchemaArrayType(name
, info
, element_type
))
1286 def _make_implicit_object_type(self
, name
, info
, role
, members
):
1289 # See also QAPISchemaObjectTypeMember._pretty_owner()
1290 name
= 'q_obj_%s-%s' % (name
, role
)
1291 if not self
.lookup_entity(name
, QAPISchemaObjectType
):
1292 self
._def
_entity
(QAPISchemaObjectType(name
, info
, None,
1296 def _def_enum_type(self
, expr
, info
):
1299 prefix
= expr
.get('prefix')
1300 self
._def
_entity
(QAPISchemaEnumType(
1301 name
, info
, self
._make
_enum
_members
(data
), prefix
))
1303 def _make_member(self
, name
, typ
, info
):
1305 if name
.startswith('*'):
1308 if isinstance(typ
, list):
1309 assert len(typ
) == 1
1310 typ
= self
._make
_array
_type
(typ
[0], info
)
1311 return QAPISchemaObjectTypeMember(name
, typ
, optional
)
1313 def _make_members(self
, data
, info
):
1314 return [self
._make
_member
(key
, value
, info
)
1315 for (key
, value
) in data
.iteritems()]
1317 def _def_struct_type(self
, expr
, info
):
1318 name
= expr
['struct']
1319 base
= expr
.get('base')
1321 self
._def
_entity
(QAPISchemaObjectType(name
, info
, base
,
1322 self
._make
_members
(data
, info
),
1325 def _make_variant(self
, case
, typ
):
1326 return QAPISchemaObjectTypeVariant(case
, typ
)
1328 def _make_simple_variant(self
, case
, typ
, info
):
1329 if isinstance(typ
, list):
1330 assert len(typ
) == 1
1331 typ
= self
._make
_array
_type
(typ
[0], info
)
1332 typ
= self
._make
_implicit
_object
_type
(
1333 typ
, info
, 'wrapper', [self
._make
_member
('data', typ
, info
)])
1334 return QAPISchemaObjectTypeVariant(case
, typ
)
1336 def _def_union_type(self
, expr
, info
):
1337 name
= expr
['union']
1339 base
= expr
.get('base')
1340 tag_name
= expr
.get('discriminator')
1342 if isinstance(base
, dict):
1343 base
= (self
._make
_implicit
_object
_type
(
1344 name
, info
, 'base', self
._make
_members
(base
, info
)))
1346 variants
= [self
._make
_variant
(key
, value
)
1347 for (key
, value
) in data
.iteritems()]
1350 variants
= [self
._make
_simple
_variant
(key
, value
, info
)
1351 for (key
, value
) in data
.iteritems()]
1352 typ
= self
._make
_implicit
_enum
_type
(name
, info
,
1353 [v
.name
for v
in variants
])
1354 tag_member
= QAPISchemaObjectTypeMember('type', typ
, False)
1355 members
= [tag_member
]
1357 QAPISchemaObjectType(name
, info
, base
, members
,
1358 QAPISchemaObjectTypeVariants(tag_name
,
1362 def _def_alternate_type(self
, expr
, info
):
1363 name
= expr
['alternate']
1365 variants
= [self
._make
_variant
(key
, value
)
1366 for (key
, value
) in data
.iteritems()]
1367 tag_member
= QAPISchemaObjectTypeMember('type', 'QType', False)
1369 QAPISchemaAlternateType(name
, info
,
1370 QAPISchemaObjectTypeVariants(None,
1374 def _def_command(self
, expr
, info
):
1375 name
= expr
['command']
1376 data
= expr
.get('data')
1377 rets
= expr
.get('returns')
1378 gen
= expr
.get('gen', True)
1379 success_response
= expr
.get('success-response', True)
1380 if isinstance(data
, OrderedDict
):
1381 data
= self
._make
_implicit
_object
_type
(
1382 name
, info
, 'arg', self
._make
_members
(data
, info
))
1383 if isinstance(rets
, list):
1384 assert len(rets
) == 1
1385 rets
= self
._make
_array
_type
(rets
[0], info
)
1386 self
._def
_entity
(QAPISchemaCommand(name
, info
, data
, rets
, gen
,
1389 def _def_event(self
, expr
, info
):
1390 name
= expr
['event']
1391 data
= expr
.get('data')
1392 if isinstance(data
, OrderedDict
):
1393 data
= self
._make
_implicit
_object
_type
(
1394 name
, info
, 'arg', self
._make
_members
(data
, info
))
1395 self
._def
_entity
(QAPISchemaEvent(name
, info
, data
))
1397 def _def_exprs(self
):
1398 for expr_elem
in self
.exprs
:
1399 expr
= expr_elem
['expr']
1400 info
= expr_elem
['info']
1402 self
._def
_enum
_type
(expr
, info
)
1403 elif 'struct' in expr
:
1404 self
._def
_struct
_type
(expr
, info
)
1405 elif 'union' in expr
:
1406 self
._def
_union
_type
(expr
, info
)
1407 elif 'alternate' in expr
:
1408 self
._def
_alternate
_type
(expr
, info
)
1409 elif 'command' in expr
:
1410 self
._def
_command
(expr
, info
)
1411 elif 'event' in expr
:
1412 self
._def
_event
(expr
, info
)
1417 for ent
in self
._entity
_dict
.values():
1420 def visit(self
, visitor
):
1421 visitor
.visit_begin(self
)
1422 for (name
, entity
) in sorted(self
._entity
_dict
.items()):
1423 if visitor
.visit_needed(entity
):
1424 entity
.visit(visitor
)
1429 # Code generation helpers
1432 def camel_case(name
):
1436 if ch
in ['_', '-']:
1439 new_name
+= ch
.upper()
1442 new_name
+= ch
.lower()
1446 # ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1447 # ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1448 # ENUM24_Name -> ENUM24_NAME
1449 def camel_to_upper(value
):
1450 c_fun_str
= c_name(value
, False)
1458 # When c is upper and no "_" appears before, do more checks
1459 if c
.isupper() and (i
> 0) and c_fun_str
[i
- 1] != "_":
1460 if i
< l
- 1 and c_fun_str
[i
+ 1].islower():
1462 elif c_fun_str
[i
- 1].isdigit():
1465 return new_name
.lstrip('_').upper()
1468 def c_enum_const(type_name
, const_name
, prefix
=None):
1469 if prefix
is not None:
1471 return camel_to_upper(type_name
) + '_' + c_name(const_name
, False).upper()
1473 c_name_trans
= string
.maketrans('.-', '__')
1476 # Map @name to a valid C identifier.
1477 # If @protect, avoid returning certain ticklish identifiers (like
1478 # C keywords) by prepending "q_".
1480 # Used for converting 'name' from a 'name':'type' qapi definition
1481 # into a generated struct member, as well as converting type names
1482 # into substrings of a generated C function name.
1483 # '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1484 # protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
1485 def c_name(name
, protect
=True):
1486 # ANSI X3J11/88-090, 3.1.1
1487 c89_words
= set(['auto', 'break', 'case', 'char', 'const', 'continue',
1488 'default', 'do', 'double', 'else', 'enum', 'extern',
1489 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1490 'return', 'short', 'signed', 'sizeof', 'static',
1491 'struct', 'switch', 'typedef', 'union', 'unsigned',
1492 'void', 'volatile', 'while'])
1493 # ISO/IEC 9899:1999, 6.4.1
1494 c99_words
= set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1495 # ISO/IEC 9899:2011, 6.4.1
1496 c11_words
= set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1497 '_Noreturn', '_Static_assert', '_Thread_local'])
1498 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1500 gcc_words
= set(['asm', 'typeof'])
1501 # C++ ISO/IEC 14882:2003 2.11
1502 cpp_words
= set(['bool', 'catch', 'class', 'const_cast', 'delete',
1503 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1504 'namespace', 'new', 'operator', 'private', 'protected',
1505 'public', 'reinterpret_cast', 'static_cast', 'template',
1506 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1507 'using', 'virtual', 'wchar_t',
1508 # alternative representations
1509 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1510 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
1511 # namespace pollution:
1512 polluted_words
= set(['unix', 'errno', 'mips', 'sparc'])
1513 name
= name
.translate(c_name_trans
)
1514 if protect
and (name
in c89_words | c99_words | c11_words | gcc_words
1515 | cpp_words | polluted_words
):
1519 eatspace
= '\033EATSPACE.'
1520 pointer_suffix
= ' *' + eatspace
1523 def genindent(count
):
1525 for _
in range(count
):
1532 def push_indent(indent_amount
=4):
1534 indent_level
+= indent_amount
1537 def pop_indent(indent_amount
=4):
1539 indent_level
-= indent_amount
1542 # Generate @code with @kwds interpolated.
1543 # Obey indent_level, and strip eatspace.
1544 def cgen(code
, **kwds
):
1547 indent
= genindent(indent_level
)
1548 # re.subn() lacks flags support before Python 2.7, use re.compile()
1549 raw
= re
.subn(re
.compile("^.", re
.MULTILINE
),
1550 indent
+ r
'\g<0>', raw
)
1552 return re
.sub(re
.escape(eatspace
) + ' *', '', raw
)
1555 def mcgen(code
, **kwds
):
1558 return cgen(code
, **kwds
)
1561 def guardname(filename
):
1562 return c_name(filename
, protect
=False).upper()
1565 def guardstart(name
):
1572 name
=guardname(name
))
1578 #endif /* %(name)s */
1581 name
=guardname(name
))
1584 def gen_enum_lookup(name
, values
, prefix
=None):
1587 const char *const %(c_name)s_lookup[] = {
1589 c_name
=c_name(name
))
1590 for value
in values
:
1591 index
= c_enum_const(name
, value
, prefix
)
1593 [%(index)s] = "%(value)s",
1595 index
=index
, value
=value
)
1597 max_index
= c_enum_const(name
, '_MAX', prefix
)
1599 [%(max_index)s] = NULL,
1602 max_index
=max_index
)
1606 def gen_enum(name
, values
, prefix
=None):
1607 # append automatically generated _MAX value
1608 enum_values
= values
+ ['_MAX']
1612 typedef enum %(c_name)s {
1614 c_name
=c_name(name
))
1617 for value
in enum_values
:
1621 c_enum
=c_enum_const(name
, value
, prefix
),
1628 c_name
=c_name(name
))
1632 extern const char *const %(c_name)s_lookup[];
1634 c_name
=c_name(name
))
1638 def gen_params(arg_type
, extra
):
1641 assert not arg_type
.variants
1644 for memb
in arg_type
.members
:
1648 ret
+= 'bool has_%s, ' % c_name(memb
.name
)
1649 ret
+= '%s %s' % (memb
.type.c_param_type(), c_name(memb
.name
))
1655 def gen_err_check():
1664 # Common command line parsing
1668 def parse_command_line(extra_options
="", extra_long_options
=[]):
1671 opts
, args
= getopt
.gnu_getopt(sys
.argv
[1:],
1672 "chp:o:" + extra_options
,
1673 ["source", "header", "prefix=",
1674 "output-dir="] + extra_long_options
)
1675 except getopt
.GetoptError
as err
:
1676 print >>sys
.stderr
, "%s: %s" % (sys
.argv
[0], str(err
))
1687 if o
in ("-p", "--prefix"):
1688 match
= re
.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a
)
1689 if match
.end() != len(a
):
1690 print >>sys
.stderr
, \
1691 "%s: 'funny character '%s' in argument of --prefix" \
1692 % (sys
.argv
[0], a
[match
.end()])
1695 elif o
in ("-o", "--output-dir"):
1696 output_dir
= a
+ "/"
1697 elif o
in ("-c", "--source"):
1699 elif o
in ("-h", "--header"):
1702 extra_opts
.append(oa
)
1704 if not do_c
and not do_h
:
1709 print >>sys
.stderr
, "%s: need exactly one argument" % sys
.argv
[0]
1713 return (fname
, output_dir
, do_c
, do_h
, prefix
, extra_opts
)
1716 # Generate output files with boilerplate
1720 def open_output(output_dir
, do_c
, do_h
, prefix
, c_file
, h_file
,
1721 c_comment
, h_comment
):
1722 guard
= guardname(prefix
+ h_file
)
1723 c_file
= output_dir
+ prefix
+ c_file
1724 h_file
= output_dir
+ prefix
+ h_file
1728 os
.makedirs(output_dir
)
1729 except os
.error
as e
:
1730 if e
.errno
!= errno
.EEXIST
:
1733 def maybe_open(really
, name
, opt
):
1735 return open(name
, opt
)
1738 return StringIO
.StringIO()
1740 fdef
= maybe_open(do_c
, c_file
, 'w')
1741 fdecl
= maybe_open(do_h
, h_file
, 'w')
1743 fdef
.write(mcgen('''
1744 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1749 fdecl
.write(mcgen('''
1750 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1756 comment
=h_comment
, guard
=guard
))
1758 return (fdef
, fdecl
)
1761 def close_output(fdef
, fdecl
):