diff mbox series

[V11.1,1/3] libxl: Add support for Virtio disk configuration

Message ID 20220716163745.28712-1-olekstysh@gmail.com (mailing list archive)
State New, archived
Headers show
Series [V11.1,1/3] libxl: Add support for Virtio disk configuration | expand

Commit Message

Oleksandr Tyshchenko July 16, 2022, 4:37 p.m. UTC
From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>

This patch adds basic support for configuring and assisting virtio-mmio
based virtio-disk backend (emulator) which is intended to run out of
Qemu and could be run in any domain.
Although the Virtio block device is quite different from traditional
Xen PV block device (vbd) from the toolstack's point of view:
 - as the frontend is virtio-blk which is not a Xenbus driver, nothing
   written to Xenstore are fetched by the frontend currently ("vdev"
   is not passed to the frontend). But this might need to be revised
   in future, so frontend data might be written to Xenstore in order to
   support hotplugging virtio devices or passing the backend domain id
   on arch where the device-tree is not available.
 - the ring-ref/event-channel are not used for the backend<->frontend
   communication, the proposed IPC for Virtio is IOREQ/DM
it is still a "block device" and ought to be integrated in existing
"disk" handling. So, re-use (and adapt) "disk" parsing/configuration
logic to deal with Virtio devices as well.

For the immediate purpose and an ability to extend that support for
other use-cases in future (Qemu, virtio-pci, etc) perform the following
actions:
- Add new disk backend type (LIBXL_DISK_BACKEND_STANDALONE) and reflect
  that in the configuration
- Introduce new disk "specification" and "transport" fields to struct
  libxl_device_disk. Both are written to the Xenstore. The transport
  field is only used for the specification "virtio" and it assumes
  only "mmio" value for now.
- Introduce new "specification" option with "xen" communication
  protocol being default value.
- Add new device kind (LIBXL__DEVICE_KIND_VIRTIO_DISK) as current
  one (LIBXL__DEVICE_KIND_VBD) doesn't fit into Virtio disk model

An example of domain configuration for Virtio disk:
disk = [ 'phy:/dev/mmcblk0p3, xvda1, backendtype=standalone, specification=virtio']

Nothing has changed for default Xen disk configuration.

Please note, this patch is not enough for virtio-disk to work
on Xen (Arm), as for every Virtio device (including disk) we need
to allocate Virtio MMIO params (IRQ and memory region) and pass
them to the backend, also update Guest device-tree. The subsequent
patch will add these missing bits. For the current patch,
the default "irq" and "base" are just written to the Xenstore.
This is not an ideal splitting, but this way we avoid breaking
the bisectability.

Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
---
Changes RFC -> V1:
   - no changes

Changes V1 -> V2:
   - rebase according to the new location of libxl_virtio_disk.c

Changes V2 -> V3:
   - no changes

Changes V3 -> V4:
   - rebase according to the new argument for DEFINE_DEVICE_TYPE_STRUCT

Changes V4 -> V5:
   - split the changes, change the order of the patches
   - update patch description
   - don't introduce new "vdisk" configuration option with own parsing logic,
     re-use Xen PV block "disk" parsing/configuration logic for the virtio-disk
   - introduce "virtio" flag and document it's usage
   - add LIBXL_HAVE_DEVICE_DISK_VIRTIO
   - update libxlu_disk_l.[ch]
   - drop num_disks variable/MAX_VIRTIO_DISKS
   - drop Wei's T-b

Changes V5 -> V6:
   - rebase on current staging
   - use "%"PRIu64 instead of %lu for disk->base in device_disk_add()
   - update *.gen.go files

Changes V6 -> V7:
   - rebase on current staging
   - update *.gen.go files and libxlu_disk_l.[ch] files
   - update patch description
   - rework significantly to support more flexible configuration
     and have more generic basic implementation for being able to extend
     that for other use-cases (virtio-pci, qemu, etc).

Changes V7 -> V8:
   - update *.gen.go files and libxlu_disk_l.[ch] files
   - update patch description and comments in the code
   - use "specification" config option instead of "protocol"
   - update libxl_types.idl and code according to new fields
     in libxl_device_disk

Changes V8 -> V9:
   - update (and harden) checks in libxl__device_disk_setdefault(),
     return error in case of incorrect settings of specification
     and transport
   - remove both asserts in device_disk_add()
   - update virtio related code in libxl__disk_from_xenstore(),
     do not fail if specification node is absent, replace
     open-coded checks of fetched specification and transport by
     libxl_disk_specification_from_string() and libxl_disk_transport_from_string()
     respectively
   - s/libxl_device_disk_get_path/libxl__device_disk_get_path
   - add a comment for virtio-mmio parameters in struct libxl_device_disk

Changes V9 -> V10:
   - s/ERROR_FAIL/ERROR_INVAL in both places in libxl__device_disk_setdefault()
   - rework libxl__device_disk_get_path()

Changes V10 -> V10.1:
   - fix small coding style issue in libxl__device_disk_get_path()
   - drop specification check in main_blockattach() and add
     required check in libxl__device_disk_setdefault()
   - update specification check in main_blockdetach()

Changes V10.1 -> V11:
   - Anthony already gave his Reviewed-by, I dropped it due to the changes
   - George already gave his Acked-by, I dropped it due to the changes
   - s/other/standalone for the backendtype

Changes V11 -> V11.1:
   - rebase
---
 docs/man/xl-disk-configuration.5.pod.in   |  38 +-
 tools/golang/xenlight/helpers.gen.go      |   8 +
 tools/golang/xenlight/types.gen.go        |  18 +
 tools/include/libxl.h                     |   7 +
 tools/libs/light/libxl_device.c           |  62 +-
 tools/libs/light/libxl_disk.c             | 146 +++-
 tools/libs/light/libxl_internal.h         |   2 +
 tools/libs/light/libxl_types.idl          |  18 +
 tools/libs/light/libxl_types_internal.idl |   1 +
 tools/libs/light/libxl_utils.c            |   2 +
 tools/libs/util/libxlu_disk_l.c           | 959 +++++++++++-----------
 tools/libs/util/libxlu_disk_l.h           |   2 +-
 tools/libs/util/libxlu_disk_l.l           |   9 +
 tools/xl/xl_block.c                       |   6 +
 14 files changed, 798 insertions(+), 480 deletions(-)

Comments

Jiamei Xie July 20, 2022, 3:29 a.m. UTC | #1
Hi Oleksandr,

We have tested it on arm64 with " disk = [ 'phy:/usr/share/guests/disk.img0, xvda1, backendtype=standalone, specification=virtio']". It works ok.

Tested-by: Jiamei Xie <jiamei.xie@arm.com>
Tested-by: Henry Wang <Henry.Wang@arm.com>

Best wishes
Jiamei Xie


> -----Original Message-----
> From: Xen-devel <xen-devel-bounces@lists.xenproject.org> On Behalf Of
> Oleksandr Tyshchenko
> Sent: Sunday, July 17, 2022 12:38 AM
> To: xen-devel@lists.xenproject.org
> Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>; Wei Liu
> <wl@xen.org>; Anthony PERARD <anthony.perard@citrix.com>; George
> Dunlap <george.dunlap@citrix.com>; Nick Rosbrook
> <rosbrookn@gmail.com>; Juergen Gross <jgross@suse.com>; Stefano
> Stabellini <sstabellini@kernel.org>; Julien Grall <julien@xen.org>; Volodymyr
> Babchuk <Volodymyr_Babchuk@epam.com>; Bertrand Marquis
> <Bertrand.Marquis@arm.com>
> Subject: [PATCH V11.1 1/3] libxl: Add support for Virtio disk configuration
> 
> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> 
> This patch adds basic support for configuring and assisting virtio-mmio
> based virtio-disk backend (emulator) which is intended to run out of
> Qemu and could be run in any domain.
> Although the Virtio block device is quite different from traditional
> Xen PV block device (vbd) from the toolstack's point of view:
>  - as the frontend is virtio-blk which is not a Xenbus driver, nothing
>    written to Xenstore are fetched by the frontend currently ("vdev"
>    is not passed to the frontend). But this might need to be revised
>    in future, so frontend data might be written to Xenstore in order to
>    support hotplugging virtio devices or passing the backend domain id
>    on arch where the device-tree is not available.
>  - the ring-ref/event-channel are not used for the backend<->frontend
>    communication, the proposed IPC for Virtio is IOREQ/DM
> it is still a "block device" and ought to be integrated in existing
> "disk" handling. So, re-use (and adapt) "disk" parsing/configuration
> logic to deal with Virtio devices as well.
> 
> For the immediate purpose and an ability to extend that support for
> other use-cases in future (Qemu, virtio-pci, etc) perform the following
> actions:
> - Add new disk backend type (LIBXL_DISK_BACKEND_STANDALONE) and
> reflect
>   that in the configuration
> - Introduce new disk "specification" and "transport" fields to struct
>   libxl_device_disk. Both are written to the Xenstore. The transport
>   field is only used for the specification "virtio" and it assumes
>   only "mmio" value for now.
> - Introduce new "specification" option with "xen" communication
>   protocol being default value.
> - Add new device kind (LIBXL__DEVICE_KIND_VIRTIO_DISK) as current
>   one (LIBXL__DEVICE_KIND_VBD) doesn't fit into Virtio disk model
> 
> An example of domain configuration for Virtio disk:
> disk = [ 'phy:/dev/mmcblk0p3, xvda1, backendtype=standalone,
> specification=virtio']
> 
> Nothing has changed for default Xen disk configuration.
> 
> Please note, this patch is not enough for virtio-disk to work
> on Xen (Arm), as for every Virtio device (including disk) we need
> to allocate Virtio MMIO params (IRQ and memory region) and pass
> them to the backend, also update Guest device-tree. The subsequent
> patch will add these missing bits. For the current patch,
> the default "irq" and "base" are just written to the Xenstore.
> This is not an ideal splitting, but this way we avoid breaking
> the bisectability.
> 
> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> ---
> Changes RFC -> V1:
>    - no changes
> 
> Changes V1 -> V2:
>    - rebase according to the new location of libxl_virtio_disk.c
> 
> Changes V2 -> V3:
>    - no changes
> 
> Changes V3 -> V4:
>    - rebase according to the new argument for DEFINE_DEVICE_TYPE_STRUCT
> 
> Changes V4 -> V5:
>    - split the changes, change the order of the patches
>    - update patch description
>    - don't introduce new "vdisk" configuration option with own parsing logic,
>      re-use Xen PV block "disk" parsing/configuration logic for the virtio-disk
>    - introduce "virtio" flag and document it's usage
>    - add LIBXL_HAVE_DEVICE_DISK_VIRTIO
>    - update libxlu_disk_l.[ch]
>    - drop num_disks variable/MAX_VIRTIO_DISKS
>    - drop Wei's T-b
> 
> Changes V5 -> V6:
>    - rebase on current staging
>    - use "%"PRIu64 instead of %lu for disk->base in device_disk_add()
>    - update *.gen.go files
> 
> Changes V6 -> V7:
>    - rebase on current staging
>    - update *.gen.go files and libxlu_disk_l.[ch] files
>    - update patch description
>    - rework significantly to support more flexible configuration
>      and have more generic basic implementation for being able to extend
>      that for other use-cases (virtio-pci, qemu, etc).
> 
> Changes V7 -> V8:
>    - update *.gen.go files and libxlu_disk_l.[ch] files
>    - update patch description and comments in the code
>    - use "specification" config option instead of "protocol"
>    - update libxl_types.idl and code according to new fields
>      in libxl_device_disk
> 
> Changes V8 -> V9:
>    - update (and harden) checks in libxl__device_disk_setdefault(),
>      return error in case of incorrect settings of specification
>      and transport
>    - remove both asserts in device_disk_add()
>    - update virtio related code in libxl__disk_from_xenstore(),
>      do not fail if specification node is absent, replace
>      open-coded checks of fetched specification and transport by
>      libxl_disk_specification_from_string() and
> libxl_disk_transport_from_string()
>      respectively
>    - s/libxl_device_disk_get_path/libxl__device_disk_get_path
>    - add a comment for virtio-mmio parameters in struct libxl_device_disk
> 
> Changes V9 -> V10:
>    - s/ERROR_FAIL/ERROR_INVAL in both places in
> libxl__device_disk_setdefault()
>    - rework libxl__device_disk_get_path()
> 
> Changes V10 -> V10.1:
>    - fix small coding style issue in libxl__device_disk_get_path()
>    - drop specification check in main_blockattach() and add
>      required check in libxl__device_disk_setdefault()
>    - update specification check in main_blockdetach()
> 
> Changes V10.1 -> V11:
>    - Anthony already gave his Reviewed-by, I dropped it due to the changes
>    - George already gave his Acked-by, I dropped it due to the changes
>    - s/other/standalone for the backendtype
> 
> Changes V11 -> V11.1:
>    - rebase
> ---
>  docs/man/xl-disk-configuration.5.pod.in   |  38 +-
>  tools/golang/xenlight/helpers.gen.go      |   8 +
>  tools/golang/xenlight/types.gen.go        |  18 +
>  tools/include/libxl.h                     |   7 +
>  tools/libs/light/libxl_device.c           |  62 +-
>  tools/libs/light/libxl_disk.c             | 146 +++-
>  tools/libs/light/libxl_internal.h         |   2 +
>  tools/libs/light/libxl_types.idl          |  18 +
>  tools/libs/light/libxl_types_internal.idl |   1 +
>  tools/libs/light/libxl_utils.c            |   2 +
>  tools/libs/util/libxlu_disk_l.c           | 959 +++++++++++-----------
>  tools/libs/util/libxlu_disk_l.h           |   2 +-
>  tools/libs/util/libxlu_disk_l.l           |   9 +
>  tools/xl/xl_block.c                       |   6 +
>  14 files changed, 798 insertions(+), 480 deletions(-)
> 
> diff --git a/docs/man/xl-disk-configuration.5.pod.in b/docs/man/xl-disk-
> configuration.5.pod.in
> index 95d039655a..bc945cc517 100644
> --- a/docs/man/xl-disk-configuration.5.pod.in
> +++ b/docs/man/xl-disk-configuration.5.pod.in
> @@ -232,7 +232,7 @@ Specifies the backend implementation to use
> 
>  =item Supported values
> 
> -phy, qdisk
> +phy, qdisk, standalone
> 
>  =item Mandatory
> 
> @@ -244,11 +244,13 @@ Automatically determine which backend to use.
> 
>  =back
> 
> -This does not affect the guest's view of the device.  It controls
> -which software implementation of the Xen backend driver is used.
> +It controls which software implementation of the backend driver is used.
> +Depending on the "specification" option this may affect the guest's view
> +of the device.
> 
>  Not all backend drivers support all combinations of other options.
> -For example, "phy" does not support formats other than "raw".
> +For example, "phy" and "standalone" do not support formats other than
> "raw"
> +and "standalone" does not support specifications other than "virtio".
>  Normally this option should not be specified, in which case libxl will
>  automatically determine the most suitable backend.
> 
> @@ -373,8 +375,36 @@ processing or causing malfunction to the frontend
> or the whole domain.
> 
>  Note frontends can ignore such recommendation.
> 
> +=item B<specification>=I<SPECIFICATION>
> +
> +=over 4
> +
> +=item Description
> +
> +Specifies the communication protocol (specification) to use for the chosen
> +"backendtype" option
> +
> +=item Supported values
> +
> +xen, virtio
> +
> +=item Mandatory
> +
> +No
> +
> +=item Default value
> +
> +xen
> +
>  =back
> 
> +Besides forcing toolstack to use specific backend implementation, this also
> +affects the guest's view of the device. For example, "virtio" requires
> +Virtio frontend driver (virtio-blk) to be used. Please note, the virtual
> +device (vdev) is not passed to the guest in that case, but it still must be
> +specified for the internal purposes.
> +
> +=back
> 
>  =head1 COLO Parameters
> 
> diff --git a/tools/golang/xenlight/helpers.gen.go
> b/tools/golang/xenlight/helpers.gen.go
> index dece545ee0..ad8c11eae1 100644
> --- a/tools/golang/xenlight/helpers.gen.go
> +++ b/tools/golang/xenlight/helpers.gen.go
> @@ -1763,6 +1763,10 @@ x.DirectIoSafe = bool(xc.direct_io_safe)
>  if err := x.DiscardEnable.fromC(&xc.discard_enable);err != nil {
>  return fmt.Errorf("converting field DiscardEnable: %v", err)
>  }
> +x.Specification = DiskSpecification(xc.specification)
> +x.Transport = DiskTransport(xc.transport)
> +x.Irq = uint32(xc.irq)
> +x.Base = uint64(xc.base)
>  if err := x.ColoEnable.fromC(&xc.colo_enable);err != nil {
>  return fmt.Errorf("converting field ColoEnable: %v", err)
>  }
> @@ -1800,6 +1804,10 @@ xc.direct_io_safe = C.bool(x.DirectIoSafe)
>  if err := x.DiscardEnable.toC(&xc.discard_enable); err != nil {
>  return fmt.Errorf("converting field DiscardEnable: %v", err)
>  }
> +xc.specification = C.libxl_disk_specification(x.Specification)
> +xc.transport = C.libxl_disk_transport(x.Transport)
> +xc.irq = C.uint32_t(x.Irq)
> +xc.base = C.uint64_t(x.Base)
>  if err := x.ColoEnable.toC(&xc.colo_enable); err != nil {
>  return fmt.Errorf("converting field ColoEnable: %v", err)
>  }
> diff --git a/tools/golang/xenlight/types.gen.go
> b/tools/golang/xenlight/types.gen.go
> index 253c9ad93d..b9143390f8 100644
> --- a/tools/golang/xenlight/types.gen.go
> +++ b/tools/golang/xenlight/types.gen.go
> @@ -99,6 +99,20 @@ DiskBackendUnknown DiskBackend = 0
>  DiskBackendPhy DiskBackend = 1
>  DiskBackendTap DiskBackend = 2
>  DiskBackendQdisk DiskBackend = 3
> +DiskBackendStandalone DiskBackend = 4
> +)
> +
> +type DiskSpecification int
> +const(
> +DiskSpecificationUnknown DiskSpecification = 0
> +DiskSpecificationXen DiskSpecification = 1
> +DiskSpecificationVirtio DiskSpecification = 2
> +)
> +
> +type DiskTransport int
> +const(
> +DiskTransportUnknown DiskTransport = 0
> +DiskTransportMmio DiskTransport = 1
>  )
> 
>  type NicType int
> @@ -645,6 +659,10 @@ Readwrite int
>  IsCdrom int
>  DirectIoSafe bool
>  DiscardEnable Defbool
> +Specification DiskSpecification
> +Transport DiskTransport
> +Irq uint32
> +Base uint64
>  ColoEnable Defbool
>  ColoRestoreEnable Defbool
>  ColoHost string
> diff --git a/tools/include/libxl.h b/tools/include/libxl.h
> index f351669039..2321a648a5 100644
> --- a/tools/include/libxl.h
> +++ b/tools/include/libxl.h
> @@ -549,6 +549,13 @@
>   */
>  #define LIBXL_HAVE_ASSISTED_APIC 1
> 
> +/*
> + * LIBXL_HAVE_DEVICE_DISK_SPECIFICATION indicates that 'specification'
> and
> + * 'transport' fields (of libxl_disk_specification and libxl_disk_transport
> + * types respectively) are present in libxl_device_disk.
> + */
> +#define LIBXL_HAVE_DEVICE_DISK_SPECIFICATION 1
> +
>  /*
>   * libxl ABI compatibility
>   *
> diff --git a/tools/libs/light/libxl_device.c b/tools/libs/light/libxl_device.c
> index e6025d135e..a75c21d433 100644
> --- a/tools/libs/light/libxl_device.c
> +++ b/tools/libs/light/libxl_device.c
> @@ -289,9 +289,16 @@ static int disk_try_backend(disk_try_backend_args
> *a,
>                              libxl_disk_backend backend)
>   {
>      libxl__gc *gc = a->gc;
> +    libxl_disk_specification specification = a->disk->specification;
>      /* returns 0 (ie, DISK_BACKEND_UNKNOWN) on failure, or
>       * backend on success */
> 
> +    if ((specification == LIBXL_DISK_SPECIFICATION_VIRTIO &&
> +         backend != LIBXL_DISK_BACKEND_STANDALONE) ||
> +        (specification != LIBXL_DISK_SPECIFICATION_VIRTIO &&
> +         backend == LIBXL_DISK_BACKEND_STANDALONE))
> +        goto bad_specification;
> +
>      switch (backend) {
>      case LIBXL_DISK_BACKEND_PHY:
>          if (a->disk->format != LIBXL_DISK_FORMAT_RAW) {
> @@ -329,6 +336,29 @@ static int disk_try_backend(disk_try_backend_args
> *a,
>          if (a->disk->script) goto bad_script;
>          return backend;
> 
> +    case LIBXL_DISK_BACKEND_STANDALONE:
> +        if (a->disk->format != LIBXL_DISK_FORMAT_RAW)
> +            goto bad_format;
> +
> +        if (a->disk->script)
> +            goto bad_script;
> +
> +        if (libxl_defbool_val(a->disk->colo_enable))
> +            goto bad_colo;
> +
> +        if (a->disk->backend_domid != LIBXL_TOOLSTACK_DOMID) {
> +            LOG(DEBUG, "Disk vdev=%s, is using a storage driver domain, "
> +                       "skipping physical device check", a->disk->vdev);
> +            return backend;
> +        }
> +
> +        if (libxl__try_phy_backend(a->stab.st_mode))
> +            return backend;
> +
> +        LOG(DEBUG, "Disk vdev=%s, backend standalone unsuitable as phys
> path not a "
> +                   "block device", a->disk->vdev);
> +        return 0;
> +
>      default:
>          LOG(DEBUG, "Disk vdev=%s, backend %d unknown", a->disk->vdev,
> backend);
>          return 0;
> @@ -352,6 +382,12 @@ static int disk_try_backend(disk_try_backend_args
> *a,
>      LOG(DEBUG, "Disk vdev=%s, backend %s not compatible with colo",
>          a->disk->vdev, libxl_disk_backend_to_string(backend));
>      return 0;
> +
> + bad_specification:
> +    LOG(DEBUG, "Disk vdev=%s, backend %s not compatible with
> specification %s",
> +        a->disk->vdev, libxl_disk_backend_to_string(backend),
> +        libxl_disk_specification_to_string(specification));
> +    return 0;
>  }
> 
>  int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
> @@ -376,8 +412,9 @@ int libxl__device_disk_set_backend(libxl__gc *gc,
> libxl_device_disk *disk) {
>      a.gc = gc;
>      a.disk = disk;
> 
> -    LOG(DEBUG, "Disk vdev=%s spec.backend=%s", disk->vdev,
> -               libxl_disk_backend_to_string(disk->backend));
> +    LOG(DEBUG, "Disk vdev=%s spec.backend=%s specification=%s", disk-
> >vdev,
> +               libxl_disk_backend_to_string(disk->backend),
> +               libxl_disk_specification_to_string(disk->specification));
> 
>      if (disk->format == LIBXL_DISK_FORMAT_EMPTY) {
>          if (!disk->is_cdrom) {
> @@ -392,7 +429,8 @@ int libxl__device_disk_set_backend(libxl__gc *gc,
> libxl_device_disk *disk) {
>          }
>          memset(&a.stab, 0, sizeof(a.stab));
>      } else if ((disk->backend == LIBXL_DISK_BACKEND_UNKNOWN ||
> -                disk->backend == LIBXL_DISK_BACKEND_PHY) &&
> +                disk->backend == LIBXL_DISK_BACKEND_PHY ||
> +                disk->backend == LIBXL_DISK_BACKEND_STANDALONE) &&
>                 disk->backend_domid == LIBXL_TOOLSTACK_DOMID &&
>                 !disk->script) {
>          if (stat(disk->pdev_path, &a.stab)) {
> @@ -408,7 +446,8 @@ int libxl__device_disk_set_backend(libxl__gc *gc,
> libxl_device_disk *disk) {
>          ok=
>              disk_try_backend(&a, LIBXL_DISK_BACKEND_PHY) ?:
>              disk_try_backend(&a, LIBXL_DISK_BACKEND_QDISK) ?:
> -            disk_try_backend(&a, LIBXL_DISK_BACKEND_TAP);
> +            disk_try_backend(&a, LIBXL_DISK_BACKEND_TAP) ?:
> +            disk_try_backend(&a, LIBXL_DISK_BACKEND_STANDALONE);
>          if (ok)
>              LOG(DEBUG, "Disk vdev=%s, using backend %s",
>                         disk->vdev,
> @@ -441,10 +480,25 @@ char
> *libxl__device_disk_string_of_backend(libxl_disk_backend backend)
>          case LIBXL_DISK_BACKEND_QDISK: return "qdisk";
>          case LIBXL_DISK_BACKEND_TAP: return "phy";
>          case LIBXL_DISK_BACKEND_PHY: return "phy";
> +        case LIBXL_DISK_BACKEND_STANDALONE: return "standalone";
> +        default: return NULL;
> +    }
> +}
> +
> +char *libxl__device_disk_string_of_specification(libxl_disk_specification
> specification)
> +{
> +    switch (specification) {
> +        case LIBXL_DISK_SPECIFICATION_XEN: return "xen";
> +        case LIBXL_DISK_SPECIFICATION_VIRTIO: return "virtio";
>          default: return NULL;
>      }
>  }
> 
> +char *libxl__device_disk_string_of_transport(libxl_disk_transport transport)
> +{
> +    return (transport == LIBXL_DISK_TRANSPORT_MMIO ? "mmio" : NULL);
> +}
> +
>  const char *libxl__qemu_disk_format_string(libxl_disk_format format)
>  {
>      switch (format) {
> diff --git a/tools/libs/light/libxl_disk.c b/tools/libs/light/libxl_disk.c
> index 9da2b2ed27..ea3623dd6f 100644
> --- a/tools/libs/light/libxl_disk.c
> +++ b/tools/libs/light/libxl_disk.c
> @@ -164,6 +164,30 @@ static int libxl__device_disk_setdefault(libxl__gc *gc,
> uint32_t domid,
>      rc = libxl__resolve_domid(gc, disk->backend_domname, &disk-
> >backend_domid);
>      if (rc < 0) return rc;
> 
> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_UNKNOWN)
> +        disk->specification = LIBXL_DISK_SPECIFICATION_XEN;
> +
> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_XEN &&
> +        disk->transport != LIBXL_DISK_TRANSPORT_UNKNOWN) {
> +        LOGD(ERROR, domid, "Transport is only supported for specification
> virtio");
> +        return ERROR_INVAL;
> +    }
> +
> +    /* Force transport mmio for specification virtio for now */
> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
> +        if (!(disk->transport == LIBXL_DISK_TRANSPORT_UNKNOWN ||
> +              disk->transport == LIBXL_DISK_TRANSPORT_MMIO)) {
> +            LOGD(ERROR, domid, "Unsupported transport for specification
> virtio");
> +            return ERROR_INVAL;
> +        }
> +        disk->transport = LIBXL_DISK_TRANSPORT_MMIO;
> +    }
> +
> +    if (hotplug && disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
> +        LOGD(ERROR, domid, "Hotplug isn't supported for specification virtio");
> +        return ERROR_FAIL;
> +    }
> +
>      /* Force Qdisk backend for CDROM devices of guests with a device model.
> */
>      if (disk->is_cdrom != 0 &&
>          libxl__domain_type(gc, domid) == LIBXL_DOMAIN_TYPE_HVM) {
> @@ -205,6 +229,9 @@ static int libxl__device_from_disk(libxl__gc *gc,
> uint32_t domid,
>          case LIBXL_DISK_BACKEND_QDISK:
>              device->backend_kind = LIBXL__DEVICE_KIND_QDISK;
>              break;
> +        case LIBXL_DISK_BACKEND_STANDALONE:
> +            device->backend_kind = LIBXL__DEVICE_KIND_VIRTIO_DISK;
> +            break;
>          default:
>              LOGD(ERROR, domid, "Unrecognized disk backend type: %d",
>                   disk->backend);
> @@ -213,7 +240,8 @@ static int libxl__device_from_disk(libxl__gc *gc,
> uint32_t domid,
> 
>      device->domid = domid;
>      device->devid = devid;
> -    device->kind  = LIBXL__DEVICE_KIND_VBD;
> +    device->kind = disk->backend == LIBXL_DISK_BACKEND_STANDALONE ?
> +        LIBXL__DEVICE_KIND_VIRTIO_DISK : LIBXL__DEVICE_KIND_VBD;
> 
>      return 0;
>  }
> @@ -331,7 +359,14 @@ static void device_disk_add(libxl__egc *egc,
> uint32_t domid,
> 
>                  assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
>                  break;
> +            case LIBXL_DISK_BACKEND_STANDALONE:
> +                dev = disk->pdev_path;
> +
> +                flexarray_append(back, "params");
> +                flexarray_append(back, dev);
> 
> +                assert(device->backend_kind ==
> LIBXL__DEVICE_KIND_VIRTIO_DISK);
> +                break;
>              case LIBXL_DISK_BACKEND_TAP:
>                  LOG(ERROR, "blktap is not supported");
>                  rc = ERROR_FAIL;
> @@ -387,6 +422,14 @@ static void device_disk_add(libxl__egc *egc,
> uint32_t domid,
>          flexarray_append_pair(back, "discard-enable",
>                                libxl_defbool_val(disk->discard_enable) ?
>                                "1" : "0");
> +        flexarray_append(back, "specification");
> +        flexarray_append(back, libxl__device_disk_string_of_specification(disk-
> >specification));
> +        if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
> +            flexarray_append(back, "transport");
> +            flexarray_append(back, libxl__device_disk_string_of_transport(disk-
> >transport));
> +            flexarray_append_pair(back, "base", GCSPRINTF("%"PRIu64, disk-
> >base));
> +            flexarray_append_pair(back, "irq", GCSPRINTF("%u", disk->irq));
> +        }
> 
>          flexarray_append(front, "backend-id");
>          flexarray_append(front, GCSPRINTF("%d", disk->backend_domid));
> @@ -535,6 +578,53 @@ static int libxl__disk_from_xenstore(libxl__gc *gc,
> const char *libxl_path,
>      }
>      libxl_string_to_backend(ctx, tmp, &(disk->backend));
> 
> +    tmp = libxl__xs_read(gc, XBT_NULL,
> +                         GCSPRINTF("%s/specification", libxl_path));
> +    if (!tmp) {
> +        LOG(DEBUG, "Missing xenstore node %s/specification, assuming
> specification xen", libxl_path);
> +        disk->specification = LIBXL_DISK_SPECIFICATION_XEN;
> +    } else {
> +        rc = libxl_disk_specification_from_string(tmp, &disk->specification);
> +        if (rc) {
> +            LOG(ERROR, "Unable to parse xenstore node %s/specification",
> libxl_path);
> +            goto cleanup;
> +        }
> +    }
> +
> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
> +        tmp = libxl__xs_read(gc, XBT_NULL,
> +                             GCSPRINTF("%s/transport", libxl_path));
> +        if (!tmp) {
> +            LOG(ERROR, "Missing xenstore node %s/transport", libxl_path);
> +            goto cleanup;
> +        }
> +        rc = libxl_disk_transport_from_string(tmp, &disk->transport);
> +        if (rc) {
> +            LOG(ERROR, "Unable to parse xenstore node %s/transport",
> libxl_path);
> +            goto cleanup;
> +        }
> +        if (disk->transport != LIBXL_DISK_TRANSPORT_MMIO) {
> +            LOG(ERROR, "Only transport mmio is expected for specification
> virtio");
> +            goto cleanup;
> +        }
> +
> +        tmp = libxl__xs_read(gc, XBT_NULL,
> +                             GCSPRINTF("%s/base", libxl_path));
> +        if (!tmp) {
> +            LOG(ERROR, "Missing xenstore node %s/base", libxl_path);
> +            goto cleanup;
> +        }
> +        disk->base = strtoul(tmp, NULL, 10);
> +
> +        tmp = libxl__xs_read(gc, XBT_NULL,
> +                             GCSPRINTF("%s/irq", libxl_path));
> +        if (!tmp) {
> +            LOG(ERROR, "Missing xenstore node %s/irq", libxl_path);
> +            goto cleanup;
> +        }
> +        disk->irq = strtoul(tmp, NULL, 10);
> +    }
> +
>      disk->vdev = xs_read(ctx->xsh, XBT_NULL,
>                           GCSPRINTF("%s/dev", libxl_path), &len);
>      if (!disk->vdev) {
> @@ -578,6 +668,42 @@ cleanup:
>      return rc;
>  }
> 
> +static int libxl__device_disk_get_path(libxl__gc *gc, uint32_t domid,
> +                                       char **path)
> +{
> +    const char *xen_dir, *virtio_dir;
> +    char *xen_path, *virtio_path;
> +    int rc;
> +
> +    /* default path */
> +    xen_path = GCSPRINTF("%s/device/%s",
> +                         libxl__xs_libxl_path(gc, domid),
> +                         libxl__device_kind_to_string(LIBXL__DEVICE_KIND_VBD));
> +
> +    rc = libxl__xs_read_checked(gc, XBT_NULL, xen_path, &xen_dir);
> +    if (rc)
> +        return rc;
> +
> +    virtio_path = GCSPRINTF("%s/device/%s",
> +                            libxl__xs_libxl_path(gc, domid),
> +
> libxl__device_kind_to_string(LIBXL__DEVICE_KIND_VIRTIO_DISK));
> +
> +    rc = libxl__xs_read_checked(gc, XBT_NULL, virtio_path, &virtio_dir);
> +    if (rc)
> +        return rc;
> +
> +    if (xen_dir && virtio_dir) {
> +        LOGD(ERROR, domid, "Invalid configuration, both xen and virtio paths
> are present");
> +        return ERROR_INVAL;
> +    } else if (virtio_dir) {
> +        *path = virtio_path;
> +    } else {
> +        *path = xen_path;
> +    }
> +
> +    return 0;
> +}
> +
>  int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid,
>                                const char *vdev, libxl_device_disk *disk)
>  {
> @@ -591,10 +717,12 @@ int libxl_vdev_to_device_disk(libxl_ctx *ctx,
> uint32_t domid,
> 
>      libxl_device_disk_init(disk);
> 
> -    libxl_path = libxl__domain_device_libxl_path(gc, domid, devid,
> -                                                 LIBXL__DEVICE_KIND_VBD);
> +    rc = libxl__device_disk_get_path(gc, domid, &libxl_path);
> +    if (rc)
> +        return rc;
> 
> -    rc = libxl__disk_from_xenstore(gc, libxl_path, devid, disk);
> +    rc = libxl__disk_from_xenstore(gc, GCSPRINTF("%s/%d", libxl_path, devid),
> +                                   devid, disk);
> 
>      GC_FREE;
>      return rc;
> @@ -608,16 +736,19 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx,
> uint32_t domid,
>      char *fe_path, *libxl_path;
>      char *val;
>      int rc;
> +    libxl__device_kind kind;
> 
>      diskinfo->backend = NULL;
> 
>      diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
> 
> -    /* tap devices entries in xenstore are written as vbd devices. */
> +    /* tap devices entries in xenstore are written as vbd/virtio_disk devices.
> */
> +    kind = disk->backend == LIBXL_DISK_BACKEND_STANDALONE ?
> +        LIBXL__DEVICE_KIND_VIRTIO_DISK : LIBXL__DEVICE_KIND_VBD;
>      fe_path = libxl__domain_device_frontend_path(gc, domid, diskinfo-
> >devid,
> -                                                 LIBXL__DEVICE_KIND_VBD);
> +                                                 kind);
>      libxl_path = libxl__domain_device_libxl_path(gc, domid, diskinfo->devid,
> -                                                 LIBXL__DEVICE_KIND_VBD);
> +                                                 kind);
>      diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
>                                  GCSPRINTF("%s/backend", libxl_path), NULL);
>      if (!diskinfo->backend) {
> @@ -1421,6 +1552,7 @@ LIBXL_DEFINE_DEVICE_LIST(disk)
>  #define libxl__device_disk_update_devid NULL
> 
>  DEFINE_DEVICE_TYPE_STRUCT(disk, VBD, disks,
> +    .get_path    = libxl__device_disk_get_path,
>      .merge       = libxl_device_disk_merge,
>      .dm_needed   = libxl_device_disk_dm_needed,
>      .from_xenstore = (device_from_xenstore_fn_t)libxl__disk_from_xenstore,
> diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h
> index bdef5a605e..cb9e8b3b8b 100644
> --- a/tools/libs/light/libxl_internal.h
> +++ b/tools/libs/light/libxl_internal.h
> @@ -1493,6 +1493,8 @@ _hidden char *
> libxl__domain_pvcontrol_read(libxl__gc *gc,
> 
>  /* from xl_device */
>  _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend
> backend);
> +_hidden char
> *libxl__device_disk_string_of_specification(libxl_disk_specification
> specification);
> +_hidden char *libxl__device_disk_string_of_transport(libxl_disk_transport
> transport);
>  _hidden char *libxl__device_disk_string_of_format(libxl_disk_format
> format);
>  _hidden const char *libxl__qemu_disk_format_string(libxl_disk_format
> format);
>  _hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk*);
> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
> index f3ceb38c9e..d634f304cd 100644
> --- a/tools/libs/light/libxl_types.idl
> +++ b/tools/libs/light/libxl_types.idl
> @@ -130,6 +130,18 @@ libxl_disk_backend = Enumeration("disk_backend",
> [
>      (1, "PHY"),
>      (2, "TAP"),
>      (3, "QDISK"),
> +    (4, "STANDALONE"), # Only relying on the Xenstore data
> +    ])
> +
> +libxl_disk_specification = Enumeration("disk_specification", [
> +    (0, "UNKNOWN"),
> +    (1, "XEN"),
> +    (2, "VIRTIO"),
> +    ])
> +
> +libxl_disk_transport = Enumeration("disk_transport", [
> +    (0, "UNKNOWN"),
> +    (1, "MMIO"),
>      ])
> 
>  libxl_nic_type = Enumeration("nic_type", [
> @@ -706,6 +718,12 @@ libxl_device_disk = Struct("device_disk", [
>      ("is_cdrom", integer),
>      ("direct_io_safe", bool),
>      ("discard_enable", libxl_defbool),
> +    ("specification", libxl_disk_specification),
> +    ("transport", libxl_disk_transport),
> +    # Note that virtio-mmio parameters (irq and base) are for internal use
> +    # by libxl and can't be modified.
> +    ("irq", uint32),
> +    ("base", uint64),
>      # Note that the COLO configuration settings should be considered unstable.
>      # They may change incompatibly in future versions of Xen.
>      ("colo_enable", libxl_defbool),
> diff --git a/tools/libs/light/libxl_types_internal.idl
> b/tools/libs/light/libxl_types_internal.idl
> index 3593e21dbb..8f71980aec 100644
> --- a/tools/libs/light/libxl_types_internal.idl
> +++ b/tools/libs/light/libxl_types_internal.idl
> @@ -32,6 +32,7 @@ libxl__device_kind = Enumeration("device_kind", [
>      (14, "PVCALLS"),
>      (15, "VSND"),
>      (16, "VINPUT"),
> +    (17, "VIRTIO_DISK"),
>      ])
> 
>  libxl__console_backend = Enumeration("console_backend", [
> diff --git a/tools/libs/light/libxl_utils.c b/tools/libs/light/libxl_utils.c
> index e5e6b2da96..e403bd9bcf 100644
> --- a/tools/libs/light/libxl_utils.c
> +++ b/tools/libs/light/libxl_utils.c
> @@ -297,6 +297,8 @@ int libxl_string_to_backend(libxl_ctx *ctx, char *s,
> libxl_disk_backend *backend
>          *backend = LIBXL_DISK_BACKEND_TAP;
>      } else if (!strcmp(s, "qdisk")) {
>          *backend = LIBXL_DISK_BACKEND_QDISK;
> +    } else if (!strcmp(s, "standalone")) {
> +        *backend = LIBXL_DISK_BACKEND_STANDALONE;
>      } else if (!strcmp(s, "tap")) {
>          p = strchr(s, ':');
>          if (!p) {
> diff --git a/tools/libs/util/libxlu_disk_l.c b/tools/libs/util/libxlu_disk_l.c
> index 32d4b74b58..0b59723b71 100644
> --- a/tools/libs/util/libxlu_disk_l.c
> +++ b/tools/libs/util/libxlu_disk_l.c
> @@ -549,8 +549,8 @@ static void yynoreturn yy_fatal_error ( const char*
> msg , yyscan_t yyscanner );
>  	yyg->yy_hold_char = *yy_cp; \
>  	*yy_cp = '\0'; \
>  	yyg->yy_c_buf_p = yy_cp;
> -#define YY_NUM_RULES 36
> -#define YY_END_OF_BUFFER 37
> +#define YY_NUM_RULES 37
> +#define YY_END_OF_BUFFER 38
>  /* This struct is not used in this scanner,
>     but its presence is necessary. */
>  struct yy_trans_info
> @@ -558,74 +558,77 @@ struct yy_trans_info
>  	flex_int32_t yy_verify;
>  	flex_int32_t yy_nxt;
>  	};
> -static const flex_int16_t yy_acclist[575] =
> +static const flex_int16_t yy_acclist[594] =
>      {   0,
> -       35,   35,   37,   33,   34,   36, 8193,   33,   34,   36,
> -    16385, 8193,   33,   36,16385,   33,   34,   36,   34,   36,
> -       33,   34,   36,   33,   34,   36,   33,   34,   36,   33,
> -       34,   36,   33,   34,   36,   33,   34,   36,   33,   34,
> -       36,   33,   34,   36,   33,   34,   36,   33,   34,   36,
> -       33,   34,   36,   33,   34,   36,   33,   34,   36,   33,
> -       34,   36,   33,   34,   36,   33,   34,   36,   35,   36,
> -       36,   33,   33, 8193,   33, 8193,   33,16385, 8193,   33,
> -     8193,   33,   33, 8224,   33,16416,   33,   33,   33,   33,
> -       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
> -
> -       33,   33,   33,   33,   33,   33,   33,   33,   33,   35,
> -     8193,   33, 8193,   33, 8193, 8224,   33, 8224,   33, 8224,
> -       23,   33,   33,   33,   33,   33,   33,   33,   33,   33,
> -       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
> -       33,   33,   33,   33,   33, 8224,   33, 8224,   33, 8224,
> -       23,   33,   33,   28, 8224,   33,16416,   33,   33,   15,
> -       33,   33,   33,   33,   33,   33,   33,   33,   33, 8217,
> -     8224,   33,16409,16416,   33,   33,   31, 8224,   33,16416,
> -       33, 8216, 8224,   33,16408,16416,   33,   33, 8219, 8224,
> -       33,16411,16416,   33,   33,   33,   33,   33,   28, 8224,
> -
> -       33,   28, 8224,   33,   28,   33,   28, 8224,   33,    3,
> -       33,   15,   33,   33,   33,   33,   33,   30, 8224,   33,
> -    16416,   33,   33,   33, 8217, 8224,   33, 8217, 8224,   33,
> -     8217,   33, 8217, 8224,   33,   33,   31, 8224,   33,   31,
> -     8224,   33,   31,   33,   31, 8224, 8216, 8224,   33, 8216,
> -     8224,   33, 8216,   33, 8216, 8224,   33, 8219, 8224,   33,
> -     8219, 8224,   33, 8219,   33, 8219, 8224,   33,   33,   10,
> -       33,   33,   28, 8224,   33,   28, 8224,   33,   28, 8224,
> -       28,   33,   28,   33,    3,   33,   33,   33,   33,   33,
> -       33,   33,   30, 8224,   33,   30, 8224,   33,   30,   33,
> -
> -       30, 8224,   33,   33,   29, 8224,   33,16416, 8217, 8224,
> -       33, 8217, 8224,   33, 8217, 8224, 8217,   33, 8217,   33,
> -       33,   31, 8224,   33,   31, 8224,   33,   31, 8224,   31,
> -       33,   31, 8216, 8224,   33, 8216, 8224,   33, 8216, 8224,
> -     8216,   33, 8216,   33, 8219, 8224,   33, 8219, 8224,   33,
> -     8219, 8224, 8219,   33, 8219,   33,   33,   10,   23,   10,
> -        7,   33,   33,   33,   33,   33,   33,   33,   13,   33,
> -       30, 8224,   33,   30, 8224,   33,   30, 8224,   30,   33,
> -       30,    2,   33,   29, 8224,   33,   29, 8224,   33,   29,
> -       33,   29, 8224,   16,   33,   33,   11,   33,   22,   10,
> -
> -       10,   23,    7,   23,    7,   33,    8,   33,   33,   33,
> -       33,    6,   33,   13,   33,    2,   23,    2,   33,   29,
> -     8224,   33,   29, 8224,   33,   29, 8224,   29,   33,   29,
> -       16,   33,   33,   11,   23,   11,   26, 8224,   33,16416,
> -       22,   23,   22,    7,    7,   23,   33,    8,   23,    8,
> -       33,   33,   33,   33,    6,   23,    6,    6,   23,    6,
> -       23,   33,    2,    2,   23,   33,   33,   11,   11,   23,
> -       26, 8224,   33,   26, 8224,   33,   26,   33,   26, 8224,
> -       22,   23,   33,    8,    8,   23,   33,   33,   17,   18,
> -        6,    6,   23,    6,    6,   33,   33,   14,   33,   26,
> -
> -     8224,   33,   26, 8224,   33,   26, 8224,   26,   33,   26,
> -       33,   33,   33,   17,   23,   17,   18,   23,   18,    6,
> -        6,   33,   33,   14,   33,   20,    9,   19,   17,   17,
> -       23,   18,   18,   23,    6,    5,    6,   33,   21,   20,
> -       23,   20,    9,   23,    9,   19,   23,   19,    4,    6,
> -        5,    6,   33,   21,   23,   21,   20,   20,   23,    9,
> -        9,   23,   19,   19,   23,    4,    6,   12,   33,   21,
> -       21,   23,   12,   33
> +       36,   36,   38,   34,   35,   37, 8193,   34,   35,   37,
> +    16385, 8193,   34,   37,16385,   34,   35,   37,   35,   37,
> +       34,   35,   37,   34,   35,   37,   34,   35,   37,   34,
> +       35,   37,   34,   35,   37,   34,   35,   37,   34,   35,
> +       37,   34,   35,   37,   34,   35,   37,   34,   35,   37,
> +       34,   35,   37,   34,   35,   37,   34,   35,   37,   34,
> +       35,   37,   34,   35,   37,   34,   35,   37,   36,   37,
> +       37,   34,   34, 8193,   34, 8193,   34,16385, 8193,   34,
> +     8193,   34,   34, 8225,   34,16417,   34,   34,   34,   34,
> +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
> +
> +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
> +       36, 8193,   34, 8193,   34, 8193, 8225,   34, 8225,   34,
> +     8225,   24,   34,   34,   34,   34,   34,   34,   34,   34,
> +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
> +       34,   34,   34,   34,   34,   34,   34, 8225,   34, 8225,
> +       34, 8225,   24,   34,   34,   29, 8225,   34,16417,   34,
> +       34,   16,   34,   34,   34,   34,   34,   34,   34,   34,
> +       34, 8218, 8225,   34,16410,16417,   34,   34,   32, 8225,
> +       34,16417,   34, 8217, 8225,   34,16409,16417,   34,   34,
> +       34, 8220, 8225,   34,16412,16417,   34,   34,   34,   34,
> +
> +       34,   29, 8225,   34,   29, 8225,   34,   29,   34,   29,
> +     8225,   34,    3,   34,   16,   34,   34,   34,   34,   34,
> +       31, 8225,   34,16417,   34,   34,   34, 8218, 8225,   34,
> +     8218, 8225,   34, 8218,   34, 8218, 8225,   34,   34,   32,
> +     8225,   34,   32, 8225,   34,   32,   34,   32, 8225, 8217,
> +     8225,   34, 8217, 8225,   34, 8217,   34, 8217, 8225,   34,
> +       34, 8220, 8225,   34, 8220, 8225,   34, 8220,   34, 8220,
> +     8225,   34,   34,   11,   34,   34,   29, 8225,   34,   29,
> +     8225,   34,   29, 8225,   29,   34,   29,   34,    3,   34,
> +       34,   34,   34,   34,   34,   34,   31, 8225,   34,   31,
> +
> +     8225,   34,   31,   34,   31, 8225,   34,   34,   30, 8225,
> +       34,16417, 8218, 8225,   34, 8218, 8225,   34, 8218, 8225,
> +     8218,   34, 8218,   34,   34,   32, 8225,   34,   32, 8225,
> +       34,   32, 8225,   32,   34,   32, 8217, 8225,   34, 8217,
> +     8225,   34, 8217, 8225, 8217,   34, 8217,   34,   34, 8220,
> +     8225,   34, 8220, 8225,   34, 8220, 8225, 8220,   34, 8220,
> +       34,   34,   11,   24,   11,    7,   34,   34,   34,   34,
> +       34,   34,   34,   14,   34,   31, 8225,   34,   31, 8225,
> +       34,   31, 8225,   31,   34,   31,    2,   34,   30, 8225,
> +       34,   30, 8225,   34,   30,   34,   30, 8225,   17,   34,
> +
> +       34,   12,   34,   34,   23,   11,   11,   24,    7,   24,
> +        7,   34,    8,   34,   34,   34,   34,    6,   34,   14,
> +       34,    2,   24,    2,   34,   30, 8225,   34,   30, 8225,
> +       34,   30, 8225,   30,   34,   30,   17,   34,   34,   12,
> +       24,   12,   34,   27, 8225,   34,16417,   23,   24,   23,
> +        7,    7,   24,   34,    8,   24,    8,   34,   34,   34,
> +       34,    6,   24,    6,    6,   24,    6,   24,   34,    2,
> +        2,   24,   34,   34,   12,   12,   24,   34,   27, 8225,
> +       34,   27, 8225,   34,   27,   34,   27, 8225,   23,   24,
> +       34,    8,    8,   24,   34,   34,   18,   19,    6,    6,
> +
> +       24,    6,    6,   34,   34,   15,   34,   34,   27, 8225,
> +       34,   27, 8225,   34,   27, 8225,   27,   34,   27,   34,
> +       34,   34,   18,   24,   18,   19,   24,   19,    6,    6,
> +       34,   34,   15,   34,   34,   21,    9,   20,   18,   18,
> +       24,   19,   19,   24,    6,    5,    6,   34,   22,   34,
> +       21,   24,   21,    9,   24,    9,   20,   24,   20,    4,
> +        6,    5,    6,   34,   22,   24,   22,   34,   21,   21,
> +       24,    9,    9,   24,   20,   20,   24,    4,    6,   13,
> +       34,   22,   22,   24,   10,   13,   34,   10,   24,   10,
> +       10,   10,   24
> +
>      } ;
> 
> -static const flex_int16_t yy_accept[356] =
> +static const flex_int16_t yy_accept[373] =
>      {   0,
>          1,    1,    1,    2,    3,    4,    7,   12,   16,   19,
>         21,   24,   27,   30,   33,   36,   39,   42,   45,   48,
> @@ -633,39 +636,41 @@ static const flex_int16_t yy_accept[356] =
>         74,   76,   79,   81,   82,   83,   84,   87,   87,   88,
>         89,   90,   91,   92,   93,   94,   95,   96,   97,   98,
>         99,  100,  101,  102,  103,  104,  105,  106,  107,  108,
> -      109,  110,  111,  113,  115,  116,  118,  120,  121,  122,
> +      109,  110,  111,  112,  114,  116,  117,  119,  121,  122,
>        123,  124,  125,  126,  127,  128,  129,  130,  131,  132,
>        133,  134,  135,  136,  137,  138,  139,  140,  141,  142,
> -      143,  144,  145,  146,  148,  150,  151,  152,  153,  154,
> -
> -      158,  159,  160,  162,  163,  164,  165,  166,  167,  168,
> -      169,  170,  175,  176,  177,  181,  182,  187,  188,  189,
> -      194,  195,  196,  197,  198,  199,  202,  205,  207,  209,
> -      210,  212,  214,  215,  216,  217,  218,  222,  223,  224,
> -      225,  228,  231,  233,  235,  236,  237,  240,  243,  245,
> -      247,  250,  253,  255,  257,  258,  261,  264,  266,  268,
> -      269,  270,  271,  272,  273,  276,  279,  281,  283,  284,
> -      285,  287,  288,  289,  290,  291,  292,  293,  296,  299,
> -      301,  303,  304,  305,  309,  312,  315,  317,  319,  320,
> -      321,  322,  325,  328,  330,  332,  333,  336,  339,  341,
> -
> -      343,  344,  345,  348,  351,  353,  355,  356,  357,  358,
> -      360,  361,  362,  363,  364,  365,  366,  367,  368,  369,
> -      371,  374,  377,  379,  381,  382,  383,  384,  387,  390,
> -      392,  394,  396,  397,  398,  399,  400,  401,  403,  405,
> -      406,  407,  408,  409,  410,  411,  412,  413,  414,  416,
> -      418,  419,  420,  423,  426,  428,  430,  431,  433,  434,
> -      436,  437,  441,  443,  444,  445,  447,  448,  450,  451,
> -      452,  453,  454,  455,  457,  458,  460,  462,  463,  464,
> -      466,  467,  468,  469,  471,  474,  477,  479,  481,  483,
> -      484,  485,  487,  488,  489,  490,  491,  492,  494,  495,
> -
> -      496,  497,  498,  500,  503,  506,  508,  510,  511,  512,
> -      513,  514,  516,  517,  519,  520,  521,  522,  523,  524,
> -      526,  527,  528,  529,  530,  532,  533,  535,  536,  538,
> -      539,  540,  542,  543,  545,  546,  548,  549,  551,  553,
> -      554,  556,  557,  558,  560,  561,  563,  564,  566,  568,
> -      570,  571,  573,  575,  575
> +      143,  144,  145,  146,  147,  148,  150,  152,  153,  154,
> +
> +      155,  156,  160,  161,  162,  164,  165,  166,  167,  168,
> +      169,  170,  171,  172,  177,  178,  179,  183,  184,  189,
> +      190,  191,  192,  197,  198,  199,  200,  201,  202,  205,
> +      208,  210,  212,  213,  215,  217,  218,  219,  220,  221,
> +      225,  226,  227,  228,  231,  234,  236,  238,  239,  240,
> +      243,  246,  248,  250,  253,  256,  258,  260,  261,  262,
> +      265,  268,  270,  272,  273,  274,  275,  276,  277,  280,
> +      283,  285,  287,  288,  289,  291,  292,  293,  294,  295,
> +      296,  297,  300,  303,  305,  307,  308,  309,  313,  316,
> +      319,  321,  323,  324,  325,  326,  329,  332,  334,  336,
> +
> +      337,  340,  343,  345,  347,  348,  349,  350,  353,  356,
> +      358,  360,  361,  362,  363,  365,  366,  367,  368,  369,
> +      370,  371,  372,  373,  374,  376,  379,  382,  384,  386,
> +      387,  388,  389,  392,  395,  397,  399,  401,  402,  403,
> +      404,  405,  406,  407,  409,  411,  412,  413,  414,  415,
> +      416,  417,  418,  419,  420,  422,  424,  425,  426,  429,
> +      432,  434,  436,  437,  439,  440,  442,  443,  444,  448,
> +      450,  451,  452,  454,  455,  457,  458,  459,  460,  461,
> +      462,  464,  465,  467,  469,  470,  471,  473,  474,  475,
> +      476,  478,  479,  482,  485,  487,  489,  491,  492,  493,
> +
> +      495,  496,  497,  498,  499,  500,  502,  503,  504,  505,
> +      506,  508,  509,  512,  515,  517,  519,  520,  521,  522,
> +      523,  525,  526,  528,  529,  530,  531,  532,  533,  535,
> +      536,  537,  538,  539,  540,  542,  543,  545,  546,  548,
> +      549,  550,  551,  553,  554,  556,  557,  559,  560,  562,
> +      564,  565,  567,  568,  569,  570,  572,  573,  575,  576,
> +      578,  580,  582,  583,  585,  586,  588,  590,  591,  592,
> +      594,  594
>      } ;
> 
>  static const YY_CHAR yy_ec[256] =
> @@ -708,216 +713,224 @@ static const YY_CHAR yy_meta[35] =
>          1,    1,    1,    1
>      } ;
> 
> -static const flex_int16_t yy_base[424] =
> +static const flex_int16_t yy_base[443] =
>      {   0,
> -        0,    0,  901,  900,  902,  897,   33,   36,  905,  905,
> -       45,   63,   31,   42,   51,   52,  890,   33,   65,   67,
> -       69,   70,  889,   71,  888,   75,    0,  905,  893,  905,
> -       91,   94,    0,    0,  103,  886,  112,    0,   89,   98,
> -      113,   92,  114,   99,  100,   48,  121,  116,  119,   74,
> -      124,  129,  123,  135,  132,  133,  137,  134,  138,  139,
> -      141,    0,  155,    0,    0,  164,    0,    0,  849,  142,
> -      152,  164,  140,  161,  165,  166,  167,  168,  169,  173,
> -      174,  178,  176,  180,  184,  208,  189,  183,  192,  195,
> -      215,  191,  193,  223,    0,    0,  905,  208,  204,  236,
> -
> -      219,  209,  238,  196,  237,  831,  242,  815,  241,  224,
> -      243,  261,  244,  259,  277,  266,  286,  250,  288,  298,
> -      249,  283,  274,  282,  294,  308,    0,  310,    0,  295,
> -      305,  905,  308,  306,  313,  314,  342,  319,  316,  320,
> -      331,    0,  349,    0,  342,  344,  356,    0,  358,    0,
> -      365,    0,  367,    0,  354,  375,    0,  377,    0,  363,
> -      356,  809,  327,  322,  384,    0,    0,    0,    0,  379,
> -      905,  382,  384,  386,  390,  372,  392,  403,    0,  410,
> -        0,  407,  413,  423,  426,    0,    0,    0,    0,  409,
> -      424,  435,    0,    0,    0,    0,  437,    0,    0,    0,
> -
> -        0,  433,  444,    0,    0,    0,    0,  391,  440,  781,
> -      905,  769,  439,  445,  444,  447,  449,  454,  453,  399,
> -      464,    0,    0,    0,    0,  757,  465,  476,    0,  478,
> -        0,  479,  476,  753,  462,  490,  749,  905,  745,  905,
> -      483,  737,  424,  485,  487,  490,  500,  493,  905,  729,
> -      905,  502,  518,    0,    0,    0,    0,  905,  498,  721,
> -      905,  527,  713,    0,  705,  905,  495,  697,  905,  365,
> -      521,  528,  530,  685,  905,  534,  540,  540,  657,  905,
> -      537,  542,  650,  905,  553,    0,  557,    0,    0,  551,
> -      641,  905,  558,  557,  633,  614,  613,  905,  547,  555,
> -
> -      563,  565,  569,  584,    0,    0,    0,    0,  583,  570,
> -      585,  612,  905,  601,  905,  522,  580,  589,  594,  905,
> -      600,  585,  563,  520,  905,  514,  905,  586,  486,  597,
> -      480,  441,  905,  416,  905,  345,  905,  334,  905,  601,
> -      254,  905,  242,  905,  200,  905,  151,  905,  905,  607,
> -       86,  905,  905,  905,  620,  624,  627,  631,  635,  639,
> -      643,  647,  651,  655,  659,  663,  667,  671,  675,  679,
> -      683,  687,  691,  695,  699,  703,  707,  711,  715,  719,
> -      723,  727,  731,  735,  739,  743,  747,  751,  755,  759,
> -      763,  767,  771,  775,  779,  783,  787,  791,  795,  799,
> -
> -      803,  807,  811,  815,  819,  823,  827,  831,  835,  839,
> -      843,  847,  851,  855,  859,  863,  867,  871,  875,  879,
> -      883,  887,  891
> +        0,    0,  936,  935,  937,  932,   33,   36,  940,  940,
> +       45,   63,   31,   42,   51,   52,  925,   33,   65,   67,
> +       69,   70,  924,   71,  923,   75,    0,  940,  928,  940,
> +       91,   95,    0,    0,  104,  921,  113,    0,   91,   99,
> +      114,   92,  115,   80,  100,   48,  119,  121,  122,   74,
> +      123,  128,  131,  129,  125,  133,  135,  136,  137,  143,
> +      138,  145,    0,  157,    0,    0,  168,    0,    0,  926,
> +      140,  146,  165,  159,  152,  164,  155,  168,  171,  176,
> +      177,  170,  180,  175,  184,  188,  212,  191,  185,  192,
> +      193,  194,  219,  212,  199,  230,    0,    0,  940,  195,
> +
> +      200,  239,  235,  197,  246,  225,  226,  919,  244,  918,
> +      243,  236,  245,  266,  248,  264,  282,  271,  291,  248,
> +      270,  254,  300,  279,  296,  302,  288,  303,  311,    0,
> +      315,    0,  311,  318,  940,  313,  319,  208,  313,  344,
> +      321,  331,  325,  333,    0,  352,    0,  345,  347,  359,
> +        0,  361,    0,  368,    0,  370,    0,  322,  366,  379,
> +        0,  381,    0,  359,  357,  923,  382,  384,  392,    0,
> +        0,    0,    0,  387,  940,  386,  390,  392,  329,  401,
> +      397,  409,    0,  417,    0,  399,  412,  426,  429,    0,
> +        0,    0,    0,  412,  427,  438,    0,    0,    0,    0,
> +
> +      440,    0,    0,    0,    0,  436,  405,  447,    0,    0,
> +        0,    0,  438,  443,  922,  940,  921,  442,  450,  449,
> +      452,  454,  459,  458,  453,  469,    0,    0,    0,    0,
> +      920,  470,  481,    0,  483,    0,  484,  481,  919,  368,
> +      467,  495,  918,  940,  917,  940,  488,  916,  479,  490,
> +      492,  495,  505,  498,  940,  915,  940,  507,  523,    0,
> +        0,    0,    0,  940,  503,  864,  940,  846,  532,  836,
> +        0,  824,  940,  516,  796,  940,  513,  530,  536,  538,
> +      784,  940,  542,  535,  547,  772,  940,  549,  551,  768,
> +      940,  502,  562,    0,  564,    0,    0,  562,  764,  940,
> +
> +      544,  557,  760,  752,  744,  940,  552,  568,  571,  568,
> +      581,  577,  588,    0,    0,    0,    0,  589,  580,  591,
> +      736,  940,  728,  940,  601,  602,  597,  599,  940,  603,
> +      720,  712,  700,  672,  940,  665,  940,  610,  656,  603,
> +      648,  607,  629,  940,  627,  940,  625,  940,  624,  940,
> +      607,  574,  940,  614,  572,  940,  491,  940,  433,  940,
> +      940,  622,  389,  940,  303,  940,  261,  940,  204,  940,
> +      940,  635,  639,  642,  646,  650,  654,  658,  662,  666,
> +      670,  674,  678,  682,  686,  690,  694,  698,  702,  706,
> +      710,  714,  718,  722,  726,  730,  734,  738,  742,  746,
> +
> +      750,  754,  758,  762,  766,  770,  774,  778,  782,  786,
> +      790,  794,  798,  802,  806,  810,  814,  818,  822,  826,
> +      830,  834,  838,  842,  846,  850,  854,  858,  862,  866,
> +      870,  874,  878,  882,  886,  890,  894,  898,  902,  906,
> +      910,  914
>      } ;
> 
> -static const flex_int16_t yy_def[424] =
> +static const flex_int16_t yy_def[443] =
>      {   0,
> -      354,    1,  355,  355,  354,  356,  357,  357,  354,  354,
> -      358,  358,   12,   12,   12,   12,   12,   12,   12,   12,
> -       12,   12,   12,   12,   12,   12,  359,  354,  356,  354,
> -      360,  357,  361,  361,  362,   12,  356,  363,   12,   12,
> -       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
> +      371,    1,  372,  372,  371,  373,  374,  374,  371,  371,
> +      375,  375,   12,   12,   12,   12,   12,   12,   12,   12,
> +       12,   12,   12,   12,   12,   12,  376,  371,  373,  371,
> +      377,  374,  378,  378,  379,   12,  373,  380,   12,   12,
>         12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
> -       12,  359,  360,  361,  361,  364,  365,  365,  354,   12,
>         12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
> -       12,   12,   12,   12,   12,  362,   12,   12,   12,   12,
> -       12,   12,   12,  364,  365,  365,  354,   12,   12,  366,
> -
> +       12,   12,  376,  377,  378,  378,  381,  382,  382,  371,
>         12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
> -       12,  367,   86,   86,  368,   12,  369,   12,   12,  370,
> -       12,   12,   12,   12,   12,  371,  372,  366,  372,   12,
> -       12,  354,   86,   12,   12,   12,  373,   12,   12,   12,
> -      374,  375,  367,  375,   86,   86,  376,  377,  368,  377,
> -      378,  379,  369,  379,   12,  380,  381,  370,  381,   12,
> -       12,  382,   12,   12,  371,  372,  372,  383,  383,   12,
> -      354,   86,   86,   86,   12,   12,   12,  384,  385,  373,
> -      385,   12,   12,  386,  374,  375,  375,  387,  387,   86,
> -       86,  376,  377,  377,  388,  388,  378,  379,  379,  389,
> -
> -      389,   12,  380,  381,  381,  390,  390,   12,   12,  391,
> -      354,  392,   86,   12,   86,   86,   86,   12,   86,   12,
> -      384,  385,  385,  393,  393,  394,   86,  395,  396,  386,
> -      396,   86,   86,  397,   12,  398,  391,  354,  399,  354,
> -       86,  400,   12,   86,   86,   86,  401,   86,  354,  402,
> -      354,   86,  395,  396,  396,  403,  403,  354,   86,  404,
> -      354,  405,  406,  406,  399,  354,   86,  407,  354,   12,
> -       86,   86,   86,  408,  354,  408,  408,   86,  402,  354,
> -       86,   86,  404,  354,  409,  410,  405,  410,  406,   86,
> -      407,  354,   12,   86,  411,  412,  408,  354,  408,  408,
> -
> -       86,   86,   86,  409,  410,  410,  413,  413,   86,   12,
> -       86,  414,  354,  415,  354,  408,  408,   86,   86,  354,
> -      416,  417,  418,  414,  354,  415,  354,  408,  408,   86,
> -      419,  420,  354,  421,  354,  422,  354,  408,  354,   86,
> -      423,  354,  420,  354,  421,  354,  422,  354,  354,   86,
> -      423,  354,  354,    0,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354
> +       12,   12,   12,   12,   12,   12,  379,   12,   12,   12,
> +       12,   12,   12,   12,   12,  381,  382,  382,  371,   12,
> +
> +       12,  383,   12,   12,   12,   12,   12,   12,   12,   12,
> +       12,   12,   12,  384,   87,   87,  385,   12,  386,   12,
> +       12,   12,  387,   12,   12,   12,   12,   12,  388,  389,
> +      383,  389,   12,   12,  371,   87,   12,   12,   12,  390,
> +       12,   12,   12,  391,  392,  384,  392,   87,   87,  393,
> +      394,  385,  394,  395,  396,  386,  396,   12,   12,  397,
> +      398,  387,  398,   12,   12,  399,   12,   12,  388,  389,
> +      389,  400,  400,   12,  371,   87,   87,   87,   12,   12,
> +       12,  401,  402,  390,  402,   12,   12,  403,  391,  392,
> +      392,  404,  404,   87,   87,  393,  394,  394,  405,  405,
> +
> +      395,  396,  396,  406,  406,   12,   12,  397,  398,  398,
> +      407,  407,   12,   12,  408,  371,  409,   87,   12,   87,
> +       87,   87,   12,   87,   12,  401,  402,  402,  410,  410,
> +      411,   87,  412,  413,  403,  413,   87,   87,  414,   12,
> +       12,  415,  408,  371,  416,  371,   87,  417,   12,   87,
> +       87,   87,  418,   87,  371,  419,  371,   87,  412,  413,
> +      413,  420,  420,  371,   87,  421,  371,   12,  422,  423,
> +      423,  416,  371,   87,  424,  371,   12,   87,   87,   87,
> +      425,  371,  425,  425,   87,  419,  371,   87,   87,  421,
> +      371,   12,  426,  427,  422,  427,  423,   87,  424,  371,
> +
> +       12,   87,  428,  429,  425,  371,  425,  425,   87,   87,
> +       87,   12,  426,  427,  427,  430,  430,   87,   12,   87,
> +      431,  371,  432,  371,  425,  425,   87,   87,  371,   12,
> +      433,  434,  435,  431,  371,  432,  371,  425,  425,   87,
> +      436,   12,  437,  371,  438,  371,  439,  371,  425,  371,
> +       87,  440,  371,   12,  437,  371,  438,  371,  439,  371,
> +      371,   87,  440,  371,  441,  371,  442,  371,  442,  371,
> +        0,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371
>      } ;
> 
> -static const flex_int16_t yy_nxt[940] =
> +static const flex_int16_t yy_nxt[975] =
>      {   0,
>          6,    7,    8,    9,    6,    6,    6,    6,   10,   11,
>         12,   13,   14,   15,   16,   17,   18,   19,   17,   17,
>         17,   17,   20,   17,   21,   22,   23,   24,   25,   17,
>         26,   17,   17,   17,   32,   32,   33,   32,   32,   33,
>         36,   34,   36,   42,   34,   29,   29,   29,   30,   35,
> -       50,   36,   37,   38,   43,   44,   39,   36,   79,   45,
> +       50,   36,   37,   38,   43,   44,   39,   36,   80,   45,
>         36,   36,   40,   29,   29,   29,   30,   35,   46,   48,
>         37,   38,   41,   47,   36,   49,   36,   53,   36,   36,
> -       36,   56,   58,   36,   36,   55,   82,   60,   51,  342,
> -       54,   61,   52,   29,   64,   32,   32,   33,   36,   65,
> -
> -       70,   36,   34,   29,   29,   29,   30,   36,   36,   36,
> -       29,   38,   66,   66,   66,   67,   66,   71,   74,   66,
> -       68,   72,   36,   36,   73,   36,   77,   78,   36,   76,
> -       36,   53,   36,   36,   75,   85,   80,   83,   36,   86,
> -       84,   36,   36,   36,   36,   81,   36,   36,   36,   36,
> -       36,   36,   93,   89,  337,   98,   88,   29,   64,  101,
> -       90,   36,   91,   65,   92,   87,   29,   95,   89,   99,
> -       36,  100,   96,   36,   36,   36,   36,   36,   36,  106,
> -      105,   85,   36,   36,  102,   36,  107,   36,  103,   36,
> -      109,  112,   36,   36,  104,  108,  115,  110,   36,  117,
> -
> -       36,   36,   36,  335,   36,   36,  122,  111,   29,   29,
> -       29,   30,  118,   36,  116,   29,   38,   36,   36,  113,
> -      114,  119,  120,  123,   36,   29,   95,  121,   36,  134,
> -      131,   96,  130,   36,  125,  124,  126,  126,   66,  127,
> -      126,  132,  133,  126,  129,  333,   36,   36,  135,  137,
> -       36,   36,   36,  140,  139,   35,   35,  352,   36,   36,
> -       85,  141,  141,   66,  142,  141,  160,  145,  141,  144,
> -       35,   35,   89,  117,  155,   36,  146,  147,  147,   66,
> -      148,  147,  162,   36,  147,  150,  151,  151,   66,  152,
> -      151,   36,   36,  151,  154,  120,  161,   36,  156,  156,
> -
> -       66,  157,  156,   36,   36,  156,  159,  164,  171,  163,
> -       29,  166,   29,  168,   36,   36,  167,  170,  169,   35,
> -       35,  172,   36,   36,  173,   36,  213,  184,   36,   36,
> -      175,   36,  174,   29,  186,  212,   36,  349,  183,  187,
> -      177,  176,  178,  178,   66,  179,  178,  182,  348,  178,
> -      181,   29,  188,   35,   35,   35,   35,  189,   29,  193,
> -       29,  195,  190,   36,  194,   36,  196,   29,  198,   29,
> -      200,  191,   36,  199,   36,  201,  219,   29,  204,   29,
> -      206,   36,  202,  205,  209,  207,   29,  166,   36,  293,
> -      208,  214,  167,   35,   35,   35,   35,   35,   35,   36,
> -
> -       36,   36,  249,  218,  220,   29,  222,  216,   36,  217,
> -      235,  223,   29,  224,  215,  226,   36,  227,  225,  346,
> -       35,   35,   36,  228,  228,   66,  229,  228,   29,  186,
> -      228,  231,  232,   36,  187,  233,   35,   29,  193,   29,
> -      198,  234,   36,  194,  344,  199,   29,  204,  236,   36,
> -       35,  241,  205,  242,   36,   35,   35,  270,   35,   35,
> -       35,   35,  247,   36,   35,   35,   29,  222,  244,  262,
> -      248,   36,  223,  243,  245,  246,   35,  252,   29,  254,
> -       29,  256,  258,  342,  255,  259,  257,   35,   35,  339,
> -       35,   35,   69,  264,   35,   35,   35,   35,   35,   35,
> -
> -      267,   35,   35,  275,   35,   35,   35,   35,  271,   35,
> -       35,  276,  277,   35,   35,  272,  278,  315,  273,  281,
> -       29,  254,  290,  313,  282,  275,  255,  285,  285,   66,
> -      286,  285,   35,   35,  285,  288,  295,  298,  296,   35,
> -       35,   35,   35,  298,  301,  328,  299,  294,   35,   35,
> -      275,   35,   35,   35,  303,   29,  305,  300,  275,   29,
> -      307,  306,   35,   35,  302,  308,  337,   36,   35,   35,
> -      309,  310,  320,  316,   35,   35,   35,   35,  322,   36,
> -       35,   35,  317,  275,  319,  311,   29,  305,  335,  275,
> -      318,  321,  306,  323,   35,   35,   35,   35,  330,  329,
> -
> -       35,   35,  331,  333,  327,   35,   35,  338,   35,   35,
> -      353,  340,   35,   35,  350,  325,  275,  315,   35,   35,
> -       27,   27,   27,   27,   29,   29,   29,   31,   31,   31,
> -       31,   36,   36,   36,   36,   62,  313,   62,   62,   63,
> -       63,   63,   63,   65,  269,   65,   65,   35,   35,   35,
> -       35,   69,   69,  261,   69,   94,   94,   94,   94,   96,
> -      251,   96,   96,  128,  128,  128,  128,  143,  143,  143,
> -      143,  149,  149,  149,  149,  153,  153,  153,  153,  158,
> -      158,  158,  158,  165,  165,  165,  165,  167,  298,  167,
> -      167,  180,  180,  180,  180,  185,  185,  185,  185,  187,
> -
> -      292,  187,  187,  192,  192,  192,  192,  194,  240,  194,
> -      194,  197,  197,  197,  197,  199,  289,  199,  199,  203,
> -      203,  203,  203,  205,  284,  205,  205,  210,  210,  210,
> -      210,  169,  280,  169,  169,  221,  221,  221,  221,  223,
> -      269,  223,  223,  230,  230,  230,  230,  189,  266,  189,
> -      189,  196,  211,  196,  196,  201,  261,  201,  201,  207,
> -      251,  207,  207,  237,  237,  237,  237,  239,  239,  239,
> -      239,  225,  240,  225,  225,  250,  250,  250,  250,  253,
> -      253,  253,  253,  255,  238,  255,  255,  260,  260,  260,
> -      260,  263,  263,  263,  263,  265,  265,  265,  265,  268,
> -
> -      268,  268,  268,  274,  274,  274,  274,  279,  279,  279,
> -      279,  257,  211,  257,  257,  283,  283,  283,  283,  287,
> -      287,  287,  287,  264,  138,  264,  264,  291,  291,  291,
> -      291,  297,  297,  297,  297,  304,  304,  304,  304,  306,
> -      136,  306,  306,  312,  312,  312,  312,  314,  314,  314,
> -      314,  308,   97,  308,  308,  324,  324,  324,  324,  326,
> -      326,  326,  326,  332,  332,  332,  332,  334,  334,  334,
> -      334,  336,  336,  336,  336,  341,  341,  341,  341,  343,
> -      343,  343,  343,  345,  345,  345,  345,  347,  347,  347,
> -      347,  351,  351,  351,  351,   36,   30,   59,   57,   36,
> -
> -       30,  354,   28,   28,    5,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354
> +       36,   56,   58,   36,   36,   55,   83,   61,   51,   36,
> +       54,   62,   52,   29,   65,   59,   32,   32,   33,   66,
> +
> +       36,   36,   71,   34,   29,   29,   29,   30,   36,   36,
> +       77,   29,   38,   67,   67,   67,   68,   67,   75,   72,
> +       67,   69,   73,   36,   36,   74,   78,   79,   36,   53,
> +       36,   36,   36,   87,   36,   76,   84,   36,   36,   85,
> +       36,   81,   36,   86,   36,   36,   36,   36,   82,   36,
> +       92,   95,   36,  100,   36,   36,   89,   90,   88,   29,
> +       65,   36,   91,  101,   36,   66,   90,   93,   36,   94,
> +       29,   97,  102,   36,   36,  104,   98,   36,  103,   36,
> +       36,  107,  108,  106,   36,   36,   36,  105,   86,   36,
> +      109,  110,  111,   36,   36,  114,  112,   36,  117,  119,
> +
> +       36,   36,   36,   36,   36,  121,   36,  368,   36,   36,
> +      120,  113,   29,   29,   29,   30,  118,   36,  134,   29,
> +       38,   36,  127,  115,  116,  122,  123,  125,   36,  126,
> +      128,  124,   29,   97,   36,   36,  180,  138,   98,  129,
> +      129,   67,  130,  129,   36,   36,  129,  132,  133,  135,
> +      136,  140,   36,   36,   36,   36,  142,   36,  137,   35,
> +       35,  123,   86,   36,  370,  143,  144,  144,   67,  145,
> +      144,  148,  158,  144,  147,   35,   35,   90,  119,   36,
> +       36,  149,  150,  150,   67,  151,  150,  159,   36,  150,
> +      153,  154,  154,   67,  155,  154,  164,   36,  154,  157,
> +
> +      160,  160,   67,  161,  160,   36,  368,  160,  163,  165,
> +      166,   36,   36,   29,  170,  167,  168,   29,  172,  171,
> +       36,  175,   36,  173,   35,   35,  176,   36,   36,  177,
> +       36,   36,  188,  174,   36,   29,  190,  178,   36,  181,
> +       36,  191,  223,  179,  182,  182,   67,  183,  182,  186,
> +      206,  182,  185,  187,   29,  192,   35,   35,   35,   35,
> +      193,   29,  197,   29,  199,  194,   36,  198,   36,  200,
> +       29,  202,   29,  204,  195,   36,  203,   36,  205,  268,
> +      207,   29,  209,   29,  211,  214,  213,  210,  218,  212,
> +      217,   36,  353,   36,   29,  170,   36,   35,   35,  219,
> +
> +      171,   35,   35,   35,   35,  224,   36,  231,   36,  225,
> +       36,   29,  227,  221,   36,  222,  232,  228,  220,   29,
> +      229,   36,  240,   35,   35,  230,  233,  233,   67,  234,
> +      233,   29,  190,  233,  236,  237,  348,  191,  238,   35,
> +       29,  197,   29,  202,  239,   36,  198,   36,  203,   29,
> +      209,  242,   36,   35,  247,  210,  255,  241,  248,   36,
> +       35,   35,   36,   35,   35,   35,   35,  253,   36,   35,
> +       35,   29,  227,  250,  269,  254,   36,  228,  249,  251,
> +      252,   35,  258,   29,  260,   29,  262,  264,   36,  261,
> +      265,  263,   35,   35,  346,   35,   35,   70,  271,   35,
> +
> +       35,   35,   35,   35,   35,  274,   35,   35,  282,   35,
> +       35,   36,  277,  278,   35,   35,  283,  284,   35,   35,
> +      279,  285,   36,  280,  288,   29,  260,   35,   35,  289,
> +      312,  261,  293,  293,   67,  294,  293,  301,  306,  293,
> +      296,   35,   35,  298,  303,  306,  304,   35,   35,   35,
> +       35,  309,  308,   36,  307,  282,  302,  319,   35,   35,
> +       35,   35,   35,  311,   29,  314,   29,  316,   35,   35,
> +      315,  282,  317,   35,   35,  344,  310,  364,  325,   35,
> +       35,  318,   35,   35,  329,  320,   36,  328,  332,   36,
> +       29,  314,   35,   35,  330,  326,  315,  331,  327,  333,
> +
> +       35,   35,   35,   35,  282,  282,  340,  341,   35,   35,
> +       35,   35,   36,  282,   35,   35,   36,  351,   35,   35,
> +      362,  339,  365,   36,  338,  366,  342,  361,  360,  354,
> +      358,  349,  356,   35,   35,   27,   27,   27,   27,   29,
> +       29,   29,   31,   31,   31,   31,   36,   36,   36,   36,
> +       63,  353,   63,   63,   64,   64,   64,   64,   66,  350,
> +       66,   66,   35,   35,   35,   35,   70,   70,  324,   70,
> +       96,   96,   96,   96,   98,  322,   98,   98,  131,  131,
> +      131,  131,  146,  146,  146,  146,  152,  152,  152,  152,
> +      156,  156,  156,  156,  162,  162,  162,  162,  169,  169,
> +
> +      169,  169,  171,  348,  171,  171,  184,  184,  184,  184,
> +      189,  189,  189,  189,  191,  346,  191,  191,  196,  196,
> +      196,  196,  198,  344,  198,  198,  201,  201,  201,  201,
> +      203,  337,  203,  203,  208,  208,  208,  208,  210,  335,
> +      210,  210,  215,  215,  215,  215,  173,  282,  173,  173,
> +      226,  226,  226,  226,  228,  324,  228,  228,  235,  235,
> +      235,  235,  193,  322,  193,  193,  200,  276,  200,  200,
> +      205,  267,  205,  205,  212,  257,  212,  212,  243,  243,
> +      243,  243,  245,  245,  245,  245,  230,  306,  230,  230,
> +      256,  256,  256,  256,  259,  259,  259,  259,  261,  300,
> +
> +      261,  261,  266,  266,  266,  266,  270,  270,  270,  270,
> +      272,  272,  272,  272,  275,  275,  275,  275,  281,  281,
> +      281,  281,  286,  286,  286,  286,  263,  246,  263,  263,
> +      290,  290,  290,  290,  295,  295,  295,  295,  271,  297,
> +      271,  271,  299,  299,  299,  299,  305,  305,  305,  305,
> +      313,  313,  313,  313,  315,  292,  315,  315,  321,  321,
> +      321,  321,  323,  323,  323,  323,  317,  291,  317,  317,
> +      334,  334,  334,  334,  336,  336,  336,  336,  343,  343,
> +      343,  343,  345,  345,  345,  345,  347,  347,  347,  347,
> +      352,  352,  352,  352,  355,  355,  355,  355,  357,  357,
> +
> +      357,  357,  359,  359,  359,  359,  363,  363,  363,  363,
> +      367,  367,  367,  367,  369,  369,  369,  369,  287,  276,
> +      273,  216,  267,  257,  246,  244,  216,  141,  139,   99,
> +       36,   30,   60,   57,   36,   30,  371,   28,   28,    5,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371
>      } ;
> 
> -static const flex_int16_t yy_chk[940] =
> +static const flex_int16_t yy_chk[975] =
>      {   0,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
> @@ -927,101 +940,105 @@ static const flex_int16_t yy_chk[940] =
>         18,   14,   11,   11,   13,   14,   11,   46,   46,   14,
>         15,   16,   11,   12,   12,   12,   12,   12,   14,   16,
>         12,   12,   12,   15,   19,   16,   20,   20,   21,   22,
> -       24,   22,   24,   50,   26,   21,   50,   26,   19,  351,
> -       20,   26,   19,   31,   31,   32,   32,   32,   39,   31,
> -
> -       39,   42,   32,   35,   35,   35,   35,   40,   44,   45,
> -       35,   35,   37,   37,   37,   37,   37,   39,   42,   37,
> -       37,   40,   41,   43,   41,   48,   45,   45,   49,   44,
> -       47,   47,   53,   51,   43,   53,   48,   51,   52,   54,
> -       52,   55,   56,   58,   54,   49,   57,   59,   60,   73,
> -       61,   70,   60,   61,  347,   70,   56,   63,   63,   73,
> -       58,   71,   59,   63,   59,   55,   66,   66,   57,   71,
> -       74,   72,   66,   72,   75,   76,   77,   78,   79,   78,
> -       77,   79,   80,   81,   74,   83,   80,   82,   75,   84,
> -       82,   85,   88,   85,   76,   81,   87,   83,   87,   89,
> -
> -       92,   89,   93,  345,   90,  104,   92,   84,   86,   86,
> -       86,   86,   90,   99,   88,   86,   86,   98,  102,   86,
> -       86,   91,   91,   93,   91,   94,   94,   91,  101,  104,
> -      102,   94,  101,  110,   99,   98,  100,  100,  100,  100,
> -      100,  103,  103,  100,  100,  343,  105,  103,  105,  107,
> -      109,  107,  111,  110,  109,  113,  113,  341,  121,  118,
> -      111,  112,  112,  112,  112,  112,  121,  113,  112,  112,
> -      114,  114,  116,  116,  118,  116,  114,  115,  115,  115,
> -      115,  115,  123,  123,  115,  115,  117,  117,  117,  117,
> -      117,  124,  122,  117,  117,  119,  122,  119,  120,  120,
> -
> -      120,  120,  120,  125,  130,  120,  120,  125,  131,  124,
> -      126,  126,  128,  128,  131,  134,  126,  130,  128,  133,
> -      133,  133,  135,  136,  133,  139,  164,  140,  138,  140,
> -      134,  164,  133,  141,  141,  163,  163,  338,  139,  141,
> -      136,  135,  137,  137,  137,  137,  137,  138,  336,  137,
> -      137,  143,  143,  145,  145,  146,  146,  143,  147,  147,
> -      149,  149,  145,  155,  147,  161,  149,  151,  151,  153,
> -      153,  146,  160,  151,  270,  153,  176,  156,  156,  158,
> -      158,  176,  155,  156,  161,  158,  165,  165,  170,  270,
> -      160,  170,  165,  172,  172,  173,  173,  174,  174,  175,
> -
> -      208,  177,  220,  175,  177,  178,  178,  173,  220,  174,
> -      208,  178,  180,  180,  172,  182,  182,  183,  180,  334,
> -      190,  190,  183,  184,  184,  184,  184,  184,  185,  185,
> -      184,  184,  190,  243,  185,  191,  191,  192,  192,  197,
> -      197,  202,  202,  192,  332,  197,  203,  203,  209,  209,
> -      213,  213,  203,  214,  214,  215,  215,  243,  216,  216,
> -      217,  217,  218,  218,  219,  219,  221,  221,  215,  235,
> -      219,  235,  221,  214,  216,  217,  227,  227,  228,  228,
> -      230,  230,  232,  331,  228,  233,  230,  233,  233,  329,
> -      232,  232,  236,  236,  241,  241,  244,  244,  245,  245,
> -
> -      241,  246,  246,  247,  248,  248,  267,  267,  244,  259,
> -      259,  247,  247,  252,  252,  245,  248,  326,  246,  252,
> -      253,  253,  267,  324,  259,  316,  253,  262,  262,  262,
> -      262,  262,  271,  271,  262,  262,  272,  276,  273,  272,
> -      272,  273,  273,  277,  278,  316,  276,  271,  281,  281,
> -      299,  278,  278,  282,  282,  285,  285,  277,  300,  287,
> -      287,  285,  290,  290,  281,  287,  323,  293,  294,  294,
> -      290,  293,  303,  299,  301,  301,  302,  302,  310,  310,
> -      303,  303,  300,  317,  302,  294,  304,  304,  322,  328,
> -      301,  309,  304,  311,  309,  309,  311,  311,  318,  317,
> -
> -      318,  318,  319,  321,  314,  319,  319,  328,  330,  330,
> -      350,  330,  340,  340,  340,  312,  297,  296,  350,  350,
> -      355,  355,  355,  355,  356,  356,  356,  357,  357,  357,
> -      357,  358,  358,  358,  358,  359,  295,  359,  359,  360,
> -      360,  360,  360,  361,  291,  361,  361,  362,  362,  362,
> -      362,  363,  363,  283,  363,  364,  364,  364,  364,  365,
> -      279,  365,  365,  366,  366,  366,  366,  367,  367,  367,
> -      367,  368,  368,  368,  368,  369,  369,  369,  369,  370,
> -      370,  370,  370,  371,  371,  371,  371,  372,  274,  372,
> -      372,  373,  373,  373,  373,  374,  374,  374,  374,  375,
> -
> -      268,  375,  375,  376,  376,  376,  376,  377,  265,  377,
> -      377,  378,  378,  378,  378,  379,  263,  379,  379,  380,
> -      380,  380,  380,  381,  260,  381,  381,  382,  382,  382,
> -      382,  383,  250,  383,  383,  384,  384,  384,  384,  385,
> -      242,  385,  385,  386,  386,  386,  386,  387,  239,  387,
> -      387,  388,  237,  388,  388,  389,  234,  389,  389,  390,
> -      226,  390,  390,  391,  391,  391,  391,  392,  392,  392,
> -      392,  393,  212,  393,  393,  394,  394,  394,  394,  395,
> -      395,  395,  395,  396,  210,  396,  396,  397,  397,  397,
> -      397,  398,  398,  398,  398,  399,  399,  399,  399,  400,
> -
> -      400,  400,  400,  401,  401,  401,  401,  402,  402,  402,
> -      402,  403,  162,  403,  403,  404,  404,  404,  404,  405,
> -      405,  405,  405,  406,  108,  406,  406,  407,  407,  407,
> -      407,  408,  408,  408,  408,  409,  409,  409,  409,  410,
> -      106,  410,  410,  411,  411,  411,  411,  412,  412,  412,
> -      412,  413,   69,  413,  413,  414,  414,  414,  414,  415,
> -      415,  415,  415,  416,  416,  416,  416,  417,  417,  417,
> -      417,  418,  418,  418,  418,  419,  419,  419,  419,  420,
> -      420,  420,  420,  421,  421,  421,  421,  422,  422,  422,
> -      422,  423,  423,  423,  423,   36,   29,   25,   23,   17,
> -
> -        6,    5,    4,    3,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
> -      354,  354,  354,  354,  354,  354,  354,  354,  354
> +       24,   22,   24,   50,   26,   21,   50,   26,   19,   44,
> +       20,   26,   19,   31,   31,   24,   32,   32,   32,   31,
> +
> +       39,   42,   39,   32,   35,   35,   35,   35,   40,   45,
> +       44,   35,   35,   37,   37,   37,   37,   37,   42,   39,
> +       37,   37,   40,   41,   43,   41,   45,   45,   47,   47,
> +       48,   49,   51,   54,   55,   43,   51,   52,   54,   52,
> +       53,   48,   56,   53,   57,   58,   59,   61,   49,   71,
> +       59,   61,   60,   71,   62,   72,   56,   62,   55,   64,
> +       64,   75,   58,   72,   77,   64,   57,   60,   74,   60,
> +       67,   67,   73,   76,   73,   75,   67,   78,   74,   82,
> +       79,   78,   79,   77,   84,   80,   81,   76,   80,   83,
> +       81,   82,   83,   85,   89,   86,   84,   86,   88,   90,
> +
> +       88,   90,   91,   92,  100,   92,  104,  369,   95,  101,
> +       91,   85,   87,   87,   87,   87,   89,  138,  104,   87,
> +       87,   94,  100,   87,   87,   93,   93,   94,   93,   95,
> +      101,   93,   96,   96,  106,  107,  138,  107,   96,  102,
> +      102,  102,  102,  102,  103,  112,  102,  102,  103,  105,
> +      105,  109,  111,  109,  113,  105,  111,  120,  106,  115,
> +      115,  122,  113,  122,  367,  112,  114,  114,  114,  114,
> +      114,  115,  120,  114,  114,  116,  116,  118,  118,  121,
> +      118,  116,  117,  117,  117,  117,  117,  121,  124,  117,
> +      117,  119,  119,  119,  119,  119,  124,  127,  119,  119,
> +
> +      123,  123,  123,  123,  123,  125,  365,  123,  123,  125,
> +      126,  126,  128,  129,  129,  127,  128,  131,  131,  129,
> +      133,  134,  139,  131,  136,  136,  136,  134,  137,  136,
> +      141,  158,  143,  133,  143,  144,  144,  136,  179,  139,
> +      142,  144,  179,  137,  140,  140,  140,  140,  140,  141,
> +      158,  140,  140,  142,  146,  146,  148,  148,  149,  149,
> +      146,  150,  150,  152,  152,  148,  165,  150,  164,  152,
> +      154,  154,  156,  156,  149,  159,  154,  240,  156,  240,
> +      159,  160,  160,  162,  162,  165,  164,  160,  168,  162,
> +      167,  167,  363,  168,  169,  169,  174,  176,  176,  174,
> +
> +      169,  177,  177,  178,  178,  180,  181,  186,  186,  181,
> +      180,  182,  182,  177,  207,  178,  187,  182,  176,  184,
> +      184,  187,  207,  194,  194,  184,  188,  188,  188,  188,
> +      188,  189,  189,  188,  188,  194,  359,  189,  195,  195,
> +      196,  196,  201,  201,  206,  206,  196,  213,  201,  208,
> +      208,  214,  214,  218,  218,  208,  225,  213,  219,  219,
> +      220,  220,  225,  221,  221,  222,  222,  223,  223,  224,
> +      224,  226,  226,  220,  241,  224,  241,  226,  219,  221,
> +      222,  232,  232,  233,  233,  235,  235,  237,  249,  233,
> +      238,  235,  238,  238,  357,  237,  237,  242,  242,  247,
> +
> +      247,  250,  250,  251,  251,  247,  252,  252,  253,  254,
> +      254,  292,  249,  250,  265,  265,  253,  253,  258,  258,
> +      251,  254,  277,  252,  258,  259,  259,  274,  274,  265,
> +      292,  259,  269,  269,  269,  269,  269,  277,  284,  269,
> +      269,  278,  278,  274,  279,  283,  280,  279,  279,  280,
> +      280,  285,  284,  301,  283,  307,  278,  301,  285,  285,
> +      288,  288,  289,  289,  293,  293,  295,  295,  302,  302,
> +      293,  308,  295,  298,  298,  355,  288,  352,  307,  310,
> +      310,  298,  309,  309,  311,  302,  312,  310,  319,  319,
> +      313,  313,  311,  311,  312,  308,  313,  318,  309,  320,
> +
> +      318,  318,  320,  320,  325,  326,  327,  328,  327,  327,
> +      328,  328,  330,  338,  340,  340,  342,  340,  351,  351,
> +      351,  326,  354,  354,  325,  362,  330,  349,  347,  342,
> +      345,  338,  343,  362,  362,  372,  372,  372,  372,  373,
> +      373,  373,  374,  374,  374,  374,  375,  375,  375,  375,
> +      376,  341,  376,  376,  377,  377,  377,  377,  378,  339,
> +      378,  378,  379,  379,  379,  379,  380,  380,  336,  380,
> +      381,  381,  381,  381,  382,  334,  382,  382,  383,  383,
> +      383,  383,  384,  384,  384,  384,  385,  385,  385,  385,
> +      386,  386,  386,  386,  387,  387,  387,  387,  388,  388,
> +
> +      388,  388,  389,  333,  389,  389,  390,  390,  390,  390,
> +      391,  391,  391,  391,  392,  332,  392,  392,  393,  393,
> +      393,  393,  394,  331,  394,  394,  395,  395,  395,  395,
> +      396,  323,  396,  396,  397,  397,  397,  397,  398,  321,
> +      398,  398,  399,  399,  399,  399,  400,  305,  400,  400,
> +      401,  401,  401,  401,  402,  304,  402,  402,  403,  403,
> +      403,  403,  404,  303,  404,  404,  405,  299,  405,  405,
> +      406,  290,  406,  406,  407,  286,  407,  407,  408,  408,
> +      408,  408,  409,  409,  409,  409,  410,  281,  410,  410,
> +      411,  411,  411,  411,  412,  412,  412,  412,  413,  275,
> +
> +      413,  413,  414,  414,  414,  414,  415,  415,  415,  415,
> +      416,  416,  416,  416,  417,  417,  417,  417,  418,  418,
> +      418,  418,  419,  419,  419,  419,  420,  272,  420,  420,
> +      421,  421,  421,  421,  422,  422,  422,  422,  423,  270,
> +      423,  423,  424,  424,  424,  424,  425,  425,  425,  425,
> +      426,  426,  426,  426,  427,  268,  427,  427,  428,  428,
> +      428,  428,  429,  429,  429,  429,  430,  266,  430,  430,
> +      431,  431,  431,  431,  432,  432,  432,  432,  433,  433,
> +      433,  433,  434,  434,  434,  434,  435,  435,  435,  435,
> +      436,  436,  436,  436,  437,  437,  437,  437,  438,  438,
> +
> +      438,  438,  439,  439,  439,  439,  440,  440,  440,  440,
> +      441,  441,  441,  441,  442,  442,  442,  442,  256,  248,
> +      245,  243,  239,  231,  217,  215,  166,  110,  108,   70,
> +       36,   29,   25,   23,   17,    6,    5,    4,    3,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
> +      371,  371,  371,  371
>      } ;
> 
>  #define YY_TRAILING_MASK 0x2000
> @@ -1160,9 +1177,17 @@ static void setbackendtype(DiskParseContext
> *dpc, const char *str) {
>      if (     !strcmp(str,"phy"))   DSET(dpc,backend,BACKEND,str,PHY);
>      else if (!strcmp(str,"tap"))   DSET(dpc,backend,BACKEND,str,TAP);
>      else if (!strcmp(str,"qdisk")) DSET(dpc,backend,BACKEND,str,QDISK);
> +    else if (!strcmp(str,"standalone"))
> DSET(dpc,backend,BACKEND,str,STANDALONE);
>      else xlu__disk_err(dpc,str,"unknown value for backendtype");
>  }
> 
> +/* Sets ->specification from the string.  IDL should provide something for
> this. */
> +static void setspecification(DiskParseContext *dpc, const char *str) {
> +    if      (!strcmp(str,"xen"))    DSET(dpc,specification,SPECIFICATION,str,XEN);
> +    else if (!strcmp(str,"virtio"))
> DSET(dpc,specification,SPECIFICATION,str,VIRTIO);
> +    else xlu__disk_err(dpc,str,"unknown value for specification");
> +}
> +
>  /* Sets ->colo-port from the string.  COLO need this. */
>  static void setcoloport(DiskParseContext *dpc, const char *str) {
>      int port = atoi(str);
> @@ -1199,9 +1224,9 @@ static int vdev_and_devtype(DiskParseContext
> *dpc, char *str) {
>  #undef DPC /* needs to be defined differently the actual lexer */
>  #define DPC ((DiskParseContext*)yyextra)
> 
> -#line 1202 "libxlu_disk_l.c"
> +#line 1227 "libxlu_disk_l.c"
> 
> -#line 1204 "libxlu_disk_l.c"
> +#line 1229 "libxlu_disk_l.c"
> 
>  #define INITIAL 0
>  #define LEXERR 1
> @@ -1477,13 +1502,13 @@ YY_DECL
>  		}
> 
>  	{
> -#line 177 "libxlu_disk_l.l"
> +#line 185 "libxlu_disk_l.l"
> 
> 
> -#line 180 "libxlu_disk_l.l"
> +#line 188 "libxlu_disk_l.l"
>   /*----- the scanner rules which do the parsing -----*/
> 
> -#line 1486 "libxlu_disk_l.c"
> +#line 1511 "libxlu_disk_l.c"
> 
>  	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is
> reached */
>  		{
> @@ -1515,14 +1540,14 @@ yy_match:
>  			while ( yy_chk[yy_base[yy_current_state] + yy_c] !=
> yy_current_state )
>  				{
>  				yy_current_state = (int)
> yy_def[yy_current_state];
> -				if ( yy_current_state >= 355 )
> +				if ( yy_current_state >= 372 )
>  					yy_c = yy_meta[yy_c];
>  				}
>  			yy_current_state = yy_nxt[yy_base[yy_current_state]
> + yy_c];
>  			*yyg->yy_state_ptr++ = yy_current_state;
>  			++yy_cp;
>  			}
> -		while ( yy_current_state != 354 );
> +		while ( yy_current_state != 371 );
> 
>  yy_find_action:
>  		yy_current_state = *--yyg->yy_state_ptr;
> @@ -1572,152 +1597,158 @@ do_action:	/* This label is used only to
> access EOF actions. */
>  case 1:
>  /* rule 1 can match eol */
>  YY_RULE_SETUP
> -#line 182 "libxlu_disk_l.l"
> +#line 190 "libxlu_disk_l.l"
>  { /* ignore whitespace before parameters */ }
>  	YY_BREAK
>  /* ordinary parameters setting enums or strings */
>  case 2:
>  /* rule 2 can match eol */
>  YY_RULE_SETUP
> -#line 186 "libxlu_disk_l.l"
> +#line 194 "libxlu_disk_l.l"
>  { STRIP(','); setformat(DPC, FROMEQUALS); }
>  	YY_BREAK
>  case 3:
>  YY_RULE_SETUP
> -#line 188 "libxlu_disk_l.l"
> +#line 196 "libxlu_disk_l.l"
>  { DPC->disk->is_cdrom = 1; }
>  	YY_BREAK
>  case 4:
>  YY_RULE_SETUP
> -#line 189 "libxlu_disk_l.l"
> +#line 197 "libxlu_disk_l.l"
>  { DPC->disk->is_cdrom = 1; }
>  	YY_BREAK
>  case 5:
>  YY_RULE_SETUP
> -#line 190 "libxlu_disk_l.l"
> +#line 198 "libxlu_disk_l.l"
>  { DPC->disk->is_cdrom = 0; }
>  	YY_BREAK
>  case 6:
>  /* rule 6 can match eol */
>  YY_RULE_SETUP
> -#line 191 "libxlu_disk_l.l"
> +#line 199 "libxlu_disk_l.l"
>  { xlu__disk_err(DPC,yytext,"unknown value for type"); }
>  	YY_BREAK
>  case 7:
>  /* rule 7 can match eol */
>  YY_RULE_SETUP
> -#line 193 "libxlu_disk_l.l"
> +#line 201 "libxlu_disk_l.l"
>  { STRIP(','); setaccess(DPC, FROMEQUALS); }
>  	YY_BREAK
>  case 8:
>  /* rule 8 can match eol */
>  YY_RULE_SETUP
> -#line 194 "libxlu_disk_l.l"
> +#line 202 "libxlu_disk_l.l"
>  { STRIP(','); SAVESTRING("backend", backend_domname, FROMEQUALS); }
>  	YY_BREAK
>  case 9:
>  /* rule 9 can match eol */
>  YY_RULE_SETUP
> -#line 195 "libxlu_disk_l.l"
> +#line 203 "libxlu_disk_l.l"
>  { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
>  	YY_BREAK
>  case 10:
>  /* rule 10 can match eol */
>  YY_RULE_SETUP
> -#line 197 "libxlu_disk_l.l"
> -{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
> +#line 204 "libxlu_disk_l.l"
> +{ STRIP(','); setspecification(DPC,FROMEQUALS); }
>  	YY_BREAK
>  case 11:
>  /* rule 11 can match eol */
>  YY_RULE_SETUP
> -#line 198 "libxlu_disk_l.l"
> -{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
> +#line 206 "libxlu_disk_l.l"
> +{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
>  	YY_BREAK
>  case 12:
> +/* rule 12 can match eol */
>  YY_RULE_SETUP
> -#line 199 "libxlu_disk_l.l"
> -{ DPC->disk->direct_io_safe = 1; }
> +#line 207 "libxlu_disk_l.l"
> +{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
>  	YY_BREAK
>  case 13:
>  YY_RULE_SETUP
> -#line 200 "libxlu_disk_l.l"
> -{ libxl_defbool_set(&DPC->disk->discard_enable, true); }
> +#line 208 "libxlu_disk_l.l"
> +{ DPC->disk->direct_io_safe = 1; }
>  	YY_BREAK
>  case 14:
>  YY_RULE_SETUP
> -#line 201 "libxlu_disk_l.l"
> -{ libxl_defbool_set(&DPC->disk->discard_enable, false); }
> +#line 209 "libxlu_disk_l.l"
> +{ libxl_defbool_set(&DPC->disk->discard_enable, true); }
>  	YY_BREAK
> -/* Note that the COLO configuration settings should be considered unstable.
> -  * They may change incompatibly in future versions of Xen. */
>  case 15:
>  YY_RULE_SETUP
> -#line 204 "libxlu_disk_l.l"
> -{ libxl_defbool_set(&DPC->disk->colo_enable, true); }
> +#line 210 "libxlu_disk_l.l"
> +{ libxl_defbool_set(&DPC->disk->discard_enable, false); }
>  	YY_BREAK
> +/* Note that the COLO configuration settings should be considered unstable.
> +  * They may change incompatibly in future versions of Xen. */
>  case 16:
>  YY_RULE_SETUP
> -#line 205 "libxlu_disk_l.l"
> -{ libxl_defbool_set(&DPC->disk->colo_enable, false); }
> +#line 213 "libxlu_disk_l.l"
> +{ libxl_defbool_set(&DPC->disk->colo_enable, true); }
>  	YY_BREAK
>  case 17:
> -/* rule 17 can match eol */
>  YY_RULE_SETUP
> -#line 206 "libxlu_disk_l.l"
> -{ STRIP(','); SAVESTRING("colo-host", colo_host, FROMEQUALS); }
> +#line 214 "libxlu_disk_l.l"
> +{ libxl_defbool_set(&DPC->disk->colo_enable, false); }
>  	YY_BREAK
>  case 18:
>  /* rule 18 can match eol */
>  YY_RULE_SETUP
> -#line 207 "libxlu_disk_l.l"
> -{ STRIP(','); setcoloport(DPC, FROMEQUALS); }
> +#line 215 "libxlu_disk_l.l"
> +{ STRIP(','); SAVESTRING("colo-host", colo_host, FROMEQUALS); }
>  	YY_BREAK
>  case 19:
>  /* rule 19 can match eol */
>  YY_RULE_SETUP
> -#line 208 "libxlu_disk_l.l"
> -{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
> +#line 216 "libxlu_disk_l.l"
> +{ STRIP(','); setcoloport(DPC, FROMEQUALS); }
>  	YY_BREAK
>  case 20:
>  /* rule 20 can match eol */
>  YY_RULE_SETUP
> -#line 209 "libxlu_disk_l.l"
> -{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
> +#line 217 "libxlu_disk_l.l"
> +{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
>  	YY_BREAK
>  case 21:
>  /* rule 21 can match eol */
>  YY_RULE_SETUP
> -#line 210 "libxlu_disk_l.l"
> +#line 218 "libxlu_disk_l.l"
> +{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
> +	YY_BREAK
> +case 22:
> +/* rule 22 can match eol */
> +YY_RULE_SETUP
> +#line 219 "libxlu_disk_l.l"
>  { STRIP(','); SAVESTRING("hidden-disk", hidden_disk, FROMEQUALS); }
>  	YY_BREAK
>  /* the target magic parameter, eats the rest of the string */
> -case 22:
> +case 23:
>  YY_RULE_SETUP
> -#line 214 "libxlu_disk_l.l"
> +#line 223 "libxlu_disk_l.l"
>  { STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
>  	YY_BREAK
>  /* unknown parameters */
> -case 23:
> -/* rule 23 can match eol */
> +case 24:
> +/* rule 24 can match eol */
>  YY_RULE_SETUP
> -#line 218 "libxlu_disk_l.l"
> +#line 227 "libxlu_disk_l.l"
>  { xlu__disk_err(DPC,yytext,"unknown parameter"); }
>  	YY_BREAK
>  /* deprecated prefixes */
>  /* the "/.*" in these patterns ensures that they count as if they
>     * matched the whole string, so these patterns take precedence */
> -case 24:
> +case 25:
>  YY_RULE_SETUP
> -#line 225 "libxlu_disk_l.l"
> +#line 234 "libxlu_disk_l.l"
>  {
>                      STRIP(':');
>                      DPC->had_depr_prefix=1; DEPRECATE("use `[format=]...,'");
>                      setformat(DPC, yytext);
>                   }
>  	YY_BREAK
> -case 25:
> +case 26:
>  YY_RULE_SETUP
> -#line 231 "libxlu_disk_l.l"
> +#line 240 "libxlu_disk_l.l"
>  {
>                      char *newscript;
>                      STRIP(':');
> @@ -1731,65 +1762,65 @@ YY_RULE_SETUP
>                      free(newscript);
>                  }
>  	YY_BREAK
> -case 26:
> +case 27:
>  *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>  yyg->yy_c_buf_p = yy_cp = yy_bp + 8;
>  YY_DO_BEFORE_ACTION; /* set up yytext again */
>  YY_RULE_SETUP
> -#line 244 "libxlu_disk_l.l"
> +#line 253 "libxlu_disk_l.l"
>  { DPC->had_depr_prefix=1; DEPRECATE(0); }
>  	YY_BREAK
> -case 27:
> +case 28:
>  YY_RULE_SETUP
> -#line 245 "libxlu_disk_l.l"
> +#line 254 "libxlu_disk_l.l"
>  { DPC->had_depr_prefix=1; DEPRECATE(0); }
>  	YY_BREAK
> -case 28:
> +case 29:
>  *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>  yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
>  YY_DO_BEFORE_ACTION; /* set up yytext again */
>  YY_RULE_SETUP
> -#line 246 "libxlu_disk_l.l"
> +#line 255 "libxlu_disk_l.l"
>  { DPC->had_depr_prefix=1; DEPRECATE(0); }
>  	YY_BREAK
> -case 29:
> +case 30:
>  *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>  yyg->yy_c_buf_p = yy_cp = yy_bp + 6;
>  YY_DO_BEFORE_ACTION; /* set up yytext again */
>  YY_RULE_SETUP
> -#line 247 "libxlu_disk_l.l"
> +#line 256 "libxlu_disk_l.l"
>  { DPC->had_depr_prefix=1; DEPRECATE(0); }
>  	YY_BREAK
> -case 30:
> +case 31:
>  *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>  yyg->yy_c_buf_p = yy_cp = yy_bp + 5;
>  YY_DO_BEFORE_ACTION; /* set up yytext again */
>  YY_RULE_SETUP
> -#line 248 "libxlu_disk_l.l"
> +#line 257 "libxlu_disk_l.l"
>  { DPC->had_depr_prefix=1; DEPRECATE(0); }
>  	YY_BREAK
> -case 31:
> +case 32:
>  *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>  yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
>  YY_DO_BEFORE_ACTION; /* set up yytext again */
>  YY_RULE_SETUP
> -#line 249 "libxlu_disk_l.l"
> +#line 258 "libxlu_disk_l.l"
>  { DPC->had_depr_prefix=1; DEPRECATE(0); }
>  	YY_BREAK
> -case 32:
> -/* rule 32 can match eol */
> +case 33:
> +/* rule 33 can match eol */
>  YY_RULE_SETUP
> -#line 251 "libxlu_disk_l.l"
> +#line 260 "libxlu_disk_l.l"
>  {
>  		  xlu__disk_err(DPC,yytext,"unknown deprecated disk
> prefix");
>  		  return 0;
>  		}
>  	YY_BREAK
>  /* positional parameters */
> -case 33:
> -/* rule 33 can match eol */
> +case 34:
> +/* rule 34 can match eol */
>  YY_RULE_SETUP
> -#line 258 "libxlu_disk_l.l"
> +#line 267 "libxlu_disk_l.l"
>  {
>      STRIP(',');
> 
> @@ -1816,27 +1847,27 @@ YY_RULE_SETUP
>      }
>  }
>  	YY_BREAK
> -case 34:
> +case 35:
>  YY_RULE_SETUP
> -#line 284 "libxlu_disk_l.l"
> +#line 293 "libxlu_disk_l.l"
>  {
>      BEGIN(LEXERR);
>      yymore();
>  }
>  	YY_BREAK
> -case 35:
> +case 36:
>  YY_RULE_SETUP
> -#line 288 "libxlu_disk_l.l"
> +#line 297 "libxlu_disk_l.l"
>  {
>      xlu__disk_err(DPC,yytext,"bad disk syntax"); return 0;
>  }
>  	YY_BREAK
> -case 36:
> +case 37:
>  YY_RULE_SETUP
> -#line 291 "libxlu_disk_l.l"
> +#line 300 "libxlu_disk_l.l"
>  YY_FATAL_ERROR( "flex scanner jammed" );
>  	YY_BREAK
> -#line 1839 "libxlu_disk_l.c"
> +#line 1870 "libxlu_disk_l.c"
>  			case YY_STATE_EOF(INITIAL):
>  			case YY_STATE_EOF(LEXERR):
>  				yyterminate();
> @@ -2104,7 +2135,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
>  		while ( yy_chk[yy_base[yy_current_state] + yy_c] !=
> yy_current_state )
>  			{
>  			yy_current_state = (int) yy_def[yy_current_state];
> -			if ( yy_current_state >= 355 )
> +			if ( yy_current_state >= 372 )
>  				yy_c = yy_meta[yy_c];
>  			}
>  		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
> @@ -2128,11 +2159,11 @@ static int yy_get_next_buffer (yyscan_t
> yyscanner)
>  	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
>  		{
>  		yy_current_state = (int) yy_def[yy_current_state];
> -		if ( yy_current_state >= 355 )
> +		if ( yy_current_state >= 372 )
>  			yy_c = yy_meta[yy_c];
>  		}
>  	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
> -	yy_is_jam = (yy_current_state == 354);
> +	yy_is_jam = (yy_current_state == 371);
>  	if ( ! yy_is_jam )
>  		*yyg->yy_state_ptr++ = yy_current_state;
> 
> @@ -2941,4 +2972,4 @@ void yyfree (void * ptr , yyscan_t yyscanner)
> 
>  #define YYTABLES_NAME "yytables"
> 
> -#line 291 "libxlu_disk_l.l"
> +#line 300 "libxlu_disk_l.l"
> diff --git a/tools/libs/util/libxlu_disk_l.h b/tools/libs/util/libxlu_disk_l.h
> index 6abeecf279..509aad67dc 100644
> --- a/tools/libs/util/libxlu_disk_l.h
> +++ b/tools/libs/util/libxlu_disk_l.h
> @@ -694,7 +694,7 @@ extern int yylex (yyscan_t yyscanner);
>  #undef yyTABLES_NAME
>  #endif
> 
> -#line 291 "libxlu_disk_l.l"
> +#line 300 "libxlu_disk_l.l"
> 
>  #line 699 "libxlu_disk_l.h"
>  #undef xlu__disk_yyIN_HEADER
> diff --git a/tools/libs/util/libxlu_disk_l.l b/tools/libs/util/libxlu_disk_l.l
> index e115460d99..6d53c093a3 100644
> --- a/tools/libs/util/libxlu_disk_l.l
> +++ b/tools/libs/util/libxlu_disk_l.l
> @@ -122,9 +122,17 @@ static void setbackendtype(DiskParseContext *dpc,
> const char *str) {
>      if (     !strcmp(str,"phy"))   DSET(dpc,backend,BACKEND,str,PHY);
>      else if (!strcmp(str,"tap"))   DSET(dpc,backend,BACKEND,str,TAP);
>      else if (!strcmp(str,"qdisk")) DSET(dpc,backend,BACKEND,str,QDISK);
> +    else if (!strcmp(str,"standalone"))
> DSET(dpc,backend,BACKEND,str,STANDALONE);
>      else xlu__disk_err(dpc,str,"unknown value for backendtype");
>  }
> 
> +/* Sets ->specification from the string.  IDL should provide something for
> this. */
> +static void setspecification(DiskParseContext *dpc, const char *str) {
> +    if      (!strcmp(str,"xen"))    DSET(dpc,specification,SPECIFICATION,str,XEN);
> +    else if (!strcmp(str,"virtio"))
> DSET(dpc,specification,SPECIFICATION,str,VIRTIO);
> +    else xlu__disk_err(dpc,str,"unknown value for specification");
> +}
> +
>  /* Sets ->colo-port from the string.  COLO need this. */
>  static void setcoloport(DiskParseContext *dpc, const char *str) {
>      int port = atoi(str);
> @@ -192,6 +200,7 @@ devtype=[^,]*,?
> 	{ xlu__disk_err(DPC,yytext,"unknown value for type"); }
>  access=[^,]*,?	{ STRIP(','); setaccess(DPC, FROMEQUALS); }
>  backend=[^,]*,? { STRIP(','); SAVESTRING("backend", backend_domname,
> FROMEQUALS); }
>  backendtype=[^,]*,? { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
> +specification=[^,]*,? { STRIP(','); setspecification(DPC,FROMEQUALS); }
> 
>  vdev=[^,]*,?	{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
>  script=[^,]*,?	{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
> diff --git a/tools/xl/xl_block.c b/tools/xl/xl_block.c
> index 70eed431e4..8836c07d6b 100644
> --- a/tools/xl/xl_block.c
> +++ b/tools/xl/xl_block.c
> @@ -119,6 +119,12 @@ int main_blockdetach(int argc, char **argv)
>          fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
>          return 1;
>      }
> +
> +    if (disk.specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
> +        fprintf(stderr, "Hotunplug isn't supported for specification virtio\n");
> +        return 1;
> +    }
> +
>      rc = !force ? libxl_device_disk_safe_remove(ctx, domid, &disk, 0) :
>          libxl_device_disk_destroy(ctx, domid, &disk, 0);
>      if (rc) {
> --
> 2.25.1
>
Oleksandr Tyshchenko July 20, 2022, 8:02 a.m. UTC | #2
On 20.07.22 06:29, Jiamei Xie wrote:
> Hi Oleksandr,

Hello Jiamei


>
> We have tested it on arm64 with " disk = [ 'phy:/usr/share/guests/disk.img0, xvda1, backendtype=standalone, specification=virtio']". It works ok.
>
> Tested-by: Jiamei Xie <jiamei.xie@arm.com>
> Tested-by: Henry Wang <Henry.Wang@arm.com>


Thank you for the testing!


>
> Best wishes
> Jiamei Xie
>
>
>> -----Original Message-----
>> From: Xen-devel <xen-devel-bounces@lists.xenproject.org> On Behalf Of
>> Oleksandr Tyshchenko
>> Sent: Sunday, July 17, 2022 12:38 AM
>> To: xen-devel@lists.xenproject.org
>> Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>; Wei Liu
>> <wl@xen.org>; Anthony PERARD <anthony.perard@citrix.com>; George
>> Dunlap <george.dunlap@citrix.com>; Nick Rosbrook
>> <rosbrookn@gmail.com>; Juergen Gross <jgross@suse.com>; Stefano
>> Stabellini <sstabellini@kernel.org>; Julien Grall <julien@xen.org>; Volodymyr
>> Babchuk <Volodymyr_Babchuk@epam.com>; Bertrand Marquis
>> <Bertrand.Marquis@arm.com>
>> Subject: [PATCH V11.1 1/3] libxl: Add support for Virtio disk configuration
>>
>> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
>>
>> This patch adds basic support for configuring and assisting virtio-mmio
>> based virtio-disk backend (emulator) which is intended to run out of
>> Qemu and could be run in any domain.
>> Although the Virtio block device is quite different from traditional
>> Xen PV block device (vbd) from the toolstack's point of view:
>>   - as the frontend is virtio-blk which is not a Xenbus driver, nothing
>>     written to Xenstore are fetched by the frontend currently ("vdev"
>>     is not passed to the frontend). But this might need to be revised
>>     in future, so frontend data might be written to Xenstore in order to
>>     support hotplugging virtio devices or passing the backend domain id
>>     on arch where the device-tree is not available.
>>   - the ring-ref/event-channel are not used for the backend<->frontend
>>     communication, the proposed IPC for Virtio is IOREQ/DM
>> it is still a "block device" and ought to be integrated in existing
>> "disk" handling. So, re-use (and adapt) "disk" parsing/configuration
>> logic to deal with Virtio devices as well.
>>
>> For the immediate purpose and an ability to extend that support for
>> other use-cases in future (Qemu, virtio-pci, etc) perform the following
>> actions:
>> - Add new disk backend type (LIBXL_DISK_BACKEND_STANDALONE) and
>> reflect
>>    that in the configuration
>> - Introduce new disk "specification" and "transport" fields to struct
>>    libxl_device_disk. Both are written to the Xenstore. The transport
>>    field is only used for the specification "virtio" and it assumes
>>    only "mmio" value for now.
>> - Introduce new "specification" option with "xen" communication
>>    protocol being default value.
>> - Add new device kind (LIBXL__DEVICE_KIND_VIRTIO_DISK) as current
>>    one (LIBXL__DEVICE_KIND_VBD) doesn't fit into Virtio disk model
>>
>> An example of domain configuration for Virtio disk:
>> disk = [ 'phy:/dev/mmcblk0p3, xvda1, backendtype=standalone,
>> specification=virtio']
>>
>> Nothing has changed for default Xen disk configuration.
>>
>> Please note, this patch is not enough for virtio-disk to work
>> on Xen (Arm), as for every Virtio device (including disk) we need
>> to allocate Virtio MMIO params (IRQ and memory region) and pass
>> them to the backend, also update Guest device-tree. The subsequent
>> patch will add these missing bits. For the current patch,
>> the default "irq" and "base" are just written to the Xenstore.
>> This is not an ideal splitting, but this way we avoid breaking
>> the bisectability.
>>
>> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
>> ---
>> Changes RFC -> V1:
>>     - no changes
>>
>> Changes V1 -> V2:
>>     - rebase according to the new location of libxl_virtio_disk.c
>>
>> Changes V2 -> V3:
>>     - no changes
>>
>> Changes V3 -> V4:
>>     - rebase according to the new argument for DEFINE_DEVICE_TYPE_STRUCT
>>
>> Changes V4 -> V5:
>>     - split the changes, change the order of the patches
>>     - update patch description
>>     - don't introduce new "vdisk" configuration option with own parsing logic,
>>       re-use Xen PV block "disk" parsing/configuration logic for the virtio-disk
>>     - introduce "virtio" flag and document it's usage
>>     - add LIBXL_HAVE_DEVICE_DISK_VIRTIO
>>     - update libxlu_disk_l.[ch]
>>     - drop num_disks variable/MAX_VIRTIO_DISKS
>>     - drop Wei's T-b
>>
>> Changes V5 -> V6:
>>     - rebase on current staging
>>     - use "%"PRIu64 instead of %lu for disk->base in device_disk_add()
>>     - update *.gen.go files
>>
>> Changes V6 -> V7:
>>     - rebase on current staging
>>     - update *.gen.go files and libxlu_disk_l.[ch] files
>>     - update patch description
>>     - rework significantly to support more flexible configuration
>>       and have more generic basic implementation for being able to extend
>>       that for other use-cases (virtio-pci, qemu, etc).
>>
>> Changes V7 -> V8:
>>     - update *.gen.go files and libxlu_disk_l.[ch] files
>>     - update patch description and comments in the code
>>     - use "specification" config option instead of "protocol"
>>     - update libxl_types.idl and code according to new fields
>>       in libxl_device_disk
>>
>> Changes V8 -> V9:
>>     - update (and harden) checks in libxl__device_disk_setdefault(),
>>       return error in case of incorrect settings of specification
>>       and transport
>>     - remove both asserts in device_disk_add()
>>     - update virtio related code in libxl__disk_from_xenstore(),
>>       do not fail if specification node is absent, replace
>>       open-coded checks of fetched specification and transport by
>>       libxl_disk_specification_from_string() and
>> libxl_disk_transport_from_string()
>>       respectively
>>     - s/libxl_device_disk_get_path/libxl__device_disk_get_path
>>     - add a comment for virtio-mmio parameters in struct libxl_device_disk
>>
>> Changes V9 -> V10:
>>     - s/ERROR_FAIL/ERROR_INVAL in both places in
>> libxl__device_disk_setdefault()
>>     - rework libxl__device_disk_get_path()
>>
>> Changes V10 -> V10.1:
>>     - fix small coding style issue in libxl__device_disk_get_path()
>>     - drop specification check in main_blockattach() and add
>>       required check in libxl__device_disk_setdefault()
>>     - update specification check in main_blockdetach()
>>
>> Changes V10.1 -> V11:
>>     - Anthony already gave his Reviewed-by, I dropped it due to the changes
>>     - George already gave his Acked-by, I dropped it due to the changes
>>     - s/other/standalone for the backendtype
>>
>> Changes V11 -> V11.1:
>>     - rebase
>> ---
>>   docs/man/xl-disk-configuration.5.pod.in   |  38 +-
>>   tools/golang/xenlight/helpers.gen.go      |   8 +
>>   tools/golang/xenlight/types.gen.go        |  18 +
>>   tools/include/libxl.h                     |   7 +
>>   tools/libs/light/libxl_device.c           |  62 +-
>>   tools/libs/light/libxl_disk.c             | 146 +++-
>>   tools/libs/light/libxl_internal.h         |   2 +
>>   tools/libs/light/libxl_types.idl          |  18 +
>>   tools/libs/light/libxl_types_internal.idl |   1 +
>>   tools/libs/light/libxl_utils.c            |   2 +
>>   tools/libs/util/libxlu_disk_l.c           | 959 +++++++++++-----------
>>   tools/libs/util/libxlu_disk_l.h           |   2 +-
>>   tools/libs/util/libxlu_disk_l.l           |   9 +
>>   tools/xl/xl_block.c                       |   6 +
>>   14 files changed, 798 insertions(+), 480 deletions(-)
>>
>> diff --git a/docs/man/xl-disk-configuration.5.pod.in b/docs/man/xl-disk-
>> configuration.5.pod.in
>> index 95d039655a..bc945cc517 100644
>> --- a/docs/man/xl-disk-configuration.5.pod.in
>> +++ b/docs/man/xl-disk-configuration.5.pod.in
>> @@ -232,7 +232,7 @@ Specifies the backend implementation to use
>>
>>   =item Supported values
>>
>> -phy, qdisk
>> +phy, qdisk, standalone
>>
>>   =item Mandatory
>>
>> @@ -244,11 +244,13 @@ Automatically determine which backend to use.
>>
>>   =back
>>
>> -This does not affect the guest's view of the device.  It controls
>> -which software implementation of the Xen backend driver is used.
>> +It controls which software implementation of the backend driver is used.
>> +Depending on the "specification" option this may affect the guest's view
>> +of the device.
>>
>>   Not all backend drivers support all combinations of other options.
>> -For example, "phy" does not support formats other than "raw".
>> +For example, "phy" and "standalone" do not support formats other than
>> "raw"
>> +and "standalone" does not support specifications other than "virtio".
>>   Normally this option should not be specified, in which case libxl will
>>   automatically determine the most suitable backend.
>>
>> @@ -373,8 +375,36 @@ processing or causing malfunction to the frontend
>> or the whole domain.
>>
>>   Note frontends can ignore such recommendation.
>>
>> +=item B<specification>=I<SPECIFICATION>
>> +
>> +=over 4
>> +
>> +=item Description
>> +
>> +Specifies the communication protocol (specification) to use for the chosen
>> +"backendtype" option
>> +
>> +=item Supported values
>> +
>> +xen, virtio
>> +
>> +=item Mandatory
>> +
>> +No
>> +
>> +=item Default value
>> +
>> +xen
>> +
>>   =back
>>
>> +Besides forcing toolstack to use specific backend implementation, this also
>> +affects the guest's view of the device. For example, "virtio" requires
>> +Virtio frontend driver (virtio-blk) to be used. Please note, the virtual
>> +device (vdev) is not passed to the guest in that case, but it still must be
>> +specified for the internal purposes.
>> +
>> +=back
>>
>>   =head1 COLO Parameters
>>
>> diff --git a/tools/golang/xenlight/helpers.gen.go
>> b/tools/golang/xenlight/helpers.gen.go
>> index dece545ee0..ad8c11eae1 100644
>> --- a/tools/golang/xenlight/helpers.gen.go
>> +++ b/tools/golang/xenlight/helpers.gen.go
>> @@ -1763,6 +1763,10 @@ x.DirectIoSafe = bool(xc.direct_io_safe)
>>   if err := x.DiscardEnable.fromC(&xc.discard_enable);err != nil {
>>   return fmt.Errorf("converting field DiscardEnable: %v", err)
>>   }
>> +x.Specification = DiskSpecification(xc.specification)
>> +x.Transport = DiskTransport(xc.transport)
>> +x.Irq = uint32(xc.irq)
>> +x.Base = uint64(xc.base)
>>   if err := x.ColoEnable.fromC(&xc.colo_enable);err != nil {
>>   return fmt.Errorf("converting field ColoEnable: %v", err)
>>   }
>> @@ -1800,6 +1804,10 @@ xc.direct_io_safe = C.bool(x.DirectIoSafe)
>>   if err := x.DiscardEnable.toC(&xc.discard_enable); err != nil {
>>   return fmt.Errorf("converting field DiscardEnable: %v", err)
>>   }
>> +xc.specification = C.libxl_disk_specification(x.Specification)
>> +xc.transport = C.libxl_disk_transport(x.Transport)
>> +xc.irq = C.uint32_t(x.Irq)
>> +xc.base = C.uint64_t(x.Base)
>>   if err := x.ColoEnable.toC(&xc.colo_enable); err != nil {
>>   return fmt.Errorf("converting field ColoEnable: %v", err)
>>   }
>> diff --git a/tools/golang/xenlight/types.gen.go
>> b/tools/golang/xenlight/types.gen.go
>> index 253c9ad93d..b9143390f8 100644
>> --- a/tools/golang/xenlight/types.gen.go
>> +++ b/tools/golang/xenlight/types.gen.go
>> @@ -99,6 +99,20 @@ DiskBackendUnknown DiskBackend = 0
>>   DiskBackendPhy DiskBackend = 1
>>   DiskBackendTap DiskBackend = 2
>>   DiskBackendQdisk DiskBackend = 3
>> +DiskBackendStandalone DiskBackend = 4
>> +)
>> +
>> +type DiskSpecification int
>> +const(
>> +DiskSpecificationUnknown DiskSpecification = 0
>> +DiskSpecificationXen DiskSpecification = 1
>> +DiskSpecificationVirtio DiskSpecification = 2
>> +)
>> +
>> +type DiskTransport int
>> +const(
>> +DiskTransportUnknown DiskTransport = 0
>> +DiskTransportMmio DiskTransport = 1
>>   )
>>
>>   type NicType int
>> @@ -645,6 +659,10 @@ Readwrite int
>>   IsCdrom int
>>   DirectIoSafe bool
>>   DiscardEnable Defbool
>> +Specification DiskSpecification
>> +Transport DiskTransport
>> +Irq uint32
>> +Base uint64
>>   ColoEnable Defbool
>>   ColoRestoreEnable Defbool
>>   ColoHost string
>> diff --git a/tools/include/libxl.h b/tools/include/libxl.h
>> index f351669039..2321a648a5 100644
>> --- a/tools/include/libxl.h
>> +++ b/tools/include/libxl.h
>> @@ -549,6 +549,13 @@
>>    */
>>   #define LIBXL_HAVE_ASSISTED_APIC 1
>>
>> +/*
>> + * LIBXL_HAVE_DEVICE_DISK_SPECIFICATION indicates that 'specification'
>> and
>> + * 'transport' fields (of libxl_disk_specification and libxl_disk_transport
>> + * types respectively) are present in libxl_device_disk.
>> + */
>> +#define LIBXL_HAVE_DEVICE_DISK_SPECIFICATION 1
>> +
>>   /*
>>    * libxl ABI compatibility
>>    *
>> diff --git a/tools/libs/light/libxl_device.c b/tools/libs/light/libxl_device.c
>> index e6025d135e..a75c21d433 100644
>> --- a/tools/libs/light/libxl_device.c
>> +++ b/tools/libs/light/libxl_device.c
>> @@ -289,9 +289,16 @@ static int disk_try_backend(disk_try_backend_args
>> *a,
>>                               libxl_disk_backend backend)
>>    {
>>       libxl__gc *gc = a->gc;
>> +    libxl_disk_specification specification = a->disk->specification;
>>       /* returns 0 (ie, DISK_BACKEND_UNKNOWN) on failure, or
>>        * backend on success */
>>
>> +    if ((specification == LIBXL_DISK_SPECIFICATION_VIRTIO &&
>> +         backend != LIBXL_DISK_BACKEND_STANDALONE) ||
>> +        (specification != LIBXL_DISK_SPECIFICATION_VIRTIO &&
>> +         backend == LIBXL_DISK_BACKEND_STANDALONE))
>> +        goto bad_specification;
>> +
>>       switch (backend) {
>>       case LIBXL_DISK_BACKEND_PHY:
>>           if (a->disk->format != LIBXL_DISK_FORMAT_RAW) {
>> @@ -329,6 +336,29 @@ static int disk_try_backend(disk_try_backend_args
>> *a,
>>           if (a->disk->script) goto bad_script;
>>           return backend;
>>
>> +    case LIBXL_DISK_BACKEND_STANDALONE:
>> +        if (a->disk->format != LIBXL_DISK_FORMAT_RAW)
>> +            goto bad_format;
>> +
>> +        if (a->disk->script)
>> +            goto bad_script;
>> +
>> +        if (libxl_defbool_val(a->disk->colo_enable))
>> +            goto bad_colo;
>> +
>> +        if (a->disk->backend_domid != LIBXL_TOOLSTACK_DOMID) {
>> +            LOG(DEBUG, "Disk vdev=%s, is using a storage driver domain, "
>> +                       "skipping physical device check", a->disk->vdev);
>> +            return backend;
>> +        }
>> +
>> +        if (libxl__try_phy_backend(a->stab.st_mode))
>> +            return backend;
>> +
>> +        LOG(DEBUG, "Disk vdev=%s, backend standalone unsuitable as phys
>> path not a "
>> +                   "block device", a->disk->vdev);
>> +        return 0;
>> +
>>       default:
>>           LOG(DEBUG, "Disk vdev=%s, backend %d unknown", a->disk->vdev,
>> backend);
>>           return 0;
>> @@ -352,6 +382,12 @@ static int disk_try_backend(disk_try_backend_args
>> *a,
>>       LOG(DEBUG, "Disk vdev=%s, backend %s not compatible with colo",
>>           a->disk->vdev, libxl_disk_backend_to_string(backend));
>>       return 0;
>> +
>> + bad_specification:
>> +    LOG(DEBUG, "Disk vdev=%s, backend %s not compatible with
>> specification %s",
>> +        a->disk->vdev, libxl_disk_backend_to_string(backend),
>> +        libxl_disk_specification_to_string(specification));
>> +    return 0;
>>   }
>>
>>   int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
>> @@ -376,8 +412,9 @@ int libxl__device_disk_set_backend(libxl__gc *gc,
>> libxl_device_disk *disk) {
>>       a.gc = gc;
>>       a.disk = disk;
>>
>> -    LOG(DEBUG, "Disk vdev=%s spec.backend=%s", disk->vdev,
>> -               libxl_disk_backend_to_string(disk->backend));
>> +    LOG(DEBUG, "Disk vdev=%s spec.backend=%s specification=%s", disk-
>>> vdev,
>> +               libxl_disk_backend_to_string(disk->backend),
>> +               libxl_disk_specification_to_string(disk->specification));
>>
>>       if (disk->format == LIBXL_DISK_FORMAT_EMPTY) {
>>           if (!disk->is_cdrom) {
>> @@ -392,7 +429,8 @@ int libxl__device_disk_set_backend(libxl__gc *gc,
>> libxl_device_disk *disk) {
>>           }
>>           memset(&a.stab, 0, sizeof(a.stab));
>>       } else if ((disk->backend == LIBXL_DISK_BACKEND_UNKNOWN ||
>> -                disk->backend == LIBXL_DISK_BACKEND_PHY) &&
>> +                disk->backend == LIBXL_DISK_BACKEND_PHY ||
>> +                disk->backend == LIBXL_DISK_BACKEND_STANDALONE) &&
>>                  disk->backend_domid == LIBXL_TOOLSTACK_DOMID &&
>>                  !disk->script) {
>>           if (stat(disk->pdev_path, &a.stab)) {
>> @@ -408,7 +446,8 @@ int libxl__device_disk_set_backend(libxl__gc *gc,
>> libxl_device_disk *disk) {
>>           ok=
>>               disk_try_backend(&a, LIBXL_DISK_BACKEND_PHY) ?:
>>               disk_try_backend(&a, LIBXL_DISK_BACKEND_QDISK) ?:
>> -            disk_try_backend(&a, LIBXL_DISK_BACKEND_TAP);
>> +            disk_try_backend(&a, LIBXL_DISK_BACKEND_TAP) ?:
>> +            disk_try_backend(&a, LIBXL_DISK_BACKEND_STANDALONE);
>>           if (ok)
>>               LOG(DEBUG, "Disk vdev=%s, using backend %s",
>>                          disk->vdev,
>> @@ -441,10 +480,25 @@ char
>> *libxl__device_disk_string_of_backend(libxl_disk_backend backend)
>>           case LIBXL_DISK_BACKEND_QDISK: return "qdisk";
>>           case LIBXL_DISK_BACKEND_TAP: return "phy";
>>           case LIBXL_DISK_BACKEND_PHY: return "phy";
>> +        case LIBXL_DISK_BACKEND_STANDALONE: return "standalone";
>> +        default: return NULL;
>> +    }
>> +}
>> +
>> +char *libxl__device_disk_string_of_specification(libxl_disk_specification
>> specification)
>> +{
>> +    switch (specification) {
>> +        case LIBXL_DISK_SPECIFICATION_XEN: return "xen";
>> +        case LIBXL_DISK_SPECIFICATION_VIRTIO: return "virtio";
>>           default: return NULL;
>>       }
>>   }
>>
>> +char *libxl__device_disk_string_of_transport(libxl_disk_transport transport)
>> +{
>> +    return (transport == LIBXL_DISK_TRANSPORT_MMIO ? "mmio" : NULL);
>> +}
>> +
>>   const char *libxl__qemu_disk_format_string(libxl_disk_format format)
>>   {
>>       switch (format) {
>> diff --git a/tools/libs/light/libxl_disk.c b/tools/libs/light/libxl_disk.c
>> index 9da2b2ed27..ea3623dd6f 100644
>> --- a/tools/libs/light/libxl_disk.c
>> +++ b/tools/libs/light/libxl_disk.c
>> @@ -164,6 +164,30 @@ static int libxl__device_disk_setdefault(libxl__gc *gc,
>> uint32_t domid,
>>       rc = libxl__resolve_domid(gc, disk->backend_domname, &disk-
>>> backend_domid);
>>       if (rc < 0) return rc;
>>
>> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_UNKNOWN)
>> +        disk->specification = LIBXL_DISK_SPECIFICATION_XEN;
>> +
>> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_XEN &&
>> +        disk->transport != LIBXL_DISK_TRANSPORT_UNKNOWN) {
>> +        LOGD(ERROR, domid, "Transport is only supported for specification
>> virtio");
>> +        return ERROR_INVAL;
>> +    }
>> +
>> +    /* Force transport mmio for specification virtio for now */
>> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
>> +        if (!(disk->transport == LIBXL_DISK_TRANSPORT_UNKNOWN ||
>> +              disk->transport == LIBXL_DISK_TRANSPORT_MMIO)) {
>> +            LOGD(ERROR, domid, "Unsupported transport for specification
>> virtio");
>> +            return ERROR_INVAL;
>> +        }
>> +        disk->transport = LIBXL_DISK_TRANSPORT_MMIO;
>> +    }
>> +
>> +    if (hotplug && disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
>> +        LOGD(ERROR, domid, "Hotplug isn't supported for specification virtio");
>> +        return ERROR_FAIL;
>> +    }
>> +
>>       /* Force Qdisk backend for CDROM devices of guests with a device model.
>> */
>>       if (disk->is_cdrom != 0 &&
>>           libxl__domain_type(gc, domid) == LIBXL_DOMAIN_TYPE_HVM) {
>> @@ -205,6 +229,9 @@ static int libxl__device_from_disk(libxl__gc *gc,
>> uint32_t domid,
>>           case LIBXL_DISK_BACKEND_QDISK:
>>               device->backend_kind = LIBXL__DEVICE_KIND_QDISK;
>>               break;
>> +        case LIBXL_DISK_BACKEND_STANDALONE:
>> +            device->backend_kind = LIBXL__DEVICE_KIND_VIRTIO_DISK;
>> +            break;
>>           default:
>>               LOGD(ERROR, domid, "Unrecognized disk backend type: %d",
>>                    disk->backend);
>> @@ -213,7 +240,8 @@ static int libxl__device_from_disk(libxl__gc *gc,
>> uint32_t domid,
>>
>>       device->domid = domid;
>>       device->devid = devid;
>> -    device->kind  = LIBXL__DEVICE_KIND_VBD;
>> +    device->kind = disk->backend == LIBXL_DISK_BACKEND_STANDALONE ?
>> +        LIBXL__DEVICE_KIND_VIRTIO_DISK : LIBXL__DEVICE_KIND_VBD;
>>
>>       return 0;
>>   }
>> @@ -331,7 +359,14 @@ static void device_disk_add(libxl__egc *egc,
>> uint32_t domid,
>>
>>                   assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
>>                   break;
>> +            case LIBXL_DISK_BACKEND_STANDALONE:
>> +                dev = disk->pdev_path;
>> +
>> +                flexarray_append(back, "params");
>> +                flexarray_append(back, dev);
>>
>> +                assert(device->backend_kind ==
>> LIBXL__DEVICE_KIND_VIRTIO_DISK);
>> +                break;
>>               case LIBXL_DISK_BACKEND_TAP:
>>                   LOG(ERROR, "blktap is not supported");
>>                   rc = ERROR_FAIL;
>> @@ -387,6 +422,14 @@ static void device_disk_add(libxl__egc *egc,
>> uint32_t domid,
>>           flexarray_append_pair(back, "discard-enable",
>>                                 libxl_defbool_val(disk->discard_enable) ?
>>                                 "1" : "0");
>> +        flexarray_append(back, "specification");
>> +        flexarray_append(back, libxl__device_disk_string_of_specification(disk-
>>> specification));
>> +        if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
>> +            flexarray_append(back, "transport");
>> +            flexarray_append(back, libxl__device_disk_string_of_transport(disk-
>>> transport));
>> +            flexarray_append_pair(back, "base", GCSPRINTF("%"PRIu64, disk-
>>> base));
>> +            flexarray_append_pair(back, "irq", GCSPRINTF("%u", disk->irq));
>> +        }
>>
>>           flexarray_append(front, "backend-id");
>>           flexarray_append(front, GCSPRINTF("%d", disk->backend_domid));
>> @@ -535,6 +578,53 @@ static int libxl__disk_from_xenstore(libxl__gc *gc,
>> const char *libxl_path,
>>       }
>>       libxl_string_to_backend(ctx, tmp, &(disk->backend));
>>
>> +    tmp = libxl__xs_read(gc, XBT_NULL,
>> +                         GCSPRINTF("%s/specification", libxl_path));
>> +    if (!tmp) {
>> +        LOG(DEBUG, "Missing xenstore node %s/specification, assuming
>> specification xen", libxl_path);
>> +        disk->specification = LIBXL_DISK_SPECIFICATION_XEN;
>> +    } else {
>> +        rc = libxl_disk_specification_from_string(tmp, &disk->specification);
>> +        if (rc) {
>> +            LOG(ERROR, "Unable to parse xenstore node %s/specification",
>> libxl_path);
>> +            goto cleanup;
>> +        }
>> +    }
>> +
>> +    if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
>> +        tmp = libxl__xs_read(gc, XBT_NULL,
>> +                             GCSPRINTF("%s/transport", libxl_path));
>> +        if (!tmp) {
>> +            LOG(ERROR, "Missing xenstore node %s/transport", libxl_path);
>> +            goto cleanup;
>> +        }
>> +        rc = libxl_disk_transport_from_string(tmp, &disk->transport);
>> +        if (rc) {
>> +            LOG(ERROR, "Unable to parse xenstore node %s/transport",
>> libxl_path);
>> +            goto cleanup;
>> +        }
>> +        if (disk->transport != LIBXL_DISK_TRANSPORT_MMIO) {
>> +            LOG(ERROR, "Only transport mmio is expected for specification
>> virtio");
>> +            goto cleanup;
>> +        }
>> +
>> +        tmp = libxl__xs_read(gc, XBT_NULL,
>> +                             GCSPRINTF("%s/base", libxl_path));
>> +        if (!tmp) {
>> +            LOG(ERROR, "Missing xenstore node %s/base", libxl_path);
>> +            goto cleanup;
>> +        }
>> +        disk->base = strtoul(tmp, NULL, 10);
>> +
>> +        tmp = libxl__xs_read(gc, XBT_NULL,
>> +                             GCSPRINTF("%s/irq", libxl_path));
>> +        if (!tmp) {
>> +            LOG(ERROR, "Missing xenstore node %s/irq", libxl_path);
>> +            goto cleanup;
>> +        }
>> +        disk->irq = strtoul(tmp, NULL, 10);
>> +    }
>> +
>>       disk->vdev = xs_read(ctx->xsh, XBT_NULL,
>>                            GCSPRINTF("%s/dev", libxl_path), &len);
>>       if (!disk->vdev) {
>> @@ -578,6 +668,42 @@ cleanup:
>>       return rc;
>>   }
>>
>> +static int libxl__device_disk_get_path(libxl__gc *gc, uint32_t domid,
>> +                                       char **path)
>> +{
>> +    const char *xen_dir, *virtio_dir;
>> +    char *xen_path, *virtio_path;
>> +    int rc;
>> +
>> +    /* default path */
>> +    xen_path = GCSPRINTF("%s/device/%s",
>> +                         libxl__xs_libxl_path(gc, domid),
>> +                         libxl__device_kind_to_string(LIBXL__DEVICE_KIND_VBD));
>> +
>> +    rc = libxl__xs_read_checked(gc, XBT_NULL, xen_path, &xen_dir);
>> +    if (rc)
>> +        return rc;
>> +
>> +    virtio_path = GCSPRINTF("%s/device/%s",
>> +                            libxl__xs_libxl_path(gc, domid),
>> +
>> libxl__device_kind_to_string(LIBXL__DEVICE_KIND_VIRTIO_DISK));
>> +
>> +    rc = libxl__xs_read_checked(gc, XBT_NULL, virtio_path, &virtio_dir);
>> +    if (rc)
>> +        return rc;
>> +
>> +    if (xen_dir && virtio_dir) {
>> +        LOGD(ERROR, domid, "Invalid configuration, both xen and virtio paths
>> are present");
>> +        return ERROR_INVAL;
>> +    } else if (virtio_dir) {
>> +        *path = virtio_path;
>> +    } else {
>> +        *path = xen_path;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>>   int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid,
>>                                 const char *vdev, libxl_device_disk *disk)
>>   {
>> @@ -591,10 +717,12 @@ int libxl_vdev_to_device_disk(libxl_ctx *ctx,
>> uint32_t domid,
>>
>>       libxl_device_disk_init(disk);
>>
>> -    libxl_path = libxl__domain_device_libxl_path(gc, domid, devid,
>> -                                                 LIBXL__DEVICE_KIND_VBD);
>> +    rc = libxl__device_disk_get_path(gc, domid, &libxl_path);
>> +    if (rc)
>> +        return rc;
>>
>> -    rc = libxl__disk_from_xenstore(gc, libxl_path, devid, disk);
>> +    rc = libxl__disk_from_xenstore(gc, GCSPRINTF("%s/%d", libxl_path, devid),
>> +                                   devid, disk);
>>
>>       GC_FREE;
>>       return rc;
>> @@ -608,16 +736,19 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx,
>> uint32_t domid,
>>       char *fe_path, *libxl_path;
>>       char *val;
>>       int rc;
>> +    libxl__device_kind kind;
>>
>>       diskinfo->backend = NULL;
>>
>>       diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
>>
>> -    /* tap devices entries in xenstore are written as vbd devices. */
>> +    /* tap devices entries in xenstore are written as vbd/virtio_disk devices.
>> */
>> +    kind = disk->backend == LIBXL_DISK_BACKEND_STANDALONE ?
>> +        LIBXL__DEVICE_KIND_VIRTIO_DISK : LIBXL__DEVICE_KIND_VBD;
>>       fe_path = libxl__domain_device_frontend_path(gc, domid, diskinfo-
>>> devid,
>> -                                                 LIBXL__DEVICE_KIND_VBD);
>> +                                                 kind);
>>       libxl_path = libxl__domain_device_libxl_path(gc, domid, diskinfo->devid,
>> -                                                 LIBXL__DEVICE_KIND_VBD);
>> +                                                 kind);
>>       diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
>>                                   GCSPRINTF("%s/backend", libxl_path), NULL);
>>       if (!diskinfo->backend) {
>> @@ -1421,6 +1552,7 @@ LIBXL_DEFINE_DEVICE_LIST(disk)
>>   #define libxl__device_disk_update_devid NULL
>>
>>   DEFINE_DEVICE_TYPE_STRUCT(disk, VBD, disks,
>> +    .get_path    = libxl__device_disk_get_path,
>>       .merge       = libxl_device_disk_merge,
>>       .dm_needed   = libxl_device_disk_dm_needed,
>>       .from_xenstore = (device_from_xenstore_fn_t)libxl__disk_from_xenstore,
>> diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h
>> index bdef5a605e..cb9e8b3b8b 100644
>> --- a/tools/libs/light/libxl_internal.h
>> +++ b/tools/libs/light/libxl_internal.h
>> @@ -1493,6 +1493,8 @@ _hidden char *
>> libxl__domain_pvcontrol_read(libxl__gc *gc,
>>
>>   /* from xl_device */
>>   _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend
>> backend);
>> +_hidden char
>> *libxl__device_disk_string_of_specification(libxl_disk_specification
>> specification);
>> +_hidden char *libxl__device_disk_string_of_transport(libxl_disk_transport
>> transport);
>>   _hidden char *libxl__device_disk_string_of_format(libxl_disk_format
>> format);
>>   _hidden const char *libxl__qemu_disk_format_string(libxl_disk_format
>> format);
>>   _hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk*);
>> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
>> index f3ceb38c9e..d634f304cd 100644
>> --- a/tools/libs/light/libxl_types.idl
>> +++ b/tools/libs/light/libxl_types.idl
>> @@ -130,6 +130,18 @@ libxl_disk_backend = Enumeration("disk_backend",
>> [
>>       (1, "PHY"),
>>       (2, "TAP"),
>>       (3, "QDISK"),
>> +    (4, "STANDALONE"), # Only relying on the Xenstore data
>> +    ])
>> +
>> +libxl_disk_specification = Enumeration("disk_specification", [
>> +    (0, "UNKNOWN"),
>> +    (1, "XEN"),
>> +    (2, "VIRTIO"),
>> +    ])
>> +
>> +libxl_disk_transport = Enumeration("disk_transport", [
>> +    (0, "UNKNOWN"),
>> +    (1, "MMIO"),
>>       ])
>>
>>   libxl_nic_type = Enumeration("nic_type", [
>> @@ -706,6 +718,12 @@ libxl_device_disk = Struct("device_disk", [
>>       ("is_cdrom", integer),
>>       ("direct_io_safe", bool),
>>       ("discard_enable", libxl_defbool),
>> +    ("specification", libxl_disk_specification),
>> +    ("transport", libxl_disk_transport),
>> +    # Note that virtio-mmio parameters (irq and base) are for internal use
>> +    # by libxl and can't be modified.
>> +    ("irq", uint32),
>> +    ("base", uint64),
>>       # Note that the COLO configuration settings should be considered unstable.
>>       # They may change incompatibly in future versions of Xen.
>>       ("colo_enable", libxl_defbool),
>> diff --git a/tools/libs/light/libxl_types_internal.idl
>> b/tools/libs/light/libxl_types_internal.idl
>> index 3593e21dbb..8f71980aec 100644
>> --- a/tools/libs/light/libxl_types_internal.idl
>> +++ b/tools/libs/light/libxl_types_internal.idl
>> @@ -32,6 +32,7 @@ libxl__device_kind = Enumeration("device_kind", [
>>       (14, "PVCALLS"),
>>       (15, "VSND"),
>>       (16, "VINPUT"),
>> +    (17, "VIRTIO_DISK"),
>>       ])
>>
>>   libxl__console_backend = Enumeration("console_backend", [
>> diff --git a/tools/libs/light/libxl_utils.c b/tools/libs/light/libxl_utils.c
>> index e5e6b2da96..e403bd9bcf 100644
>> --- a/tools/libs/light/libxl_utils.c
>> +++ b/tools/libs/light/libxl_utils.c
>> @@ -297,6 +297,8 @@ int libxl_string_to_backend(libxl_ctx *ctx, char *s,
>> libxl_disk_backend *backend
>>           *backend = LIBXL_DISK_BACKEND_TAP;
>>       } else if (!strcmp(s, "qdisk")) {
>>           *backend = LIBXL_DISK_BACKEND_QDISK;
>> +    } else if (!strcmp(s, "standalone")) {
>> +        *backend = LIBXL_DISK_BACKEND_STANDALONE;
>>       } else if (!strcmp(s, "tap")) {
>>           p = strchr(s, ':');
>>           if (!p) {
>> diff --git a/tools/libs/util/libxlu_disk_l.c b/tools/libs/util/libxlu_disk_l.c
>> index 32d4b74b58..0b59723b71 100644
>> --- a/tools/libs/util/libxlu_disk_l.c
>> +++ b/tools/libs/util/libxlu_disk_l.c
>> @@ -549,8 +549,8 @@ static void yynoreturn yy_fatal_error ( const char*
>> msg , yyscan_t yyscanner );
>>   	yyg->yy_hold_char = *yy_cp; \
>>   	*yy_cp = '\0'; \
>>   	yyg->yy_c_buf_p = yy_cp;
>> -#define YY_NUM_RULES 36
>> -#define YY_END_OF_BUFFER 37
>> +#define YY_NUM_RULES 37
>> +#define YY_END_OF_BUFFER 38
>>   /* This struct is not used in this scanner,
>>      but its presence is necessary. */
>>   struct yy_trans_info
>> @@ -558,74 +558,77 @@ struct yy_trans_info
>>   	flex_int32_t yy_verify;
>>   	flex_int32_t yy_nxt;
>>   	};
>> -static const flex_int16_t yy_acclist[575] =
>> +static const flex_int16_t yy_acclist[594] =
>>       {   0,
>> -       35,   35,   37,   33,   34,   36, 8193,   33,   34,   36,
>> -    16385, 8193,   33,   36,16385,   33,   34,   36,   34,   36,
>> -       33,   34,   36,   33,   34,   36,   33,   34,   36,   33,
>> -       34,   36,   33,   34,   36,   33,   34,   36,   33,   34,
>> -       36,   33,   34,   36,   33,   34,   36,   33,   34,   36,
>> -       33,   34,   36,   33,   34,   36,   33,   34,   36,   33,
>> -       34,   36,   33,   34,   36,   33,   34,   36,   35,   36,
>> -       36,   33,   33, 8193,   33, 8193,   33,16385, 8193,   33,
>> -     8193,   33,   33, 8224,   33,16416,   33,   33,   33,   33,
>> -       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
>> -
>> -       33,   33,   33,   33,   33,   33,   33,   33,   33,   35,
>> -     8193,   33, 8193,   33, 8193, 8224,   33, 8224,   33, 8224,
>> -       23,   33,   33,   33,   33,   33,   33,   33,   33,   33,
>> -       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
>> -       33,   33,   33,   33,   33, 8224,   33, 8224,   33, 8224,
>> -       23,   33,   33,   28, 8224,   33,16416,   33,   33,   15,
>> -       33,   33,   33,   33,   33,   33,   33,   33,   33, 8217,
>> -     8224,   33,16409,16416,   33,   33,   31, 8224,   33,16416,
>> -       33, 8216, 8224,   33,16408,16416,   33,   33, 8219, 8224,
>> -       33,16411,16416,   33,   33,   33,   33,   33,   28, 8224,
>> -
>> -       33,   28, 8224,   33,   28,   33,   28, 8224,   33,    3,
>> -       33,   15,   33,   33,   33,   33,   33,   30, 8224,   33,
>> -    16416,   33,   33,   33, 8217, 8224,   33, 8217, 8224,   33,
>> -     8217,   33, 8217, 8224,   33,   33,   31, 8224,   33,   31,
>> -     8224,   33,   31,   33,   31, 8224, 8216, 8224,   33, 8216,
>> -     8224,   33, 8216,   33, 8216, 8224,   33, 8219, 8224,   33,
>> -     8219, 8224,   33, 8219,   33, 8219, 8224,   33,   33,   10,
>> -       33,   33,   28, 8224,   33,   28, 8224,   33,   28, 8224,
>> -       28,   33,   28,   33,    3,   33,   33,   33,   33,   33,
>> -       33,   33,   30, 8224,   33,   30, 8224,   33,   30,   33,
>> -
>> -       30, 8224,   33,   33,   29, 8224,   33,16416, 8217, 8224,
>> -       33, 8217, 8224,   33, 8217, 8224, 8217,   33, 8217,   33,
>> -       33,   31, 8224,   33,   31, 8224,   33,   31, 8224,   31,
>> -       33,   31, 8216, 8224,   33, 8216, 8224,   33, 8216, 8224,
>> -     8216,   33, 8216,   33, 8219, 8224,   33, 8219, 8224,   33,
>> -     8219, 8224, 8219,   33, 8219,   33,   33,   10,   23,   10,
>> -        7,   33,   33,   33,   33,   33,   33,   33,   13,   33,
>> -       30, 8224,   33,   30, 8224,   33,   30, 8224,   30,   33,
>> -       30,    2,   33,   29, 8224,   33,   29, 8224,   33,   29,
>> -       33,   29, 8224,   16,   33,   33,   11,   33,   22,   10,
>> -
>> -       10,   23,    7,   23,    7,   33,    8,   33,   33,   33,
>> -       33,    6,   33,   13,   33,    2,   23,    2,   33,   29,
>> -     8224,   33,   29, 8224,   33,   29, 8224,   29,   33,   29,
>> -       16,   33,   33,   11,   23,   11,   26, 8224,   33,16416,
>> -       22,   23,   22,    7,    7,   23,   33,    8,   23,    8,
>> -       33,   33,   33,   33,    6,   23,    6,    6,   23,    6,
>> -       23,   33,    2,    2,   23,   33,   33,   11,   11,   23,
>> -       26, 8224,   33,   26, 8224,   33,   26,   33,   26, 8224,
>> -       22,   23,   33,    8,    8,   23,   33,   33,   17,   18,
>> -        6,    6,   23,    6,    6,   33,   33,   14,   33,   26,
>> -
>> -     8224,   33,   26, 8224,   33,   26, 8224,   26,   33,   26,
>> -       33,   33,   33,   17,   23,   17,   18,   23,   18,    6,
>> -        6,   33,   33,   14,   33,   20,    9,   19,   17,   17,
>> -       23,   18,   18,   23,    6,    5,    6,   33,   21,   20,
>> -       23,   20,    9,   23,    9,   19,   23,   19,    4,    6,
>> -        5,    6,   33,   21,   23,   21,   20,   20,   23,    9,
>> -        9,   23,   19,   19,   23,    4,    6,   12,   33,   21,
>> -       21,   23,   12,   33
>> +       36,   36,   38,   34,   35,   37, 8193,   34,   35,   37,
>> +    16385, 8193,   34,   37,16385,   34,   35,   37,   35,   37,
>> +       34,   35,   37,   34,   35,   37,   34,   35,   37,   34,
>> +       35,   37,   34,   35,   37,   34,   35,   37,   34,   35,
>> +       37,   34,   35,   37,   34,   35,   37,   34,   35,   37,
>> +       34,   35,   37,   34,   35,   37,   34,   35,   37,   34,
>> +       35,   37,   34,   35,   37,   34,   35,   37,   36,   37,
>> +       37,   34,   34, 8193,   34, 8193,   34,16385, 8193,   34,
>> +     8193,   34,   34, 8225,   34,16417,   34,   34,   34,   34,
>> +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
>> +
>> +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
>> +       36, 8193,   34, 8193,   34, 8193, 8225,   34, 8225,   34,
>> +     8225,   24,   34,   34,   34,   34,   34,   34,   34,   34,
>> +       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
>> +       34,   34,   34,   34,   34,   34,   34, 8225,   34, 8225,
>> +       34, 8225,   24,   34,   34,   29, 8225,   34,16417,   34,
>> +       34,   16,   34,   34,   34,   34,   34,   34,   34,   34,
>> +       34, 8218, 8225,   34,16410,16417,   34,   34,   32, 8225,
>> +       34,16417,   34, 8217, 8225,   34,16409,16417,   34,   34,
>> +       34, 8220, 8225,   34,16412,16417,   34,   34,   34,   34,
>> +
>> +       34,   29, 8225,   34,   29, 8225,   34,   29,   34,   29,
>> +     8225,   34,    3,   34,   16,   34,   34,   34,   34,   34,
>> +       31, 8225,   34,16417,   34,   34,   34, 8218, 8225,   34,
>> +     8218, 8225,   34, 8218,   34, 8218, 8225,   34,   34,   32,
>> +     8225,   34,   32, 8225,   34,   32,   34,   32, 8225, 8217,
>> +     8225,   34, 8217, 8225,   34, 8217,   34, 8217, 8225,   34,
>> +       34, 8220, 8225,   34, 8220, 8225,   34, 8220,   34, 8220,
>> +     8225,   34,   34,   11,   34,   34,   29, 8225,   34,   29,
>> +     8225,   34,   29, 8225,   29,   34,   29,   34,    3,   34,
>> +       34,   34,   34,   34,   34,   34,   31, 8225,   34,   31,
>> +
>> +     8225,   34,   31,   34,   31, 8225,   34,   34,   30, 8225,
>> +       34,16417, 8218, 8225,   34, 8218, 8225,   34, 8218, 8225,
>> +     8218,   34, 8218,   34,   34,   32, 8225,   34,   32, 8225,
>> +       34,   32, 8225,   32,   34,   32, 8217, 8225,   34, 8217,
>> +     8225,   34, 8217, 8225, 8217,   34, 8217,   34,   34, 8220,
>> +     8225,   34, 8220, 8225,   34, 8220, 8225, 8220,   34, 8220,
>> +       34,   34,   11,   24,   11,    7,   34,   34,   34,   34,
>> +       34,   34,   34,   14,   34,   31, 8225,   34,   31, 8225,
>> +       34,   31, 8225,   31,   34,   31,    2,   34,   30, 8225,
>> +       34,   30, 8225,   34,   30,   34,   30, 8225,   17,   34,
>> +
>> +       34,   12,   34,   34,   23,   11,   11,   24,    7,   24,
>> +        7,   34,    8,   34,   34,   34,   34,    6,   34,   14,
>> +       34,    2,   24,    2,   34,   30, 8225,   34,   30, 8225,
>> +       34,   30, 8225,   30,   34,   30,   17,   34,   34,   12,
>> +       24,   12,   34,   27, 8225,   34,16417,   23,   24,   23,
>> +        7,    7,   24,   34,    8,   24,    8,   34,   34,   34,
>> +       34,    6,   24,    6,    6,   24,    6,   24,   34,    2,
>> +        2,   24,   34,   34,   12,   12,   24,   34,   27, 8225,
>> +       34,   27, 8225,   34,   27,   34,   27, 8225,   23,   24,
>> +       34,    8,    8,   24,   34,   34,   18,   19,    6,    6,
>> +
>> +       24,    6,    6,   34,   34,   15,   34,   34,   27, 8225,
>> +       34,   27, 8225,   34,   27, 8225,   27,   34,   27,   34,
>> +       34,   34,   18,   24,   18,   19,   24,   19,    6,    6,
>> +       34,   34,   15,   34,   34,   21,    9,   20,   18,   18,
>> +       24,   19,   19,   24,    6,    5,    6,   34,   22,   34,
>> +       21,   24,   21,    9,   24,    9,   20,   24,   20,    4,
>> +        6,    5,    6,   34,   22,   24,   22,   34,   21,   21,
>> +       24,    9,    9,   24,   20,   20,   24,    4,    6,   13,
>> +       34,   22,   22,   24,   10,   13,   34,   10,   24,   10,
>> +       10,   10,   24
>> +
>>       } ;
>>
>> -static const flex_int16_t yy_accept[356] =
>> +static const flex_int16_t yy_accept[373] =
>>       {   0,
>>           1,    1,    1,    2,    3,    4,    7,   12,   16,   19,
>>          21,   24,   27,   30,   33,   36,   39,   42,   45,   48,
>> @@ -633,39 +636,41 @@ static const flex_int16_t yy_accept[356] =
>>          74,   76,   79,   81,   82,   83,   84,   87,   87,   88,
>>          89,   90,   91,   92,   93,   94,   95,   96,   97,   98,
>>          99,  100,  101,  102,  103,  104,  105,  106,  107,  108,
>> -      109,  110,  111,  113,  115,  116,  118,  120,  121,  122,
>> +      109,  110,  111,  112,  114,  116,  117,  119,  121,  122,
>>         123,  124,  125,  126,  127,  128,  129,  130,  131,  132,
>>         133,  134,  135,  136,  137,  138,  139,  140,  141,  142,
>> -      143,  144,  145,  146,  148,  150,  151,  152,  153,  154,
>> -
>> -      158,  159,  160,  162,  163,  164,  165,  166,  167,  168,
>> -      169,  170,  175,  176,  177,  181,  182,  187,  188,  189,
>> -      194,  195,  196,  197,  198,  199,  202,  205,  207,  209,
>> -      210,  212,  214,  215,  216,  217,  218,  222,  223,  224,
>> -      225,  228,  231,  233,  235,  236,  237,  240,  243,  245,
>> -      247,  250,  253,  255,  257,  258,  261,  264,  266,  268,
>> -      269,  270,  271,  272,  273,  276,  279,  281,  283,  284,
>> -      285,  287,  288,  289,  290,  291,  292,  293,  296,  299,
>> -      301,  303,  304,  305,  309,  312,  315,  317,  319,  320,
>> -      321,  322,  325,  328,  330,  332,  333,  336,  339,  341,
>> -
>> -      343,  344,  345,  348,  351,  353,  355,  356,  357,  358,
>> -      360,  361,  362,  363,  364,  365,  366,  367,  368,  369,
>> -      371,  374,  377,  379,  381,  382,  383,  384,  387,  390,
>> -      392,  394,  396,  397,  398,  399,  400,  401,  403,  405,
>> -      406,  407,  408,  409,  410,  411,  412,  413,  414,  416,
>> -      418,  419,  420,  423,  426,  428,  430,  431,  433,  434,
>> -      436,  437,  441,  443,  444,  445,  447,  448,  450,  451,
>> -      452,  453,  454,  455,  457,  458,  460,  462,  463,  464,
>> -      466,  467,  468,  469,  471,  474,  477,  479,  481,  483,
>> -      484,  485,  487,  488,  489,  490,  491,  492,  494,  495,
>> -
>> -      496,  497,  498,  500,  503,  506,  508,  510,  511,  512,
>> -      513,  514,  516,  517,  519,  520,  521,  522,  523,  524,
>> -      526,  527,  528,  529,  530,  532,  533,  535,  536,  538,
>> -      539,  540,  542,  543,  545,  546,  548,  549,  551,  553,
>> -      554,  556,  557,  558,  560,  561,  563,  564,  566,  568,
>> -      570,  571,  573,  575,  575
>> +      143,  144,  145,  146,  147,  148,  150,  152,  153,  154,
>> +
>> +      155,  156,  160,  161,  162,  164,  165,  166,  167,  168,
>> +      169,  170,  171,  172,  177,  178,  179,  183,  184,  189,
>> +      190,  191,  192,  197,  198,  199,  200,  201,  202,  205,
>> +      208,  210,  212,  213,  215,  217,  218,  219,  220,  221,
>> +      225,  226,  227,  228,  231,  234,  236,  238,  239,  240,
>> +      243,  246,  248,  250,  253,  256,  258,  260,  261,  262,
>> +      265,  268,  270,  272,  273,  274,  275,  276,  277,  280,
>> +      283,  285,  287,  288,  289,  291,  292,  293,  294,  295,
>> +      296,  297,  300,  303,  305,  307,  308,  309,  313,  316,
>> +      319,  321,  323,  324,  325,  326,  329,  332,  334,  336,
>> +
>> +      337,  340,  343,  345,  347,  348,  349,  350,  353,  356,
>> +      358,  360,  361,  362,  363,  365,  366,  367,  368,  369,
>> +      370,  371,  372,  373,  374,  376,  379,  382,  384,  386,
>> +      387,  388,  389,  392,  395,  397,  399,  401,  402,  403,
>> +      404,  405,  406,  407,  409,  411,  412,  413,  414,  415,
>> +      416,  417,  418,  419,  420,  422,  424,  425,  426,  429,
>> +      432,  434,  436,  437,  439,  440,  442,  443,  444,  448,
>> +      450,  451,  452,  454,  455,  457,  458,  459,  460,  461,
>> +      462,  464,  465,  467,  469,  470,  471,  473,  474,  475,
>> +      476,  478,  479,  482,  485,  487,  489,  491,  492,  493,
>> +
>> +      495,  496,  497,  498,  499,  500,  502,  503,  504,  505,
>> +      506,  508,  509,  512,  515,  517,  519,  520,  521,  522,
>> +      523,  525,  526,  528,  529,  530,  531,  532,  533,  535,
>> +      536,  537,  538,  539,  540,  542,  543,  545,  546,  548,
>> +      549,  550,  551,  553,  554,  556,  557,  559,  560,  562,
>> +      564,  565,  567,  568,  569,  570,  572,  573,  575,  576,
>> +      578,  580,  582,  583,  585,  586,  588,  590,  591,  592,
>> +      594,  594
>>       } ;
>>
>>   static const YY_CHAR yy_ec[256] =
>> @@ -708,216 +713,224 @@ static const YY_CHAR yy_meta[35] =
>>           1,    1,    1,    1
>>       } ;
>>
>> -static const flex_int16_t yy_base[424] =
>> +static const flex_int16_t yy_base[443] =
>>       {   0,
>> -        0,    0,  901,  900,  902,  897,   33,   36,  905,  905,
>> -       45,   63,   31,   42,   51,   52,  890,   33,   65,   67,
>> -       69,   70,  889,   71,  888,   75,    0,  905,  893,  905,
>> -       91,   94,    0,    0,  103,  886,  112,    0,   89,   98,
>> -      113,   92,  114,   99,  100,   48,  121,  116,  119,   74,
>> -      124,  129,  123,  135,  132,  133,  137,  134,  138,  139,
>> -      141,    0,  155,    0,    0,  164,    0,    0,  849,  142,
>> -      152,  164,  140,  161,  165,  166,  167,  168,  169,  173,
>> -      174,  178,  176,  180,  184,  208,  189,  183,  192,  195,
>> -      215,  191,  193,  223,    0,    0,  905,  208,  204,  236,
>> -
>> -      219,  209,  238,  196,  237,  831,  242,  815,  241,  224,
>> -      243,  261,  244,  259,  277,  266,  286,  250,  288,  298,
>> -      249,  283,  274,  282,  294,  308,    0,  310,    0,  295,
>> -      305,  905,  308,  306,  313,  314,  342,  319,  316,  320,
>> -      331,    0,  349,    0,  342,  344,  356,    0,  358,    0,
>> -      365,    0,  367,    0,  354,  375,    0,  377,    0,  363,
>> -      356,  809,  327,  322,  384,    0,    0,    0,    0,  379,
>> -      905,  382,  384,  386,  390,  372,  392,  403,    0,  410,
>> -        0,  407,  413,  423,  426,    0,    0,    0,    0,  409,
>> -      424,  435,    0,    0,    0,    0,  437,    0,    0,    0,
>> -
>> -        0,  433,  444,    0,    0,    0,    0,  391,  440,  781,
>> -      905,  769,  439,  445,  444,  447,  449,  454,  453,  399,
>> -      464,    0,    0,    0,    0,  757,  465,  476,    0,  478,
>> -        0,  479,  476,  753,  462,  490,  749,  905,  745,  905,
>> -      483,  737,  424,  485,  487,  490,  500,  493,  905,  729,
>> -      905,  502,  518,    0,    0,    0,    0,  905,  498,  721,
>> -      905,  527,  713,    0,  705,  905,  495,  697,  905,  365,
>> -      521,  528,  530,  685,  905,  534,  540,  540,  657,  905,
>> -      537,  542,  650,  905,  553,    0,  557,    0,    0,  551,
>> -      641,  905,  558,  557,  633,  614,  613,  905,  547,  555,
>> -
>> -      563,  565,  569,  584,    0,    0,    0,    0,  583,  570,
>> -      585,  612,  905,  601,  905,  522,  580,  589,  594,  905,
>> -      600,  585,  563,  520,  905,  514,  905,  586,  486,  597,
>> -      480,  441,  905,  416,  905,  345,  905,  334,  905,  601,
>> -      254,  905,  242,  905,  200,  905,  151,  905,  905,  607,
>> -       86,  905,  905,  905,  620,  624,  627,  631,  635,  639,
>> -      643,  647,  651,  655,  659,  663,  667,  671,  675,  679,
>> -      683,  687,  691,  695,  699,  703,  707,  711,  715,  719,
>> -      723,  727,  731,  735,  739,  743,  747,  751,  755,  759,
>> -      763,  767,  771,  775,  779,  783,  787,  791,  795,  799,
>> -
>> -      803,  807,  811,  815,  819,  823,  827,  831,  835,  839,
>> -      843,  847,  851,  855,  859,  863,  867,  871,  875,  879,
>> -      883,  887,  891
>> +        0,    0,  936,  935,  937,  932,   33,   36,  940,  940,
>> +       45,   63,   31,   42,   51,   52,  925,   33,   65,   67,
>> +       69,   70,  924,   71,  923,   75,    0,  940,  928,  940,
>> +       91,   95,    0,    0,  104,  921,  113,    0,   91,   99,
>> +      114,   92,  115,   80,  100,   48,  119,  121,  122,   74,
>> +      123,  128,  131,  129,  125,  133,  135,  136,  137,  143,
>> +      138,  145,    0,  157,    0,    0,  168,    0,    0,  926,
>> +      140,  146,  165,  159,  152,  164,  155,  168,  171,  176,
>> +      177,  170,  180,  175,  184,  188,  212,  191,  185,  192,
>> +      193,  194,  219,  212,  199,  230,    0,    0,  940,  195,
>> +
>> +      200,  239,  235,  197,  246,  225,  226,  919,  244,  918,
>> +      243,  236,  245,  266,  248,  264,  282,  271,  291,  248,
>> +      270,  254,  300,  279,  296,  302,  288,  303,  311,    0,
>> +      315,    0,  311,  318,  940,  313,  319,  208,  313,  344,
>> +      321,  331,  325,  333,    0,  352,    0,  345,  347,  359,
>> +        0,  361,    0,  368,    0,  370,    0,  322,  366,  379,
>> +        0,  381,    0,  359,  357,  923,  382,  384,  392,    0,
>> +        0,    0,    0,  387,  940,  386,  390,  392,  329,  401,
>> +      397,  409,    0,  417,    0,  399,  412,  426,  429,    0,
>> +        0,    0,    0,  412,  427,  438,    0,    0,    0,    0,
>> +
>> +      440,    0,    0,    0,    0,  436,  405,  447,    0,    0,
>> +        0,    0,  438,  443,  922,  940,  921,  442,  450,  449,
>> +      452,  454,  459,  458,  453,  469,    0,    0,    0,    0,
>> +      920,  470,  481,    0,  483,    0,  484,  481,  919,  368,
>> +      467,  495,  918,  940,  917,  940,  488,  916,  479,  490,
>> +      492,  495,  505,  498,  940,  915,  940,  507,  523,    0,
>> +        0,    0,    0,  940,  503,  864,  940,  846,  532,  836,
>> +        0,  824,  940,  516,  796,  940,  513,  530,  536,  538,
>> +      784,  940,  542,  535,  547,  772,  940,  549,  551,  768,
>> +      940,  502,  562,    0,  564,    0,    0,  562,  764,  940,
>> +
>> +      544,  557,  760,  752,  744,  940,  552,  568,  571,  568,
>> +      581,  577,  588,    0,    0,    0,    0,  589,  580,  591,
>> +      736,  940,  728,  940,  601,  602,  597,  599,  940,  603,
>> +      720,  712,  700,  672,  940,  665,  940,  610,  656,  603,
>> +      648,  607,  629,  940,  627,  940,  625,  940,  624,  940,
>> +      607,  574,  940,  614,  572,  940,  491,  940,  433,  940,
>> +      940,  622,  389,  940,  303,  940,  261,  940,  204,  940,
>> +      940,  635,  639,  642,  646,  650,  654,  658,  662,  666,
>> +      670,  674,  678,  682,  686,  690,  694,  698,  702,  706,
>> +      710,  714,  718,  722,  726,  730,  734,  738,  742,  746,
>> +
>> +      750,  754,  758,  762,  766,  770,  774,  778,  782,  786,
>> +      790,  794,  798,  802,  806,  810,  814,  818,  822,  826,
>> +      830,  834,  838,  842,  846,  850,  854,  858,  862,  866,
>> +      870,  874,  878,  882,  886,  890,  894,  898,  902,  906,
>> +      910,  914
>>       } ;
>>
>> -static const flex_int16_t yy_def[424] =
>> +static const flex_int16_t yy_def[443] =
>>       {   0,
>> -      354,    1,  355,  355,  354,  356,  357,  357,  354,  354,
>> -      358,  358,   12,   12,   12,   12,   12,   12,   12,   12,
>> -       12,   12,   12,   12,   12,   12,  359,  354,  356,  354,
>> -      360,  357,  361,  361,  362,   12,  356,  363,   12,   12,
>> -       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
>> +      371,    1,  372,  372,  371,  373,  374,  374,  371,  371,
>> +      375,  375,   12,   12,   12,   12,   12,   12,   12,   12,
>> +       12,   12,   12,   12,   12,   12,  376,  371,  373,  371,
>> +      377,  374,  378,  378,  379,   12,  373,  380,   12,   12,
>>          12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
>> -       12,  359,  360,  361,  361,  364,  365,  365,  354,   12,
>>          12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
>> -       12,   12,   12,   12,   12,  362,   12,   12,   12,   12,
>> -       12,   12,   12,  364,  365,  365,  354,   12,   12,  366,
>> -
>> +       12,   12,  376,  377,  378,  378,  381,  382,  382,  371,
>>          12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
>> -       12,  367,   86,   86,  368,   12,  369,   12,   12,  370,
>> -       12,   12,   12,   12,   12,  371,  372,  366,  372,   12,
>> -       12,  354,   86,   12,   12,   12,  373,   12,   12,   12,
>> -      374,  375,  367,  375,   86,   86,  376,  377,  368,  377,
>> -      378,  379,  369,  379,   12,  380,  381,  370,  381,   12,
>> -       12,  382,   12,   12,  371,  372,  372,  383,  383,   12,
>> -      354,   86,   86,   86,   12,   12,   12,  384,  385,  373,
>> -      385,   12,   12,  386,  374,  375,  375,  387,  387,   86,
>> -       86,  376,  377,  377,  388,  388,  378,  379,  379,  389,
>> -
>> -      389,   12,  380,  381,  381,  390,  390,   12,   12,  391,
>> -      354,  392,   86,   12,   86,   86,   86,   12,   86,   12,
>> -      384,  385,  385,  393,  393,  394,   86,  395,  396,  386,
>> -      396,   86,   86,  397,   12,  398,  391,  354,  399,  354,
>> -       86,  400,   12,   86,   86,   86,  401,   86,  354,  402,
>> -      354,   86,  395,  396,  396,  403,  403,  354,   86,  404,
>> -      354,  405,  406,  406,  399,  354,   86,  407,  354,   12,
>> -       86,   86,   86,  408,  354,  408,  408,   86,  402,  354,
>> -       86,   86,  404,  354,  409,  410,  405,  410,  406,   86,
>> -      407,  354,   12,   86,  411,  412,  408,  354,  408,  408,
>> -
>> -       86,   86,   86,  409,  410,  410,  413,  413,   86,   12,
>> -       86,  414,  354,  415,  354,  408,  408,   86,   86,  354,
>> -      416,  417,  418,  414,  354,  415,  354,  408,  408,   86,
>> -      419,  420,  354,  421,  354,  422,  354,  408,  354,   86,
>> -      423,  354,  420,  354,  421,  354,  422,  354,  354,   86,
>> -      423,  354,  354,    0,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354
>> +       12,   12,   12,   12,   12,   12,  379,   12,   12,   12,
>> +       12,   12,   12,   12,   12,  381,  382,  382,  371,   12,
>> +
>> +       12,  383,   12,   12,   12,   12,   12,   12,   12,   12,
>> +       12,   12,   12,  384,   87,   87,  385,   12,  386,   12,
>> +       12,   12,  387,   12,   12,   12,   12,   12,  388,  389,
>> +      383,  389,   12,   12,  371,   87,   12,   12,   12,  390,
>> +       12,   12,   12,  391,  392,  384,  392,   87,   87,  393,
>> +      394,  385,  394,  395,  396,  386,  396,   12,   12,  397,
>> +      398,  387,  398,   12,   12,  399,   12,   12,  388,  389,
>> +      389,  400,  400,   12,  371,   87,   87,   87,   12,   12,
>> +       12,  401,  402,  390,  402,   12,   12,  403,  391,  392,
>> +      392,  404,  404,   87,   87,  393,  394,  394,  405,  405,
>> +
>> +      395,  396,  396,  406,  406,   12,   12,  397,  398,  398,
>> +      407,  407,   12,   12,  408,  371,  409,   87,   12,   87,
>> +       87,   87,   12,   87,   12,  401,  402,  402,  410,  410,
>> +      411,   87,  412,  413,  403,  413,   87,   87,  414,   12,
>> +       12,  415,  408,  371,  416,  371,   87,  417,   12,   87,
>> +       87,   87,  418,   87,  371,  419,  371,   87,  412,  413,
>> +      413,  420,  420,  371,   87,  421,  371,   12,  422,  423,
>> +      423,  416,  371,   87,  424,  371,   12,   87,   87,   87,
>> +      425,  371,  425,  425,   87,  419,  371,   87,   87,  421,
>> +      371,   12,  426,  427,  422,  427,  423,   87,  424,  371,
>> +
>> +       12,   87,  428,  429,  425,  371,  425,  425,   87,   87,
>> +       87,   12,  426,  427,  427,  430,  430,   87,   12,   87,
>> +      431,  371,  432,  371,  425,  425,   87,   87,  371,   12,
>> +      433,  434,  435,  431,  371,  432,  371,  425,  425,   87,
>> +      436,   12,  437,  371,  438,  371,  439,  371,  425,  371,
>> +       87,  440,  371,   12,  437,  371,  438,  371,  439,  371,
>> +      371,   87,  440,  371,  441,  371,  442,  371,  442,  371,
>> +        0,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371
>>       } ;
>>
>> -static const flex_int16_t yy_nxt[940] =
>> +static const flex_int16_t yy_nxt[975] =
>>       {   0,
>>           6,    7,    8,    9,    6,    6,    6,    6,   10,   11,
>>          12,   13,   14,   15,   16,   17,   18,   19,   17,   17,
>>          17,   17,   20,   17,   21,   22,   23,   24,   25,   17,
>>          26,   17,   17,   17,   32,   32,   33,   32,   32,   33,
>>          36,   34,   36,   42,   34,   29,   29,   29,   30,   35,
>> -       50,   36,   37,   38,   43,   44,   39,   36,   79,   45,
>> +       50,   36,   37,   38,   43,   44,   39,   36,   80,   45,
>>          36,   36,   40,   29,   29,   29,   30,   35,   46,   48,
>>          37,   38,   41,   47,   36,   49,   36,   53,   36,   36,
>> -       36,   56,   58,   36,   36,   55,   82,   60,   51,  342,
>> -       54,   61,   52,   29,   64,   32,   32,   33,   36,   65,
>> -
>> -       70,   36,   34,   29,   29,   29,   30,   36,   36,   36,
>> -       29,   38,   66,   66,   66,   67,   66,   71,   74,   66,
>> -       68,   72,   36,   36,   73,   36,   77,   78,   36,   76,
>> -       36,   53,   36,   36,   75,   85,   80,   83,   36,   86,
>> -       84,   36,   36,   36,   36,   81,   36,   36,   36,   36,
>> -       36,   36,   93,   89,  337,   98,   88,   29,   64,  101,
>> -       90,   36,   91,   65,   92,   87,   29,   95,   89,   99,
>> -       36,  100,   96,   36,   36,   36,   36,   36,   36,  106,
>> -      105,   85,   36,   36,  102,   36,  107,   36,  103,   36,
>> -      109,  112,   36,   36,  104,  108,  115,  110,   36,  117,
>> -
>> -       36,   36,   36,  335,   36,   36,  122,  111,   29,   29,
>> -       29,   30,  118,   36,  116,   29,   38,   36,   36,  113,
>> -      114,  119,  120,  123,   36,   29,   95,  121,   36,  134,
>> -      131,   96,  130,   36,  125,  124,  126,  126,   66,  127,
>> -      126,  132,  133,  126,  129,  333,   36,   36,  135,  137,
>> -       36,   36,   36,  140,  139,   35,   35,  352,   36,   36,
>> -       85,  141,  141,   66,  142,  141,  160,  145,  141,  144,
>> -       35,   35,   89,  117,  155,   36,  146,  147,  147,   66,
>> -      148,  147,  162,   36,  147,  150,  151,  151,   66,  152,
>> -      151,   36,   36,  151,  154,  120,  161,   36,  156,  156,
>> -
>> -       66,  157,  156,   36,   36,  156,  159,  164,  171,  163,
>> -       29,  166,   29,  168,   36,   36,  167,  170,  169,   35,
>> -       35,  172,   36,   36,  173,   36,  213,  184,   36,   36,
>> -      175,   36,  174,   29,  186,  212,   36,  349,  183,  187,
>> -      177,  176,  178,  178,   66,  179,  178,  182,  348,  178,
>> -      181,   29,  188,   35,   35,   35,   35,  189,   29,  193,
>> -       29,  195,  190,   36,  194,   36,  196,   29,  198,   29,
>> -      200,  191,   36,  199,   36,  201,  219,   29,  204,   29,
>> -      206,   36,  202,  205,  209,  207,   29,  166,   36,  293,
>> -      208,  214,  167,   35,   35,   35,   35,   35,   35,   36,
>> -
>> -       36,   36,  249,  218,  220,   29,  222,  216,   36,  217,
>> -      235,  223,   29,  224,  215,  226,   36,  227,  225,  346,
>> -       35,   35,   36,  228,  228,   66,  229,  228,   29,  186,
>> -      228,  231,  232,   36,  187,  233,   35,   29,  193,   29,
>> -      198,  234,   36,  194,  344,  199,   29,  204,  236,   36,
>> -       35,  241,  205,  242,   36,   35,   35,  270,   35,   35,
>> -       35,   35,  247,   36,   35,   35,   29,  222,  244,  262,
>> -      248,   36,  223,  243,  245,  246,   35,  252,   29,  254,
>> -       29,  256,  258,  342,  255,  259,  257,   35,   35,  339,
>> -       35,   35,   69,  264,   35,   35,   35,   35,   35,   35,
>> -
>> -      267,   35,   35,  275,   35,   35,   35,   35,  271,   35,
>> -       35,  276,  277,   35,   35,  272,  278,  315,  273,  281,
>> -       29,  254,  290,  313,  282,  275,  255,  285,  285,   66,
>> -      286,  285,   35,   35,  285,  288,  295,  298,  296,   35,
>> -       35,   35,   35,  298,  301,  328,  299,  294,   35,   35,
>> -      275,   35,   35,   35,  303,   29,  305,  300,  275,   29,
>> -      307,  306,   35,   35,  302,  308,  337,   36,   35,   35,
>> -      309,  310,  320,  316,   35,   35,   35,   35,  322,   36,
>> -       35,   35,  317,  275,  319,  311,   29,  305,  335,  275,
>> -      318,  321,  306,  323,   35,   35,   35,   35,  330,  329,
>> -
>> -       35,   35,  331,  333,  327,   35,   35,  338,   35,   35,
>> -      353,  340,   35,   35,  350,  325,  275,  315,   35,   35,
>> -       27,   27,   27,   27,   29,   29,   29,   31,   31,   31,
>> -       31,   36,   36,   36,   36,   62,  313,   62,   62,   63,
>> -       63,   63,   63,   65,  269,   65,   65,   35,   35,   35,
>> -       35,   69,   69,  261,   69,   94,   94,   94,   94,   96,
>> -      251,   96,   96,  128,  128,  128,  128,  143,  143,  143,
>> -      143,  149,  149,  149,  149,  153,  153,  153,  153,  158,
>> -      158,  158,  158,  165,  165,  165,  165,  167,  298,  167,
>> -      167,  180,  180,  180,  180,  185,  185,  185,  185,  187,
>> -
>> -      292,  187,  187,  192,  192,  192,  192,  194,  240,  194,
>> -      194,  197,  197,  197,  197,  199,  289,  199,  199,  203,
>> -      203,  203,  203,  205,  284,  205,  205,  210,  210,  210,
>> -      210,  169,  280,  169,  169,  221,  221,  221,  221,  223,
>> -      269,  223,  223,  230,  230,  230,  230,  189,  266,  189,
>> -      189,  196,  211,  196,  196,  201,  261,  201,  201,  207,
>> -      251,  207,  207,  237,  237,  237,  237,  239,  239,  239,
>> -      239,  225,  240,  225,  225,  250,  250,  250,  250,  253,
>> -      253,  253,  253,  255,  238,  255,  255,  260,  260,  260,
>> -      260,  263,  263,  263,  263,  265,  265,  265,  265,  268,
>> -
>> -      268,  268,  268,  274,  274,  274,  274,  279,  279,  279,
>> -      279,  257,  211,  257,  257,  283,  283,  283,  283,  287,
>> -      287,  287,  287,  264,  138,  264,  264,  291,  291,  291,
>> -      291,  297,  297,  297,  297,  304,  304,  304,  304,  306,
>> -      136,  306,  306,  312,  312,  312,  312,  314,  314,  314,
>> -      314,  308,   97,  308,  308,  324,  324,  324,  324,  326,
>> -      326,  326,  326,  332,  332,  332,  332,  334,  334,  334,
>> -      334,  336,  336,  336,  336,  341,  341,  341,  341,  343,
>> -      343,  343,  343,  345,  345,  345,  345,  347,  347,  347,
>> -      347,  351,  351,  351,  351,   36,   30,   59,   57,   36,
>> -
>> -       30,  354,   28,   28,    5,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354
>> +       36,   56,   58,   36,   36,   55,   83,   61,   51,   36,
>> +       54,   62,   52,   29,   65,   59,   32,   32,   33,   66,
>> +
>> +       36,   36,   71,   34,   29,   29,   29,   30,   36,   36,
>> +       77,   29,   38,   67,   67,   67,   68,   67,   75,   72,
>> +       67,   69,   73,   36,   36,   74,   78,   79,   36,   53,
>> +       36,   36,   36,   87,   36,   76,   84,   36,   36,   85,
>> +       36,   81,   36,   86,   36,   36,   36,   36,   82,   36,
>> +       92,   95,   36,  100,   36,   36,   89,   90,   88,   29,
>> +       65,   36,   91,  101,   36,   66,   90,   93,   36,   94,
>> +       29,   97,  102,   36,   36,  104,   98,   36,  103,   36,
>> +       36,  107,  108,  106,   36,   36,   36,  105,   86,   36,
>> +      109,  110,  111,   36,   36,  114,  112,   36,  117,  119,
>> +
>> +       36,   36,   36,   36,   36,  121,   36,  368,   36,   36,
>> +      120,  113,   29,   29,   29,   30,  118,   36,  134,   29,
>> +       38,   36,  127,  115,  116,  122,  123,  125,   36,  126,
>> +      128,  124,   29,   97,   36,   36,  180,  138,   98,  129,
>> +      129,   67,  130,  129,   36,   36,  129,  132,  133,  135,
>> +      136,  140,   36,   36,   36,   36,  142,   36,  137,   35,
>> +       35,  123,   86,   36,  370,  143,  144,  144,   67,  145,
>> +      144,  148,  158,  144,  147,   35,   35,   90,  119,   36,
>> +       36,  149,  150,  150,   67,  151,  150,  159,   36,  150,
>> +      153,  154,  154,   67,  155,  154,  164,   36,  154,  157,
>> +
>> +      160,  160,   67,  161,  160,   36,  368,  160,  163,  165,
>> +      166,   36,   36,   29,  170,  167,  168,   29,  172,  171,
>> +       36,  175,   36,  173,   35,   35,  176,   36,   36,  177,
>> +       36,   36,  188,  174,   36,   29,  190,  178,   36,  181,
>> +       36,  191,  223,  179,  182,  182,   67,  183,  182,  186,
>> +      206,  182,  185,  187,   29,  192,   35,   35,   35,   35,
>> +      193,   29,  197,   29,  199,  194,   36,  198,   36,  200,
>> +       29,  202,   29,  204,  195,   36,  203,   36,  205,  268,
>> +      207,   29,  209,   29,  211,  214,  213,  210,  218,  212,
>> +      217,   36,  353,   36,   29,  170,   36,   35,   35,  219,
>> +
>> +      171,   35,   35,   35,   35,  224,   36,  231,   36,  225,
>> +       36,   29,  227,  221,   36,  222,  232,  228,  220,   29,
>> +      229,   36,  240,   35,   35,  230,  233,  233,   67,  234,
>> +      233,   29,  190,  233,  236,  237,  348,  191,  238,   35,
>> +       29,  197,   29,  202,  239,   36,  198,   36,  203,   29,
>> +      209,  242,   36,   35,  247,  210,  255,  241,  248,   36,
>> +       35,   35,   36,   35,   35,   35,   35,  253,   36,   35,
>> +       35,   29,  227,  250,  269,  254,   36,  228,  249,  251,
>> +      252,   35,  258,   29,  260,   29,  262,  264,   36,  261,
>> +      265,  263,   35,   35,  346,   35,   35,   70,  271,   35,
>> +
>> +       35,   35,   35,   35,   35,  274,   35,   35,  282,   35,
>> +       35,   36,  277,  278,   35,   35,  283,  284,   35,   35,
>> +      279,  285,   36,  280,  288,   29,  260,   35,   35,  289,
>> +      312,  261,  293,  293,   67,  294,  293,  301,  306,  293,
>> +      296,   35,   35,  298,  303,  306,  304,   35,   35,   35,
>> +       35,  309,  308,   36,  307,  282,  302,  319,   35,   35,
>> +       35,   35,   35,  311,   29,  314,   29,  316,   35,   35,
>> +      315,  282,  317,   35,   35,  344,  310,  364,  325,   35,
>> +       35,  318,   35,   35,  329,  320,   36,  328,  332,   36,
>> +       29,  314,   35,   35,  330,  326,  315,  331,  327,  333,
>> +
>> +       35,   35,   35,   35,  282,  282,  340,  341,   35,   35,
>> +       35,   35,   36,  282,   35,   35,   36,  351,   35,   35,
>> +      362,  339,  365,   36,  338,  366,  342,  361,  360,  354,
>> +      358,  349,  356,   35,   35,   27,   27,   27,   27,   29,
>> +       29,   29,   31,   31,   31,   31,   36,   36,   36,   36,
>> +       63,  353,   63,   63,   64,   64,   64,   64,   66,  350,
>> +       66,   66,   35,   35,   35,   35,   70,   70,  324,   70,
>> +       96,   96,   96,   96,   98,  322,   98,   98,  131,  131,
>> +      131,  131,  146,  146,  146,  146,  152,  152,  152,  152,
>> +      156,  156,  156,  156,  162,  162,  162,  162,  169,  169,
>> +
>> +      169,  169,  171,  348,  171,  171,  184,  184,  184,  184,
>> +      189,  189,  189,  189,  191,  346,  191,  191,  196,  196,
>> +      196,  196,  198,  344,  198,  198,  201,  201,  201,  201,
>> +      203,  337,  203,  203,  208,  208,  208,  208,  210,  335,
>> +      210,  210,  215,  215,  215,  215,  173,  282,  173,  173,
>> +      226,  226,  226,  226,  228,  324,  228,  228,  235,  235,
>> +      235,  235,  193,  322,  193,  193,  200,  276,  200,  200,
>> +      205,  267,  205,  205,  212,  257,  212,  212,  243,  243,
>> +      243,  243,  245,  245,  245,  245,  230,  306,  230,  230,
>> +      256,  256,  256,  256,  259,  259,  259,  259,  261,  300,
>> +
>> +      261,  261,  266,  266,  266,  266,  270,  270,  270,  270,
>> +      272,  272,  272,  272,  275,  275,  275,  275,  281,  281,
>> +      281,  281,  286,  286,  286,  286,  263,  246,  263,  263,
>> +      290,  290,  290,  290,  295,  295,  295,  295,  271,  297,
>> +      271,  271,  299,  299,  299,  299,  305,  305,  305,  305,
>> +      313,  313,  313,  313,  315,  292,  315,  315,  321,  321,
>> +      321,  321,  323,  323,  323,  323,  317,  291,  317,  317,
>> +      334,  334,  334,  334,  336,  336,  336,  336,  343,  343,
>> +      343,  343,  345,  345,  345,  345,  347,  347,  347,  347,
>> +      352,  352,  352,  352,  355,  355,  355,  355,  357,  357,
>> +
>> +      357,  357,  359,  359,  359,  359,  363,  363,  363,  363,
>> +      367,  367,  367,  367,  369,  369,  369,  369,  287,  276,
>> +      273,  216,  267,  257,  246,  244,  216,  141,  139,   99,
>> +       36,   30,   60,   57,   36,   30,  371,   28,   28,    5,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371
>>       } ;
>>
>> -static const flex_int16_t yy_chk[940] =
>> +static const flex_int16_t yy_chk[975] =
>>       {   0,
>>           1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>>           1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>> @@ -927,101 +940,105 @@ static const flex_int16_t yy_chk[940] =
>>          18,   14,   11,   11,   13,   14,   11,   46,   46,   14,
>>          15,   16,   11,   12,   12,   12,   12,   12,   14,   16,
>>          12,   12,   12,   15,   19,   16,   20,   20,   21,   22,
>> -       24,   22,   24,   50,   26,   21,   50,   26,   19,  351,
>> -       20,   26,   19,   31,   31,   32,   32,   32,   39,   31,
>> -
>> -       39,   42,   32,   35,   35,   35,   35,   40,   44,   45,
>> -       35,   35,   37,   37,   37,   37,   37,   39,   42,   37,
>> -       37,   40,   41,   43,   41,   48,   45,   45,   49,   44,
>> -       47,   47,   53,   51,   43,   53,   48,   51,   52,   54,
>> -       52,   55,   56,   58,   54,   49,   57,   59,   60,   73,
>> -       61,   70,   60,   61,  347,   70,   56,   63,   63,   73,
>> -       58,   71,   59,   63,   59,   55,   66,   66,   57,   71,
>> -       74,   72,   66,   72,   75,   76,   77,   78,   79,   78,
>> -       77,   79,   80,   81,   74,   83,   80,   82,   75,   84,
>> -       82,   85,   88,   85,   76,   81,   87,   83,   87,   89,
>> -
>> -       92,   89,   93,  345,   90,  104,   92,   84,   86,   86,
>> -       86,   86,   90,   99,   88,   86,   86,   98,  102,   86,
>> -       86,   91,   91,   93,   91,   94,   94,   91,  101,  104,
>> -      102,   94,  101,  110,   99,   98,  100,  100,  100,  100,
>> -      100,  103,  103,  100,  100,  343,  105,  103,  105,  107,
>> -      109,  107,  111,  110,  109,  113,  113,  341,  121,  118,
>> -      111,  112,  112,  112,  112,  112,  121,  113,  112,  112,
>> -      114,  114,  116,  116,  118,  116,  114,  115,  115,  115,
>> -      115,  115,  123,  123,  115,  115,  117,  117,  117,  117,
>> -      117,  124,  122,  117,  117,  119,  122,  119,  120,  120,
>> -
>> -      120,  120,  120,  125,  130,  120,  120,  125,  131,  124,
>> -      126,  126,  128,  128,  131,  134,  126,  130,  128,  133,
>> -      133,  133,  135,  136,  133,  139,  164,  140,  138,  140,
>> -      134,  164,  133,  141,  141,  163,  163,  338,  139,  141,
>> -      136,  135,  137,  137,  137,  137,  137,  138,  336,  137,
>> -      137,  143,  143,  145,  145,  146,  146,  143,  147,  147,
>> -      149,  149,  145,  155,  147,  161,  149,  151,  151,  153,
>> -      153,  146,  160,  151,  270,  153,  176,  156,  156,  158,
>> -      158,  176,  155,  156,  161,  158,  165,  165,  170,  270,
>> -      160,  170,  165,  172,  172,  173,  173,  174,  174,  175,
>> -
>> -      208,  177,  220,  175,  177,  178,  178,  173,  220,  174,
>> -      208,  178,  180,  180,  172,  182,  182,  183,  180,  334,
>> -      190,  190,  183,  184,  184,  184,  184,  184,  185,  185,
>> -      184,  184,  190,  243,  185,  191,  191,  192,  192,  197,
>> -      197,  202,  202,  192,  332,  197,  203,  203,  209,  209,
>> -      213,  213,  203,  214,  214,  215,  215,  243,  216,  216,
>> -      217,  217,  218,  218,  219,  219,  221,  221,  215,  235,
>> -      219,  235,  221,  214,  216,  217,  227,  227,  228,  228,
>> -      230,  230,  232,  331,  228,  233,  230,  233,  233,  329,
>> -      232,  232,  236,  236,  241,  241,  244,  244,  245,  245,
>> -
>> -      241,  246,  246,  247,  248,  248,  267,  267,  244,  259,
>> -      259,  247,  247,  252,  252,  245,  248,  326,  246,  252,
>> -      253,  253,  267,  324,  259,  316,  253,  262,  262,  262,
>> -      262,  262,  271,  271,  262,  262,  272,  276,  273,  272,
>> -      272,  273,  273,  277,  278,  316,  276,  271,  281,  281,
>> -      299,  278,  278,  282,  282,  285,  285,  277,  300,  287,
>> -      287,  285,  290,  290,  281,  287,  323,  293,  294,  294,
>> -      290,  293,  303,  299,  301,  301,  302,  302,  310,  310,
>> -      303,  303,  300,  317,  302,  294,  304,  304,  322,  328,
>> -      301,  309,  304,  311,  309,  309,  311,  311,  318,  317,
>> -
>> -      318,  318,  319,  321,  314,  319,  319,  328,  330,  330,
>> -      350,  330,  340,  340,  340,  312,  297,  296,  350,  350,
>> -      355,  355,  355,  355,  356,  356,  356,  357,  357,  357,
>> -      357,  358,  358,  358,  358,  359,  295,  359,  359,  360,
>> -      360,  360,  360,  361,  291,  361,  361,  362,  362,  362,
>> -      362,  363,  363,  283,  363,  364,  364,  364,  364,  365,
>> -      279,  365,  365,  366,  366,  366,  366,  367,  367,  367,
>> -      367,  368,  368,  368,  368,  369,  369,  369,  369,  370,
>> -      370,  370,  370,  371,  371,  371,  371,  372,  274,  372,
>> -      372,  373,  373,  373,  373,  374,  374,  374,  374,  375,
>> -
>> -      268,  375,  375,  376,  376,  376,  376,  377,  265,  377,
>> -      377,  378,  378,  378,  378,  379,  263,  379,  379,  380,
>> -      380,  380,  380,  381,  260,  381,  381,  382,  382,  382,
>> -      382,  383,  250,  383,  383,  384,  384,  384,  384,  385,
>> -      242,  385,  385,  386,  386,  386,  386,  387,  239,  387,
>> -      387,  388,  237,  388,  388,  389,  234,  389,  389,  390,
>> -      226,  390,  390,  391,  391,  391,  391,  392,  392,  392,
>> -      392,  393,  212,  393,  393,  394,  394,  394,  394,  395,
>> -      395,  395,  395,  396,  210,  396,  396,  397,  397,  397,
>> -      397,  398,  398,  398,  398,  399,  399,  399,  399,  400,
>> -
>> -      400,  400,  400,  401,  401,  401,  401,  402,  402,  402,
>> -      402,  403,  162,  403,  403,  404,  404,  404,  404,  405,
>> -      405,  405,  405,  406,  108,  406,  406,  407,  407,  407,
>> -      407,  408,  408,  408,  408,  409,  409,  409,  409,  410,
>> -      106,  410,  410,  411,  411,  411,  411,  412,  412,  412,
>> -      412,  413,   69,  413,  413,  414,  414,  414,  414,  415,
>> -      415,  415,  415,  416,  416,  416,  416,  417,  417,  417,
>> -      417,  418,  418,  418,  418,  419,  419,  419,  419,  420,
>> -      420,  420,  420,  421,  421,  421,  421,  422,  422,  422,
>> -      422,  423,  423,  423,  423,   36,   29,   25,   23,   17,
>> -
>> -        6,    5,    4,    3,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
>> -      354,  354,  354,  354,  354,  354,  354,  354,  354
>> +       24,   22,   24,   50,   26,   21,   50,   26,   19,   44,
>> +       20,   26,   19,   31,   31,   24,   32,   32,   32,   31,
>> +
>> +       39,   42,   39,   32,   35,   35,   35,   35,   40,   45,
>> +       44,   35,   35,   37,   37,   37,   37,   37,   42,   39,
>> +       37,   37,   40,   41,   43,   41,   45,   45,   47,   47,
>> +       48,   49,   51,   54,   55,   43,   51,   52,   54,   52,
>> +       53,   48,   56,   53,   57,   58,   59,   61,   49,   71,
>> +       59,   61,   60,   71,   62,   72,   56,   62,   55,   64,
>> +       64,   75,   58,   72,   77,   64,   57,   60,   74,   60,
>> +       67,   67,   73,   76,   73,   75,   67,   78,   74,   82,
>> +       79,   78,   79,   77,   84,   80,   81,   76,   80,   83,
>> +       81,   82,   83,   85,   89,   86,   84,   86,   88,   90,
>> +
>> +       88,   90,   91,   92,  100,   92,  104,  369,   95,  101,
>> +       91,   85,   87,   87,   87,   87,   89,  138,  104,   87,
>> +       87,   94,  100,   87,   87,   93,   93,   94,   93,   95,
>> +      101,   93,   96,   96,  106,  107,  138,  107,   96,  102,
>> +      102,  102,  102,  102,  103,  112,  102,  102,  103,  105,
>> +      105,  109,  111,  109,  113,  105,  111,  120,  106,  115,
>> +      115,  122,  113,  122,  367,  112,  114,  114,  114,  114,
>> +      114,  115,  120,  114,  114,  116,  116,  118,  118,  121,
>> +      118,  116,  117,  117,  117,  117,  117,  121,  124,  117,
>> +      117,  119,  119,  119,  119,  119,  124,  127,  119,  119,
>> +
>> +      123,  123,  123,  123,  123,  125,  365,  123,  123,  125,
>> +      126,  126,  128,  129,  129,  127,  128,  131,  131,  129,
>> +      133,  134,  139,  131,  136,  136,  136,  134,  137,  136,
>> +      141,  158,  143,  133,  143,  144,  144,  136,  179,  139,
>> +      142,  144,  179,  137,  140,  140,  140,  140,  140,  141,
>> +      158,  140,  140,  142,  146,  146,  148,  148,  149,  149,
>> +      146,  150,  150,  152,  152,  148,  165,  150,  164,  152,
>> +      154,  154,  156,  156,  149,  159,  154,  240,  156,  240,
>> +      159,  160,  160,  162,  162,  165,  164,  160,  168,  162,
>> +      167,  167,  363,  168,  169,  169,  174,  176,  176,  174,
>> +
>> +      169,  177,  177,  178,  178,  180,  181,  186,  186,  181,
>> +      180,  182,  182,  177,  207,  178,  187,  182,  176,  184,
>> +      184,  187,  207,  194,  194,  184,  188,  188,  188,  188,
>> +      188,  189,  189,  188,  188,  194,  359,  189,  195,  195,
>> +      196,  196,  201,  201,  206,  206,  196,  213,  201,  208,
>> +      208,  214,  214,  218,  218,  208,  225,  213,  219,  219,
>> +      220,  220,  225,  221,  221,  222,  222,  223,  223,  224,
>> +      224,  226,  226,  220,  241,  224,  241,  226,  219,  221,
>> +      222,  232,  232,  233,  233,  235,  235,  237,  249,  233,
>> +      238,  235,  238,  238,  357,  237,  237,  242,  242,  247,
>> +
>> +      247,  250,  250,  251,  251,  247,  252,  252,  253,  254,
>> +      254,  292,  249,  250,  265,  265,  253,  253,  258,  258,
>> +      251,  254,  277,  252,  258,  259,  259,  274,  274,  265,
>> +      292,  259,  269,  269,  269,  269,  269,  277,  284,  269,
>> +      269,  278,  278,  274,  279,  283,  280,  279,  279,  280,
>> +      280,  285,  284,  301,  283,  307,  278,  301,  285,  285,
>> +      288,  288,  289,  289,  293,  293,  295,  295,  302,  302,
>> +      293,  308,  295,  298,  298,  355,  288,  352,  307,  310,
>> +      310,  298,  309,  309,  311,  302,  312,  310,  319,  319,
>> +      313,  313,  311,  311,  312,  308,  313,  318,  309,  320,
>> +
>> +      318,  318,  320,  320,  325,  326,  327,  328,  327,  327,
>> +      328,  328,  330,  338,  340,  340,  342,  340,  351,  351,
>> +      351,  326,  354,  354,  325,  362,  330,  349,  347,  342,
>> +      345,  338,  343,  362,  362,  372,  372,  372,  372,  373,
>> +      373,  373,  374,  374,  374,  374,  375,  375,  375,  375,
>> +      376,  341,  376,  376,  377,  377,  377,  377,  378,  339,
>> +      378,  378,  379,  379,  379,  379,  380,  380,  336,  380,
>> +      381,  381,  381,  381,  382,  334,  382,  382,  383,  383,
>> +      383,  383,  384,  384,  384,  384,  385,  385,  385,  385,
>> +      386,  386,  386,  386,  387,  387,  387,  387,  388,  388,
>> +
>> +      388,  388,  389,  333,  389,  389,  390,  390,  390,  390,
>> +      391,  391,  391,  391,  392,  332,  392,  392,  393,  393,
>> +      393,  393,  394,  331,  394,  394,  395,  395,  395,  395,
>> +      396,  323,  396,  396,  397,  397,  397,  397,  398,  321,
>> +      398,  398,  399,  399,  399,  399,  400,  305,  400,  400,
>> +      401,  401,  401,  401,  402,  304,  402,  402,  403,  403,
>> +      403,  403,  404,  303,  404,  404,  405,  299,  405,  405,
>> +      406,  290,  406,  406,  407,  286,  407,  407,  408,  408,
>> +      408,  408,  409,  409,  409,  409,  410,  281,  410,  410,
>> +      411,  411,  411,  411,  412,  412,  412,  412,  413,  275,
>> +
>> +      413,  413,  414,  414,  414,  414,  415,  415,  415,  415,
>> +      416,  416,  416,  416,  417,  417,  417,  417,  418,  418,
>> +      418,  418,  419,  419,  419,  419,  420,  272,  420,  420,
>> +      421,  421,  421,  421,  422,  422,  422,  422,  423,  270,
>> +      423,  423,  424,  424,  424,  424,  425,  425,  425,  425,
>> +      426,  426,  426,  426,  427,  268,  427,  427,  428,  428,
>> +      428,  428,  429,  429,  429,  429,  430,  266,  430,  430,
>> +      431,  431,  431,  431,  432,  432,  432,  432,  433,  433,
>> +      433,  433,  434,  434,  434,  434,  435,  435,  435,  435,
>> +      436,  436,  436,  436,  437,  437,  437,  437,  438,  438,
>> +
>> +      438,  438,  439,  439,  439,  439,  440,  440,  440,  440,
>> +      441,  441,  441,  441,  442,  442,  442,  442,  256,  248,
>> +      245,  243,  239,  231,  217,  215,  166,  110,  108,   70,
>> +       36,   29,   25,   23,   17,    6,    5,    4,    3,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
>> +      371,  371,  371,  371
>>       } ;
>>
>>   #define YY_TRAILING_MASK 0x2000
>> @@ -1160,9 +1177,17 @@ static void setbackendtype(DiskParseContext
>> *dpc, const char *str) {
>>       if (     !strcmp(str,"phy"))   DSET(dpc,backend,BACKEND,str,PHY);
>>       else if (!strcmp(str,"tap"))   DSET(dpc,backend,BACKEND,str,TAP);
>>       else if (!strcmp(str,"qdisk")) DSET(dpc,backend,BACKEND,str,QDISK);
>> +    else if (!strcmp(str,"standalone"))
>> DSET(dpc,backend,BACKEND,str,STANDALONE);
>>       else xlu__disk_err(dpc,str,"unknown value for backendtype");
>>   }
>>
>> +/* Sets ->specification from the string.  IDL should provide something for
>> this. */
>> +static void setspecification(DiskParseContext *dpc, const char *str) {
>> +    if      (!strcmp(str,"xen"))    DSET(dpc,specification,SPECIFICATION,str,XEN);
>> +    else if (!strcmp(str,"virtio"))
>> DSET(dpc,specification,SPECIFICATION,str,VIRTIO);
>> +    else xlu__disk_err(dpc,str,"unknown value for specification");
>> +}
>> +
>>   /* Sets ->colo-port from the string.  COLO need this. */
>>   static void setcoloport(DiskParseContext *dpc, const char *str) {
>>       int port = atoi(str);
>> @@ -1199,9 +1224,9 @@ static int vdev_and_devtype(DiskParseContext
>> *dpc, char *str) {
>>   #undef DPC /* needs to be defined differently the actual lexer */
>>   #define DPC ((DiskParseContext*)yyextra)
>>
>> -#line 1202 "libxlu_disk_l.c"
>> +#line 1227 "libxlu_disk_l.c"
>>
>> -#line 1204 "libxlu_disk_l.c"
>> +#line 1229 "libxlu_disk_l.c"
>>
>>   #define INITIAL 0
>>   #define LEXERR 1
>> @@ -1477,13 +1502,13 @@ YY_DECL
>>   		}
>>
>>   	{
>> -#line 177 "libxlu_disk_l.l"
>> +#line 185 "libxlu_disk_l.l"
>>
>>
>> -#line 180 "libxlu_disk_l.l"
>> +#line 188 "libxlu_disk_l.l"
>>    /*----- the scanner rules which do the parsing -----*/
>>
>> -#line 1486 "libxlu_disk_l.c"
>> +#line 1511 "libxlu_disk_l.c"
>>
>>   	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is
>> reached */
>>   		{
>> @@ -1515,14 +1540,14 @@ yy_match:
>>   			while ( yy_chk[yy_base[yy_current_state] + yy_c] !=
>> yy_current_state )
>>   				{
>>   				yy_current_state = (int)
>> yy_def[yy_current_state];
>> -				if ( yy_current_state >= 355 )
>> +				if ( yy_current_state >= 372 )
>>   					yy_c = yy_meta[yy_c];
>>   				}
>>   			yy_current_state = yy_nxt[yy_base[yy_current_state]
>> + yy_c];
>>   			*yyg->yy_state_ptr++ = yy_current_state;
>>   			++yy_cp;
>>   			}
>> -		while ( yy_current_state != 354 );
>> +		while ( yy_current_state != 371 );
>>
>>   yy_find_action:
>>   		yy_current_state = *--yyg->yy_state_ptr;
>> @@ -1572,152 +1597,158 @@ do_action:	/* This label is used only to
>> access EOF actions. */
>>   case 1:
>>   /* rule 1 can match eol */
>>   YY_RULE_SETUP
>> -#line 182 "libxlu_disk_l.l"
>> +#line 190 "libxlu_disk_l.l"
>>   { /* ignore whitespace before parameters */ }
>>   	YY_BREAK
>>   /* ordinary parameters setting enums or strings */
>>   case 2:
>>   /* rule 2 can match eol */
>>   YY_RULE_SETUP
>> -#line 186 "libxlu_disk_l.l"
>> +#line 194 "libxlu_disk_l.l"
>>   { STRIP(','); setformat(DPC, FROMEQUALS); }
>>   	YY_BREAK
>>   case 3:
>>   YY_RULE_SETUP
>> -#line 188 "libxlu_disk_l.l"
>> +#line 196 "libxlu_disk_l.l"
>>   { DPC->disk->is_cdrom = 1; }
>>   	YY_BREAK
>>   case 4:
>>   YY_RULE_SETUP
>> -#line 189 "libxlu_disk_l.l"
>> +#line 197 "libxlu_disk_l.l"
>>   { DPC->disk->is_cdrom = 1; }
>>   	YY_BREAK
>>   case 5:
>>   YY_RULE_SETUP
>> -#line 190 "libxlu_disk_l.l"
>> +#line 198 "libxlu_disk_l.l"
>>   { DPC->disk->is_cdrom = 0; }
>>   	YY_BREAK
>>   case 6:
>>   /* rule 6 can match eol */
>>   YY_RULE_SETUP
>> -#line 191 "libxlu_disk_l.l"
>> +#line 199 "libxlu_disk_l.l"
>>   { xlu__disk_err(DPC,yytext,"unknown value for type"); }
>>   	YY_BREAK
>>   case 7:
>>   /* rule 7 can match eol */
>>   YY_RULE_SETUP
>> -#line 193 "libxlu_disk_l.l"
>> +#line 201 "libxlu_disk_l.l"
>>   { STRIP(','); setaccess(DPC, FROMEQUALS); }
>>   	YY_BREAK
>>   case 8:
>>   /* rule 8 can match eol */
>>   YY_RULE_SETUP
>> -#line 194 "libxlu_disk_l.l"
>> +#line 202 "libxlu_disk_l.l"
>>   { STRIP(','); SAVESTRING("backend", backend_domname, FROMEQUALS); }
>>   	YY_BREAK
>>   case 9:
>>   /* rule 9 can match eol */
>>   YY_RULE_SETUP
>> -#line 195 "libxlu_disk_l.l"
>> +#line 203 "libxlu_disk_l.l"
>>   { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
>>   	YY_BREAK
>>   case 10:
>>   /* rule 10 can match eol */
>>   YY_RULE_SETUP
>> -#line 197 "libxlu_disk_l.l"
>> -{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
>> +#line 204 "libxlu_disk_l.l"
>> +{ STRIP(','); setspecification(DPC,FROMEQUALS); }
>>   	YY_BREAK
>>   case 11:
>>   /* rule 11 can match eol */
>>   YY_RULE_SETUP
>> -#line 198 "libxlu_disk_l.l"
>> -{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
>> +#line 206 "libxlu_disk_l.l"
>> +{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
>>   	YY_BREAK
>>   case 12:
>> +/* rule 12 can match eol */
>>   YY_RULE_SETUP
>> -#line 199 "libxlu_disk_l.l"
>> -{ DPC->disk->direct_io_safe = 1; }
>> +#line 207 "libxlu_disk_l.l"
>> +{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
>>   	YY_BREAK
>>   case 13:
>>   YY_RULE_SETUP
>> -#line 200 "libxlu_disk_l.l"
>> -{ libxl_defbool_set(&DPC->disk->discard_enable, true); }
>> +#line 208 "libxlu_disk_l.l"
>> +{ DPC->disk->direct_io_safe = 1; }
>>   	YY_BREAK
>>   case 14:
>>   YY_RULE_SETUP
>> -#line 201 "libxlu_disk_l.l"
>> -{ libxl_defbool_set(&DPC->disk->discard_enable, false); }
>> +#line 209 "libxlu_disk_l.l"
>> +{ libxl_defbool_set(&DPC->disk->discard_enable, true); }
>>   	YY_BREAK
>> -/* Note that the COLO configuration settings should be considered unstable.
>> -  * They may change incompatibly in future versions of Xen. */
>>   case 15:
>>   YY_RULE_SETUP
>> -#line 204 "libxlu_disk_l.l"
>> -{ libxl_defbool_set(&DPC->disk->colo_enable, true); }
>> +#line 210 "libxlu_disk_l.l"
>> +{ libxl_defbool_set(&DPC->disk->discard_enable, false); }
>>   	YY_BREAK
>> +/* Note that the COLO configuration settings should be considered unstable.
>> +  * They may change incompatibly in future versions of Xen. */
>>   case 16:
>>   YY_RULE_SETUP
>> -#line 205 "libxlu_disk_l.l"
>> -{ libxl_defbool_set(&DPC->disk->colo_enable, false); }
>> +#line 213 "libxlu_disk_l.l"
>> +{ libxl_defbool_set(&DPC->disk->colo_enable, true); }
>>   	YY_BREAK
>>   case 17:
>> -/* rule 17 can match eol */
>>   YY_RULE_SETUP
>> -#line 206 "libxlu_disk_l.l"
>> -{ STRIP(','); SAVESTRING("colo-host", colo_host, FROMEQUALS); }
>> +#line 214 "libxlu_disk_l.l"
>> +{ libxl_defbool_set(&DPC->disk->colo_enable, false); }
>>   	YY_BREAK
>>   case 18:
>>   /* rule 18 can match eol */
>>   YY_RULE_SETUP
>> -#line 207 "libxlu_disk_l.l"
>> -{ STRIP(','); setcoloport(DPC, FROMEQUALS); }
>> +#line 215 "libxlu_disk_l.l"
>> +{ STRIP(','); SAVESTRING("colo-host", colo_host, FROMEQUALS); }
>>   	YY_BREAK
>>   case 19:
>>   /* rule 19 can match eol */
>>   YY_RULE_SETUP
>> -#line 208 "libxlu_disk_l.l"
>> -{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
>> +#line 216 "libxlu_disk_l.l"
>> +{ STRIP(','); setcoloport(DPC, FROMEQUALS); }
>>   	YY_BREAK
>>   case 20:
>>   /* rule 20 can match eol */
>>   YY_RULE_SETUP
>> -#line 209 "libxlu_disk_l.l"
>> -{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
>> +#line 217 "libxlu_disk_l.l"
>> +{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
>>   	YY_BREAK
>>   case 21:
>>   /* rule 21 can match eol */
>>   YY_RULE_SETUP
>> -#line 210 "libxlu_disk_l.l"
>> +#line 218 "libxlu_disk_l.l"
>> +{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
>> +	YY_BREAK
>> +case 22:
>> +/* rule 22 can match eol */
>> +YY_RULE_SETUP
>> +#line 219 "libxlu_disk_l.l"
>>   { STRIP(','); SAVESTRING("hidden-disk", hidden_disk, FROMEQUALS); }
>>   	YY_BREAK
>>   /* the target magic parameter, eats the rest of the string */
>> -case 22:
>> +case 23:
>>   YY_RULE_SETUP
>> -#line 214 "libxlu_disk_l.l"
>> +#line 223 "libxlu_disk_l.l"
>>   { STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
>>   	YY_BREAK
>>   /* unknown parameters */
>> -case 23:
>> -/* rule 23 can match eol */
>> +case 24:
>> +/* rule 24 can match eol */
>>   YY_RULE_SETUP
>> -#line 218 "libxlu_disk_l.l"
>> +#line 227 "libxlu_disk_l.l"
>>   { xlu__disk_err(DPC,yytext,"unknown parameter"); }
>>   	YY_BREAK
>>   /* deprecated prefixes */
>>   /* the "/.*" in these patterns ensures that they count as if they
>>      * matched the whole string, so these patterns take precedence */
>> -case 24:
>> +case 25:
>>   YY_RULE_SETUP
>> -#line 225 "libxlu_disk_l.l"
>> +#line 234 "libxlu_disk_l.l"
>>   {
>>                       STRIP(':');
>>                       DPC->had_depr_prefix=1; DEPRECATE("use `[format=]...,'");
>>                       setformat(DPC, yytext);
>>                    }
>>   	YY_BREAK
>> -case 25:
>> +case 26:
>>   YY_RULE_SETUP
>> -#line 231 "libxlu_disk_l.l"
>> +#line 240 "libxlu_disk_l.l"
>>   {
>>                       char *newscript;
>>                       STRIP(':');
>> @@ -1731,65 +1762,65 @@ YY_RULE_SETUP
>>                       free(newscript);
>>                   }
>>   	YY_BREAK
>> -case 26:
>> +case 27:
>>   *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>>   yyg->yy_c_buf_p = yy_cp = yy_bp + 8;
>>   YY_DO_BEFORE_ACTION; /* set up yytext again */
>>   YY_RULE_SETUP
>> -#line 244 "libxlu_disk_l.l"
>> +#line 253 "libxlu_disk_l.l"
>>   { DPC->had_depr_prefix=1; DEPRECATE(0); }
>>   	YY_BREAK
>> -case 27:
>> +case 28:
>>   YY_RULE_SETUP
>> -#line 245 "libxlu_disk_l.l"
>> +#line 254 "libxlu_disk_l.l"
>>   { DPC->had_depr_prefix=1; DEPRECATE(0); }
>>   	YY_BREAK
>> -case 28:
>> +case 29:
>>   *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>>   yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
>>   YY_DO_BEFORE_ACTION; /* set up yytext again */
>>   YY_RULE_SETUP
>> -#line 246 "libxlu_disk_l.l"
>> +#line 255 "libxlu_disk_l.l"
>>   { DPC->had_depr_prefix=1; DEPRECATE(0); }
>>   	YY_BREAK
>> -case 29:
>> +case 30:
>>   *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>>   yyg->yy_c_buf_p = yy_cp = yy_bp + 6;
>>   YY_DO_BEFORE_ACTION; /* set up yytext again */
>>   YY_RULE_SETUP
>> -#line 247 "libxlu_disk_l.l"
>> +#line 256 "libxlu_disk_l.l"
>>   { DPC->had_depr_prefix=1; DEPRECATE(0); }
>>   	YY_BREAK
>> -case 30:
>> +case 31:
>>   *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>>   yyg->yy_c_buf_p = yy_cp = yy_bp + 5;
>>   YY_DO_BEFORE_ACTION; /* set up yytext again */
>>   YY_RULE_SETUP
>> -#line 248 "libxlu_disk_l.l"
>> +#line 257 "libxlu_disk_l.l"
>>   { DPC->had_depr_prefix=1; DEPRECATE(0); }
>>   	YY_BREAK
>> -case 31:
>> +case 32:
>>   *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
>>   yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
>>   YY_DO_BEFORE_ACTION; /* set up yytext again */
>>   YY_RULE_SETUP
>> -#line 249 "libxlu_disk_l.l"
>> +#line 258 "libxlu_disk_l.l"
>>   { DPC->had_depr_prefix=1; DEPRECATE(0); }
>>   	YY_BREAK
>> -case 32:
>> -/* rule 32 can match eol */
>> +case 33:
>> +/* rule 33 can match eol */
>>   YY_RULE_SETUP
>> -#line 251 "libxlu_disk_l.l"
>> +#line 260 "libxlu_disk_l.l"
>>   {
>>   		  xlu__disk_err(DPC,yytext,"unknown deprecated disk
>> prefix");
>>   		  return 0;
>>   		}
>>   	YY_BREAK
>>   /* positional parameters */
>> -case 33:
>> -/* rule 33 can match eol */
>> +case 34:
>> +/* rule 34 can match eol */
>>   YY_RULE_SETUP
>> -#line 258 "libxlu_disk_l.l"
>> +#line 267 "libxlu_disk_l.l"
>>   {
>>       STRIP(',');
>>
>> @@ -1816,27 +1847,27 @@ YY_RULE_SETUP
>>       }
>>   }
>>   	YY_BREAK
>> -case 34:
>> +case 35:
>>   YY_RULE_SETUP
>> -#line 284 "libxlu_disk_l.l"
>> +#line 293 "libxlu_disk_l.l"
>>   {
>>       BEGIN(LEXERR);
>>       yymore();
>>   }
>>   	YY_BREAK
>> -case 35:
>> +case 36:
>>   YY_RULE_SETUP
>> -#line 288 "libxlu_disk_l.l"
>> +#line 297 "libxlu_disk_l.l"
>>   {
>>       xlu__disk_err(DPC,yytext,"bad disk syntax"); return 0;
>>   }
>>   	YY_BREAK
>> -case 36:
>> +case 37:
>>   YY_RULE_SETUP
>> -#line 291 "libxlu_disk_l.l"
>> +#line 300 "libxlu_disk_l.l"
>>   YY_FATAL_ERROR( "flex scanner jammed" );
>>   	YY_BREAK
>> -#line 1839 "libxlu_disk_l.c"
>> +#line 1870 "libxlu_disk_l.c"
>>   			case YY_STATE_EOF(INITIAL):
>>   			case YY_STATE_EOF(LEXERR):
>>   				yyterminate();
>> @@ -2104,7 +2135,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
>>   		while ( yy_chk[yy_base[yy_current_state] + yy_c] !=
>> yy_current_state )
>>   			{
>>   			yy_current_state = (int) yy_def[yy_current_state];
>> -			if ( yy_current_state >= 355 )
>> +			if ( yy_current_state >= 372 )
>>   				yy_c = yy_meta[yy_c];
>>   			}
>>   		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
>> @@ -2128,11 +2159,11 @@ static int yy_get_next_buffer (yyscan_t
>> yyscanner)
>>   	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
>>   		{
>>   		yy_current_state = (int) yy_def[yy_current_state];
>> -		if ( yy_current_state >= 355 )
>> +		if ( yy_current_state >= 372 )
>>   			yy_c = yy_meta[yy_c];
>>   		}
>>   	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
>> -	yy_is_jam = (yy_current_state == 354);
>> +	yy_is_jam = (yy_current_state == 371);
>>   	if ( ! yy_is_jam )
>>   		*yyg->yy_state_ptr++ = yy_current_state;
>>
>> @@ -2941,4 +2972,4 @@ void yyfree (void * ptr , yyscan_t yyscanner)
>>
>>   #define YYTABLES_NAME "yytables"
>>
>> -#line 291 "libxlu_disk_l.l"
>> +#line 300 "libxlu_disk_l.l"
>> diff --git a/tools/libs/util/libxlu_disk_l.h b/tools/libs/util/libxlu_disk_l.h
>> index 6abeecf279..509aad67dc 100644
>> --- a/tools/libs/util/libxlu_disk_l.h
>> +++ b/tools/libs/util/libxlu_disk_l.h
>> @@ -694,7 +694,7 @@ extern int yylex (yyscan_t yyscanner);
>>   #undef yyTABLES_NAME
>>   #endif
>>
>> -#line 291 "libxlu_disk_l.l"
>> +#line 300 "libxlu_disk_l.l"
>>
>>   #line 699 "libxlu_disk_l.h"
>>   #undef xlu__disk_yyIN_HEADER
>> diff --git a/tools/libs/util/libxlu_disk_l.l b/tools/libs/util/libxlu_disk_l.l
>> index e115460d99..6d53c093a3 100644
>> --- a/tools/libs/util/libxlu_disk_l.l
>> +++ b/tools/libs/util/libxlu_disk_l.l
>> @@ -122,9 +122,17 @@ static void setbackendtype(DiskParseContext *dpc,
>> const char *str) {
>>       if (     !strcmp(str,"phy"))   DSET(dpc,backend,BACKEND,str,PHY);
>>       else if (!strcmp(str,"tap"))   DSET(dpc,backend,BACKEND,str,TAP);
>>       else if (!strcmp(str,"qdisk")) DSET(dpc,backend,BACKEND,str,QDISK);
>> +    else if (!strcmp(str,"standalone"))
>> DSET(dpc,backend,BACKEND,str,STANDALONE);
>>       else xlu__disk_err(dpc,str,"unknown value for backendtype");
>>   }
>>
>> +/* Sets ->specification from the string.  IDL should provide something for
>> this. */
>> +static void setspecification(DiskParseContext *dpc, const char *str) {
>> +    if      (!strcmp(str,"xen"))    DSET(dpc,specification,SPECIFICATION,str,XEN);
>> +    else if (!strcmp(str,"virtio"))
>> DSET(dpc,specification,SPECIFICATION,str,VIRTIO);
>> +    else xlu__disk_err(dpc,str,"unknown value for specification");
>> +}
>> +
>>   /* Sets ->colo-port from the string.  COLO need this. */
>>   static void setcoloport(DiskParseContext *dpc, const char *str) {
>>       int port = atoi(str);
>> @@ -192,6 +200,7 @@ devtype=[^,]*,?
>> 	{ xlu__disk_err(DPC,yytext,"unknown value for type"); }
>>   access=[^,]*,?	{ STRIP(','); setaccess(DPC, FROMEQUALS); }
>>   backend=[^,]*,? { STRIP(','); SAVESTRING("backend", backend_domname,
>> FROMEQUALS); }
>>   backendtype=[^,]*,? { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
>> +specification=[^,]*,? { STRIP(','); setspecification(DPC,FROMEQUALS); }
>>
>>   vdev=[^,]*,?	{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
>>   script=[^,]*,?	{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
>> diff --git a/tools/xl/xl_block.c b/tools/xl/xl_block.c
>> index 70eed431e4..8836c07d6b 100644
>> --- a/tools/xl/xl_block.c
>> +++ b/tools/xl/xl_block.c
>> @@ -119,6 +119,12 @@ int main_blockdetach(int argc, char **argv)
>>           fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
>>           return 1;
>>       }
>> +
>> +    if (disk.specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
>> +        fprintf(stderr, "Hotunplug isn't supported for specification virtio\n");
>> +        return 1;
>> +    }
>> +
>>       rc = !force ? libxl_device_disk_safe_remove(ctx, domid, &disk, 0) :
>>           libxl_device_disk_destroy(ctx, domid, &disk, 0);
>>       if (rc) {
>> --
>> 2.25.1
>>
Anthony PERARD July 20, 2022, 4:03 p.m. UTC | #3
On Sat, Jul 16, 2022 at 07:37:45PM +0300, Oleksandr Tyshchenko wrote:
> From: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>
> 
> This patch adds basic support for configuring and assisting virtio-mmio
> based virtio-disk backend (emulator) which is intended to run out of
> Qemu and could be run in any domain.
> Although the Virtio block device is quite different from traditional
> Xen PV block device (vbd) from the toolstack's point of view:
>  - as the frontend is virtio-blk which is not a Xenbus driver, nothing
>    written to Xenstore are fetched by the frontend currently ("vdev"
>    is not passed to the frontend). But this might need to be revised
>    in future, so frontend data might be written to Xenstore in order to
>    support hotplugging virtio devices or passing the backend domain id
>    on arch where the device-tree is not available.
>  - the ring-ref/event-channel are not used for the backend<->frontend
>    communication, the proposed IPC for Virtio is IOREQ/DM
> it is still a "block device" and ought to be integrated in existing
> "disk" handling. So, re-use (and adapt) "disk" parsing/configuration
> logic to deal with Virtio devices as well.
> 
> For the immediate purpose and an ability to extend that support for
> other use-cases in future (Qemu, virtio-pci, etc) perform the following
> actions:
> - Add new disk backend type (LIBXL_DISK_BACKEND_STANDALONE) and reflect
>   that in the configuration
> - Introduce new disk "specification" and "transport" fields to struct
>   libxl_device_disk. Both are written to the Xenstore. The transport
>   field is only used for the specification "virtio" and it assumes
>   only "mmio" value for now.
> - Introduce new "specification" option with "xen" communication
>   protocol being default value.
> - Add new device kind (LIBXL__DEVICE_KIND_VIRTIO_DISK) as current
>   one (LIBXL__DEVICE_KIND_VBD) doesn't fit into Virtio disk model
> 
> An example of domain configuration for Virtio disk:
> disk = [ 'phy:/dev/mmcblk0p3, xvda1, backendtype=standalone, specification=virtio']
> 
> Nothing has changed for default Xen disk configuration.
> 
> Please note, this patch is not enough for virtio-disk to work
> on Xen (Arm), as for every Virtio device (including disk) we need
> to allocate Virtio MMIO params (IRQ and memory region) and pass
> them to the backend, also update Guest device-tree. The subsequent
> patch will add these missing bits. For the current patch,
> the default "irq" and "base" are just written to the Xenstore.
> This is not an ideal splitting, but this way we avoid breaking
> the bisectability.
> 
> Signed-off-by: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com>

Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>

Thanks,
Julien Grall July 28, 2022, 6:28 p.m. UTC | #4
Hi Oleksandr,

On 16/07/2022 17:37, Oleksandr Tyshchenko wrote:
> Changes V10.1 -> V11:
>     - Anthony already gave his Reviewed-by, I dropped it due to the changes
>     - George already gave his Acked-by, I dropped it due to the changes
>     - s/other/standalone for the backendtype

As discussed with Andrew on IRC, the golang changes are autogenerated. 
So I have kept George's acked-by and committed the series.

Cheers,
Oleksandr Tyshchenko July 28, 2022, 6:59 p.m. UTC | #5
чт, 28 июл. 2022 г., 21:28 Julien Grall <julien@xen.org>:

> Hi Oleksandr,
>


Hello Julien

(sorry for the possible format issues)


> On 16/07/2022 17:37, Oleksandr Tyshchenko wrote:
> > Changes V10.1 -> V11:
> >     - Anthony already gave his Reviewed-by, I dropped it due to the
> changes
> >     - George already gave his Acked-by, I dropped it due to the changes
> >     - s/other/standalone for the backendtype
>
> As discussed with Andrew on IRC, the golang changes are autogenerated.
> So I have kept George's acked-by and committed the series.
>


Thank you very much!


> Cheers,
>
> --
> Julien Grall
>
diff mbox series

Patch

diff --git a/docs/man/xl-disk-configuration.5.pod.in b/docs/man/xl-disk-configuration.5.pod.in
index 95d039655a..bc945cc517 100644
--- a/docs/man/xl-disk-configuration.5.pod.in
+++ b/docs/man/xl-disk-configuration.5.pod.in
@@ -232,7 +232,7 @@  Specifies the backend implementation to use
 
 =item Supported values
 
-phy, qdisk
+phy, qdisk, standalone
 
 =item Mandatory
 
@@ -244,11 +244,13 @@  Automatically determine which backend to use.
 
 =back
 
-This does not affect the guest's view of the device.  It controls
-which software implementation of the Xen backend driver is used.
+It controls which software implementation of the backend driver is used.
+Depending on the "specification" option this may affect the guest's view
+of the device.
 
 Not all backend drivers support all combinations of other options.
-For example, "phy" does not support formats other than "raw".
+For example, "phy" and "standalone" do not support formats other than "raw"
+and "standalone" does not support specifications other than "virtio".
 Normally this option should not be specified, in which case libxl will
 automatically determine the most suitable backend.
 
@@ -373,8 +375,36 @@  processing or causing malfunction to the frontend or the whole domain.
 
 Note frontends can ignore such recommendation.
 
+=item B<specification>=I<SPECIFICATION>
+
+=over 4
+
+=item Description
+
+Specifies the communication protocol (specification) to use for the chosen
+"backendtype" option
+
+=item Supported values
+
+xen, virtio
+
+=item Mandatory
+
+No
+
+=item Default value
+
+xen
+
 =back
 
+Besides forcing toolstack to use specific backend implementation, this also
+affects the guest's view of the device. For example, "virtio" requires
+Virtio frontend driver (virtio-blk) to be used. Please note, the virtual
+device (vdev) is not passed to the guest in that case, but it still must be
+specified for the internal purposes.
+
+=back
 
 =head1 COLO Parameters
 
diff --git a/tools/golang/xenlight/helpers.gen.go b/tools/golang/xenlight/helpers.gen.go
index dece545ee0..ad8c11eae1 100644
--- a/tools/golang/xenlight/helpers.gen.go
+++ b/tools/golang/xenlight/helpers.gen.go
@@ -1763,6 +1763,10 @@  x.DirectIoSafe = bool(xc.direct_io_safe)
 if err := x.DiscardEnable.fromC(&xc.discard_enable);err != nil {
 return fmt.Errorf("converting field DiscardEnable: %v", err)
 }
+x.Specification = DiskSpecification(xc.specification)
+x.Transport = DiskTransport(xc.transport)
+x.Irq = uint32(xc.irq)
+x.Base = uint64(xc.base)
 if err := x.ColoEnable.fromC(&xc.colo_enable);err != nil {
 return fmt.Errorf("converting field ColoEnable: %v", err)
 }
@@ -1800,6 +1804,10 @@  xc.direct_io_safe = C.bool(x.DirectIoSafe)
 if err := x.DiscardEnable.toC(&xc.discard_enable); err != nil {
 return fmt.Errorf("converting field DiscardEnable: %v", err)
 }
+xc.specification = C.libxl_disk_specification(x.Specification)
+xc.transport = C.libxl_disk_transport(x.Transport)
+xc.irq = C.uint32_t(x.Irq)
+xc.base = C.uint64_t(x.Base)
 if err := x.ColoEnable.toC(&xc.colo_enable); err != nil {
 return fmt.Errorf("converting field ColoEnable: %v", err)
 }
diff --git a/tools/golang/xenlight/types.gen.go b/tools/golang/xenlight/types.gen.go
index 253c9ad93d..b9143390f8 100644
--- a/tools/golang/xenlight/types.gen.go
+++ b/tools/golang/xenlight/types.gen.go
@@ -99,6 +99,20 @@  DiskBackendUnknown DiskBackend = 0
 DiskBackendPhy DiskBackend = 1
 DiskBackendTap DiskBackend = 2
 DiskBackendQdisk DiskBackend = 3
+DiskBackendStandalone DiskBackend = 4
+)
+
+type DiskSpecification int
+const(
+DiskSpecificationUnknown DiskSpecification = 0
+DiskSpecificationXen DiskSpecification = 1
+DiskSpecificationVirtio DiskSpecification = 2
+)
+
+type DiskTransport int
+const(
+DiskTransportUnknown DiskTransport = 0
+DiskTransportMmio DiskTransport = 1
 )
 
 type NicType int
@@ -645,6 +659,10 @@  Readwrite int
 IsCdrom int
 DirectIoSafe bool
 DiscardEnable Defbool
+Specification DiskSpecification
+Transport DiskTransport
+Irq uint32
+Base uint64
 ColoEnable Defbool
 ColoRestoreEnable Defbool
 ColoHost string
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index f351669039..2321a648a5 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -549,6 +549,13 @@ 
  */
 #define LIBXL_HAVE_ASSISTED_APIC 1
 
+/*
+ * LIBXL_HAVE_DEVICE_DISK_SPECIFICATION indicates that 'specification' and
+ * 'transport' fields (of libxl_disk_specification and libxl_disk_transport
+ * types respectively) are present in libxl_device_disk.
+ */
+#define LIBXL_HAVE_DEVICE_DISK_SPECIFICATION 1
+
 /*
  * libxl ABI compatibility
  *
diff --git a/tools/libs/light/libxl_device.c b/tools/libs/light/libxl_device.c
index e6025d135e..a75c21d433 100644
--- a/tools/libs/light/libxl_device.c
+++ b/tools/libs/light/libxl_device.c
@@ -289,9 +289,16 @@  static int disk_try_backend(disk_try_backend_args *a,
                             libxl_disk_backend backend)
  {
     libxl__gc *gc = a->gc;
+    libxl_disk_specification specification = a->disk->specification;
     /* returns 0 (ie, DISK_BACKEND_UNKNOWN) on failure, or
      * backend on success */
 
+    if ((specification == LIBXL_DISK_SPECIFICATION_VIRTIO &&
+         backend != LIBXL_DISK_BACKEND_STANDALONE) ||
+        (specification != LIBXL_DISK_SPECIFICATION_VIRTIO &&
+         backend == LIBXL_DISK_BACKEND_STANDALONE))
+        goto bad_specification;
+
     switch (backend) {
     case LIBXL_DISK_BACKEND_PHY:
         if (a->disk->format != LIBXL_DISK_FORMAT_RAW) {
@@ -329,6 +336,29 @@  static int disk_try_backend(disk_try_backend_args *a,
         if (a->disk->script) goto bad_script;
         return backend;
 
+    case LIBXL_DISK_BACKEND_STANDALONE:
+        if (a->disk->format != LIBXL_DISK_FORMAT_RAW)
+            goto bad_format;
+
+        if (a->disk->script)
+            goto bad_script;
+
+        if (libxl_defbool_val(a->disk->colo_enable))
+            goto bad_colo;
+
+        if (a->disk->backend_domid != LIBXL_TOOLSTACK_DOMID) {
+            LOG(DEBUG, "Disk vdev=%s, is using a storage driver domain, "
+                       "skipping physical device check", a->disk->vdev);
+            return backend;
+        }
+
+        if (libxl__try_phy_backend(a->stab.st_mode))
+            return backend;
+
+        LOG(DEBUG, "Disk vdev=%s, backend standalone unsuitable as phys path not a "
+                   "block device", a->disk->vdev);
+        return 0;
+
     default:
         LOG(DEBUG, "Disk vdev=%s, backend %d unknown", a->disk->vdev, backend);
         return 0;
@@ -352,6 +382,12 @@  static int disk_try_backend(disk_try_backend_args *a,
     LOG(DEBUG, "Disk vdev=%s, backend %s not compatible with colo",
         a->disk->vdev, libxl_disk_backend_to_string(backend));
     return 0;
+
+ bad_specification:
+    LOG(DEBUG, "Disk vdev=%s, backend %s not compatible with specification %s",
+        a->disk->vdev, libxl_disk_backend_to_string(backend),
+        libxl_disk_specification_to_string(specification));
+    return 0;
 }
 
 int libxl__backendpath_parse_domid(libxl__gc *gc, const char *be_path,
@@ -376,8 +412,9 @@  int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
     a.gc = gc;
     a.disk = disk;
 
-    LOG(DEBUG, "Disk vdev=%s spec.backend=%s", disk->vdev,
-               libxl_disk_backend_to_string(disk->backend));
+    LOG(DEBUG, "Disk vdev=%s spec.backend=%s specification=%s", disk->vdev,
+               libxl_disk_backend_to_string(disk->backend),
+               libxl_disk_specification_to_string(disk->specification));
 
     if (disk->format == LIBXL_DISK_FORMAT_EMPTY) {
         if (!disk->is_cdrom) {
@@ -392,7 +429,8 @@  int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
         }
         memset(&a.stab, 0, sizeof(a.stab));
     } else if ((disk->backend == LIBXL_DISK_BACKEND_UNKNOWN ||
-                disk->backend == LIBXL_DISK_BACKEND_PHY) &&
+                disk->backend == LIBXL_DISK_BACKEND_PHY ||
+                disk->backend == LIBXL_DISK_BACKEND_STANDALONE) &&
                disk->backend_domid == LIBXL_TOOLSTACK_DOMID &&
                !disk->script) {
         if (stat(disk->pdev_path, &a.stab)) {
@@ -408,7 +446,8 @@  int libxl__device_disk_set_backend(libxl__gc *gc, libxl_device_disk *disk) {
         ok=
             disk_try_backend(&a, LIBXL_DISK_BACKEND_PHY) ?:
             disk_try_backend(&a, LIBXL_DISK_BACKEND_QDISK) ?:
-            disk_try_backend(&a, LIBXL_DISK_BACKEND_TAP);
+            disk_try_backend(&a, LIBXL_DISK_BACKEND_TAP) ?:
+            disk_try_backend(&a, LIBXL_DISK_BACKEND_STANDALONE);
         if (ok)
             LOG(DEBUG, "Disk vdev=%s, using backend %s",
                        disk->vdev,
@@ -441,10 +480,25 @@  char *libxl__device_disk_string_of_backend(libxl_disk_backend backend)
         case LIBXL_DISK_BACKEND_QDISK: return "qdisk";
         case LIBXL_DISK_BACKEND_TAP: return "phy";
         case LIBXL_DISK_BACKEND_PHY: return "phy";
+        case LIBXL_DISK_BACKEND_STANDALONE: return "standalone";
+        default: return NULL;
+    }
+}
+
+char *libxl__device_disk_string_of_specification(libxl_disk_specification specification)
+{
+    switch (specification) {
+        case LIBXL_DISK_SPECIFICATION_XEN: return "xen";
+        case LIBXL_DISK_SPECIFICATION_VIRTIO: return "virtio";
         default: return NULL;
     }
 }
 
+char *libxl__device_disk_string_of_transport(libxl_disk_transport transport)
+{
+    return (transport == LIBXL_DISK_TRANSPORT_MMIO ? "mmio" : NULL);
+}
+
 const char *libxl__qemu_disk_format_string(libxl_disk_format format)
 {
     switch (format) {
diff --git a/tools/libs/light/libxl_disk.c b/tools/libs/light/libxl_disk.c
index 9da2b2ed27..ea3623dd6f 100644
--- a/tools/libs/light/libxl_disk.c
+++ b/tools/libs/light/libxl_disk.c
@@ -164,6 +164,30 @@  static int libxl__device_disk_setdefault(libxl__gc *gc, uint32_t domid,
     rc = libxl__resolve_domid(gc, disk->backend_domname, &disk->backend_domid);
     if (rc < 0) return rc;
 
+    if (disk->specification == LIBXL_DISK_SPECIFICATION_UNKNOWN)
+        disk->specification = LIBXL_DISK_SPECIFICATION_XEN;
+
+    if (disk->specification == LIBXL_DISK_SPECIFICATION_XEN &&
+        disk->transport != LIBXL_DISK_TRANSPORT_UNKNOWN) {
+        LOGD(ERROR, domid, "Transport is only supported for specification virtio");
+        return ERROR_INVAL;
+    }
+
+    /* Force transport mmio for specification virtio for now */
+    if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
+        if (!(disk->transport == LIBXL_DISK_TRANSPORT_UNKNOWN ||
+              disk->transport == LIBXL_DISK_TRANSPORT_MMIO)) {
+            LOGD(ERROR, domid, "Unsupported transport for specification virtio");
+            return ERROR_INVAL;
+        }
+        disk->transport = LIBXL_DISK_TRANSPORT_MMIO;
+    }
+
+    if (hotplug && disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
+        LOGD(ERROR, domid, "Hotplug isn't supported for specification virtio");
+        return ERROR_FAIL;
+    }
+
     /* Force Qdisk backend for CDROM devices of guests with a device model. */
     if (disk->is_cdrom != 0 &&
         libxl__domain_type(gc, domid) == LIBXL_DOMAIN_TYPE_HVM) {
@@ -205,6 +229,9 @@  static int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
         case LIBXL_DISK_BACKEND_QDISK:
             device->backend_kind = LIBXL__DEVICE_KIND_QDISK;
             break;
+        case LIBXL_DISK_BACKEND_STANDALONE:
+            device->backend_kind = LIBXL__DEVICE_KIND_VIRTIO_DISK;
+            break;
         default:
             LOGD(ERROR, domid, "Unrecognized disk backend type: %d",
                  disk->backend);
@@ -213,7 +240,8 @@  static int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
 
     device->domid = domid;
     device->devid = devid;
-    device->kind  = LIBXL__DEVICE_KIND_VBD;
+    device->kind = disk->backend == LIBXL_DISK_BACKEND_STANDALONE ?
+        LIBXL__DEVICE_KIND_VIRTIO_DISK : LIBXL__DEVICE_KIND_VBD;
 
     return 0;
 }
@@ -331,7 +359,14 @@  static void device_disk_add(libxl__egc *egc, uint32_t domid,
 
                 assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
                 break;
+            case LIBXL_DISK_BACKEND_STANDALONE:
+                dev = disk->pdev_path;
+
+                flexarray_append(back, "params");
+                flexarray_append(back, dev);
 
+                assert(device->backend_kind == LIBXL__DEVICE_KIND_VIRTIO_DISK);
+                break;
             case LIBXL_DISK_BACKEND_TAP:
                 LOG(ERROR, "blktap is not supported");
                 rc = ERROR_FAIL;
@@ -387,6 +422,14 @@  static void device_disk_add(libxl__egc *egc, uint32_t domid,
         flexarray_append_pair(back, "discard-enable",
                               libxl_defbool_val(disk->discard_enable) ?
                               "1" : "0");
+        flexarray_append(back, "specification");
+        flexarray_append(back, libxl__device_disk_string_of_specification(disk->specification));
+        if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
+            flexarray_append(back, "transport");
+            flexarray_append(back, libxl__device_disk_string_of_transport(disk->transport));
+            flexarray_append_pair(back, "base", GCSPRINTF("%"PRIu64, disk->base));
+            flexarray_append_pair(back, "irq", GCSPRINTF("%u", disk->irq));
+        }
 
         flexarray_append(front, "backend-id");
         flexarray_append(front, GCSPRINTF("%d", disk->backend_domid));
@@ -535,6 +578,53 @@  static int libxl__disk_from_xenstore(libxl__gc *gc, const char *libxl_path,
     }
     libxl_string_to_backend(ctx, tmp, &(disk->backend));
 
+    tmp = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/specification", libxl_path));
+    if (!tmp) {
+        LOG(DEBUG, "Missing xenstore node %s/specification, assuming specification xen", libxl_path);
+        disk->specification = LIBXL_DISK_SPECIFICATION_XEN;
+    } else {
+        rc = libxl_disk_specification_from_string(tmp, &disk->specification);
+        if (rc) {
+            LOG(ERROR, "Unable to parse xenstore node %s/specification", libxl_path);
+            goto cleanup;
+        }
+    }
+
+    if (disk->specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
+        tmp = libxl__xs_read(gc, XBT_NULL,
+                             GCSPRINTF("%s/transport", libxl_path));
+        if (!tmp) {
+            LOG(ERROR, "Missing xenstore node %s/transport", libxl_path);
+            goto cleanup;
+        }
+        rc = libxl_disk_transport_from_string(tmp, &disk->transport);
+        if (rc) {
+            LOG(ERROR, "Unable to parse xenstore node %s/transport", libxl_path);
+            goto cleanup;
+        }
+        if (disk->transport != LIBXL_DISK_TRANSPORT_MMIO) {
+            LOG(ERROR, "Only transport mmio is expected for specification virtio");
+            goto cleanup;
+        }
+
+        tmp = libxl__xs_read(gc, XBT_NULL,
+                             GCSPRINTF("%s/base", libxl_path));
+        if (!tmp) {
+            LOG(ERROR, "Missing xenstore node %s/base", libxl_path);
+            goto cleanup;
+        }
+        disk->base = strtoul(tmp, NULL, 10);
+
+        tmp = libxl__xs_read(gc, XBT_NULL,
+                             GCSPRINTF("%s/irq", libxl_path));
+        if (!tmp) {
+            LOG(ERROR, "Missing xenstore node %s/irq", libxl_path);
+            goto cleanup;
+        }
+        disk->irq = strtoul(tmp, NULL, 10);
+    }
+
     disk->vdev = xs_read(ctx->xsh, XBT_NULL,
                          GCSPRINTF("%s/dev", libxl_path), &len);
     if (!disk->vdev) {
@@ -578,6 +668,42 @@  cleanup:
     return rc;
 }
 
+static int libxl__device_disk_get_path(libxl__gc *gc, uint32_t domid,
+                                       char **path)
+{
+    const char *xen_dir, *virtio_dir;
+    char *xen_path, *virtio_path;
+    int rc;
+
+    /* default path */
+    xen_path = GCSPRINTF("%s/device/%s",
+                         libxl__xs_libxl_path(gc, domid),
+                         libxl__device_kind_to_string(LIBXL__DEVICE_KIND_VBD));
+
+    rc = libxl__xs_read_checked(gc, XBT_NULL, xen_path, &xen_dir);
+    if (rc)
+        return rc;
+
+    virtio_path = GCSPRINTF("%s/device/%s",
+                            libxl__xs_libxl_path(gc, domid),
+                            libxl__device_kind_to_string(LIBXL__DEVICE_KIND_VIRTIO_DISK));
+
+    rc = libxl__xs_read_checked(gc, XBT_NULL, virtio_path, &virtio_dir);
+    if (rc)
+        return rc;
+
+    if (xen_dir && virtio_dir) {
+        LOGD(ERROR, domid, "Invalid configuration, both xen and virtio paths are present");
+        return ERROR_INVAL;
+    } else if (virtio_dir) {
+        *path = virtio_path;
+    } else {
+        *path = xen_path;
+    }
+
+    return 0;
+}
+
 int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid,
                               const char *vdev, libxl_device_disk *disk)
 {
@@ -591,10 +717,12 @@  int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid,
 
     libxl_device_disk_init(disk);
 
-    libxl_path = libxl__domain_device_libxl_path(gc, domid, devid,
-                                                 LIBXL__DEVICE_KIND_VBD);
+    rc = libxl__device_disk_get_path(gc, domid, &libxl_path);
+    if (rc)
+        return rc;
 
-    rc = libxl__disk_from_xenstore(gc, libxl_path, devid, disk);
+    rc = libxl__disk_from_xenstore(gc, GCSPRINTF("%s/%d", libxl_path, devid),
+                                   devid, disk);
 
     GC_FREE;
     return rc;
@@ -608,16 +736,19 @@  int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
     char *fe_path, *libxl_path;
     char *val;
     int rc;
+    libxl__device_kind kind;
 
     diskinfo->backend = NULL;
 
     diskinfo->devid = libxl__device_disk_dev_number(disk->vdev, NULL, NULL);
 
-    /* tap devices entries in xenstore are written as vbd devices. */
+    /* tap devices entries in xenstore are written as vbd/virtio_disk devices. */
+    kind = disk->backend == LIBXL_DISK_BACKEND_STANDALONE ?
+        LIBXL__DEVICE_KIND_VIRTIO_DISK : LIBXL__DEVICE_KIND_VBD;
     fe_path = libxl__domain_device_frontend_path(gc, domid, diskinfo->devid,
-                                                 LIBXL__DEVICE_KIND_VBD);
+                                                 kind);
     libxl_path = libxl__domain_device_libxl_path(gc, domid, diskinfo->devid,
-                                                 LIBXL__DEVICE_KIND_VBD);
+                                                 kind);
     diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
                                 GCSPRINTF("%s/backend", libxl_path), NULL);
     if (!diskinfo->backend) {
@@ -1421,6 +1552,7 @@  LIBXL_DEFINE_DEVICE_LIST(disk)
 #define libxl__device_disk_update_devid NULL
 
 DEFINE_DEVICE_TYPE_STRUCT(disk, VBD, disks,
+    .get_path    = libxl__device_disk_get_path,
     .merge       = libxl_device_disk_merge,
     .dm_needed   = libxl_device_disk_dm_needed,
     .from_xenstore = (device_from_xenstore_fn_t)libxl__disk_from_xenstore,
diff --git a/tools/libs/light/libxl_internal.h b/tools/libs/light/libxl_internal.h
index bdef5a605e..cb9e8b3b8b 100644
--- a/tools/libs/light/libxl_internal.h
+++ b/tools/libs/light/libxl_internal.h
@@ -1493,6 +1493,8 @@  _hidden char * libxl__domain_pvcontrol_read(libxl__gc *gc,
 
 /* from xl_device */
 _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend);
+_hidden char *libxl__device_disk_string_of_specification(libxl_disk_specification specification);
+_hidden char *libxl__device_disk_string_of_transport(libxl_disk_transport transport);
 _hidden char *libxl__device_disk_string_of_format(libxl_disk_format format);
 _hidden const char *libxl__qemu_disk_format_string(libxl_disk_format format);
 _hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk*);
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index f3ceb38c9e..d634f304cd 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -130,6 +130,18 @@  libxl_disk_backend = Enumeration("disk_backend", [
     (1, "PHY"),
     (2, "TAP"),
     (3, "QDISK"),
+    (4, "STANDALONE"), # Only relying on the Xenstore data
+    ])
+
+libxl_disk_specification = Enumeration("disk_specification", [
+    (0, "UNKNOWN"),
+    (1, "XEN"),
+    (2, "VIRTIO"),
+    ])
+
+libxl_disk_transport = Enumeration("disk_transport", [
+    (0, "UNKNOWN"),
+    (1, "MMIO"),
     ])
 
 libxl_nic_type = Enumeration("nic_type", [
@@ -706,6 +718,12 @@  libxl_device_disk = Struct("device_disk", [
     ("is_cdrom", integer),
     ("direct_io_safe", bool),
     ("discard_enable", libxl_defbool),
+    ("specification", libxl_disk_specification),
+    ("transport", libxl_disk_transport),
+    # Note that virtio-mmio parameters (irq and base) are for internal use
+    # by libxl and can't be modified.
+    ("irq", uint32),
+    ("base", uint64),
     # Note that the COLO configuration settings should be considered unstable.
     # They may change incompatibly in future versions of Xen.
     ("colo_enable", libxl_defbool),
diff --git a/tools/libs/light/libxl_types_internal.idl b/tools/libs/light/libxl_types_internal.idl
index 3593e21dbb..8f71980aec 100644
--- a/tools/libs/light/libxl_types_internal.idl
+++ b/tools/libs/light/libxl_types_internal.idl
@@ -32,6 +32,7 @@  libxl__device_kind = Enumeration("device_kind", [
     (14, "PVCALLS"),
     (15, "VSND"),
     (16, "VINPUT"),
+    (17, "VIRTIO_DISK"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libs/light/libxl_utils.c b/tools/libs/light/libxl_utils.c
index e5e6b2da96..e403bd9bcf 100644
--- a/tools/libs/light/libxl_utils.c
+++ b/tools/libs/light/libxl_utils.c
@@ -297,6 +297,8 @@  int libxl_string_to_backend(libxl_ctx *ctx, char *s, libxl_disk_backend *backend
         *backend = LIBXL_DISK_BACKEND_TAP;
     } else if (!strcmp(s, "qdisk")) {
         *backend = LIBXL_DISK_BACKEND_QDISK;
+    } else if (!strcmp(s, "standalone")) {
+        *backend = LIBXL_DISK_BACKEND_STANDALONE;
     } else if (!strcmp(s, "tap")) {
         p = strchr(s, ':');
         if (!p) {
diff --git a/tools/libs/util/libxlu_disk_l.c b/tools/libs/util/libxlu_disk_l.c
index 32d4b74b58..0b59723b71 100644
--- a/tools/libs/util/libxlu_disk_l.c
+++ b/tools/libs/util/libxlu_disk_l.c
@@ -549,8 +549,8 @@  static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
 	yyg->yy_hold_char = *yy_cp; \
 	*yy_cp = '\0'; \
 	yyg->yy_c_buf_p = yy_cp;
-#define YY_NUM_RULES 36
-#define YY_END_OF_BUFFER 37
+#define YY_NUM_RULES 37
+#define YY_END_OF_BUFFER 38
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -558,74 +558,77 @@  struct yy_trans_info
 	flex_int32_t yy_verify;
 	flex_int32_t yy_nxt;
 	};
-static const flex_int16_t yy_acclist[575] =
+static const flex_int16_t yy_acclist[594] =
     {   0,
-       35,   35,   37,   33,   34,   36, 8193,   33,   34,   36,
-    16385, 8193,   33,   36,16385,   33,   34,   36,   34,   36,
-       33,   34,   36,   33,   34,   36,   33,   34,   36,   33,
-       34,   36,   33,   34,   36,   33,   34,   36,   33,   34,
-       36,   33,   34,   36,   33,   34,   36,   33,   34,   36,
-       33,   34,   36,   33,   34,   36,   33,   34,   36,   33,
-       34,   36,   33,   34,   36,   33,   34,   36,   35,   36,
-       36,   33,   33, 8193,   33, 8193,   33,16385, 8193,   33,
-     8193,   33,   33, 8224,   33,16416,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   35,
-     8193,   33, 8193,   33, 8193, 8224,   33, 8224,   33, 8224,
-       23,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33,   33,   33,   33,   33,   33,
-       33,   33,   33,   33,   33, 8224,   33, 8224,   33, 8224,
-       23,   33,   33,   28, 8224,   33,16416,   33,   33,   15,
-       33,   33,   33,   33,   33,   33,   33,   33,   33, 8217,
-     8224,   33,16409,16416,   33,   33,   31, 8224,   33,16416,
-       33, 8216, 8224,   33,16408,16416,   33,   33, 8219, 8224,
-       33,16411,16416,   33,   33,   33,   33,   33,   28, 8224,
-
-       33,   28, 8224,   33,   28,   33,   28, 8224,   33,    3,
-       33,   15,   33,   33,   33,   33,   33,   30, 8224,   33,
-    16416,   33,   33,   33, 8217, 8224,   33, 8217, 8224,   33,
-     8217,   33, 8217, 8224,   33,   33,   31, 8224,   33,   31,
-     8224,   33,   31,   33,   31, 8224, 8216, 8224,   33, 8216,
-     8224,   33, 8216,   33, 8216, 8224,   33, 8219, 8224,   33,
-     8219, 8224,   33, 8219,   33, 8219, 8224,   33,   33,   10,
-       33,   33,   28, 8224,   33,   28, 8224,   33,   28, 8224,
-       28,   33,   28,   33,    3,   33,   33,   33,   33,   33,
-       33,   33,   30, 8224,   33,   30, 8224,   33,   30,   33,
-
-       30, 8224,   33,   33,   29, 8224,   33,16416, 8217, 8224,
-       33, 8217, 8224,   33, 8217, 8224, 8217,   33, 8217,   33,
-       33,   31, 8224,   33,   31, 8224,   33,   31, 8224,   31,
-       33,   31, 8216, 8224,   33, 8216, 8224,   33, 8216, 8224,
-     8216,   33, 8216,   33, 8219, 8224,   33, 8219, 8224,   33,
-     8219, 8224, 8219,   33, 8219,   33,   33,   10,   23,   10,
-        7,   33,   33,   33,   33,   33,   33,   33,   13,   33,
-       30, 8224,   33,   30, 8224,   33,   30, 8224,   30,   33,
-       30,    2,   33,   29, 8224,   33,   29, 8224,   33,   29,
-       33,   29, 8224,   16,   33,   33,   11,   33,   22,   10,
-
-       10,   23,    7,   23,    7,   33,    8,   33,   33,   33,
-       33,    6,   33,   13,   33,    2,   23,    2,   33,   29,
-     8224,   33,   29, 8224,   33,   29, 8224,   29,   33,   29,
-       16,   33,   33,   11,   23,   11,   26, 8224,   33,16416,
-       22,   23,   22,    7,    7,   23,   33,    8,   23,    8,
-       33,   33,   33,   33,    6,   23,    6,    6,   23,    6,
-       23,   33,    2,    2,   23,   33,   33,   11,   11,   23,
-       26, 8224,   33,   26, 8224,   33,   26,   33,   26, 8224,
-       22,   23,   33,    8,    8,   23,   33,   33,   17,   18,
-        6,    6,   23,    6,    6,   33,   33,   14,   33,   26,
-
-     8224,   33,   26, 8224,   33,   26, 8224,   26,   33,   26,
-       33,   33,   33,   17,   23,   17,   18,   23,   18,    6,
-        6,   33,   33,   14,   33,   20,    9,   19,   17,   17,
-       23,   18,   18,   23,    6,    5,    6,   33,   21,   20,
-       23,   20,    9,   23,    9,   19,   23,   19,    4,    6,
-        5,    6,   33,   21,   23,   21,   20,   20,   23,    9,
-        9,   23,   19,   19,   23,    4,    6,   12,   33,   21,
-       21,   23,   12,   33
+       36,   36,   38,   34,   35,   37, 8193,   34,   35,   37,
+    16385, 8193,   34,   37,16385,   34,   35,   37,   35,   37,
+       34,   35,   37,   34,   35,   37,   34,   35,   37,   34,
+       35,   37,   34,   35,   37,   34,   35,   37,   34,   35,
+       37,   34,   35,   37,   34,   35,   37,   34,   35,   37,
+       34,   35,   37,   34,   35,   37,   34,   35,   37,   34,
+       35,   37,   34,   35,   37,   34,   35,   37,   36,   37,
+       37,   34,   34, 8193,   34, 8193,   34,16385, 8193,   34,
+     8193,   34,   34, 8225,   34,16417,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       36, 8193,   34, 8193,   34, 8193, 8225,   34, 8225,   34,
+     8225,   24,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34,   34,   34,   34,
+       34,   34,   34,   34,   34,   34,   34, 8225,   34, 8225,
+       34, 8225,   24,   34,   34,   29, 8225,   34,16417,   34,
+       34,   16,   34,   34,   34,   34,   34,   34,   34,   34,
+       34, 8218, 8225,   34,16410,16417,   34,   34,   32, 8225,
+       34,16417,   34, 8217, 8225,   34,16409,16417,   34,   34,
+       34, 8220, 8225,   34,16412,16417,   34,   34,   34,   34,
+
+       34,   29, 8225,   34,   29, 8225,   34,   29,   34,   29,
+     8225,   34,    3,   34,   16,   34,   34,   34,   34,   34,
+       31, 8225,   34,16417,   34,   34,   34, 8218, 8225,   34,
+     8218, 8225,   34, 8218,   34, 8218, 8225,   34,   34,   32,
+     8225,   34,   32, 8225,   34,   32,   34,   32, 8225, 8217,
+     8225,   34, 8217, 8225,   34, 8217,   34, 8217, 8225,   34,
+       34, 8220, 8225,   34, 8220, 8225,   34, 8220,   34, 8220,
+     8225,   34,   34,   11,   34,   34,   29, 8225,   34,   29,
+     8225,   34,   29, 8225,   29,   34,   29,   34,    3,   34,
+       34,   34,   34,   34,   34,   34,   31, 8225,   34,   31,
+
+     8225,   34,   31,   34,   31, 8225,   34,   34,   30, 8225,
+       34,16417, 8218, 8225,   34, 8218, 8225,   34, 8218, 8225,
+     8218,   34, 8218,   34,   34,   32, 8225,   34,   32, 8225,
+       34,   32, 8225,   32,   34,   32, 8217, 8225,   34, 8217,
+     8225,   34, 8217, 8225, 8217,   34, 8217,   34,   34, 8220,
+     8225,   34, 8220, 8225,   34, 8220, 8225, 8220,   34, 8220,
+       34,   34,   11,   24,   11,    7,   34,   34,   34,   34,
+       34,   34,   34,   14,   34,   31, 8225,   34,   31, 8225,
+       34,   31, 8225,   31,   34,   31,    2,   34,   30, 8225,
+       34,   30, 8225,   34,   30,   34,   30, 8225,   17,   34,
+
+       34,   12,   34,   34,   23,   11,   11,   24,    7,   24,
+        7,   34,    8,   34,   34,   34,   34,    6,   34,   14,
+       34,    2,   24,    2,   34,   30, 8225,   34,   30, 8225,
+       34,   30, 8225,   30,   34,   30,   17,   34,   34,   12,
+       24,   12,   34,   27, 8225,   34,16417,   23,   24,   23,
+        7,    7,   24,   34,    8,   24,    8,   34,   34,   34,
+       34,    6,   24,    6,    6,   24,    6,   24,   34,    2,
+        2,   24,   34,   34,   12,   12,   24,   34,   27, 8225,
+       34,   27, 8225,   34,   27,   34,   27, 8225,   23,   24,
+       34,    8,    8,   24,   34,   34,   18,   19,    6,    6,
+
+       24,    6,    6,   34,   34,   15,   34,   34,   27, 8225,
+       34,   27, 8225,   34,   27, 8225,   27,   34,   27,   34,
+       34,   34,   18,   24,   18,   19,   24,   19,    6,    6,
+       34,   34,   15,   34,   34,   21,    9,   20,   18,   18,
+       24,   19,   19,   24,    6,    5,    6,   34,   22,   34,
+       21,   24,   21,    9,   24,    9,   20,   24,   20,    4,
+        6,    5,    6,   34,   22,   24,   22,   34,   21,   21,
+       24,    9,    9,   24,   20,   20,   24,    4,    6,   13,
+       34,   22,   22,   24,   10,   13,   34,   10,   24,   10,
+       10,   10,   24
+
     } ;
 
-static const flex_int16_t yy_accept[356] =
+static const flex_int16_t yy_accept[373] =
     {   0,
         1,    1,    1,    2,    3,    4,    7,   12,   16,   19,
        21,   24,   27,   30,   33,   36,   39,   42,   45,   48,
@@ -633,39 +636,41 @@  static const flex_int16_t yy_accept[356] =
        74,   76,   79,   81,   82,   83,   84,   87,   87,   88,
        89,   90,   91,   92,   93,   94,   95,   96,   97,   98,
        99,  100,  101,  102,  103,  104,  105,  106,  107,  108,
-      109,  110,  111,  113,  115,  116,  118,  120,  121,  122,
+      109,  110,  111,  112,  114,  116,  117,  119,  121,  122,
       123,  124,  125,  126,  127,  128,  129,  130,  131,  132,
       133,  134,  135,  136,  137,  138,  139,  140,  141,  142,
-      143,  144,  145,  146,  148,  150,  151,  152,  153,  154,
-
-      158,  159,  160,  162,  163,  164,  165,  166,  167,  168,
-      169,  170,  175,  176,  177,  181,  182,  187,  188,  189,
-      194,  195,  196,  197,  198,  199,  202,  205,  207,  209,
-      210,  212,  214,  215,  216,  217,  218,  222,  223,  224,
-      225,  228,  231,  233,  235,  236,  237,  240,  243,  245,
-      247,  250,  253,  255,  257,  258,  261,  264,  266,  268,
-      269,  270,  271,  272,  273,  276,  279,  281,  283,  284,
-      285,  287,  288,  289,  290,  291,  292,  293,  296,  299,
-      301,  303,  304,  305,  309,  312,  315,  317,  319,  320,
-      321,  322,  325,  328,  330,  332,  333,  336,  339,  341,
-
-      343,  344,  345,  348,  351,  353,  355,  356,  357,  358,
-      360,  361,  362,  363,  364,  365,  366,  367,  368,  369,
-      371,  374,  377,  379,  381,  382,  383,  384,  387,  390,
-      392,  394,  396,  397,  398,  399,  400,  401,  403,  405,
-      406,  407,  408,  409,  410,  411,  412,  413,  414,  416,
-      418,  419,  420,  423,  426,  428,  430,  431,  433,  434,
-      436,  437,  441,  443,  444,  445,  447,  448,  450,  451,
-      452,  453,  454,  455,  457,  458,  460,  462,  463,  464,
-      466,  467,  468,  469,  471,  474,  477,  479,  481,  483,
-      484,  485,  487,  488,  489,  490,  491,  492,  494,  495,
-
-      496,  497,  498,  500,  503,  506,  508,  510,  511,  512,
-      513,  514,  516,  517,  519,  520,  521,  522,  523,  524,
-      526,  527,  528,  529,  530,  532,  533,  535,  536,  538,
-      539,  540,  542,  543,  545,  546,  548,  549,  551,  553,
-      554,  556,  557,  558,  560,  561,  563,  564,  566,  568,
-      570,  571,  573,  575,  575
+      143,  144,  145,  146,  147,  148,  150,  152,  153,  154,
+
+      155,  156,  160,  161,  162,  164,  165,  166,  167,  168,
+      169,  170,  171,  172,  177,  178,  179,  183,  184,  189,
+      190,  191,  192,  197,  198,  199,  200,  201,  202,  205,
+      208,  210,  212,  213,  215,  217,  218,  219,  220,  221,
+      225,  226,  227,  228,  231,  234,  236,  238,  239,  240,
+      243,  246,  248,  250,  253,  256,  258,  260,  261,  262,
+      265,  268,  270,  272,  273,  274,  275,  276,  277,  280,
+      283,  285,  287,  288,  289,  291,  292,  293,  294,  295,
+      296,  297,  300,  303,  305,  307,  308,  309,  313,  316,
+      319,  321,  323,  324,  325,  326,  329,  332,  334,  336,
+
+      337,  340,  343,  345,  347,  348,  349,  350,  353,  356,
+      358,  360,  361,  362,  363,  365,  366,  367,  368,  369,
+      370,  371,  372,  373,  374,  376,  379,  382,  384,  386,
+      387,  388,  389,  392,  395,  397,  399,  401,  402,  403,
+      404,  405,  406,  407,  409,  411,  412,  413,  414,  415,
+      416,  417,  418,  419,  420,  422,  424,  425,  426,  429,
+      432,  434,  436,  437,  439,  440,  442,  443,  444,  448,
+      450,  451,  452,  454,  455,  457,  458,  459,  460,  461,
+      462,  464,  465,  467,  469,  470,  471,  473,  474,  475,
+      476,  478,  479,  482,  485,  487,  489,  491,  492,  493,
+
+      495,  496,  497,  498,  499,  500,  502,  503,  504,  505,
+      506,  508,  509,  512,  515,  517,  519,  520,  521,  522,
+      523,  525,  526,  528,  529,  530,  531,  532,  533,  535,
+      536,  537,  538,  539,  540,  542,  543,  545,  546,  548,
+      549,  550,  551,  553,  554,  556,  557,  559,  560,  562,
+      564,  565,  567,  568,  569,  570,  572,  573,  575,  576,
+      578,  580,  582,  583,  585,  586,  588,  590,  591,  592,
+      594,  594
     } ;
 
 static const YY_CHAR yy_ec[256] =
@@ -708,216 +713,224 @@  static const YY_CHAR yy_meta[35] =
         1,    1,    1,    1
     } ;
 
-static const flex_int16_t yy_base[424] =
+static const flex_int16_t yy_base[443] =
     {   0,
-        0,    0,  901,  900,  902,  897,   33,   36,  905,  905,
-       45,   63,   31,   42,   51,   52,  890,   33,   65,   67,
-       69,   70,  889,   71,  888,   75,    0,  905,  893,  905,
-       91,   94,    0,    0,  103,  886,  112,    0,   89,   98,
-      113,   92,  114,   99,  100,   48,  121,  116,  119,   74,
-      124,  129,  123,  135,  132,  133,  137,  134,  138,  139,
-      141,    0,  155,    0,    0,  164,    0,    0,  849,  142,
-      152,  164,  140,  161,  165,  166,  167,  168,  169,  173,
-      174,  178,  176,  180,  184,  208,  189,  183,  192,  195,
-      215,  191,  193,  223,    0,    0,  905,  208,  204,  236,
-
-      219,  209,  238,  196,  237,  831,  242,  815,  241,  224,
-      243,  261,  244,  259,  277,  266,  286,  250,  288,  298,
-      249,  283,  274,  282,  294,  308,    0,  310,    0,  295,
-      305,  905,  308,  306,  313,  314,  342,  319,  316,  320,
-      331,    0,  349,    0,  342,  344,  356,    0,  358,    0,
-      365,    0,  367,    0,  354,  375,    0,  377,    0,  363,
-      356,  809,  327,  322,  384,    0,    0,    0,    0,  379,
-      905,  382,  384,  386,  390,  372,  392,  403,    0,  410,
-        0,  407,  413,  423,  426,    0,    0,    0,    0,  409,
-      424,  435,    0,    0,    0,    0,  437,    0,    0,    0,
-
-        0,  433,  444,    0,    0,    0,    0,  391,  440,  781,
-      905,  769,  439,  445,  444,  447,  449,  454,  453,  399,
-      464,    0,    0,    0,    0,  757,  465,  476,    0,  478,
-        0,  479,  476,  753,  462,  490,  749,  905,  745,  905,
-      483,  737,  424,  485,  487,  490,  500,  493,  905,  729,
-      905,  502,  518,    0,    0,    0,    0,  905,  498,  721,
-      905,  527,  713,    0,  705,  905,  495,  697,  905,  365,
-      521,  528,  530,  685,  905,  534,  540,  540,  657,  905,
-      537,  542,  650,  905,  553,    0,  557,    0,    0,  551,
-      641,  905,  558,  557,  633,  614,  613,  905,  547,  555,
-
-      563,  565,  569,  584,    0,    0,    0,    0,  583,  570,
-      585,  612,  905,  601,  905,  522,  580,  589,  594,  905,
-      600,  585,  563,  520,  905,  514,  905,  586,  486,  597,
-      480,  441,  905,  416,  905,  345,  905,  334,  905,  601,
-      254,  905,  242,  905,  200,  905,  151,  905,  905,  607,
-       86,  905,  905,  905,  620,  624,  627,  631,  635,  639,
-      643,  647,  651,  655,  659,  663,  667,  671,  675,  679,
-      683,  687,  691,  695,  699,  703,  707,  711,  715,  719,
-      723,  727,  731,  735,  739,  743,  747,  751,  755,  759,
-      763,  767,  771,  775,  779,  783,  787,  791,  795,  799,
-
-      803,  807,  811,  815,  819,  823,  827,  831,  835,  839,
-      843,  847,  851,  855,  859,  863,  867,  871,  875,  879,
-      883,  887,  891
+        0,    0,  936,  935,  937,  932,   33,   36,  940,  940,
+       45,   63,   31,   42,   51,   52,  925,   33,   65,   67,
+       69,   70,  924,   71,  923,   75,    0,  940,  928,  940,
+       91,   95,    0,    0,  104,  921,  113,    0,   91,   99,
+      114,   92,  115,   80,  100,   48,  119,  121,  122,   74,
+      123,  128,  131,  129,  125,  133,  135,  136,  137,  143,
+      138,  145,    0,  157,    0,    0,  168,    0,    0,  926,
+      140,  146,  165,  159,  152,  164,  155,  168,  171,  176,
+      177,  170,  180,  175,  184,  188,  212,  191,  185,  192,
+      193,  194,  219,  212,  199,  230,    0,    0,  940,  195,
+
+      200,  239,  235,  197,  246,  225,  226,  919,  244,  918,
+      243,  236,  245,  266,  248,  264,  282,  271,  291,  248,
+      270,  254,  300,  279,  296,  302,  288,  303,  311,    0,
+      315,    0,  311,  318,  940,  313,  319,  208,  313,  344,
+      321,  331,  325,  333,    0,  352,    0,  345,  347,  359,
+        0,  361,    0,  368,    0,  370,    0,  322,  366,  379,
+        0,  381,    0,  359,  357,  923,  382,  384,  392,    0,
+        0,    0,    0,  387,  940,  386,  390,  392,  329,  401,
+      397,  409,    0,  417,    0,  399,  412,  426,  429,    0,
+        0,    0,    0,  412,  427,  438,    0,    0,    0,    0,
+
+      440,    0,    0,    0,    0,  436,  405,  447,    0,    0,
+        0,    0,  438,  443,  922,  940,  921,  442,  450,  449,
+      452,  454,  459,  458,  453,  469,    0,    0,    0,    0,
+      920,  470,  481,    0,  483,    0,  484,  481,  919,  368,
+      467,  495,  918,  940,  917,  940,  488,  916,  479,  490,
+      492,  495,  505,  498,  940,  915,  940,  507,  523,    0,
+        0,    0,    0,  940,  503,  864,  940,  846,  532,  836,
+        0,  824,  940,  516,  796,  940,  513,  530,  536,  538,
+      784,  940,  542,  535,  547,  772,  940,  549,  551,  768,
+      940,  502,  562,    0,  564,    0,    0,  562,  764,  940,
+
+      544,  557,  760,  752,  744,  940,  552,  568,  571,  568,
+      581,  577,  588,    0,    0,    0,    0,  589,  580,  591,
+      736,  940,  728,  940,  601,  602,  597,  599,  940,  603,
+      720,  712,  700,  672,  940,  665,  940,  610,  656,  603,
+      648,  607,  629,  940,  627,  940,  625,  940,  624,  940,
+      607,  574,  940,  614,  572,  940,  491,  940,  433,  940,
+      940,  622,  389,  940,  303,  940,  261,  940,  204,  940,
+      940,  635,  639,  642,  646,  650,  654,  658,  662,  666,
+      670,  674,  678,  682,  686,  690,  694,  698,  702,  706,
+      710,  714,  718,  722,  726,  730,  734,  738,  742,  746,
+
+      750,  754,  758,  762,  766,  770,  774,  778,  782,  786,
+      790,  794,  798,  802,  806,  810,  814,  818,  822,  826,
+      830,  834,  838,  842,  846,  850,  854,  858,  862,  866,
+      870,  874,  878,  882,  886,  890,  894,  898,  902,  906,
+      910,  914
     } ;
 
-static const flex_int16_t yy_def[424] =
+static const flex_int16_t yy_def[443] =
     {   0,
-      354,    1,  355,  355,  354,  356,  357,  357,  354,  354,
-      358,  358,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,   12,  359,  354,  356,  354,
-      360,  357,  361,  361,  362,   12,  356,  363,   12,   12,
-       12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
+      371,    1,  372,  372,  371,  373,  374,  374,  371,  371,
+      375,  375,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,   12,   12,   12,  376,  371,  373,  371,
+      377,  374,  378,  378,  379,   12,  373,  380,   12,   12,
        12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,  359,  360,  361,  361,  364,  365,  365,  354,   12,
        12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,   12,   12,   12,   12,  362,   12,   12,   12,   12,
-       12,   12,   12,  364,  365,  365,  354,   12,   12,  366,
-
+       12,   12,  376,  377,  378,  378,  381,  382,  382,  371,
        12,   12,   12,   12,   12,   12,   12,   12,   12,   12,
-       12,  367,   86,   86,  368,   12,  369,   12,   12,  370,
-       12,   12,   12,   12,   12,  371,  372,  366,  372,   12,
-       12,  354,   86,   12,   12,   12,  373,   12,   12,   12,
-      374,  375,  367,  375,   86,   86,  376,  377,  368,  377,
-      378,  379,  369,  379,   12,  380,  381,  370,  381,   12,
-       12,  382,   12,   12,  371,  372,  372,  383,  383,   12,
-      354,   86,   86,   86,   12,   12,   12,  384,  385,  373,
-      385,   12,   12,  386,  374,  375,  375,  387,  387,   86,
-       86,  376,  377,  377,  388,  388,  378,  379,  379,  389,
-
-      389,   12,  380,  381,  381,  390,  390,   12,   12,  391,
-      354,  392,   86,   12,   86,   86,   86,   12,   86,   12,
-      384,  385,  385,  393,  393,  394,   86,  395,  396,  386,
-      396,   86,   86,  397,   12,  398,  391,  354,  399,  354,
-       86,  400,   12,   86,   86,   86,  401,   86,  354,  402,
-      354,   86,  395,  396,  396,  403,  403,  354,   86,  404,
-      354,  405,  406,  406,  399,  354,   86,  407,  354,   12,
-       86,   86,   86,  408,  354,  408,  408,   86,  402,  354,
-       86,   86,  404,  354,  409,  410,  405,  410,  406,   86,
-      407,  354,   12,   86,  411,  412,  408,  354,  408,  408,
-
-       86,   86,   86,  409,  410,  410,  413,  413,   86,   12,
-       86,  414,  354,  415,  354,  408,  408,   86,   86,  354,
-      416,  417,  418,  414,  354,  415,  354,  408,  408,   86,
-      419,  420,  354,  421,  354,  422,  354,  408,  354,   86,
-      423,  354,  420,  354,  421,  354,  422,  354,  354,   86,
-      423,  354,  354,    0,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354
+       12,   12,   12,   12,   12,   12,  379,   12,   12,   12,
+       12,   12,   12,   12,   12,  381,  382,  382,  371,   12,
+
+       12,  383,   12,   12,   12,   12,   12,   12,   12,   12,
+       12,   12,   12,  384,   87,   87,  385,   12,  386,   12,
+       12,   12,  387,   12,   12,   12,   12,   12,  388,  389,
+      383,  389,   12,   12,  371,   87,   12,   12,   12,  390,
+       12,   12,   12,  391,  392,  384,  392,   87,   87,  393,
+      394,  385,  394,  395,  396,  386,  396,   12,   12,  397,
+      398,  387,  398,   12,   12,  399,   12,   12,  388,  389,
+      389,  400,  400,   12,  371,   87,   87,   87,   12,   12,
+       12,  401,  402,  390,  402,   12,   12,  403,  391,  392,
+      392,  404,  404,   87,   87,  393,  394,  394,  405,  405,
+
+      395,  396,  396,  406,  406,   12,   12,  397,  398,  398,
+      407,  407,   12,   12,  408,  371,  409,   87,   12,   87,
+       87,   87,   12,   87,   12,  401,  402,  402,  410,  410,
+      411,   87,  412,  413,  403,  413,   87,   87,  414,   12,
+       12,  415,  408,  371,  416,  371,   87,  417,   12,   87,
+       87,   87,  418,   87,  371,  419,  371,   87,  412,  413,
+      413,  420,  420,  371,   87,  421,  371,   12,  422,  423,
+      423,  416,  371,   87,  424,  371,   12,   87,   87,   87,
+      425,  371,  425,  425,   87,  419,  371,   87,   87,  421,
+      371,   12,  426,  427,  422,  427,  423,   87,  424,  371,
+
+       12,   87,  428,  429,  425,  371,  425,  425,   87,   87,
+       87,   12,  426,  427,  427,  430,  430,   87,   12,   87,
+      431,  371,  432,  371,  425,  425,   87,   87,  371,   12,
+      433,  434,  435,  431,  371,  432,  371,  425,  425,   87,
+      436,   12,  437,  371,  438,  371,  439,  371,  425,  371,
+       87,  440,  371,   12,  437,  371,  438,  371,  439,  371,
+      371,   87,  440,  371,  441,  371,  442,  371,  442,  371,
+        0,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371
     } ;
 
-static const flex_int16_t yy_nxt[940] =
+static const flex_int16_t yy_nxt[975] =
     {   0,
         6,    7,    8,    9,    6,    6,    6,    6,   10,   11,
        12,   13,   14,   15,   16,   17,   18,   19,   17,   17,
        17,   17,   20,   17,   21,   22,   23,   24,   25,   17,
        26,   17,   17,   17,   32,   32,   33,   32,   32,   33,
        36,   34,   36,   42,   34,   29,   29,   29,   30,   35,
-       50,   36,   37,   38,   43,   44,   39,   36,   79,   45,
+       50,   36,   37,   38,   43,   44,   39,   36,   80,   45,
        36,   36,   40,   29,   29,   29,   30,   35,   46,   48,
        37,   38,   41,   47,   36,   49,   36,   53,   36,   36,
-       36,   56,   58,   36,   36,   55,   82,   60,   51,  342,
-       54,   61,   52,   29,   64,   32,   32,   33,   36,   65,
-
-       70,   36,   34,   29,   29,   29,   30,   36,   36,   36,
-       29,   38,   66,   66,   66,   67,   66,   71,   74,   66,
-       68,   72,   36,   36,   73,   36,   77,   78,   36,   76,
-       36,   53,   36,   36,   75,   85,   80,   83,   36,   86,
-       84,   36,   36,   36,   36,   81,   36,   36,   36,   36,
-       36,   36,   93,   89,  337,   98,   88,   29,   64,  101,
-       90,   36,   91,   65,   92,   87,   29,   95,   89,   99,
-       36,  100,   96,   36,   36,   36,   36,   36,   36,  106,
-      105,   85,   36,   36,  102,   36,  107,   36,  103,   36,
-      109,  112,   36,   36,  104,  108,  115,  110,   36,  117,
-
-       36,   36,   36,  335,   36,   36,  122,  111,   29,   29,
-       29,   30,  118,   36,  116,   29,   38,   36,   36,  113,
-      114,  119,  120,  123,   36,   29,   95,  121,   36,  134,
-      131,   96,  130,   36,  125,  124,  126,  126,   66,  127,
-      126,  132,  133,  126,  129,  333,   36,   36,  135,  137,
-       36,   36,   36,  140,  139,   35,   35,  352,   36,   36,
-       85,  141,  141,   66,  142,  141,  160,  145,  141,  144,
-       35,   35,   89,  117,  155,   36,  146,  147,  147,   66,
-      148,  147,  162,   36,  147,  150,  151,  151,   66,  152,
-      151,   36,   36,  151,  154,  120,  161,   36,  156,  156,
-
-       66,  157,  156,   36,   36,  156,  159,  164,  171,  163,
-       29,  166,   29,  168,   36,   36,  167,  170,  169,   35,
-       35,  172,   36,   36,  173,   36,  213,  184,   36,   36,
-      175,   36,  174,   29,  186,  212,   36,  349,  183,  187,
-      177,  176,  178,  178,   66,  179,  178,  182,  348,  178,
-      181,   29,  188,   35,   35,   35,   35,  189,   29,  193,
-       29,  195,  190,   36,  194,   36,  196,   29,  198,   29,
-      200,  191,   36,  199,   36,  201,  219,   29,  204,   29,
-      206,   36,  202,  205,  209,  207,   29,  166,   36,  293,
-      208,  214,  167,   35,   35,   35,   35,   35,   35,   36,
-
-       36,   36,  249,  218,  220,   29,  222,  216,   36,  217,
-      235,  223,   29,  224,  215,  226,   36,  227,  225,  346,
-       35,   35,   36,  228,  228,   66,  229,  228,   29,  186,
-      228,  231,  232,   36,  187,  233,   35,   29,  193,   29,
-      198,  234,   36,  194,  344,  199,   29,  204,  236,   36,
-       35,  241,  205,  242,   36,   35,   35,  270,   35,   35,
-       35,   35,  247,   36,   35,   35,   29,  222,  244,  262,
-      248,   36,  223,  243,  245,  246,   35,  252,   29,  254,
-       29,  256,  258,  342,  255,  259,  257,   35,   35,  339,
-       35,   35,   69,  264,   35,   35,   35,   35,   35,   35,
-
-      267,   35,   35,  275,   35,   35,   35,   35,  271,   35,
-       35,  276,  277,   35,   35,  272,  278,  315,  273,  281,
-       29,  254,  290,  313,  282,  275,  255,  285,  285,   66,
-      286,  285,   35,   35,  285,  288,  295,  298,  296,   35,
-       35,   35,   35,  298,  301,  328,  299,  294,   35,   35,
-      275,   35,   35,   35,  303,   29,  305,  300,  275,   29,
-      307,  306,   35,   35,  302,  308,  337,   36,   35,   35,
-      309,  310,  320,  316,   35,   35,   35,   35,  322,   36,
-       35,   35,  317,  275,  319,  311,   29,  305,  335,  275,
-      318,  321,  306,  323,   35,   35,   35,   35,  330,  329,
-
-       35,   35,  331,  333,  327,   35,   35,  338,   35,   35,
-      353,  340,   35,   35,  350,  325,  275,  315,   35,   35,
-       27,   27,   27,   27,   29,   29,   29,   31,   31,   31,
-       31,   36,   36,   36,   36,   62,  313,   62,   62,   63,
-       63,   63,   63,   65,  269,   65,   65,   35,   35,   35,
-       35,   69,   69,  261,   69,   94,   94,   94,   94,   96,
-      251,   96,   96,  128,  128,  128,  128,  143,  143,  143,
-      143,  149,  149,  149,  149,  153,  153,  153,  153,  158,
-      158,  158,  158,  165,  165,  165,  165,  167,  298,  167,
-      167,  180,  180,  180,  180,  185,  185,  185,  185,  187,
-
-      292,  187,  187,  192,  192,  192,  192,  194,  240,  194,
-      194,  197,  197,  197,  197,  199,  289,  199,  199,  203,
-      203,  203,  203,  205,  284,  205,  205,  210,  210,  210,
-      210,  169,  280,  169,  169,  221,  221,  221,  221,  223,
-      269,  223,  223,  230,  230,  230,  230,  189,  266,  189,
-      189,  196,  211,  196,  196,  201,  261,  201,  201,  207,
-      251,  207,  207,  237,  237,  237,  237,  239,  239,  239,
-      239,  225,  240,  225,  225,  250,  250,  250,  250,  253,
-      253,  253,  253,  255,  238,  255,  255,  260,  260,  260,
-      260,  263,  263,  263,  263,  265,  265,  265,  265,  268,
-
-      268,  268,  268,  274,  274,  274,  274,  279,  279,  279,
-      279,  257,  211,  257,  257,  283,  283,  283,  283,  287,
-      287,  287,  287,  264,  138,  264,  264,  291,  291,  291,
-      291,  297,  297,  297,  297,  304,  304,  304,  304,  306,
-      136,  306,  306,  312,  312,  312,  312,  314,  314,  314,
-      314,  308,   97,  308,  308,  324,  324,  324,  324,  326,
-      326,  326,  326,  332,  332,  332,  332,  334,  334,  334,
-      334,  336,  336,  336,  336,  341,  341,  341,  341,  343,
-      343,  343,  343,  345,  345,  345,  345,  347,  347,  347,
-      347,  351,  351,  351,  351,   36,   30,   59,   57,   36,
-
-       30,  354,   28,   28,    5,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354
+       36,   56,   58,   36,   36,   55,   83,   61,   51,   36,
+       54,   62,   52,   29,   65,   59,   32,   32,   33,   66,
+
+       36,   36,   71,   34,   29,   29,   29,   30,   36,   36,
+       77,   29,   38,   67,   67,   67,   68,   67,   75,   72,
+       67,   69,   73,   36,   36,   74,   78,   79,   36,   53,
+       36,   36,   36,   87,   36,   76,   84,   36,   36,   85,
+       36,   81,   36,   86,   36,   36,   36,   36,   82,   36,
+       92,   95,   36,  100,   36,   36,   89,   90,   88,   29,
+       65,   36,   91,  101,   36,   66,   90,   93,   36,   94,
+       29,   97,  102,   36,   36,  104,   98,   36,  103,   36,
+       36,  107,  108,  106,   36,   36,   36,  105,   86,   36,
+      109,  110,  111,   36,   36,  114,  112,   36,  117,  119,
+
+       36,   36,   36,   36,   36,  121,   36,  368,   36,   36,
+      120,  113,   29,   29,   29,   30,  118,   36,  134,   29,
+       38,   36,  127,  115,  116,  122,  123,  125,   36,  126,
+      128,  124,   29,   97,   36,   36,  180,  138,   98,  129,
+      129,   67,  130,  129,   36,   36,  129,  132,  133,  135,
+      136,  140,   36,   36,   36,   36,  142,   36,  137,   35,
+       35,  123,   86,   36,  370,  143,  144,  144,   67,  145,
+      144,  148,  158,  144,  147,   35,   35,   90,  119,   36,
+       36,  149,  150,  150,   67,  151,  150,  159,   36,  150,
+      153,  154,  154,   67,  155,  154,  164,   36,  154,  157,
+
+      160,  160,   67,  161,  160,   36,  368,  160,  163,  165,
+      166,   36,   36,   29,  170,  167,  168,   29,  172,  171,
+       36,  175,   36,  173,   35,   35,  176,   36,   36,  177,
+       36,   36,  188,  174,   36,   29,  190,  178,   36,  181,
+       36,  191,  223,  179,  182,  182,   67,  183,  182,  186,
+      206,  182,  185,  187,   29,  192,   35,   35,   35,   35,
+      193,   29,  197,   29,  199,  194,   36,  198,   36,  200,
+       29,  202,   29,  204,  195,   36,  203,   36,  205,  268,
+      207,   29,  209,   29,  211,  214,  213,  210,  218,  212,
+      217,   36,  353,   36,   29,  170,   36,   35,   35,  219,
+
+      171,   35,   35,   35,   35,  224,   36,  231,   36,  225,
+       36,   29,  227,  221,   36,  222,  232,  228,  220,   29,
+      229,   36,  240,   35,   35,  230,  233,  233,   67,  234,
+      233,   29,  190,  233,  236,  237,  348,  191,  238,   35,
+       29,  197,   29,  202,  239,   36,  198,   36,  203,   29,
+      209,  242,   36,   35,  247,  210,  255,  241,  248,   36,
+       35,   35,   36,   35,   35,   35,   35,  253,   36,   35,
+       35,   29,  227,  250,  269,  254,   36,  228,  249,  251,
+      252,   35,  258,   29,  260,   29,  262,  264,   36,  261,
+      265,  263,   35,   35,  346,   35,   35,   70,  271,   35,
+
+       35,   35,   35,   35,   35,  274,   35,   35,  282,   35,
+       35,   36,  277,  278,   35,   35,  283,  284,   35,   35,
+      279,  285,   36,  280,  288,   29,  260,   35,   35,  289,
+      312,  261,  293,  293,   67,  294,  293,  301,  306,  293,
+      296,   35,   35,  298,  303,  306,  304,   35,   35,   35,
+       35,  309,  308,   36,  307,  282,  302,  319,   35,   35,
+       35,   35,   35,  311,   29,  314,   29,  316,   35,   35,
+      315,  282,  317,   35,   35,  344,  310,  364,  325,   35,
+       35,  318,   35,   35,  329,  320,   36,  328,  332,   36,
+       29,  314,   35,   35,  330,  326,  315,  331,  327,  333,
+
+       35,   35,   35,   35,  282,  282,  340,  341,   35,   35,
+       35,   35,   36,  282,   35,   35,   36,  351,   35,   35,
+      362,  339,  365,   36,  338,  366,  342,  361,  360,  354,
+      358,  349,  356,   35,   35,   27,   27,   27,   27,   29,
+       29,   29,   31,   31,   31,   31,   36,   36,   36,   36,
+       63,  353,   63,   63,   64,   64,   64,   64,   66,  350,
+       66,   66,   35,   35,   35,   35,   70,   70,  324,   70,
+       96,   96,   96,   96,   98,  322,   98,   98,  131,  131,
+      131,  131,  146,  146,  146,  146,  152,  152,  152,  152,
+      156,  156,  156,  156,  162,  162,  162,  162,  169,  169,
+
+      169,  169,  171,  348,  171,  171,  184,  184,  184,  184,
+      189,  189,  189,  189,  191,  346,  191,  191,  196,  196,
+      196,  196,  198,  344,  198,  198,  201,  201,  201,  201,
+      203,  337,  203,  203,  208,  208,  208,  208,  210,  335,
+      210,  210,  215,  215,  215,  215,  173,  282,  173,  173,
+      226,  226,  226,  226,  228,  324,  228,  228,  235,  235,
+      235,  235,  193,  322,  193,  193,  200,  276,  200,  200,
+      205,  267,  205,  205,  212,  257,  212,  212,  243,  243,
+      243,  243,  245,  245,  245,  245,  230,  306,  230,  230,
+      256,  256,  256,  256,  259,  259,  259,  259,  261,  300,
+
+      261,  261,  266,  266,  266,  266,  270,  270,  270,  270,
+      272,  272,  272,  272,  275,  275,  275,  275,  281,  281,
+      281,  281,  286,  286,  286,  286,  263,  246,  263,  263,
+      290,  290,  290,  290,  295,  295,  295,  295,  271,  297,
+      271,  271,  299,  299,  299,  299,  305,  305,  305,  305,
+      313,  313,  313,  313,  315,  292,  315,  315,  321,  321,
+      321,  321,  323,  323,  323,  323,  317,  291,  317,  317,
+      334,  334,  334,  334,  336,  336,  336,  336,  343,  343,
+      343,  343,  345,  345,  345,  345,  347,  347,  347,  347,
+      352,  352,  352,  352,  355,  355,  355,  355,  357,  357,
+
+      357,  357,  359,  359,  359,  359,  363,  363,  363,  363,
+      367,  367,  367,  367,  369,  369,  369,  369,  287,  276,
+      273,  216,  267,  257,  246,  244,  216,  141,  139,   99,
+       36,   30,   60,   57,   36,   30,  371,   28,   28,    5,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371
     } ;
 
-static const flex_int16_t yy_chk[940] =
+static const flex_int16_t yy_chk[975] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -927,101 +940,105 @@  static const flex_int16_t yy_chk[940] =
        18,   14,   11,   11,   13,   14,   11,   46,   46,   14,
        15,   16,   11,   12,   12,   12,   12,   12,   14,   16,
        12,   12,   12,   15,   19,   16,   20,   20,   21,   22,
-       24,   22,   24,   50,   26,   21,   50,   26,   19,  351,
-       20,   26,   19,   31,   31,   32,   32,   32,   39,   31,
-
-       39,   42,   32,   35,   35,   35,   35,   40,   44,   45,
-       35,   35,   37,   37,   37,   37,   37,   39,   42,   37,
-       37,   40,   41,   43,   41,   48,   45,   45,   49,   44,
-       47,   47,   53,   51,   43,   53,   48,   51,   52,   54,
-       52,   55,   56,   58,   54,   49,   57,   59,   60,   73,
-       61,   70,   60,   61,  347,   70,   56,   63,   63,   73,
-       58,   71,   59,   63,   59,   55,   66,   66,   57,   71,
-       74,   72,   66,   72,   75,   76,   77,   78,   79,   78,
-       77,   79,   80,   81,   74,   83,   80,   82,   75,   84,
-       82,   85,   88,   85,   76,   81,   87,   83,   87,   89,
-
-       92,   89,   93,  345,   90,  104,   92,   84,   86,   86,
-       86,   86,   90,   99,   88,   86,   86,   98,  102,   86,
-       86,   91,   91,   93,   91,   94,   94,   91,  101,  104,
-      102,   94,  101,  110,   99,   98,  100,  100,  100,  100,
-      100,  103,  103,  100,  100,  343,  105,  103,  105,  107,
-      109,  107,  111,  110,  109,  113,  113,  341,  121,  118,
-      111,  112,  112,  112,  112,  112,  121,  113,  112,  112,
-      114,  114,  116,  116,  118,  116,  114,  115,  115,  115,
-      115,  115,  123,  123,  115,  115,  117,  117,  117,  117,
-      117,  124,  122,  117,  117,  119,  122,  119,  120,  120,
-
-      120,  120,  120,  125,  130,  120,  120,  125,  131,  124,
-      126,  126,  128,  128,  131,  134,  126,  130,  128,  133,
-      133,  133,  135,  136,  133,  139,  164,  140,  138,  140,
-      134,  164,  133,  141,  141,  163,  163,  338,  139,  141,
-      136,  135,  137,  137,  137,  137,  137,  138,  336,  137,
-      137,  143,  143,  145,  145,  146,  146,  143,  147,  147,
-      149,  149,  145,  155,  147,  161,  149,  151,  151,  153,
-      153,  146,  160,  151,  270,  153,  176,  156,  156,  158,
-      158,  176,  155,  156,  161,  158,  165,  165,  170,  270,
-      160,  170,  165,  172,  172,  173,  173,  174,  174,  175,
-
-      208,  177,  220,  175,  177,  178,  178,  173,  220,  174,
-      208,  178,  180,  180,  172,  182,  182,  183,  180,  334,
-      190,  190,  183,  184,  184,  184,  184,  184,  185,  185,
-      184,  184,  190,  243,  185,  191,  191,  192,  192,  197,
-      197,  202,  202,  192,  332,  197,  203,  203,  209,  209,
-      213,  213,  203,  214,  214,  215,  215,  243,  216,  216,
-      217,  217,  218,  218,  219,  219,  221,  221,  215,  235,
-      219,  235,  221,  214,  216,  217,  227,  227,  228,  228,
-      230,  230,  232,  331,  228,  233,  230,  233,  233,  329,
-      232,  232,  236,  236,  241,  241,  244,  244,  245,  245,
-
-      241,  246,  246,  247,  248,  248,  267,  267,  244,  259,
-      259,  247,  247,  252,  252,  245,  248,  326,  246,  252,
-      253,  253,  267,  324,  259,  316,  253,  262,  262,  262,
-      262,  262,  271,  271,  262,  262,  272,  276,  273,  272,
-      272,  273,  273,  277,  278,  316,  276,  271,  281,  281,
-      299,  278,  278,  282,  282,  285,  285,  277,  300,  287,
-      287,  285,  290,  290,  281,  287,  323,  293,  294,  294,
-      290,  293,  303,  299,  301,  301,  302,  302,  310,  310,
-      303,  303,  300,  317,  302,  294,  304,  304,  322,  328,
-      301,  309,  304,  311,  309,  309,  311,  311,  318,  317,
-
-      318,  318,  319,  321,  314,  319,  319,  328,  330,  330,
-      350,  330,  340,  340,  340,  312,  297,  296,  350,  350,
-      355,  355,  355,  355,  356,  356,  356,  357,  357,  357,
-      357,  358,  358,  358,  358,  359,  295,  359,  359,  360,
-      360,  360,  360,  361,  291,  361,  361,  362,  362,  362,
-      362,  363,  363,  283,  363,  364,  364,  364,  364,  365,
-      279,  365,  365,  366,  366,  366,  366,  367,  367,  367,
-      367,  368,  368,  368,  368,  369,  369,  369,  369,  370,
-      370,  370,  370,  371,  371,  371,  371,  372,  274,  372,
-      372,  373,  373,  373,  373,  374,  374,  374,  374,  375,
-
-      268,  375,  375,  376,  376,  376,  376,  377,  265,  377,
-      377,  378,  378,  378,  378,  379,  263,  379,  379,  380,
-      380,  380,  380,  381,  260,  381,  381,  382,  382,  382,
-      382,  383,  250,  383,  383,  384,  384,  384,  384,  385,
-      242,  385,  385,  386,  386,  386,  386,  387,  239,  387,
-      387,  388,  237,  388,  388,  389,  234,  389,  389,  390,
-      226,  390,  390,  391,  391,  391,  391,  392,  392,  392,
-      392,  393,  212,  393,  393,  394,  394,  394,  394,  395,
-      395,  395,  395,  396,  210,  396,  396,  397,  397,  397,
-      397,  398,  398,  398,  398,  399,  399,  399,  399,  400,
-
-      400,  400,  400,  401,  401,  401,  401,  402,  402,  402,
-      402,  403,  162,  403,  403,  404,  404,  404,  404,  405,
-      405,  405,  405,  406,  108,  406,  406,  407,  407,  407,
-      407,  408,  408,  408,  408,  409,  409,  409,  409,  410,
-      106,  410,  410,  411,  411,  411,  411,  412,  412,  412,
-      412,  413,   69,  413,  413,  414,  414,  414,  414,  415,
-      415,  415,  415,  416,  416,  416,  416,  417,  417,  417,
-      417,  418,  418,  418,  418,  419,  419,  419,  419,  420,
-      420,  420,  420,  421,  421,  421,  421,  422,  422,  422,
-      422,  423,  423,  423,  423,   36,   29,   25,   23,   17,
-
-        6,    5,    4,    3,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354,  354,
-      354,  354,  354,  354,  354,  354,  354,  354,  354
+       24,   22,   24,   50,   26,   21,   50,   26,   19,   44,
+       20,   26,   19,   31,   31,   24,   32,   32,   32,   31,
+
+       39,   42,   39,   32,   35,   35,   35,   35,   40,   45,
+       44,   35,   35,   37,   37,   37,   37,   37,   42,   39,
+       37,   37,   40,   41,   43,   41,   45,   45,   47,   47,
+       48,   49,   51,   54,   55,   43,   51,   52,   54,   52,
+       53,   48,   56,   53,   57,   58,   59,   61,   49,   71,
+       59,   61,   60,   71,   62,   72,   56,   62,   55,   64,
+       64,   75,   58,   72,   77,   64,   57,   60,   74,   60,
+       67,   67,   73,   76,   73,   75,   67,   78,   74,   82,
+       79,   78,   79,   77,   84,   80,   81,   76,   80,   83,
+       81,   82,   83,   85,   89,   86,   84,   86,   88,   90,
+
+       88,   90,   91,   92,  100,   92,  104,  369,   95,  101,
+       91,   85,   87,   87,   87,   87,   89,  138,  104,   87,
+       87,   94,  100,   87,   87,   93,   93,   94,   93,   95,
+      101,   93,   96,   96,  106,  107,  138,  107,   96,  102,
+      102,  102,  102,  102,  103,  112,  102,  102,  103,  105,
+      105,  109,  111,  109,  113,  105,  111,  120,  106,  115,
+      115,  122,  113,  122,  367,  112,  114,  114,  114,  114,
+      114,  115,  120,  114,  114,  116,  116,  118,  118,  121,
+      118,  116,  117,  117,  117,  117,  117,  121,  124,  117,
+      117,  119,  119,  119,  119,  119,  124,  127,  119,  119,
+
+      123,  123,  123,  123,  123,  125,  365,  123,  123,  125,
+      126,  126,  128,  129,  129,  127,  128,  131,  131,  129,
+      133,  134,  139,  131,  136,  136,  136,  134,  137,  136,
+      141,  158,  143,  133,  143,  144,  144,  136,  179,  139,
+      142,  144,  179,  137,  140,  140,  140,  140,  140,  141,
+      158,  140,  140,  142,  146,  146,  148,  148,  149,  149,
+      146,  150,  150,  152,  152,  148,  165,  150,  164,  152,
+      154,  154,  156,  156,  149,  159,  154,  240,  156,  240,
+      159,  160,  160,  162,  162,  165,  164,  160,  168,  162,
+      167,  167,  363,  168,  169,  169,  174,  176,  176,  174,
+
+      169,  177,  177,  178,  178,  180,  181,  186,  186,  181,
+      180,  182,  182,  177,  207,  178,  187,  182,  176,  184,
+      184,  187,  207,  194,  194,  184,  188,  188,  188,  188,
+      188,  189,  189,  188,  188,  194,  359,  189,  195,  195,
+      196,  196,  201,  201,  206,  206,  196,  213,  201,  208,
+      208,  214,  214,  218,  218,  208,  225,  213,  219,  219,
+      220,  220,  225,  221,  221,  222,  222,  223,  223,  224,
+      224,  226,  226,  220,  241,  224,  241,  226,  219,  221,
+      222,  232,  232,  233,  233,  235,  235,  237,  249,  233,
+      238,  235,  238,  238,  357,  237,  237,  242,  242,  247,
+
+      247,  250,  250,  251,  251,  247,  252,  252,  253,  254,
+      254,  292,  249,  250,  265,  265,  253,  253,  258,  258,
+      251,  254,  277,  252,  258,  259,  259,  274,  274,  265,
+      292,  259,  269,  269,  269,  269,  269,  277,  284,  269,
+      269,  278,  278,  274,  279,  283,  280,  279,  279,  280,
+      280,  285,  284,  301,  283,  307,  278,  301,  285,  285,
+      288,  288,  289,  289,  293,  293,  295,  295,  302,  302,
+      293,  308,  295,  298,  298,  355,  288,  352,  307,  310,
+      310,  298,  309,  309,  311,  302,  312,  310,  319,  319,
+      313,  313,  311,  311,  312,  308,  313,  318,  309,  320,
+
+      318,  318,  320,  320,  325,  326,  327,  328,  327,  327,
+      328,  328,  330,  338,  340,  340,  342,  340,  351,  351,
+      351,  326,  354,  354,  325,  362,  330,  349,  347,  342,
+      345,  338,  343,  362,  362,  372,  372,  372,  372,  373,
+      373,  373,  374,  374,  374,  374,  375,  375,  375,  375,
+      376,  341,  376,  376,  377,  377,  377,  377,  378,  339,
+      378,  378,  379,  379,  379,  379,  380,  380,  336,  380,
+      381,  381,  381,  381,  382,  334,  382,  382,  383,  383,
+      383,  383,  384,  384,  384,  384,  385,  385,  385,  385,
+      386,  386,  386,  386,  387,  387,  387,  387,  388,  388,
+
+      388,  388,  389,  333,  389,  389,  390,  390,  390,  390,
+      391,  391,  391,  391,  392,  332,  392,  392,  393,  393,
+      393,  393,  394,  331,  394,  394,  395,  395,  395,  395,
+      396,  323,  396,  396,  397,  397,  397,  397,  398,  321,
+      398,  398,  399,  399,  399,  399,  400,  305,  400,  400,
+      401,  401,  401,  401,  402,  304,  402,  402,  403,  403,
+      403,  403,  404,  303,  404,  404,  405,  299,  405,  405,
+      406,  290,  406,  406,  407,  286,  407,  407,  408,  408,
+      408,  408,  409,  409,  409,  409,  410,  281,  410,  410,
+      411,  411,  411,  411,  412,  412,  412,  412,  413,  275,
+
+      413,  413,  414,  414,  414,  414,  415,  415,  415,  415,
+      416,  416,  416,  416,  417,  417,  417,  417,  418,  418,
+      418,  418,  419,  419,  419,  419,  420,  272,  420,  420,
+      421,  421,  421,  421,  422,  422,  422,  422,  423,  270,
+      423,  423,  424,  424,  424,  424,  425,  425,  425,  425,
+      426,  426,  426,  426,  427,  268,  427,  427,  428,  428,
+      428,  428,  429,  429,  429,  429,  430,  266,  430,  430,
+      431,  431,  431,  431,  432,  432,  432,  432,  433,  433,
+      433,  433,  434,  434,  434,  434,  435,  435,  435,  435,
+      436,  436,  436,  436,  437,  437,  437,  437,  438,  438,
+
+      438,  438,  439,  439,  439,  439,  440,  440,  440,  440,
+      441,  441,  441,  441,  442,  442,  442,  442,  256,  248,
+      245,  243,  239,  231,  217,  215,  166,  110,  108,   70,
+       36,   29,   25,   23,   17,    6,    5,    4,    3,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371,  371,  371,  371,  371,  371,  371,
+      371,  371,  371,  371
     } ;
 
 #define YY_TRAILING_MASK 0x2000
@@ -1160,9 +1177,17 @@  static void setbackendtype(DiskParseContext *dpc, const char *str) {
     if (     !strcmp(str,"phy"))   DSET(dpc,backend,BACKEND,str,PHY);
     else if (!strcmp(str,"tap"))   DSET(dpc,backend,BACKEND,str,TAP);
     else if (!strcmp(str,"qdisk")) DSET(dpc,backend,BACKEND,str,QDISK);
+    else if (!strcmp(str,"standalone")) DSET(dpc,backend,BACKEND,str,STANDALONE);
     else xlu__disk_err(dpc,str,"unknown value for backendtype");
 }
 
+/* Sets ->specification from the string.  IDL should provide something for this. */
+static void setspecification(DiskParseContext *dpc, const char *str) {
+    if      (!strcmp(str,"xen"))    DSET(dpc,specification,SPECIFICATION,str,XEN);
+    else if (!strcmp(str,"virtio")) DSET(dpc,specification,SPECIFICATION,str,VIRTIO);
+    else xlu__disk_err(dpc,str,"unknown value for specification");
+}
+
 /* Sets ->colo-port from the string.  COLO need this. */
 static void setcoloport(DiskParseContext *dpc, const char *str) {
     int port = atoi(str);
@@ -1199,9 +1224,9 @@  static int vdev_and_devtype(DiskParseContext *dpc, char *str) {
 #undef DPC /* needs to be defined differently the actual lexer */
 #define DPC ((DiskParseContext*)yyextra)
 
-#line 1202 "libxlu_disk_l.c"
+#line 1227 "libxlu_disk_l.c"
 
-#line 1204 "libxlu_disk_l.c"
+#line 1229 "libxlu_disk_l.c"
 
 #define INITIAL 0
 #define LEXERR 1
@@ -1477,13 +1502,13 @@  YY_DECL
 		}
 
 	{
-#line 177 "libxlu_disk_l.l"
+#line 185 "libxlu_disk_l.l"
 
 
-#line 180 "libxlu_disk_l.l"
+#line 188 "libxlu_disk_l.l"
  /*----- the scanner rules which do the parsing -----*/
 
-#line 1486 "libxlu_disk_l.c"
+#line 1511 "libxlu_disk_l.c"
 
 	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
 		{
@@ -1515,14 +1540,14 @@  yy_match:
 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 				{
 				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 355 )
+				if ( yy_current_state >= 372 )
 					yy_c = yy_meta[yy_c];
 				}
 			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
 			*yyg->yy_state_ptr++ = yy_current_state;
 			++yy_cp;
 			}
-		while ( yy_current_state != 354 );
+		while ( yy_current_state != 371 );
 
 yy_find_action:
 		yy_current_state = *--yyg->yy_state_ptr;
@@ -1572,152 +1597,158 @@  do_action:	/* This label is used only to access EOF actions. */
 case 1:
 /* rule 1 can match eol */
 YY_RULE_SETUP
-#line 182 "libxlu_disk_l.l"
+#line 190 "libxlu_disk_l.l"
 { /* ignore whitespace before parameters */ }
 	YY_BREAK
 /* ordinary parameters setting enums or strings */
 case 2:
 /* rule 2 can match eol */
 YY_RULE_SETUP
-#line 186 "libxlu_disk_l.l"
+#line 194 "libxlu_disk_l.l"
 { STRIP(','); setformat(DPC, FROMEQUALS); }
 	YY_BREAK
 case 3:
 YY_RULE_SETUP
-#line 188 "libxlu_disk_l.l"
+#line 196 "libxlu_disk_l.l"
 { DPC->disk->is_cdrom = 1; }
 	YY_BREAK
 case 4:
 YY_RULE_SETUP
-#line 189 "libxlu_disk_l.l"
+#line 197 "libxlu_disk_l.l"
 { DPC->disk->is_cdrom = 1; }
 	YY_BREAK
 case 5:
 YY_RULE_SETUP
-#line 190 "libxlu_disk_l.l"
+#line 198 "libxlu_disk_l.l"
 { DPC->disk->is_cdrom = 0; }
 	YY_BREAK
 case 6:
 /* rule 6 can match eol */
 YY_RULE_SETUP
-#line 191 "libxlu_disk_l.l"
+#line 199 "libxlu_disk_l.l"
 { xlu__disk_err(DPC,yytext,"unknown value for type"); }
 	YY_BREAK
 case 7:
 /* rule 7 can match eol */
 YY_RULE_SETUP
-#line 193 "libxlu_disk_l.l"
+#line 201 "libxlu_disk_l.l"
 { STRIP(','); setaccess(DPC, FROMEQUALS); }
 	YY_BREAK
 case 8:
 /* rule 8 can match eol */
 YY_RULE_SETUP
-#line 194 "libxlu_disk_l.l"
+#line 202 "libxlu_disk_l.l"
 { STRIP(','); SAVESTRING("backend", backend_domname, FROMEQUALS); }
 	YY_BREAK
 case 9:
 /* rule 9 can match eol */
 YY_RULE_SETUP
-#line 195 "libxlu_disk_l.l"
+#line 203 "libxlu_disk_l.l"
 { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
 	YY_BREAK
 case 10:
 /* rule 10 can match eol */
 YY_RULE_SETUP
-#line 197 "libxlu_disk_l.l"
-{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
+#line 204 "libxlu_disk_l.l"
+{ STRIP(','); setspecification(DPC,FROMEQUALS); }
 	YY_BREAK
 case 11:
 /* rule 11 can match eol */
 YY_RULE_SETUP
-#line 198 "libxlu_disk_l.l"
-{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
+#line 206 "libxlu_disk_l.l"
+{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
 	YY_BREAK
 case 12:
+/* rule 12 can match eol */
 YY_RULE_SETUP
-#line 199 "libxlu_disk_l.l"
-{ DPC->disk->direct_io_safe = 1; }
+#line 207 "libxlu_disk_l.l"
+{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
 	YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 200 "libxlu_disk_l.l"
-{ libxl_defbool_set(&DPC->disk->discard_enable, true); }
+#line 208 "libxlu_disk_l.l"
+{ DPC->disk->direct_io_safe = 1; }
 	YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 201 "libxlu_disk_l.l"
-{ libxl_defbool_set(&DPC->disk->discard_enable, false); }
+#line 209 "libxlu_disk_l.l"
+{ libxl_defbool_set(&DPC->disk->discard_enable, true); }
 	YY_BREAK
-/* Note that the COLO configuration settings should be considered unstable.
-  * They may change incompatibly in future versions of Xen. */
 case 15:
 YY_RULE_SETUP
-#line 204 "libxlu_disk_l.l"
-{ libxl_defbool_set(&DPC->disk->colo_enable, true); }
+#line 210 "libxlu_disk_l.l"
+{ libxl_defbool_set(&DPC->disk->discard_enable, false); }
 	YY_BREAK
+/* Note that the COLO configuration settings should be considered unstable.
+  * They may change incompatibly in future versions of Xen. */
 case 16:
 YY_RULE_SETUP
-#line 205 "libxlu_disk_l.l"
-{ libxl_defbool_set(&DPC->disk->colo_enable, false); }
+#line 213 "libxlu_disk_l.l"
+{ libxl_defbool_set(&DPC->disk->colo_enable, true); }
 	YY_BREAK
 case 17:
-/* rule 17 can match eol */
 YY_RULE_SETUP
-#line 206 "libxlu_disk_l.l"
-{ STRIP(','); SAVESTRING("colo-host", colo_host, FROMEQUALS); }
+#line 214 "libxlu_disk_l.l"
+{ libxl_defbool_set(&DPC->disk->colo_enable, false); }
 	YY_BREAK
 case 18:
 /* rule 18 can match eol */
 YY_RULE_SETUP
-#line 207 "libxlu_disk_l.l"
-{ STRIP(','); setcoloport(DPC, FROMEQUALS); }
+#line 215 "libxlu_disk_l.l"
+{ STRIP(','); SAVESTRING("colo-host", colo_host, FROMEQUALS); }
 	YY_BREAK
 case 19:
 /* rule 19 can match eol */
 YY_RULE_SETUP
-#line 208 "libxlu_disk_l.l"
-{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
+#line 216 "libxlu_disk_l.l"
+{ STRIP(','); setcoloport(DPC, FROMEQUALS); }
 	YY_BREAK
 case 20:
 /* rule 20 can match eol */
 YY_RULE_SETUP
-#line 209 "libxlu_disk_l.l"
-{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
+#line 217 "libxlu_disk_l.l"
+{ STRIP(','); SAVESTRING("colo-export", colo_export, FROMEQUALS); }
 	YY_BREAK
 case 21:
 /* rule 21 can match eol */
 YY_RULE_SETUP
-#line 210 "libxlu_disk_l.l"
+#line 218 "libxlu_disk_l.l"
+{ STRIP(','); SAVESTRING("active-disk", active_disk, FROMEQUALS); }
+	YY_BREAK
+case 22:
+/* rule 22 can match eol */
+YY_RULE_SETUP
+#line 219 "libxlu_disk_l.l"
 { STRIP(','); SAVESTRING("hidden-disk", hidden_disk, FROMEQUALS); }
 	YY_BREAK
 /* the target magic parameter, eats the rest of the string */
-case 22:
+case 23:
 YY_RULE_SETUP
-#line 214 "libxlu_disk_l.l"
+#line 223 "libxlu_disk_l.l"
 { STRIP(','); SAVESTRING("target", pdev_path, FROMEQUALS); }
 	YY_BREAK
 /* unknown parameters */
-case 23:
-/* rule 23 can match eol */
+case 24:
+/* rule 24 can match eol */
 YY_RULE_SETUP
-#line 218 "libxlu_disk_l.l"
+#line 227 "libxlu_disk_l.l"
 { xlu__disk_err(DPC,yytext,"unknown parameter"); }
 	YY_BREAK
 /* deprecated prefixes */
 /* the "/.*" in these patterns ensures that they count as if they
    * matched the whole string, so these patterns take precedence */
-case 24:
+case 25:
 YY_RULE_SETUP
-#line 225 "libxlu_disk_l.l"
+#line 234 "libxlu_disk_l.l"
 {
                     STRIP(':');
                     DPC->had_depr_prefix=1; DEPRECATE("use `[format=]...,'");
                     setformat(DPC, yytext);
                  }
 	YY_BREAK
-case 25:
+case 26:
 YY_RULE_SETUP
-#line 231 "libxlu_disk_l.l"
+#line 240 "libxlu_disk_l.l"
 {
                     char *newscript;
                     STRIP(':');
@@ -1731,65 +1762,65 @@  YY_RULE_SETUP
                     free(newscript);
                 }
 	YY_BREAK
-case 26:
+case 27:
 *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
 yyg->yy_c_buf_p = yy_cp = yy_bp + 8;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 244 "libxlu_disk_l.l"
+#line 253 "libxlu_disk_l.l"
 { DPC->had_depr_prefix=1; DEPRECATE(0); }
 	YY_BREAK
-case 27:
+case 28:
 YY_RULE_SETUP
-#line 245 "libxlu_disk_l.l"
+#line 254 "libxlu_disk_l.l"
 { DPC->had_depr_prefix=1; DEPRECATE(0); }
 	YY_BREAK
-case 28:
+case 29:
 *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
 yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 246 "libxlu_disk_l.l"
+#line 255 "libxlu_disk_l.l"
 { DPC->had_depr_prefix=1; DEPRECATE(0); }
 	YY_BREAK
-case 29:
+case 30:
 *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
 yyg->yy_c_buf_p = yy_cp = yy_bp + 6;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 247 "libxlu_disk_l.l"
+#line 256 "libxlu_disk_l.l"
 { DPC->had_depr_prefix=1; DEPRECATE(0); }
 	YY_BREAK
-case 30:
+case 31:
 *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
 yyg->yy_c_buf_p = yy_cp = yy_bp + 5;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 248 "libxlu_disk_l.l"
+#line 257 "libxlu_disk_l.l"
 { DPC->had_depr_prefix=1; DEPRECATE(0); }
 	YY_BREAK
-case 31:
+case 32:
 *yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */
 yyg->yy_c_buf_p = yy_cp = yy_bp + 4;
 YY_DO_BEFORE_ACTION; /* set up yytext again */
 YY_RULE_SETUP
-#line 249 "libxlu_disk_l.l"
+#line 258 "libxlu_disk_l.l"
 { DPC->had_depr_prefix=1; DEPRECATE(0); }
 	YY_BREAK
-case 32:
-/* rule 32 can match eol */
+case 33:
+/* rule 33 can match eol */
 YY_RULE_SETUP
-#line 251 "libxlu_disk_l.l"
+#line 260 "libxlu_disk_l.l"
 {
 		  xlu__disk_err(DPC,yytext,"unknown deprecated disk prefix");
 		  return 0;
 		}
 	YY_BREAK
 /* positional parameters */
-case 33:
-/* rule 33 can match eol */
+case 34:
+/* rule 34 can match eol */
 YY_RULE_SETUP
-#line 258 "libxlu_disk_l.l"
+#line 267 "libxlu_disk_l.l"
 {
     STRIP(',');
 
@@ -1816,27 +1847,27 @@  YY_RULE_SETUP
     }
 }
 	YY_BREAK
-case 34:
+case 35:
 YY_RULE_SETUP
-#line 284 "libxlu_disk_l.l"
+#line 293 "libxlu_disk_l.l"
 {
     BEGIN(LEXERR);
     yymore();
 }
 	YY_BREAK
-case 35:
+case 36:
 YY_RULE_SETUP
-#line 288 "libxlu_disk_l.l"
+#line 297 "libxlu_disk_l.l"
 {
     xlu__disk_err(DPC,yytext,"bad disk syntax"); return 0;
 }
 	YY_BREAK
-case 36:
+case 37:
 YY_RULE_SETUP
-#line 291 "libxlu_disk_l.l"
+#line 300 "libxlu_disk_l.l"
 YY_FATAL_ERROR( "flex scanner jammed" );
 	YY_BREAK
-#line 1839 "libxlu_disk_l.c"
+#line 1870 "libxlu_disk_l.c"
 			case YY_STATE_EOF(INITIAL):
 			case YY_STATE_EOF(LEXERR):
 				yyterminate();
@@ -2104,7 +2135,7 @@  static int yy_get_next_buffer (yyscan_t yyscanner)
 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 			{
 			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 355 )
+			if ( yy_current_state >= 372 )
 				yy_c = yy_meta[yy_c];
 			}
 		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
@@ -2128,11 +2159,11 @@  static int yy_get_next_buffer (yyscan_t yyscanner)
 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
 		{
 		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 355 )
+		if ( yy_current_state >= 372 )
 			yy_c = yy_meta[yy_c];
 		}
 	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
-	yy_is_jam = (yy_current_state == 354);
+	yy_is_jam = (yy_current_state == 371);
 	if ( ! yy_is_jam )
 		*yyg->yy_state_ptr++ = yy_current_state;
 
@@ -2941,4 +2972,4 @@  void yyfree (void * ptr , yyscan_t yyscanner)
 
 #define YYTABLES_NAME "yytables"
 
-#line 291 "libxlu_disk_l.l"
+#line 300 "libxlu_disk_l.l"
diff --git a/tools/libs/util/libxlu_disk_l.h b/tools/libs/util/libxlu_disk_l.h
index 6abeecf279..509aad67dc 100644
--- a/tools/libs/util/libxlu_disk_l.h
+++ b/tools/libs/util/libxlu_disk_l.h
@@ -694,7 +694,7 @@  extern int yylex (yyscan_t yyscanner);
 #undef yyTABLES_NAME
 #endif
 
-#line 291 "libxlu_disk_l.l"
+#line 300 "libxlu_disk_l.l"
 
 #line 699 "libxlu_disk_l.h"
 #undef xlu__disk_yyIN_HEADER
diff --git a/tools/libs/util/libxlu_disk_l.l b/tools/libs/util/libxlu_disk_l.l
index e115460d99..6d53c093a3 100644
--- a/tools/libs/util/libxlu_disk_l.l
+++ b/tools/libs/util/libxlu_disk_l.l
@@ -122,9 +122,17 @@  static void setbackendtype(DiskParseContext *dpc, const char *str) {
     if (     !strcmp(str,"phy"))   DSET(dpc,backend,BACKEND,str,PHY);
     else if (!strcmp(str,"tap"))   DSET(dpc,backend,BACKEND,str,TAP);
     else if (!strcmp(str,"qdisk")) DSET(dpc,backend,BACKEND,str,QDISK);
+    else if (!strcmp(str,"standalone")) DSET(dpc,backend,BACKEND,str,STANDALONE);
     else xlu__disk_err(dpc,str,"unknown value for backendtype");
 }
 
+/* Sets ->specification from the string.  IDL should provide something for this. */
+static void setspecification(DiskParseContext *dpc, const char *str) {
+    if      (!strcmp(str,"xen"))    DSET(dpc,specification,SPECIFICATION,str,XEN);
+    else if (!strcmp(str,"virtio")) DSET(dpc,specification,SPECIFICATION,str,VIRTIO);
+    else xlu__disk_err(dpc,str,"unknown value for specification");
+}
+
 /* Sets ->colo-port from the string.  COLO need this. */
 static void setcoloport(DiskParseContext *dpc, const char *str) {
     int port = atoi(str);
@@ -192,6 +200,7 @@  devtype=[^,]*,?	{ xlu__disk_err(DPC,yytext,"unknown value for type"); }
 access=[^,]*,?	{ STRIP(','); setaccess(DPC, FROMEQUALS); }
 backend=[^,]*,? { STRIP(','); SAVESTRING("backend", backend_domname, FROMEQUALS); }
 backendtype=[^,]*,? { STRIP(','); setbackendtype(DPC,FROMEQUALS); }
+specification=[^,]*,? { STRIP(','); setspecification(DPC,FROMEQUALS); }
 
 vdev=[^,]*,?	{ STRIP(','); SAVESTRING("vdev", vdev, FROMEQUALS); }
 script=[^,]*,?	{ STRIP(','); SAVESTRING("script", script, FROMEQUALS); }
diff --git a/tools/xl/xl_block.c b/tools/xl/xl_block.c
index 70eed431e4..8836c07d6b 100644
--- a/tools/xl/xl_block.c
+++ b/tools/xl/xl_block.c
@@ -119,6 +119,12 @@  int main_blockdetach(int argc, char **argv)
         fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
         return 1;
     }
+
+    if (disk.specification == LIBXL_DISK_SPECIFICATION_VIRTIO) {
+        fprintf(stderr, "Hotunplug isn't supported for specification virtio\n");
+        return 1;
+    }
+
     rc = !force ? libxl_device_disk_safe_remove(ctx, domid, &disk, 0) :
         libxl_device_disk_destroy(ctx, domid, &disk, 0);
     if (rc) {