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
>