Commit d626b6c1 authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Markus Armbruster
Browse files

qapi-introspect: add preprocessor conditions to generated QLit



This commit adds 'ifcond' conditions to top-level QLit objects.
Future work will add them to object and enum type members, i.e. within
QLit objects.

Extend the QLit generator to_qlit() to accept (@obj, @cond) tuples in
addition to just @obj.  The tuple causes the QLit generated for
objects for @obj with #if/#endif conditions for @cond.

See generated tests/test-qmp-introspect.c. Example diff after this
patch:

    --- before	2018-01-08 11:55:24.757083654 +0100
    +++ tests/test-qmp-introspect.c	2018-01-08 13:08:44.477641629 +0100
    @@ -51,6 +51,8 @@
             { "name", QLIT_QSTR("EVENT_F"), },
             {}
         })),
    +#if defined(TEST_IF_CMD)
    +#if defined(TEST_IF_STRUCT)
         QLIT_QDICT(((QLitDictEntry[]) {
             { "arg-type", QLIT_QSTR("5"), },
             { "meta-type", QLIT_QSTR("command"), },
    @@ -58,12 +60,16 @@
             { "ret-type", QLIT_QSTR("0"), },
             {}
         })),
    +#endif /* defined(TEST_IF_STRUCT) */
    +#endif /* defined(TEST_IF_CMD) */

Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: default avatarMarkus Armbruster <armbru@redhat.com>
Message-Id: <20180703155648.11933-9-marcandre.lureau@redhat.com>
Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
parent 40bb1376
Loading
Loading
Loading
Loading
+21 −10
Original line number Diff line number Diff line
@@ -18,6 +18,15 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
    def indent(level):
        return level * 4 * ' '

    if isinstance(obj, tuple):
        ifobj, ifcond = obj
        ret = gen_if(ifcond)
        ret += to_qlit(ifobj, level)
        endif = gen_endif(ifcond)
        if endif:
            ret += '\n' + endif
        return ret

    ret = ''
    if not suppress_first_indent:
        ret += indent(level)
@@ -26,7 +35,7 @@ def to_qlit(obj, level=0, suppress_first_indent=False):
    elif isinstance(obj, str):
        ret += 'QLIT_QSTR(' + to_c_string(obj) + ')'
    elif isinstance(obj, list):
        elts = [to_qlit(elt, level + 1)
        elts = [to_qlit(elt, level + 1).strip('\n')
                for elt in obj]
        elts.append(indent(level + 1) + "{}")
        ret += 'QLIT_QLIST(((QLitObject[]) {\n'
@@ -128,12 +137,12 @@ const QLitObject %(c_name)s = %(c_string)s;
            return '[' + self._use_type(typ.element_type) + ']'
        return self._name(typ.name)

    def _gen_qlit(self, name, mtype, obj):
    def _gen_qlit(self, name, mtype, obj, ifcond):
        if mtype not in ('command', 'event', 'builtin', 'array'):
            name = self._name(name)
        obj['name'] = name
        obj['meta-type'] = mtype
        self._qlits.append(obj)
        self._qlits.append((obj, ifcond))

    def _gen_member(self, member):
        ret = {'name': member.name, 'type': self._use_type(member.type)}
@@ -149,26 +158,27 @@ const QLitObject %(c_name)s = %(c_string)s;
        return {'case': variant.name, 'type': self._use_type(variant.type)}

    def visit_builtin_type(self, name, info, json_type):
        self._gen_qlit(name, 'builtin', {'json-type': json_type})
        self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])

    def visit_enum_type(self, name, info, ifcond, values, prefix):
        self._gen_qlit(name, 'enum', {'values': values})
        self._gen_qlit(name, 'enum', {'values': values}, ifcond)

    def visit_array_type(self, name, info, ifcond, element_type):
        element = self._use_type(element_type)
        self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
        self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
                       ifcond)

    def visit_object_type_flat(self, name, info, ifcond, members, variants):
        obj = {'members': [self._gen_member(m) for m in members]}
        if variants:
            obj.update(self._gen_variants(variants.tag_member.name,
                                          variants.variants))
        self._gen_qlit(name, 'object', obj)
        self._gen_qlit(name, 'object', obj, ifcond)

    def visit_alternate_type(self, name, info, ifcond, variants):
        self._gen_qlit(name, 'alternate',
                       {'members': [{'type': self._use_type(m.type)}
                                    for m in variants.variants]})
                                    for m in variants.variants]}, ifcond)

    def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
                      success_response, boxed, allow_oob, allow_preconfig):
@@ -178,11 +188,12 @@ const QLitObject %(c_name)s = %(c_string)s;
                       {'arg-type': self._use_type(arg_type),
                        'ret-type': self._use_type(ret_type),
                        'allow-oob': allow_oob,
                        'allow-preconfig': allow_preconfig})
                        'allow-preconfig': allow_preconfig}, ifcond)

    def visit_event(self, name, info, ifcond, arg_type, boxed):
        arg_type = arg_type or self._schema.the_empty_object_type
        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
        self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)},
                       ifcond)


def gen_introspect(schema, output_dir, prefix, opt_unmask):