[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging] tools: move libxlutil to tools/libs/util



commit 3ae0d316f01c08903a96f6b5b39275c67b823264
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Wed Sep 23 06:57:20 2020 +0200
Commit:     Juergen Gross <jgross@xxxxxxxx>
CommitDate: Thu Oct 1 13:26:17 2020 +0200

    tools: move libxlutil to tools/libs/util
    
    Move the libxlutil source to tools/libs/util and delete tools/libxl.
    
    Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
    Acked-by: Wei Liu <wl@xxxxxxx>
---
 .gitignore                          |    6 +-
 tools/Makefile                      |    1 -
 tools/Rules.mk                      |    7 -
 tools/libs/Makefile                 |    1 +
 tools/libs/uselibs.mk               |    3 +
 tools/libs/util/CODING_STYLE        |  330 ++++
 tools/libs/util/Makefile            |   63 +
 tools/libs/util/include/libxlutil.h |  136 ++
 tools/libs/util/libxlu_cfg.c        |  712 +++++++++
 tools/libs/util/libxlu_cfg_i.h      |   59 +
 tools/libs/util/libxlu_cfg_l.c      | 2375 ++++++++++++++++++++++++++++
 tools/libs/util/libxlu_cfg_l.h      |  734 +++++++++
 tools/libs/util/libxlu_cfg_l.l      |  104 ++
 tools/libs/util/libxlu_cfg_y.c      | 1705 ++++++++++++++++++++
 tools/libs/util/libxlu_cfg_y.h      |   96 ++
 tools/libs/util/libxlu_cfg_y.y      |   79 +
 tools/libs/util/libxlu_disk.c       |  102 ++
 tools/libs/util/libxlu_disk_i.h     |   29 +
 tools/libs/util/libxlu_disk_l.c     | 2944 +++++++++++++++++++++++++++++++++++
 tools/libs/util/libxlu_disk_l.h     |  701 +++++++++
 tools/libs/util/libxlu_disk_l.l     |  289 ++++
 tools/libs/util/libxlu_internal.h   |   84 +
 tools/libs/util/libxlu_pci.c        |  264 ++++
 tools/libs/util/libxlu_vif.c        |  149 ++
 tools/libxl/CODING_STYLE            |  330 ----
 tools/libxl/Makefile                |  124 --
 tools/libxl/libxlu_cfg.c            |  712 ---------
 tools/libxl/libxlu_cfg_i.h          |   59 -
 tools/libxl/libxlu_cfg_l.c          | 2375 ----------------------------
 tools/libxl/libxlu_cfg_l.h          |  734 ---------
 tools/libxl/libxlu_cfg_l.l          |  104 --
 tools/libxl/libxlu_cfg_y.c          | 1705 --------------------
 tools/libxl/libxlu_cfg_y.h          |   96 --
 tools/libxl/libxlu_cfg_y.y          |   79 -
 tools/libxl/libxlu_disk.c           |  102 --
 tools/libxl/libxlu_disk_i.h         |   29 -
 tools/libxl/libxlu_disk_l.c         | 2944 -----------------------------------
 tools/libxl/libxlu_disk_l.h         |  701 ---------
 tools/libxl/libxlu_disk_l.l         |  289 ----
 tools/libxl/libxlu_internal.h       |   84 -
 tools/libxl/libxlu_pci.c            |  264 ----
 tools/libxl/libxlu_vif.c            |  149 --
 tools/libxl/libxlutil.h             |  136 --
 43 files changed, 10963 insertions(+), 11026 deletions(-)

diff --git a/.gitignore b/.gitignore
index f30550255f..188495783e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -154,6 +154,10 @@ tools/libs/store/utils.h
 tools/libs/store/xenstore.pc
 tools/libs/store/xs_lib.c
 tools/libs/store/include/xenstore_lib.h
