On Sun, Mar 03, 2019 at 07:10:25PM +0000, Frediano Ziglio wrote: > Allows to specify a @declare attribute for messages and structure > that can generate the needed C structures. > > Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> > --- > python_modules/ptypes.py | 64 ++++++++++++++++++++++++++++++++++++++++ > spice_codegen.py | 47 +++++++++++++++++++++++++++++ > 2 files changed, 111 insertions(+) > > diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py > index 7dca78d..64c198e 100644 > --- a/python_modules/ptypes.py > +++ b/python_modules/ptypes.py > @@ -72,6 +72,8 @@ valid_attributes=set([ > 'zero', > # this attribute does not exist on the network, fill just structure with the value > 'virtual', > + # generate C structure declarations from protocol definition > + 'declare', > ]) > > attributes_with_arguments=set([ > @@ -485,6 +487,26 @@ class ArrayType(Type): > def c_type(self): > return self.element_type.c_type() > > + def generate_c_declaration(self, writer, member): > + name = member.name > + if member.has_attr("chunk"): > + return writer.writeln('SpiceChunks *%s;' % name) > + if member.has_attr("as_ptr"): > + len_var = member.attributes["as_ptr"][0] > + writer.writeln('uint32_t %s;' % len_var) > + return writer.writeln('%s *%s;' % (self.c_type(), name)) > + if member.has_attr("to_ptr"): # TODO len > + return writer.writeln('%s *%s;' % (self.c_type(), name)) > + if member.has_attr("ptr_array"): # TODO where the length is stored? overflow? > + return writer.writeln('%s *%s[0];' % (self.c_type(), name)) > + if member.has_end_attr() or self.is_remaining_length(): # TODO len > + return writer.writeln('%s %s[0];' % (self.c_type(), name)) These TODO are worrying, but only the has_end_attr() one seems to be run at the moment, the others seem to be dead code? Looks good otherwise, Acked-by: Christophe Fergeau <cfergeau@xxxxxxxxxx> > + if self.is_constant_length(): > + return writer.writeln('%s %s[%s];' % (self.c_type(), name, self.size)) > + if self.is_identifier_length(): > + return writer.writeln('%s *%s;' % (self.c_type(), name)) > + raise NotImplementedError('unknown array %s' % str(self)) > + > class PointerType(Type): > def __init__(self, target_type): > Type.__init__(self) > @@ -529,6 +551,15 @@ class PointerType(Type): > def get_num_pointers(self): > return 1 > > + def generate_c_declaration(self, writer, member): > + target_type = self.target_type > + is_array = target_type.is_array() > + if not is_array or target_type.is_identifier_length(): > + writer.writeln("%s *%s;" % (target_type.c_type(), member.name)) > + return > + raise NotImplementedError('Some pointers to array declarations are not implemented %s' % > +member) > + > class Containee: > def __init__(self): > self.attributes = {} > @@ -624,6 +655,14 @@ class Member(Containee): > names = [prefix + "_" + name for name in names] > return names > > + def generate_c_declaration(self, writer): > + if self.has_attr("zero"): > + return > + if self.is_pointer() or self.is_array(): > + self.member_type.generate_c_declaration(writer, self) > + return > + return writer.writeln("%s %s;" % (self.member_type.c_type(), self.name)) > + > class SwitchCase: > def __init__(self, values, member): > self.values = values > @@ -747,6 +786,17 @@ class Switch(Containee): > names = names + c.get_pointer_names(marshalled) > return names > > + def generate_c_declaration(self, writer): > + if self.has_attr("anon") and len(self.cases) == 1: > + self.cases[0].member.generate_c_declaration(writer) > + return > + writer.writeln('union {') > + writer.indent() > + for m in self.cases: > + m.member.generate_c_declaration(writer) > + writer.unindent() > + writer.writeln('} %s;' % self.name) > + > class ContainerType(Type): > def is_fixed_sizeof(self): > for m in self.members: > @@ -857,6 +907,20 @@ class ContainerType(Type): > > return member > > + def generate_c_declaration(self, writer): > + if not self.has_attr('declare'): > + return > + name = self.c_type() > + writer.writeln('typedef struct %s {' % name) > + writer.indent() > + for m in self.members: > + m.generate_c_declaration(writer) > + if len(self.members) == 0: > + # make sure generated structure are not empty > + writer.writeln("char dummy[0];") > + writer.unindent() > + writer.writeln('} %s;' % name).newline() > + > class StructType(ContainerType): > def __init__(self, name, members, attribute_list): > Type.__init__(self) > diff --git a/spice_codegen.py b/spice_codegen.py > index 4664740..66f99a5 100755 > --- a/spice_codegen.py > +++ b/spice_codegen.py > @@ -177,6 +177,8 @@ parser.add_option("--license", dest="license", > help="license to use for generated file(s) (LGPL/BSD)", default="LGPL") > parser.add_option("--generated-header", dest="generated_header", metavar="FILE", > help="Name of the file to generate the header") > +parser.add_option("--generated-declaration-file", dest="generated_declaration_file", metavar="FILE", > + help="Name of the file to generate declarations") > > (options, args) = parser.parse_args() > > @@ -259,6 +261,51 @@ else: > print >> sys.stderr, "Invalid license specified: %s" % options.license > sys.exit(1) > > +all_structures = {} > +def generate_declaration(t, writer_top): > + writer = codegen.CodeWriter() > + try: > + c_type = t.c_type() > + t.generate_c_declaration(writer) > + value = writer.getvalue().strip() > + if not value: > + return > + if c_type in all_structures: > + assert all_structures[c_type] == value, """Structure %s redefinition > +previous: > +%s > +--- > +current: > +%s > +---""" % (c_type, all_structures[c_type], value) > + else: > + all_structures[c_type] = value > + t.generate_c_declaration(writer_top) > + except: > + print >> sys.stderr, 'type %s' % t > + print >> sys.stderr, writer.getvalue() > + traceback.print_exc(sys.stderr) > + > +def generate_declarations(): > + writer = codegen.CodeWriter() > + writer.public_prefix = options.prefix > + writer.write(license) > + > + # all types > + for t in ptypes.get_named_types(): > + if isinstance(t, ptypes.StructType): > + generate_declaration(t, writer) > + if isinstance(t, ptypes.ChannelType): > + for m in t.client_messages + t.server_messages: > + generate_declaration(m.message_type, writer) > + > + content = writer.getvalue() > + write_content(options.generated_declaration_file, content, > + options.keep_identical_file) > + > +if options.generated_declaration_file: > + generate_declarations() > + > writer.public_prefix = options.prefix > > writer.writeln("/* this is a file autogenerated by spice_codegen.py */") > -- > 2.20.1 > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/spice-devel
Attachment:
signature.asc
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel