summaryrefslogtreecommitdiff
path: root/scripts/qapi-event.py
AgeCommit message (Collapse)AuthorFilesLines
2016-07-19qapi: Implement boxed types for commands/eventsEric Blake1-1/+4
Turn on the ability to pass command and event arguments in a single boxed parameter, which must name a non-empty type (although the type can be a struct with all optional members). For structs, it makes it possible to pass a single qapi type instead of a breakout of all struct members (useful if the arguments are already in a struct or if the number of members is large); for other complex types, it is now possible to use a union or alternate as the data for a command or event. The empty type may be technically feasible if needed down the road, but it's easier to forbid it now and relax things to allow it later, than it is to allow it now and have to special case how the generated 'q_empty' type is handled (see commit 7ce106a9 for reasons why nothing is generated for the empty type). An alternate type is never considered empty, but now that a boxed type can be either an object or an alternate, we have to provide a trivial QAPISchemaAlternateType.is_empty(). The new call to arg_type.is_empty() during QAPISchemaCommand.check() requires that we first check the type in question; but there is no chance of introducing a cycle since objects do not refer back to commands. We still have a split in syntax checking between ad-hoc parsing up front (merely validates that 'boxed' has a sane value) and during .check() methods (if 'boxed' is set, then 'data' must name a non-empty user-defined type). Generated code is unchanged, as long as no client uses the new feature. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1468468228-27827-10-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [Test files renamed to *-boxed-*] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-19qapi: Plumb in 'boxed' to qapi generator lower levelsEric Blake1-9/+9
The next patch will add support for passing a qapi union type as the 'data' of a command. But to do that, the user function for implementing the command, as called by the generated marshal command, must take the corresponding C struct as a single boxed pointer, rather than a breakdown into one parameter per member. Even without a union, being able to use a C struct rather than a list of parameters can make it much easier to handle coding with QAPI. This patch adds the internal plumbing of a 'boxed' flag associated with each command and event. In several cases, this means adding indentation, with one new dead branch and the remaining branch being the original code more deeply nested; this was done so that the new implementation in the next patch is easier to review without also being mixed with indentation changes. For this patch, no behavior or generated output changes, other than the testsuite outputting the value of the new flag (always False for now). Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1468468228-27827-9-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> [Identifier box renamed to boxed in two places] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-19qapi-event: Simplify visit of non-implicit dataEric Blake1-2/+17
Commit 7ce106a9 documented why we don't generated a visit_type_FOO() for implicit types; and therefore events with an anonymous type for 'data' have to open-code a visit. Note that the open-coded visit in qapi-event.c is slightly different from what is done in qapi-visit.c for normal types, in part because we don't have to check for *obj being NULL or free things on error. But where the type is not implicit, it is nicer to reuse the normal visit instead of open-coding a duplicate. At the moment, the only event with a non-implicit 'data' is in the testsuite, where test-qapi-event.c changes as follows: |@@ -155,6 +155,7 @@ void qapi_event_send___org_qemu_x_event( | __org_qemu_x_Struct param = { | __org_qemu_x_member1, (char *)__org_qemu_x_member2, has_q_wchar_t, q_wchar_t | }; |+ __org_qemu_x_Struct *arg = &param; | | emit = qmp_event_get_func_emit(); | if (!emit) { |@@ -164,16 +165,7 @@ void qapi_event_send___org_qemu_x_event( | qmp = qmp_event_build_dict("__ORG.QEMU_X-EVENT"); | | v = qmp_output_visitor_new(&obj); |- |- visit_start_struct(v, "__ORG.QEMU_X-EVENT", NULL, 0, &err); |- if (err) { |- goto out; |- } |- visit_type___org_qemu_x_Struct_members(v, &param, &err); |- if (!err) { |- if (!err) { |- visit_check_struct(v, &err); |- } |- visit_end_struct(v, NULL); |+ visit_type___org_qemu_x_Struct(v, "__ORG.QEMU_X-EVENT", &arg, &err); | if (err) { | goto out; | } Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1468468228-27827-8-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-19qapi: Add type.is_empty() helperEric Blake1-3/+3
In the near future, we want to lift our artificial restriction of no variants at the top level of an event, at which point the currently open-coded check for empty members will become insufficient. Factor it out into a new helper method is_empty() now, and future-proof it by checking variants, too, along with an assert that it is not used prior to the completion of .check(). Update places that were checking for (non-)empty .members to use the new helper. All of the current callers assert that there are no variants (either directly, or by qapi.py asserting that base types have no variants), so this is not a semantic change. No change to generated code. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1468468228-27827-6-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-06qapi: Add new visit_complete() functionEric Blake1-4/+4
Making each output visitor provide its own output collection function was the only remaining reason for exposing visitor sub-types to the rest of the code base. Add a polymorphic visit_complete() function which is a no-op for input visitors, and which populates an opaque pointer for output visitors. For maximum type-safety, also add a parameter to the output visitor constructors with a type-correct version of the output pointer, and assert that the two uses match. This approach was considered superior to either passing the output parameter only during construction (action at a distance during visit_free() feels awkward) or only during visit_complete() (defeating type safety makes it easier to use incorrectly). Most callers were function-local, and therefore a mechanical conversion; the testsuite was a bit trickier, but the previous cleanup patch minimized the churn here. The visit_complete() function may be called at most once; doing so lets us use transfer semantics rather than duplication or ref-count semantics to get the just-built output back to the caller, even though it means our behavior is not idempotent. Generated code is simplified as follows for events: |@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP | QDict *qmp; | Error *err = NULL; | QMPEventFuncEmit emit; |- QmpOutputVisitor *qov; |+ QObject *obj; | Visitor *v; | q_obj_ACPI_DEVICE_OST_arg param = { | info |@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP | | qmp = qmp_event_build_dict("ACPI_DEVICE_OST"); | |- qov = qmp_output_visitor_new(); |- v = qmp_output_get_visitor(qov); |+ v = qmp_output_visitor_new(&obj); | | visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err); | if (err) { |@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP | goto out; | } | |- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov)); |+ visit_complete(v, &obj); |+ qdict_put_obj(qmp, "data", obj); | emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err); and for commands: | { | Error *err = NULL; |- QmpOutputVisitor *qov = qmp_output_visitor_new(); | Visitor *v; | |- v = qmp_output_get_visitor(qov); |+ v = qmp_output_visitor_new(ret_out); | visit_type_AddfdInfo(v, "unused", &ret_in, &err); |- if (err) { |- goto out; |+ if (!err) { |+ visit_complete(v, ret_out); | } |- *ret_out = qmp_output_get_qobject(qov); |- |-out: | error_propagate(errp, err); Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-06qapi: Add new visit_free() functionEric Blake1-1/+1
Making each visitor provide its own (awkwardly-named) FOO_cleanup() is unusual, when we can instead have a polymorphic visit_free() interface. Over the next few patches, we can use the polymorphic functions to eliminate the need for a FOO_get_visitor() function for accessing specific visitor functionality, once everything can be accessed directly through the Visitor* interfaces. The dealloc visitor is the first one converted to completely use the new entry point, since qapi_dealloc_visitor_cleanup() was the only reason that qapi_dealloc_get_visitor() existed, and only generated and testsuite code was even using it. With the new visit_free() entry point in place, we no longer need to expose the QapiDeallocVisitor subtype through qapi_dealloc_visitor_new(), and can get by with less generated code, with diffs that look like: | void qapi_free_ACPIOSTInfo(ACPIOSTInfo *obj) | { |- QapiDeallocVisitor *qdv; | Visitor *v; | | if (!obj) { | return; | } | |- qdv = qapi_dealloc_visitor_new(); |- v = qapi_dealloc_get_visitor(qdv); |+ v = qapi_dealloc_visitor_new(); | visit_type_ACPIOSTInfo(v, NULL, &obj, NULL); |- qapi_dealloc_visitor_cleanup(qdv); |+ visit_free(v); |} Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1465490926-28625-5-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-07-06qapi: Add parameter to visit_end_*Eric Blake1-1/+1
Rather than making the dealloc visitor track of stack of pointers remembered during visit_start_* in order to free them during visit_end_*, it's a lot easier to just make all callers pass the same pointer to visit_end_*. The generated code has access to the same pointer, while all other users are doing virtual walks and can pass NULL. The dealloc visitor is then greatly simplified. All three visit_end_*() functions intentionally take a void**, even though the visit_start_*() functions differ between void**, GenericList**, and GenericAlternate**. This is done for several reasons: when doing a virtual walk, passing NULL doesn't care what the type is, but when doing a generated walk, we already have to cast the caller's specific FOO* to call visit_start, while using void** lets us use visit_end without a cast. Also, an upcoming patch will add a clone visitor that wants to use the same implementation for all three visit_end callbacks, which is made easier if all three share the same signature. For visitors with already track per-object state (the QMP visitors via a stack, and the string visitors which do not allow nesting), add an assertion that the caller is indeed passing the same pointer to paired calls. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1465490926-28625-4-git-send-email-eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-05-12qapi: Split visit_end_struct() into piecesEric Blake1-1/+4
As mentioned in previous patches, we want to call visit_end_struct() functions unconditionally, so that visitors can release resources tied up since the matching visit_start_struct() without also having to worry about error priority if more than one error occurs. Even though error_propagate() can be safely used to ignore a second error during cleanup caused by a first error, it is simpler if the cleanup cannot set an error. So, split out the error checking portion (basically, input visitors checking for unvisited keys) into a new function visit_check_struct(), which can be safely skipped if any earlier errors are encountered, and leave the cleanup portion (which never fails, but must be called unconditionally if visit_start_struct() succeeded) in visit_end_struct(). Generated code in qapi-visit.c has diffs resembling: |@@ -59,10 +59,12 @@ void visit_type_ACPIOSTInfo(Visitor *v, | goto out_obj; | } | visit_type_ACPIOSTInfo_members(v, obj, &err); |- error_propagate(errp, err); |- err = NULL; |+ if (err) { |+ goto out_obj; |+ } |+ visit_check_struct(v, &err); | out_obj: |- visit_end_struct(v, &err); |+ visit_end_struct(v); | out: and in qapi-event.c: @@ -47,7 +47,10 @@ void qapi_event_send_acpi_device_ost(ACP | goto out; | } | visit_type_q_obj_ACPI_DEVICE_OST_arg_members(v, &param, &err); |- visit_end_struct(v, err ? NULL : &err); |+ if (!err) { |+ visit_check_struct(v, &err); |+ } |+ visit_end_struct(v); | if (err) { | goto out; Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1461879932-9020-20-git-send-email-eblake@redhat.com> [Conflict with a doc fixup resolved] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18qapi-event: Utilize implicit struct visitsEric Blake1-10/+38
Rather than generate inline per-member visits, take advantage of the 'visit_type_FOO_members()' function for emitting events. This is possible now that implicit structs can be visited like any other. Generated code shrinks accordingly; by initializing a struct based on parameters, through a new gen_param_var() helper, like: |@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con | QMPEventFuncEmit emit = qmp_event_get_func_emit(); | QmpOutputVisitor *qov; | Visitor *v; |+ q_obj_BLOCK_JOB_ERROR_arg param = { |+ (char *)device, operation, action |+ }; | | if (!emit) { | return; @@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con | if (err) { | goto out; | } |- visit_type_str(v, "device", (char **)&device, &err); |- if (err) { |- goto out_obj; |- } |- visit_type_IoOperationType(v, "operation", &operation, &err); |- if (err) { |- goto out_obj; |- } |- visit_type_BlockErrorAction(v, "action", &action, &err); |- if (err) { |- goto out_obj; |- } |-out_obj: |+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, &param, &err); | visit_end_struct(v, err ? NULL : &err); Notice that the initialization of 'param' has to cast away const (just as the old gen_visit_members() had to do): we can't change the signature of the user function (which uses 'const char *'), but have to assign it to a non-const QAPI object (which requires 'char *'). While touching this, document with a FIXME comment that there is still a potential collision between QMP members and our choice of local variable names within qapi_event_send_FOO(). This patch also paves the way for some followup simplifications in the generator, in subsequent patches. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18qapi-event: Drop qmp_output_get_qobject() null checkEric Blake1-5/+1
qmp_output_get_qobject() was changed never to return null some time ago (in commit 6c2f9a15), but the qapi_event_send_FOO() functions still check. Clean that up: |@@ -28,7 +28,6 @@ void qapi_event_send_acpi_device_ost(ACP | QMPEventFuncEmit emit; | QmpOutputVisitor *qov; | Visitor *v; |- QObject *obj; | | emit = qmp_event_get_func_emit(); | if (!emit) { |@@ -54,10 +53,7 @@ out_obj: | goto out; | } | |- obj = qmp_output_get_qobject(qov); |- g_assert(obj); |- |- qdict_put_obj(qmp, "data", obj); |+ qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov)); | emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err); | | out: Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1458254921-17042-7-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18qapi: Assert in places where variants are not handledEric Blake1-0/+1
We are getting closer to the point where we could use one union as the base or variant type within another union type (as long as there are no collisions between any possible combination of member names allowed across all discriminator choices). But until we get to that point, it is worth asserting that variants are not present in places where we are not prepared to handle them: when exploding a type into a parameter list, we do not expect variants. The qapi.py code is already checking this, via the older check_type() method; but someday we hope to get rid of that and move checking into QAPISchema*.check(). The two asserts added here make sure any refactoring still catches problems, and makes it locally obvious why we can iterate over only type.members without worrying about type.variants. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1458254921-17042-2-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-05qapi: Rename 'fields' to 'members' in generatorEric Blake1-2/+2
C types and JSON objects don't have fields, but members. We shouldn't gratuitously invent terminology. This patch is a strict renaming of generator code internals (including testsuite comments), before later patches rename C interfaces. No change to generated code with this patch. Suggested-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1457021813-10704-2-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-16qapi: Clean up includes in generated filesEric Blake1-0/+1
As a followup to commit cbf2115, clean up the includes in files generated by QAPI so that osdep.h is included first in .c files, and headers which it implies are not included manually. This patch is done manually, since Coccinelle (and therefore scripts/clean-includes) doesn't see into the generator scripts. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Eric Blake <eblake@redhat.com>
2016-02-08qapi: Drop unused 'kind' for struct/enum visitEric Blake1-1/+1
visit_start_struct() and visit_type_enum() had a 'kind' argument that was usually set to either the stringized version of the corresponding qapi type name, or to NULL (although some clients didn't even get that right). But nothing ever used the argument. It's even hard to argue that it would be useful in a debugger, as a stack backtrace also tells which type is being visited. Therefore, drop the 'kind' argument as dead. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <1454075341-13658-22-git-send-email-eblake@redhat.com> [Harmless rebase mistake cleaned up] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-08qapi: Swap visit_* arguments for consistent 'name' placementEric Blake1-1/+1
JSON uses "name":value, but many of our visitor interfaces were called with visit_type_FOO(v, &value, name, errp). This can be a bit confusing to have to mentally swap the parameter order to match JSON order. It's particularly bad for visit_start_struct(), where the 'name' parameter is smack in the middle of the otherwise-related group of 'obj, kind, size' parameters! It's time to do a global swap of the parameter ordering, so that the 'name' parameter is always immediately after the Visitor argument. Additional reason in favor of the swap: the existing include/qjson.h prefers listing 'name' first in json_prop_*(), and I have plans to unify that file with the qapi visitors; listing 'name' first in qapi will minimize churn to the (admittedly few) qjson.h clients. Later patches will then fix docs, object.h, visitor-impl.h, and those clients to match. Done by first patching scripts/qapi*.py by hand to make generated files do what I want, then by running the following Coccinelle script to affect the rest of the code base: $ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'` I then had to apply some touchups (Coccinelle insisted on TAB indentation in visitor.h, and botched the signature of visit_type_enum() by rewriting 'const char *const strings[]' to the syntactically invalid 'const char*const[] strings'). The movement of parameters is sufficient to provoke compiler errors if any callers were missed. // Part 1: Swap declaration order @@ type TV, TErr, TObj, T1, T2; identifier OBJ, ARG1, ARG2; @@ void visit_start_struct -(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp) +(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp) { ... } @@ type bool, TV, T1; identifier ARG1; @@ bool visit_optional -(TV v, T1 ARG1, const char *name) +(TV v, const char *name, T1 ARG1) { ... } @@ type TV, TErr, TObj, T1; identifier OBJ, ARG1; @@ void visit_get_next_type -(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp) +(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp) { ... } @@ type TV, TErr, TObj, T1, T2; identifier OBJ, ARG1, ARG2; @@ void visit_type_enum -(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp) +(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp) { ... } @@ type TV, TErr, TObj; identifier OBJ; identifier VISIT_TYPE =~ "^visit_type_"; @@ void VISIT_TYPE -(TV v, TObj OBJ, const char *name, TErr errp) +(TV v, const char *name, TObj OBJ, TErr errp) { ... } // Part 2: swap caller order @@ expression V, NAME, OBJ, ARG1, ARG2, ERR; identifier VISIT_TYPE =~ "^visit_type_"; @@ ( -visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR) +visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR) | -visit_optional(V, ARG1, NAME) +visit_optional(V, NAME, ARG1) | -visit_get_next_type(V, OBJ, ARG1, NAME, ERR) +visit_get_next_type(V, NAME, OBJ, ARG1, ERR) | -visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR) +visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR) | -VISIT_TYPE(V, OBJ, NAME, ERR) +VISIT_TYPE(V, NAME, OBJ, ERR) ) Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-02-08qapi: Improve generated event use of qapi visitorEric Blake1-9/+7
All other successful clients of visit_start_struct() were paired with an unconditional visit_end_struct(); but the generated code for events was relying on qmp_output_visitor_cleanup() to work on an incomplete visit. Alter the code to guarantee that the struct is completed, which will make a future patch to split visit_end_struct() easier to reason about. While at it, drop some assertions and comments that are not present in other uses of the qmp output visitor, and pass NULL rather than "" as the 'kind' parameter (matching most other uses where obj is NULL). The changes to the generated code look like: | qmp = qmp_event_build_dict("DEVICE_TRAY_MOVED"); | | qov = qmp_output_visitor_new(); |- g_assert(qov); |- | v = qmp_output_get_visitor(qov); |- g_assert(v); | |- /* Fake visit, as if all members are under a structure */ |- visit_start_struct(v, NULL, "", "DEVICE_TRAY_MOVED", 0, &err); |+ visit_start_struct(v, NULL, NULL, "DEVICE_TRAY_MOVED", 0, &err); | if (err) { | goto out; | } | visit_type_str(v, (char **)&device, "device", &err); | if (err) { |- goto out; |+ goto out_obj; | } | visit_type_bool(v, &tray_open, "tray-open", &err); | if (err) { |- goto out; |+ goto out_obj; | } |- visit_end_struct(v, &err); |+out_obj: |+ visit_end_struct(v, err ? NULL : &err); | if (err) { | goto out; | } | | obj = qmp_output_get_qobject(qov); |- g_assert(obj != NULL); |+ g_assert(obj); | | qdict_put_obj(qmp, "data", obj); | emit(QAPI_EVENT_DEVICE_TRAY_MOVED, qmp, &err); Note that the 'goto out_obj' with no intervening code before the label, as well as the construct of 'err ? NULL : &err', are both a bit unusual but also temporary; they get fixed in a later patch that splits visit_end_struct() to drop its errp parameter by moving some checking before the label. But until that time, this was the simplest way to avoid the appearance of passing a possibly-set error to visit_end_struct(), even though actual code inspection shows that visit_end_struct() for a QMP output visitor will never set an error. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1454075341-13658-11-git-send-email-eblake@redhat.com> [Commit message's code diff tweaked] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-12qapi: Share gen_visit_fields()Eric Blake1-30/+1
Consolidate the code between visit, command marshalling, and event generation that iterates over the members of a struct. It reduces code duplication in the generator, so that a future patch can reduce the size of generated code while touching only one instead of three locations. There are no changes to the generated marshal code. The visitor code becomes slightly more verbose, but remains semantically equivalent, and is actually easier to read as it follows a more common idiom: | visit_optional(v, &(*obj)->has_device, "device", &err); |- if (!err && (*obj)->has_device) { |- visit_type_str(v, &(*obj)->device, "device", &err); |- } | if (err) { | goto out; | } |+ if ((*obj)->has_device) { |+ visit_type_str(v, &(*obj)->device, "device", &err); |+ if (err) { |+ goto out; |+ } |+ } The event code becomes slightly more verbose, but this is arguably a bug fix: although the visitors are not well documented, use of an optional member should not be attempted unless guarded by a prior call to visit_optional(). Works only because the output qmp visitor has a no-op visit_optional(): |+ visit_optional(v, &has_offset, "offset", &err); |+ if (err) { |+ goto out; |+ } | if (has_offset) { | visit_type_int(v, &offset, "offset", &err); Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1443565276-4535-17-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-12qapi: Share gen_err_check()Eric Blake1-8/+2
qapi-commands has a nice helper gen_err_check(), but did not use it everywhere. In fact, using it in more places makes it easier to reduce the lines of code used for generating error checks. This in turn will make it easier for later patches to consolidate another common pattern among the generators. The generated code has fewer blank lines in qapi-event.c functions, but has no semantic difference. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1443565276-4535-16-git-send-email-eblake@redhat.com> [Drop another blank line for symmetry] Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-12qapi: Consistent generated code: prefer common labelsEric Blake1-4/+4
We had some pointless differences in the generated code for visit, command marshalling, and events; unifying them makes it easier for future patches to consolidate to common helper functions. This is one patch of a series to clean up these differences. This patch names the goto labels 'out' (not 'clean') and 'out_obj' (not 'out_end'). Additionally, the generator was inconsistent on whether labels had a leading space [our HACKING is silent; while emacs 'gnu' style adds the space to avoid littering column 1]. For minimal churn, prefer no leading space; this also matches the style that is more prevalent in current qemu.git. No change in semantics to the generated code. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1443565276-4535-13-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-10-12qapi: Consistent generated code: prefer error 'err'Eric Blake1-9/+9
We had some pointless differences in the generated code for visit, command marshalling, and events; unifying them makes it easier for future patches to consolidate to common helper functions. This is one patch of a series to clean up these differences. This patch consistently names the local error variable 'err' rather than 'local_err'. No change in semantics to the generated code. Signed-off-by: Eric Blake <eblake@redhat.com> Message-Id: <1443565276-4535-11-git-send-email-eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-21qapi: De-duplicate parameter list generationMarkus Armbruster1-15/+3
Generated qapi-event.[ch] lose line breaks. No change otherwise. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Message-Id: <1442401589-24189-18-git-send-email-armbru@redhat.com>
2015-09-21qapi: Clean up after recent conversions to QAPISchemaVisitorMarkus Armbruster1-64/+58
Generate just 'FOO' instead of 'struct FOO' when possible. Drop helper functions that are now unused. Make pep8 and pylint reasonably happy. Rename generate_FOO() functions to gen_FOO() for consistency. Use more consistent and sensible variable names. Consistently use c_ for mapping keys when their value is a C identifier or type. Simplify gen_enum() and gen_visit_union() Consistently use single quotes for C text string literals. Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <1442401589-24189-14-git-send-email-armbru@redhat.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-21qapi-event: Convert to QAPISchemaVisitor, fixing data with baseMarkus Armbruster1-43/+48
Fixes events whose data is struct with base to include the struct's base members. Test case is qapi-schema-test.json's event __org.qemu_x-command: { 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' } { 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base', 'data': { '__org.qemu_x-member2': 'str' } } { 'struct': '__org.qemu_x-Base', 'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } } Patch's effect on generated qapi_event_send___org_qemu_x_event(): -void qapi_event_send___org_qemu_x_event(const char *__org_qemu_x_member2, +void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1, + const char *__org_qemu_x_member2, Error **errp) { QDict *qmp; @@ -224,6 +225,10 @@ void qapi_event_send___org_qemu_x_event( goto clean; } + visit_type___org_qemu_x_Enum(v, &__org_qemu_x_member1, "__org.qemu_x-member1", &local_err); + if (local_err) { + goto clean; + } visit_type_str(v, (char **)&__org_qemu_x_member2, "__org.qemu_x-member2", &local_err); if (local_err) { goto clean; Code is generated in a different order now, but that doesn't matter. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2015-09-21qapi-event: Eliminate global variable event_enum_valueMarkus Armbruster1-2/+1
Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Message-Id: <1442401589-24189-11-git-send-email-armbru@redhat.com>
2015-09-21qapi: De-duplicate enum code generationMarkus Armbruster1-63/+4
Duplicated in commit 21cd70d. Yes, we can't import qapi-types, but that's no excuse. Move the helpers from qapi-types.py to qapi.py, and replace the duplicates in qapi-event.py. The generated event enumeration type's lookup table becomes const-correct (see commit 2e4450f), and uses explicit indexes instead of relying on order (see commit 912ae9c). Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-Id: <1442401589-24189-10-git-send-email-armbru@redhat.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-21qapi: New QAPISchema intermediate reperesentationMarkus Armbruster1-1/+1
The QAPI code generators work with a syntax tree (nested dictionaries) plus a few symbol tables (also dictionaries) on the side. They have clearly outgrown these simple data structures. There's lots of rummaging around in dictionaries, and information is recomputed on the fly. For the work I'm going to do, I want more clearly defined and more convenient interfaces. Going forward, I also want less coupling between the back-ends and the syntax tree, to make messing with the syntax easier. Create a bunch of classes to represent QAPI schemata. Have the QAPISchema initializer call the parser, then walk the syntax tree to create the new internal representation, and finally perform semantic analysis. Shortcut: the semantic analysis still relies on existing check_exprs() to do the actual semantic checking. All this code needs to move into the classes. Mark as TODO. Simple unions are lowered to flat unions. Flat unions and structs are represented as a more general object type. Catching name collisions in generated code would be nice. Mark as TODO. We generate array types eagerly, even though most of them aren't used. Mark as TODO. Nothing uses the new intermediate representation just yet, thus no change to generated files. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-04qapi: Generated code cleanupMarkus Armbruster1-2/+1
Clean up white-space, brace placement, and superfluous #ifdef QAPI_TYPES_BUILTIN_CLEANUP_DEF. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-04qapi: Drop unused and useless parameters and variablesMarkus Armbruster1-1/+0
gen_sync_call()'s parameter indent is useless: gen_sync_call() uses it only as optional argument for push_indent() and pop_indent(), their default is four, and gen_sync_call()'s only caller passes four. Drop the parameter. gen_visitor_input_containers_decl()'s parameter obj is always "QOBJECT(args)". Use that, and drop the parameter. Drop unused parameters of gen_marshal_output(), gen_marshal_input_decl(), generate_visit_struct_body(), generate_visit_list(), generate_visit_enum(), generate_declaration(), generate_enum_declaration(), generate_decl_enum(). Drop unused variables in generate_event_enum_lookup(), generate_enum_lookup(), generate_visit_struct_fields(), check_event(). Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-09-04qapi-event: Clean up how name of enum QAPIEvent is madeMarkus Armbruster1-1/+1
Use c_name() instead of ad hoc code. Doesn't upcase the -p prefix, which is an improvement in my book. Unbreaks prefix containing '.', but other funny characters remain broken. To be fixed next. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-05-14qapi: Factor open_output(), close_output() out of generatorsMarkus Armbruster1-55/+20
Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-05-14qapi: Factor parse_command_line() out of the generatorsMarkus Armbruster1-31/+1
Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-05-14qapi: qapi-event.py option -b does nothing, drop itMarkus Armbruster1-5/+2
Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2015-05-14qapi: Rename generate_enum_full_value() to c_enum_const()Markus Armbruster1-3/+2
Signed-off-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Eric Blake <eblake@redhat.com>
2015-05-14qapi: Rename identical c_fun()/c_var() into c_name()Eric Blake1-5/+5
Now that the two functions are identical, we only need one of them, and we might as well give it a more descriptive name. Basically, the function serves as the translation from a QAPI name into a (portion of a) C identifier, without regards to whether it is a variable or function name. Signed-off-by: Eric Blake <eblake@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-05-05qapi: Drop support for inline nested typesEric Blake1-2/+2
A future patch will be using a 'name':{dictionary} entry in the QAPI schema to specify a default value for an optional argument (see previous commit messages for more details why); but existing use of inline nested structs conflicts with that goal. Now that all commands have been changed to avoid inline nested structs, nuke support for them, and turn it into a hard error. Update the testsuite to reflect tighter parsing rules. Signed-off-by: Eric Blake <eblake@redhat.com> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
2014-06-27qapi script: clean up in scriptsWenchao Xia1-3/+2
This patch improve docs and uses c_type(argentry, is_param=True) in script. Signed-off-by: Wenchao Xia <wenchaoqemu@gmail.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
2014-06-23qapi script: add event supportWenchao Xia1-0/+369
qapi-event.py will parse the schema and generate qapi-event.c, then the API in qapi-event.c can be used to handle events in qemu code. All API have prefix "qapi_event". The script mainly includes two parts: generate API for each event define, generate an enum type for all defined events. Since in some cases the real emit behavior may change, for example, qemu-img would not send a event, a callback layer is used to control the behavior. As a result, the stubs at compile time can be saved, the binding of block layer code and monitor code will become looser. Signed-off-by: Wenchao Xia <wenchaoqemu@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>