Polite ping.
Regards,
Shi Lei
From: "Shi Lei" <shi_lei(a)massclouds.com>
Date: 2020-09-04 11:34:52
To: libvir-list(a)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