|
|
1.1 root 1: #
2: # QAPI visitor generator
3: #
4: # Copyright IBM, Corp. 2011
5: #
6: # Authors:
7: # Anthony Liguori <[email protected]>
8: # Michael Roth <[email protected]>
9: #
10: # This work is licensed under the terms of the GNU GPLv2.
11: # See the COPYING.LIB file in the top-level directory.
12:
13: from ordereddict import OrderedDict
14: from qapi import *
15: import sys
16: import os
17: import getopt
18: import errno
19:
20: def generate_visit_struct_body(field_prefix, members):
21: ret = ""
22: if len(field_prefix):
23: field_prefix = field_prefix + "."
24: for argname, argentry, optional, structured in parse_args(members):
25: if optional:
26: ret += mcgen('''
27: visit_start_optional(m, (obj && *obj) ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", errp);
28: if ((*obj)->%(prefix)shas_%(c_name)s) {
29: ''',
30: c_prefix=c_var(field_prefix), prefix=field_prefix,
31: c_name=c_var(argname), name=argname)
32: push_indent()
33:
34: if structured:
35: ret += mcgen('''
36: visit_start_struct(m, NULL, "", "%(name)s", 0, errp);
37: ''',
38: name=argname)
39: ret += generate_visit_struct_body(field_prefix + argname, argentry)
40: ret += mcgen('''
41: visit_end_struct(m, errp);
42: ''')
43: else:
44: ret += mcgen('''
45: visit_type_%(type)s(m, (obj && *obj) ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", errp);
46: ''',
47: c_prefix=c_var(field_prefix), prefix=field_prefix,
48: type=type_name(argentry), c_name=c_var(argname),
49: name=argname)
50:
51: if optional:
52: pop_indent()
53: ret += mcgen('''
54: }
55: visit_end_optional(m, errp);
56: ''')
57: return ret
58:
59: def generate_visit_struct(name, members):
60: ret = mcgen('''
61:
62: void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
63: {
1.1.1.3 ! root 64: if (error_is_set(errp)) {
! 65: return;
! 66: }
1.1 root 67: visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp);
1.1.1.3 ! root 68: if (obj && !*obj) {
! 69: goto end;
! 70: }
1.1 root 71: ''',
72: name=name)
73: push_indent()
74: ret += generate_visit_struct_body("", members)
75: pop_indent()
76:
77: ret += mcgen('''
1.1.1.3 ! root 78: end:
1.1 root 79: visit_end_struct(m, errp);
80: }
81: ''')
82: return ret
83:
84: def generate_visit_list(name, members):
85: return mcgen('''
86:
87: void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
88: {
1.1.1.3 ! root 89: GenericList *i, **prev = (GenericList **)obj;
1.1 root 90:
1.1.1.3 ! root 91: if (error_is_set(errp)) {
! 92: return;
! 93: }
1.1 root 94: visit_start_list(m, name, errp);
95:
1.1.1.3 ! root 96: for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
1.1 root 97: %(name)sList *native_i = (%(name)sList *)i;
98: visit_type_%(name)s(m, &native_i->value, NULL, errp);
99: }
100:
101: visit_end_list(m, errp);
102: }
103: ''',
104: name=name)
105:
106: def generate_visit_enum(name, members):
107: return mcgen('''
108:
109: void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp)
110: {
111: visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp);
112: }
113: ''',
114: name=name)
115:
116: def generate_visit_union(name, members):
117: ret = generate_visit_enum('%sKind' % name, members.keys())
118:
119: ret += mcgen('''
120:
121: void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
122: {
1.1.1.3 ! root 123: Error *err = NULL;
! 124:
! 125: if (error_is_set(errp)) {
! 126: return;
! 127: }
! 128: visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
! 129: if (obj && !*obj) {
! 130: goto end;
! 131: }
! 132: visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
! 133: if (err) {
! 134: error_propagate(errp, err);
! 135: goto end;
! 136: }
! 137: switch ((*obj)->kind) {
1.1 root 138: ''',
139: name=name)
140:
1.1.1.3 ! root 141: for key in members:
! 142: ret += mcgen('''
! 143: case %(abbrev)s_KIND_%(enum)s:
! 144: visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", errp);
! 145: break;
! 146: ''',
! 147: abbrev = de_camel_case(name).upper(),
! 148: enum = c_fun(de_camel_case(key)).upper(),
! 149: c_type=members[key],
! 150: c_name=c_fun(key))
! 151:
! 152: ret += mcgen('''
! 153: default:
! 154: abort();
! 155: }
! 156: end:
! 157: visit_end_struct(m, errp);
! 158: }
! 159: ''')
! 160:
1.1 root 161: return ret
162:
163: def generate_declaration(name, members, genlist=True):
164: ret = mcgen('''
165:
166: void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
167: ''',
168: name=name)
169:
170: if genlist:
171: ret += mcgen('''
172: void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp);
173: ''',
174: name=name)
175:
176: return ret
177:
178: def generate_decl_enum(name, members, genlist=True):
179: return mcgen('''
180:
181: void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
182: ''',
183: name=name)
184:
185: try:
1.1.1.3 ! root 186: opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
! 187: ["source", "header", "prefix=", "output-dir="])
1.1 root 188: except getopt.GetoptError, err:
189: print str(err)
190: sys.exit(1)
191:
192: output_dir = ""
193: prefix = ""
194: c_file = 'qapi-visit.c'
195: h_file = 'qapi-visit.h'
196:
1.1.1.3 ! root 197: do_c = False
! 198: do_h = False
! 199:
1.1 root 200: for o, a in opts:
201: if o in ("-p", "--prefix"):
202: prefix = a
203: elif o in ("-o", "--output-dir"):
204: output_dir = a + "/"
1.1.1.3 ! root 205: elif o in ("-c", "--source"):
! 206: do_c = True
! 207: elif o in ("-h", "--header"):
! 208: do_h = True
! 209:
! 210: if not do_c and not do_h:
! 211: do_c = True
! 212: do_h = True
1.1 root 213:
214: c_file = output_dir + prefix + c_file
215: h_file = output_dir + prefix + h_file
216:
217: try:
218: os.makedirs(output_dir)
219: except os.error, e:
220: if e.errno != errno.EEXIST:
221: raise
222:
1.1.1.3 ! root 223: def maybe_open(really, name, opt):
! 224: if really:
! 225: return open(name, opt)
! 226: else:
! 227: import StringIO
! 228: return StringIO.StringIO()
! 229:
! 230: fdef = maybe_open(do_c, c_file, 'w')
! 231: fdecl = maybe_open(do_h, h_file, 'w')
1.1 root 232:
233: fdef.write(mcgen('''
234: /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
235:
236: /*
237: * schema-defined QAPI visitor functions
238: *
239: * Copyright IBM, Corp. 2011
240: *
241: * Authors:
242: * Anthony Liguori <[email protected]>
243: *
244: * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
245: * See the COPYING.LIB file in the top-level directory.
246: *
247: */
248:
249: #include "%(header)s"
250: ''',
251: header=basename(h_file)))
252:
253: fdecl.write(mcgen('''
254: /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
255:
256: /*
257: * schema-defined QAPI visitor function
258: *
259: * Copyright IBM, Corp. 2011
260: *
261: * Authors:
262: * Anthony Liguori <[email protected]>
263: *
264: * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
265: * See the COPYING.LIB file in the top-level directory.
266: *
267: */
268:
269: #ifndef %(guard)s
270: #define %(guard)s
271:
272: #include "qapi/qapi-visit-core.h"
273: #include "%(prefix)sqapi-types.h"
274: ''',
275: prefix=prefix, guard=guardname(h_file)))
276:
277: exprs = parse_schema(sys.stdin)
278:
279: for expr in exprs:
280: if expr.has_key('type'):
281: ret = generate_visit_struct(expr['type'], expr['data'])
282: ret += generate_visit_list(expr['type'], expr['data'])
283: fdef.write(ret)
284:
285: ret = generate_declaration(expr['type'], expr['data'])
286: fdecl.write(ret)
287: elif expr.has_key('union'):
288: ret = generate_visit_union(expr['union'], expr['data'])
1.1.1.3 ! root 289: ret += generate_visit_list(expr['union'], expr['data'])
1.1 root 290: fdef.write(ret)
291:
292: ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys())
293: ret += generate_declaration(expr['union'], expr['data'])
294: fdecl.write(ret)
295: elif expr.has_key('enum'):
296: ret = generate_visit_enum(expr['enum'], expr['data'])
297: fdef.write(ret)
298:
299: ret = generate_decl_enum(expr['enum'], expr['data'])
300: fdecl.write(ret)
301:
302: fdecl.write('''
303: #endif
304: ''')
305:
306: fdecl.flush()
307: fdecl.close()
308:
309: fdef.flush()
310: fdef.close()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.