qemu/scripts/qapi-event.py
<<
>>
Prefs
   1#
   2# QAPI event generator
   3#
   4# Copyright (c) 2014 Wenchao Xia
   5# Copyright (c) 2015-2016 Red Hat Inc.
   6#
   7# Authors:
   8#  Wenchao Xia <wenchaoqemu@gmail.com>
   9#  Markus Armbruster <armbru@redhat.com>
  10#
  11# This work is licensed under the terms of the GNU GPL, version 2.
  12# See the COPYING file in the top-level directory.
  13
  14from qapi import *
  15
  16
  17def gen_event_send_proto(name, arg_type):
  18    return 'void qapi_event_send_%(c_name)s(%(param)s)' % {
  19        'c_name': c_name(name.lower()),
  20        'param': gen_params(arg_type, 'Error **errp')}
  21
  22
  23def gen_event_send_decl(name, arg_type):
  24    return mcgen('''
  25
  26%(proto)s;
  27''',
  28                 proto=gen_event_send_proto(name, arg_type))
  29
  30
  31# Declare and initialize an object 'qapi' using parameters from gen_params()
  32def gen_param_var(typ):
  33    assert not typ.variants
  34    ret = mcgen('''
  35    %(c_name)s param = {
  36''',
  37                c_name=typ.c_name())
  38    sep = '        '
  39    for memb in typ.members:
  40        ret += sep
  41        sep = ', '
  42        if memb.optional:
  43            ret += 'has_' + c_name(memb.name) + sep
  44        if memb.type.name == 'str':
  45            # Cast away const added in gen_params()
  46            ret += '(char *)'
  47        ret += c_name(memb.name)
  48    ret += mcgen('''
  49
  50    };
  51''')
  52    return ret
  53
  54
  55def gen_event_send(name, arg_type):
  56    # FIXME: Our declaration of local variables (and of 'errp' in the
  57    # parameter list) can collide with exploded members of the event's
  58    # data type passed in as parameters.  If this collision ever hits in
  59    # practice, we can rename our local variables with a leading _ prefix,
  60    # or split the code into a wrapper function that creates a boxed
  61    # 'param' object then calls another to do the real work.
  62    ret = mcgen('''
  63
  64%(proto)s
  65{
  66    QDict *qmp;
  67    Error *err = NULL;
  68    QMPEventFuncEmit emit;
  69''',
  70                proto=gen_event_send_proto(name, arg_type))
  71
  72    if arg_type and arg_type.members:
  73        ret += mcgen('''
  74    QmpOutputVisitor *qov;
  75    Visitor *v;
  76''')
  77        ret += gen_param_var(arg_type)
  78
  79    ret += mcgen('''
  80
  81    emit = qmp_event_get_func_emit();
  82    if (!emit) {
  83        return;
  84    }
  85
  86    qmp = qmp_event_build_dict("%(name)s");
  87
  88''',
  89                 name=name)
  90
  91    if arg_type and arg_type.members:
  92        ret += mcgen('''
  93    qov = qmp_output_visitor_new();
  94    v = qmp_output_get_visitor(qov);
  95
  96    visit_start_struct(v, "%(name)s", NULL, 0, &err);
  97    if (err) {
  98        goto out;
  99    }
 100    visit_type_%(c_name)s_members(v, &param, &err);
 101    visit_end_struct(v, err ? NULL : &err);
 102    if (err) {
 103        goto out;
 104    }
 105
 106    qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
 107''',
 108                     name=name, c_name=arg_type.c_name())
 109
 110    ret += mcgen('''
 111    emit(%(c_enum)s, qmp, &err);
 112
 113''',
 114                 c_enum=c_enum_const(event_enum_name, name))
 115
 116    if arg_type and arg_type.members:
 117        ret += mcgen('''
 118out:
 119    qmp_output_visitor_cleanup(qov);
 120''')
 121    ret += mcgen('''
 122    error_propagate(errp, err);
 123    QDECREF(qmp);
 124}
 125''')
 126    return ret
 127
 128
 129class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
 130    def __init__(self):
 131        self.decl = None
 132        self.defn = None
 133        self._event_names = None
 134
 135    def visit_begin(self, schema):
 136        self.decl = ''
 137        self.defn = ''
 138        self._event_names = []
 139
 140    def visit_end(self):
 141        self.decl += gen_enum(event_enum_name, self._event_names)
 142        self.defn += gen_enum_lookup(event_enum_name, self._event_names)
 143        self._event_names = None
 144
 145    def visit_event(self, name, info, arg_type):
 146        self.decl += gen_event_send_decl(name, arg_type)
 147        self.defn += gen_event_send(name, arg_type)
 148        self._event_names.append(name)
 149
 150
 151(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
 152
 153c_comment = '''
 154/*
 155 * schema-defined QAPI event functions
 156 *
 157 * Copyright (c) 2014 Wenchao Xia
 158 *
 159 * Authors:
 160 *  Wenchao Xia   <wenchaoqemu@gmail.com>
 161 *
 162 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 163 * See the COPYING.LIB file in the top-level directory.
 164 *
 165 */
 166'''
 167h_comment = '''
 168/*
 169 * schema-defined QAPI event functions
 170 *
 171 * Copyright (c) 2014 Wenchao Xia
 172 *
 173 * Authors:
 174 *  Wenchao Xia  <wenchaoqemu@gmail.com>
 175 *
 176 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 177 * See the COPYING.LIB file in the top-level directory.
 178 *
 179 */
 180'''
 181
 182(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
 183                            'qapi-event.c', 'qapi-event.h',
 184                            c_comment, h_comment)
 185
 186fdef.write(mcgen('''
 187#include "qemu/osdep.h"
 188#include "qemu-common.h"
 189#include "%(prefix)sqapi-event.h"
 190#include "%(prefix)sqapi-visit.h"
 191#include "qapi/qmp-output-visitor.h"
 192#include "qapi/qmp-event.h"
 193
 194''',
 195                 prefix=prefix))
 196
 197fdecl.write(mcgen('''
 198#include "qapi/error.h"
 199#include "qapi/qmp/qdict.h"
 200#include "%(prefix)sqapi-types.h"
 201
 202''',
 203                  prefix=prefix))
 204
 205event_enum_name = c_name(prefix + "QAPIEvent", protect=False)
 206
 207schema = QAPISchema(input_file)
 208gen = QAPISchemaGenEventVisitor()
 209schema.visit(gen)
 210fdef.write(gen.defn)
 211fdecl.write(gen.decl)
 212
 213close_output(fdef, fdecl)
 214