|
|
1.1 ! root 1: # ! 2: # QAPI command marshaller 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_decl_enum(name, members, genlist=True): ! 21: return mcgen(''' ! 22: ! 23: void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp); ! 24: ''', ! 25: name=name) ! 26: ! 27: def generate_command_decl(name, args, ret_type): ! 28: arglist="" ! 29: for argname, argtype, optional, structured in parse_args(args): ! 30: argtype = c_type(argtype) ! 31: if argtype == "char *": ! 32: argtype = "const char *" ! 33: if optional: ! 34: arglist += "bool has_%s, " % c_var(argname) ! 35: arglist += "%s %s, " % (argtype, c_var(argname)) ! 36: return mcgen(''' ! 37: %(ret_type)s qmp_%(name)s(%(args)sError **errp); ! 38: ''', ! 39: ret_type=c_type(ret_type), name=c_var(name), args=arglist).strip() ! 40: ! 41: def gen_sync_call(name, args, ret_type, indent=0): ! 42: ret = "" ! 43: arglist="" ! 44: retval="" ! 45: if ret_type: ! 46: retval = "retval = " ! 47: for argname, argtype, optional, structured in parse_args(args): ! 48: if optional: ! 49: arglist += "has_%s, " % c_var(argname) ! 50: arglist += "%s, " % (c_var(argname)) ! 51: push_indent(indent) ! 52: ret = mcgen(''' ! 53: %(retval)sqmp_%(name)s(%(args)serrp); ! 54: ! 55: ''', ! 56: name=c_var(name), args=arglist, retval=retval).rstrip() ! 57: if ret_type: ! 58: ret += "\n" + mcgen('''' ! 59: %(marshal_output_call)s ! 60: ''', ! 61: marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip() ! 62: pop_indent(indent) ! 63: return ret.rstrip() ! 64: ! 65: ! 66: def gen_marshal_output_call(name, ret_type): ! 67: if not ret_type: ! 68: return "" ! 69: return "qmp_marshal_output_%s(retval, ret, errp);" % c_var(name) ! 70: ! 71: def gen_visitor_output_containers_decl(ret_type): ! 72: ret = "" ! 73: push_indent() ! 74: if ret_type: ! 75: ret += mcgen(''' ! 76: QmpOutputVisitor *mo; ! 77: QapiDeallocVisitor *md; ! 78: Visitor *v; ! 79: ''') ! 80: pop_indent() ! 81: ! 82: return ret ! 83: ! 84: def gen_visitor_input_containers_decl(args): ! 85: ret = "" ! 86: ! 87: push_indent() ! 88: if len(args) > 0: ! 89: ret += mcgen(''' ! 90: QmpInputVisitor *mi; ! 91: QapiDeallocVisitor *md; ! 92: Visitor *v; ! 93: ''') ! 94: pop_indent() ! 95: ! 96: return ret.rstrip() ! 97: ! 98: def gen_visitor_input_vars_decl(args): ! 99: ret = "" ! 100: push_indent() ! 101: for argname, argtype, optional, structured in parse_args(args): ! 102: if optional: ! 103: ret += mcgen(''' ! 104: bool has_%(argname)s = false; ! 105: ''', ! 106: argname=c_var(argname)) ! 107: if c_type(argtype).endswith("*"): ! 108: ret += mcgen(''' ! 109: %(argtype)s %(argname)s = NULL; ! 110: ''', ! 111: argname=c_var(argname), argtype=c_type(argtype)) ! 112: else: ! 113: ret += mcgen(''' ! 114: %(argtype)s %(argname)s; ! 115: ''', ! 116: argname=c_var(argname), argtype=c_type(argtype)) ! 117: ! 118: pop_indent() ! 119: return ret.rstrip() ! 120: ! 121: def gen_visitor_input_block(args, obj, dealloc=False): ! 122: ret = "" ! 123: if len(args) == 0: ! 124: return ret ! 125: ! 126: push_indent() ! 127: ! 128: if dealloc: ! 129: ret += mcgen(''' ! 130: md = qapi_dealloc_visitor_new(); ! 131: v = qapi_dealloc_get_visitor(md); ! 132: ''') ! 133: else: ! 134: ret += mcgen(''' ! 135: mi = qmp_input_visitor_new(%(obj)s); ! 136: v = qmp_input_get_visitor(mi); ! 137: ''', ! 138: obj=obj) ! 139: ! 140: for argname, argtype, optional, structured in parse_args(args): ! 141: if optional: ! 142: ret += mcgen(''' ! 143: visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp); ! 144: if (has_%(c_name)s) { ! 145: ''', ! 146: c_name=c_var(argname), name=argname) ! 147: push_indent() ! 148: ret += mcgen(''' ! 149: visit_type_%(argtype)s(v, &%(c_name)s, "%(name)s", errp); ! 150: ''', ! 151: c_name=c_var(argname), name=argname, argtype=argtype) ! 152: if optional: ! 153: pop_indent() ! 154: ret += mcgen(''' ! 155: } ! 156: visit_end_optional(v, errp); ! 157: ''') ! 158: ! 159: if dealloc: ! 160: ret += mcgen(''' ! 161: qapi_dealloc_visitor_cleanup(md); ! 162: ''') ! 163: else: ! 164: ret += mcgen(''' ! 165: qmp_input_visitor_cleanup(mi); ! 166: ''') ! 167: pop_indent() ! 168: return ret.rstrip() ! 169: ! 170: def gen_marshal_output(name, args, ret_type): ! 171: if not ret_type: ! 172: return "" ! 173: ret = mcgen(''' ! 174: static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp) ! 175: { ! 176: QapiDeallocVisitor *md = qapi_dealloc_visitor_new(); ! 177: QmpOutputVisitor *mo = qmp_output_visitor_new(); ! 178: Visitor *v; ! 179: ! 180: v = qmp_output_get_visitor(mo); ! 181: visit_type_%(ret_type)s(v, &ret_in, "unused", errp); ! 182: if (!error_is_set(errp)) { ! 183: *ret_out = qmp_output_get_qobject(mo); ! 184: } ! 185: qmp_output_visitor_cleanup(mo); ! 186: v = qapi_dealloc_get_visitor(md); ! 187: visit_type_%(ret_type)s(v, &ret_in, "unused", errp); ! 188: qapi_dealloc_visitor_cleanup(md); ! 189: } ! 190: ''', ! 191: c_ret_type=c_type(ret_type), c_name=c_var(name), ret_type=ret_type) ! 192: ! 193: return ret ! 194: ! 195: def gen_marshal_input(name, args, ret_type): ! 196: ret = mcgen(''' ! 197: static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **errp) ! 198: { ! 199: ''', ! 200: c_name=c_var(name)) ! 201: ! 202: if ret_type: ! 203: if c_type(ret_type).endswith("*"): ! 204: retval = " %s retval = NULL;" % c_type(ret_type) ! 205: else: ! 206: retval = " %s retval;" % c_type(ret_type) ! 207: ret += mcgen(''' ! 208: %(retval)s ! 209: ''', ! 210: retval=retval) ! 211: ! 212: if len(args) > 0: ! 213: ret += mcgen(''' ! 214: %(visitor_input_containers_decl)s ! 215: %(visitor_input_vars_decl)s ! 216: ! 217: %(visitor_input_block)s ! 218: ! 219: ''', ! 220: visitor_input_containers_decl=gen_visitor_input_containers_decl(args), ! 221: visitor_input_vars_decl=gen_visitor_input_vars_decl(args), ! 222: visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)")) ! 223: ! 224: ret += mcgen(''' ! 225: if (error_is_set(errp)) { ! 226: goto out; ! 227: } ! 228: %(sync_call)s ! 229: ''', ! 230: sync_call=gen_sync_call(name, args, ret_type, indent=4)) ! 231: ret += mcgen(''' ! 232: ! 233: out: ! 234: ''') ! 235: ret += mcgen(''' ! 236: %(visitor_input_block_cleanup)s ! 237: return; ! 238: } ! 239: ''', ! 240: visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True)) ! 241: return ret ! 242: ! 243: def gen_registry(commands): ! 244: registry="" ! 245: push_indent() ! 246: for cmd in commands: ! 247: registry += mcgen(''' ! 248: qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s); ! 249: ''', ! 250: name=cmd['command'], c_name=c_var(cmd['command'])) ! 251: pop_indent() ! 252: ret = mcgen(''' ! 253: static void qmp_init_marshal(void) ! 254: { ! 255: %(registry)s ! 256: } ! 257: ! 258: qapi_init(qmp_init_marshal); ! 259: ''', ! 260: registry=registry.rstrip()) ! 261: return ret ! 262: ! 263: def gen_command_decl_prologue(header, guard, prefix=""): ! 264: ret = mcgen(''' ! 265: /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ ! 266: ! 267: /* ! 268: * schema-defined QAPI function prototypes ! 269: * ! 270: * Copyright IBM, Corp. 2011 ! 271: * ! 272: * Authors: ! 273: * Anthony Liguori <[email protected]> ! 274: * ! 275: * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. ! 276: * See the COPYING.LIB file in the top-level directory. ! 277: * ! 278: */ ! 279: ! 280: #ifndef %(guard)s ! 281: #define %(guard)s ! 282: ! 283: #include "%(prefix)sqapi-types.h" ! 284: #include "error.h" ! 285: ! 286: ''', ! 287: header=basename(h_file), guard=guardname(h_file), prefix=prefix) ! 288: return ret ! 289: ! 290: def gen_command_def_prologue(prefix="", proxy=False): ! 291: ret = mcgen(''' ! 292: /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ ! 293: ! 294: /* ! 295: * schema-defined QMP->QAPI command dispatch ! 296: * ! 297: * Copyright IBM, Corp. 2011 ! 298: * ! 299: * Authors: ! 300: * Anthony Liguori <[email protected]> ! 301: * ! 302: * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. ! 303: * See the COPYING.LIB file in the top-level directory. ! 304: * ! 305: */ ! 306: ! 307: #include "qemu-objects.h" ! 308: #include "qapi/qmp-core.h" ! 309: #include "qapi/qapi-visit-core.h" ! 310: #include "qapi/qmp-output-visitor.h" ! 311: #include "qapi/qmp-input-visitor.h" ! 312: #include "qapi/qapi-dealloc-visitor.h" ! 313: #include "%(prefix)sqapi-types.h" ! 314: #include "%(prefix)sqapi-visit.h" ! 315: ! 316: ''', ! 317: prefix=prefix) ! 318: if not proxy: ! 319: ret += '#include "%sqmp-commands.h"' % prefix ! 320: return ret + "\n" ! 321: ! 322: ! 323: try: ! 324: opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir=", "type="]) ! 325: except getopt.GetoptError, err: ! 326: print str(err) ! 327: sys.exit(1) ! 328: ! 329: output_dir = "" ! 330: prefix = "" ! 331: dispatch_type = "sync" ! 332: c_file = 'qmp-marshal.c' ! 333: h_file = 'qmp-commands.h' ! 334: ! 335: for o, a in opts: ! 336: if o in ("-p", "--prefix"): ! 337: prefix = a ! 338: elif o in ("-o", "--output-dir"): ! 339: output_dir = a + "/" ! 340: elif o in ("-t", "--type"): ! 341: dispatch_type = a ! 342: ! 343: c_file = output_dir + prefix + c_file ! 344: h_file = output_dir + prefix + h_file ! 345: ! 346: try: ! 347: os.makedirs(output_dir) ! 348: except os.error, e: ! 349: if e.errno != errno.EEXIST: ! 350: raise ! 351: ! 352: exprs = parse_schema(sys.stdin) ! 353: commands = filter(lambda expr: expr.has_key('command'), exprs) ! 354: ! 355: if dispatch_type == "sync": ! 356: fdecl = open(h_file, 'w') ! 357: fdef = open(c_file, 'w') ! 358: ret = gen_command_decl_prologue(header=basename(h_file), guard=guardname(h_file), prefix=prefix) ! 359: fdecl.write(ret) ! 360: ret = gen_command_def_prologue(prefix=prefix) ! 361: fdef.write(ret) ! 362: ! 363: for cmd in commands: ! 364: arglist = [] ! 365: ret_type = None ! 366: if cmd.has_key('data'): ! 367: arglist = cmd['data'] ! 368: if cmd.has_key('returns'): ! 369: ret_type = cmd['returns'] ! 370: ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n" ! 371: fdecl.write(ret) ! 372: if ret_type: ! 373: ret = gen_marshal_output(cmd['command'], arglist, ret_type) + "\n" ! 374: fdef.write(ret) ! 375: ret = gen_marshal_input(cmd['command'], arglist, ret_type) + "\n" ! 376: fdef.write(ret) ! 377: ! 378: fdecl.write("\n#endif"); ! 379: ret = gen_registry(commands) ! 380: fdef.write(ret) ! 381: ! 382: fdef.flush() ! 383: fdef.close() ! 384: fdecl.flush() ! 385: fdecl.close()
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.