Commit a4a1c70d authored by Markus Armbruster's avatar Markus Armbruster
Browse files

qapi: Make input visitors detect unvisited list tails



Fix the design flaw demonstrated in the previous commit: new method
check_list() lets input visitors report that unvisited input remains
for a list, exactly like check_struct() lets them report that
unvisited input remains for a struct or union.

Implement the method for the qobject input visitor (straightforward),
and the string input visitor (less so, due to the magic list syntax
there).  The opts visitor's list magic is even more impenetrable, and
all I can do there today is a stub with a FIXME comment.  No worse
than before.

Signed-off-by: default avatarMarkus Armbruster <armbru@redhat.com>
Message-Id: <1488544368-30622-26-git-send-email-armbru@redhat.com>
Reviewed-by: default avatarEric Blake <eblake@redhat.com>
parent 86ca0dbe
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -326,7 +326,12 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name,
                    return;
                }
            }
            visit_check_list(v, &err);
            visit_end_list(v, NULL);
            if (err) {
                error_propagate(errp, err);
                return;
            }
            break;
        }
        default:
+3 −0
Original line number Diff line number Diff line
@@ -61,6 +61,9 @@ struct Visitor
    /* Must be set */
    GenericList *(*next_list)(Visitor *v, GenericList *tail, size_t size);

    /* Optional; intended for input visitors */
    void (*check_list)(Visitor *v, Error **errp);

    /* Must be set */
    void (*end_list)(Visitor *v, void **list);

+13 −0
Original line number Diff line number Diff line
@@ -369,6 +369,19 @@ void visit_start_list(Visitor *v, const char *name, GenericList **list,
 */
GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size);

/*
 * Prepare for completing a list visit.
 *
 * @errp obeys typical error usage, and reports failures such as
 * unvisited list tail remaining in the input stream.
 *
 * Should be called prior to visit_end_list() if all other
 * intermediate visit steps were successful, to allow the visitor one
 * last chance to report errors.  May be skipped on a cleanup path,
 * where there is no need to check for further errors.
 */
void visit_check_list(Visitor *v, Error **errp);

/*
 * Complete a list visit started earlier.
 *
+11 −0
Original line number Diff line number Diff line
@@ -272,6 +272,16 @@ opts_next_list(Visitor *v, GenericList *tail, size_t size)
}


static void
opts_check_list(Visitor *v, Error **errp)
{
    /*
     * FIXME should set error when unvisited elements remain.  Mostly
     * harmless, as the generated visits always visit all elements.
     */
}


static void
opts_end_list(Visitor *v, void **obj)
{
@@ -539,6 +549,7 @@ opts_visitor_new(const QemuOpts *opts)

    ov->visitor.start_list = &opts_start_list;
    ov->visitor.next_list  = &opts_next_list;
    ov->visitor.check_list = &opts_check_list;
    ov->visitor.end_list   = &opts_end_list;

    ov->visitor.type_int64  = &opts_type_int64;
+8 −0
Original line number Diff line number Diff line
@@ -90,6 +90,14 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
    return v->next_list(v, tail, size);
}

void visit_check_list(Visitor *v, Error **errp)
{
    trace_visit_check_list(v);
    if (v->check_list) {
        v->check_list(v, errp);
    }
}

void visit_end_list(Visitor *v, void **obj)
{
    trace_visit_end_list(v, obj);
Loading