1. 16 3月, 2017 12 次提交
  2. 16 1月, 2017 2 次提交
    • M
      qapi: add qapi2texi script · 3313b612
      Marc-André Lureau 提交于
      As the name suggests, the qapi2texi script converts JSON QAPI
      description into a texi file suitable for different target
      formats (info/man/txt/pdf/html...).
      
      It parses the following kind of blocks:
      
      Free-form:
      
        ##
        # = Section
        # == Subsection
        #
        # Some text foo with *emphasis*
        # 1. with a list
        # 2. like that
        #
        # And some code:
        # | $ echo foo
        # | -> do this
        # | <- get that
        #
        ##
      
      Symbol description:
      
        ##
        # @symbol:
        #
        # Symbol body ditto ergo sum. Foo bar
        # baz ding.
        #
        # @param1: the frob to frobnicate
        # @param2: #optional how hard to frobnicate
        #
        # Returns: the frobnicated frob.
        #          If frob isn't frobnicatable, GenericError.
        #
        # Since: version
        # Notes: notes, comments can have
        #        - itemized list
        #        - like this
        #
        # Example:
        #
        # -> { "execute": "quit" }
        # <- { "return": {} }
        #
        ##
      
      That's roughly following the following EBNF grammar:
      
      api_comment = "##\n" comment "##\n"
      comment = freeform_comment | symbol_comment
      freeform_comment = { "# " text "\n" | "#\n" }
      symbol_comment = "# @" name ":\n" { member | tag_section | freeform_comment }
      member = "# @" name ':' [ text ] "\n" freeform_comment
      tag_section = "# " ( "Returns:", "Since:", "Note:", "Notes:", "Example:", "Examples:" ) [ text ]  "\n" freeform_comment
      text = free text with markup
      
      Note that the grammar is ambiguous: a line "# @foo:\n" can be parsed
      both as freeform_comment and as symbol_comment.  The actual parser
      recognizes symbol_comment.
      
      See docs/qapi-code-gen.txt for more details.
      
      Deficiencies and limitations:
      - the generated QMP documentation includes internal types
      - union type support is lacking
      - type information is lacking in generated documentation
      - doc comment error message positions are imprecise, they point
        to the beginning of the comment.
      - a few minor issues, all marked TODO/FIXME in the code
      Signed-off-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-Id: <20170113144135.5150-16-marcandre.lureau@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      [test-qapi.py tweaked to avoid trailing empty lines in .out]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      3313b612
    • M
      qapi: rework qapi Exception · 4148c298
      Marc-André Lureau 提交于
      Use a base class QAPIError, and QAPIParseError for parser errors and
      QAPISemError for semantic errors, suggested by Markus Armbruster.
      Signed-off-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      Message-Id: <20170113144135.5150-12-marcandre.lureau@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      4148c298
  3. 19 7月, 2016 7 次提交
    • E
      qapi: Implement boxed types for commands/events · c818408e
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1468468228-27827-10-git-send-email-eblake@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      [Test files renamed to *-boxed-*]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      c818408e
    • E
      qapi: Plumb in 'boxed' to qapi generator lower levels · 48825ca4
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1468468228-27827-9-git-send-email-eblake@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      [Identifier box renamed to boxed in two places]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      48825ca4
    • E
      qapi: Drop useless gen_err_check() · fa274ed6
      Eric Blake 提交于
      Ever since commit 12f254fd removed the last parameterization
      of gen_err_check(), it no longer makes sense to hide the three
      lines of generated C code behind a macro call. Just inline it
      into the remaining users.
      
      No change to generated code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1468468228-27827-7-git-send-email-eblake@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      fa274ed6
    • E
      qapi: Add type.is_empty() helper · b6167706
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1468468228-27827-6-git-send-email-eblake@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      b6167706
    • E
      qapi: Hide tag_name data member of variants · da9cb193
      Eric Blake 提交于
      Clean up the only remaining external use of the tag_name field of
      QAPISchemaObjectTypeVariants, by explicitly listing the generated
      'type' tag for all variants in the testsuite (you can still tell
      simple unions by the -wrapper types).  Then we can mark the
      tag_name field as private by adding a leading underscore to prevent
      any further use.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1468468228-27827-5-git-send-email-eblake@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      da9cb193
    • E
      qapi: Special case c_name() for empty type · cd50a256
      Eric Blake 提交于
      Commit 7ce106a9 rendered QAPISchemaObjectType.c_name() redundant,
      since it now does nothing more than delegate to its superclass.
      However, rather than deleting it, we can restore part of the
      assertion that was removed in that commit, to prove that we never
      emit the empty type directly in generated code, but rather
      special-case it as a built-in that makes other aspects of code
      generation easier to reason about.
      Reported-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1468468228-27827-4-git-send-email-eblake@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      cd50a256
    • E
      qapi: Require all branches of flat union enum to be covered · d0b18239
      Eric Blake 提交于
      We were previously enforcing that all flat union branches were
      found in the corresponding enum, but not that all enum values
      were covered by branches.  The resulting generated code would
      abort() if the user passes the uncovered enum value.
      
      We don't automatically treat non-present branches in a flat
      union as empty types, for symmetry with simple unions (there,
      the enum type is generated from the list of all branches, so
      there is no way to omit a branch but still have it be part of
      the union).
      
      A later patch will add shorthand so that branches that are empty
      in flat unions can be declared as 'branch':{} instead of
      'branch':'Empty', to avoid the need for an otherwise useless
      explicit empty type.  [Such shorthand for simple unions is a bit
      harder to justify, since we would still have to generate a
      wrapper type that parses 'data':{}, rather than truly being an
      empty branch with no additional siblings to the 'type' member.]
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1468468228-27827-3-git-send-email-eblake@redhat.com>
      Reviewed-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      d0b18239
  4. 18 3月, 2016 8 次提交
    • E
      qapi: Use anonymous bases in QMP flat unions · 3666a97f
      Eric Blake 提交于
      Now that the generator supports it, we might as well use an
      anonymous base rather than breaking out a single-use Base
      structure, for all three of our current QMP flat unions.
      
      Oddly enough, this change does not affect the resulting
      introspection output (because we already inline the members of
      a base type into an object, and had no independent use of the
      base type reachable from a command).
      
      The case_whitelist now has to list the name of an implicit
      type; which is not too bad (consider it a feature if it makes
      it harder for developers to make the whitelist grow :)
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-16-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      3666a97f
    • E
      qapi: Allow anonymous base for flat union · ac4338f8
      Eric Blake 提交于
      Rather than requiring all flat unions to explicitly create
      a separate base struct, we can allow the qapi schema to specify
      the common members via an inline dictionary. This is similar to
      how commands can specify an inline anonymous type for its 'data'.
      We already have several struct types that only exist to serve as
      a single flat union's base; the next commit will clean them up.
      In particular, this patch's change to the BlockdevOptions example
      in qapi-code-gen.txt will actually be done in the real QAPI schema.
      
      Now that anonymous bases are legal, we need to rework the
      flat-union-bad-base negative test (as previously written, it
      forms what is now valid QAPI; tweak it to now provide coverage
      of a new error message path), and add a positive test in
      qapi-schema-test to use an anonymous base (making the integer
      argument optional, for even more coverage).
      
      Note that this patch only allows anonymous bases for flat unions;
      simple unions are already enough syntactic sugar that we do not
      want to burden them further.  Meanwhile, while it would be easy
      to also allow an anonymous base for structs, that would be quite
      redundant, as the members can be put right into the struct
      instead.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-15-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      ac4338f8
    • E
      qapi: Don't special-case simple union wrappers · 32bafa8f
      Eric Blake 提交于
      Simple unions were carrying a special case that hid their 'data'
      QMP member from the resulting C struct, via the hack method
      QAPISchemaObjectTypeVariant.simple_union_type().  But by using
      the work we started by unboxing flat union and alternate
      branches, coupled with the ability to visit the members of an
      implicit type, we can now expose the simple union's implicit
      type in qapi-types.h:
      
      | struct q_obj_ImageInfoSpecificQCow2_wrapper {
      |     ImageInfoSpecificQCow2 *data;
      | };
      |
      | struct q_obj_ImageInfoSpecificVmdk_wrapper {
      |     ImageInfoSpecificVmdk *data;
      | };
      ...
      | struct ImageInfoSpecific {
      |     ImageInfoSpecificKind type;
      |     union { /* union tag is @type */
      |         void *data;
      |-        ImageInfoSpecificQCow2 *qcow2;
      |-        ImageInfoSpecificVmdk *vmdk;
      |+        q_obj_ImageInfoSpecificQCow2_wrapper qcow2;
      |+        q_obj_ImageInfoSpecificVmdk_wrapper vmdk;
      |     } u;
      | };
      
      Doing this removes asymmetry between QAPI's QMP side and its
      C side (both sides now expose 'data'), and means that the
      treatment of a simple union as sugar for a flat union is now
      equivalent in both languages (previously the two approaches used
      a different layer of dereferencing, where the simple union could
      be converted to a flat union with equivalent C layout but
      different {} on the wire, or to an equivalent QMP wire form
      but with different C representation).  Using the implicit type
      also lets us get rid of the simple_union_type() hack.
      
      Of course, now all clients of simple unions have to adjust from
      using su->u.member to using su->u.member.data; while this touches
      a number of files in the tree, some earlier cleanup patches
      helped minimize the change to the initialization of a temporary
      variable rather than every single member access.  The generated
      qapi-visit.c code is also affected by the layout change:
      
      |@@ -7393,10 +7393,10 @@ void visit_type_ImageInfoSpecific_member
      |     }
      |     switch (obj->type) {
      |     case IMAGE_INFO_SPECIFIC_KIND_QCOW2:
      |-        visit_type_ImageInfoSpecificQCow2(v, "data", &obj->u.qcow2, &err);
      |+        visit_type_q_obj_ImageInfoSpecificQCow2_wrapper_members(v, &obj->u.qcow2, &err);
      |         break;
      |     case IMAGE_INFO_SPECIFIC_KIND_VMDK:
      |-        visit_type_ImageInfoSpecificVmdk(v, "data", &obj->u.vmdk, &err);
      |+        visit_type_q_obj_ImageInfoSpecificVmdk_wrapper_members(v, &obj->u.vmdk, &err);
      |         break;
      |     default:
      |         abort();
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-13-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      32bafa8f
    • E
      qapi: Drop unused c_null() · 861877a0
      Eric Blake 提交于
      Now that we are always bulk-initializing a QAPI C struct to 0
      (whether by g_malloc0() or by 'Type arg = {0};'), we no longer
      have any clients of c_null() in the generator for per-element
      initialization.  This patch is easy enough to revert if we find
      a use in the future, but in the present, get rid of the dead code.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-12-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      861877a0
    • E
      qapi: Inline gen_visit_members() into lone caller · 12f254fd
      Eric Blake 提交于
      Commit 82ca8e46 noticed that we had multiple implementations of
      visiting every member of a struct, and consolidated it into
      gen_visit_fields() (now gen_visit_members()) with enough
      parameters to cater to slight differences between the clients.
      But recent exposure of implicit types has meant that we are now
      down to a single use of that method, so we can clean up the
      unused conditionals and just inline it into the remaining
      caller: gen_visit_object_members().
      
      Likewise, gen_err_check() no longer needs optional parameters,
      as the lone use of non-defaults was via gen_visit_members().
      
      No change to generated code.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-11-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      12f254fd
    • E
      qapi: Emit implicit structs in generated C · 7ce106a9
      Eric Blake 提交于
      We already have several places that want to visit all the members
      of an implicit object within a larger context (simple union variant,
      event with anonymous data, command with anonymous arguments struct);
      and will be adding another one soon (the ability to declare an
      anonymous base for a flat union).  Having a C struct declared for
      these implicit types, along with a visit_type_FOO_members() helper
      function, will make for fewer special cases in our generator.
      
      We do not, however, need qapi_free_FOO() or visit_type_FOO()
      functions for implicit types, because they should not be used
      directly outside of the generated code.  This is done by adding a
      conditional in visit_object_type() for both qapi-types.py and
      qapi-visit.py based on the object name.  The comparison of
      "name.startswith('q_')" is a bit hacky (it's basically duplicating
      what .is_implicit() already uses), but beats changing the signature
      of the visit_object_type() callback to pass a new 'implicit' flag.
      The hack should be temporary: we are considering adding a future
      patch that consolidates the narrow visit_object_type(..., base,
      local_members, variants) and visit_object_type_flat(...,
      all_members, variants) [where different sets of information are
      already broken out, and the QAPISchemaObjectType is no longer
      available] into a broader visit_object_type(obj_type) [where the
      visitor can query the needed fields from obj_type directly].
      
      Also, now that we WANT to output C code for implicits, we no longer
      need the visit_needed() filter, leaving 'q_empty' as the only object
      still needing a special case.  Remember, 'q_empty' is the only
      built-in generated object, which means that without a special case
      it would be emitted in multiple files (the main qapi-types.h and in
      qga-qapi-types.h) causing compilation failure due to redefinition.
      But since it has no members, it's easier to just avoid an attempt to
      visit that particular type; since gen_object() is called recursively,
      we also prime the objects_seen set to cover any recursion into the
      empty type.
      
      The patch relies on the changed naming of implicit types in the
      previous patch.  It is a bit unfortunate that the generated struct
      names and visit_type_FOO_members() don't match normal naming
      conventions, but it's not too bad, since they will only be used in
      generated code.
      
      The generated code grows substantially in size: the implicit
      '-wrapper' types must be emitted in qapi-types.h before any union
      can include an unboxed member of that type.  Arguably, the '-args'
      types could be emitted in a private header for just qapi-visit.c
      and qmp-marshal.c, rather than polluting qapi-types.h; but adding
      complexity to the generator to split the output location according
      to role doesn't seem worth the maintenance costs.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-6-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      7ce106a9
    • E
      qapi: Adjust names of implicit types · 7599697c
      Eric Blake 提交于
      The original choice of ':obj-' as the prefix for implicit types
      made it obvious that we weren't going to clash with any user-defined
      names, which cannot contain ':'.  But now we want to create structs
      for implicit types, to get rid of special cases in the generators,
      and our use of ':' in implicit names needs a tweak to produce valid
      C code.
      
      We could transliterate ':' to '_', except that C99 mandates that
      "identifiers that begin with an underscore are always reserved for
      use as identifiers with file scope in both the ordinary and tag name
      spaces".  So it's time to change our naming convention: we can
      instead use the 'q_' prefix that we reserved for ourselves back in
      commit 9fb081e0.  Technically, since we aren't planning on exposing
      the empty type in generated code, we could keep the name ':empty',
      but renaming it to 'q_empty' makes the check for startswith('q_')
      cover all implicit types, whether or not code is generated for them.
      
      As long as we don't declare 'empty' or 'obj' ticklish, it shouldn't
      clash with c_name() prepending 'q_' to the user's ticklish names.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-5-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      7599697c
    • E
      qapi: Make c_type() more OO-like · 4040d995
      Eric Blake 提交于
      QAPISchemaType.c_type() is a bit awkward: it takes two optional
      boolean flags is_param and is_unboxed, and they should never both
      be True.
      
      Add a new method for each of the flags, and drop the flags from
      c_type().
      
      Most callers pass no flags; they remain unchanged.
      
      One caller passes is_param=True; call the new .c_param_type()
      instead.
      
      One caller passes is_unboxed=True, except for simple union types.
      This is actually an ugly special case that will go away soon, so
      until then, we now have to call either .c_type() or the new
      .c_unboxed_type().  Tolerable in the interim.
      
      It requires slightly more Python, but is arguably easier to read.
      Suggested-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1458254921-17042-4-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      4040d995
  5. 05 3月, 2016 1 次提交
  6. 01 3月, 2016 2 次提交
  7. 19 2月, 2016 3 次提交
    • E
      qapi: Don't box struct branch of alternate · becceedc
      Eric Blake 提交于
      There's no reason to do two malloc's for an alternate type visiting
      a QAPI struct; let's just inline the struct directly as the C union
      branch of the struct.
      
      Surprisingly, no clients were actually using the struct member prior
      to this patch outside of the testsuite; an earlier patch in the series
      added some testsuite coverage to make the effect of this patch more
      obvious.
      
      In qapi.py, c_type() gains a new is_unboxed flag to control when we
      are emitting a C struct unboxed within the context of an outer
      struct (different from our other two modes of usage with no flags
      for normal local variable declarations, and with is_param for adding
      'const' in a parameter list).  I don't know if there is any more
      pythonic way of collapsing the two flags into a single parameter,
      as we never have a caller setting both flags at once.
      
      Ultimately, we want to also unbox branches for QAPI unions, but as
      that touches a lot more client code, it is better as separate
      patches.  But since unions and alternates share gen_variants(), I
      had to hack in a way to test if we are visiting an alternate type
      for setting the is_unboxed flag: look for a non-object branch.
      This works because alternates have at least two branches, with at
      most one object branch, while unions have only object branches.
      The hack will go away in a later patch.
      
      The generated code difference to qapi-types.h is relatively small:
      
      | struct BlockdevRef {
      |     QType type;
      |     union { /* union tag is @type */
      |         void *data;
      |-        BlockdevOptions *definition;
      |+        BlockdevOptions definition;
      |         char *reference;
      |     } u;
      | };
      
      The corresponding spot in qapi-visit.c calls visit_type_FOO(), which
      first calls visit_start_struct() to allocate or deallocate the member
      and handle a layer of {} from the JSON stream, then visits the
      members.  To peel off the indirection and the memory management that
      comes with it, we inline this call, then suppress allocation /
      deallocation by passing NULL to visit_start_struct(), and adjust the
      member visit:
      
      |     switch ((*obj)->type) {
      |     case QTYPE_QDICT:
      |-        visit_type_BlockdevOptions(v, name, &(*obj)->u.definition, &err);
      |+        visit_start_struct(v, name, NULL, 0, &err);
      |+        if (err) {
      |+            break;
      |+        }
      |+        visit_type_BlockdevOptions_fields(v, &(*obj)->u.definition, &err);
      |+        error_propagate(errp, err);
      |+        err = NULL;
      |+        visit_end_struct(v, &err);
      |         break;
      |     case QTYPE_QSTRING:
      |         visit_type_str(v, name, &(*obj)->u.reference, &err);
      
      The visit of non-object fields is unchanged.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-13-git-send-email-eblake@redhat.com>
      [Commit message tweaked]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      becceedc
    • E
      qapi: Forbid 'any' inside an alternate · 46534309
      Eric Blake 提交于
      The whole point of an alternate is to allow some type-safety while
      still accepting more than one JSON type.  Meanwhile, the 'any'
      type exists to bypass type-safety altogether.  The two are
      incompatible: you can't accept every type, and still tell which
      branch of the alternate to use for the parse; fix this to give a
      sane error instead of a Python stack trace.
      
      Note that other types that can't be alternate members are caught
      earlier, by check_type().
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-4-git-send-email-eblake@redhat.com>
      [Commit message tweaked]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      46534309
    • E
      qapi: Forbid empty unions and useless alternates · 02a57ae3
      Eric Blake 提交于
      Empty unions serve no purpose, and while we compile with gcc
      which permits them, strict C99 forbids them.  We happen to inject
      a dummy 'void *data' member into the C unions that represent QAPI
      unions and alternates, but we want to get rid of that member (it
      pollutes the namespace for no good reason), which would leave us
      with an empty union if the user didn't provide any branches.  While
      empty structs make sense in QAPI, empty unions don't add any
      expressiveness to the QMP language.  So prohibit them at parse
      time.  Update the documentation and testsuite to match.
      
      Note that the documentation already mentioned that alternates
      should have "two or more JSON data types"; so this also fixes
      the code to enforce that.  However, we have existing uses of a
      union type with only one branch, so the 2-or-more strictness
      is intentionally limited to alternates.
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1455778109-6278-3-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      02a57ae3
  8. 09 2月, 2016 5 次提交
    • E
      qapi: Fix compilation failure on MIPS and SPARC · 86ae1911
      Eric Blake 提交于
      Commit 86f4b687 broke compilation on MIPS and SPARC, which have a
      preprocessor pollution of '#define mips 1' and '#define sparc 1',
      respectively.  Treat it the same way as we do for the pollution with
      'unix', so that QMP remains backwards compatible and only the C code
      needs to use the alternative 'q_mips', 'q_sparc' spelling.
      
      CC: James Hogan <james.hogan@imgtec.com>
      CC: Peter Maydell <peter.maydell@linaro.org>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Tested-by: NJames Hogan <james.hogan@imgtec.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      86ae1911
    • E
      qapi: Swap visit_* arguments for consistent 'name' placement · 51e72bc1
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Reviewed-by: NMarc-André Lureau <marcandre.lureau@redhat.com>
      Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      51e72bc1
    • E
      qapi: Improve generated event use of qapi visitor · a16e3e5c
      Eric Blake 提交于
      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: NEric Blake <eblake@redhat.com>
      Message-Id: <1454075341-13658-11-git-send-email-eblake@redhat.com>
      [Commit message's code diff tweaked]
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      a16e3e5c
    • E
      qapi: Drop dead parameter in gen_params() · e4083115
      Eric Blake 提交于
      Commit 5cdc8831 reworked gen_params() to be simpler, but forgot
      to clean up a now-unused errp named argument.
      
      No change to generated code.
      Reported-by: NMarkus Armbruster <armbru@redhat.com>
      Signed-off-by: NEric Blake <eblake@redhat.com>
      Message-Id: <1454075341-13658-6-git-send-email-eblake@redhat.com>
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      e4083115
    • M
      qapi: Use Python 2.6 "except E as ..." syntax · 291928a8
      Markus Armbruster 提交于
      PEP 8 calls for it, because it's forward compatible with Python 3.
      Supported since Python 2.6, which we require (commit fec21036).
      Signed-off-by: NMarkus Armbruster <armbru@redhat.com>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      Acked-by: NStefan Hajnoczi <stefanha@redhat.com>
      Message-Id: <1450425164-24969-2-git-send-email-armbru@redhat.com>
      291928a8