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
.members
is not None
1004 return not self
.members
and not self
.variants
1007 assert self
.name
!= 'q_empty'
1008 return QAPISchemaType
.c_name(self
)
1011 assert not self
.is_implicit()
1012 return c_name(self
.name
) + pointer_suffix
1014 def c_unboxed_type(self
):
1015 return c_name(self
.name
)
1017 def json_type(self
):
1020 def visit(self
, visitor
):
1021 visitor
.visit_object_type(self
.name
, self
.info
,
1022 self
.base
, self
.local_members
, self
.variants
)
1023 visitor
.visit_object_type_flat(self
.name
, self
.info
,
1024 self
.members
, self
.variants
)
1027 class QAPISchemaMember(object):
1030 def __init__(self
, name
):
1031 assert isinstance(name
, str)
1035 def set_owner(self
, name
):
1036 assert not self
.owner
1039 def check_clash(self
, info
, seen
):
1040 cname
= c_name(self
.name
)
1041 if cname
.lower() != cname
and self
.owner
not in case_whitelist
:
1042 raise QAPIExprError(info
,
1043 "%s should not use uppercase" % self
.describe())
1045 raise QAPIExprError(info
,
1046 "%s collides with %s"
1047 % (self
.describe(), seen
[cname
].describe()))
1050 def _pretty_owner(self
):
1052 if owner
.startswith('q_obj_'):
1053 # See QAPISchema._make_implicit_object_type() - reverse the
1054 # mapping there to create a nice human-readable description
1056 if owner
.endswith('-arg'):
1057 return '(parameter of %s)' % owner
[:-4]
1058 elif owner
.endswith('-base'):
1059 return '(base of %s)' % owner
[:-5]
1061 assert owner
.endswith('-wrapper')
1062 # Unreachable and not implemented
1064 if owner
.endswith('Kind'):
1065 # See QAPISchema._make_implicit_enum_type()
1066 return '(branch of %s)' % owner
[:-4]
1067 return '(%s of %s)' % (self
.role
, owner
)
1070 return "'%s' %s" % (self
.name
, self
._pretty
_owner
())
1073 class QAPISchemaObjectTypeMember(QAPISchemaMember
):
1074 def __init__(self
, name
, typ
, optional
):
1075 QAPISchemaMember
.__init
__(self
, name
)
1076 assert isinstance(typ
, str)
1077 assert isinstance(optional
, bool)
1078 self
._type
_name
= typ
1080 self
.optional
= optional
1082 def check(self
, schema
):
1084 self
.type = schema
.lookup_type(self
._type
_name
)
1088 class QAPISchemaObjectTypeVariants(object):
1089 def __init__(self
, tag_name
, tag_member
, variants
):
1090 # Flat unions pass tag_name but not tag_member.
1091 # Simple unions and alternates pass tag_member but not tag_name.
1092 # After check(), tag_member is always set, and tag_name remains
1093 # a reliable witness of being used by a flat union.
1094 assert bool(tag_member
) != bool(tag_name
)
1095 assert (isinstance(tag_name
, str) or
1096 isinstance(tag_member
, QAPISchemaObjectTypeMember
))
1097 assert len(variants
) > 0
1099 assert isinstance(v
, QAPISchemaObjectTypeVariant
)
1100 self
._tag
_name
= tag_name
1101 self
.tag_member
= tag_member
1102 self
.variants
= variants
1104 def set_owner(self
, name
):
1105 for v
in self
.variants
:
1108 def check(self
, schema
, seen
):
1109 if not self
.tag_member
: # flat union
1110 self
.tag_member
= seen
[c_name(self
._tag
_name
)]
1111 assert self
._tag
_name
== self
.tag_member
.name
1112 assert isinstance(self
.tag_member
.type, QAPISchemaEnumType
)
1113 for v
in self
.variants
:
1115 # Union names must match enum values; alternate names are
1116 # checked separately. Use 'seen' to tell the two apart.
1118 assert v
.name
in self
.tag_member
.type.member_names()
1119 assert isinstance(v
.type, QAPISchemaObjectType
)
1120 v
.type.check(schema
)
1122 def check_clash(self
, schema
, info
, seen
):
1123 for v
in self
.variants
:
1124 # Reset seen map for each variant, since qapi names from one
1125 # branch do not affect another branch
1126 assert isinstance(v
.type, QAPISchemaObjectType
)
1127 v
.type.check_clash(schema
, info
, dict(seen
))
1130 class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember
):
1133 def __init__(self
, name
, typ
):
1134 QAPISchemaObjectTypeMember
.__init
__(self
, name
, typ
, False)
1137 class QAPISchemaAlternateType(QAPISchemaType
):
1138 def __init__(self
, name
, info
, variants
):
1139 QAPISchemaType
.__init
__(self
, name
, info
)
1140 assert isinstance(variants
, QAPISchemaObjectTypeVariants
)
1141 assert variants
.tag_member
1142 variants
.set_owner(name
)
1143 variants
.tag_member
.set_owner(self
.name
)
1144 self
.variants
= variants
1146 def check(self
, schema
):
1147 self
.variants
.tag_member
.check(schema
)
1148 # Not calling self.variants.check_clash(), because there's nothing
1150 self
.variants
.check(schema
, {})
1151 # Alternate branch names have no relation to the tag enum values;
1152 # so we have to check for potential name collisions ourselves.
1154 for v
in self
.variants
.variants
:
1155 v
.check_clash(self
.info
, seen
)
1158 return c_name(self
.name
) + pointer_suffix
1160 def json_type(self
):
1163 def visit(self
, visitor
):
1164 visitor
.visit_alternate_type(self
.name
, self
.info
, self
.variants
)
1167 class QAPISchemaCommand(QAPISchemaEntity
):
1168 def __init__(self
, name
, info
, arg_type
, ret_type
, gen
, success_response
):
1169 QAPISchemaEntity
.__init
__(self
, name
, info
)
1170 assert not arg_type
or isinstance(arg_type
, str)
1171 assert not ret_type
or isinstance(ret_type
, str)
1172 self
._arg
_type
_name
= arg_type
1173 self
.arg_type
= None
1174 self
._ret
_type
_name
= ret_type
1175 self
.ret_type
= None
1177 self
.success_response
= success_response
1179 def check(self
, schema
):
1180 if self
._arg
_type
_name
:
1181 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1182 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1183 assert not self
.arg_type
.variants
# not implemented
1184 if self
._ret
_type
_name
:
1185 self
.ret_type
= schema
.lookup_type(self
._ret
_type
_name
)
1186 assert isinstance(self
.ret_type
, QAPISchemaType
)
1188 def visit(self
, visitor
):
1189 visitor
.visit_command(self
.name
, self
.info
,
1190 self
.arg_type
, self
.ret_type
,
1191 self
.gen
, self
.success_response
)
1194 class QAPISchemaEvent(QAPISchemaEntity
):
1195 def __init__(self
, name
, info
, arg_type
):
1196 QAPISchemaEntity
.__init
__(self
, name
, info
)
1197 assert not arg_type
or isinstance(arg_type
, str)
1198 self
._arg
_type
_name
= arg_type
1199 self
.arg_type
= None
1201 def check(self
, schema
):
1202 if self
._arg
_type
_name
:
1203 self
.arg_type
= schema
.lookup_type(self
._arg
_type
_name
)
1204 assert isinstance(self
.arg_type
, QAPISchemaObjectType
)
1205 assert not self
.arg_type
.variants
# not implemented
1207 def visit(self
, visitor
):
1208 visitor
.visit_event(self
.name
, self
.info
, self
.arg_type
)
1211 class QAPISchema(object):
1212 def __init__(self
, fname
):
1214 self
.exprs
= check_exprs(QAPISchemaParser(open(fname
, "r")).exprs
)
1215 self
._entity
_dict
= {}
1216 self
._predefining
= True
1217 self
._def
_predefineds
()
1218 self
._predefining
= False
1221 except (QAPISchemaError
, QAPIExprError
) as err
:
1222 print >>sys
.stderr
, err
1225 def _def_entity(self
, ent
):
1226 # Only the predefined types are allowed to not have info
1227 assert ent
.info
or self
._predefining
1228 assert ent
.name
not in self
._entity
_dict
1229 self
._entity
_dict
[ent
.name
] = ent
1231 def lookup_entity(self
, name
, typ
=None):
1232 ent
= self
._entity
_dict
.get(name
)
1233 if typ
and not isinstance(ent
, typ
):
1237 def lookup_type(self
, name
):
1238 return self
.lookup_entity(name
, QAPISchemaType
)
1240 def _def_builtin_type(self
, name
, json_type
, c_type
):
1241 self
._def
_entity
(QAPISchemaBuiltinType(name
, json_type
, c_type
))
1242 # TODO As long as we have QAPI_TYPES_BUILTIN to share multiple
1243 # qapi-types.h from a single .c, all arrays of builtins must be
1244 # declared in the first file whether or not they are used. Nicer
1245 # would be to use lazy instantiation, while figuring out how to
1246 # avoid compilation issues with multiple qapi-types.h.
1247 self
._make
_array
_type
(name
, None)
1249 def _def_predefineds(self
):
1250 for t
in [('str', 'string', 'char' + pointer_suffix
),
1251 ('number', 'number', 'double'),
1252 ('int', 'int', 'int64_t'),
1253 ('int8', 'int', 'int8_t'),
1254 ('int16', 'int', 'int16_t'),
1255 ('int32', 'int', 'int32_t'),
1256 ('int64', 'int', 'int64_t'),
1257 ('uint8', 'int', 'uint8_t'),
1258 ('uint16', 'int', 'uint16_t'),
1259 ('uint32', 'int', 'uint32_t'),
1260 ('uint64', 'int', 'uint64_t'),
1261 ('size', 'int', 'uint64_t'),
1262 ('bool', 'boolean', 'bool'),
1263 ('any', 'value', 'QObject' + pointer_suffix
)]:
1264 self
._def
_builtin
_type
(*t
)
1265 self
.the_empty_object_type
= QAPISchemaObjectType('q_empty', None,
1267 self
._def
_entity
(self
.the_empty_object_type
)
1268 qtype_values
= self
._make
_enum
_members
(['none', 'qnull', 'qint',
1269 'qstring', 'qdict', 'qlist',
1271 self
._def
_entity
(QAPISchemaEnumType('QType', None, qtype_values
,
1274 def _make_enum_members(self
, values
):
1275 return [QAPISchemaMember(v
) for v
in values
]
1277 def _make_implicit_enum_type(self
, name
, info
, values
):
1278 # See also QAPISchemaObjectTypeMember._pretty_owner()
1279 name
= name
+ 'Kind' # Use namespace reserved by add_name()
1280 self
._def
_entity
(QAPISchemaEnumType(
1281 name
, info
, self
._make
_enum
_members
(values
), None))
1284 def _make_array_type(self
, element_type
, info
):
1285 name
= element_type
+ 'List' # Use namespace reserved by add_name()
1286 if not self
.lookup_type(name
):
1287 self
._def
_entity
(QAPISchemaArrayType(name
, info
, element_type
))
1290 def _make_implicit_object_type(self
, name
, info
, role
, members
):
1293 # See also QAPISchemaObjectTypeMember._pretty_owner()
1294 name
= 'q_obj_%s-%s' % (name
, role
)
1295 if not self
.lookup_entity(name
, QAPISchemaObjectType
):
1296 self
._def
_entity
(QAPISchemaObjectType(name
, info
, None,
1300 def _def_enum_type(self
, expr
, info
):
1303 prefix
= expr
.get('prefix')
1304 self
._def
_entity
(QAPISchemaEnumType(
1305 name
, info
, self
._make
_enum
_members
(data
), prefix
))
1307 def _make_member(self
, name
, typ
, info
):
1309 if name
.startswith('*'):
1312 if isinstance(typ
, list):
1313 assert len(typ
) == 1
1314 typ
= self
._make
_array
_type
(typ
[0], info
)
1315 return QAPISchemaObjectTypeMember(name
, typ
, optional
)
1317 def _make_members(self
, data
, info
):
1318 return [self
._make
_member
(key
, value
, info
)
1319 for (key
, value
) in data
.iteritems()]
1321 def _def_struct_type(self
, expr
, info
):
1322 name
= expr
['struct']
1323 base
= expr
.get('base')
1325 self
._def
_entity
(QAPISchemaObjectType(name
, info
, base
,
1326 self
._make
_members
(data
, info
),
1329 def _make_variant(self
, case
, typ
):
1330 return QAPISchemaObjectTypeVariant(case
, typ
)
1332 def _make_simple_variant(self
, case
, typ
, info
):
1333 if isinstance(typ
, list):
1334 assert len(typ
) == 1
1335 typ
= self
._make
_array
_type
(typ
[0], info
)
1336 typ
= self
._make
_implicit
_object
_type
(
1337 typ
, info
, 'wrapper', [self
._make
_member
('data', typ
, info
)])
1338 return QAPISchemaObjectTypeVariant(case
, typ
)
1340 def _def_union_type(self
, expr
, info
):
1341 name
= expr
['union']
1343 base
= expr
.get('base')
1344 tag_name
= expr
.get('discriminator')
1346 if isinstance(base
, dict):
1347 base
= (self
._make
_implicit
_object
_type
(
1348 name
, info
, 'base', self
._make
_members
(base
, info
)))
1350 variants
= [self
._make
_variant
(key
, value
)
1351 for (key
, value
) in data
.iteritems()]
1354 variants
= [self
._make
_simple
_variant
(key
, value
, info
)
1355 for (key
, value
) in data
.iteritems()]
1356 typ
= self
._make
_implicit
_enum
_type
(name
, info
,
1357 [v
.name
for v
in variants
])
1358 tag_member
= QAPISchemaObjectTypeMember('type', typ
, False)
1359 members
= [tag_member
]
1361 QAPISchemaObjectType(name
, info
, base
, members
,
1362 QAPISchemaObjectTypeVariants(tag_name
,
1366 def _def_alternate_type(self
, expr
, info
):
1367 name
= expr
['alternate']
1369 variants
= [self
._make
_variant
(key
, value
)
1370 for (key
, value
) in data
.iteritems()]
1371 tag_member
= QAPISchemaObjectTypeMember('type', 'QType', False)
1373 QAPISchemaAlternateType(name
, info
,
1374 QAPISchemaObjectTypeVariants(None,
1378 def _def_command(self
, expr
, info
):
1379 name
= expr
['command']
1380 data
= expr
.get('data')
1381 rets
= expr
.get('returns')
1382 gen
= expr
.get('gen', True)
1383 success_response
= expr
.get('success-response', True)
1384 if isinstance(data
, OrderedDict
):
1385 data
= self
._make
_implicit
_object
_type
(
1386 name
, info
, 'arg', self
._make
_members
(data
, info
))
1387 if isinstance(rets
, list):
1388 assert len(rets
) == 1
1389 rets
= self
._make
_array
_type
(rets
[0], info
)
1390 self
._def
_entity
(QAPISchemaCommand(name
, info
, data
, rets
, gen
,
1393 def _def_event(self
, expr
, info
):
1394 name
= expr
['event']
1395 data
= expr
.get('data')
1396 if isinstance(data
, OrderedDict
):
1397 data
= self
._make
_implicit
_object
_type
(
1398 name
, info
, 'arg', self
._make
_members
(data
, info
))
1399 self
._def
_entity
(QAPISchemaEvent(name
, info
, data
))
1401 def _def_exprs(self
):
1402 for expr_elem
in self
.exprs
:
1403 expr
= expr_elem
['expr']
1404 info
= expr_elem
['info']
1406 self
._def
_enum
_type
(expr
, info
)
1407 elif 'struct' in expr
:
1408 self
._def
_struct
_type
(expr
, info
)
1409 elif 'union' in expr
:
1410 self
._def
_union
_type
(expr
, info
)
1411 elif 'alternate' in expr
:
1412 self
._def
_alternate
_type
(expr
, info
)
1413 elif 'command' in expr
:
1414 self
._def
_command
(expr
, info
)
1415 elif 'event' in expr
:
1416 self
._def
_event
(expr
, info
)
1421 for ent
in self
._entity
_dict
.values():
1424 def visit(self
, visitor
):
1425 visitor
.visit_begin(self
)
1426 for (name
, entity
) in sorted(self
._entity
_dict
.items()):
1427 if visitor
.visit_needed(entity
):
1428 entity
.visit(visitor
)
1433 # Code generation helpers
1436 def camel_case(name
):
1440 if ch
in ['_', '-']:
1443 new_name
+= ch
.upper()
1446 new_name
+= ch
.lower()
1450 # ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
1451 # ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
1452 # ENUM24_Name -> ENUM24_NAME
1453 def camel_to_upper(value
):
1454 c_fun_str
= c_name(value
, False)
1462 # When c is upper and no "_" appears before, do more checks
1463 if c
.isupper() and (i
> 0) and c_fun_str
[i
- 1] != "_":
1464 if i
< l
- 1 and c_fun_str
[i
+ 1].islower():
1466 elif c_fun_str
[i
- 1].isdigit():
1469 return new_name
.lstrip('_').upper()
1472 def c_enum_const(type_name
, const_name
, prefix
=None):
1473 if prefix
is not None:
1475 return camel_to_upper(type_name
) + '_' + c_name(const_name
, False).upper()
1477 c_name_trans
= string
.maketrans('.-', '__')
1480 # Map @name to a valid C identifier.
1481 # If @protect, avoid returning certain ticklish identifiers (like
1482 # C keywords) by prepending "q_".
1484 # Used for converting 'name' from a 'name':'type' qapi definition
1485 # into a generated struct member, as well as converting type names
1486 # into substrings of a generated C function name.
1487 # '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
1488 # protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
1489 def c_name(name
, protect
=True):
1490 # ANSI X3J11/88-090, 3.1.1
1491 c89_words
= set(['auto', 'break', 'case', 'char', 'const', 'continue',
1492 'default', 'do', 'double', 'else', 'enum', 'extern',
1493 'float', 'for', 'goto', 'if', 'int', 'long', 'register',
1494 'return', 'short', 'signed', 'sizeof', 'static',
1495 'struct', 'switch', 'typedef', 'union', 'unsigned',
1496 'void', 'volatile', 'while'])
1497 # ISO/IEC 9899:1999, 6.4.1
1498 c99_words
= set(['inline', 'restrict', '_Bool', '_Complex', '_Imaginary'])
1499 # ISO/IEC 9899:2011, 6.4.1
1500 c11_words
= set(['_Alignas', '_Alignof', '_Atomic', '_Generic',
1501 '_Noreturn', '_Static_assert', '_Thread_local'])
1502 # GCC http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/C-Extensions.html
1504 gcc_words
= set(['asm', 'typeof'])
1505 # C++ ISO/IEC 14882:2003 2.11
1506 cpp_words
= set(['bool', 'catch', 'class', 'const_cast', 'delete',
1507 'dynamic_cast', 'explicit', 'false', 'friend', 'mutable',
1508 'namespace', 'new', 'operator', 'private', 'protected',
1509 'public', 'reinterpret_cast', 'static_cast', 'template',
1510 'this', 'throw', 'true', 'try', 'typeid', 'typename',
1511 'using', 'virtual', 'wchar_t',
1512 # alternative representations
1513 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not',
1514 'not_eq', 'or', 'or_eq', 'xor', 'xor_eq'])
1515 # namespace pollution:
1516 polluted_words
= set(['unix', 'errno', 'mips', 'sparc'])
1517 name
= name
.translate(c_name_trans
)
1518 if protect
and (name
in c89_words | c99_words | c11_words | gcc_words
1519 | cpp_words | polluted_words
):
1523 eatspace
= '\033EATSPACE.'
1524 pointer_suffix
= ' *' + eatspace
1527 def genindent(count
):
1529 for _
in range(count
):
1536 def push_indent(indent_amount
=4):
1538 indent_level
+= indent_amount
1541 def pop_indent(indent_amount
=4):
1543 indent_level
-= indent_amount
1546 # Generate @code with @kwds interpolated.
1547 # Obey indent_level, and strip eatspace.
1548 def cgen(code
, **kwds
):
1551 indent
= genindent(indent_level
)
1552 # re.subn() lacks flags support before Python 2.7, use re.compile()
1553 raw
= re
.subn(re
.compile("^.", re
.MULTILINE
),
1554 indent
+ r
'\g<0>', raw
)
1556 return re
.sub(re
.escape(eatspace
) + ' *', '', raw
)
1559 def mcgen(code
, **kwds
):
1562 return cgen(code
, **kwds
)
1565 def guardname(filename
):
1566 return c_name(filename
, protect
=False).upper()
1569 def guardstart(name
):
1576 name
=guardname(name
))
1582 #endif /* %(name)s */
1585 name
=guardname(name
))
1588 def gen_enum_lookup(name
, values
, prefix
=None):
1591 const char *const %(c_name)s_lookup[] = {
1593 c_name
=c_name(name
))
1594 for value
in values
:
1595 index
= c_enum_const(name
, value
, prefix
)
1597 [%(index)s] = "%(value)s",
1599 index
=index
, value
=value
)
1601 max_index
= c_enum_const(name
, '_MAX', prefix
)
1603 [%(max_index)s] = NULL,
1606 max_index
=max_index
)
1610 def gen_enum(name
, values
, prefix
=None):
1611 # append automatically generated _MAX value
1612 enum_values
= values
+ ['_MAX']
1616 typedef enum %(c_name)s {
1618 c_name
=c_name(name
))
1621 for value
in enum_values
:
1625 c_enum
=c_enum_const(name
, value
, prefix
),
1632 c_name
=c_name(name
))
1636 extern const char *const %(c_name)s_lookup[];
1638 c_name
=c_name(name
))
1642 def gen_params(arg_type
, extra
):
1645 assert not arg_type
.variants
1648 for memb
in arg_type
.members
:
1652 ret
+= 'bool has_%s, ' % c_name(memb
.name
)
1653 ret
+= '%s %s' % (memb
.type.c_param_type(), c_name(memb
.name
))
1659 def gen_err_check():
1668 # Common command line parsing
1672 def parse_command_line(extra_options
="", extra_long_options
=[]):
1675 opts
, args
= getopt
.gnu_getopt(sys
.argv
[1:],
1676 "chp:o:" + extra_options
,
1677 ["source", "header", "prefix=",
1678 "output-dir="] + extra_long_options
)
1679 except getopt
.GetoptError
as err
:
1680 print >>sys
.stderr
, "%s: %s" % (sys
.argv
[0], str(err
))
1691 if o
in ("-p", "--prefix"):
1692 match
= re
.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a
)
1693 if match
.end() != len(a
):
1694 print >>sys
.stderr
, \
1695 "%s: 'funny character '%s' in argument of --prefix" \
1696 % (sys
.argv
[0], a
[match
.end()])
1699 elif o
in ("-o", "--output-dir"):
1700 output_dir
= a
+ "/"
1701 elif o
in ("-c", "--source"):
1703 elif o
in ("-h", "--header"):
1706 extra_opts
.append(oa
)
1708 if not do_c
and not do_h
:
1713 print >>sys
.stderr
, "%s: need exactly one argument" % sys
.argv
[0]
1717 return (fname
, output_dir
, do_c
, do_h
, prefix
, extra_opts
)
1720 # Generate output files with boilerplate
1724 def open_output(output_dir
, do_c
, do_h
, prefix
, c_file
, h_file
,
1725 c_comment
, h_comment
):
1726 guard
= guardname(prefix
+ h_file
)
1727 c_file
= output_dir
+ prefix
+ c_file
1728 h_file
= output_dir
+ prefix
+ h_file
1732 os
.makedirs(output_dir
)
1733 except os
.error
as e
:
1734 if e
.errno
!= errno
.EEXIST
:
1737 def maybe_open(really
, name
, opt
):
1739 return open(name
, opt
)
1742 return StringIO
.StringIO()
1744 fdef
= maybe_open(do_c
, c_file
, 'w')
1745 fdecl
= maybe_open(do_h
, h_file
, 'w')
1747 fdef
.write(mcgen('''
1748 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1753 fdecl
.write(mcgen('''
1754 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
1760 comment
=h_comment
, guard
=guard
))
1762 return (fdef
, fdecl
)
1765 def close_output(fdef
, fdecl
):