5 from optparse import OptionParser
7 from python_modules import spice_parser
8 from python_modules import ptypes
9 from python_modules import codegen
10 from python_modules import demarshal
11 from python_modules import marshal
13 def write_channel_enums(writer, channel, client):
14 messages = filter(lambda m : m.channel == channel, \
15 channel.client_messages if client else channel.server_messages)
16 if len(messages) == 0:
18 writer.begin_block("enum")
24 if channel.member_name:
25 prefix.append(channel.member_name.upper())
26 prefix.append(None) # To be replaced with name
28 prefix[-1] = m.name.upper()
29 enum = codegen.prefix_underscore_upper(*prefix)
31 writer.writeln("%s," % enum)
34 writer.writeln("%s = %s," % (enum, m.value))
36 if channel.member_name:
37 prefix[-1] = prefix[-2]
40 writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix)))
41 writer.end_block(semicolon=True)
44 def write_enums(writer):
45 writer.writeln("#ifndef _H_SPICE_ENUMS")
46 writer.writeln("#define _H_SPICE_ENUMS")
48 writer.comment("Generated from %s, don't edit" % writer.options["source"]).newline()
52 for t in ptypes.get_named_types():
53 if isinstance(t, ptypes.EnumBaseType):
57 writer.begin_block("enum")
58 for c in proto.channels:
59 enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
61 writer.writeln("%s," % enum)
64 writer.writeln("%s = %s," % (enum, c.value))
67 writer.writeln("SPICE_END_CHANNEL")
68 writer.end_block(semicolon=True)
71 for c in ptypes.get_named_types():
72 if not isinstance(c, ptypes.ChannelType):
74 write_channel_enums(writer, c, False)
75 write_channel_enums(writer, c, True)
77 writer.writeln("#endif /* _H_SPICE_ENUMS */")
79 parser = OptionParser(usage="usage: %prog [options] <protocol_file> <destination file>")
80 parser.add_option("-e", "--generate-enums",
81 action="store_true", dest="generate_enums", default=False,
82 help="Generate enums")
83 parser.add_option("-d", "--generate-demarshallers",
84 action="store_true", dest="generate_demarshallers", default=False,
85 help="Generate demarshallers")
86 parser.add_option("-m", "--generate-marshallers",
87 action="store_true", dest="generate_marshallers", default=False,
88 help="Generate message marshallers")
89 parser.add_option("-P", "--private-marshallers",
90 action="store_true", dest="private_marshallers", default=False,
91 help="Generate private message marshallers")
92 parser.add_option("-M", "--generate-struct-marshaller",
93 action="append", dest="struct_marshallers",
94 help="Generate struct marshallers")
95 parser.add_option("-a", "--assert-on-error",
96 action="store_true", dest="assert_on_error", default=False,
97 help="Assert on error")
98 parser.add_option("-H", "--header",
99 action="store_true", dest="header", default=False,
100 help="Generate header")
101 parser.add_option("-p", "--print-error",
102 action="store_true", dest="print_error", default=False,
104 parser.add_option("-s", "--server",
105 action="store_true", dest="server", default=False,
107 parser.add_option("-c", "--client",
108 action="store_true", dest="client", default=False,
110 parser.add_option("-k", "--keep-identical-file",
111 action="store_true", dest="keep_identical_file", default=False,
113 parser.add_option("-i", "--include",
114 action="append", dest="includes", metavar="FILE",
115 help="Include FILE in generated code")
116 parser.add_option("--prefix", dest="prefix",
117 help="set public symbol prefix", default="")
118 parser.add_option("--ptrsize", dest="ptrsize",
119 help="set default pointer size", default="4")
121 (options, args) = parser.parse_args()
124 parser.error("No protocol file specified")
127 parser.error("No destination file specified")
129 ptypes.default_pointer_size = int(options.ptrsize)
133 proto = spice_parser.parse(proto_file)
138 codegen.set_prefix(proto.name)
139 writer = codegen.CodeWriter()
140 writer.header = codegen.CodeWriter()
141 writer.set_option("source", os.path.basename(proto_file))
143 writer.public_prefix = options.prefix
145 writer.writeln("/* this is a file autogenerated by spice_codegen.py */")
146 writer.header.writeln("/* this is a file autogenerated by spice_codegen.py */")
147 if not options.header and not options.generate_enums:
148 writer.writeln("#ifdef HAVE_CONFIG_H")
149 writer.writeln("#include <config.h>")
150 writer.writeln("#endif")
152 if options.assert_on_error:
153 writer.set_option("assert_on_error")
155 if options.print_error:
156 writer.set_option("print_error")
159 for i in options.includes:
160 writer.header.writeln('#include "%s"' % i)
161 writer.writeln('#include "%s"' % i)
163 if options.generate_enums:
166 if options.generate_demarshallers:
167 if not options.server and not options.client:
168 print >> sys.stderr, "Must specify client and/or server"
170 demarshal.write_includes(writer)
173 demarshal.write_protocol_parser(writer, proto, False)
175 demarshal.write_protocol_parser(writer, proto, True)
177 if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0):
178 marshal.write_includes(writer)
180 if options.generate_marshallers:
181 if not options.server and not options.client:
182 print >> sys.stderr, "Must specify client and/or server"
185 marshal.write_protocol_marshaller(writer, proto, False, options.private_marshallers)
187 marshal.write_protocol_marshaller(writer, proto, True, options.private_marshallers)
189 if options.struct_marshallers:
190 for structname in options.struct_marshallers:
191 t = ptypes.lookup_type(structname)
192 marshal.write_marshal_ptr_function(writer, t, False)
194 if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0):
195 marshal.write_trailer(writer)
198 content = writer.header.getvalue()
200 content = writer.getvalue()
201 if options.keep_identical_file:
203 f = open(dest_file, 'rb')
204 old_content = f.read()
207 if content == old_content:
208 print "No changes to %s" % dest_file
214 f = open(dest_file, 'wb')
218 print "Wrote %s" % dest_file