Polite ping.

Regards,
Shi Lei


From: "Shi Lei" <shi_lei@massclouds.com>
Date: 2020-09-04 11:34:52
To:  libvir-list@redhat.com
Subject: [RFCv2 00/46] RFC: Generate parsexml/formatbuf functions based on directives>V1 here: [https://www.redhat.com/archives/libvir-list/2020-June/msg00357.html]
>
>Differ from V1:
>
>  * Move the generator into scripts/xmlgen and rename it 'xmlgen'.
>
>  * Declare virXMLChildNode and virXMLChildNodeSet in libvirt_private.syms.
>
>  * Replace VIR_FREE with g_free and VIR_ALLOC[_N] with g_new0.
>
>  * Adjust virReportError to avoid unnecessary translation.
>
>  * Remove the macro VIR_USED and use G_GNUC_UNUSED to declare arguments.
>
>  * When parsing string member, assign value to it directly instead of
>    using middle variable.
>
>  * Don't set libclang_path. Just use python-clang's default setting.
>
>  * Use virEscapeString for escaping xml characters.
>
>  * Enable directive 'genformat' with a parameter to support separation mode.
>
>  * Add directive 'xmlswitch' and 'xmlgroup' to support discriminated unions.
>
>  * Allow directive 'array' and 'specified' to carry with a parameter,
>    which specifies its counterpart explicitly.
>
>  * Enable directive 'xmlattr' with path.
>
>  * Add directive 'formatflag' and 'formathook'.
>
>
>For those new and changed directives, illustrate them by an example:
>
>struct _virDomainGraphicsAuthDef {  /* genparse, genformat:separate */
>    char *passwd;                   /* xmlattr, formatflag:VIR_DOMAIN_DEF_FORMAT_SECURE */
>    bool expires;
>    time_t validTo;                 /* xmlattr:passwdValidTo, specified:expires */
>    virDomainGraphicsAuthConnectedType connected;   /* xmlattr */
>};
>
>struct _virDomainGraphicsListenDef {    /* genparse:withhook, genformat */
>    virDomainGraphicsListenType type;   /* xmlattr */
>    char *address;                      /* xmlattr, formathook */
>    char *network;                      /* xmlattr, formatflag:VIR_DOMAIN_GRAPHICS_LISTEN_TYPE_NETWORK */
>    char *socket;                       /* xmlattr, formathook */
>    int fromConfig;                     /* xmlattr, formatflag:%VIR_DOMAIN_DEF_FORMAT_STATUS */
>    bool autoGenerated;                 /* xmlattr, formatflag:%VIR_DOMAIN_DEF_FORMAT_STATUS */
>};
>
>struct _virDomainGraphicsSDLDef {   /* genparse, genformat:separate */
>    char *display;                  /* xmlattr */
>    char *xauth;                    /* xmlattr */
>    bool fullscreen;                /* xmlattr */
>    virTristateBool gl;             /* xmlattr:gl/enable */
>};
>
>struct _virDomainGraphicsDef {  /* genparse:concisehook, genformat */
>    virObjectPtr privateData;
>    virDomainGraphicsType type;                         /* xmlattr */
>
>    size_t nListens;
>    virDomainGraphicsListenDefPtr listens;  /* xmlelem, array:nListens */
>
>    union {
>        virDomainGraphicsSDLDef sdl;                    /* xmlgroup */
>        virDomainGraphicsVNCDef vnc;                    /* xmlgroup */
>        virDomainGraphicsRDPDef rdp;                    /* xmlgroup */
>        virDomainGraphicsDesktopDef desktop;            /* xmlgroup */
>        virDomainGraphicsSpiceDef spice;                /* xmlgroup */
>        virDomainGraphicsEGLHeadlessDef egl_headless;   /* xmlgroup */
>    } data;                                             /* xmlswitch:type */
>};
>
>
>Explanation for these directives:
>
>    - genformat[:separate|onlyattrs|onlyelems]
>
>      Only work on a struct.
>      Generate formatbuf function for this struct only if 'genformat' is specified.
>      The function name is based on struct-name and suffixed with 'FormatBuf'.
>
>      When 'genformat:separate' is specified, generate two formatbuf functions
>      rather than a single full-mode formatbuf function.
>      One for formatting attributes and another for formatting elements.
>      These function names are based on struct-name and suffixed with 'FormatAttr'
>      and 'FormatElem' respectively.
>
>      The 'onlyattrs' and 'onlyelems' are just like 'separate', but only
>      generate one of those two functions according to its denotation.
>
>    - xmlattr[:[parentname/]thename]
>
>      Parse/Format the field as an XML attribute or
>      attribute wrapped by an XML element.
>      If only 'thename' is specified, use it as the XML attribute name;
>      or use the filed name.
>      The 'parentname' is the name of the attribute's parent element.
>      If 'parentname/thename' is specified, the corresponding form is
>      <parentname thename='..' />.
>
>    - xmlgroup
>
>      The field is a struct, but its corresponding form in XML is a group
>      rather than an element.
>
>    - xmlswitch:thename
>
>      Only for discriminated union. 'thename' is the name of its relative enum.
>      The name of each union member should match a shortname of the enum.
>
>    - array[:countername]
>
>      Parse/Format the field as an array.
>      Each array field must have an related counter field, which name is
>      specified by 'countername'.
>      If 'countername' is omitted, follow the pattern:
>      n + 'field_name'.
>
>    - specified[:thename]
>
>      This field has an related field to indicate its existence, and
>      'thename' specifies the name of this related field.
>      When 'thename' is omitted, follow the pattern:
>      'field_name' + '_specified'.
>
>    - formatflag:[!|%]flag
>
>      This field will be formatted and written out to XML only if the 'flag'
>      hits a target flagset.
>      The target flagset is passed into the formatbuf function through the
>      argument 'opaque'.
>
>      Adding a '!' before 'flag' means NOT hitting.
>
>      Adding a '%' before 'flag' means that flag hitting-check is the unique
>      condition for formatting this field. For example,
>      for 'passwd' in 'virDomainGraphicsAuthDef', the directive is:
>
>        formatflag:VIR_DOMAIN_DEF_FORMAT_SECURE
>
>      then the generated code:
>
>        if (def->passwd && (virXMLFlag(opaque) & VIR_DOMAIN_DEF_FORMAT_SECURE))
>            virBufferEscapeString(buf, " passwd='%s'", def->passwd);
>
>      If '%' is inserted like this:
>
>        formatflag:%VIR_DOMAIN_DEF_FORMAT_SECURE
>
>      then the generated code:
>
>        if ((virXMLFlag(opaque) & VIR_DOMAIN_DEF_FORMAT_SECURE))
>            virBufferEscapeString(buf, " passwd='%s'", def->passwd);
>
>    - formathook
>      Introduce hooks to handle the field if xmlgen can't deal with it now.
>
>      E.g., virDomainGraphicsListenDef have two fields with 'formathook',
>      which are 'address' and 'socket'.
>      The xmlgen will generate the declaration of some hooks for formatting
>      these fields and developers should implement them.
>
>      1) Check the declaration of hook by a commandline.
>
>        # ./scripts/xmlgen/go show virDomainGraphicsListenDef -kf
>
>        int
>        virDomainGraphicsListenDefFormatHook(const virDomainGraphicsListenDef *def,
>                                             const void *parent,
>                                             const void *opaque,
>                                             virBufferPtr addressBuf,
>                                             virBufferPtr socketBuf);
>
>        bool
>        virDomainGraphicsListenDefCheckHook(const virDomainGraphicsListenDef *def,
>                                            const void *parent,
>                                            void *opaque,
>                                            bool result);
>
>      2) Implement these two hooks in src/conf/domain_conf.c.
>
>      2.1) virXXXFormatHook
>        It is the hook for formatting field 'address' and 'socket'.
>        The 'addressBuf' and 'socketBuf' are used for output destinations respectively.
>
>      2.2) virXXXCheckHook
>        For structs, the xmlgen generates virXXXCheck function to come with
>        the virXXXFormatBuf. The virXXXCheck reports whether the corresponding
>        XML element is null.
>
>        The virXXXCheckHook intercepts the 'result' of virXXXCheck. It changes 'result'
>        or just forwards it according to those fields with 'formathook'.
>
>    Thanks!
>
>
>Shi Lei (46):
>  scripts: Add a tool to generate xml parse/format functions
>  maint: Check python3-clang
>  maint: Call xmlgen automatically when c-head-files change
>  util: Add some xml-helper-functions to cooperate with xmlgen
>  util: Add helper functions for 'bool' and 'time_t' and cooperate with
>    xmlgen
>  util: Add parsexml/formatbuf helper functions for virSocketAddr
>  conf: Extract error-checking code from virNetworkDNSTxtDefParseXML
>  conf: Replace virNetworkDNSTxtDefParseXML(hardcoded) with
>    namesake(generated)
>  conf: Generate virNetworkDNSTxtDefFormatBuf
>  conf: Extract error-checking code from virNetworkDNSSrvDefParseXML
>  conf: Replace virNetworkDNSSrvDefParseXML(hardcoded) with
>    namesake(generated)
>  conf: Generate virNetworkDNSSrvDefFormatBuf
>  conf: Extract error-checking code from virNetworkDNSHostDefParseXML
>  conf: Replace virNetworkDNSHostDefParseXML(hardcoded) with
>    namesake(generated)
>  conf: Generate virNetworkDNSHostDefFormatBuf
>  conf: Extract virNetworkDNSForwarderParseXML from
>    virNetworkDNSParseXML
>  conf: Replace virNetworkDNSForwarderParseXML(hardcoded) with
>    namesake(generated)
>  conf: Generate virNetworkDNSForwarderFormatBuf
>  conf: Extract error-checking code from virNetworkDNSDefParseXML
>  conf: Replace virNetworkDNSDefParseXML(hardcoded) with
>    namesake(generated)
>  conf: Generate virNetworkDNSDefFormatBuf
>  conf: Extract embedded structs from virDomainGraphicsDef as standalone
>    structs
>  conf: Replace virDomainGraphicsDefParseXMLSDL(hardcoded) with
>    virDomainGraphicsSDLDefParseXML(generated)
>  conf: Generate format functions for virDomainGraphicsSDLDef
>  conf: Replace virDomainGraphicsAuthDefParseXML(hardcoded) with
>    namesake(generated)
>  conf: Generate format functions for virDomainGraphicsAuthDef
>  conf: Extract error-checking code from virDomainGraphicsDefParseXMLVNC
>  conf: Replace virDomainGraphicsDefParseXMLVNC(hardcoded) with
>    virDomainGraphicsVNCDefParseXML(generated)
>  conf: Generate virDomainGraphicsVNCDefFormatAttr
>  conf: Extract error-checking code from virDomainGraphicsDefParseXMLRDP
>  conf: Replace virDomainGraphicsDefParseXMLRDP(hardcoded) with
>    virDomainGraphicsRDPDefParseXML(generated)
>  conf: Generate virDomainGraphicsRDPDefFormatAttr
>  conf: Replace virDomainGraphicsDefParseXMLDesktop(hardcoded) with
>    virDomainGraphicsDesktopDefParseXML(generated)
>  conf: Generate virDomainGraphicsDesktopDefFormatAttr
>  conf: Add virSpiceChannelDef to help to parse the member 'channels' of
>    virDomainGraphicsSpiceDef
>  conf: Extract error-checking code from
>    virDomainGraphicsDefParseXMLSpice
>  conf: Replace virDomainGraphicsDefParseXMLSpice(hardcoded) with
>    virDomainGraphicsSpiceDefParseXML(generated)
>  conf: Generate virDomainGraphicsSpiceDefFormatElem and
>    virDomainGraphicsSpiceDefFormatAttr
>  conf: Replace virDomainGraphicsDefParseXMLEGLHeadless(hardcoded) with
>    virDomainGraphicsEGLHeadlessDefParseXML(generated)
>  conf: Generate virDomainGraphicsEGLHeadlessDefFormatElem
>  conf: Extract error-checking code from
>    virDomainGraphicsListenDefParseXML
>  conf: Replace virDomainGraphicsListenDefParseXML(hardcoded) with
>    namesake(generated)
>  conf: Generate virDomainGraphicsListenDefFormatBuf
>  conf: Extract error-checking code from virDomainGraphicsDefParseXML
>  conf: Replace virDomainGraphicsDefParseXML(hardcoded) with
>    namesake(generated)
>  conf: Replace virDomainGraphicsDefFormat(hardcoded) with
>    virDomainGraphicsDefFormatBuf(generated)
>
> meson.build                      |    5 +
> po/POTFILES.in                   |    3 +
> scripts/meson.build              |    8 +
> scripts/xmlgen/directive.py      | 1115 ++++++++++++++++++++
> scripts/xmlgen/go                |    7 +
> scripts/xmlgen/main.py           |  439 ++++++++
> scripts/xmlgen/utils.py          |  121 +++
> src/conf/domain_conf.c           | 1650 +++++++++---------------------
> src/conf/domain_conf.h           |  179 ++--
> src/conf/meson.build             |   41 +
> src/conf/network_conf.c          |  467 ++-------
> src/conf/network_conf.h          |   54 +-
> src/conf/virconftypes.h          |   18 +
> src/libvirt_private.syms         |    9 +
> src/meson.build                  |    6 +
> src/qemu/qemu_command.c          |    4 +
> src/qemu/qemu_driver.c           |    2 +
> src/qemu/qemu_hotplug.c          |    2 +
> src/qemu/qemu_migration_cookie.c |    1 +
> src/qemu/qemu_process.c          |    5 +
> src/qemu/qemu_validate.c         |    2 +
> src/util/virsocketaddr.c         |   42 +
> src/util/virsocketaddr.h         |   26 +-
> src/util/virstring.c             |   57 ++
> src/util/virstring.h             |    9 +
> src/util/virxml.c                |  105 ++
> src/util/virxml.h                |    6 +
> src/vmx/vmx.c                    |    1 +
> tests/meson.build                |    1 +
> tools/meson.build                |    2 +
> 30 files changed, 2738 insertions(+), 1649 deletions(-)
> create mode 100644 scripts/xmlgen/directive.py
> create mode 100755 scripts/xmlgen/go
> create mode 100755 scripts/xmlgen/main.py
> create mode 100644 scripts/xmlgen/utils.py
>
>--
>2.25.1
>