Get rid of string type and replace with a bool type
[fidl.git] / qemu-gen-marshal
blobea3c2a079d966737887977479beda78ab5aecc6b
1 #!/usr/bin/python
2 ##
3 # Flexible IDL framework
5 # Copyright IBM, Corp. 2010
7 # Authors:
8 # Anthony Liguori <aliguori@us.ibm.com>
10 # This work is licensed under the terms of the GNU GPL, version 2. See
11 # the COPYING file in the top-level directory.
14 from fidl import parse, scan, ASTWalker
16 # Generate the function name of the marshalling function for a type
17 class Marshaller(ASTWalker):
18 def n_type(self, node):
19 if node.value.endswith('_t'):
20 return node.value[:-2]
21 return node.value
23 def n_input(self, node):
24 if node.base.value == 'char':
25 return 'string'
26 else:
27 return self.walk(node.base)
29 def n_output(self, node):
30 return self.walk(node.base)
32 def n_struct(self, node):
33 return 'struct_%s' % node.name
35 def marshalfn(t):
36 m = Marshaller()
37 return 'marshal_%s' % m.walk(t)
39 # Helper to emit code depending on the output mode
40 def emit(f, definition, body, header=False):
41 if header:
42 f.write('''%s;
43 ''' % definition)
44 else:
45 f.write('''%s
50 ''' % (definition, '\n '.join(body)))
52 # Walk the AST and generate marshalling code. We always generate the body but
53 # mark the function definitions in a special way. The header generation then
54 # discards everything but the function definitions.
55 class Walker(ASTWalker):
56 def __init__(self, f, header=False):
57 ASTWalker.__init__(self)
58 self.header = header
59 self.f = f
61 # helper to generate the marshalling code for an array
62 def c_array(self, node, ns):
63 body = []
64 body.append('marshal_start_array(m, "%s", errp);' % node.name)
65 body.append('if (error_is_set(errp)) {')
66 body.append(' return;')
67 body.append('}')
69 if node.type.kind == 'array':
70 body.append('for (i = 0; i < %s; i++) {' % node.size)
71 elif node.type.kind == 'varray':
72 body.append('for (i = 0; i < %s%s; i++) {' % (ns, node.type.size))
73 marshaller = marshalfn(node.type.base)
74 body.append(' %s(m, &%s%s[i], NULL, errp);' %
75 (marshaller, ns, node.name))
76 body.append(' if (error_is_set(errp)) {')
77 body.append(' return;')
78 body.append(' }')
79 body.append('}')
80 body.append('marshal_end_array(m, errp);')
81 body.append('if (error_is_set(errp)) {')
82 body.append(' return;')
83 body.append('}')
84 return body
86 # helper to generate marshalling code for a structure
87 def c_struct(self, node, name, ns):
88 body = []
89 if node.name:
90 kind = '"%s"' % node.name
91 else:
92 kind = 'NULL'
94 if hasattr(node, 'feature'):
95 body.append('marshal_start_feature(m, &%s%s, "%s", errp);' % (ns, node.feature, node.feature))
96 body.append('if (error_is_set(errp)) {')
97 body.append(' return;')
98 body.append('}')
100 body.append('marshal_start_struct(m, %s, %s, errp);' % (kind, name))
101 body.append('if (error_is_set(errp)) {')
102 body.append(' return;')
103 body.append('}')
104 for member in node.members:
105 marshaller = marshalfn(member.type)
106 if hasattr(node, 'feature') and member.name == node.feature:
107 continue
108 if member.type.kind == 'output':
109 body.append('%s(m, %s%s, "%s", errp);' % (marshaller, ns, member.name, member.name))
110 body.append('if (error_is_set(errp)) {')
111 body.append(' return;')
112 body.append('}')
113 elif member.type.kind in ['array', 'varray']:
114 body += self.c_array(member, ns)
115 elif member.type.kind == 'struct' and hasattr(member.type, 'members'):
116 body += self.c_struct(member.type, '"%s"' % member.name, "%s%s." % (ns, member.name))
117 else:
118 body.append('%s(m, &%s%s, "%s", errp);' % (marshaller, ns, member.name, member.name))
119 body.append('if (error_is_set(errp)) {')
120 body.append(' return;')
121 body.append('}')
122 body.append('marshal_end_struct(m, errp);')
123 body.append('if (error_is_set(errp)) {')
124 body.append(' return;')
125 body.append('}')
126 if hasattr(node, 'feature'):
127 body.append('marshal_end_feature(m, errp);')
128 body.append('if (error_is_set(errp)) {')
129 body.append(' return;')
130 body.append('}')
131 return body
134 # visitor for structs
135 def n_struct(self, node):
136 if hasattr(node, 'members'):
137 hdr = 'void marshal_struct_%s(Marshaller *m, struct %s *obj, const char *name, Error **errp)' % (
138 node.name, node.name)
140 body = []
141 body.append('int i = 0;')
142 body.append('(void)i;')
143 body += self.c_struct(node, 'name', 'obj->')
144 emit(self.f, hdr, body, self.header)
145 return None
147 # visitor for typedefs. we output a second function and call the marshaller
148 # for the base type.
149 def n_typedef(self, node):
150 self.walk(node.base)
151 emit(self.f, 'void marshal_%s(Marshaller *m, %s *obj, const char *name, Error **errp)' %
152 (node.alias, node.alias),
153 ['%s(m, obj, name, errp);' % marshalfn(node.base)], self.header)
154 return None
156 def walk(f, tree, header=False):
157 walker = Walker(f, header)
158 return walker.walk(tree)
160 # generate a C or H file
161 def generate(filename, base, tree, header=False):
162 f = open(filename, 'w')
164 f.write('''/* THIS FILE IS AUTO-GENERATED, DO NOT EDIT */
166 ''')
167 if header:
168 guard = base.rsplit('.', 1)[0]
169 guard = guard.rsplit('/', 1)[-1]
170 guard = guard.upper()
171 guard = guard.replace('-', '_')
172 guard = 'QEMU_%s_MARSHAL_H' % guard
173 f.write('''#ifndef %s
174 #define %s
176 #include "marshal.h"
177 #include "%s"
179 ''' % (guard, guard, base))
180 else:
181 f.write('''#include "%s.h"
183 ''' % filename.rsplit('.', 1)[0])
185 walk(f, tree, header)
187 if header:
188 f.write('''
189 #endif
190 ''')
192 f.close()
194 def usage(name):
195 print '''Usage: %s [OPTIONS] FILENAME OUTPUT
196 Generate marshalling code from header FILENAME
198 Where OPTIONS may be:
200 -h, --help display this help screen
201 --debug-scan display lexical pass results
202 --debug-parse display initial parse tree
203 --header generate marshalling header in OUTPUT
204 --body generating marshalling body in OUTPUT (default)
206 Report bugs to <qemu-devel@nongnu.org>''' % name
208 def main(args):
209 import getopt
211 opts, args = getopt.getopt(args, 'h',
212 ['debug-scan', 'debug-parse',
213 'header', 'body', 'help'])
215 header = False
216 debug_scan = False
217 debug_parse = False
219 for opt, value in opts:
220 if opt in ['-h', '--help']:
221 usage('qemu-gen-marshal')
222 return 0
223 elif opt in ['--debug-scan']:
224 debug_scan = True
225 elif opt in ['--debug-parse']:
226 debug_parse = True
227 elif opt in ['--header']:
228 header = True
229 elif opt in ['--body']:
230 header = False
232 if len(args) != 2:
233 sys.stderr.write('Incorrect number of arguments\n')
234 usage('qemu-gen-marshal')
235 return 1
237 filename = args[0]
238 output = args[1]
240 f = open(filename)
242 s = scan(f)
243 if debug_scan:
244 print s
246 tree = parse(s)
247 if debug_parse:
248 print tree
250 f.close()
251 generate(output, filename, tree, header)
253 return 0
255 if __name__ == '__main__':
256 import sys
257 main(sys.argv[1:])