+tools/libs/util/*.pc
+tools/libs/util/_paths.h
+tools/libs/util/libxlu_cfg_y.output
+tools/libs/util/libxenutil.map
 tools/libs/vchan/headers.chk
 tools/libs/vchan/libxenvchan.map
 tools/libs/vchan/xenvchan.pc
@@ -232,8 +236,6 @@ tools/include/xen/*
 tools/include/xen-xsm/*
 tools/include/xen-foreign/*.(c|h|size)
 tools/include/xen-foreign/checker
-tools/libxl/*.pc
-tools/libxl/libxlu_cfg_y.output
 tools/misc/cpuperf/cpuperf-perfcntr
 tools/misc/cpuperf/cpuperf-xen
 tools/misc/xc_shadow
diff --git a/tools/Makefile b/tools/Makefile
index c1eba22c0c..ed71474421 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -29,7 +29,6 @@ SUBDIRS-$(CONFIG_QEMU_XEN) += qemu-xen-dir
 endif
 
 SUBDIRS-y += xenpmd
-SUBDIRS-y += libxl
 SUBDIRS-$(CONFIG_GOLANG) += golang
 SUBDIRS-y += xl
 SUBDIRS-y += helpers
diff --git a/tools/Rules.mk b/tools/Rules.mk
index 75d44c4a4b..f3e0078927 100644
--- a/tools/Rules.mk
+++ b/tools/Rules.mk
@@ -15,8 +15,6 @@ XEN_INCLUDE        = $(XEN_ROOT)/tools/include
 
 include $(XEN_ROOT)/tools/libs/uselibs.mk
 
-XEN_libxenutil     = $(XEN_ROOT)/tools/libxl
-
 CFLAGS_xeninclude = -I$(XEN_INCLUDE)
 
 XENSTORE_XENSTORED ?= y
@@ -117,11 +115,6 @@ else
 CFLAGS += -O2 -fomit-frame-pointer
 endif
 
-CFLAGS_libxenutil = -I$(XEN_libxenutil)
-SHDEPS_libxenutil = $(SHLIB_libxenlight)
-LDLIBS_libxenutil = $(SHDEPS_libxenutil) 
$(XEN_libxenutil)/libxlutil$(libextension)
-SHLIB_libxenutil  = $(SHDEPS_libxenutil) -Wl,-rpath-link=$(XEN_libxenutil)
-
 CFLAGS += -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__
 
 # Get gcc to generate the dependencies for us.
diff --git a/tools/libs/Makefile b/tools/libs/Makefile
index c41455c604..1afcd12e2b 100644
--- a/tools/libs/Makefile
+++ b/tools/libs/Makefile
@@ -16,6 +16,7 @@ SUBDIRS-y += store
 SUBDIRS-y += stat
 SUBDIRS-$(CONFIG_Linux) += vchan
 SUBDIRS-y += light
+SUBDIRS-y += util
 
 ifeq ($(CONFIG_RUMP),y)
 SUBDIRS-y := toolcore
diff --git a/tools/libs/uselibs.mk b/tools/libs/uselibs.mk
index 685f368aed..efd7a475ba 100644
--- a/tools/libs/uselibs.mk
+++ b/tools/libs/uselibs.mk
@@ -28,3 +28,6 @@ LIBS_LIBS += stat
 USELIBS_stat := ctrl store
 LIBS_LIBS += light
 USELIBS_light := toollog evtchn toolcore ctrl store hypfs guest
+LIBS_LIBS += util
+USELIBS_util := light
+FILENAME_util := xlutil
diff --git a/tools/libs/util/CODING_STYLE b/tools/libs/util/CODING_STYLE
new file mode 100644
index 0000000000..3d572f6925
--- /dev/null
+++ b/tools/libs/util/CODING_STYLE
@@ -0,0 +1,330 @@
+LIBXENLIGHT CODING STYLE
+========================
+
+
+AN APOLOGY AND WARNING
+----------------------
+
+Much of the code in libxl does not yet follow this coding style
+document in every respect.  However, new code is expected to conform.
+
+Patches to improve the style of existing code are welcome.  Please
+separate these out from functional changes.
+
+If it is not feasible to conform fully to the style while patching old
+code, without doing substantial style reengineering first, we may
+accept patches which contain nonconformant elements, provided that
+they don't make the coding style problem worse overall.
+
+In this case, the new code should conform to the prevailing style in
+the area being touched.
+
+
+MEMORY ALLOCATION
+-----------------
+
+Memory allocation for libxl-internal purposes should normally be done
+with the provided gc mechanisms; there is then no need to free.  See
+"libxl memory management" in libxl.h.
+
+
+CONVENTIONAL VARIABLE NAMES
+---------------------------
+
+The following local variable names should be used where applicable:
+
+  int rc;    /* a libxl error code - and not anything else */
+  int r;     /* the return value from a system call (or libxc call) */
+  bool ok;   /* the success return value from a boolean function */
+
+  uint32_t domid;
+  libxl__gc *gc;
+  libxl__egc *egc;
+  libxl__ao *ao;
+
+  libxl_foo_bar_state *fbs;    /* local variable */
+  libxl_foo_bar_state foo_bar; /* inside another state struct */
+
+
+CONVENIENCE MACROS
+------------------
+
+There are a number of convenience macros which shorten the program and
+avoid opportunity for mistakes.  In some cases non-use of the macros
+produces functional bugs or incorrect error handling.  Use the macros
+whenever they are applicable.  For example:
+
+ Usually, don't use:     Instead, use (see libxl_internal.h):
+  libxl__log[v]           LOG, LOGE, LOGEV
+  libxl__sprintf          GCSPRINTF
+  libxl__*alloc et al.    GCNEW, GCNEW_ARRAY, GCREALLOC_ARRAY
+  isalnum etc. directly   CTYPE
+  libxl__ctx_[un]lock     CTX_LOCK, CTX_UNLOCK
+  gc=...; ao=...;         EGC_GC, AO_GC, STATE_AO_GC
+  explicit gc creation    GC_INIT, GC_FREE
+  memset(..,0,sizeof..)   FILLZERO
+
+Instead of malloc et al one should (as an exception to the above) use
+libxl__{zalloc,calloc,realloc} etc but passing NOGC.
+
+ERROR HANDLING
+--------------
+
+Unless, there are good reasons to do otherwise, the following error
+handling and cleanup paradigm should be used:
+
+  * All local variables referring to resources which might need
+    cleaning up are declared at the top of the function, and
+    initialised to a sentinel value indicating "nothing allocated".
+    For example,
+            libxl_evgen_disk_eject *evg = NULL;
+            int nullfd = -1;
+
+  * If the function is to return a libxl error value, `rc' is
+    used to contain the error code, but it is NOT initialised:
+            int rc;
+
+  * There is only one error cleanup path out of the function.  It
+    starts with a label `out:'.  That error cleanup path checks for
+    each allocated resource and frees it iff necessary.  It then
+    returns rc.  For example,
+         out:
+             if (evg) libxl__evdisable_disk_eject(gc, evg);
+             if (nullfd >= 0) close(nullfd);
+             return rc;
+
+  * Function calls which might fail (ie most function calls) are
+    handled by putting the return/status value into a variable, and
+    then checking it in a separate statement:
+            char *dompath = libxl__xs_get_dompath(gc, bl->domid);
+            if (!dompath) { rc = ERROR_FAIL; goto out; }
+
+  * If a resource is freed in the main body of the function (for
+    example, in a loop), the corresponding variable has to be reset to
+    the sentinel at the point where it's freed.
+
+Whether to use the `out' path for successful returns as well as error
+returns is a matter of taste and convenience for the specific
+function.  Not reusing the out path is fine if the duplicated function
+exit code is only `CTX_UNLOCK; GC_FREE;' (or similar).
+
+If you reuse the `out' path for successful returns, there may be
+resources which are to be returned to the caller rather than freed.
+In that case you have to reset the local variable to `nothing here',
+to avoid the resource being freed on the out path.  That resetting
+should be done immediately after the resource value is stored at the
+applicable _r function parameter (or equivalent).  Do not test `rc' in
+the out section, to discover whether to free things.
+
+The uses of the single-line formatting in the examples above are
+permitted exceptions to the usual libxl code formatting rules.
+
+
+
+IDEMPOTENT DATA STRUCTURE CONSTRUCTION/DESTRUCTION
+--------------------------------------------------
+
+Nontrivial data structures (in structs) should come with an idempotent
+_dispose function, which must free all resources associated with the
+data structure (but not free the struct itself).
+
+Such a struct should also come with an _init function which
+initialises the struct so that _dispose is a no-op.
+
+
+ASYNCHRONOUS/LONG-RUNNING OPERATIONS
+------------------------------------
+
+All long-running operations in libxl need to use the asynchronous
+operation machinery.  Consult the programmer documentation in
+libxl_internal.h for details - search for "Machinery for asynchronous
+operations".
+
+The code for asynchronous operations should be laid out in
+chronological order.  That is, where there is a chain of callback
+functions, each subsequent function should be, textually, the next
+function in the file.  This will normally involve predeclaring the
+callback functions.  Synchronous helper functions should be separated
+out into a section preceding the main callback chain.
+
+Control flow arrangements in asynchronous operations should be made as
+simple as possible, because it can otherwise be very hard to see
+through the tangle.
+
+
+When inventing a new sub-operation in asynchronous code, consider
+whether to structure it formally as a sub-operation with its own state
+structure.  (See, for example, libxl__datacopier_*.)
+
+An ao-suboperation state structure should contain, in this order:
+  * fields that the caller must fill in, and which are,
+    effectively, the parameters to the operation, including:
+      - libxl__ao *ao
+      - the callback function pointer(s), which
+        should be named callback or callback_*.
+  * shared information fields or ones used for returning information
+    to the calling operation
+  * private fields
+These sections should be clearly demarcated by comments.
+
+An asynchronous operation should normally have an idempotent stop or
+cancel function.  It should normally also have an _init function for
+its state struct, which arranges that the stop is a no-op.
+
+The permitted order of calls into your ao operation's methods must be
+documented in comments, if it is nontrivial.
+
+
+When using an ao sub-operation, you should normally:
+ * Physically include the sub-operation state struct in your
+   own state struct;
+ * Use CONTAINER_OF to find your own state struct at the start of
+   your implementations of the sub-operation callback functions;
+ * Unconditionally initialise the sub-operation's struct (with its
+   _init method) in your own _init method.
+ * Unconditionally cancel or destroy the sub-operation in your own
+   cancel or destroy method.
+
+
+FORMATTING AND NAMING
+---------------------
+
+Blatantly copied from qemu and linux with few modifications.
+
+
+1. Whitespace
+
+Of course, the most important aspect in any coding style is whitespace.
+Crusty old coders who have trouble spotting the glasses on their noses
+can tell the difference between a tab and eight spaces from a distance
+of approximately fifteen parsecs.  Many a flamewar have been fought and
+lost on this issue.
+
+Libxenlight indents are four spaces.  Tabs are never used, except in
+Makefiles where they have been irreversibly coded into the syntax.
+Spaces of course are superior to tabs because:
+
+ - You have just one way to specify whitespace, not two.  Ambiguity breeds
+   mistakes.
+ - The confusion surrounding 'use tabs to indent, spaces to justify' is gone.
+ - Tab indents push your code to the right, making your screen seriously
+   unbalanced.
+ - Tabs will be rendered incorrectly on editors who are misconfigured not
+   to use tab stops of eight positions.
+ - Tabs are rendered badly in patches, causing off-by-one errors in almost
+   every line.
+ - It is the libxenlight coding style.
+
+Do not leave whitespace dangling off the ends of lines.
+
+
+2. Line width
+
+Lines are limited to 75 characters.
+
+Rationale:
+ - Some people like to tile their 24" screens with a 6x4 matrix of 80x24
+   xterms and use vi in all of them.  The best way to punish them is to
+   let them keep doing it.
+ - In an 80 column terminal, some room needs to be left for > quoting
+   characters, +/- diff characters, and so on, in emails.
+ - Code and especially patches is much more readable if limited to a sane
+   line length.  Eighty is traditional.
+ - It is the libxenlight coding style.
+
+
+3. Naming
+
+C is a Spartan language, and so should your naming be.  Unlike Modula-2
+and Pascal programmers, C programmers do not use cute names like
+ThisVariableIsATemporaryCounter.  A C programmer would call that
+variable "tmp", which is much easier to write, and not the least more
+difficult to understand.
+
+HOWEVER, while mixed-case names are frowned upon, descriptive names for
+global variables are a must.  To call a global function "foo" is a
+shooting offense.
+
+GLOBAL variables (to be used only if you _really_ need them) need to
+have descriptive names, as do global functions.  If you have a function
+that counts the number of active users, you should call that
+"count_active_users()" or similar, you should _not_ call it "cntusr()".
+
+Encoding the type of a function into the name (so-called Hungarian
+notation) is brain damaged - the compiler knows the types anyway and can
+check those, and it only confuses the programmer.
+
+LOCAL variable names should be short, and to the point.  If you have
+some random integer loop counter, it should probably be called "i".
+Calling it "loop_counter" is non-productive, if there is no chance of it
+being mis-understood.  Similarly, "tmp" can be just about any type of
+variable that is used to hold a temporary value.
+
+Local variables used to store return values should have descriptive name
+like "rc" or "ret". Following the same reasoning the label used as exit
+path should be called "out".
+
+Function arguments which are used to return values to the caller
+should be suffixed `_r' or `_out'.
+
+Variables, type names and function names are
+lower_case_with_underscores.
+Type names and function names use the prefix libxl__ when internal to
+libxenlight and libxl_ when exported in libxl.h.
+Xl should avoid using libxl_ and libxl__ as prefix for its own function
+names.
+
+When wrapping standard library functions, use the prefix libxl_ to alert
+readers that they are seeing a wrapped version; otherwise avoid this prefix.
+
+Typedefs are used to eliminate the redundant 'struct' keyword.
+It is the libxenlight coding style.
+
+
+4. Statements
+
+Don't put multiple statements on a single line.
+Don't put multiple assignments on a single line either.
+Error code paths with an if statement and a goto or a return on the same
+line are allowed. Examples:
+
+    if (rc) goto out;
+    if (rc < 0) return;
+
+Libxenlight coding style is super simple.  Avoid tricky expressions.
+
+
+5. Block structure
+
+Every indented statement is braced, but blocks that contain just one
+statement may have the braces omitted.  To avoid confusion, either all
+the blocks in an if...else chain have braces, or none of them do.
+
+The opening brace is on the line that contains the control flow
+statement that introduces the new block; the closing brace is on the
+same line as the else keyword, or on a line by itself if there is no
+else keyword.  Examples:
+
+    if (a == 5) {
+        printf("a was 5.\n");
+    } else if (a == 6) {
+        printf("a was 6.\n");
+    } else {
+        printf("a was something else entirely.\n");
+    }
+
+    if (a == 5)
+        printf("a was 5.\n");
+
+An exception is the opening brace for a function; for reasons of tradition
+and clarity it comes on a line by itself:
+
+    void a_function(void)
+    {
+        do_something();
+    }
+
+Rationale: a consistent (except for functions...) bracing style reduces
+ambiguity and avoids needless churn when lines are added or removed.
+Furthermore, it is the libxenlight coding style.
+
diff --git a/tools/libs/util/Makefile b/tools/libs/util/Makefile
new file mode 100644
index 0000000000..0c9db8027d
--- /dev/null
+++ b/tools/libs/util/Makefile
@@ -0,0 +1,63 @@
+XEN_ROOT = $(CURDIR)/../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+SRCS-y += libxlu_cfg_y.c
+SRCS-y += libxlu_cfg_l.c
+SRCS-y += libxlu_cfg.c
+SRCS-y += libxlu_disk_l.c
+SRCS-y += libxlu_disk.c
+SRCS-y += libxlu_vif.c
+SRCS-y += libxlu_pci.c
+
+CFLAGS += -Wno-format-zero-length -Wmissing-declarations \
+       -Wno-declaration-after-statement -Wformat-nonliteral
+CFLAGS += -I. $(CFLAGS_libxenctrl)
+
+CFLAGS += $(PTHREAD_CFLAGS)
+LDFLAGS += $(PTHREAD_LDFLAGS)
+
+ifeq ($(FLEX),)
+%.c %.h:: %.l
+       $(warning Flex is needed to rebuild some libxl parsers and \
+                 scanners, please install it and rerun configure)
+endif
+
+ifeq ($(BISON),)
+%.c %.h:: %.y
+       $(warning Bison is needed to rebuild some libxl parsers and \
+                 scanners, please install it and rerun configure)
+endif
+
+AUTOINCS = libxlu_cfg_y.h libxlu_cfg_l.h libxlu_disk_l.h
+AUTOSRCS = libxlu_cfg_y.c libxlu_cfg_l.c
+
+LIBHEADER := libxlutil.h
+PKG_CONFIG_NAME := Xlutil
+PKG_CONFIG_DESC := The xl utility library for Xen hypervisor
+
+NO_HEADERS_CHK := y
+
+include $(XEN_ROOT)/tools/libs/libs.mk
+
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_INCDIR = $(XEN_libxenutil)/include
+$(PKG_CONFIG_LOCAL): PKG_CONFIG_CFLAGS_LOCAL = $(CFLAGS_xeninclude)
+
+$(LIB_OBJS) $(PIC_OBJS): $(AUTOINCS) _paths.h
+
+%.c %.h:: %.y
+       @rm -f $*.[ch]
+       $(BISON) --output=$*.c $<
+
+%.c %.h:: %.l
+       @rm -f $*.[ch]
+       $(FLEX) --header-file=$*.h --outfile=$*.c $<
+
+genpath-target = $(call buildmakevars2header,_paths.h)
+$(eval $(genpath-target))
+
+clean: cleanlocal
+
+.PHONY: cleanlocal
+cleanlocal:
+       $(RM) -f _*.h
+       $(RM) -f libxlutil.map
diff --git a/tools/libs/util/include/libxlutil.h 
b/tools/libs/util/include/libxlutil.h
new file mode 100644
index 0000000000..92e35c5462
--- /dev/null
+++ b/tools/libs/util/include/libxlutil.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010      Citrix Ltd.
+ * Author Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef LIBXLUTIL_H
+#define LIBXLUTIL_H
+
+#include <stdio.h>
+
+#include "libxl.h"
+
+enum XLU_ConfigValueType {
+    XLU_STRING,
+    XLU_LIST,
+};
+
+enum XLU_Operation {
+    XLU_OP_ASSIGNMENT = 0,
+    XLU_OP_ADDITION,
+};
+
+/* Unless otherwise stated, all functions return an errno value. */
+typedef struct XLU_Config XLU_Config;
+typedef struct XLU_ConfigList XLU_ConfigList;
+typedef struct XLU_ConfigValue XLU_ConfigValue;
+
+XLU_Config *xlu_cfg_init(FILE *report, const char *report_filename);
+  /* 0 means we got ENOMEM. */
+  /* report_filename is copied; report is saved and must remain valid
+   *  until the Config is destroyed. */
+
+int xlu_cfg_readfile(XLU_Config*, const char *real_filename);
+int xlu_cfg_readdata(XLU_Config*, const char *data, int length);
+  /* If these fail, then it is undefined behaviour to call xlu_cfg_get_...
+   * functions.  You have to just xlu_cfg_destroy. */
+
+void xlu_cfg_destroy(XLU_Config*);
+
+
+/* All of the following print warnings to "report" if there is a problem.
+ * Return values are:
+ *   0        OK
+ *   ESRCH    not defined
+ *   EINVAL   value found but wrong format for request (prints warning unless 
dont_warn=true)
+ *   ERANGE   value out of range (from strtol)
+ */
+
+int xlu_cfg_get_string(const XLU_Config*, const char *n, const char **value_r,
+                       int dont_warn);
+/* free/strdup version */
+int xlu_cfg_replace_string(const XLU_Config *cfg, const char *n,
+                           char **value_r, int dont_warn);
+int xlu_cfg_get_long(const XLU_Config*, const char *n, long *value_r,
+                     int dont_warn);
+int xlu_cfg_get_bounded_long(const XLU_Config*, const char *n, long min,
+                             long max, long *value_r, int dont_warn);
+int xlu_cfg_get_defbool(const XLU_Config*, const char *n, libxl_defbool *b,
+                     int dont_warn);
+
+int xlu_cfg_get_list(const XLU_Config*, const char *n,
+                     XLU_ConfigList **list_r /* may be 0 */,
+                     int *entries_r /* may be 0 */,
+                     int dont_warn);
+  /* there is no need to free *list_r; lifetime is that of the XLU_Config */
+int xlu_cfg_get_list_as_string_list(const XLU_Config *cfg, const char *n,
+                                    libxl_string_list *sl, int dont_warn);
+const char *xlu_cfg_get_listitem(const XLU_ConfigList*, int entry);
+  /* xlu_cfg_get_listitem cannot fail, except that if entry is
+   * out of range it returns 0 (not setting errno) */
+
+enum XLU_ConfigValueType xlu_cfg_value_type(const XLU_ConfigValue *value);
+int xlu_cfg_value_get_string(const XLU_Config *cfg,  XLU_ConfigValue *value,
+                             char **value_r, int dont_warn);
+int xlu_cfg_value_get_list(const XLU_Config *cfg, XLU_ConfigValue *value,
+                           XLU_ConfigList **value_r, int dont_warn);
+XLU_ConfigValue *xlu_cfg_get_listitem2(const XLU_ConfigList *list,
+                                       int entry);
+
+/*
+ * Disk specification parsing.
+ */
+
+int xlu_disk_parse(XLU_Config *cfg, int nspecs, const char *const *specs,
+                   libxl_device_disk *disk);
+  /* disk must have been initialised.
+   *
+   * On error, returns errno value.  Bad strings cause EINVAL and
+   * print a message to cfg's report (that's all cfg is used for).
+   *
+   * Normally one would pass nspecs==1 and only specs[0].  But it is
+   * permitted to pass more strings in which case each is parsed as a
+   * string containing a collection of parameters (but they all refer
+   * to of the configuration for a single disk).
+   *
+   * nspecs==0 is permitted but since it does not specify some mandatory
+   * properties, it produces a run-time configuration error if the
+   * resulting disk struct is used with libxl.
+   */
+
+/*
+ * PCI specification parsing
+ */
+int xlu_pci_parse_bdf(XLU_Config *cfg, libxl_device_pci *pcidev, const char 
*str);
+
+/*
+ * RDM parsing
+ */
+int xlu_rdm_parse(XLU_Config *cfg, libxl_rdm_reserve *rdm, const char *str);
+
+/*
+ * Vif rate parsing.
+ */
+
+int xlu_vif_parse_rate(XLU_Config *cfg, const char *rate,
+                       libxl_device_nic *nic);
+
+#endif /* LIBXLUTIL_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/util/libxlu_cfg.c b/tools/libs/util/libxlu_cfg.c
new file mode 100644
index 0000000000..874f5abfb9
--- /dev/null
+++ b/tools/libs/util/libxlu_cfg.c
@@ -0,0 +1,712 @@
+/*
+ * libxlu_cfg.c - xl configuration file parsing: setup and helper functions
+ *
+ * Copyright (C) 2010      Citrix Ltd.
+ * Author Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#define _GNU_SOURCE
+
+#include <limits.h>
+
+#include "libxlu_internal.h"
+#include "libxlu_cfg_y.h"
+#include "libxlu_cfg_l.h"
+#include "libxlu_cfg_i.h"
+
+XLU_Config *xlu_cfg_init(FILE *report, const char *report_source) {
+    XLU_Config *cfg;
+
+    cfg= malloc(sizeof(*cfg));
+    if (!cfg) return 0;
+
+    cfg->report= report;
+    cfg->config_source= strdup(report_source);
+    if (!cfg->config_source) { free(cfg); return 0; }
+
+    cfg->settings= 0;
+    return cfg;
+}
+
+static int ctx_prep(CfgParseContext *ctx, XLU_Config *cfg) {
+    int e;
+
+    ctx->cfg= cfg;
+    ctx->err= 0;
+    ctx->lexerrlineno= -1;
+    ctx->likely_python= 0;
+    ctx->scanner= 0;
+
+    e= xlu__cfg_yylex_init_extra(ctx, &ctx->scanner);
+    if (e) {
+        fprintf(cfg->report,"%s: unable to create scanner: %s\n",
+                cfg->config_source, strerror(e));
+        return e;
+    }
+    return 0;
+}
+
+static void ctx_dispose(CfgParseContext *ctx) {
+    if (ctx->scanner) xlu__cfg_yylex_destroy(ctx->scanner);
+}
+
+static void parse(CfgParseContext *ctx) {
+    /* On return, ctx.err will be updated with the error status. */
+    int r;
+
+    xlu__cfg_yyset_lineno(1, ctx->scanner);
+
+    r= xlu__cfg_yyparse(ctx);
+    if (r) assert(ctx->err);
+
+    if (ctx->err && ctx->likely_python) {
+        fputs(
+ "warning: Config file looks like it contains Python code.\n"
+ "warning:  Arbitrary Python is no longer supported.\n"
+ "warning:  See https://wiki.xen.org/wiki/PythonInXlConfig\n";,
+              ctx->cfg->report);
+    }
+}
+
+int xlu_cfg_readfile(XLU_Config *cfg, const char *real_filename) {
+    FILE *f = 0;
+    int e;
+
+    CfgParseContext ctx;
+    e = ctx_prep(&ctx, cfg);
+    if (e) { ctx.err= e; goto xe; }
+
+    f= fopen(real_filename, "r");
+    if (!f) {
+        ctx.err = errno;
+        fprintf(cfg->report,"%s: unable to open configuration file: %s\n",
+                real_filename, strerror(e));
+        goto xe;
+    }
+
+    xlu__cfg_yyrestart(f, ctx.scanner);
+
+    parse(&ctx);
+
+ xe:
+    ctx_dispose(&ctx);
+    if (f) fclose(f);
+
+    return ctx.err;
+}
+
+int xlu_cfg_readdata(XLU_Config *cfg, const char *data, int length) {
+    int e;
+    YY_BUFFER_STATE buf= 0;
+
+    CfgParseContext ctx;
+    e= ctx_prep(&ctx, cfg);
+    if (e) { ctx.err= e; goto xe; }
+
+    buf = xlu__cfg_yy_scan_bytes(data, length, ctx.scanner);
+    if (!buf) {
+        fprintf(cfg->report,"%s: unable to allocate scanner buffer\n",
+                cfg->config_source);
+        ctx.err= ENOMEM;
+        goto xe;
+    }
+
+    parse(&ctx);
+
+ xe:
+    if (buf) xlu__cfg_yy_delete_buffer(buf, ctx.scanner);
+    ctx_dispose(&ctx);
+
+    return ctx.err;
+}
+
+void xlu__cfg_value_free(XLU_ConfigValue *value)
+{
+    int i;
+
+    if (!value) return;
+
+    switch (value->type) {
+    case XLU_STRING:
+        free(value->u.string);
+        break;
+    case XLU_LIST:
+        for (i = 0; i < value->u.list.nvalues; i++)
+            xlu__cfg_value_free(value->u.list.values[i]);
+        free(value->u.list.values);
+    }
+    free(value);
+}
+
+void xlu__cfg_set_free(XLU_ConfigSetting *set) {
+    if (!set) return;
+    free(set->name);
+    xlu__cfg_value_free(set->value);
+    free(set);
+}
+
+void xlu_cfg_destroy(XLU_Config *cfg) {
+    XLU_ConfigSetting *set, *set_next;
+
+    if (!cfg) return;
+    for (set= cfg->settings;
+         set;
+         set= set_next) {
+        set_next= set->next;
+        xlu__cfg_set_free(set);
+    }
+    free(cfg->config_source);
+    free(cfg);
+}
+
+static XLU_ConfigSetting *find(const XLU_Config *cfg, const char *n) {
+    XLU_ConfigSetting *set;
+
+    for (set= cfg->settings;
+         set;
+         set= set->next)
+        if (!strcmp(set->name, n))
+            return set;
+    return 0;
+}
+
+static int find_atom(const XLU_Config *cfg, const char *n,
+                     XLU_ConfigSetting **set_r, int dont_warn) {
+    XLU_ConfigSetting *set;
+
+    set= find(cfg,n);
+    if (!set) return ESRCH;
+
+    if (set->value->type!=XLU_STRING) {
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d: warning: parameter `%s' is"
+                    " a list but should be a single value\n",
+                    cfg->config_source, set->lineno, n);
+        return EINVAL;
+    }
+    *set_r= set;
+    return 0;
+}
+
+
+enum XLU_ConfigValueType xlu_cfg_value_type(const XLU_ConfigValue *value)
+{
+    return value->type;
+}
+
+int xlu_cfg_value_get_string(const XLU_Config *cfg, XLU_ConfigValue *value,
+                             char **value_r, int dont_warn)
+{
+    if (value->type != XLU_STRING) {
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d:%d: warning: value is not a string\n",
+                    cfg->config_source, value->loc.first_line,
+                    value->loc.first_column);
+        *value_r = NULL;
+        return EINVAL;
+    }
+
+    *value_r = value->u.string;
+    return 0;
+}
+
+int xlu_cfg_value_get_list(const XLU_Config *cfg, XLU_ConfigValue *value,
+                           XLU_ConfigList **value_r, int dont_warn)
+{
+    if (value->type != XLU_LIST) {
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d:%d: warning: value is not a list\n",
+                    cfg->config_source, value->loc.first_line,
+                    value->loc.first_column);
+        *value_r = NULL;
+        return EINVAL;
+    }
+
+    *value_r = &value->u.list;
+    return 0;
+}
+
+XLU_ConfigValue *xlu_cfg_get_listitem2(const XLU_ConfigList *list,
+                                       int entry)
+{
+    if (entry < 0 || entry >= list->nvalues) return NULL;
+    return list->values[entry];
+}
+
+int xlu_cfg_get_string(const XLU_Config *cfg, const char *n,
+                       const char **value_r, int dont_warn) {
+    XLU_ConfigSetting *set;
+    int e;
+
+    e= find_atom(cfg,n,&set,dont_warn);  if (e) return e;
+    *value_r= set->value->u.string;
+    return 0;
+}
+
+int xlu_cfg_replace_string(const XLU_Config *cfg, const char *n,
+                           char **value_r, int dont_warn) {
+    XLU_ConfigSetting *set;
+    int e;
+
+    e= find_atom(cfg,n,&set,dont_warn);  if (e) return e;
+    free(*value_r);
+    *value_r= strdup(set->value->u.string);
+    return 0;
+}
+
+int xlu_cfg_get_bounded_long(const XLU_Config *cfg, const char *n,
+                             long min, long max, long *value_r,
+                             int dont_warn) {
+    long l;
+    XLU_ConfigSetting *set;
+    int e;
+    char *ep;
+
+    e= find_atom(cfg,n,&set,dont_warn);  if (e) return e;
+    if (set->op == XLU_OP_ADDITION) {
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d: warning: can't use += with numbers"
+                    " for parameter `%s'\n",
+                    cfg->config_source, set->lineno, n);
+        return EINVAL;
+    }
+    errno= 0; l= strtol(set->value->u.string, &ep, 0);
+    e= errno;
+    if (errno) {
+        e= errno;
+        assert(e==EINVAL || e==ERANGE);
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d: warning: parameter `%s' could not be parsed"
+                    " as a number: %s\n",
+                    cfg->config_source, set->lineno, n, strerror(e));
+        return e;
+    }
+    if (*ep || ep==set->value->u.string) {
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d: warning: parameter `%s' is not a valid number\n",
+                    cfg->config_source, set->lineno, n);
+        return EINVAL;
+    }
+    if (l < min) {
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d: warning: value `%ld' is smaller than minimum bound 
'%ld'\n",
+                    cfg->config_source, set->lineno, l, min);
+        return EINVAL;
+    }
+    if (l > max) {
+        if (!dont_warn)
+            fprintf(cfg->report,
+                    "%s:%d: warning: value `%ld' is greater than maximum bound 
'%ld'\n",
+                    cfg->config_source, set->lineno, l, max);
+        return EINVAL;
+    }
+
+    *value_r= l;
+    return 0;
+}
+
+int xlu_cfg_get_long(const XLU_Config *cfg, const char *n,
+                     long *value_r, int dont_warn) {
+    return xlu_cfg_get_bounded_long(cfg, n, LONG_MIN, LONG_MAX, value_r,
+                                    dont_warn);
+}
+
+int xlu_cfg_get_defbool(const XLU_Config *cfg, const char *n, libxl_defbool *b,
+                     int dont_warn)
+{
+    int ret;
+    long l;
+
+    ret = xlu_cfg_get_long(cfg, n, &l, dont_warn);
+    if (ret) return ret;
+    libxl_defbool_set(b, !!l);
+    return 0;
+}
+
+int xlu_cfg_get_list(const XLU_Config *cfg, const char *n,
+                     XLU_ConfigList **list_r, int *entries_r, int dont_warn) {
+    XLU_ConfigSetting *set;
+    set= find(cfg,n);  if (!set) return ESRCH;
+    if (set->value->type!=XLU_LIST) {
+        if (!dont_warn) {
+            fprintf(cfg->report,
+                    "%s:%d: warning: parameter `%s' is a single value"
+                    " but should be a list\n",
+                    cfg->config_source, set->lineno, n);
+        }
+        return EINVAL;
+    }
+    if (list_r) *list_r= &set->value->u.list;
+    if (entries_r) *entries_r= set->value->u.list.nvalues;
+    return 0;
+}
+
+int xlu_cfg_get_list_as_string_list(const XLU_Config *cfg, const char *n,
+                     libxl_string_list *psl, int dont_warn) {
+    int i, rc, nr;
+    XLU_ConfigList *list;
+    libxl_string_list sl;
+
+    rc = xlu_cfg_get_list(cfg, n, &list, &nr, dont_warn);
+    if (rc)  return rc;
+
+    sl = malloc(sizeof(char*)*(nr + 1));
+    if (sl == NULL) return ENOMEM;
+
+    for (i=0; i<nr; i++) {
+        const char *a = xlu_cfg_get_listitem(list, i);
+        sl[i] = a ? strdup(a) : NULL;
+    }
+
+    sl[nr] = NULL;
+
+    *psl = sl;
+    return 0;
+}
+
+const char *xlu_cfg_get_listitem(const XLU_ConfigList *list, int entry) {
+    if (entry < 0 || entry >= list->nvalues) return 0;
+    if (list->values[entry]->type != XLU_STRING) return 0;
+    return list->values[entry]->u.string;
+}
+
+
+XLU_ConfigValue *xlu__cfg_string_mk(CfgParseContext *ctx, char *atom,
+                                    YYLTYPE *loc)
+{
+    XLU_ConfigValue *value = NULL;
+
+    if (ctx->err) goto x;
+
+    value = malloc(sizeof(*value));
+    if (!value) goto xe;
+    value->type = XLU_STRING;
+    value->u.string = atom;
+    memcpy(&value->loc, loc, sizeof(*loc));
+
+    return value;
+
+ xe:
+    ctx->err= errno;
+ x:
+    free(value);
+    free(atom);
+    return NULL;
+}
+
+XLU_ConfigValue *xlu__cfg_list_mk(CfgParseContext *ctx,
+                                  XLU_ConfigValue *val,
+                                  YYLTYPE *loc)
+{
+    XLU_ConfigValue *value = NULL;
+    XLU_ConfigValue **values = NULL;
+
+    if (ctx->err) goto x;
+
+    values = malloc(sizeof(*values));
+    if (!values) goto xe;
+    values[0] = val;
+
+    value = malloc(sizeof(*value));
+    if (!value) goto xe;
+    value->type = XLU_LIST;
+    value->u.list.nvalues = !!val;
+    value->u.list.avalues = 1;
+    value->u.list.values = values;
+    memcpy(&value->loc, loc, sizeof(*loc));
+
+    return value;
+
+ xe:
+    ctx->err= errno;
+ x:
+    free(value);
+    free(values);
+    xlu__cfg_value_free(val);
+    return NULL;
+}
+
+void xlu__cfg_list_append(CfgParseContext *ctx,
+                          XLU_ConfigValue *list,
+                          XLU_ConfigValue *val)
+{
+    if (ctx->err) return;
+
+    assert(val);
+    assert(list->type == XLU_LIST);
+
+    if (list->u.list.nvalues >= list->u.list.avalues) {
+        int new_avalues;
+        XLU_ConfigValue **new_values = NULL;
+
+        if (list->u.list.avalues > INT_MAX / 100) {
+            ctx->err = ERANGE;
+            xlu__cfg_value_free(val);
+            return;
+        }
+
+        new_avalues = list->u.list.avalues * 4;
+        new_values  = realloc(list->u.list.values,
+                              sizeof(*new_values) * new_avalues);
+        if (!new_values) {
+            ctx->err = errno;
+            xlu__cfg_value_free(val);
+            return;
+        }
+
+        list->u.list.avalues = new_avalues;
+        list->u.list.values  = new_values;
+    }
+
+    list->u.list.values[list->u.list.nvalues] = val;
+    list->u.list.nvalues++;
+}
+
+static int xlu__cfg_concat_vals(CfgParseContext *ctx,
+                                XLU_ConfigValue *prev,
+                                XLU_ConfigValue *to_add)
+{
+    int r;
+
+    if (prev->type != to_add->type) {
+        xlu__cfgl_lexicalerror(ctx,
+                           "can't add [list] to \"string\" or vice versa");
+        return EINVAL;
+    }
+
+    switch (to_add->type) {
+    case XLU_STRING: {
+        char *new_string = NULL;
+
+        r = asprintf(&new_string, "%s%s", prev->u.string,
+                     to_add->u.string);
+        if (r < 0) {
+            return errno;
+        }
+        free(to_add->u.string);
+        to_add->u.string = new_string;
+        return 0;
+    }
+    case XLU_LIST: {
+        XLU_ConfigList *const prev_list = &prev->u.list;
+        XLU_ConfigList *const cur_list = &to_add->u.list;
+        int nvalues;
+
+        if (prev->u.list.nvalues > INT_MAX - to_add->u.list.nvalues) {
+            return ERANGE;
+        }
+        nvalues = prev->u.list.nvalues + to_add->u.list.nvalues;
+
+        if (nvalues >= cur_list->avalues) {
+            XLU_ConfigValue **new_vals;
+            new_vals = realloc(cur_list->values,
+                               nvalues * sizeof(*new_vals));
+            if (!new_vals) {
+                return ENOMEM;
+            }
+            cur_list->avalues = nvalues;
+            cur_list->values = new_vals;
+        }
+
+        /* make space for `prev' into `to_add' */
+        memmove(cur_list->values + prev_list->nvalues,
+                cur_list->values,
+                cur_list->nvalues * sizeof(XLU_ConfigValue *));
+        /* move values from `prev' to `to_add' as the list in `prev' will
+         * not be reachable by find(). */
+        memcpy(cur_list->values,
+               prev_list->values,
+               prev_list->nvalues * sizeof(XLU_ConfigValue *));
+        cur_list->nvalues = nvalues;
+        prev_list->nvalues = 0;
+        memset(prev_list->values, 0,
+               prev_list->nvalues * sizeof(XLU_ConfigValue *));
+        return 0;
+    }
+    default:
+        abort();
+    }
+    return -1;
+}
+
+void xlu__cfg_set_store(CfgParseContext *ctx, char *name,
+                        enum XLU_Operation op,
+                        XLU_ConfigValue *val, int lineno) {
+    XLU_ConfigSetting *set;
+    int r;
+
+    if (ctx->err) goto out;
+
+    assert(name);
+
+    if (op == XLU_OP_ADDITION) {
+        /* If we have += concatenate with previous value with same name */
+        XLU_ConfigSetting *prev_set = find(ctx->cfg, name);
+        if (prev_set) {
+            r = xlu__cfg_concat_vals(ctx, prev_set->value, val);
+            if (r) {
+                ctx->err = r;
+                goto out;
+            }
+        }
+    }
+
+    set = malloc(sizeof(*set));
+    if (!set) {
+        ctx->err = errno;
+        goto out;
+    }
+    set->name= name;
+    set->value = val;
+    set->op = op;
+    set->lineno= lineno;
+    set->next= ctx->cfg->settings;
+    ctx->cfg->settings= set;
+    return;
+out:
+    assert(ctx->err);
+    free(name);
+    xlu__cfg_value_free(val);
+}
+
+char *xlu__cfgl_strdup(CfgParseContext *ctx, const char *src) {
+    char *result;
+
+    if (ctx->err) return 0;
+    result= strdup(src);
+    if (!result) ctx->err= errno;
+    return result;
+}
+
+char *xlu__cfgl_dequote(CfgParseContext *ctx, const char *src) {
+    char *result;
+    const char *p;
+    char *q;
+    int len, c, nc;
+
+    if (ctx->err) return 0;
+
+    len= strlen(src);
+    assert(len>=2 && src[0]==src[len-1]);
+
+    result= malloc(len-1);
+    if (!result) { ctx->err= errno; return 0; }
+
+    q= result;
+
+    for (p= src+1;
+         p < src+len-1;
+         ) {
+        c= *p++;
+        if (c=='\\') {
+            assert(p < src+len-1);
+            nc= *p++;
+            if (nc=='"' || nc=='\'' || nc=='\\') {
+                *q++= nc;
+            } else if (nc=='a') { *q++= '\007';
+            } else if (nc=='b') { *q++= '\010';
+            } else if (nc=='f') { *q++= '\014';
+            } else if (nc=='n') { *q++= '\n';
+            } else if (nc=='r') { *q++= '\r';
+            } else if (nc=='t') { *q++= '\t';
+            } else if (nc=='v') { *q++= '\013';
+            } else if (nc=='x') {
+
+#define NUMERIC_CHAR(minlen,maxlen,base,basetext) do{                        \
+                char numbuf[(maxlen)+1], *ep;                                \
+                unsigned long val;                                           \
+                                                                             \
+                strncpy(numbuf,p,(maxlen));                                  \
+                numbuf[(maxlen)]= 0;                                         \
+                val= strtoul(numbuf, &ep, (base));                           \
+                if (ep <= numbuf+(minlen)) {                                 \
+                    xlu__cfgl_lexicalerror(ctx,"invalid digit after"         \
+                         " backslash " basetext "numerical character escape" \
+                         " in quoted string");                               \
+                    ctx->err= EINVAL;                                        \
+                    goto x;                                                  \
+                }                                                            \
+                p += (ep - numbuf);                                          \
+ }while(0)
+
+                p++;
+                NUMERIC_CHAR(2,2,16,"hex");
+            } else if (nc>='0' && nc<='7') {
+                NUMERIC_CHAR(1,3,10,"octal");
+            } else {
+                xlu__cfgl_lexicalerror(ctx,
+                           "invalid character after backlash in quoted 
string");
+                ctx->err= EINVAL;
+                goto x;
+            }
+            assert(p <= src+len-1);
+        } else {
+            *q++= c;
+        }
+    }
+
+ x:
+    *q++= 0;
+    return result;
+}
+
+void xlu__cfgl_lexicalerror(CfgParseContext *ctx, char const *msg) {
+    YYLTYPE loc;
+    loc.first_line= xlu__cfg_yyget_lineno(ctx->scanner);
+    xlu__cfg_yyerror(&loc, ctx, msg);
+    ctx->lexerrlineno= loc.first_line;
+}
+
+void xlu__cfg_yyerror(YYLTYPE *loc, CfgParseContext *ctx, char const *msg) {
+    const char *text, *newline;
+    int len, lineno;
+
+    lineno= loc->first_line;
+    if (lineno <= ctx->lexerrlineno) return;
+
+    text= xlu__cfg_yyget_text(ctx->scanner);
+    len= xlu__cfg_yyget_leng(ctx->scanner);
+    newline= "";
+    if (len>0 && text[len-1]=='\n') {
+        len--;
+        lineno--;
+        if (!len) {
+            newline= "<newline>";
+        }
+    }
+    while (len>0 && (text[len-1]=='\t' || text[len-1]==' ')) {
+        len--;
+    }
+
+    fprintf(ctx->cfg->report,
+            "%s:%d: config parsing error near %s%.*s%s%s: %s\n",
+            ctx->cfg->config_source, lineno,
+            len?"`":"", len, text, len?"'":"", newline,
+            msg);
+    if (!ctx->err) ctx->err= EINVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/util/libxlu_cfg_i.h b/tools/libs/util/libxlu_cfg_i.h
new file mode 100644
index 0000000000..4217f5b28d
--- /dev/null
+++ b/tools/libs/util/libxlu_cfg_i.h
@@ -0,0 +1,59 @@
+/*
+ * libxlu_cfg_i.h - xl configuration file parsing: parser-internal declarations
+ *
+ * Copyright (C) 2010      Citrix Ltd.
+ * Author Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#ifndef LIBXLU_CFG_I_H
+#define LIBXLU_CFG_I_H
+
+#include "libxlu_internal.h"
+#include "libxlu_cfg_y.h"
+
+void xlu__cfg_set_free(XLU_ConfigSetting *set);
+void xlu__cfg_set_store(CfgParseContext*, char *name,
+                        enum XLU_Operation op,
+                        XLU_ConfigValue *val, int lineno);
+XLU_ConfigValue *xlu__cfg_string_mk(CfgParseContext *ctx,
+                                    char *atom, YYLTYPE *loc);
+XLU_ConfigValue *xlu__cfg_list_mk(CfgParseContext *ctx,
+                                  XLU_ConfigValue *val,
+                                  YYLTYPE *loc);
+void xlu__cfg_list_append(CfgParseContext *ctx,
+                          XLU_ConfigValue *list,
+                          XLU_ConfigValue *val);
+void xlu__cfg_value_free(XLU_ConfigValue *value);
+char *xlu__cfgl_strdup(CfgParseContext*, const char *src);
+char *xlu__cfgl_dequote(CfgParseContext*, const char *src);
+
+void xlu__cfg_yyerror(YYLTYPE *locp, CfgParseContext*, char const *msg);
+void xlu__cfgl_lexicalerror(CfgParseContext*, char const *msg);
+
+void xlu__cfgl_likely_python(CfgParseContext *ctx);
+
+
+
+/* Why oh why does bison not declare this in its autogenerated .h ? */
+int xlu__cfg_yyparse(CfgParseContext *ctx);
+
+
+#endif /*LIBXLU_CFG_I_H*/
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libs/util/libxlu_cfg_l.c b/tools/libs/util/libxlu_cfg_l.c
new file mode 100644
index 0000000000..406b50a037
--- /dev/null
+++ b/tools/libs/util/libxlu_cfg_l.c
@@ -0,0 +1,2375 @@
+#line 2 "libxlu_cfg_l.c"
+
+#line 4 "libxlu_cfg_l.c"
+
+#define  YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 6
+#define YY_FLEX_SUBMINOR_VERSION 4
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+#ifdef yy_create_buffer
+#define xlu__cfg_yy_create_buffer_ALREADY_DEFINED
+#else
+#define yy_create_buffer xlu__cfg_yy_create_buffer
+#endif
+
+#ifdef yy_delete_buffer
+#define xlu__cfg_yy_delete_buffer_ALREADY_DEFINED
+#else
+#define yy_delete_buffer xlu__cfg_yy_delete_buffer
+#endif
+
+#ifdef yy_scan_buffer
+#define xlu__cfg_yy_scan_buffer_ALREADY_DEFINED
+#else
+#define yy_scan_buffer xlu__cfg_yy_scan_buffer
+#endif
+
+#ifdef yy_scan_string
+#define xlu__cfg_yy_scan_string_ALREADY_DEFINED
+#else
+#define yy_scan_string xlu__cfg_yy_scan_string
+#endif
+
+#ifdef yy_scan_bytes
+#define xlu__cfg_yy_scan_bytes_ALREADY_DEFINED
+#else
+#define yy_scan_bytes xlu__cfg_yy_scan_bytes
+#endif
+
+#ifdef yy_init_buffer
+#define xlu__cfg_yy_init_buffer_ALREADY_DEFINED
+#else
+#define yy_init_buffer xlu__cfg_yy_init_buffer
+#endif
+
+#ifdef yy_flush_buffer
+#define xlu__cfg_yy_flush_buffer_ALREADY_DEFINED
+#else
+#define yy_flush_buffer xlu__cfg_yy_flush_buffer
+#endif
+
+#ifdef yy_load_buffer_state
+#define xlu__cfg_yy_load_buffer_state_ALREADY_DEFINED
+#else
+#define yy_load_buffer_state xlu__cfg_yy_load_buffer_state
+#endif
+
+#ifdef yy_switch_to_buffer
+#define xlu__cfg_yy_switch_to_buffer_ALREADY_DEFINED
+#else
+#define yy_switch_to_buffer xlu__cfg_yy_switch_to_buffer
+#endif
+
+#ifdef yypush_buffer_state
+#define xlu__cfg_yypush_buffer_state_ALREADY_DEFINED
+#else
+#define yypush_buffer_state xlu__cfg_yypush_buffer_state
+#endif
+
+#ifdef yypop_buffer_state
+#define xlu__cfg_yypop_buffer_state_ALREADY_DEFINED
+#else
+#define yypop_buffer_state xlu__cfg_yypop_buffer_state
+#endif
+
+#ifdef yyensure_buffer_stack
+#define xlu__cfg_yyensure_buffer_stack_ALREADY_DEFINED
+#else
+#define yyensure_buffer_stack xlu__cfg_yyensure_buffer_stack
+#endif
+
+#ifdef yylex
+#define xlu__cfg_yylex_ALREADY_DEFINED
+#else
+#define yylex xlu__cfg_yylex
+#endif
+
+#ifdef yyrestart
+#define xlu__cfg_yyrestart_ALREADY_DEFINED
+#else
+#define yyrestart xlu__cfg_yyrestart
+#endif
+
+#ifdef yylex_init
+#define xlu__cfg_yylex_init_ALREADY_DEFINED
+#else
+#define yylex_init xlu__cfg_yylex_init
+#endif
+
+#ifdef yylex_init_extra
+#define xlu__cfg_yylex_init_extra_ALREADY_DEFINED
+#else
+#define yylex_init_extra xlu__cfg_yylex_init_extra
+#endif
+
+#ifdef yylex_destroy
+#define xlu__cfg_yylex_destroy_ALREADY_DEFINED
+#else
+#define yylex_destroy xlu__cfg_yylex_destroy
+#endif
+
+#ifdef yyget_debug
+#define xlu__cfg_yyget_debug_ALREADY_DEFINED
+#else
+#define yyget_debug xlu__cfg_yyget_debug
+#endif
+
+#ifdef yyset_debug
+#define xlu__cfg_yyset_debug_ALREADY_DEFINED
+#else
+#define yyset_debug xlu__cfg_yyset_debug
+#endif
+
+#ifdef yyget_extra
+#define xlu__cfg_yyget_extra_ALREADY_DEFINED
+#else
+#define yyget_extra xlu__cfg_yyget_extra
+#endif
+
+#ifdef yyset_extra
+#define xlu__cfg_yyset_extra_ALREADY_DEFINED
+#else
+#define yyset_extra xlu__cfg_yyset_extra
+#endif
+
+#ifdef yyget_in
+#define xlu__cfg_yyget_in_ALREADY_DEFINED
+#else
+#define yyget_in xlu__cfg_yyget_in
+#endif
+
+#ifdef yyset_in
+#define xlu__cfg_yyset_in_ALREADY_DEFINED
+#else
+#define yyset_in xlu__cfg_yyset_in
+#endif
+
+#ifdef yyget_out
+#define xlu__cfg_yyget_out_ALREADY_DEFINED
+#else
+#define yyget_out xlu__cfg_yyget_out
+#endif
+
+#ifdef yyset_out
+#define xlu__cfg_yyset_out_ALREADY_DEFINED
+#else
+#define yyset_out xlu__cfg_yyset_out
+#endif
+
+#ifdef yyget_leng
+#define xlu__cfg_yyget_leng_ALREADY_DEFINED
+#else
+#define yyget_leng xlu__cfg_yyget_leng
+#endif
+
+#ifdef yyget_text
+#define xlu__cfg_yyget_text_ALREADY_DEFINED
+#else
+#define yyget_text xlu__cfg_yyget_text
+#endif
+
+#ifdef yyget_lineno
+#define xlu__cfg_yyget_lineno_ALREADY_DEFINED
+#else
+#define yyget_lineno xlu__cfg_yyget_lineno
+#endif
+
+#ifdef yyset_lineno
+#define xlu__cfg_yyset_lineno_ALREADY_DEFINED
+#else
+#define yyset_lineno xlu__cfg_yyset_lineno
+#endif
+
+#ifdef yyget_column
+#define xlu__cfg_yyget_column_ALREADY_DEFINED
+#else
+#define yyget_column xlu__cfg_yyget_column
+#endif
+
+#ifdef yyset_column
+#define xlu__cfg_yyset_column_ALREADY_DEFINED
+#else
+#define yyset_column xlu__cfg_yyset_column
+#endif
+
+#ifdef yywrap
+#define xlu__cfg_yywrap_ALREADY_DEFINED
+#else
+#define yywrap xlu__cfg_yywrap
+#endif
+
+#ifdef yyget_lval
+#define xlu__cfg_yyget_lval_ALREADY_DEFINED
+#else
+#define yyget_lval xlu__cfg_yyget_lval
+#endif
+
+#ifdef yyset_lval
+#define xlu__cfg_yyset_lval_ALREADY_DEFINED
+#else
+#define yyset_lval xlu__cfg_yyset_lval
+#endif
+
+#ifdef yyget_lloc
+#define xlu__cfg_yyget_lloc_ALREADY_DEFINED
+#else
+#define yyget_lloc xlu__cfg_yyget_lloc
+#endif
+
+#ifdef yyset_lloc
+#define xlu__cfg_yyset_lloc_ALREADY_DEFINED
+#else
+#define yyset_lloc xlu__cfg_yyset_lloc
+#endif
+
+#ifdef yyalloc
+#define xlu__cfg_yyalloc_ALREADY_DEFINED
+#else
+#define yyalloc xlu__cfg_yyalloc
+#endif
+
+#ifdef yyrealloc
+#define xlu__cfg_yyrealloc_ALREADY_DEFINED
+#else
+#define yyrealloc xlu__cfg_yyrealloc
+#endif
+
+#ifdef yyfree
+#define xlu__cfg_yyfree_ALREADY_DEFINED
+#else
+#define yyfree xlu__cfg_yyfree
+#endif
+
+/* First, we deal with  platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types. 
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t; 
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN               (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN              (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN              (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX               (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX              (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX              (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX              (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX             (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX             (4294967295U)
+#endif
+
+#ifndef SIZE_MAX
+#define SIZE_MAX               (~(size_t)0)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+/* begin standard C++ headers. */
+
+/* TODO: this is always defined, so inline it */
+#define yyconst const
+
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define yynoreturn __attribute__((__noreturn__))
+#else
+#define yynoreturn
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an
+ *   integer in range [0..255] for use as an array index.
+ */
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+   are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin , yyscanner )
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the 
main buffer.
+ */
+#define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+    
+    /* Note: We specifically omit the test for yy_rule_can_match_eol because 
it requires
+     *       access to the local variable yy_act. Since yyless() is a macro, 
it would break
+     *       existing scanners that call yyless() from OUTSIDE yylex.
+     *       One obvious solution it to make yy_act a global. I tried that, 
and saw
+     *       a 5% performance hit in a non-yylineno scanner, because yy_act is
+     *       normally declared as a register variable-- so it is not worth it.
+     */
+    #define  YY_LESS_LINENO(n) \
+            do { \
+                int yyl;\
+                for ( yyl = n; yyl < yyleng; ++yyl )\
+                    if ( yytext[yyl] == '\n' )\
+                        --yylineno;\
+            }while(0)
+    #define YY_LINENO_REWIND_TO(dst) \
+            do {\
+                const char *p;\
+                for ( p = yy_cp-1; p >= (dst); --p)\
+                    if ( *p == '\n' )\
+                        --yylineno;\
+            }while(0)
+    
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+        int yyless_macro_arg = (n); \
+        YY_LESS_LINENO(yyless_macro_arg);\
+               *yy_cp = yyg->yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - 
YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       int yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+    int yy_bs_lineno; /**< The line count. */
+    int yy_bs_column; /**< The column count. */
+
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+
+       };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+                          ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+                          : NULL)
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void yyrestart ( FILE *input_file , yyscan_t yyscanner );
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner );
+void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner );
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner );
+void yypop_buffer_state ( yyscan_t yyscanner );
+
+static void yyensure_buffer_stack ( yyscan_t yyscanner );
+static void yy_load_buffer_state ( yyscan_t yyscanner );
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t 
yyscanner );
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner)
+
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t 
yyscanner );
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len , yyscan_t 
yyscanner );
+
+void *yyalloc ( yy_size_t , yyscan_t yyscanner );
+void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner );
+void yyfree ( void * , yyscan_t yyscanner );
+
+#define yy_new_buffer yy_create_buffer
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){ \
+        yyensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+       }
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! YY_CURRENT_BUFFER ){\
+        yyensure_buffer_stack (yyscanner); \
+               YY_CURRENT_BUFFER_LVALUE =    \
+            yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \
+       } \
+       YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+       }
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+#define xlu__cfg_yywrap(yyscanner) (/*CONSTCOND*/1)
+#define YY_SKIP_YYWRAP
+typedef flex_uint8_t YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state ( yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state  , 
yyscan_t yyscanner);
+static int yy_get_next_buffer ( yyscan_t yyscanner );
+static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yyg->yytext_ptr = yy_bp; \
+       yyg->yytext_ptr -= yyg->yy_more_len; \
+       yyleng = (int) (yy_cp - yyg->yytext_ptr); \
+       yyg->yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yyg->yy_c_buf_p = yy_cp;
+#define YY_NUM_RULES 17
+#define YY_END_OF_BUFFER 18
+/* This struct is not used in this scanner,
+   but its presence is necessary. */
+struct yy_trans_info
+       {
+       flex_int32_t yy_verify;
+       flex_int32_t yy_nxt;
+       };
+static const flex_int16_t yy_accept[37] =
+    {   0,
+        0,    0,   15,   15,   18,   14,    3,   10,   14,   14,
+       14,   13,   13,    4,    2,    9,    8,    5,    6,    1,
+       15,   15,   16,    0,   12,    0,    0,   10,    0,   11,
+        0,    7,    2,    1,   15,    0
+    } ;
+
+static const YY_CHAR yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    5,    1,    1,    1,    6,    7,
+        7,    1,    8,    9,    7,   10,    1,   11,   11,   11,
+       11,   11,   11,   11,   11,   11,   11,    7,   12,    1,
+       13,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+       14,   15,   16,    1,   17,    1,   18,   18,   18,   18,
+
+       18,   18,   19,   19,   19,   19,   19,   19,   19,   19,
+       19,   19,   19,   19,   19,   19,   19,   19,   19,   18,
+       19,   19,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static const YY_CHAR yy_meta[20] =
+    {   0,
+        1,    2,    3,    1,    1,    1,    1,    1,    1,    4,
+        4,    1,    1,    1,    1,    1,    4,    4,    4
+    } ;
+
+static const flex_int16_t yy_base[43] =
+    {   0,
+        0,    0,   18,   20,   53,   59,   59,   59,   20,   42,
+       19,   59,   19,   59,   15,   59,   59,   59,   59,    0,
+        0,   59,   59,   23,   59,    0,   28,   59,   22,   59,
+        0,   59,   18,    0,    0,   59,   38,   42,   46,   50,
+       26,   54
+    } ;
+
+static const flex_int16_t yy_def[43] =
+    {   0,
+       36,    1,   37,   37,   36,   36,   36,   36,   38,   39,
+       40,   36,   36,   36,   36,   36,   36,   36,   36,   41,
+       42,   36,   36,   38,   36,   38,   39,   36,   40,   36,
+       40,   36,   36,   41,   42,    0,   36,   36,   36,   36,
+       36,   36
+    } ;
+
+static const flex_int16_t yy_nxt[79] =
+    {   0,
+        6,    7,    8,    9,   10,   11,   12,   13,   14,   12,
+       15,   16,   17,   18,    6,   19,    6,   20,   20,   22,
+       23,   22,   23,   25,   30,   33,   25,   30,   33,   34,
+       28,   32,   33,   31,   26,   33,   31,   26,   21,   21,
+       21,   21,   24,   24,   28,   24,   27,   27,   27,   27,
+       29,   29,   36,   29,   35,   36,   36,   35,    5,   36,
+       36,   36,   36,   36,   36,   36,   36,   36,   36,   36,
+       36,   36,   36,   36,   36,   36,   36,   36
+    } ;
+
+static const flex_int16_t yy_chk[79] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    3,
+        3,    4,    4,    9,   11,   15,   24,   29,   33,   41,
+       27,   13,   15,   11,    9,   33,   29,   24,   37,   37,
+       37,   37,   38,   38,   10,   38,   39,   39,   39,   39,
+       40,   40,    5,   40,   42,    0,    0,   42,   36,   36,
+       36,   36,   36,   36,   36,   36,   36,   36,   36,   36,
+       36,   36,   36,   36,   36,   36,   36,   36
+    } ;
+
+/* Table of booleans, true if rule could match eol. */
+static const flex_int32_t yy_rule_can_match_eol[18] =
+    {   0,
+0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,     };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() (yyg->yy_more_flag = 1)
+#define YY_MORE_ADJ yyg->yy_more_len
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "libxlu_cfg_l.l"
+/* -*- fundamental -*- */
+/*
+ * libxlu_cfg_l.l - xl configuration file parsing: lexer
+ *
+ * Copyright (C) 2010      Citrix Ltd.
+ * Author Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+#line 20 "libxlu_cfg_l.l"
+#include "libxlu_cfg_i.h"
+
+#define ctx ((CfgParseContext*)yyextra)
+#define YY_NO_INPUT
+
+#define GOT(x) do{                \
+    yylloc->first_line= yylineno; \
+    return (x);                   \
+  }while(0)
+
+/* Some versions of flex have a bug (Fedora bugzilla 612465) which causes
+ * it to fail to declare these functions, which it defines.  So declare
+ * them ourselves.  Hopefully we won't have to simultaneously support
+ * a flex version which declares these differently somehow. */
+int xlu__cfg_yyget_column(yyscan_t yyscanner);
+void xlu__cfg_yyset_column(int  column_no, yyscan_t yyscanner);
+
+#line 740 "libxlu_cfg_l.c"
+
+#line 742 "libxlu_cfg_l.c"
+
+#define INITIAL 0
+#define lexerr 1
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+    {
+
+    /* User-defined. Not touched by flex. */
+    YY_EXTRA_TYPE yyextra_r;
+
+    /* The rest are the same as the globals declared in the non-reentrant 
scanner. */
+    FILE *yyin_r, *yyout_r;
+    size_t yy_buffer_stack_top; /**< index of top of stack. */
+    size_t yy_buffer_stack_max; /**< capacity of stack. */
+    YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+    char yy_hold_char;
+    int yy_n_chars;
+    int yyleng_r;
+    char *yy_c_buf_p;
+    int yy_init;
+    int yy_start;
+    int yy_did_buffer_switch_on_eof;
+    int yy_start_stack_ptr;
+    int yy_start_stack_depth;
+    int *yy_start_stack;
+    yy_state_type yy_last_accepting_state;
+    char* yy_last_accepting_cpos;
+
+    int yylineno_r;
+    int yy_flex_debug_r;
+
+    char *yytext_r;
+    int yy_more_flag;
+    int yy_more_len;
+
+    YYSTYPE * yylval_r;
+
+    YYLTYPE * yylloc_r;
+
+    }; /* end struct yyguts_t */
+
+static int yy_init_globals ( yyscan_t yyscanner );
+
+    /* This must go here because YYSTYPE and YYLTYPE are included
+     * from bison output in section 1.*/
+    #    define yylval yyg->yylval_r
+    
+    #    define yylloc yyg->yylloc_r
+    
+int yylex_init (yyscan_t* scanner);
+
+int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner);
+
+/* Accessor methods to globals.
+   These are made visible to non-reentrant scanners for convenience. */
+
+int yylex_destroy ( yyscan_t yyscanner );
+
+int yyget_debug ( yyscan_t yyscanner );
+
+void yyset_debug ( int debug_flag , yyscan_t yyscanner );
+
+YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner );
+
+void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner );
+
+FILE *yyget_in ( yyscan_t yyscanner );
+
+void yyset_in  ( FILE * _in_str , yyscan_t yyscanner );
+
+FILE *yyget_out ( yyscan_t yyscanner );
+
+void yyset_out  ( FILE * _out_str , yyscan_t yyscanner );
+
+                       int yyget_leng ( yyscan_t yyscanner );
+
+char *yyget_text ( yyscan_t yyscanner );
+
+int yyget_lineno ( yyscan_t yyscanner );
+
+void yyset_lineno ( int _line_number , yyscan_t yyscanner );
+
+int yyget_column  ( yyscan_t yyscanner );
+
+void yyset_column ( int _column_no , yyscan_t yyscanner );
+
+YYSTYPE * yyget_lval ( yyscan_t yyscanner );
+
+void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner );
+
+       YYLTYPE *yyget_lloc ( yyscan_t yyscanner );
+    
+        void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner );
+    
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap ( yyscan_t yyscanner );
+#else
+extern int yywrap ( yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+    
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen ( const char * , yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput ( yyscan_t yyscanner );
+#else
+static int input ( yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while 
(0)
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+               { \
+               int c = '*'; \
+               int n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, 
yyin)) == 0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" 
); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t 
yyscanner);
+
+#define YY_DECL int yylex \
+               (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t 
yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK /*LINTED*/break;
+#endif
+
+#define YY_RULE_SETUP \
+       YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+       yy_state_type yy_current_state;
+       char *yy_cp, *yy_bp;
+       int yy_act;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+    yylval = yylval_param;
+
+    yylloc = yylloc_param;
+
+       if ( !yyg->yy_init )
+               {
+               yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yyg->yy_start )
+                       yyg->yy_start = 1;      /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! YY_CURRENT_BUFFER ) {
+                       yyensure_buffer_stack (yyscanner);
+                       YY_CURRENT_BUFFER_LVALUE =
+                               yy_create_buffer( yyin, YY_BUF_SIZE , 
yyscanner);
+               }
+
+               yy_load_buffer_state( yyscanner );
+               }
+
+       {
+#line 53 "libxlu_cfg_l.l"
+
+
+#line 1028 "libxlu_cfg_l.c"
+
+       while ( /*CONSTCOND*/1 )                /* loops until end-of-file is 
reached */
+               {
+               yyg->yy_more_len = 0;
+               if ( yyg->yy_more_flag )
+                       {
+                       yyg->yy_more_len = (int) (yyg->yy_c_buf_p - 
yyg->yytext_ptr);
+                       yyg->yy_more_flag = 0;
+                       }
+               yy_cp = yyg->yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yyg->yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yyg->yy_start;
+yy_match:
+               do
+                       {
+                       YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               yyg->yy_last_accepting_state = yy_current_state;
+                               yyg->yy_last_accepting_cpos = yy_cp;
+                               }
+                       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 >= 37 )
+                                       yy_c = yy_meta[yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + 
yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_current_state != 36 );
+               yy_cp = yyg->yy_last_accepting_cpos;
+               yy_current_state = yyg->yy_last_accepting_state;
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+
+               YY_DO_BEFORE_ACTION;
+
+               if ( yy_act != YY_END_OF_BUFFER && 
yy_rule_can_match_eol[yy_act] )
+                       {
+                       int yyl;
+                       for ( yyl = yyg->yy_more_len; yyl < yyleng; ++yyl )
+                               if ( yytext[yyl] == '\n' )
+                                       
+    do{ yylineno++;
+        yycolumn=0;
+    }while(0)
+;
+                       }
+
+do_action:     /* This label is used only to access EOF actions. */
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = yyg->yy_hold_char;
+                       yy_cp = yyg->yy_last_accepting_cpos;
+                       yy_current_state = yyg->yy_last_accepting_state;
+                       goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 55 "libxlu_cfg_l.l"
+{
+                          yylval->string= xlu__cfgl_strdup(ctx,yytext);
+                          GOT(IDENT);
+                        }
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 59 "libxlu_cfg_l.l"
+{
+                          yylval->string= xlu__cfgl_strdup(ctx,yytext);
+                          GOT(NUMBER);
+                        }
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 64 "libxlu_cfg_l.l"
+
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 66 "libxlu_cfg_l.l"
+{ GOT(','); }
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 67 "libxlu_cfg_l.l"
+{ GOT('['); }
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 68 "libxlu_cfg_l.l"
+{ GOT(']'); }
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 69 "libxlu_cfg_l.l"
+{ GOT(OP_ADD); }
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 70 "libxlu_cfg_l.l"
+{ GOT('='); }
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 71 "libxlu_cfg_l.l"
+{ GOT(';'); }
+       YY_BREAK
+case 10:
+/* rule 10 can match eol */
+YY_RULE_SETUP
+#line 73 "libxlu_cfg_l.l"
+{ yylloc->first_line= yylineno-1; return NEWLINE; }
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 75 "libxlu_cfg_l.l"
+{
+                          yylval->string= xlu__cfgl_dequote(ctx,yytext);
+                          GOT(STRING);
+                        }
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 79 "libxlu_cfg_l.l"
+{
+                          yylval->string= xlu__cfgl_dequote(ctx,yytext);
+                          GOT(STRING);
+                        }
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 84 "libxlu_cfg_l.l"
+{
+                          ctx->likely_python= 1;
+                          BEGIN(lexerr);
+                          yymore();
+                        }
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 90 "libxlu_cfg_l.l"
+{
+                          BEGIN(lexerr);
+                          yymore();
+                        }
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 95 "libxlu_cfg_l.l"
+{
+                          xlu__cfgl_lexicalerror(ctx,"lexical error");
+                          BEGIN(0);
+                        }
+       YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 100 "libxlu_cfg_l.l"
+{
+                          xlu__cfgl_lexicalerror(ctx,"lexical error");
+                          BEGIN(0);
+                          GOT(NEWLINE);
+                        }
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 105 "libxlu_cfg_l.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+       YY_BREAK
+#line 1212 "libxlu_cfg_l.c"
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(lexerr):
+       yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) 
- 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yyg->yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == 
YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between YY_CURRENT_BUFFER and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+                       YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = 
YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yyg->yy_c_buf_p <= 
&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yyg->yy_c_buf_p = yyg->yytext_ptr + 
yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state( yyscanner );
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state , 
yyscanner);
+
+                       yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yyg->yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yyg->yy_last_accepting_cpos;
+                               yy_current_state = yyg->yy_last_accepting_state;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer( yyscanner ) )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yyg->yy_did_buffer_switch_on_eof = 0;
+
+                               if ( yywrap( yyscanner ) )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yyg->yy_c_buf_p = yyg->yytext_ptr + 
YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yyg->yy_did_buffer_switch_on_eof 
)
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yyg->yy_c_buf_p =
+                                       yyg->yytext_ptr + 
yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state( 
yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yyg->yy_c_buf_p =
+                               
&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state( 
yyscanner );
+
+                               yy_cp = yyg->yy_c_buf_p;
+                               yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+       } /* end of user's declarations */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+       char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+       char *source = yyg->yytext_ptr;
+       int number_to_move, i;
+       int ret_val;
+
+       if ( yyg->yy_c_buf_p > 
&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == 
YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+       else
+               {
+                       int num_to_read =
+                       YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move 
- 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yyrealloc( (void *) b->yy_ch_buf,
+                                                        (yy_size_t) 
(b->yy_buf_size + 2) , yyscanner );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = NULL;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+                                               number_to_move - 1;
+
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( 
(&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+                       yyg->yy_n_chars, num_to_read );
+
+               YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+               }
+
+       if ( yyg->yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart( yyin  , yyscanner);
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       if ((yyg->yy_n_chars + number_to_move) > 
YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+               /* Extend the array by 50%, plus the number we really need. */
+               int new_size = yyg->yy_n_chars + number_to_move + 
(yyg->yy_n_chars >> 1);
+               YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
+                       (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, 
(yy_size_t) new_size , yyscanner );
+               if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+                       YY_FATAL_ERROR( "out of dynamic memory in 
yy_get_next_buffer()" );
+               /* "- 2" to take care of EOB's */
+               YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
+       }
+
+       yyg->yy_n_chars += number_to_move;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = 
YY_END_OF_BUFFER_CHAR;
+       YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = 
YY_END_OF_BUFFER_CHAR;
+
+       yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+       return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached 
*/
+
+    static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+       yy_state_type yy_current_state;
+       char *yy_cp;
+    struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+       yy_current_state = yyg->yy_start;
+
+       for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; 
++yy_cp )
+               {
+               YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       yyg->yy_last_accepting_state = yy_current_state;
+                       yyg->yy_last_accepting_cpos = yy_cp;
+                       }
+               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 >= 37 )
+                               yy_c = yy_meta[yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
+               }
+



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.