summaryrefslogtreecommitdiffstats
path: root/contrib/libxo
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2014-10-23 22:30:14 +0000
committermarcel <marcel@FreeBSD.org>2014-10-23 22:30:14 +0000
commitfefcd296e4716886912a74acd38abba4c94bc340 (patch)
treece8b178967e5d33cbba89d0b2f3d2c2ea45616cb /contrib/libxo
parentbc4f095bf4554f6047f55bd8d28df41679cade6b (diff)
downloadFreeBSD-src-fefcd296e4716886912a74acd38abba4c94bc340.zip
FreeBSD-src-fefcd296e4716886912a74acd38abba4c94bc340.tar.gz
Import libxo 0.1.4
Obtained from: https://github.com/Juniper/libxo Sponsored by: Juniper Networks, Inc.
Diffstat (limited to 'contrib/libxo')
-rw-r--r--contrib/libxo/.gitignore43
-rw-r--r--contrib/libxo/.travis.yml12
-rw-r--r--contrib/libxo/Copyright23
-rw-r--r--contrib/libxo/LICENSE23
-rw-r--r--contrib/libxo/Makefile.am102
-rw-r--r--contrib/libxo/README.md62
-rw-r--r--contrib/libxo/bin/Makefile.am29
-rw-r--r--contrib/libxo/bin/Zaliases24
-rwxr-xr-xcontrib/libxo/bin/setup.sh31
-rw-r--r--contrib/libxo/build/.create0
-rw-r--r--contrib/libxo/configure.ac263
-rw-r--r--contrib/libxo/doc/Makefile.am65
-rw-r--r--contrib/libxo/doc/libxo.txt2400
-rwxr-xr-xcontrib/libxo/install-sh527
-rw-r--r--contrib/libxo/libxo-config.in119
-rw-r--r--contrib/libxo/libxo/Makefile.am49
-rwxr-xr-xcontrib/libxo/libxo/gen-wide.sh76
-rw-r--r--contrib/libxo/libxo/libxo.3149
-rw-r--r--contrib/libxo/libxo/libxo.c4353
-rw-r--r--contrib/libxo/libxo/xo.h300
-rw-r--r--contrib/libxo/libxo/xo_attr.377
-rw-r--r--contrib/libxo/libxo/xo_create.385
-rw-r--r--contrib/libxo/libxo/xo_emit.371
-rw-r--r--contrib/libxo/libxo/xo_err.384
-rw-r--r--contrib/libxo/libxo/xo_finish.359
-rw-r--r--contrib/libxo/libxo/xo_flush.354
-rw-r--r--contrib/libxo/libxo/xo_format.5657
-rw-r--r--contrib/libxo/libxo/xo_no_setlocale.363
-rw-r--r--contrib/libxo/libxo/xo_open_container.3216
-rw-r--r--contrib/libxo/libxo/xo_open_list.3169
-rw-r--r--contrib/libxo/libxo/xo_parse_args.3133
-rw-r--r--contrib/libxo/libxo/xo_set_allocator.373
-rw-r--r--contrib/libxo/libxo/xo_set_flags.3128
-rw-r--r--contrib/libxo/libxo/xo_set_info.3113
-rw-r--r--contrib/libxo/libxo/xo_set_options.352
-rw-r--r--contrib/libxo/libxo/xo_set_style.372
-rw-r--r--contrib/libxo/libxo/xo_set_writer.368
-rw-r--r--contrib/libxo/libxo/xoconfig.h.in198
-rw-r--r--contrib/libxo/libxo/xoversion.h.in38
-rw-r--r--contrib/libxo/m4/libtool.m47982
-rw-r--r--contrib/libxo/m4/ltoptions.m4384
-rw-r--r--contrib/libxo/m4/ltsugar.m4123
-rw-r--r--contrib/libxo/m4/ltversion.m423
-rw-r--r--contrib/libxo/m4/lt~obsolete.m498
-rw-r--r--contrib/libxo/packaging/libxo.pc.in11
-rw-r--r--contrib/libxo/packaging/libxo.spec.in44
-rw-r--r--contrib/libxo/tests/Makefile.am28
-rw-r--r--contrib/libxo/tests/core/Makefile.am107
-rw-r--r--contrib/libxo/tests/core/saved/test_01.H.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.H.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_01.HIPx.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.HIPx.out238
-rw-r--r--contrib/libxo/tests/core/saved/test_01.HP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.HP.out238
-rw-r--r--contrib/libxo/tests/core/saved/test_01.J.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_01.JP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.JP.out93
-rw-r--r--contrib/libxo/tests/core/saved/test_01.T.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.T.out38
-rw-r--r--contrib/libxo/tests/core/saved/test_01.X.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.X.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_01.XP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.XP.out85
-rw-r--r--contrib/libxo/tests/core/saved/test_01.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_01.out38
-rw-r--r--contrib/libxo/tests/core/saved/test_02.H.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.H.out3
-rw-r--r--contrib/libxo/tests/core/saved/test_02.HIPx.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.HIPx.out125
-rw-r--r--contrib/libxo/tests/core/saved/test_02.HP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.HP.out125
-rw-r--r--contrib/libxo/tests/core/saved/test_02.J.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_02.JP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.JP.out40
-rw-r--r--contrib/libxo/tests/core/saved/test_02.T.err1
-rw-r--r--contrib/libxo/tests/core/saved/test_02.T.out20
-rw-r--r--contrib/libxo/tests/core/saved/test_02.X.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.X.out3
-rw-r--r--contrib/libxo/tests/core/saved/test_02.XP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.XP.out55
-rw-r--r--contrib/libxo/tests/core/saved/test_02.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_02.out38
-rw-r--r--contrib/libxo/tests/core/saved/test_03.H.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.H.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_03.HIPx.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.HIPx.out21
-rw-r--r--contrib/libxo/tests/core/saved/test_03.HP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.HP.out21
-rw-r--r--contrib/libxo/tests/core/saved/test_03.J.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_03.JP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.JP.out21
-rw-r--r--contrib/libxo/tests/core/saved/test_03.T.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.T.out3
-rw-r--r--contrib/libxo/tests/core/saved/test_03.X.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.X.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_03.XP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.XP.out17
-rw-r--r--contrib/libxo/tests/core/saved/test_03.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_03.out3
-rw-r--r--contrib/libxo/tests/core/saved/test_04.H.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.H.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_04.HIPx.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.HIPx.out20
-rw-r--r--contrib/libxo/tests/core/saved/test_04.HP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.HP.out20
-rw-r--r--contrib/libxo/tests/core/saved/test_04.J.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_04.JP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.JP.out21
-rw-r--r--contrib/libxo/tests/core/saved/test_04.T.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.T.out4
-rw-r--r--contrib/libxo/tests/core/saved/test_04.X.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.X.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_04.XP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_04.XP.out17
-rw-r--r--contrib/libxo/tests/core/saved/test_05.H.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.H.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_05.HIPx.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.HIPx.out77
-rw-r--r--contrib/libxo/tests/core/saved/test_05.HP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.HP.out77
-rw-r--r--contrib/libxo/tests/core/saved/test_05.J.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_05.JP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.JP.out56
-rw-r--r--contrib/libxo/tests/core/saved/test_05.T.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.T.out9
-rw-r--r--contrib/libxo/tests/core/saved/test_05.X.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.X.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_05.XP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_05.XP.out52
-rw-r--r--contrib/libxo/tests/core/saved/test_06.H.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.H.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_06.HIPx.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.HIPx.out21
-rw-r--r--contrib/libxo/tests/core/saved/test_06.HP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.HP.out21
-rw-r--r--contrib/libxo/tests/core/saved/test_06.J.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_06.JP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.JP.out21
-rw-r--r--contrib/libxo/tests/core/saved/test_06.T.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.T.out3
-rw-r--r--contrib/libxo/tests/core/saved/test_06.X.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.X.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_06.XP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_06.XP.out17
-rw-r--r--contrib/libxo/tests/core/saved/test_07.H.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.H.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_07.HIPx.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.HIPx.out107
-rw-r--r--contrib/libxo/tests/core/saved/test_07.HP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.HP.out107
-rw-r--r--contrib/libxo/tests/core/saved/test_07.J.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.J.out2
-rw-r--r--contrib/libxo/tests/core/saved/test_07.JP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.JP.out66
-rw-r--r--contrib/libxo/tests/core/saved/test_07.T.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.T.out19
-rw-r--r--contrib/libxo/tests/core/saved/test_07.X.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.X.out1
-rw-r--r--contrib/libxo/tests/core/saved/test_07.XP.err0
-rw-r--r--contrib/libxo/tests/core/saved/test_07.XP.out62
-rw-r--r--contrib/libxo/tests/core/test_01.c150
-rw-r--r--contrib/libxo/tests/core/test_02.c99
-rw-r--r--contrib/libxo/tests/core/test_03.c61
-rw-r--r--contrib/libxo/tests/core/test_04.c63
-rw-r--r--contrib/libxo/tests/core/test_05.c83
-rw-r--r--contrib/libxo/tests/core/test_06.c63
-rw-r--r--contrib/libxo/tests/core/test_07.c90
-rw-r--r--contrib/libxo/tests/xo/Makefile.am90
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.H.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.H.out1
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.HIPx.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.HIPx.out52
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.HP.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.HP.out52
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.J.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.J.out1
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.JP.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.JP.out22
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.T.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.T.out4
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.X.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.X.out1
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.XP.err0
-rw-r--r--contrib/libxo/tests/xo/saved/xo_01.XP.out22
-rwxr-xr-xcontrib/libxo/tests/xo/xo_01.sh27
-rw-r--r--contrib/libxo/warnings.mk57
-rw-r--r--contrib/libxo/xo/Makefile.am35
-rw-r--r--contrib/libxo/xo/xo.1190
-rw-r--r--contrib/libxo/xo/xo.c440
-rw-r--r--contrib/libxo/xohtml/external/jquery.js9300
-rw-r--r--contrib/libxo/xohtml/external/jquery.qtip.css599
-rw-r--r--contrib/libxo/xohtml/external/jquery.qtip.js2656
-rw-r--r--contrib/libxo/xohtml/xohtml.css1016
-rw-r--r--contrib/libxo/xohtml/xohtml.js54
-rw-r--r--contrib/libxo/xohtml/xohtml.sh.in55
-rw-r--r--contrib/libxo/xolint/Makefile.am14
-rw-r--r--contrib/libxo/xolint/xolint.189
-rwxr-xr-xcontrib/libxo/xolint/xolint.pl556
204 files changed, 37851 insertions, 0 deletions
diff --git a/contrib/libxo/.gitignore b/contrib/libxo/.gitignore
new file mode 100644
index 0000000..386bfc8
--- /dev/null
+++ b/contrib/libxo/.gitignore
@@ -0,0 +1,43 @@
+# Object files
+*.o
+
+# Libraries
+*.lib
+*.a
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.app
+
+*~
+*.orig
+
+aclocal.m4
+ar-lib
+autom4te.cache
+build
+compile
+config.guess
+config.h.in
+config.sub
+depcomp
+ltmain.sh
+missing
+
+Makefile.in
+configure
+.DS_Store
+
+xoconfig.h.in
+
+.gdbinit
+.gdbinit.local
+xtest
+xtest.dSYM
+tests/w
diff --git a/contrib/libxo/.travis.yml b/contrib/libxo/.travis.yml
new file mode 100644
index 0000000..e26a769
--- /dev/null
+++ b/contrib/libxo/.travis.yml
@@ -0,0 +1,12 @@
+language: c
+
+script: printenv && uname -a && /bin/sh ./bin/setup.sh && cd build && ../configure --enable-warnings && make && sudo make install && make test
+
+notifications:
+ recipients:
+ - libslax-noise@googlegroups.com
+
+branches:
+ only:
+ - master
+ - develop
diff --git a/contrib/libxo/Copyright b/contrib/libxo/Copyright
new file mode 100644
index 0000000..94ba75e
--- /dev/null
+++ b/contrib/libxo/Copyright
@@ -0,0 +1,23 @@
+Copyright (c) 2014 Juniper Networks, Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/contrib/libxo/LICENSE b/contrib/libxo/LICENSE
new file mode 100644
index 0000000..874da7b
--- /dev/null
+++ b/contrib/libxo/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2014, Juniper Networks
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/contrib/libxo/Makefile.am b/contrib/libxo/Makefile.am
new file mode 100644
index 0000000..f1fc999
--- /dev/null
+++ b/contrib/libxo/Makefile.am
@@ -0,0 +1,102 @@
+#
+# $Id$
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+ACLOCAL_AMFLAGS = -I m4
+
+SUBDIRS = libxo xo xolint tests doc
+bin_SCRIPTS=libxo-config
+dist_doc_DATA = Copyright
+
+EXTRA_DIST = \
+ libxo-config.in \
+ warnings.mk \
+ README.md \
+ INSTALL.md \
+ packaging/libxo.spec
+
+.PHONY: test tests
+
+test tests:
+ @(cd tests ; ${MAKE} test)
+
+errors:
+ @(cd tests/errors ; ${MAKE} test)
+
+docs:
+ @(cd doc ; ${MAKE} docs)
+
+
+DIST_FILES_DIR = ~/Dropbox/dist-files/
+GH_PAGES_DIR = gh-pages/
+PACKAGE_FILE = ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.gz
+
+upload: dist upload-docs
+ @echo "Remember to run:"
+ @echo " gt tag ${PACKAGE_VERSION}"
+
+upload-docs: docs
+ @echo "Uploading libxo-manual.html ... "
+ @-[ -d ${GH_PAGES_DIR} ] \
+ && echo "Updating manual on gh-pages ..." \
+ && cp doc/libxo-manual.html ${GH_PAGES_DIR} \
+ && (cd ${GH_PAGES_DIR} \
+ && git commit -m 'new docs' \
+ libxo-manual.html \
+ && git push origin gh-pages ) ; true
+
+pkgconfigdir=$(libdir)/pkgconfig
+pkgconfig_DATA = packaging/${PACKAGE_NAME}.pc
+
+get-wiki:
+ git clone https://github.com/Juniper/${PACKAGE_NAME}.wiki.git wiki
+
+get-gh-pages:
+ git clone https://github.com/Juniper/${PACKAGE_NAME}.git \
+ gh-pages -b gh-pages
+
+UPDATE_PACKAGE_FILE = \
+ -e "s;__SHA1__;$$SHA1;" \
+ -e "s;__SHA256__;SHA256 (textproc/${PACKAGE_FILE}) = $$SHA256;" \
+ -e "s;__SIZE__;SIZE (textproc/${PACKAGE_FILE}) = $$SIZE;"
+
+GH_PACKAGING_DIR = packaging/${PACKAGE_VERSION}
+GH_PAGES_PACKAGE_DIR = ${GH_PAGES_DIR}/${GH_PACKAGING_DIR}
+
+packages:
+ @-[ -d ${GH_PAGES_DIR} ] && set -x \
+ && echo "Updating packages on gh-pages ..." \
+ && SHA1="`openssl sha1 ${PACKAGE_FILE} | awk '{print $$2}'`" \
+ && SHA256="`openssl sha256 ${PACKAGE_FILE} | awk '{print $$2}'`" \
+ && SIZE="`ls -l ${PACKAGE_FILE} | awk '{print $$5}'`" \
+ && mkdir -p ${GH_PAGES_PACKAGE_DIR}/freebsd \
+ && echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.rb ..." \
+ && sed ${UPDATE_PACKAGE_FILE} \
+ packaging/${PACKAGE_NAME}.rb.base \
+ > ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.rb \
+ && echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec ..." \
+ && cp packaging/${PACKAGE_NAME}.spec \
+ ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec \
+ && echo "... ${GH_PAGES_PACKAGE_DIR}/freebsd ..." \
+ && sed ${UPDATE_PACKAGE_FILE} \
+ ${srcdir}/packaging/freebsd/distinfo.base \
+ > ${GH_PAGES_PACKAGE_DIR}/freebsd/distinfo \
+ && cp ${srcdir}/packaging/freebsd/pkg-descr \
+ ${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-descr \
+ && cp ${srcdir}/packaging/freebsd/pkg-plist \
+ ${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-plist \
+ && cp ${srcdir}/packaging/freebsd/pkg-plist \
+ ${GH_PAGES_PACKAGE_DIR}/freebsd/pkg-plist \
+ && cp packaging/freebsd/port-Makefile \
+ ${GH_PAGES_PACKAGE_DIR}/freebsd/Makefile \
+ && (cd ${GH_PAGES_DIR} \
+ && git add ${GH_PACKAGING_DIR} \
+ && git commit -m 'new packaging data' \
+ ${GH_PACKAGING_DIR} \
+ && git push origin gh-pages ) ; true
diff --git a/contrib/libxo/README.md b/contrib/libxo/README.md
new file mode 100644
index 0000000..40c162b
--- /dev/null
+++ b/contrib/libxo/README.md
@@ -0,0 +1,62 @@
+libxo
+=====
+
+libxo - A Library for Generating Text, XML, JSON, and HTML Output
+
+The libxo library allows an application to generate text, XML, JSON,
+and HTML output using a common set of function calls. The application
+decides at run time which output style should be produced. The
+application calls a function "xo_emit" to product output that is
+described in a format string. A "field descriptor" tells libxo what
+the field is and what it means.
+
+```
+ xo_emit(" {:lines/%7ju/%ju} {:words/%7ju/%ju} "
+ "{:characters/%7ju/%ju}{d:filename/%s}\n",
+ linect, wordct, charct, file);
+```
+
+Output can then be generated in various style, using the "--libxo"
+option:
+
+```
+ % wc /etc/motd
+ 25 165 1140 /etc/motd
+ % wc --libxo xml,pretty,warn /etc/motd
+ <wc>
+ <file>
+ <filename>/etc/motd</filename>
+ <lines>25</lines>
+ <words>165</words>
+ <characters>1140</characters>
+ </file>
+ </wc>
+ % wc --libxo json,pretty,warn /etc/motd
+ {
+ "wc": {
+ "file": [
+ {
+ "filename": "/etc/motd",
+ "lines": 25,
+ "words": 165,
+ "characters": 1140
+ }
+ ]
+ }
+ }
+ % wc --libxo html,pretty,warn /etc/motd
+ <div class="line">
+ <div class="text"> </div>
+ <div class="data" data-tag="lines"> 25</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="words"> 165</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="characters"> 1140</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="filename">/etc/motd</div>
+ </div>
+```
+
+View the beautiful documentation at:
+
+http://juniper.github.io/libxo/libxo-manual.html
diff --git a/contrib/libxo/bin/Makefile.am b/contrib/libxo/bin/Makefile.am
new file mode 100644
index 0000000..3bda1be
--- /dev/null
+++ b/contrib/libxo/bin/Makefile.am
@@ -0,0 +1,29 @@
+#
+# Copyright 2013, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+ACLOCAL_AMFLAGS = -I m4
+
+EXTRA_DIST = gt setup.sh
+
+GT_INSTALL_DIR = ${prefix}/bin
+GT_INSTALL_FILES = gt
+
+install-data-hook:
+ @echo "Installing gt ... "
+ @-mkdir -p ${GT_INSTALL_DIR}
+ @for file in ${GT_INSTALL_FILES} ; do \
+ if [ -f $$file ]; then \
+ rfile=$$file ; \
+ else \
+ rfile=${srcdir}/$$file ; \
+ fi ; \
+ mdir=${GT_INSTALL_DIR}/ ; \
+ mkdir -p $$mdir ; \
+ cp $$rfile $$mdir/ ; \
+ done
+ @${CHMOD} a+x ${GT_INSTALL_DIR}/gt
diff --git a/contrib/libxo/bin/Zaliases b/contrib/libxo/bin/Zaliases
new file mode 100644
index 0000000..a24d33e
--- /dev/null
+++ b/contrib/libxo/bin/Zaliases
@@ -0,0 +1,24 @@
+set top_src=`pwd`
+alias Zautoreconf "(cd $top_src ; autoreconf --install)"
+
+set opts=' \
+--with-libslax-prefix=/Users/phil/work/root \
+--enable-debug \
+--enable-warnings \
+--enable-printflike \
+--prefix ${HOME}/work/root \
+'
+set opts=`echo $opts`
+
+setenv CONFIGURE_OPTS "$opts"
+setenv ADB_PATH $top_src/build/libxo/.libs
+
+alias Zconfigure "(cd $top_src/build; ../configure $opts)"
+alias Zbuild "(cd $top_src/build; make \!* )"
+alias mi "(cd $top_src/build; make && make install); ."
+
+mkdir -p build
+cd build
+
+
+alias xx 'cc -I.. -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Werror -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wformat -Wimplicit -Wmissing-declarations -Wnested-externs -Wparentheses -Wreturn-type -Wshadow -Wswitch -Wtrigraphs -Wuninitialized -Wunused -Wwrite-strings -fno-inline-functions-called-once -g -O2 -o xtest -DUNIT_TEST libxo.c'
diff --git a/contrib/libxo/bin/setup.sh b/contrib/libxo/bin/setup.sh
new file mode 100755
index 0000000..5e03ff3
--- /dev/null
+++ b/contrib/libxo/bin/setup.sh
@@ -0,0 +1,31 @@
+#
+# Copyright 2013, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+
+if [ ! -f configure ]; then
+ vers=`autoreconf --version | head -1`
+ echo "Using" $vers
+
+ autoreconf --install
+
+ if [ ! -f configure ]; then
+ echo "Failed to create configure script"
+ exit 1
+ fi
+fi
+
+echo "Creating build directory ..."
+mkdir build
+
+echo "Setup is complete. To build libslax:"
+
+echo " 1) Type 'cd build ; ../configure' to configure libslax"
+echo " 2) Type 'make' to build libslax"
+echo " 3) Type 'make install' to install libslax"
+
+exit 0
diff --git a/contrib/libxo/build/.create b/contrib/libxo/build/.create
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/build/.create
diff --git a/contrib/libxo/configure.ac b/contrib/libxo/configure.ac
new file mode 100644
index 0000000..2412d12
--- /dev/null
+++ b/contrib/libxo/configure.ac
@@ -0,0 +1,263 @@
+#
+# $Id$
+#
+# See ./INSTALL for more info
+#
+
+#
+# Release numbering: even numbered dot releases are official ones, and
+# odd numbers are development ones. The svn version of this file will
+# only (ONLY!) ever (EVER!) contain odd numbers, so I'll always know if
+# a particular user has the dist or svn release.
+#
+
+AC_PREREQ(2.2)
+AC_INIT([libxo], [0.1.4], [phil@juniper.net])
+AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability])
+
+# Support silent build rules. Requires at least automake-1.11.
+# Disable with "configure --disable-silent-rules" or "make V=1"
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_PROG_CC
+AM_PROG_AR
+AC_PROG_INSTALL
+AC_CONFIG_MACRO_DIR([m4])
+AC_PROG_LN_S
+
+# Must be after AC_PROG_AR
+LT_INIT([dlopen shared])
+
+AC_PATH_PROG(BASENAME, basename, /usr/bin/basename)
+AC_PATH_PROG(BISON, bison, /usr/bin/bison)
+AC_PATH_PROG(CAT, cat, /bin/cat)
+AC_PATH_PROG(CHMOD, chmod, /bin/chmod)
+AC_PATH_PROG(CP, cp, /bin/cp)
+AC_PATH_PROG(DIFF, diff, /usr/bin/diff)
+AC_PATH_PROG(MKDIR, mkdir, /bin/mkdir)
+AC_PATH_PROG(MV, mv, /bin/mv)
+AC_PATH_PROG(RM, rm, /bin/rm)
+AC_PATH_PROG(SED, sed, /bin/sed)
+
+AC_STDC_HEADERS
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_C_INLINE
+AC_TYPE_SIZE_T
+
+# Checks for library functions.
+AC_FUNC_ALLOCA
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_CHECK_FUNCS([bzero memmove strchr strcspn strerror strspn])
+AC_CHECK_FUNCS([sranddev srand strlcpy])
+AC_CHECK_FUNCS([fdopen getrusage])
+AC_CHECK_FUNCS([gettimeofday ctime])
+AC_CHECK_FUNCS([getpass])
+AC_CHECK_FUNCS([sysctlbyname])
+AC_CHECK_FUNCS([flock])
+AC_CHECK_FUNCS([asprintf])
+
+AC_CHECK_HEADERS([dlfcn.h])
+AC_CHECK_HEADERS([tzfile.h])
+AC_CHECK_HEADERS([stdtime/tzfile.h])
+AC_CHECK_FUNCS([dlfunc])
+
+AC_CHECK_HEADERS([sys/time.h])
+AC_CHECK_HEADERS([ctype.h errno.h stdio.h stdlib.h])
+AC_CHECK_HEADERS([string.h sys/param.h unistd.h ])
+AC_CHECK_HEADERS([sys/sysctl.h])
+
+AC_CHECK_LIB([crypto], [MD5_Init])
+AM_CONDITIONAL([HAVE_LIBCRYPTO], [test "$HAVE_LIBCRYPTO" != "no"])
+
+dnl
+dnl Some packages need to be checked against version numbers so we
+dnl define a function here for later use
+dnl
+AC_DEFUN([VERSION_TO_NUMBER],
+[`$1 | sed -e 's/lib.* //' | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 1000 + [$]2) * 1000 + [$]3;}'`])
+
+LIBSLAX_CONFIG_PREFIX=""
+LIBSLAX_SRC=""
+
+AC_ARG_WITH(libslax-prefix,
+ [ --with-libslax-prefix=[PFX] Specify location of libslax config],
+ LIBSLAX_CONFIG_PREFIX=$withval
+)
+
+AC_MSG_CHECKING(for libslax)
+if test "x$LIBSLAX_CONFIG_PREFIX" != "x"
+then
+ SLAX_CONFIG=${LIBSLAX_CONFIG_PREFIX}/bin/slax-config
+else
+ SLAX_CONFIG=slax-config
+fi
+
+dnl
+dnl make sure slax-config is executable,
+dnl test version and init our variables
+dnl
+
+if ${SLAX_CONFIG} --libs > /dev/null 2>&1
+then
+ LIBSLAX_VERSION=`$SLAX_CONFIG --version`
+ SLAX_BINDIR="`$SLAX_CONFIG --bindir | head -1`"
+ SLAX_OXTRADOCDIR="`$SLAX_CONFIG --oxtradoc | head -1`"
+ AC_MSG_RESULT($LIBSLAX_VERSION found)
+else
+ LIBSLAX_VERSION=
+ SLAX_BINDIR=
+ SLAX_OXTRADOCDIR=
+ AC_MSG_RESULT([no])
+fi
+
+AC_SUBST(SLAX_BINDIR)
+AC_SUBST(SLAX_OXTRADOCDIR)
+
+AC_MSG_CHECKING([whether to build with warnings])
+AC_ARG_ENABLE([warnings],
+ [ --enable-warnings Turn on compiler warnings],
+ [LIBXO_WARNINGS=$enableval],
+ [LIBXO_WARNINGS=no])
+AC_MSG_RESULT([$LIBXO_WARNINGS])
+AM_CONDITIONAL([LIBXO_WARNINGS_HIGH], [test "$LIBXO_WARNINGS" != "no"])
+
+AC_MSG_CHECKING([whether to build with debugging])
+AC_ARG_ENABLE([debug],
+ [ --enable-debug Turn on debugging],
+ [LIBXO_DEBUG=yes; AC_DEFINE([LIBXO_DEBUG], [1], [Enable debugging])],
+ [LIBXO_DEBUG=no])
+AC_MSG_RESULT([$LIBXO_DEBUG])
+AM_CONDITIONAL([LIBXO_DEBUG], [test "$LIBXO_DEBUG" != "no"])
+
+AC_CHECK_LIB([m], [lrint])
+AM_CONDITIONAL([HAVE_LIBM], [test "$HAVE_LIBM" != "no"])
+
+AC_MSG_CHECKING([compiler for gcc])
+HAVE_GCC=no
+if test "${CC}" != ""; then
+ HAVE_GCC=`${CC} --version 2>&1 | grep GCC`
+ if test "${HAVE_GCC}" != ""; then
+ HAVE_GCC=yes
+ else
+ HAVE_GCC=no
+ fi
+fi
+AC_MSG_RESULT([$HAVE_GCC])
+AM_CONDITIONAL([HAVE_GCC], [test "$HAVE_GCC" = "yes"])
+
+AC_MSG_CHECKING([whether to build with printflike])
+AC_ARG_ENABLE([printflike],
+ [ --enable-printflike Enable use of GCC __printflike attribute],
+ [HAVE_PRINTFLIKE=yes;
+ AC_DEFINE([HAVE_PRINTFLIKE], [1], [Support printflike])],
+ [HAVE_PRINTFLIKE=no])
+AC_MSG_RESULT([$HAVE_PRINTFLIKE])
+AM_CONDITIONAL([HAVE_PRINTFLIKE], [test "$HAVE_PRINTFLIKE" != ""])
+
+AC_MSG_CHECKING([whether to build with LIBXO_OPTIONS])
+AC_ARG_ENABLE([libxo-options],
+ [ --disable-libxo-options Turn off support for LIBXO_OPTIONS],
+ [LIBXO_OPTS=$enableval],
+ [LIBXO_OPTS=yes])
+AC_MSG_RESULT([$LIBXO_OPTS])
+AM_CONDITIONAL([NO_LIBXO_OPTIONS], [test "$LIBXO_OPTS" != "yes"])
+
+
+case $host_os in
+ darwin*)
+ LIBTOOL=glibtool
+ ;;
+ Linux*|linux*)
+ CFLAGS="-D_GNU_SOURCE $CFLAGS"
+ LDFLAGS=-ldl
+ ;;
+ cygwin*|CYGWIN*)
+ LDFLAGS=-no-undefined
+ ;;
+esac
+
+case $prefix in
+ NONE)
+ prefix=/usr/local
+ ;;
+esac
+
+XO_LIBS=-lxo
+XO_SRCDIR=${srcdir}
+XO_LIBDIR=${libdir}
+XO_BINDIR=${bindir}
+XO_INCLUDEDIR=${includedir}
+
+AC_SUBST(XO_SRCDIR)
+AC_SUBST(XO_LIBDIR)
+AC_SUBST(XO_BINDIR)
+AC_SUBST(XO_INCLUDEDIR)
+
+AC_ARG_WITH(share-dir,
+ [ --with-share-dir=[DIR] Specify location of shared files],
+ [XO_SHAREDIR=$withval],
+ [XO_SHAREDIR=$datarootdir/libxo]
+)
+XO_SHAREDIR=`echo $XO_SHAREDIR | sed "s;\\${prefix};$prefix;"`
+AC_SUBST(XO_SHAREDIR)
+
+dnl for the spec file
+RELDATE=`date +'%Y-%m-%d%n'`
+AC_SUBST(RELDATE)
+
+AC_MSG_RESULT(Using configure dir $ac_abs_confdir)
+
+if test -d $ac_abs_confdir/.git ; then
+ extra=`git branch | awk '/\*/ { print $2 }'`
+ if test "$extra" != "" -a "$extra" != "master"
+ then
+ LIBXO_VERSION_EXTRA="-git-$extra"
+ fi
+fi
+
+LIBXO_VERSION=$PACKAGE_VERSION
+LIBXO_VERSION_NUMBER=VERSION_TO_NUMBER(echo $PACKAGE_VERSION)
+AC_SUBST(LIBXO_VERSION)
+AC_SUBST(LIBXO_VERSION_NUMBER)
+AC_SUBST(LIBXO_VERSION_EXTRA)
+
+AC_CONFIG_HEADERS([libxo/xoconfig.h])
+AC_CONFIG_FILES([
+ Makefile
+ libxo-config
+ xohtml/xohtml.sh
+ libxo/Makefile
+ libxo/xoversion.h
+ xo/Makefile
+ xolint/Makefile
+ packaging/libxo.pc
+ doc/Makefile
+ tests/Makefile
+ tests/core/Makefile
+ tests/xo/Makefile
+ packaging/libxo.spec
+])
+AC_OUTPUT
+
+AC_MSG_NOTICE([summary of build options:
+
+ libxo version: ${VERSION} ${LIBXO_VERSION_EXTRA}
+ host type: ${host} / ${host_os}
+ install prefix: ${prefix}
+ srcdir: ${XO_SRCDIR}
+ libdir: ${XO_LIBDIR}
+ bindir: ${XO_BINDIR}
+ includedir: ${XO_INCLUDEDIR}
+ share dir: ${XO_SHAREDIR}
+
+ compiler: ${CC} (${HAVE_GCC:-no})
+ compiler flags: ${CFLAGS}
+ library types: Shared=${enable_shared}, Static=${enable_static}
+
+ warnings: ${LIBXO_WARNINGS:-no}
+ debug: ${LIBXO_DEBUG:-no}
+ printf-like: ${HAVE_PRINTFLIKE:-no}
+ libxo-options: ${LIBXO_OPTS:-no}
+])
diff --git a/contrib/libxo/doc/Makefile.am b/contrib/libxo/doc/Makefile.am
new file mode 100644
index 0000000..c0c3271
--- /dev/null
+++ b/contrib/libxo/doc/Makefile.am
@@ -0,0 +1,65 @@
+#
+# $Id$
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+OXTRADOC_DIR = ${SLAX_OXTRADOCDIR}
+OXTRADOC_PREFIX = ${OXTRADOC_DIR}
+OXTRADOC = ${OXTRADOC_DIR}/oxtradoc
+SLAXPROC_BINDIR = ${SLAX_BINDIR}
+
+XML2RFC = ${OXTRADOC_DIR}/xml2rfc.tcl
+XML2HTMLDIR = ${OXTRADOC_DIR}
+XML2HTMLBIN = ${XML2HTMLDIR}/rfc2629-to-html.slax
+SLAXPROC = ${SLAX_BINDIR}/slaxproc
+
+SLAXPROC_ARGS = \
+ -a oxtradoc-dir ${OXTRADOC_DIR} \
+ -a oxtradoc-install-dir ${OXTRADOC_DIR} \
+ -a anchor-prefix docs
+
+SLAXPROC_ARGS_INLINE = \
+ -a oxtradoc-inline yes
+
+SLAXPROC_ARGS += ${SLAXPROC_ARGS_INLINE}
+
+XML2HTML = \
+ ${SLAXPROC} -g -e -I ${OXTRADOC_DIR} -I . \
+ ${SLAXPROC_ARGS} \
+ ${XML2HTMLBIN}
+
+OX_ARGS = -P ${OXTRADOC_PREFIX} -L ${OXTRADOC_PREFIX}
+OX_ARGS += -S ${SLAXPROC} -p doc
+OX_CMD = ${PERL} ${PERLOPTS} ${OXTRADOC} ${OX_ARGS}
+OXTRADOC_CMD = ${OX_CMD}
+
+
+OUTPUT = libxo-manual
+INPUT = libxo.txt
+
+EXTRA_DIST = \
+ ${INPUT} \
+ ${OUTPUT}.html \
+ ${OUTPUT}.txt
+
+doc docs: ${OUTPUT}.txt ${OUTPUT}.html
+
+${OUTPUT}.txt: ${INPUT} ${OXTRADOC} xolint.txt
+ ${OXTRADOC_CMD} -m text -o $@ $<
+
+${OUTPUT}.html: ${INPUT} ${OXTRADOC} ${XML2HTMLBIN} xolint.txt
+ ${OXTRADOC_CMD} -m html -o $@ $<
+
+xolint.txt: ${top_srcdir}/xolint/xolint.pl
+ perl ${top_srcdir}/xolint/xolint.pl -D > xolint.txt
+
+CLEANFILES = \
+${OUTPUT}.xml \
+${OUTPUT}.txt \
+${OUTPUT}.fxml \
+${OUTPUT}.html
diff --git a/contrib/libxo/doc/libxo.txt b/contrib/libxo/doc/libxo.txt
new file mode 100644
index 0000000..5148de0
--- /dev/null
+++ b/contrib/libxo/doc/libxo.txt
@@ -0,0 +1,2400 @@
+#
+# Copyright (c) 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+# Phil Shafer, July 2014
+#
+
+* libxo
+
+libxo - A Library for Generating Text, XML, JSON, and HTML Output
+
+You live in the present, but you want to live in the future. You'd
+love a flying car, but need to get to work today. You want to support
+features like XML, JSON, and HTML rendering to allow integration with
+NETCONF, REST, and web browsers, but you need to make text output for
+command line users. And you don't want multiple code paths that can't
+help but get out of sync. None of this "if (xml) {... } else {...}"
+logic. And ifdefs are right out. But you'd really, really like all
+the fancy features that modern encoding formats can provide.
+
+The libxo library allows an application to generate text, XML, JSON,
+and HTML output using a common set of function calls. The application
+decides at run time which output style should be produced. The
+application calls a function "xo_emit" to product output that is
+described in a format string. A "field descriptor" tells libxo what
+the field is and what it means. Each field descriptor is placed in
+braces with a printf-like format string:
+
+ xo_emit(" {:lines/%7ju} {:words/%7ju} "
+ "{:characters/%7ju}{d:filename/%s}\n",
+ linect, wordct, charct, file);
+
+Each field can have a role, with the 'value' role being the default,
+and the role tells libxo how and when to render that field. Output
+can then be generated in various style, using the "--libxo" option:
+
+ % wc /etc/motd
+ 25 165 1140 /etc/motd
+ % wc --libxo xml,pretty,warn /etc/motd
+ <wc>
+ <file>
+ <filename>/etc/motd</filename>
+ <lines>25</lines>
+ <words>165</words>
+ <characters>1140</characters>
+ </file>
+ </wc>
+ % wc --libxo json,pretty,warn /etc/motd
+ {
+ "wc": {
+ "file": [
+ {
+ "filename": "/etc/motd",
+ "lines": 25,
+ "words": 165,
+ "characters": 1140
+ }
+ ]
+ }
+ }
+ % wc --libxo html,pretty,warn /etc/motd
+ <div class="line">
+ <div class="text"> </div>
+ <div class="data" data-tag="lines"> 25</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="words"> 165</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="characters"> 1140</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="filename">/etc/motd</div>
+ </div>
+
+** Getting libxo
+
+libxo lives on github as:
+
+ https://github.com/Juniper/libxo
+
+The latest release of libxo is available at:
+
+ https://github.com/Juniper/libxo/releases
+
+We are following the branching scheme from
+^http://nvie.com/posts/a-successful-git-branching-model/^
+which means we will do development under the "develop" branch, and
+release from the master. To clone a developer tree, run the following
+command:
+
+ git clone https://github.com/Juniper/libxo.git -b develop
+
+We're using semantic release numbering.
+
+* Overview
+
+Most unix commands emit text output aimed at humans. It is designed
+to be parsed and understood by a user. Humans are gifted at extracted
+details and pattern matching. Often programmers need to extract
+information from this human-oriented output. Programmers use tools
+like grep, awk, and regular expressions to ferret out the pieces of
+information they need. Such solutions are fragile and require
+updates when output contents change or evolve, requiring testing and
+validation.
+
+Modern tool developers favors encoding schemes like XML and JSON,
+which allow trivial parsing and extraction of data. Such formats are
+simple, well understood, hierarchical, easily parsed, and often
+integrate easier with common tools and environments.
+
+In addition, modern reality means that more output ends up in web
+browsers than in terminals, making HTML output valuable.
+
+libxo allows a single set of function calls in source code to generate
+traditional text output, as well as XML and JSON formatted data. HTML
+can also be generated; "<div>" elements surround the traditional text
+output, with attributes that detail how to render the data.
+
+A single libxo function call in source code is all that's required:
+
+ xo_emit("Connecting to {:host}.{:domain}...\n", host, domain);
+
+ Text:
+ Connection to my-box.example.com...
+ XML:
+ <host>my-box</host>
+ <domain>example.com</domain>
+ JSON:
+ "host": my-box",
+ "domain": "example.com"
+
+For brevity, the HTML output is emitted.
+
+** Encoding Styles
+
+There are four encoding styles supported by libxo: TEXT, HTML, JSON,
+and XML. JSON and XML are suitable for encoding data, while TEXT and
+HTML are suited for display to the user. TEXT output can be display
+on a terminal session, allowing compatibility with traditional usage.
+HTML can be matched with a small CSS file to permit rendering in any
+HTML5 browser. XML output is suitable for tools like XPath and
+protocols like NETCONF. JSON output can be used for RESTful APIs.
+
+*** Text Output
+
+Most traditional programs generate text output on standard output,
+with contents like:
+
+ 36 ./src
+ 40 ./bin
+ 90 .
+
+In this example (taken from du source code), the code to generate this
+data might look like:
+
+ printf("%d\t%s\n", num_blocks, path);
+
+Simple, direct, obvious. But it's only making text output. Imagine
+using a single code path to make text, XML, JSON or HTML, deciding at
+run time which to generate.
+
+libxo expands on the idea of printf format strings to make a single
+format containing instructions for creating multiple output styles:
+
+ xo_emit("{:blocks/%d}\t{:path/%s}\n", num_blocks, path);
+
+This line will generate the same text output as the earlier printf
+call, but also has enough information to generate XML, JSON, and HTML.
+
+The following sections introduce the other formats.
+
+*** XML Output
+
+XML output consists of a hierarchical set of elements, each encoded
+with a start tag and an end tag. The element should be named for data
+value that it is encoding:
+
+ <item>
+ <blocks>36</blocks>
+ <path>./src</path>
+ </item>
+ <item>
+ <blocks>40</blocks>
+ <path>./bin</path>
+ </item>
+ <item>
+ <blocks>90</blocks>
+ <path>.</path>
+ </item>
+
+XML is a W3C standard for encoding data. See w3c.org/TR/xml for
+additional information.
+
+*** JSON Output
+
+JSON output consists of a hierarchical set of objects and lists, each
+encoded with a quoted name, a colon, and a value. If the value is a
+string, it must be quoted, but numbers are not quoted. Objects are
+encoded using braces; lists are encoded using square brackets.
+Data inside objects and lists is separated using commas:
+
+ items: [
+ { "blocks": 36, "path" : "./src" },
+ { "blocks": 40, "path" : "./bin" },
+ { "blocks": 90, "path" : "./" }
+ ]
+
+*** HTML Output
+
+HTML output is designed to allow the output to be rendered in a web
+browser with minimal effort. Each piece of output data is rendered
+inside a <div> element, with a class name related to the role of the
+data. By using a small set of class attribute values, a CSS
+stylesheet can render the HTML into rich text that mirrors the
+traditional text content.
+
+Additional attributes can be enabled to provide more details about the
+data, including data type, description, and an XPath location.
+
+ <div class="line">
+ <div class="data" data-tag="blocks">36</div>
+ <div class="padding"> </div>
+ <div class="data data-tag="path">./src</div>
+ </div>
+ <div class="line">
+ <div class="data" data-tag="blocks">40</div>
+ <div class="padding"> </div>
+ <div class="data data-tag="path">./bin</div>
+ </div>
+ <div class="line">
+ <div class="data" data-tag="blocks">90</div>
+ <div class="padding"> </div>
+ <div class="data data-tag="path">./</div>
+ </div>
+
+** Format Strings @format-strings@
+
+libxo uses format strings to control the rendering of data into the
+various output styles. Each format string contains a set of zero or
+more field descriptions, which describe independent data fields. Each
+field description contains a set of modifiers, a content string, and
+zero, one, or two format descriptors. The modifiers tell libxo what
+the field is and how to treat it, while the format descriptors are
+formatting instructions using printf-style format strings, telling
+libxo how to format the field. The field description is placed inside
+a set of braces, with a colon (":") after the modifiers and a slash
+("/") before each format descriptors. Text may be intermixed with
+field descriptions within the format string.
+
+The field description is given as follows:
+
+ '{' [ role | modifier ]* ':' [ content ]
+ [ '/' field-format [ '/' encoding-format ]] '}'
+
+The role describes the function of the field, while the modifiers
+enable optional behaviors. The contents, field-format, and
+encoding-format are used in varying ways, based on the role. These
+are described in the following sections.
+
+In the following example, three field descriptors appear. The first
+is a padding field containing three spaces of padding, the second is a
+label ("In stock"), and the third is a value field ("in-stock"). The
+in-stock field has a "%u" format that will parse the next argument
+passed to the xo_emit function as an unsigned integer.
+
+ xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n", 65);
+
+This single line of code can generate text (" In stock: 65\n"), XML
+("<in-stock>65</in-stock>"), JSON ('"in-stock": 6'), or HTML (too
+lengthy to be listed here).
+
+*** Modifier Roles
+
+Modifiers are optional, and indicate the role and formatting of the
+content. The roles are listed below; only one role is permitted:
+
+|---+--------------+-------------------------------------------------|
+| M | Name | Description |
+|---+--------------+-------------------------------------------------|
+| D | decoration | Field is non-text (e.g. colon, comma) |
+| E | error | Field is an error message |
+| L | label | Field is text that prefixes a value |
+| N | note | Field is text that follows a value |
+| P | padding | Field is spaces needed for vertical alignment |
+| T | title | Field is a title value for headings |
+| U | units | Field is the units for the previous value field |
+| V | value | Field is the name of field (the default) |
+| W | warning | Field is a warning message |
+| [ | start anchor | Begin a section of anchored variable-width text |
+| ] | stop anchor | End a section of anchored variable-width text |
+|---+--------------+-------------------------------------------------|
+
+**** The Decoration Role ({D:})
+
+Decorations are typically punctuation marks such as colons,
+semi-colons, and commas used to decorate the text and make it simpler
+for human readers. By marking these distinctly, HTML usage scenarios
+can use CSS to direct their display parameters.
+
+ xo_emit("{D:((}{:name}{D:))}\n", name);
+
+**** The Label Role ({L:})
+
+Labels are text that appears before a value.
+
+ xo_emit("{Lwc:Cost}{:cost/%u}\n", cost);
+
+**** The Note Role ({N:})
+
+Notes are text that appears after a value.
+
+ xo_emit("{:cost/%u} {N:per year}\n", cost);
+
+**** The Padding Role ({P:})
+
+Padding represents whitespace used before and between fields.
+
+The padding content can be either static, when placed directly within
+the field descriptor, or a printf-style format descriptor can be used,
+if preceded by a slash ("/"):
+
+ xo_emit("{P: }{Lwc:Cost}{:cost/%u}\n", cost);
+ xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\n", "", cost);
+
+**** The Title Role ({T:})
+
+Title are heading or column headers that are meant to be displayed to
+the user. The title can be either static, when placed directly within
+the field descriptor, or a printf-style format descriptor can be used,
+if preceded by a slash ("/"):
+
+ xo_emit("{T:Interface Statistics}\n");
+ xo_emit("{T:/%20.20s}{T:/%6.6s}\n", "Item Name", "Cost");
+
+**** The Units Role ({U:})
+
+Units are the dimension by which values are measured, such as degrees,
+miles, bytes, and decibels. The units field carries this information
+for the previous value field.
+
+ xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\n", miles);
+
+Note that the sense of the 'w' modifier is reversed for units;
+a blank is added before the contents, rather than after it.
+
+When the XOF_UNITS flag is set, units are rendered in XML as the
+"units" attribute:
+
+ <distance units="miles">50</distance>
+
+Units can also be rendered in HTML as the "data-units" attribute:
+
+ <div class="data" data-tag="distance" data-units="miles"
+ data-xpath="/top/data/distance">50</div>
+
+**** The Value Role ({V:} and {:})
+
+The value role is used to represent the a data value that is
+interesting for the non-display output styles (XML and JSON). Value
+is the default role; if no other role designation is given, the field
+is a value. The field name must appear within the field descriptor,
+followed by one or two format descriptors. The first format
+descriptor is used for display styles (TEXT and HTML), while the
+second one is used for encoding styles (XML and JSON). If no second
+format is given, the encoding format defaults to the first format,
+with any minimum width removed. If no first format is given, both
+format descriptors default to "%s".
+
+ xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\n",
+ length, width, height);
+ xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\n,
+ author, poem, year);
+
+**** The Anchor Modifiers ({[:} and {]:})
+
+The anchor roles allow a set of strings by be padded as a group,
+but still be visible to xo_emit as distinct fields. Either the start
+or stop anchor can give a field width and it can be either directly in
+the descriptor or passed as an argument. Any fields between the start
+and stop anchor are padded to meet the minimum width given.
+
+To give a width directly, encode it as the content of the anchor tag:
+
+ xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\n", min, max);
+
+To pass a width as an argument, use "%d" as the format, which must
+appear after the "/". Note that only "%d" is supported for widths.
+Using any other value could ruin your day.
+
+ xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\n", width, min, max);
+
+If the width is negative, padding will be added on the right, suitable
+for left justification. Otherwise the padding will be added to the
+left of the fields between the start and stop anchors, suitable for
+right justification. If the width is zero, nothing happens. If the
+number of columns of output between the start and stop anchors is less
+than the absolute value of the given width, nothing happens.
+
+Widths over 8k are considered probable errors and not supported. If
+XOF_WARN is set, a warning will be generated.
+
+*** Modifier Flags
+
+The modifiers can also include the following flags, which modify the
+content emitted for some output styles:
+
+|---+--------------+-------------------------------------------------|
+| M | Name | Description |
+|---+--------------+-------------------------------------------------|
+| c | colon | A colon (":") is appended after the label |
+| d | display | Only emit field for display styles (text/HTML) |
+| e | encoding | Only emit for encoding styles (XML/JSON) |
+| k | key | Field is a key, suitable for XPath predicates |
+| n | no-quotes | Do not quote the field when using JSON style |
+| q | quotes | Quote the field when using JSON style |
+| w | white space | A blank (" ") is appended after the label |
+|---+--------------+-------------------------------------------------|
+
+For example, the modifier string "Lwc" means the field has a label
+role (text that describes the next field) and should be followed by a
+colon ('c') and a space ('w'). The modifier string "Vkq" means the
+field has a value role, that it is a key for the current instance, and
+that the value should be quoted when encoded for JSON.
+
+**** The Colon Modifier ({c:})
+
+The colon modifier appends a single colon to the data value:
+
+ EXAMPLE:
+ xo_emit("{Lc:Name}{:name}\n", "phil");
+ TEXT:
+ Name:phil
+
+The colon modifier is only used for the TEXT and HTML output
+styles. It is commonly combined with the space modifier ('{w:').
+It is purely a convenience feature.
+
+**** The Display Modifier ({d:})
+
+The display modifier indicated the field should only be generated for
+the display output styles, TEXT and HTML.
+
+ EXAMPLE:
+ xo_emit("{Lcw:Name}{d:name} {:id/%d}\n", "phil", 1);
+ TEXT:
+ Name: phil 1
+ XML:
+ <id>1</id>
+
+The display modifier is the opposite of the encoding modifier, and
+they are often used to give to distinct views of the underlying data.
+
+**** The Encoding Modifier ({e:}) @e-modifier@
+
+The display modifier indicated the field should only be generated for
+the display output styles, TEXT and HTML.
+
+ EXAMPLE:
+ xo_emit("{Lcw:Name}{:name} {e:id/%d}\n", "phil", 1);
+ TEXT:
+ Name: phil
+ XML:
+ <name>phil</name><id>1</id>
+
+The encoding modifier is the opposite of the display modifier, and
+they are often used to give to distinct views of the underlying data.
+
+**** The Key Modifier ({k:})
+
+The key modifier is used to indicate that a particular field helps
+uniquely identify an instance of list data.
+
+ EXAMPLE:
+ xo_open_list("user");
+ for (i = 0; i < num_users; i++) {
+ xo_open_instance("user");
+ xo_emit("User {k:name} has {:count} tickets\n",
+ user[i].u_name, user[i].u_tickets);
+ xo_close_instance("user");
+ }
+ xo_close_list("user");
+
+Currently the key modifier is only used when generating XPath value
+for the HTML output style when XOF_XPATH is set, but other uses are
+likely in the near future.
+
+**** The No-Quotes Modifier ({n:})
+
+The no-quotes modifier (and its twin, the 'quotes' modifier) affect
+the quoting of values in the JSON output style. JSON uses quotes for
+string value, but no quotes for numeric, boolean, and null data.
+xo_emit applies a simple heuristic to determine whether quotes are
+needed, but often this needs to be controlled by the caller.
+
+ EXAMPLE:
+ const char *bool = is_true ? "true" : "false";
+ xo_emit("{n:fancy/%s}", bool);
+ JSON:
+ "fancy": true
+
+**** The Quotes Modifier ({q:})
+
+The quotes modifier (and its twin, the 'no-quotes' modifier) affect
+the quoting of values in the JSON output style. JSON uses quotes for
+string value, but no quotes for numeric, boolean, and null data.
+xo_emit applies a simple heuristic to determine whether quotes are
+needed, but often this needs to be controlled by the caller.
+
+ EXAMPLE:
+ xo_emit("{q:time/%d}", 2014);
+ JSON:
+ "year": "2014"
+
+**** The White Space Modifier ({w:})
+
+The white space modifier appends a single space to the data value:
+
+ EXAMPLE:
+ xo_emit("{Lw:Name}{:name}\n", "phil");
+ TEXT:
+ Name phil
+
+The white space modifier is only used for the TEXT and HTML output
+styles. It is commonly combined with the colon modifier ('{c:').
+It is purely a convenience feature.
+
+Note that the sense of the 'w' modifier is reversed for the units role
+({Uw:}); a blank is added before the contents, rather than after it.
+
+*** Field Formatting
+
+The field format is similar to the format string for printf(3). It's
+used varies based on the role of the field, but generally is used to
+format the field's contents.
+
+If not provided, the format string defaults to "%s".
+
+Note a field definition can contain zero or more printf-style
+'directives', which are sequences that start with a '%' and end with a
+one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive
+is matched by one of more arguments to the xo_emit function.
+
+The format string has the form:
+
+ '%' format-modifier * format-character
+
+The format- modifier can be:
+- a '#' character, indicating the output value should be prefixed with
+'0x', typically to indicate a base 16 (hex) value.
+- a minus sign ('-'), indicating the output value should be padded on
+the right instead of the left.
+- a leading zero ('0') indicating the output value should be padded on the
+left with zeroes instead of spaces (' ').
+- one or more digits ('0' - '9') indicating the minimum width of the
+argument. If the width in columns of the output value is less that
+the minumum width, the value will be padded to reach the minimum.
+- a period followed by one or more digits indicating the maximum
+number of bytes which will be examined for a string argument, or the maximum
+width for a non-string argument. When handling ASCII strings this is
+functions as the field width but for multi-byte characters, a single
+character may be composed of multiple bytes.
+xo_emit will never dereference memory beyond the given number of bytes.
+- a second period followed by one or more digits indicating the maximum
+width for a string argument. This modifier cannot be given for non-string
+arguments.
+- one or more 'h' characters, indicating shorter input data.
+- one or more 'l' characters, indicating longer input data.
+- a 'z' character, indicating a 'size_t' argument.
+- a 't' character, indicating a 'ptrdiff_t' argument.
+- a ' ' character, indicating a space should be emitted before
+positive numbers.
+- a '+' character, indicating sign should emitted before any number.
+
+Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be
+removed eventually.
+
+The format character is described in the following table:
+
+|-----+-----------------+----------------------|
+| Ltr | Argument Type | Format |
+|-----+-----------------+----------------------|
+| d | int | base 10 (decimal) |
+| i | int | base 10 (decimal) |
+| o | int | base 8 (octal) |
+| u | unsigned | base 10 (decimal) |
+| x | unsigned | base 16 (hex) |
+| X | unsigned long | base 16 (hex) |
+| D | long | base 10 (decimal) |
+| O | unsigned long | base 8 (octal) |
+| U | unsigned long | base 10 (decimal) |
+| e | double | [-]d.ddde+-dd |
+| E | double | [-]d.dddE+-dd |
+| f | double | [-]ddd.ddd |
+| F | double | [-]ddd.ddd |
+| g | double | as 'e' or 'f' |
+| G | double | as 'E' or 'F' |
+| a | double | [-]0xh.hhhp[+-]d |
+| A | double | [-]0Xh.hhhp[+-]d |
+| c | unsigned char | a character |
+| C | wint_t | a character |
+| s | char * | a UTF-8 string |
+| S | wchar_t * | a unicode/WCS string |
+| p | void * | '%#lx' |
+|-----+-----------------+----------------------|
+
+The 'h' and 'l' modifiers affect the size and treatment of the
+argument:
+
+|-----+-------------+--------------------|
+| Mod | d, i | o, u, x, X |
+|-----+-------------+--------------------|
+| hh | signed char | unsigned char |
+| h | short | unsigned short |
+| l | long | unsigned long |
+| ll | long long | unsigned long long |
+| j | intmax_t | uintmax_t |
+| t | ptrdiff_t | ptrdiff_t |
+| z | size_t | size_t |
+| q | quad_t | u_quad_t |
+|-----+-------------+--------------------|
+
+*** UTF-8 and Locale Strings
+
+For strings, the 'h' and 'l' modifiers affect the interpretation of
+the bytes pointed to argument. The default '%s' string is a 'char *'
+pointer to a string encoded as UTF-8. Since UTF-8 is compatible with
+ASCII data, a normal 7-bit ASCII string can be used. '%ls' expects a
+'wchar_t *' pointer to a wide-character string, encoded as a 32-bit
+Unicode values. '%hs' expects a 'char *' pointer to a multi-byte
+string encoded with the current locale, as given by the LC_CTYPE,
+LANG, or LC_ALL environment varibles. The first of this list of
+variables is used and if none of the variables, the locale defaults to
+"UTF-8".
+
+For example, a function is passed a locale-base name, a hat size,
+and a time value. The hat size is formatted in a UTF-8 (ASCII)
+string, and the time value is formatted into a wchar_t string.
+
+ void print_order (const char *name, int size,
+ struct tm *timep) {
+ char buf[32];
+ const char *size_val = "unknown";
+
+ if (size > 0)
+ snprintf(buf, sizeof(buf), "%d", size);
+ size_val = buf;
+ }
+
+ wchar_t when[32];
+ wcsftime(when, sizeof(when), L"%d%b%y", timep);
+
+ xo_emit("The hat for {:name/%hs} is {:size/%s}.\n",
+ name, size_val);
+ xo_emit("It was ordered on {:order-time/%ls}.\n",
+ when);
+ }
+
+It is important to note that xo_emit will perform the conversion
+required to make appropriate output. Text style output uses the
+current locale (as described above), while XML, JSON, and HTML use
+UTF-8.
+
+UTF-8 and locale-encoded strings can use multiple bytes to encode one
+column of data. The traditional "precision'" (aka "max-width") value
+for "%s" printf formatting becomes overloaded since it specifies both
+the number of bytes that can be safely referenced and the maximum
+number of columns to emit. xo_emit uses the precision as the former,
+and adds a third value for specifying the maximum number of columns.
+
+In this example, the name field is printed with a minimum of 3 columns
+and a maximum of 6. Up to ten bytes are in used in filling those
+columns.
+
+ xo_emit("{:name/%3.10.6s}", name);
+
+*** Characters Outside of Field Definitions
+
+Characters in the format string are not part of a field definition are
+copied to the output for the TEXT style, and are ignored for the JSON
+and XML styles. For HTML, these characters are placed in a <div> with
+class "text".
+
+ EXAMPLE:
+ xo_emit("The hat is {:size/%s}.\n", size_val);
+ TEXT:
+ The hat is extra small.
+ XML:
+ <size>extra small</size>
+ JSON:
+ "size": "extra small"
+ HTML:
+ <div class="text">The hat is </div>
+ <div class="data" data-tag="size">extra small</div>
+ <div class="text">.</div>
+
+*** "%n" is Not Supported
+
+libxo does not support the '%n' directive. It's a bad idea and we
+just don't do it.
+
+*** The Encoding Format (eformat)
+
+The "eformat" string is the format string used when encoding the field
+for JSON and XML. If not provided, it defaults to the primary format
+with any minimum width removed. If the primary is not given, both
+default to "%s".
+
+*** Content Strings
+
+For padding and labels, the content string is considered the content,
+unless a format is given.
+
+*** Example
+
+In this example, the value for the number of items in stock is emitted:
+
+ xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n",
+ instock);
+
+This call will generate the following output:
+
+ TEXT:
+ In stock: 144
+ XML:
+ <in-stock>144</in-stock>
+ JSON:
+ "in-stock": 144,
+ HTML:
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">144</div>
+ </div>
+
+Clearly HTML wins the verbosity award, and this output does
+not include XOF_XPATH or XOF_INFO data, which would expand the
+penultimate line to:
+
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock"
+ data-type="number"
+ data-help="Number of items in stock">144</div>
+
+** Command-line Arguments
+
+libxo uses command line options to trigger rendering behavior. The
+following options are recognised:
+
+- --libxo <options>
+- --libxo=<options>
+- --libxo:<brief-options>
+
+Options is a comma-separated list of tokens that correspond to output
+styles, flags, or features:
+
+|-----------+-------------------------------------------------------|
+| Token | Action |
+|-----------+-------------------------------------------------------|
+| dtrt | Enable "Do The Right Thing" mode |
+| html | Emit HTML output |
+| indent=xx | Set the indentation level |
+| info | Add info attributes (HTML) |
+| json | Emit JSON output |
+| keys | Emit the key attribute for keys (XML) |
+| no-locale | Do not initialize the locale setting |
+| no-top | Do not emit a top set of braces (JSON) |
+| not-first | Pretend the 1st output item was not 1st (JSON) |
+| pretty | Emit pretty-printed output |
+| text | Emit TEXT output |
+| units | Add the 'units' (XML) or 'data-units (HTML) attribute |
+| warn | Emit warnings when libxo detects bad calls |
+| warn-xml | Emit warnings in XML |
+| xml | Emit XML output |
+| xpath | Add XPath expressions (HTML) |
+|-----------+-------------------------------------------------------|
+
+The brief options are detailed in ^LIBXO_OPTIONS^.
+
+** Representing Hierarchy
+
+For XML and JSON, individual fields appear inside hierarchies which
+provide context and meaning to the fields. Unfortunately, these
+encoding have a basic disconnect between how lists is similar objects
+are represented.
+
+XML encodes lists as set of sequential elements:
+
+ <user>phil</user>
+ <user>pallavi</user>
+ <user>sjg</user>
+
+JSON encodes lists using a single name and square brackets:
+
+ "user": [ "phil", "pallavi", "sjg" ]
+
+This means libxo needs three distinct indications of hierarchy: one
+for containers of hierarchy appear only once for any specific parent,
+one for lists, and one for each item in a list.
+
+*** Containers
+
+A "container" is an element of a hierarchy that appears only once
+under any specific parent. The container has no value, but serves to
+contain other nodes.
+
+To open a container, call xo_open_container() or
+xo_open_container_h(). The former uses the default handle and
+the latter accepts a specific handle.
+
+ int xo_open_container_h (xo_handle_t *xop, const char *name);
+ int xo_open_container (const char *name);
+
+To close a level, use the xo_close_container() or
+xo_close_container_h() functions:
+
+ int xo_close_container_h (xo_handle_t *xop, const char *name);
+ int xo_close_container (const char *name);
+
+Each open call must have a matching close call. If the XOF_WARN flag
+is set and the name given does not match the name of the currently open
+container, a warning will be generated.
+
+ Example:
+
+ xo_open_container("top");
+ xo_open_container("system");
+ xo_emit("{:host-name/%s%s%s", hostname,
+ domainname ? "." : "", domainname ?: "");
+ xo_close_container("system");
+ xo_close_container("top");
+
+ Sample Output:
+ Text:
+ my-host.example.org
+ XML:
+ <top>
+ <system>
+ <host-name>my-host.example.org</host-name>
+ </system>
+ </top>
+ JSON:
+ "top" : {
+ "system" : {
+ "host-name": "my-host.example.org"
+ }
+ }
+ HTML:
+ <div class="data"
+ data-tag="host-name">my-host.example.org</div>
+
+*** Lists and Instances
+
+A list is set of one or more instances that appear under the same
+parent. The instances contains details about a specific object. One
+can think of instances as objects or records. A call is needed to
+open and close the list, while a distinct call is needed to open and
+close each instance of the list:
+
+ xo_open_list("item");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+ xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+
+Getting the list and instance calls correct is critical to the proper
+generation of XML and JSON data.
+
+*** DTRT Mode
+
+Some user may find tracking the names of open containers, lists, and
+instances inconvenient. libxo offers "Do The Right Thing" mode, where
+libxo will track the names of open containers, lists, and instances so
+the close function can be called without a name. To enable DTRT mode,
+turn on the XOF_DTRT flag prior to making any other libxo output.
+
+ xo_set_flags(NULL, XOF_DTRT);
+
+Each open and close function has a version with the suffix "_d", which
+will close the open container, list, or instance:
+
+ xo_open_container("top");
+ ...
+ xo_close_container_d();
+
+Note that the XOF_WARN flag will also cause libxo to track open
+containers, lists, and instances. A warning is generated with the
+name given to the close function and the name recorded do not match.
+
+** Handles
+
+libxo uses "handles" to control its rendering functionality. The
+handle contains state and buffered data, as well as callback functions
+to process data.
+
+A default handle is used when a NULL is passed to functions accepting
+a handle. This handle is initialized to write its data to stdout
+using the default style of text (XO_STYLE_TEXT).
+
+For the convenience of callers, the libxo library includes handle-less
+functions that implicitly use the default handle. Any function that
+takes a handle will use the default handle is a value of NULL is
+passed in place of a valid handle.
+
+For example, the following are equivalent:
+
+ xo_emit("test");
+ xo_emit_h(NULL, "test");
+
+Handles are created using xo_create() and destroy using xo_destroy().
+
+** UTF-8
+
+All strings for libxo must be UTF-8. libxo will handle turning them
+into locale-based strings for display to the user.
+
+The only exception is argument formatted using the "%ls" format, which
+require a wide character string (wchar_t *) as input. libxo will
+convert these arguments as needed to either UTF-8 (for XML, JSON, and
+HTML styles) or locale-based strings for display in text style.
+
+ xo_emit("Alll strings are utf-8 content {:tag/%ls}",
+ L"except for wide strings");
+
+"%S" is equivalent to "%ls".
+
+* The libxo API
+
+This section gives details about the functions in libxo, how to call
+them, and the actions they perform.
+
+** Handles
+
+Handles give an abstraction for libxo that encapsulates the state of a
+stream of output. Handles have the data type "xo_handle_t" and are
+opaque to the caller.
+
+The library has a default handle that is automatically initialized.
+By default, this handle will send text style output to standard output.
+The xo_set_style and xo_set_flags functions can be used to change this
+behavior.
+
+Many libxo functions take a handle as their first parameter; most that
+do not use the default handle. Any function taking a handle can
+be passed NULL to access the default handle.
+
+For the typical command that is generating output on standard output,
+there is no need to create an explicit handle, but they are available
+when needed, e.g. for daemons that generate multiple streams of
+output.
+
+*** xo_create
+
+A handle can be allocated using the xo_create() function:
+
+ xo_handle_t *xo_create (unsigned style, unsigned flags);
+
+ Example:
+ xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN);
+ ....
+ xo_emit_h(xop, "testing\n");
+
+See also ^styles^ and ^flags^.
+
+*** xo_create_to_file
+
+By default, libxo writes output to standard output. A convenience
+function is provided for situations when output should be written to
+different file:
+
+ xo_handle_t *xo_create_to_file (FILE *fp, unsigned style,
+ unsigned flags);
+
+Use the XOF_CLOSE_FP flag to trigger a call to fclose() for
+the FILE pointer when the handle is destroyed.
+
+*** xo_set_writer
+
+The xo_set_writer function allows custom 'write' functions
+which can tailor how libxo writes data. An opaque argument is
+recorded and passed back to the write function, allowing the function
+to acquire context information. The 'close' function can
+release this opaque data and any other resources as needed.
+
+ void xo_set_writer (xo_handle_t *xop, void *opaque,
+ xo_write_func_t write_func,
+ xo_close_func_t close_func);
+
+*** xo_set_style
+
+To set the style, use the xo_set_style() function:
+
+ void xo_set_style(xo_handle_t *xop, unsigned style);
+
+To use the default handle, pass a NULL handle:
+
+ xo_set_style(NULL, XO_STYLE_XML);
+
+**** Output Styles (XO_STYLE_*) @styles@
+
+The libxo functions accept a set of output styles:
+
+|---------------+-------------------------|
+| Flag | Description |
+|---------------+-------------------------|
+| XO_STYLE_TEXT | Traditional text output |
+| XO_STYLE_XML | XML encoded data |
+| XO_STYLE_JSON | JSON encoded data |
+| XO_STYLE_HTML | HTML encoded data |
+|---------------+-------------------------|
+
+**** xo_set_style_name
+
+The xo_set_style_name() can be used to set the style based on a name
+encoded as a string:
+
+ int xo_set_style_name (xo_handle_t *xop, const char *style);
+
+The name can be any of the styles: "text", "xml", "json", or "html".
+
+ EXAMPLE:
+ xo_set_style_name(NULL, "html");
+
+*** xo_set_flags
+
+To set the flags, use the xo_set_flags() function:
+
+ void xo_set_flags(xo_handle_t *xop, unsigned flags);
+
+To use the default handle, pass a NULL handle:
+
+ xo_set_style(NULL, XO_STYLE_XML);
+
+**** Flags (XOF_*) @flags@
+
+The set of valid flags include:
+
+|-----------------+---------------------------------------|
+| Flag | Description |
+|-----------------+---------------------------------------|
+| XOF_CLOSE_FP | Close file pointer on xo_destroy() |
+| XOF_DTRT | Enable "do the right thing" mode |
+| XOF_INFO | Display info data attributes (HTML) |
+| XOF_KEYS | Emit the key attribute (XML) |
+| XOF_NO_ENV | Do not use the LIBXO_OPTIONS env var |
+| XOF_PRETTY | Make 'pretty printed' output |
+| XOF_UNDERSCORES | Replaces hyphens with underscores |
+| XOF_UNITS | Display units (XML and HMTL) |
+| XOF_WARN | Generate warnings for broken calls |
+| XOF_WARN_XML | Generate warnings in XML on stdout |
+| XOF_XPATH | Emit XPath expressions (HTML) |
+| XOF_COLUMNS | Force xo_emit to return columns used |
+| XOF_FLUSH | Flush output after each xo_emit call |
+|-----------------+---------------------------------------|
+
+The XOF_CLOSE_FP flag will trigger the call of the close_func
+(provided via xo_set_writer()) when the handle is destroyed.
+
+The XOF_PRETTY flag requests 'pretty printing', which will trigger the
+addition of indentation and newlines to enhance the readability of
+XML, JSON, and HTML output. Text output is not affected.
+
+The XOF_WARN flag requests that warnings will trigger diagnostic
+output (on standard error) when the library notices errors during
+operations, or with arguments to functions. Without warning enabled,
+such conditions are ignored.
+
+Warnings allow developers to debug their interaction with libxo.
+The function "xo_failure" can used as a breakpoint for a debugger,
+regardless of whether warnings are enabled.
+
+If the style is XO_STYLE_HTML, the following additional flags can be
+used:
+
+|---------------+-----------------------------------------|
+| Flag | Description |
+|---------------+-----------------------------------------|
+| XOF_XPATH | Emit "data-xpath" attributes |
+| XOF_INFO | Emit additional info fields |
+|---------------+-----------------------------------------|
+
+The XOF_XPATH flag enables the emission of XPath expressions detailing
+the hierarchy of XML elements used to encode the data field, if the
+XPATH style of output were requested.
+
+The XOF_INFO flag encodes additional informational fields for HTML
+output. See ^info^ for details.
+
+If the style is XO_STYLE_XML, the following additional flags can be
+used:
+
+|---------------+-----------------------------------------|
+| Flag | Description |
+|---------------+-----------------------------------------|
+| XOF_KEYS | Flag 'key' fields for xml |
+|---------------+-----------------------------------------|
+
+The XOF_KEYS flag adds 'key' attribute to the XML encoding for
+field definitions that use the 'k' modifier. The key attribute has
+the value "key":
+
+ xo_emit("{k:name}", item);
+
+ XML:
+ <name key="key">truck</name>
+
+**** xo_clear_flags
+
+The xo_clear_flags() function turns off the given flags in a specific
+handle.
+
+ void xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags);
+
+**** xo_set_options
+
+The xo_set_options() function accepts a comma-separated list of styles
+and flags and enables them for a specific handle.
+
+ int xo_set_options (xo_handle_t *xop, const char *input);
+
+The options are identical to those listed in ^command-line-arguments^.
+
+*** xo_destroy
+
+The xo_destroy function releases a handle and any resources it is
+using. Calling xo_destroy with a NULL handle will release any
+resources associated with the default handle.
+
+ void xo_destroy(xo_handle_t *xop);
+
+** Emitting Content (xo_emit)
+
+The following functions are used to emit output:
+
+ int xo_emit (const char *fmt, ...);
+ int xo_emit_h (xo_handle_t *xop, const char *fmt, ...);
+ int xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap);
+
+The "fmt" argument is a string containing field descriptors as
+specified in ^format-strings^. The use of a handle is optional and
+NULL can be passed to access the internal 'default' handle. See
+^handles^.
+
+The remaining arguments to xo_emit() and xo_emit_h() are a set of
+arguments corresponding to the fields in the format string. Care must
+be taken to ensure the argument types match the fields in the format
+string, since an inappropriate cast can ruin your day. The vap
+argument to xo_emit_hv() points to a variable argument list that can
+be used to retrieve arguments via va_arg().
+
+*** Attributes (xo_attr) @xo_attr@
+
+The xo_attr() function emits attributes for the XML output style.
+
+
+ int xo_attr (const char *name, const char *fmt, ...);
+ int xo_attr_h (xo_handle_t *xop, const char *name,
+ const char *fmt, ...);
+ int xo_attr_hv (xo_handle_t *xop, const char *name,
+ const char *fmt, va_list vap);
+
+The name parameter give the name of the attribute to be encoded. The
+fmt parameter gives a printf-style format string used to format the
+value of the attribute using any remaining arguments, or the vap
+parameter passed to xo_attr_hv().
+
+ EXAMPLE:
+ xo_attr("seconds", "%ld", (unsigned long) login_time);
+ struct tm *tmp = localtime(login_time);
+ strftime(buf, sizeof(buf), "%R", tmp);
+ xo_emit("Logged in at {:login-time}\n", buf);
+ XML:
+ <login-time seconds="1408336270">00:14</login-time>
+
+*** Flushing Output (xo_flush)
+
+libxo buffers data, both for performance and consistency, but also to
+allow some advanced features to work properly. At various times, the
+caller may wish to flush any data buffered within the library. The
+xo_flush() call is used for this:
+
+ void xo_flush (void);
+ void xo_flush_h (xo_handle_t *xop);
+
+*** Finishing Output (xo_finish)
+
+When the program is ready to exit or close a handle, a call to
+xo_finish() is required. This flushes any buffered data, closes
+open libxo constructs, and completes any pending operations.
+
+ void xo_finish (void);
+ void xo_finish_h (xo_handle_t *xop);
+
+Calling this function is vital to the proper operation of libxo,
+especially for the non-TEXT output styles.
+
+** Emitting Hierarchy
+
+libxo represents to types of hierarchy: containers and lists. A
+container appears once under a given parent where a list contains
+instances that can appear multiple times. A container is used to hold
+related fields and to give the data organization and scope.
+
+To create a container, use the xo_open_container and
+xo_close_container functions:
+
+ int xo_open_container (const char *name);
+ int xo_open_container_h (xo_handle_t *xop, const char *name);
+ int xo_open_container_hd (xo_handle_t *xop, const char *name);
+ int xo_open_container_d (const char *name);
+
+ int xo_close_container (const char *name);
+ int xo_close_container_h (xo_handle_t *xop, const char *name);
+ int xo_close_container_hd (xo_handle_t *xop);
+ int xo_close_container_d (void);
+
+The name parameter gives the name of the container, encoded in UTF-8.
+Since ASCII is a proper subset of UTF-8, traditional C strings can be
+used directly.
+
+The close functions with the "_d" suffix are used in "Do The Right
+Thing" mode, where the name of the open containers, lists, and
+instances are maintained internally by libxo to allow the caller to
+avoid keeping track of the open container name.
+
+Use the XOF_WARN flag to generate a warning if the name given on the
+close does not match the current open container.
+
+For TEXT and HTML output, containers are not rendered into output
+text, though for HTML they are used when the XOF_XPATH flag is set.
+
+ EXAMPLE:
+ xo_open_container("system");
+ xo_emit("The host name is {:host-name}\n", hn);
+ xo_close_container("system");
+ XML:
+ <system><host-name>foo</host-name></system>
+
+*** Lists and Instances
+
+Lists are sequences of instances of homogeneous data objects. Two
+distinct levels of calls are needed to represent them in our output
+styles. Calls must be made to open and close a list, and for each
+instance of data in that list, calls must be make to open and close
+that instance.
+
+The name given to all calls must be identical, and it is strong
+suggested that the name be singular, not plural, as a matter of
+style and usage expectations.
+
+ EXAMPLE:
+ xo_open_list("user");
+ for (i = 0; i < num_users; i++) {
+ xo_open_instance("user");
+ xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n",
+ pw[i].pw_name, pw[i].pw_uid,
+ pw[i].pw_gid, pw[i].pw_dir);
+ xo_close_instance("user");
+ }
+ xo_close_list("user");
+ TEXT:
+ phil:1001:1001:/home/phil
+ pallavi:1002:1002:/home/pallavi
+ XML:
+ <user>
+ <name>phil</name>
+ <uid>1001</uid>
+ <gid>1001</gid>
+ <home>/home/phil</home>
+ </user>
+ <user>
+ <name>pallavi</name>
+ <uid>1002</uid>
+ <gid>1002</gid>
+ <home>/home/pallavi</home>
+ </user>
+ JSON:
+ user: [
+ {
+ "name": "phil",
+ "uid": 1001,
+ "gid": 1001,
+ "home": "/home/phil",
+ },
+ {
+ "name": "pallavi",
+ "uid": 1002,
+ "gid": 1002,
+ "home": "/home/pallavi",
+ }
+ ]
+
+** Additional Functionality
+
+*** Parsing Command-line Arguments (xo_parse_args)
+
+The xo_parse_args() function is used to process a program's
+arguments. libxo-specific options are processed and removed
+from the argument list so the calling application does not
+need to process them. If successful, a new value for argc
+is returned. On failure, a message it emitted and -1 is returned.
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(1);
+
+Following the call to xo_parse_args, the application can process the
+remaining arguments in a normal manner. See ^command-line-arguments^
+for a description of valid arguments.
+
+*** Field Information (xo_info_t) @info@
+
+HTML data can include additional information in attributes that
+begin with "data-". To enable this, three things must occur:
+
+First the application must build an array of xo_info_t structures,
+one per tag. The array must be sorted by name, since libxo uses a
+binary search to find the entry that matches names from format
+instructions.
+
+Second, the application must inform libxo about this information using
+the xo_set_info() call:
+
+ typedef struct xo_info_s {
+ const char *xi_name; /* Name of the element */
+ const char *xi_type; /* Type of field */
+ const char *xi_help; /* Description of field */
+ } xo_info_t;
+
+ void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
+
+Like other libxo calls, passing NULL for the handle tells libxo to use
+the default handle.
+
+If the count is -1, libxo will count the elements of infop, but there
+must be an empty element at the end. More typically, the number is
+known to the application:
+
+ xo_info_t info[] = {
+ { "in-stock", "number", "Number of items in stock" },
+ { "name", "string", "Name of the item" },
+ { "on-order", "number", "Number of items on order" },
+ { "sku", "string", "Stock Keeping Unit" },
+ { "sold", "number", "Number of items sold" },
+ };
+ int info_count = (sizeof(info) / sizeof(info[0]));
+ ...
+ xo_set_info(NULL, info, info_count);
+
+Third, the emitting of info must be triggered with the XOF_INFO flag
+using either the xo_set_flags() function or the "--libxo=info" command
+line argument.
+
+The type and help values, if present, are emitted as the "data-type"
+and "data-help" attributes:
+
+ <div class="data" data-tag="sku" data-type="string"
+ data-help="Stock Keeping Unit">GRO-000-533</div>
+
+*** Memory Allocation
+
+The xo_set_allocator function allows libxo to be used in environments
+where the standard realloc() and free() functions are not available.
+
+ void xo_set_allocator (xo_realloc_func_t realloc_func,
+ xo_free_func_t free_func);
+
+realloc_func should expect the same arguments as realloc(3) and return
+a pointer to memory following the same convention. free_func will
+receive the same argument as free(3) and should release it, as
+appropriate for the environment.
+
+By default, the standard realloc() and free() functions are used.
+
+*** LIBXO_OPTIONS @LIBXO_OPTIONS@
+
+The environment variable "LIBXO_OPTIONS" can be set to a string of
+options:
+
+|--------+-------------------------------------------|
+| Option | Action |
+|--------+-------------------------------------------|
+| H | Enable HTML output (XO_STYLE_HTML) |
+| I | Enable info output (XOF_INFO) |
+| i<num> | Indent by <number> |
+| J | Enable JSON output (XO_STYLE_JSON) |
+| P | Enable pretty-printed output (XOF_PRETTY) |
+| T | Enable text output (XO_STYLE_TEXT) |
+| W | Enable warnings (XOF_WARN) |
+| X | Enable XML output (XO_STYLE_XML) |
+| x | Enable XPath data (XOF_XPATH) |
+|--------+-------------------------------------------|
+
+For example, warnings can be enabled by:
+
+ % env LIBXO_OPTIONS=W my-app
+
+Complete HTML output can be generated with:
+
+ % env LIBXO_OPTIONS=HXI my-app
+
+*** Errors, Warnings, and Messages
+
+Many programs make use of the standard library functions err() and
+warn() to generate errors and warnings for the user. libxo wants to
+pass that information via the current output style, and provides
+compatible functions to allow this:
+
+ void xo_warn (const char *fmt, ...);
+ void xo_warnx (const char *fmt, ...);
+ void xo_warn_c (int code, const char *fmt, ...);
+ void xo_warn_hc (xo_handle_t *xop, int code,
+ const char *fmt, ...);
+ void xo_err (int eval, const char *fmt, ...);
+ void xo_errc (int eval, int code, const char *fmt, ...);
+ void xo_errx (int eval, const char *fmt, ...);
+ void xo_message (const char *fmt, ...);
+ void xo_message_c (int code, const char *fmt, ...);
+ void xo_message_hc (xo_handle_t *xop, int code,
+ const char *fmt, ...);
+ void xo_message_hcv (xo_handle_t *xop, int code,
+ const char *fmt, va_list vap);
+
+These functions display the program name, a colon, a formatted message
+based on the arguments, and then optionally a colon and an error
+message associated with either "errno" or the "code" parameter.
+
+ EXAMPLE:
+ if (open(filename, O_RDONLY) < 0)
+ xo_err(1, "cannot open file '%s'", filename);
+
+*** xo_no_setlocale
+
+libxo automatically initializes the locale based on setting of the
+environment variables LC_CTYPE, LANG, and LC_ALL. The first of this
+list of variables is used and if none of the variables, the locale
+defaults to "UTF-8". The caller may wish to avoid this behavior, and
+can do so by calling the xo_no_setlocale() function.
+
+ void xo_no_setlocale (void);
+
+* The "xo" Utility
+
+The "xo" utility allows command line access to the functionality of
+the libxo library. Using "xo", shell scripts can emit XML, JSON, and
+HTML using the same commands that emit text output.
+
+The style of output can be selected using a specific option: "-X" for
+XML, "-J" for JSON, "-H" for HTML, or "-T" for TEXT, which is the
+default. The "--style <style>" option can also be used. The
+LIBXO_OPTIONS environment variable can also be used to set the style,
+as well as other flags.
+
+The "xo" utility accepts a format string suitable for xo_emit() and a
+set of zero or more arguments used to supply data for that string.
+
+ xo "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
+
+ TEXT:
+ The fish weighs 6 pounds.
+ XML:
+ <name>fish</name>
+ <weight>6</weight>
+ JSON:
+ "name": "fish",
+ "weight": 6
+ HTML:
+ <div class="line">
+ <div class="text">The </div>
+ <div class="data" data-tag="name">fish</div>
+ <div class="text"> weighs </div>
+ <div class="data" data-tag="weight">6</div>
+ <div class="text"> pounds.</div>
+ </div>
+
+The "--wrap <path>" option can be used to wrap emitted content in a
+specific hierarchy. The path is a set of hierarchical names separated
+by the '/' character.
+
+ xo --wrap top/a/b/c '{:tag}' value
+
+ XML:
+ <top>
+ <a>
+ <b>
+ <c>
+ <tag>value</tag>
+ </c>
+ </b>
+ </a>
+ </top>
+ JSON:
+ "top": {
+ "a": {
+ "b": {
+ "c": {
+ "tag": "value"
+ }
+ }
+ }
+ }
+
+The "--open <path>" and "--close <path>" can be used to emit
+hierarchical information without the matching close and open
+tag. This allows a shell script to emit open tags, data, and
+then close tags. The "--depth" option may be used to set the
+depth for indentation. The "--leading-xpath" may be used to
+prepend data to the XPath values used for HTML output style.
+
+ #!/bin/sh
+ xo --open top/data
+ xo --depth 2 '{tag}' value
+ xo --close top/data
+ XML:
+ <top>
+ <data>
+ <tag>value</tag>
+ </data>
+ </top>
+ JSON:
+ "top": {
+ "data": {
+ "tag": "value"
+ }
+ }
+
+** Command Line Options
+
+Usage: xo [options] format [fields]
+ --close <path> Close tags for the given path
+ --depth <num> Set the depth for pretty printing
+ --help Display this help text
+ --html OR -H Generate HTML output
+ --json OR -J Generate JSON output
+ --leading-xpath <path> Add a prefix to generated XPaths (HTML)
+ --open <path> Open tags for the given path
+ --pretty OR -p Make 'pretty' output (add indent, newlines)
+ --style <style> Generate given style (xml, json, text, html)
+ --text OR -T Generate text output (the default style)
+ --version Display version information
+ --warn OR -W Display warnings in text on stderr
+ --warn-xml Display warnings in xml on stdout
+ --wrap <path> Wrap output in a set of containers
+ --xml OR -X Generate XML output
+ --xpath Add XPath data to HTML output);
+
+** Example
+
+ % xo 'The {:product} is {:status}\n' stereo "in route"
+ The stereo is in route
+ % ./xo/xo -p -X 'The {:product} is {:status}\n' stereo "in route"
+ <product>stereo</product>
+ <status>in route</status>
+
+* xolint
+
+xolint is a tool for reporting common mistakes in format strings
+in source code that invokes xo_emit(). It allows these errors
+to be diagnosed at build time, rather than waiting until runtime.
+
+xolint takes the one or more C files as arguments, and reports
+and errors, warning, or informational messages as needed.
+
+|------------+---------------------------------------------------|
+| Option | Meaning |
+|------------+---------------------------------------------------|
+| -c | Invoke 'cpp' against the input file |
+| -C <flags> | Flags that are passed to 'cpp |
+| -d | Enable debug output |
+| -D | Generate documentation for all xolint messages |
+| -I | Generate info table code |
+| -p | Print the offending lines after the message |
+| -V | Print vocabulary of all field names |
+| -X | Extract samples from xolint, suitable for testing |
+|------------+---------------------------------------------------|
+
+Output message contain the source filename and line number, the
+class of the message, the message, and, if -p is given, the
+line that contains the error:
+
+ % xolint.pl -t xolint.c
+ xolint.c: 16: error: anchor format should be "%d"
+ 16 xo_emit("{[:/%s}");
+
+The "-I" option will generate a table of xo_info_t structures ,
+
+The "-V" option does not report errors, but prints a complete list of
+all field names, sorted alphabetically. The output can help spot
+inconsistencies and spelling errors.
+
+* FAQs
+
+This section contains the set of questions that users typically ask,
+along with answers that might be helpful.
+
+!! list-sections
+
+** General
+
+*** Can you share the history of libxo?
+
+In 2001, we added an XML API to the JUNOS operating system, which is
+built on top of FreeBSD. Eventually this API became standardized as
+the NETCONF API (RFC 6241). As part of this effort, we modified many
+FreeBSD utilities to emit XML, typically via a "-X" switch. The
+results were mixed. The cost of maintaining this code, updating it
+and carrying it were non-trivial, and contributed to our expense (and
+the associated delay) with upgrading the version of FreeBSD on which
+each release of JUNOS is based.
+
+A recent (2014) effort within JUNOS aims at removing our modifications
+to the underlying FreeBSD code as a means of reducing the expense and
+delay. JUNOS is structured to have system components generate XML
+that is rendered by the CLI (think: login shell) into human-readable
+text. This allows the API to use the same plumbing as the CLI, and
+ensures that all components emit XML, and that it is emitted with
+knowledge of the consumer of that XML, yielding an API that have no
+incremental cost or feature delay.
+
+libxo is an effort to mix the best aspects of the JUNOS strategy into
+FreeBSD in a seemless way, allowing commands to make printf-like
+output calls without needing to care how the output is rendered.
+
+*** What makes a good field name?
+
+To make useful, consistent field names, follow these guidelines:
+
+= Use lower case, even for TLAs
+Lower case is more civilized. Even TLAs should be lower case
+to avoid scenarios where the differences between "XPath" and
+"Xpath" drive your users crazy. Using "xpath" is simpler and better.
+= Use hyphens, not underscores
+Use of hyphens is traditional in XML, and the XOF_UNDERSCORES
+flag can be used to generate underscores in JSON, if desired.
+But the raw field name should use hyphens.
+= Use full words
+Don't abbreviate especially when the abbreviation is not obvious or
+not widely used. Use "data-size", not "dsz" or "dsize". Use
+"interface" instead of "ifname", "if-name", "iface", "if", or "intf".
+= Use <verb>-<units>
+Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in
+making consistent, useful names, avoiding the situation where one app
+uses "sent-packet" and another "packets-sent" and another
+"packets-we-have-sent". The <units> can be dropped when it is
+obvious, as can obvious words in the classification.
+Use "receive-after-window-packets" instead of
+"received-packets-of-data-after-window".
+= Reuse existing field names
+Nothing's worse than writing expressions like:
+
+ if ($src1/process[pid == $pid]/name ==
+ $src2/proc-table/proc/p[process-id == $pid]/proc-name) {
+ ...
+ }
+
+Find someone else who is expressing similar data and follow their
+field's and hierarchy. Remember the quote is not "Consistency is the
+hobgoblin of little minds", but "A foolish consistency is the
+hobgoblin of little minds".
+= Think about your users
+Have empathy for your users, choosing clear and useful fields that
+contain clear and useful data. You may need to augment the display
+content with xo_attr() calls (^xo_attr^) or "{e:}" fields
+(^e-modifier^) to make the data useful.
+= Don't use an arbitrary number postfix
+What does "errors2" mean? No one will know. "errors-after-restart"
+would be a better choice. Think of you users, and think of the
+future. If you make "errors2", the next guy will happily make
+"errors3" and before you know it, someone will be asking what's the
+difference between errors37 and errors63.
+= Be consistent, uniform, unsurprising, and predictable
+Think of your field vocabulary as an API. You want it useful,
+expressive, meaningful, direct, and obvious. You want the client
+application's programmer to move between without the need to
+understand a variety of opinions on how fields are named. They should
+see the system as a single cohesive whole, not a sack of cats.
+
+Field names constitute the means by which client programmers interact
+with our system. By choosing wise names now, you are making their
+lives better.
+
+After using "xolint" to find errors in your field descriptors, use
+"xolint -V" to spell check your field names and to detect different
+names for the same data. "dropped-short" and "dropped-too-short" are
+both reasonable names, but using them both will lead users to ask the
+difference between the two fields. If there isn't a difference,
+use only one of the field names. If there is a difference, change the
+names to make that difference more obvious.
+
+** What does this message mean?
+
+!!include-file xolint.txt
+
+* Examples
+
+** Unit Test
+
+Here is the unit test example:
+
+ int
+ main (int argc, char **argv)
+ {
+ static char base_grocery[] = "GRO";
+ static char base_hardware[] = "HRD";
+ struct item {
+ const char *i_title;
+ int i_sold;
+ int i_instock;
+ int i_onorder;
+ const char *i_sku_base;
+ int i_sku_num;
+ };
+ struct item list[] = {
+ { "gum", 1412, 54, 10, base_grocery, 415 },
+ { "rope", 85, 4, 2, base_hardware, 212 },
+ { "ladder", 0, 2, 1, base_hardware, 517 },
+ { "bolt", 4123, 144, 42, base_hardware, 632 },
+ { "water", 17, 14, 2, base_grocery, 2331 },
+ { NULL, 0, 0, 0, NULL, 0 }
+ };
+ struct item list2[] = {
+ { "fish", 1321, 45, 1, base_grocery, 533 },
+ };
+ struct item *ip;
+ xo_info_t info[] = {
+ { "in-stock", "number", "Number of items in stock" },
+ { "name", "string", "Name of the item" },
+ { "on-order", "number", "Number of items on order" },
+ { "sku", "string", "Stock Keeping Unit" },
+ { "sold", "number", "Number of items sold" },
+ { NULL, NULL, NULL },
+ };
+ int info_count = (sizeof(info) / sizeof(info[0])) - 1;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(1);
+
+ xo_set_info(NULL, info, info_count);
+
+ xo_open_container_h(NULL, "top");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title);
+ xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n",
+ ip->i_sold, ip->i_sold ? ".0" : "");
+ xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n",
+ ip->i_instock);
+ xo_emit("{P: }{Lwc:On order}{:on-order/%u}\n",
+ ip->i_onorder);
+ xo_emit("{P: }{L:SKU}: {q:sku/%s-000-%u}\n",
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ for (ip = list2; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
+ xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n",
+ ip->i_sold, ip->i_sold ? ".0" : "");
+ xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\n",
+ ip->i_instock);
+ xo_emit("{P: }{Lwc:On order}{:on-order/%u}\n",
+ ip->i_onorder);
+ xo_emit("{P: }{L:SKU}: {q:sku/%s-000-%u}\n",
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_close_container_h(NULL, "top");
+
+ return 0;
+ }
+
+Text output:
+
+ % ./testxo --libxo text
+ Item 'gum':
+ Total sold: 1412.0
+ In stock: 54
+ On order: 10
+ SKU: GRO-000-415
+ Item 'rope':
+ Total sold: 85.0
+ In stock: 4
+ On order: 2
+ SKU: HRD-000-212
+ Item 'ladder':
+ Total sold: 0
+ In stock: 2
+ On order: 1
+ SKU: HRD-000-517
+ Item 'bolt':
+ Total sold: 4123.0
+ In stock: 144
+ On order: 42
+ SKU: HRD-000-632
+ Item 'water':
+ Total sold: 17.0
+ In stock: 14
+ On order: 2
+ SKU: GRO-000-2331
+ Item 'fish':
+ Total sold: 1321.0
+ In stock: 45
+ On order: 1
+ SKU: GRO-000-533
+
+JSON output:
+
+ % ./testxo --libxo json,pretty
+ "top": {
+ "data": {
+ "item": [
+ {
+ "name": "gum",
+ "sold": 1412.0,
+ "in-stock": 54,
+ "on-order": 10,
+ "sku": "GRO-000-415"
+ },
+ {
+ "name": "rope",
+ "sold": 85.0,
+ "in-stock": 4,
+ "on-order": 2,
+ "sku": "HRD-000-212"
+ },
+ {
+ "name": "ladder",
+ "sold": 0,
+ "in-stock": 2,
+ "on-order": 1,
+ "sku": "HRD-000-517"
+ },
+ {
+ "name": "bolt",
+ "sold": 4123.0,
+ "in-stock": 144,
+ "on-order": 42,
+ "sku": "HRD-000-632"
+ },
+ {
+ "name": "water",
+ "sold": 17.0,
+ "in-stock": 14,
+ "on-order": 2,
+ "sku": "GRO-000-2331"
+ }
+ ]
+ },
+ "data": {
+ "item": [
+ {
+ "name": "fish",
+ "sold": 1321.0,
+ "in-stock": 45,
+ "on-order": 1,
+ "sku": "GRO-000-533"
+ }
+ ]
+ }
+ }
+
+XML output:
+
+ % ./testxo --libxo pretty,xml
+ <top>
+ <data>
+ <item>
+ <name>gum</name>
+ <sold>1412.0</sold>
+ <in-stock>54</in-stock>
+ <on-order>10</on-order>
+ <sku>GRO-000-415</sku>
+ </item>
+ <item>
+ <name>rope</name>
+ <sold>85.0</sold>
+ <in-stock>4</in-stock>
+ <on-order>2</on-order>
+ <sku>HRD-000-212</sku>
+ </item>
+ <item>
+ <name>ladder</name>
+ <sold>0</sold>
+ <in-stock>2</in-stock>
+ <on-order>1</on-order>
+ <sku>HRD-000-517</sku>
+ </item>
+ <item>
+ <name>bolt</name>
+ <sold>4123.0</sold>
+ <in-stock>144</in-stock>
+ <on-order>42</on-order>
+ <sku>HRD-000-632</sku>
+ </item>
+ <item>
+ <name>water</name>
+ <sold>17.0</sold>
+ <in-stock>14</in-stock>
+ <on-order>2</on-order>
+ <sku>GRO-000-2331</sku>
+ </item>
+ </data>
+ <data>
+ <item>
+ <name>fish</name>
+ <sold>1321.0</sold>
+ <in-stock>45</in-stock>
+ <on-order>1</on-order>
+ <sku>GRO-000-533</sku>
+ </item>
+ </data>
+ </top>
+
+HMTL output:
+
+ % ./testxo --libxo pretty,html
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name">gum</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">1412.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">54</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">10</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku">GRO-000-415</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name">rope</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">85.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">4</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">2</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku">HRD-000-212</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name">ladder</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">2</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">1</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku">HRD-000-517</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name">bolt</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">4123.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">144</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">42</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku">HRD-000-632</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name">water</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">17.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">14</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">2</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku">GRO-000-2331</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name">fish</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">1321.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">45</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">1</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku">GRO-000-533</div>
+ </div>
+
+HTML output with xpath and info flags:
+
+ % ./testxo --libxo pretty,html,xpath,info
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name"
+ data-xpath="/top/data/item/name" data-type="string"
+ data-help="Name of the item">gum</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold"
+ data-xpath="/top/data/item/sold" data-type="number"
+ data-help="Number of items sold">1412.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock" data-type="number"
+ data-help="Number of items in stock">54</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order"
+ data-xpath="/top/data/item/on-order" data-type="number"
+ data-help="Number of items on order">10</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku"
+ data-xpath="/top/data/item/sku" data-type="string"
+ data-help="Stock Keeping Unit">GRO-000-415</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name"
+ data-xpath="/top/data/item/name" data-type="string"
+ data-help="Name of the item">rope</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold"
+ data-xpath="/top/data/item/sold" data-type="number"
+ data-help="Number of items sold">85.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock" data-type="number"
+ data-help="Number of items in stock">4</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order"
+ data-xpath="/top/data/item/on-order" data-type="number"
+ data-help="Number of items on order">2</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku"
+ data-xpath="/top/data/item/sku" data-type="string"
+ data-help="Stock Keeping Unit">HRD-000-212</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name"
+ data-xpath="/top/data/item/name" data-type="string"
+ data-help="Name of the item">ladder</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold"
+ data-xpath="/top/data/item/sold" data-type="number"
+ data-help="Number of items sold">0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock" data-type="number"
+ data-help="Number of items in stock">2</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order"
+ data-xpath="/top/data/item/on-order" data-type="number"
+ data-help="Number of items on order">1</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku"
+ data-xpath="/top/data/item/sku" data-type="string"
+ data-help="Stock Keeping Unit">HRD-000-517</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name"
+ data-xpath="/top/data/item/name" data-type="string"
+ data-help="Name of the item">bolt</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold"
+ data-xpath="/top/data/item/sold" data-type="number"
+ data-help="Number of items sold">4123.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock" data-type="number"
+ data-help="Number of items in stock">144</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order"
+ data-xpath="/top/data/item/on-order" data-type="number"
+ data-help="Number of items on order">42</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku"
+ data-xpath="/top/data/item/sku" data-type="string"
+ data-help="Stock Keeping Unit">HRD-000-632</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name"
+ data-xpath="/top/data/item/name" data-type="string"
+ data-help="Name of the item">water</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold"
+ data-xpath="/top/data/item/sold" data-type="number"
+ data-help="Number of items sold">17.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock" data-type="number"
+ data-help="Number of items in stock">14</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order"
+ data-xpath="/top/data/item/on-order" data-type="number"
+ data-help="Number of items on order">2</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku"
+ data-xpath="/top/data/item/sku" data-type="string"
+ data-help="Stock Keeping Unit">GRO-000-2331</div>
+ </div>
+ <div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name"
+ data-xpath="/top/data/item/name" data-type="string"
+ data-help="Name of the item">fish</div>
+ <div class="text">':</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold"
+ data-xpath="/top/data/item/sold" data-type="number"
+ data-help="Number of items sold">1321.0</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock" data-type="number"
+ data-help="Number of items in stock">45</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order"
+ data-xpath="/top/data/item/on-order" data-type="number"
+ data-help="Number of items on order">1</div>
+ </div>
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku"
+ data-xpath="/top/data/item/sku" data-type="string"
+ data-help="Stock Keeping Unit">GRO-000-533</div>
+ </div>
+
+{{document:
+ name libxo-manual;
+ private "The libxo Project";
+ ipr none;
+ category exp;
+ abbreviation LIBXO-MANUAL;
+ title "libxo: The Easy Way to Generate text, XML, JSON, and HTML output";
+ contributor "author:Phil Shafer:Juniper Networks:phil@juniper.net";
+}}
diff --git a/contrib/libxo/install-sh b/contrib/libxo/install-sh
new file mode 100755
index 0000000..377bb86
--- /dev/null
+++ b/contrib/libxo/install-sh
@@ -0,0 +1,527 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-11-20.07; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t) dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call 'install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names problematic for 'test' and other utilities.
+ case $src in
+ -* | [=\(\)!]) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+ dst=$dst_arg
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/contrib/libxo/libxo-config.in b/contrib/libxo/libxo-config.in
new file mode 100644
index 0000000..3dbb7d4
--- /dev/null
+++ b/contrib/libxo/libxo-config.in
@@ -0,0 +1,119 @@
+#! /bin/sh
+#
+# $Id$
+#
+# Copyright 2011-2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+includedir=@includedir@
+libdir=@libdir@
+
+usage()
+{
+ cat <<EOF
+Usage: libxo-config [OPTION]
+
+Known values for OPTION are:
+
+ --prefix=DIR change libxo prefix [default $prefix]
+ --exec-prefix=DIR change libxo exec prefix [default $exec_prefix]
+ --libs print library linking information
+ --bindir print the bin directory
+ --cflags print pre-processor and compiler flags
+ --share print share directory
+ --help display this help and exit
+ --version output version information
+EOF
+
+ exit $1
+}
+
+if test $# -eq 0; then
+ usage 1
+fi
+
+cflags=false
+libs=false
+
+while test $# -gt 0; do
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case "$1" in
+ --prefix=*)
+ prefix=$optarg
+ includedir=$prefix/include
+ libdir=$prefix/lib
+ ;;
+
+ --prefix)
+ echo $prefix
+ ;;
+
+ --exec-prefix=*)
+ exec_prefix=$optarg
+ libdir=$exec_prefix/lib
+ ;;
+
+ --exec-prefix)
+ echo $exec_prefix
+ ;;
+
+ --version)
+ echo @VERSION@
+ exit 0
+ ;;
+
+ --help)
+ usage 0
+ ;;
+
+ --cflags)
+ echo -I@LIBXO_INCLUDEDIR@ @LIBXO_CFLAGS@
+ ;;
+
+
+ --share)
+ echo @LIBXO_SHAREDIR@
+ ;;
+
+ --bindir)
+ echo @LIBXO_BINDIR@
+ ;;
+
+ --libdir)
+ echo @LIBXO_LIBDIR@
+ ;;
+
+
+ --libs)
+ if [ "`uname`" = "Linux" ]
+ then
+ if [ "@LIBXO_LIBDIR@" = "-L/usr/lib" -o "@LIBXO_LIBDIR@" = "-L/usr/lib64" ]
+ then
+ echo @LIBXO_LIBS@
+ else
+ echo -L@LIBXO_LIBDIR@ @LIBXO_LIBS@
+ fi
+ else
+ echo -L@LIBXO_LIBDIR@ @LIBXO_LIBS@ @WIN32_EXTRA_LIBADD@
+ fi
+ ;;
+
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+exit 0
diff --git a/contrib/libxo/libxo/Makefile.am b/contrib/libxo/libxo/Makefile.am
new file mode 100644
index 0000000..3303e94
--- /dev/null
+++ b/contrib/libxo/libxo/Makefile.am
@@ -0,0 +1,49 @@
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+if LIBXO_WARNINGS_HIGH
+LIBXO_WARNINGS = HIGH
+endif
+if HAVE_GCC
+GCC_WARNINGS = yes
+endif
+include ${top_srcdir}/warnings.mk
+
+libxoincdir = ${includedir}/libxo
+
+AM_CFLAGS = -I${top_srcdir} ${WARNINGS}
+
+lib_LTLIBRARIES = libxo.la
+
+libxoinc_HEADERS = \
+ xo.h
+
+libxo_la_SOURCES = \
+ libxo.c
+
+man_MANS = \
+ libxo.3 \
+ xo_attr.3 \
+ xo_create.3 \
+ xo_emit.3 \
+ xo_err.3 \
+ xo_finish.3 \
+ xo_flush.3 \
+ xo_format.5 \
+ xo_no_setlocale.3 \
+ xo_open_container.3 \
+ xo_open_list.3 \
+ xo_parse_args.3 \
+ xo_set_allocator.3 \
+ xo_set_flags.3 \
+ xo_set_info.3 \
+ xo_set_options.3 \
+ xo_set_style.3 \
+ xo_set_writer.3
+
+EXTRA_DIST =
diff --git a/contrib/libxo/libxo/gen-wide.sh b/contrib/libxo/libxo/gen-wide.sh
new file mode 100755
index 0000000..b034287
--- /dev/null
+++ b/contrib/libxo/libxo/gen-wide.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+
+FILE=$1
+
+SYMBOLS="
+xo_buffer_s
+xo_buffer_t
+xo_stack_s
+xo_stack_t
+xo_handle_s
+xo_handle_t
+xo_default_handle
+xo_default_inited
+xo_realloc
+xo_free
+xo_write_to_file
+xo_close_file
+xo_buf_init
+xo_init_handle
+xo_default_init
+xo_buf_has_room
+xo_printf
+xo_escape_xml
+xo_escape_json
+xo_buf_append
+xo_buf_escape
+xo_data_append
+xo_data_escape
+xo_default
+xo_indent
+xo_warn
+xo_create
+xo_create_to_file
+xo_destroy
+xo_set_style
+xo_set_flags
+xo_set_info
+xo_set_formatter
+xo_clear_flags
+xo_buf_indent
+xo_line_ensure_open
+xo_line_close
+xo_info_compare
+xo_info_find
+xo_format_data
+xo_buf_append_div
+xo_format_text
+xo_format_label
+xo_format_title
+xo_format_prep
+xo_format_value
+xo_format_decoration
+xo_format_padding
+xo_do_emit
+xo_emit_hv
+xo_emit_h
+xo_emit
+xo_attr_hv
+xo_attr_h
+xo_attr
+xo_depth_change
+xo_open_container_h
+xo_open_container
+xo_close_container_h
+xo_close_container
+xo_open_list_h
+xo_open_list
+xo_close_list_h
+xo_close_list
+xo_open_instance_h
+xo_open_instance
+xo_close_instance_h
+xo_close_instance
+xo_set_writer
+xo_set_allocator
+"
diff --git a/contrib/libxo/libxo/libxo.3 b/contrib/libxo/libxo/libxo.3
new file mode 100644
index 0000000..fca0774
--- /dev/null
+++ b/contrib/libxo/libxo/libxo.3
@@ -0,0 +1,149 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm libxo
+.Nd library for emitting text, XML, JSON, or HTML output
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Sh DESCRIPTION
+The functions defined in
+.Lb libxo
+are used to generate a choice of
+.Em TEXT ,
+.Em XML ,
+.Em JSON ,
+or
+.Em HTML
+output. A common set of functions are used, with
+command line switches passed to the library to control the details of
+the output.
+.Pp
+Most commands emit text output aimed at humans. It is designed
+to be parsed and understood by a user. Humans are gifted at extracted
+details and pattern matching. Often programmers need to extract
+information from this human-oriented output. Programmers use tools
+like grep, awk, and regular expressions to ferret out the pieces of
+information they need. Such solutions are fragile and require
+updates when output contents change or evolve, requiring testing and
+validation.
+.Pp
+Modern tool developers favors encoding schemes like XML and JSON,
+which allow trivial parsing and extraction of data. Such formats are
+simple, well understood, hierarchical, easily parsed, and often
+integrate easier with common tools and environments.
+.Pp
+In addition, modern reality means that more output ends up in web
+browsers than in terminals, making HTML output valuable.
+.Pp
+.Em libxo
+allows a single set of function calls in source code to generate
+traditional text output, as well as XML and JSON formatted data. HTML
+can also be generated; "<div>" elements surround the traditional text
+output, with attributes that detail how to render the data.
+.Pp
+There are four encoding styles supported by libxo: TEXT, HTML, JSON,
+and XML. JSON and XML are suitable for encoding data, while TEXT and
+HTML are suited for display to the user. TEXT output can be display
+on a terminal session, allowing compatibility with traditional usage.
+HTML can be matched with a small CSS file to permit rendering in any
+HTML5 browser. XML output is suitable for tools like XPath and
+protocols like NETCONF. JSON output can be used for RESTful APIs.
+.Pp
+The
+.Em libxo
+library allows an application to generate text, XML, JSON,
+and HTML output using a common set of function calls. The application
+decides at run time which output style should be produced. The
+application calls a function
+.Fn xo_emit
+to product output that is
+described in a format string. A "field descriptor" tells libxo what
+the field is and what it means. Each field descriptor is placed in
+braces with a printf-like format string:
+.Bd -literal -offset indent
+ xo_emit(" {:lines/%7ju} {:words/%7ju} "
+ "{:characters/%7ju}{d:filename/%s}\\n",
+ linect, wordct, charct, file);
+.Ed
+.Pp
+Each field can have a role, with the 'value' role being the default,
+and the role tells libxo how and when to render that field, as well as
+a
+.Xr printf 3 -like
+format string.
+.Pp
+Output
+can then be generated in various style, using the "--libxo" option.
+.Sh DEFAULT HANDLE
+Handles give an abstraction for libxo that encapsulates the state of a
+stream of output. Handles have the data type "xo_handle_t" and are
+opaque to the caller.
+
+The library has a default handle that is automatically initialized.
+By default, this handle will send text style output to standard output.
+The xo_set_style and xo_set_flags functions can be used to change this
+behavior.
+
+Many libxo functions take a handle as their first parameter; most that
+do not use the default handle. Any function taking a handle can
+be passed NULL to access the default handle.
+
+For the typical command that is generating output on standard output,
+there is no need to create an explicit handle, but they are available
+when needed, e.g. for daemons that generate multiple streams of
+output.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_attr 3 ,
+.Xr xo_create 3 ,
+.Xr xo_emit 3 ,
+.Xr xo_err 3 ,
+.Xr xo_finish 3 ,
+.Xr xo_flush 3 ,
+.Xr xo_format 5 ,
+.Xr xo_no_setlocale 3 ,
+.Xr xo_open_container 3 ,
+.Xr xo_open_list 3 ,
+.Xr xo_parse_args 3 ,
+.Xr xo_set_allocator 3 ,
+.Xr xo_set_flags 3 ,
+.Xr xo_set_info 3 ,
+.Xr xo_set_options 3 ,
+.Xr xo_set_style 3 ,
+.Xr xo_set_writer 3 ,
+.Xr xo 1 ,
+and
+.Xr xolint 1 .
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/libxo.c b/contrib/libxo/libxo/libxo.c
new file mode 100644
index 0000000..ebe55b9
--- /dev/null
+++ b/contrib/libxo/libxo/libxo.c
@@ -0,0 +1,4353 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <wchar.h>
+#include <locale.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <ctype.h>
+#include <wctype.h>
+#include <getopt.h>
+
+#include "xoconfig.h"
+#include "xo.h"
+#include "xoversion.h"
+
+const char xo_version[] = LIBXO_VERSION;
+const char xo_version_extra[] = LIBXO_VERSION_EXTRA;
+
+#ifndef UNUSED
+#define UNUSED __attribute__ ((__unused__))
+#endif /* UNUSED */
+
+#define XO_INDENT_BY 2 /* Amount to indent when pretty printing */
+#define XO_BUFSIZ (8*1024) /* Initial buffer size */
+#define XO_DEPTH 512 /* Default stack depth */
+#define XO_MAX_ANCHOR_WIDTH (8*1024) /* Anything wider is just sillyb */
+
+#define XO_FAILURE_NAME "failure"
+
+/*
+ * xo_buffer_t: a memory buffer that can be grown as needed. We
+ * use them for building format strings and output data.
+ */
+typedef struct xo_buffer_s {
+ char *xb_bufp; /* Buffer memory */
+ char *xb_curp; /* Current insertion point */
+ int xb_size; /* Size of buffer */
+} xo_buffer_t;
+
+/* Flags for the stack frame */
+typedef unsigned xo_xsf_flags_t; /* XSF_* flags */
+#define XSF_NOT_FIRST (1<<0) /* Not the first element */
+#define XSF_LIST (1<<1) /* Frame is a list */
+#define XSF_INSTANCE (1<<2) /* Frame is an instance */
+#define XSF_DTRT (1<<3) /* Save the name for DTRT mode */
+
+/*
+ * xo_stack_t: As we open and close containers and levels, we
+ * create a stack of frames to track them. This is needed for
+ * XOF_WARN and XOF_XPATH.
+ */
+typedef struct xo_stack_s {
+ xo_xsf_flags_t xs_flags; /* Flags for this frame */
+ char *xs_name; /* Name (for XPath value) */
+ char *xs_keys; /* XPath predicate for any key fields */
+} xo_stack_t;
+
+/*
+ * xo_handle_t: this is the principle data structure for libxo.
+ * It's used as a store for state, options, and content.
+ */
+struct xo_handle_s {
+ unsigned long xo_flags; /* Flags */
+ unsigned short xo_style; /* XO_STYLE_* value */
+ unsigned short xo_indent; /* Indent level (if pretty) */
+ unsigned short xo_indent_by; /* Indent amount (tab stop) */
+ xo_write_func_t xo_write; /* Write callback */
+ xo_close_func_t xo_close; /* Clo;se callback */
+ xo_formatter_t xo_formatter; /* Custom formating function */
+ xo_checkpointer_t xo_checkpointer; /* Custom formating support function */
+ void *xo_opaque; /* Opaque data for write function */
+ FILE *xo_fp; /* XXX File pointer */
+ xo_buffer_t xo_data; /* Output data */
+ xo_buffer_t xo_fmt; /* Work area for building format strings */
+ xo_buffer_t xo_attrs; /* Work area for building XML attributes */
+ xo_buffer_t xo_predicate; /* Work area for building XPath predicates */
+ xo_stack_t *xo_stack; /* Stack pointer */
+ int xo_depth; /* Depth of stack */
+ int xo_stack_size; /* Size of the stack */
+ xo_info_t *xo_info; /* Info fields for all elements */
+ int xo_info_count; /* Number of info entries */
+ va_list xo_vap; /* Variable arguments (stdargs) */
+ char *xo_leading_xpath; /* A leading XPath expression */
+ mbstate_t xo_mbstate; /* Multi-byte character conversion state */
+ unsigned xo_anchor_offset; /* Start of anchored text */
+ unsigned xo_anchor_columns; /* Number of columns since the start anchor */
+ int xo_anchor_min_width; /* Desired width of anchored text */
+ unsigned xo_units_offset; /* Start of units insertion point */
+ unsigned xo_columns; /* Columns emitted during this xo_emit call */
+};
+
+/* Flags for formatting functions */
+typedef unsigned long xo_xff_flags_t;
+#define XFF_COLON (1<<0) /* Append a ":" */
+#define XFF_COMMA (1<<1) /* Append a "," iff there's more output */
+#define XFF_WS (1<<2) /* Append a blank */
+#define XFF_ENCODE_ONLY (1<<3) /* Only emit for encoding formats (xml and json) */
+
+#define XFF_QUOTE (1<<4) /* Force quotes */
+#define XFF_NOQUOTE (1<<5) /* Force no quotes */
+#define XFF_DISPLAY_ONLY (1<<6) /* Only emit for display formats (text and html) */
+#define XFF_KEY (1<<7) /* Field is a key (for XPath) */
+
+#define XFF_XML (1<<8) /* Force XML encoding style (for XPath) */
+#define XFF_ATTR (1<<9) /* Escape value using attribute rules (XML) */
+#define XFF_BLANK_LINE (1<<10) /* Emit a blank line */
+#define XFF_NO_OUTPUT (1<<11) /* Do not make any output */
+
+#define XFF_TRIM_WS (1<<12) /* Trim whitespace off encoded values */
+#define XFF_LEAF_LIST (1<<13) /* A leaf-list (list of values) */
+#define XFF_UNESCAPE (1<<14) /* Need to printf-style unescape the value */
+
+/*
+ * Normal printf has width and precision, which for strings operate as
+ * min and max number of columns. But this depends on the idea that
+ * one byte means one column, which UTF-8 and multi-byte characters
+ * pitches on its ear. It may take 40 bytes of data to populate 14
+ * columns, but we can't go off looking at 40 bytes of data without the
+ * caller's permission for fear/knowledge that we'll generate core files.
+ *
+ * So we make three values, distinguishing between "max column" and
+ * "number of bytes that we will inspect inspect safely" We call the
+ * later "size", and make the format "%[[<min>].[[<size>].<max>]]s".
+ *
+ * Under the "first do no harm" theory, we default "max" to "size".
+ * This is a reasonable assumption for folks that don't grok the
+ * MBS/WCS/UTF-8 world, and while it will be annoying, it will never
+ * be evil.
+ *
+ * For example, xo_emit("{:tag/%-14.14s}", buf) will make 14
+ * columns of output, but will never look at more than 14 bytes of the
+ * input buffer. This is mostly compatible with printf and caller's
+ * expectations.
+ *
+ * In contrast xo_emit("{:tag/%-14..14s}", buf) will look at however
+ * many bytes (or until a NUL is seen) are needed to fill 14 columns
+ * of output. xo_emit("{:tag/%-14.*.14s}", xx, buf) will look at up
+ * to xx bytes (or until a NUL is seen) in order to fill 14 columns
+ * of output.
+ *
+ * It's fairly amazing how a good idea (handle all languages of the
+ * world) blows such a big hole in the bottom of the fairly weak boat
+ * that is C string handling. The simplicity and completenesss are
+ * sunk in ways we haven't even begun to understand.
+ */
+
+#define XF_WIDTH_MIN 0 /* Minimal width */
+#define XF_WIDTH_SIZE 1 /* Maximum number of bytes to examine */
+#define XF_WIDTH_MAX 2 /* Maximum width */
+#define XF_WIDTH_NUM 3 /* Numeric fields in printf (min.size.max) */
+
+/* Input and output string encodings */
+#define XF_ENC_WIDE 1 /* Wide characters (wchar_t) */
+#define XF_ENC_UTF8 2 /* UTF-8 */
+#define XF_ENC_LOCALE 3 /* Current locale */
+
+/*
+ * A place to parse printf-style format flags for each field
+ */
+typedef struct xo_format_s {
+ unsigned char xf_fc; /* Format character */
+ unsigned char xf_enc; /* Encoding of the string (XF_ENC_*) */
+ unsigned char xf_skip; /* Skip this field */
+ unsigned char xf_lflag; /* 'l' (long) */
+ unsigned char xf_hflag;; /* 'h' (half) */
+ unsigned char xf_jflag; /* 'j' (intmax_t) */
+ unsigned char xf_tflag; /* 't' (ptrdiff_t) */
+ unsigned char xf_zflag; /* 'z' (size_t) */
+ unsigned char xf_qflag; /* 'q' (quad_t) */
+ unsigned char xf_seen_minus; /* Seen a minus */
+ int xf_leading_zero; /* Seen a leading zero (zero fill) */
+ unsigned xf_dots; /* Seen one or more '.'s */
+ int xf_width[XF_WIDTH_NUM]; /* Width/precision/size numeric fields */
+ unsigned xf_stars; /* Seen one or more '*'s */
+ unsigned char xf_star[XF_WIDTH_NUM]; /* Seen one or more '*'s */
+} xo_format_t;
+
+/*
+ * We keep a default handle to allow callers to avoid having to
+ * allocate one. Passing NULL to any of our functions will use
+ * this default handle.
+ */
+static xo_handle_t xo_default_handle;
+static int xo_default_inited;
+static int xo_locale_inited;
+static char *xo_program;
+
+/*
+ * To allow libxo to be used in diverse environment, we allow the
+ * caller to give callbacks for memory allocation.
+ */
+static xo_realloc_func_t xo_realloc = realloc;
+static xo_free_func_t xo_free = free;
+
+/* Forward declarations */
+static void
+xo_failure (xo_handle_t *xop, const char *fmt, ...);
+
+static void
+xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
+ const char *name, int nlen,
+ const char *value, int vlen,
+ const char *encoding, int elen);
+
+static void
+xo_anchor_clear (xo_handle_t *xop);
+
+/*
+ * Callback to write data to a FILE pointer
+ */
+static int
+xo_write_to_file (void *opaque, const char *data)
+{
+ FILE *fp = (FILE *) opaque;
+ return fprintf(fp, "%s", data);
+}
+
+/*
+ * Callback to close a file
+ */
+static void
+xo_close_file (void *opaque)
+{
+ FILE *fp = (FILE *) opaque;
+ fclose(fp);
+}
+
+/*
+ * Initialize the contents of an xo_buffer_t.
+ */
+static void
+xo_buf_init (xo_buffer_t *xbp)
+{
+ xbp->xb_size = XO_BUFSIZ;
+ xbp->xb_bufp = xo_realloc(NULL, xbp->xb_size);
+ xbp->xb_curp = xbp->xb_bufp;
+}
+
+/*
+ * Initialize the contents of an xo_buffer_t.
+ */
+static void
+xo_buf_cleanup (xo_buffer_t *xbp)
+{
+ if (xbp->xb_bufp)
+ xo_free(xbp->xb_bufp);
+ bzero(xbp, sizeof(*xbp));
+}
+
+static int
+xo_depth_check (xo_handle_t *xop, int depth)
+{
+ xo_stack_t *xsp;
+
+ if (depth >= xop->xo_stack_size) {
+ depth += 16;
+ xsp = xo_realloc(xop->xo_stack, sizeof(xop->xo_stack[0]) * depth);
+ if (xsp == NULL) {
+ xo_failure(xop, "xo_depth_check: out of memory (%d)", depth);
+ return 0;
+ }
+
+ int count = depth - xop->xo_stack_size;
+
+ bzero(xsp + xop->xo_stack_size, count * sizeof(*xsp));
+ xop->xo_stack_size = depth;
+ xop->xo_stack = xsp;
+ }
+
+ return 0;
+}
+
+void
+xo_no_setlocale (void)
+{
+ xo_locale_inited = 1; /* Skip initialization */
+}
+
+/*
+ * Initialize an xo_handle_t, using both static defaults and
+ * the global settings from the LIBXO_OPTIONS environment
+ * variable.
+ */
+static void
+xo_init_handle (xo_handle_t *xop)
+{
+ xop->xo_opaque = stdout;
+ xop->xo_write = xo_write_to_file;
+
+ /*
+ * We need to initialize the locale, which isn't really pretty.
+ * Libraries should depend on their caller to set up the
+ * environment. But we really can't count on the caller to do
+ * this, because well, they won't. Trust me.
+ */
+ if (!xo_locale_inited) {
+ xo_locale_inited = 1; /* Only do this once */
+
+ const char *cp = getenv("LC_CTYPE");
+ if (cp == NULL)
+ cp = getenv("LANG");
+ if (cp == NULL)
+ cp = getenv("LC_ALL");
+ if (cp == NULL)
+ cp = "UTF-8"; /* Optimistic? */
+ cp = setlocale(LC_CTYPE, cp);
+ }
+
+ /*
+ * Initialize only the xo_buffers we know we'll need; the others
+ * can be allocated as needed.
+ */
+ xo_buf_init(&xop->xo_data);
+ xo_buf_init(&xop->xo_fmt);
+
+ xop->xo_indent_by = XO_INDENT_BY;
+ xo_depth_check(xop, XO_DEPTH);
+
+#if !defined(NO_LIBXO_OPTIONS)
+ if (!(xop->xo_flags & XOF_NO_ENV)) {
+ char *env = getenv("LIBXO_OPTIONS");
+ if (env)
+ xo_set_options(xop, env);
+ }
+#endif /* NO_GETENV */
+}
+
+/*
+ * Initialize the default handle.
+ */
+static void
+xo_default_init (void)
+{
+ xo_handle_t *xop = &xo_default_handle;
+
+ xo_init_handle(xop);
+
+ xo_default_inited = 1;
+}
+
+/*
+ * Does the buffer have room for the given number of bytes of data?
+ * If not, realloc the buffer to make room. If that fails, we
+ * return 0 to tell the caller they are in trouble.
+ */
+static int
+xo_buf_has_room (xo_buffer_t *xbp, int len)
+{
+ if (xbp->xb_curp + len >= xbp->xb_bufp + xbp->xb_size) {
+ int sz = xbp->xb_size + XO_BUFSIZ;
+ char *bp = xo_realloc(xbp->xb_bufp, sz);
+ if (bp == NULL) {
+ /*
+ * XXX If we wanted to put a stick XOF_ENOMEM on xop,
+ * this would be the place to do it. But we'd need
+ * to churn the code to pass xop in here....
+ */
+ return 0;
+ }
+
+ xbp->xb_curp = bp + (xbp->xb_curp - xbp->xb_bufp);
+ xbp->xb_bufp = bp;
+ xbp->xb_size = sz;
+ }
+
+ return 1;
+}
+
+/*
+ * Cheap convenience function to return either the argument, or
+ * the internal handle, after it has been initialized. The usage
+ * is:
+ * xop = xo_default(xop);
+ */
+static xo_handle_t *
+xo_default (xo_handle_t *xop)
+{
+ if (xop == NULL) {
+ if (xo_default_inited == 0)
+ xo_default_init();
+ xop = &xo_default_handle;
+ }
+
+ return xop;
+}
+
+/*
+ * Return the number of spaces we should be indenting. If
+ * we are pretty-printing, theis is indent * indent_by.
+ */
+static int
+xo_indent (xo_handle_t *xop)
+{
+ int rc = 0;
+
+ xop = xo_default(xop);
+
+ if (xop->xo_flags & XOF_PRETTY) {
+ rc = xop->xo_indent * xop->xo_indent_by;
+ if (xop->xo_flags & XOF_TOP_EMITTED)
+ rc += xop->xo_indent_by;
+ }
+
+ return rc;
+}
+
+static void
+xo_buf_indent (xo_handle_t *xop, int indent)
+{
+ xo_buffer_t *xbp = &xop->xo_data;
+
+ if (indent <= 0)
+ indent = xo_indent(xop);
+
+ if (!xo_buf_has_room(xbp, indent))
+ return;
+
+ memset(xbp->xb_curp, ' ', indent);
+ xbp->xb_curp += indent;
+}
+
+static char xo_xml_amp[] = "&amp;";
+static char xo_xml_lt[] = "&lt;";
+static char xo_xml_gt[] = "&gt;";
+static char xo_xml_quot[] = "&quot;";
+
+static int
+xo_escape_xml (xo_buffer_t *xbp, int len, int attr)
+{
+ int slen;
+ unsigned delta = 0;
+ char *cp, *ep, *ip;
+ const char *sp;
+
+ for (cp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) {
+ /* We're subtracting 2: 1 for the NUL, 1 for the char we replace */
+ if (*cp == '<')
+ delta += sizeof(xo_xml_lt) - 2;
+ else if (*cp == '>')
+ delta += sizeof(xo_xml_gt) - 2;
+ else if (*cp == '&')
+ delta += sizeof(xo_xml_amp) - 2;
+ else if (attr && *cp == '"')
+ delta += sizeof(xo_xml_quot) - 2;
+ }
+
+ if (delta == 0) /* Nothing to escape; bail */
+ return len;
+
+ if (!xo_buf_has_room(xbp, delta)) /* No room; bail, but don't append */
+ return 0;
+
+ ep = xbp->xb_curp;
+ cp = ep + len;
+ ip = cp + delta;
+ do {
+ cp -= 1;
+ ip -= 1;
+
+ if (*cp == '<')
+ sp = xo_xml_lt;
+ else if (*cp == '>')
+ sp = xo_xml_gt;
+ else if (*cp == '&')
+ sp = xo_xml_amp;
+ else if (attr && *cp == '"')
+ sp = xo_xml_quot;
+ else {
+ *ip = *cp;
+ continue;
+ }
+
+ slen = strlen(sp);
+ ip -= slen - 1;
+ memcpy(ip, sp, slen);
+
+ } while (cp > ep && cp != ip);
+
+ return len + delta;
+}
+
+static int
+xo_escape_json (xo_buffer_t *xbp, int len)
+{
+ unsigned delta = 0;
+ char *cp, *ep, *ip;
+
+ for (cp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) {
+ if (*cp == '\\')
+ delta += 1;
+ else if (*cp == '"')
+ delta += 1;
+ }
+
+ if (delta == 0) /* Nothing to escape; bail */
+ return len;
+
+ if (!xo_buf_has_room(xbp, delta)) /* No room; bail, but don't append */
+ return 0;
+
+ ep = xbp->xb_curp;
+ cp = ep + len;
+ ip = cp + delta;
+ do {
+ cp -= 1;
+ ip -= 1;
+
+ if (*cp != '\\' && *cp != '"') {
+ *ip = *cp;
+ continue;
+ }
+
+ *ip-- = *cp;
+ *ip = '\\';
+
+ } while (cp > ep && cp != ip);
+
+ return len + delta;
+}
+
+/*
+ * Append the given string to the given buffer
+ */
+static void
+xo_buf_append (xo_buffer_t *xbp, const char *str, int len)
+{
+ if (!xo_buf_has_room(xbp, len))
+ return;
+
+ memcpy(xbp->xb_curp, str, len);
+ xbp->xb_curp += len;
+}
+
+static void
+xo_buf_escape (xo_handle_t *xop, xo_buffer_t *xbp,
+ const char *str, int len, xo_xff_flags_t flags)
+{
+ if (!xo_buf_has_room(xbp, len))
+ return;
+
+ memcpy(xbp->xb_curp, str, len);
+
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ case XO_STYLE_HTML:
+ len = xo_escape_xml(xbp, len, (flags & XFF_ATTR));
+ break;
+
+ case XO_STYLE_JSON:
+ len = xo_escape_json(xbp, len);
+ break;
+ }
+
+ xbp->xb_curp += len;
+}
+
+/*
+ * Write the current contents of the data buffer using the handle's
+ * xo_write function.
+ */
+static void
+xo_write (xo_handle_t *xop)
+{
+ xo_buffer_t *xbp = &xop->xo_data;
+
+ if (xbp->xb_curp != xbp->xb_bufp) {
+ xo_buf_append(xbp, "", 1); /* Append ending NUL */
+ xo_anchor_clear(xop);
+ xop->xo_write(xop->xo_opaque, xbp->xb_bufp);
+ xbp->xb_curp = xbp->xb_bufp;
+ }
+
+ /* Turn off the flags that don't survive across writes */
+ xop->xo_flags &= ~(XOF_UNITS_PENDING);
+}
+
+/*
+ * Format arguments into our buffer. If a custom formatter has been set,
+ * we use that to do the work; otherwise we vsnprintf().
+ */
+static int
+xo_vsnprintf (xo_handle_t *xop, xo_buffer_t *xbp, const char *fmt, va_list vap)
+{
+ va_list va_local;
+ int rc;
+ int left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+
+ va_copy(va_local, vap);
+
+ if (xop->xo_formatter)
+ rc = xop->xo_formatter(xop, xbp->xb_curp, left, fmt, va_local);
+ else
+ rc = vsnprintf(xbp->xb_curp, left, fmt, va_local);
+
+ if (rc > xbp->xb_size) {
+ if (!xo_buf_has_room(xbp, rc))
+ return -1;
+
+ /*
+ * After we call vsnprintf(), the stage of vap is not defined.
+ * We need to copy it before we pass. Then we have to do our
+ * own logic below to move it along. This is because the
+ * implementation can have va_list be a point (bsd) or a
+ * structure (macosx) or anything in between.
+ */
+
+ va_end(va_local); /* Reset vap to the start */
+ va_copy(va_local, vap);
+
+ left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ if (xop->xo_formatter)
+ xop->xo_formatter(xop, xbp->xb_curp, left, fmt, va_local);
+ else
+ rc = vsnprintf(xbp->xb_curp, left, fmt, va_local);
+ }
+ va_end(va_local);
+
+ return rc;
+}
+
+/*
+ * Print some data thru the handle.
+ */
+static int
+xo_printf_v (xo_handle_t *xop, const char *fmt, va_list vap)
+{
+ xo_buffer_t *xbp = &xop->xo_data;
+ int left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ int rc;
+ va_list va_local;
+
+ va_copy(va_local, vap);
+
+ rc = vsnprintf(xbp->xb_curp, left, fmt, va_local);
+
+ if (rc > xbp->xb_size) {
+ if (!xo_buf_has_room(xbp, rc))
+ return -1;
+
+ va_end(va_local); /* Reset vap to the start */
+ va_copy(va_local, vap);
+
+ left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ rc = vsnprintf(xbp->xb_curp, left, fmt, va_local);
+ }
+
+ va_end(va_local);
+
+ if (rc > 0)
+ xbp->xb_curp += rc;
+
+ return rc;
+}
+
+static int
+xo_printf (xo_handle_t *xop, const char *fmt, ...)
+{
+ int rc;
+ va_list vap;
+
+ va_start(vap, fmt);
+
+ rc = xo_printf_v(xop, fmt, vap);
+
+ va_end(vap);
+ return rc;
+}
+
+/*
+ * These next few function are make The Essential UTF-8 Ginsu Knife.
+ * Identify an input and output character, and convert it.
+ */
+static int xo_utf8_bits[7] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
+
+static int
+xo_is_utf8 (char ch)
+{
+ return (ch & 0x80);
+}
+
+static int
+xo_utf8_to_wc_len (const char *buf)
+{
+ unsigned b = (unsigned char) *buf;
+ int len;
+
+ if ((b & 0x80) == 0x0)
+ len = 1;
+ else if ((b & 0xe0) == 0xc0)
+ len = 2;
+ else if ((b & 0xf0) == 0xe0)
+ len = 3;
+ else if ((b & 0xf8) == 0xf0)
+ len = 4;
+ else if ((b & 0xfc) == 0xf8)
+ len = 5;
+ else if ((b & 0xfe) == 0xfc)
+ len = 6;
+ else
+ len = -1;
+
+ return len;
+}
+
+static int
+xo_buf_utf8_len (xo_handle_t *xop, const char *buf, int bufsiz)
+{
+
+ unsigned b = (unsigned char) *buf;
+ int len, i;
+
+ len = xo_utf8_to_wc_len(buf);
+ if (len == -1) {
+ xo_failure(xop, "invalid UTF-8 data: %02hhx", b);
+ return -1;
+ }
+
+ if (len > bufsiz) {
+ xo_failure(xop, "invalid UTF-8 data (short): %02hhx (%d/%d)",
+ b, len, bufsiz);
+ return -1;
+ }
+
+ for (i = 2; i < len; i++) {
+ b = (unsigned char ) buf[i];
+ if ((b & 0xc0) != 0x80) {
+ xo_failure(xop, "invalid UTF-8 data (byte %d): %x", i, b);
+ return -1;
+ }
+ }
+
+ return len;
+}
+
+/*
+ * Build a wide character from the input buffer; the number of
+ * bits we pull off the first character is dependent on the length,
+ * but we put 6 bits off all other bytes.
+ */
+static wchar_t
+xo_utf8_char (const char *buf, int len)
+{
+ int i;
+ wchar_t wc;
+ const unsigned char *cp = (const unsigned char *) buf;
+
+ wc = *cp & xo_utf8_bits[len];
+ for (i = 1; i < len; i++) {
+ wc <<= 6;
+ wc |= cp[i] & 0x3f;
+ if ((cp[i] & 0xc0) != 0x80)
+ return (wchar_t) -1;
+ }
+
+ return wc;
+}
+
+/*
+ * Determine the number of bytes needed to encode a wide character.
+ */
+static int
+xo_utf8_emit_len (wchar_t wc)
+{
+ int len;
+
+ if ((wc & ((1<<7) - 1)) == wc) /* Simple case */
+ len = 1;
+ else if ((wc & ((1<<11) - 1)) == wc)
+ len = 2;
+ else if ((wc & ((1<<16) - 1)) == wc)
+ len = 3;
+ else if ((wc & ((1<<21) - 1)) == wc)
+ len = 4;
+ else if ((wc & ((1<<26) - 1)) == wc)
+ len = 5;
+ else
+ len = 6;
+
+ return len;
+}
+
+static void
+xo_utf8_emit_char (char *buf, int len, wchar_t wc)
+{
+ int i;
+
+ if (len == 1) { /* Simple case */
+ buf[0] = wc & 0x7f;
+ return;
+ }
+
+ for (i = len - 1; i >= 0; i--) {
+ buf[i] = 0x80 | (wc & 0x3f);
+ wc >>= 6;
+ }
+
+ buf[0] &= xo_utf8_bits[len];
+ buf[0] |= ~xo_utf8_bits[len] << 1;
+}
+
+static int
+xo_buf_append_locale_from_utf8 (xo_handle_t *xop, xo_buffer_t *xbp,
+ const char *ibuf, int ilen)
+{
+ wchar_t wc;
+ int len;
+
+ /*
+ * Build our wide character from the input buffer; the number of
+ * bits we pull off the first character is dependent on the length,
+ * but we put 6 bits off all other bytes.
+ */
+ wc = xo_utf8_char(ibuf, ilen);
+ if (wc == (wchar_t) -1) {
+ xo_failure(xop, "invalid utf-8 byte sequence");
+ return 0;
+ }
+
+ if (xop->xo_flags & XOF_NO_LOCALE) {
+ if (!xo_buf_has_room(xbp, ilen))
+ return 0;
+
+ memcpy(xbp->xb_curp, ibuf, ilen);
+ xbp->xb_curp += ilen;
+
+ } else {
+ if (!xo_buf_has_room(xbp, MB_LEN_MAX + 1))
+ return 0;
+
+ bzero(&xop->xo_mbstate, sizeof(xop->xo_mbstate));
+ len = wcrtomb(xbp->xb_curp, wc, &xop->xo_mbstate);
+
+ if (len <= 0) {
+ xo_failure(xop, "could not convert wide char: %lx",
+ (unsigned long) wc);
+ return 0;
+ }
+ xbp->xb_curp += len;
+ }
+
+ return wcwidth(wc);
+}
+
+static void
+xo_buf_append_locale (xo_handle_t *xop, xo_buffer_t *xbp,
+ const char *cp, int len)
+{
+ const char *sp = cp, *ep = cp + len;
+ unsigned save_off = xbp->xb_bufp - xbp->xb_curp;
+ int slen;
+ int cols = 0;
+
+ for ( ; cp < ep; cp++) {
+ if (!xo_is_utf8(*cp)) {
+ cols += 1;
+ continue;
+ }
+
+ /*
+ * We're looking at a non-ascii UTF-8 character.
+ * First we copy the previous data.
+ * Then we need find the length and validate it.
+ * Then we turn it into a wide string.
+ * Then we turn it into a localized string.
+ * Then we repeat. Isn't i18n fun?
+ */
+ if (sp != cp)
+ xo_buf_append(xbp, sp, cp - sp); /* Append previous data */
+
+ slen = xo_buf_utf8_len(xop, cp, ep - cp);
+ if (slen <= 0) {
+ /* Bad data; back it all out */
+ xbp->xb_curp = xbp->xb_bufp + save_off;
+ return;
+ }
+
+ cols += xo_buf_append_locale_from_utf8(xop, xbp, cp, slen);
+
+ /* Next time thru, we'll start at the next character */
+ cp += slen - 1;
+ sp = cp + 1;
+ }
+
+ /* Update column values */
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += cols;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += cols;
+
+ /* Before we fall into the basic logic below, we need reset len */
+ len = ep - sp;
+ if (len != 0) /* Append trailing data */
+ xo_buf_append(xbp, sp, len);
+}
+
+/*
+ * Append the given string to the given buffer
+ */
+static void
+xo_data_append (xo_handle_t *xop, const char *str, int len)
+{
+ xo_buf_append(&xop->xo_data, str, len);
+}
+
+/*
+ * Append the given string to the given buffer
+ */
+static void
+xo_data_escape (xo_handle_t *xop, const char *str, int len)
+{
+ xo_buf_escape(xop, &xop->xo_data, str, len, 0);
+}
+
+/*
+ * Generate a warning. Normally, this is a text message written to
+ * standard error. If the XOF_WARN_XML flag is set, then we generate
+ * XMLified content on standard output.
+ */
+static void
+xo_warn_hcv (xo_handle_t *xop, int code, int check_warn,
+ const char *fmt, va_list vap)
+{
+ xop = xo_default(xop);
+ if (check_warn && !(xop->xo_flags & XOF_WARN))
+ return;
+
+ if (fmt == NULL)
+ return;
+
+ int len = strlen(fmt);
+ int plen = xo_program ? strlen(xo_program) : 0;
+ char *newfmt = alloca(len + 2 + plen + 2); /* newline, NUL, and ": " */
+
+ if (plen) {
+ memcpy(newfmt, xo_program, plen);
+ newfmt[plen++] = ':';
+ newfmt[plen++] = ' ';
+ }
+ memcpy(newfmt + plen, fmt, len);
+
+ /* Add a newline to the fmt string */
+ if (!(xop->xo_flags & XOF_WARN_XML))
+ newfmt[len++ + plen] = '\n';
+ newfmt[len + plen] = '\0';
+
+ if (xop->xo_flags & XOF_WARN_XML) {
+ static char err_open[] = "<error>";
+ static char err_close[] = "</error>";
+ static char msg_open[] = "<message>";
+ static char msg_close[] = "</message>";
+
+ xo_buffer_t *xbp = &xop->xo_data;
+
+ xo_buf_append(xbp, err_open, sizeof(err_open) - 1);
+ xo_buf_append(xbp, msg_open, sizeof(msg_open) - 1);
+
+ va_list va_local;
+ va_copy(va_local, vap);
+
+ int left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ int rc = vsnprintf(xbp->xb_curp, left, newfmt, vap);
+ if (rc > xbp->xb_size) {
+ if (!xo_buf_has_room(xbp, rc))
+ return;
+
+ va_end(vap); /* Reset vap to the start */
+ va_copy(vap, va_local);
+
+ left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ rc = vsnprintf(xbp->xb_curp, left, fmt, vap);
+ }
+ va_end(va_local);
+
+ rc = xo_escape_xml(xbp, rc, 1);
+ xbp->xb_curp += rc;
+
+ xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1);
+ xo_buf_append(xbp, err_close, sizeof(err_close) - 1);
+
+ if (code > 0) {
+ const char *msg = strerror(code);
+ if (msg) {
+ xo_buf_append(xbp, ": ", 2);
+ xo_buf_append(xbp, msg, strlen(msg));
+ }
+ }
+
+ xo_buf_append(xbp, "\n", 2); /* Append newline and NUL to string */
+ xo_write(xop);
+
+ } else {
+ vfprintf(stderr, newfmt, vap);
+ }
+}
+
+void
+xo_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(xop, code, 0, fmt, vap);
+ va_end(vap);
+}
+
+void
+xo_warn_c (int code, const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(NULL, 0, code, fmt, vap);
+ va_end(vap);
+}
+
+void
+xo_warn (const char *fmt, ...)
+{
+ int code = errno;
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(NULL, code, 0, fmt, vap);
+ va_end(vap);
+}
+
+void
+xo_warnx (const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(NULL, -1, 0, fmt, vap);
+ va_end(vap);
+}
+
+void
+xo_err (int eval, const char *fmt, ...)
+{
+ int code = errno;
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(NULL, code, 0, fmt, vap);
+ va_end(vap);
+ xo_finish();
+ exit(eval);
+}
+
+void
+xo_errx (int eval, const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(NULL, -1, 0, fmt, vap);
+ va_end(vap);
+ xo_finish();
+ exit(eval);
+}
+
+void
+xo_errc (int eval, int code, const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(NULL, code, 0, fmt, vap);
+ va_end(vap);
+ xo_finish();
+ exit(eval);
+}
+
+/*
+ * Generate a warning. Normally, this is a text message written to
+ * standard error. If the XOF_WARN_XML flag is set, then we generate
+ * XMLified content on standard output.
+ */
+void
+xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap)
+{
+ static char msg_open[] = "<message>";
+ static char msg_close[] = "</message>";
+ xo_buffer_t *xbp;
+ int rc;
+ va_list va_local;
+
+ xop = xo_default(xop);
+
+ if (fmt == NULL || *fmt == '\0')
+ return;
+
+ int need_nl = (fmt[strlen(fmt) - 1] != '\n');
+
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ xbp = &xop->xo_data;
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_buf_indent(xop, xop->xo_indent_by);
+ xo_buf_append(xbp, msg_open, sizeof(msg_open) - 1);
+
+ va_copy(va_local, vap);
+
+ int left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ rc = vsnprintf(xbp->xb_curp, left, fmt, vap);
+ if (rc > xbp->xb_size) {
+ if (!xo_buf_has_room(xbp, rc))
+ return;
+
+ va_end(vap); /* Reset vap to the start */
+ va_copy(vap, va_local);
+
+ left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ rc = vsnprintf(xbp->xb_curp, left, fmt, vap);
+ }
+ va_end(va_local);
+
+ rc = xo_escape_xml(xbp, rc, 1);
+ xbp->xb_curp += rc;
+
+ if (need_nl && code > 0) {
+ const char *msg = strerror(code);
+ if (msg) {
+ xo_buf_append(xbp, ": ", 2);
+ xo_buf_append(xbp, msg, strlen(msg));
+ }
+ }
+
+ xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1);
+ if (need_nl)
+ xo_buf_append(xbp, "\n", 2); /* Append newline and NUL to string */
+ xo_write(xop);
+ break;
+
+ case XO_STYLE_HTML:
+ {
+ char buf[BUFSIZ], *bp = buf, *cp;
+ int bufsiz = sizeof(buf);
+ int rc2;
+
+ va_copy(va_local, vap);
+
+ rc = vsnprintf(buf, bufsiz, fmt, va_local);
+ if (rc > bufsiz) {
+ bufsiz = rc + BUFSIZ;
+ bp = alloca(bufsiz);
+ va_end(va_local);
+ va_copy(va_local, vap);
+ rc = vsnprintf(buf, bufsiz, fmt, va_local);
+ }
+ cp = bp + rc;
+
+ if (need_nl) {
+ rc2 = snprintf(cp, bufsiz - rc, "%s%s\n",
+ (code > 0) ? ": " : "",
+ (code > 0) ? strerror(code) : "");
+ if (rc2 > 0)
+ rc += rc2;
+ }
+
+ xo_buf_append_div(xop, "message", 0, NULL, 0, bp, rc, NULL, 0);
+ }
+ break;
+
+ case XO_STYLE_JSON:
+ /* No meanings of representing messages in JSON */
+ break;
+
+ case XO_STYLE_TEXT:
+ rc = xo_printf_v(xop, fmt, vap);
+ /*
+ * XXX need to handle UTF-8 widths
+ */
+ if (rc > 0) {
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += rc;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += rc;
+ }
+
+ if (need_nl && code > 0) {
+ const char *msg = strerror(code);
+ if (msg) {
+ xo_printf(xop, ": %s", msg);
+ }
+ }
+ if (need_nl)
+ xo_printf(xop, "\n");
+
+ break;
+ }
+
+ xo_flush_h(xop);
+}
+
+void
+xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_message_hcv(xop, code, fmt, vap);
+ va_end(vap);
+}
+
+void
+xo_message_c (int code, const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_message_hcv(NULL, code, fmt, vap);
+ va_end(vap);
+}
+
+void
+xo_message (const char *fmt, ...)
+{
+ int code = errno;
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_message_hcv(NULL, code, fmt, vap);
+ va_end(vap);
+}
+
+static void
+xo_failure (xo_handle_t *xop, const char *fmt, ...)
+{
+ if (!(xop->xo_flags & XOF_WARN))
+ return;
+
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_warn_hcv(xop, -1, 1, fmt, vap);
+ va_end(vap);
+}
+
+/**
+ * Create a handle for use by later libxo functions.
+ *
+ * Note: normal use of libxo does not require a distinct handle, since
+ * the default handle (used when NULL is passed) generates text on stdout.
+ *
+ * @style Style of output desired (XO_STYLE_* value)
+ * @flags Set of XOF_* flags in use with this handle
+ */
+xo_handle_t *
+xo_create (xo_style_t style, xo_xof_flags_t flags)
+{
+ xo_handle_t *xop = xo_realloc(NULL, sizeof(*xop));
+
+ if (xop) {
+ bzero(xop, sizeof(*xop));
+
+ xop->xo_style = style;
+ xop->xo_flags = flags;
+ xo_init_handle(xop);
+ }
+
+ return xop;
+}
+
+/**
+ * Create a handle that will write to the given file. Use
+ * the XOF_CLOSE_FP flag to have the file closed on xo_destroy().
+ * @fp FILE pointer to use
+ * @style Style of output desired (XO_STYLE_* value)
+ * @flags Set of XOF_* flags to use with this handle
+ */
+xo_handle_t *
+xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags)
+{
+ xo_handle_t *xop = xo_create(style, flags);
+
+ if (xop) {
+ xop->xo_opaque = fp;
+ xop->xo_write = xo_write_to_file;
+ xop->xo_close = xo_close_file;
+ }
+
+ return xop;
+}
+
+/**
+ * Release any resources held by the handle.
+ * @xop XO handle to alter (or NULL for default handle)
+ */
+void
+xo_destroy (xo_handle_t *xop)
+{
+ xop = xo_default(xop);
+
+ if (xop->xo_close && (xop->xo_flags & XOF_CLOSE_FP))
+ xop->xo_close(xop->xo_opaque);
+
+ xo_free(xop->xo_stack);
+ xo_buf_cleanup(&xop->xo_data);
+ xo_buf_cleanup(&xop->xo_fmt);
+ xo_buf_cleanup(&xop->xo_predicate);
+ xo_buf_cleanup(&xop->xo_attrs);
+
+ if (xop == &xo_default_handle) {
+ bzero(&xo_default_handle, sizeof(&xo_default_handle));
+ xo_default_inited = 0;
+ } else
+ xo_free(xop);
+}
+
+/**
+ * Record a new output style to use for the given handle (or default if
+ * handle is NULL). This output style will be used for any future output.
+ *
+ * @xop XO handle to alter (or NULL for default handle)
+ * @style new output style (XO_STYLE_*)
+ */
+void
+xo_set_style (xo_handle_t *xop, xo_style_t style)
+{
+ xop = xo_default(xop);
+ xop->xo_style = style;
+}
+
+xo_style_t
+xo_get_style (xo_handle_t *xop)
+{
+ xop = xo_default(xop);
+ return xop->xo_style;
+}
+
+static int
+xo_name_to_style (const char *name)
+{
+ if (strcmp(name, "xml") == 0)
+ return XO_STYLE_XML;
+ else if (strcmp(name, "json") == 0)
+ return XO_STYLE_JSON;
+ else if (strcmp(name, "text") == 0)
+ return XO_STYLE_TEXT;
+ else if (strcmp(name, "html") == 0)
+ return XO_STYLE_HTML;
+
+ return -1;
+}
+
+/*
+ * Convert string name to XOF_* flag value.
+ * Not all are useful. Or safe. Or sane.
+ */
+static unsigned
+xo_name_to_flag (const char *name)
+{
+ if (strcmp(name, "pretty") == 0)
+ return XOF_PRETTY;
+ if (strcmp(name, "warn") == 0)
+ return XOF_WARN;
+ if (strcmp(name, "xpath") == 0)
+ return XOF_XPATH;
+ if (strcmp(name, "info") == 0)
+ return XOF_INFO;
+ if (strcmp(name, "warn-xml") == 0)
+ return XOF_WARN_XML;
+ if (strcmp(name, "columns") == 0)
+ return XOF_COLUMNS;
+ if (strcmp(name, "dtrt") == 0)
+ return XOF_DTRT;
+ if (strcmp(name, "flush") == 0)
+ return XOF_FLUSH;
+ if (strcmp(name, "keys") == 0)
+ return XOF_KEYS;
+ if (strcmp(name, "ignore-close") == 0)
+ return XOF_IGNORE_CLOSE;
+ if (strcmp(name, "not-first") == 0)
+ return XOF_NOT_FIRST;
+ if (strcmp(name, "no-locale") == 0)
+ return XOF_NO_LOCALE;
+ if (strcmp(name, "no-top") == 0)
+ return XOF_NO_TOP;
+ if (strcmp(name, "units") == 0)
+ return XOF_UNITS;
+ if (strcmp(name, "underscores") == 0)
+ return XOF_UNDERSCORES;
+
+ return 0;
+}
+
+int
+xo_set_style_name (xo_handle_t *xop, const char *name)
+{
+ if (name == NULL)
+ return -1;
+
+ int style = xo_name_to_style(name);
+ if (style < 0)
+ return -1;
+
+ xo_set_style(xop, style);
+ return 0;
+}
+
+/*
+ * Set the options for a handle using a string of options
+ * passed in. The input is a comma-separated set of names
+ * and optional values: "xml,pretty,indent=4"
+ */
+int
+xo_set_options (xo_handle_t *xop, const char *input)
+{
+ char *cp, *ep, *vp, *np, *bp;
+ int style = -1, new_style, len, rc = 0;
+ xo_xof_flags_t new_flag;
+
+ if (input == NULL)
+ return 0;
+
+ xop = xo_default(xop);
+
+ /*
+ * We support a simpler, old-school style of giving option
+ * also, using a single character for each option. It's
+ * ideal for lazy people, such as myself.
+ */
+ if (*input == ':') {
+ int sz;
+
+ for (input++ ; *input; input++) {
+ switch (*input) {
+ case 'f':
+ xop->xo_flags |= XOF_FLUSH;
+ break;
+
+ case 'H':
+ xop->xo_style = XO_STYLE_HTML;
+ break;
+
+ case 'I':
+ xop->xo_flags |= XOF_INFO;
+ break;
+
+ case 'i':
+ sz = strspn(input + 1, "0123456789");
+ if (sz > 0) {
+ xop->xo_indent_by = atoi(input + 1);
+ input += sz - 1; /* Skip value */
+ }
+ break;
+
+ case 'k':
+ xop->xo_flags |= XOF_KEYS;
+ break;
+
+ case 'J':
+ xop->xo_style = XO_STYLE_JSON;
+ break;
+
+ case 'P':
+ xop->xo_flags |= XOF_PRETTY;
+ break;
+
+ case 'T':
+ xop->xo_style = XO_STYLE_TEXT;
+ break;
+
+ case 'U':
+ xop->xo_flags |= XOF_UNITS;
+ break;
+
+ case 'u':
+ xop->xo_flags |= XOF_UNDERSCORES;
+ break;
+
+ case 'W':
+ xop->xo_flags |= XOF_WARN;
+ break;
+
+ case 'X':
+ xop->xo_style = XO_STYLE_XML;
+ break;
+
+ case 'x':
+ xop->xo_flags |= XOF_XPATH;
+ break;
+ }
+ }
+ return 0;
+ }
+
+ len = strlen(input) + 1;
+ bp = alloca(len);
+ memcpy(bp, input, len);
+
+ for (cp = bp, ep = cp + len - 1; cp && cp < ep; cp = np) {
+ np = strchr(cp, ',');
+ if (np)
+ *np++ = '\0';
+
+ vp = strchr(cp, '=');
+ if (vp)
+ *vp++ = '\0';
+
+ new_style = xo_name_to_style(cp);
+ if (new_style >= 0) {
+ if (style >= 0)
+ xo_warnx("ignoring multiple styles: '%s'", cp);
+ else
+ style = new_style;
+ } else {
+ new_flag = xo_name_to_flag(cp);
+ if (new_flag != 0)
+ xop->xo_flags |= new_flag;
+ else {
+ if (strcmp(cp, "indent") == 0) {
+ xop->xo_indent_by = atoi(vp);
+ } else {
+ xo_warnx("unknown option: '%s'", cp);
+ rc = -1;
+ }
+ }
+ }
+ }
+
+ if (style > 0)
+ xop->xo_style= style;
+
+ return rc;
+}
+
+/**
+ * Set one or more flags for a given handle (or default if handle is NULL).
+ * These flags will affect future output.
+ *
+ * @xop XO handle to alter (or NULL for default handle)
+ * @flags Flags to be set (XOF_*)
+ */
+void
+xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags)
+{
+ xop = xo_default(xop);
+
+ xop->xo_flags |= flags;
+}
+
+xo_xof_flags_t
+xo_get_flags (xo_handle_t *xop)
+{
+ xop = xo_default(xop);
+
+ return xop->xo_flags;
+}
+
+/**
+ * Record a leading prefix for the XPath we generate. This allows the
+ * generated data to be placed within an XML hierarchy but still have
+ * accurate XPath expressions.
+ *
+ * @xop XO handle to alter (or NULL for default handle)
+ * @path The XPath expression
+ */
+void
+xo_set_leading_xpath (xo_handle_t *xop, const char *path)
+{
+ xop = xo_default(xop);
+
+ if (xop->xo_leading_xpath) {
+ xo_free(xop->xo_leading_xpath);
+ xop->xo_leading_xpath = NULL;
+ }
+
+ if (path == NULL)
+ return;
+
+ int len = strlen(path);
+ xop->xo_leading_xpath = xo_realloc(NULL, len + 1);
+ if (xop->xo_leading_xpath) {
+ memcpy(xop->xo_leading_xpath, path, len + 1);
+ }
+}
+
+/**
+ * Record the info data for a set of tags
+ *
+ * @xop XO handle to alter (or NULL for default handle)
+ * @info Info data (xo_info_t) to be recorded (or NULL) (MUST BE SORTED)
+ * @count Number of entries in info (or -1 to count them ourselves)
+ */
+void
+xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count)
+{
+ xop = xo_default(xop);
+
+ if (count < 0 && infop) {
+ xo_info_t *xip;
+
+ for (xip = infop, count = 0; xip->xi_name; xip++, count++)
+ continue;
+ }
+
+ xop->xo_info = infop;
+ xop->xo_info_count = count;
+}
+
+/**
+ * Set the formatter callback for a handle. The callback should
+ * return a newly formatting contents of a formatting instruction,
+ * meaning the bits inside the braces.
+ */
+void
+xo_set_formatter (xo_handle_t *xop, xo_formatter_t func,
+ xo_checkpointer_t cfunc)
+{
+ xop = xo_default(xop);
+
+ xop->xo_formatter = func;
+ xop->xo_checkpointer = cfunc;
+}
+
+/**
+ * Clear one or more flags for a given handle (or default if handle is NULL).
+ * These flags will affect future output.
+ *
+ * @xop XO handle to alter (or NULL for default handle)
+ * @flags Flags to be cleared (XOF_*)
+ */
+void
+xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags)
+{
+ xop = xo_default(xop);
+
+ xop->xo_flags &= ~flags;
+}
+
+static void
+xo_line_ensure_open (xo_handle_t *xop, xo_xff_flags_t flags UNUSED)
+{
+ static char div_open[] = "<div class=\"line\">";
+ static char div_open_blank[] = "<div class=\"blank-line\">";
+
+ if (xop->xo_flags & XOF_DIV_OPEN)
+ return;
+
+ if (xop->xo_style != XO_STYLE_HTML)
+ return;
+
+ xop->xo_flags |= XOF_DIV_OPEN;
+ if (flags & XFF_BLANK_LINE)
+ xo_data_append(xop, div_open_blank, sizeof(div_open_blank) - 1);
+ else
+ xo_data_append(xop, div_open, sizeof(div_open) - 1);
+
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_data_append(xop, "\n", 1);
+}
+
+static void
+xo_line_close (xo_handle_t *xop)
+{
+ static char div_close[] = "</div>";
+
+ switch (xop->xo_style) {
+ case XO_STYLE_HTML:
+ if (!(xop->xo_flags & XOF_DIV_OPEN))
+ xo_line_ensure_open(xop, 0);
+
+ xop->xo_flags &= ~XOF_DIV_OPEN;
+ xo_data_append(xop, div_close, sizeof(div_close) - 1);
+
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_data_append(xop, "\n", 1);
+ break;
+
+ case XO_STYLE_TEXT:
+ xo_data_append(xop, "\n", 1);
+ break;
+ }
+}
+
+static int
+xo_info_compare (const void *key, const void *data)
+{
+ const char *name = key;
+ const xo_info_t *xip = data;
+
+ return strcmp(name, xip->xi_name);
+}
+
+
+static xo_info_t *
+xo_info_find (xo_handle_t *xop, const char *name, int nlen)
+{
+ xo_info_t *xip;
+ char *cp = alloca(nlen + 1); /* Need local copy for NUL termination */
+
+ memcpy(cp, name, nlen);
+ cp[nlen] = '\0';
+
+ xip = bsearch(cp, xop->xo_info, xop->xo_info_count,
+ sizeof(xop->xo_info[0]), xo_info_compare);
+ return xip;
+}
+
+#define CONVERT(_have, _need) (((_have) << 8) | (_need))
+
+/*
+ * Check to see that the conversion is safe and sane.
+ */
+static int
+xo_check_conversion (xo_handle_t *xop, int have_enc, int need_enc)
+{
+ switch (CONVERT(have_enc, need_enc)) {
+ case CONVERT(XF_ENC_UTF8, XF_ENC_UTF8):
+ case CONVERT(XF_ENC_UTF8, XF_ENC_LOCALE):
+ case CONVERT(XF_ENC_WIDE, XF_ENC_UTF8):
+ case CONVERT(XF_ENC_WIDE, XF_ENC_LOCALE):
+ case CONVERT(XF_ENC_LOCALE, XF_ENC_LOCALE):
+ case CONVERT(XF_ENC_LOCALE, XF_ENC_UTF8):
+ return 0;
+
+ default:
+ xo_failure(xop, "invalid conversion (%c:%c)", have_enc, need_enc);
+ return 1;
+ }
+}
+
+static int
+xo_format_string_direct (xo_handle_t *xop, xo_buffer_t *xbp,
+ xo_xff_flags_t flags,
+ const wchar_t *wcp, const char *cp, int len, int max,
+ int need_enc, int have_enc)
+{
+ int cols = 0;
+ wchar_t wc;
+ int ilen, olen, width;
+ int attr = (flags & XFF_ATTR);
+ const char *sp;
+
+ if (len > 0 && !xo_buf_has_room(xbp, len))
+ return 0;
+
+ for (;;) {
+ if (len == 0)
+ break;
+
+ if (cp) {
+ if (*cp == '\0')
+ break;
+ if ((flags & XFF_UNESCAPE) && (*cp == '\\' || *cp == '%')) {
+ cp += 1;
+ len -= 1;
+ }
+ }
+
+ if (wcp && *wcp == L'\0')
+ break;
+
+ ilen = 0;
+
+ switch (have_enc) {
+ case XF_ENC_WIDE: /* Wide character */
+ wc = *wcp++;
+ ilen = 1;
+ break;
+
+ case XF_ENC_UTF8: /* UTF-8 */
+ ilen = xo_utf8_to_wc_len(cp);
+ if (ilen < 0) {
+ xo_failure(xop, "invalid UTF-8 character: %02hhx", *cp);
+ return -1;
+ }
+
+ if (len > 0 && len < ilen) {
+ len = 0; /* Break out of the loop */
+ continue;
+ }
+
+ wc = xo_utf8_char(cp, ilen);
+ if (wc == (wchar_t) -1) {
+ xo_failure(xop, "invalid UTF-8 character: %02hhx/%d",
+ *cp, ilen);
+ return -1;
+ }
+ cp += ilen;
+ break;
+
+ case XF_ENC_LOCALE: /* Native locale */
+ ilen = (len > 0) ? len : MB_LEN_MAX;
+ ilen = mbrtowc(&wc, cp, ilen, &xop->xo_mbstate);
+ if (ilen < 0) { /* Invalid data; skip */
+ xo_failure(xop, "invalid mbs char: %02hhx", *cp);
+ continue;
+ }
+ if (ilen == 0) { /* Hit a wide NUL character */
+ len = 0;
+ continue;
+ }
+
+ cp += ilen;
+ break;
+ }
+
+ /* Reduce len, but not below zero */
+ if (len > 0) {
+ len -= ilen;
+ if (len < 0)
+ len = 0;
+ }
+
+ /*
+ * Find the width-in-columns of this character, which must be done
+ * in wide characters, since we lack a mbswidth() function. If
+ * it doesn't fit
+ */
+ width = wcwidth(wc);
+ if (width < 0)
+ width = iswcntrl(wc) ? 0 : 1;
+
+ if (xop->xo_style == XO_STYLE_TEXT || xop->xo_style == XO_STYLE_HTML) {
+ if (max > 0 && cols + width > max)
+ break;
+ }
+
+ switch (need_enc) {
+ case XF_ENC_UTF8:
+
+ /* Output in UTF-8 needs to be escaped, based on the style */
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ case XO_STYLE_HTML:
+ if (wc == '<')
+ sp = xo_xml_lt;
+ else if (wc == '>')
+ sp = xo_xml_gt;
+ else if (wc == '&')
+ sp = xo_xml_amp;
+ else if (attr && wc == '"')
+ sp = xo_xml_quot;
+ else
+ break;
+
+ int slen = strlen(sp);
+ if (!xo_buf_has_room(xbp, slen - 1))
+ return -1;
+
+ memcpy(xbp->xb_curp, sp, slen);
+ xbp->xb_curp += slen;
+ goto done_with_encoding; /* Need multi-level 'break' */
+
+ case XO_STYLE_JSON:
+ if (wc != '\\' && wc != '"')
+ break;
+
+ if (!xo_buf_has_room(xbp, 2))
+ return -1;
+
+ *xbp->xb_curp++ = '\\';
+ *xbp->xb_curp++ = wc & 0x7f;
+ goto done_with_encoding;
+ }
+
+ olen = xo_utf8_emit_len(wc);
+ if (olen < 0) {
+ xo_failure(xop, "ignoring bad length");
+ continue;
+ }
+
+ if (!xo_buf_has_room(xbp, olen))
+ return -1;
+
+ xo_utf8_emit_char(xbp->xb_curp, olen, wc);
+ xbp->xb_curp += olen;
+ break;
+
+ case XF_ENC_LOCALE:
+ if (!xo_buf_has_room(xbp, MB_LEN_MAX + 1))
+ return -1;
+
+ olen = wcrtomb(xbp->xb_curp, wc, &xop->xo_mbstate);
+ if (olen <= 0) {
+ xo_failure(xop, "could not convert wide char: %lx",
+ (unsigned long) wc);
+ olen = 1;
+ width = 1;
+ *xbp->xb_curp++ = '?';
+ } else
+ xbp->xb_curp += olen;
+ break;
+ }
+
+ done_with_encoding:
+ cols += width;
+ }
+
+ return cols;
+}
+
+static int
+xo_format_string (xo_handle_t *xop, xo_buffer_t *xbp, xo_xff_flags_t flags,
+ xo_format_t *xfp)
+{
+ static char null[] = "(null)";
+ char *cp = NULL;
+ wchar_t *wcp = NULL;
+ int len, cols = 0, rc = 0;
+ int off = xbp->xb_curp - xbp->xb_bufp, off2;
+ int need_enc = (xop->xo_style == XO_STYLE_TEXT)
+ ? XF_ENC_LOCALE : XF_ENC_UTF8;
+
+ if (xo_check_conversion(xop, xfp->xf_enc, need_enc))
+ return 0;
+
+ if (xfp->xf_enc == XF_ENC_WIDE) {
+ wcp = va_arg(xop->xo_vap, wchar_t *);
+ if (xfp->xf_skip)
+ return 0;
+
+ } else {
+ cp = va_arg(xop->xo_vap, char *); /* UTF-8 or native */
+ if (xfp->xf_skip)
+ return 0;
+
+ /*
+ * Optimize the most common case, which is "%s". We just
+ * need to copy the complete string to the output buffer.
+ */
+ if (xfp->xf_enc == need_enc
+ && xfp->xf_width[XF_WIDTH_MIN] < 0
+ && xfp->xf_width[XF_WIDTH_SIZE] < 0
+ && xfp->xf_width[XF_WIDTH_MAX] < 0
+ && !(xop->xo_flags & (XOF_ANCHOR | XOF_COLUMNS))) {
+ len = strlen(cp);
+ xo_buf_escape(xop, xbp, cp, len, flags);
+
+ /*
+ * Our caller expects xb_curp left untouched, so we have
+ * to reset it and return the number of bytes written to
+ * the buffer.
+ */
+ off2 = xbp->xb_curp - xbp->xb_bufp;
+ rc = off2 - off;
+ xbp->xb_curp = xbp->xb_bufp + off;
+
+ return rc;
+ }
+ }
+
+ len = xfp->xf_width[XF_WIDTH_SIZE];
+
+ /*
+ * Dont' deref NULL; use the traditional "(null)" instead
+ * of the more accurate "who's been a naughty boy, then?".
+ */
+ if (cp == NULL && wcp == NULL) {
+ cp = null;
+ len = sizeof(null) - 1;
+ }
+
+ cols = xo_format_string_direct(xop, xbp, flags, wcp, cp, len,
+ xfp->xf_width[XF_WIDTH_MAX],
+ need_enc, xfp->xf_enc);
+ if (cols < 0)
+ goto bail;
+
+ /*
+ * xo_buf_append* will move xb_curp, so we save/restore it.
+ */
+ off2 = xbp->xb_curp - xbp->xb_bufp;
+ rc = off2 - off;
+ xbp->xb_curp = xbp->xb_bufp + off;
+
+ if (cols < xfp->xf_width[XF_WIDTH_MIN]) {
+ /*
+ * Find the number of columns needed to display the string.
+ * If we have the original wide string, we just call wcswidth,
+ * but if we did the work ourselves, then we need to do it.
+ */
+ int delta = xfp->xf_width[XF_WIDTH_MIN] - cols;
+ if (!xo_buf_has_room(xbp, delta))
+ goto bail;
+
+ /*
+ * If seen_minus, then pad on the right; otherwise move it so
+ * we can pad on the left.
+ */
+ if (xfp->xf_seen_minus) {
+ cp = xbp->xb_curp + rc;
+ } else {
+ cp = xbp->xb_curp;
+ memmove(xbp->xb_curp + delta, xbp->xb_curp, rc);
+ }
+
+ /* Set the padding */
+ memset(cp, (xfp->xf_leading_zero > 0) ? '0' : ' ', delta);
+ rc += delta;
+ cols += delta;
+ }
+
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += cols;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += cols;
+
+ return rc;
+
+ bail:
+ xbp->xb_curp = xbp->xb_bufp + off;
+ return 0;
+}
+
+static void
+xo_data_append_content (xo_handle_t *xop, const char *str, int len)
+{
+ int cols;
+ int need_enc = (xop->xo_style == XO_STYLE_TEXT)
+ ? XF_ENC_LOCALE : XF_ENC_UTF8;
+
+ cols = xo_format_string_direct(xop, &xop->xo_data, XFF_UNESCAPE,
+ NULL, str, len, -1,
+ need_enc, XF_ENC_UTF8);
+
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += cols;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += cols;
+}
+
+static void
+xo_bump_width (xo_format_t *xfp, int digit)
+{
+ int *ip = &xfp->xf_width[xfp->xf_dots];
+
+ *ip = ((*ip > 0) ? *ip : 0) * 10 + digit;
+}
+
+static int
+xo_trim_ws (xo_buffer_t *xbp, int len)
+{
+ char *cp, *sp, *ep;
+ int delta;
+
+ /* First trim leading space */
+ for (cp = sp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) {
+ if (*cp != ' ')
+ break;
+ }
+
+ delta = cp - sp;
+ if (delta) {
+ len -= delta;
+ memmove(sp, cp, len);
+ }
+
+ /* Then trim off the end */
+ for (cp = xbp->xb_curp, sp = ep = cp + len; cp < ep; ep--) {
+ if (ep[-1] != ' ')
+ break;
+ }
+
+ delta = sp - ep;
+ if (delta) {
+ len -= delta;
+ cp[len] = '\0';
+ }
+
+ return len;
+}
+
+static int
+xo_format_data (xo_handle_t *xop, xo_buffer_t *xbp,
+ const char *fmt, int flen, xo_xff_flags_t flags)
+{
+ xo_format_t xf;
+ const char *cp, *ep, *sp, *xp = NULL;
+ int rc, cols;
+ int style = (flags & XFF_XML) ? XO_STYLE_XML : xop->xo_style;
+ unsigned make_output = !(flags & XFF_NO_OUTPUT);
+ int need_enc = (xop->xo_style == XO_STYLE_TEXT)
+ ? XF_ENC_LOCALE : XF_ENC_UTF8;
+
+ if (xbp == NULL)
+ xbp = &xop->xo_data;
+
+ for (cp = fmt, ep = fmt + flen; cp < ep; cp++) {
+ if (*cp != '%') {
+ add_one:
+ if (xp == NULL)
+ xp = cp;
+
+ if (*cp == '\\' && cp[1] != '\0')
+ cp += 1;
+ continue;
+
+ } if (cp + 1 < ep && cp[1] == '%') {
+ cp += 1;
+ goto add_one;
+ }
+
+ if (xp) {
+ if (make_output) {
+ cols = xo_format_string_direct(xop, xbp, flags | XFF_UNESCAPE,
+ NULL, xp, cp - xp, -1,
+ need_enc, XF_ENC_UTF8);
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += cols;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += cols;
+ }
+
+ xp = NULL;
+ }
+
+ bzero(&xf, sizeof(xf));
+ xf.xf_leading_zero = -1;
+ xf.xf_width[0] = xf.xf_width[1] = xf.xf_width[2] = -1;
+
+ /*
+ * "%@" starts an XO-specific set of flags:
+ * @X@ - XML-only field; ignored if style isn't XML
+ */
+ if (cp[1] == '@') {
+ for (cp += 2; cp < ep; cp++) {
+ if (*cp == '@') {
+ break;
+ }
+ if (*cp == '*') {
+ /*
+ * '*' means there's a "%*.*s" value in vap that
+ * we want to ignore
+ */
+ if (!(xop->xo_flags & XOF_NO_VA_ARG))
+ va_arg(xop->xo_vap, int);
+ }
+ }
+ }
+
+ /* Hidden fields are only visible to JSON and XML */
+ if (xop->xo_flags & XFF_ENCODE_ONLY) {
+ if (style != XO_STYLE_XML
+ && xop->xo_style != XO_STYLE_JSON)
+ xf.xf_skip = 1;
+ } else if (xop->xo_flags & XFF_DISPLAY_ONLY) {
+ if (style != XO_STYLE_TEXT
+ && xop->xo_style != XO_STYLE_HTML)
+ xf.xf_skip = 1;
+ }
+
+ if (!make_output)
+ xf.xf_skip = 1;
+
+ /*
+ * Looking at one piece of a format; find the end and
+ * call snprintf. Then advance xo_vap on our own.
+ *
+ * Note that 'n', 'v', and '$' are not supported.
+ */
+ sp = cp; /* Save start pointer */
+ for (cp += 1; cp < ep; cp++) {
+ if (*cp == 'l')
+ xf.xf_lflag += 1;
+ else if (*cp == 'h')
+ xf.xf_hflag += 1;
+ else if (*cp == 'j')
+ xf.xf_jflag += 1;
+ else if (*cp == 't')
+ xf.xf_tflag += 1;
+ else if (*cp == 'z')
+ xf.xf_zflag += 1;
+ else if (*cp == 'q')
+ xf.xf_qflag += 1;
+ else if (*cp == '.') {
+ if (++xf.xf_dots >= XF_WIDTH_NUM) {
+ xo_failure(xop, "Too many dots in format: '%s'", fmt);
+ return -1;
+ }
+ } else if (*cp == '-')
+ xf.xf_seen_minus = 1;
+ else if (isdigit((int) *cp)) {
+ if (xf.xf_leading_zero < 0)
+ xf.xf_leading_zero = (*cp == '0');
+ xo_bump_width(&xf, *cp - '0');
+ } else if (*cp == '*') {
+ xf.xf_stars += 1;
+ xf.xf_star[xf.xf_dots] = 1;
+ } else if (strchr("diouxXDOUeEfFgGaAcCsSp", *cp) != NULL)
+ break;
+ else if (*cp == 'n' || *cp == 'v') {
+ xo_failure(xop, "unsupported format: '%s'", fmt);
+ return -1;
+ }
+ }
+
+ if (cp == ep)
+ xo_failure(xop, "field format missing format character: %s",
+ fmt);
+
+ xf.xf_fc = *cp;
+
+ if (!(xop->xo_flags & XOF_NO_VA_ARG)) {
+ if (*cp == 's' || *cp == 'S') {
+ /* Handle "%*.*.*s" */
+ int s;
+ for (s = 0; s < XF_WIDTH_NUM; s++) {
+ if (xf.xf_star[s]) {
+ xf.xf_width[s] = va_arg(xop->xo_vap, int);
+
+ /* Normalize a negative width value */
+ if (xf.xf_width[s] < 0) {
+ if (s == 0) {
+ xf.xf_width[0] = -xf.xf_width[0];
+ xf.xf_seen_minus = 1;
+ } else
+ xf.xf_width[s] = -1; /* Ignore negative values */
+ }
+ }
+ }
+ }
+ }
+
+ /* If no max is given, it defaults to size */
+ if (xf.xf_width[XF_WIDTH_MAX] < 0 && xf.xf_width[XF_WIDTH_SIZE] >= 0)
+ xf.xf_width[XF_WIDTH_MAX] = xf.xf_width[XF_WIDTH_SIZE];
+
+ if (xf.xf_fc == 'D' || xf.xf_fc == 'O' || xf.xf_fc == 'U')
+ xf.xf_lflag = 1;
+
+ if (!xf.xf_skip) {
+ xo_buffer_t *fbp = &xop->xo_fmt;
+ int len = cp - sp + 1;
+ if (!xo_buf_has_room(fbp, len + 1))
+ return -1;
+
+ char *newfmt = fbp->xb_curp;
+ memcpy(newfmt, sp, len);
+ newfmt[0] = '%'; /* If we skipped over a "%@...@s" format */
+ newfmt[len] = '\0';
+
+ /*
+ * Bad news: our strings are UTF-8, but the stock printf
+ * functions won't handle field widths for wide characters
+ * correctly. So we have to handle this ourselves.
+ */
+ if (xop->xo_formatter == NULL
+ && (xf.xf_fc == 's' || xf.xf_fc == 'S')) {
+ xf.xf_enc = (xf.xf_lflag || (xf.xf_fc == 'S'))
+ ? XF_ENC_WIDE : xf.xf_hflag ? XF_ENC_LOCALE : XF_ENC_UTF8;
+ rc = xo_format_string(xop, xbp, flags, &xf);
+
+ if ((flags & XFF_TRIM_WS)
+ && (xop->xo_style == XO_STYLE_XML
+ || xop->xo_style == XO_STYLE_JSON))
+ rc = xo_trim_ws(xbp, rc);
+
+ } else {
+ int columns = rc = xo_vsnprintf(xop, xbp, newfmt, xop->xo_vap);
+
+ /*
+ * For XML and HTML, we need "&<>" processing; for JSON,
+ * it's quotes. Text gets nothing.
+ */
+ switch (style) {
+ case XO_STYLE_XML:
+ if (flags & XFF_TRIM_WS)
+ columns = rc = xo_trim_ws(xbp, rc);
+ /* fall thru */
+ case XO_STYLE_HTML:
+ rc = xo_escape_xml(xbp, rc, (flags & XFF_ATTR));
+ break;
+
+ case XO_STYLE_JSON:
+ if (flags & XFF_TRIM_WS)
+ columns = rc = xo_trim_ws(xbp, rc);
+ rc = xo_escape_json(xbp, rc);
+ break;
+ }
+
+ /*
+ * We can assume all the data we've added is ASCII, so
+ * the columns and bytes are the same. xo_format_string
+ * handles all the fancy string conversions and updates
+ * xo_anchor_columns accordingly.
+ */
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += columns;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += columns;
+ }
+
+ xbp->xb_curp += rc;
+ }
+
+ /*
+ * Now for the tricky part: we need to move the argument pointer
+ * along by the amount needed.
+ */
+ if (!(xop->xo_flags & XOF_NO_VA_ARG)) {
+
+ if (xf.xf_fc == 's' ||xf.xf_fc == 'S') {
+ /*
+ * The 'S' and 's' formats are normally handled in
+ * xo_format_string, but if we skipped it, then we
+ * need to pop it.
+ */
+ if (xf.xf_skip)
+ va_arg(xop->xo_vap, char *);
+
+ } else {
+ int s;
+ for (s = 0; s < XF_WIDTH_NUM; s++) {
+ if (xf.xf_star[s])
+ va_arg(xop->xo_vap, int);
+ }
+
+ if (strchr("diouxXDOU", xf.xf_fc) != NULL) {
+ if (xf.xf_hflag > 1) {
+ va_arg(xop->xo_vap, int);
+
+ } else if (xf.xf_hflag > 0) {
+ va_arg(xop->xo_vap, int);
+
+ } else if (xf.xf_lflag > 1) {
+ va_arg(xop->xo_vap, unsigned long long);
+
+ } else if (xf.xf_lflag > 0) {
+ va_arg(xop->xo_vap, unsigned long);
+
+ } else if (xf.xf_jflag > 0) {
+ va_arg(xop->xo_vap, intmax_t);
+
+ } else if (xf.xf_tflag > 0) {
+ va_arg(xop->xo_vap, ptrdiff_t);
+
+ } else if (xf.xf_zflag > 0) {
+ va_arg(xop->xo_vap, size_t);
+
+ } else if (xf.xf_qflag > 0) {
+ va_arg(xop->xo_vap, quad_t);
+
+ } else {
+ va_arg(xop->xo_vap, int);
+ }
+ } else if (strchr("eEfFgGaA", xf.xf_fc) != NULL)
+ if (xf.xf_lflag)
+ va_arg(xop->xo_vap, long double);
+ else
+ va_arg(xop->xo_vap, double);
+
+ else if (xf.xf_fc == 'C' || (xf.xf_fc == 'c' && xf.xf_lflag))
+ va_arg(xop->xo_vap, wint_t);
+
+ else if (xf.xf_fc == 'c')
+ va_arg(xop->xo_vap, int);
+
+ else if (xf.xf_fc == 'p')
+ va_arg(xop->xo_vap, void *);
+ }
+ }
+ }
+
+ if (xp) {
+ if (make_output) {
+ cols = xo_format_string_direct(xop, xbp, flags | XFF_UNESCAPE,
+ NULL, xp, cp - xp, -1,
+ need_enc, XF_ENC_UTF8);
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += cols;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += cols;
+ }
+
+ xp = NULL;
+ }
+
+ return 0;
+}
+
+static char *
+xo_fix_encoding (xo_handle_t *xop UNUSED, char *encoding)
+{
+ char *cp = encoding;
+
+ if (cp[0] != '%' || !isdigit((int) cp[1]))
+ return encoding;
+
+ for (cp += 2; *cp; cp++) {
+ if (!isdigit((int) *cp))
+ break;
+ }
+
+ cp -= 1;
+ *cp = '%';
+
+ return cp;
+}
+
+static void
+xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags,
+ const char *name, int nlen,
+ const char *value, int vlen,
+ const char *encoding, int elen)
+{
+ static char div_start[] = "<div class=\"";
+ static char div_tag[] = "\" data-tag=\"";
+ static char div_xpath[] = "\" data-xpath=\"";
+ static char div_key[] = "\" data-key=\"key";
+ static char div_end[] = "\">";
+ static char div_close[] = "</div>";
+
+ /*
+ * To build our XPath predicate, we need to save the va_list before
+ * we format our data, and then restore it before we format the
+ * xpath expression.
+ * Display-only keys implies that we've got an encode-only key
+ * elsewhere, so we don't use them from making predicates.
+ */
+ int need_predidate =
+ (name && (flags & XFF_KEY) && !(flags & XFF_DISPLAY_ONLY)
+ && (xop->xo_flags & XOF_XPATH));
+
+ if (need_predidate) {
+ va_list va_local;
+
+ va_copy(va_local, xop->xo_vap);
+ if (xop->xo_checkpointer)
+ xop->xo_checkpointer(xop, xop->xo_vap, 0);
+
+ /*
+ * Build an XPath predicate expression to match this key.
+ * We use the format buffer.
+ */
+ xo_buffer_t *pbp = &xop->xo_predicate;
+ pbp->xb_curp = pbp->xb_bufp; /* Restart buffer */
+
+ xo_buf_append(pbp, "[", 1);
+ xo_buf_escape(xop, pbp, name, nlen, 0);
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_buf_append(pbp, " = '", 4);
+ else
+ xo_buf_append(pbp, "='", 2);
+
+ /* The encoding format defaults to the normal format */
+ if (encoding == NULL) {
+ char *enc = alloca(vlen + 1);
+ memcpy(enc, value, vlen);
+ enc[vlen] = '\0';
+ encoding = xo_fix_encoding(xop, enc);
+ elen = strlen(encoding);
+ }
+
+ xo_format_data(xop, pbp, encoding, elen, XFF_XML | XFF_ATTR);
+
+ xo_buf_append(pbp, "']", 2);
+
+ /* Now we record this predicate expression in the stack */
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+ int olen = xsp->xs_keys ? strlen(xsp->xs_keys) : 0;
+ int dlen = pbp->xb_curp - pbp->xb_bufp;
+
+ char *cp = xo_realloc(xsp->xs_keys, olen + dlen + 1);
+ if (cp) {
+ memcpy(cp + olen, pbp->xb_bufp, dlen);
+ cp[olen + dlen] = '\0';
+ xsp->xs_keys = cp;
+ }
+
+ /* Now we reset the xo_vap as if we were never here */
+ va_end(xop->xo_vap);
+ va_copy(xop->xo_vap, va_local);
+ va_end(va_local);
+ if (xop->xo_checkpointer)
+ xop->xo_checkpointer(xop, xop->xo_vap, 1);
+ }
+
+ if (flags & XFF_ENCODE_ONLY) {
+ /*
+ * Even if this is encode-only, we need to go thru the
+ * work of formatting it to make sure the args are cleared
+ * from xo_vap.
+ */
+ xo_format_data(xop, &xop->xo_data, encoding, elen,
+ flags | XFF_NO_OUTPUT);
+ return;
+ }
+
+ xo_line_ensure_open(xop, 0);
+
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_buf_indent(xop, xop->xo_indent_by);
+
+ xo_data_append(xop, div_start, sizeof(div_start) - 1);
+ xo_data_append(xop, class, strlen(class));
+
+ if (name) {
+ xo_data_append(xop, div_tag, sizeof(div_tag) - 1);
+ xo_data_escape(xop, name, nlen);
+
+ /*
+ * Save the offset at which we'd place units. See xo_format_units.
+ */
+ if (xop->xo_flags & XOF_UNITS) {
+ xop->xo_flags |= XOF_UNITS_PENDING;
+ /*
+ * Note: We need the '+1' here because we know we've not
+ * added the closing quote. We add one, knowing the quote
+ * will be added shortly.
+ */
+ xop->xo_units_offset =
+ xop->xo_data.xb_curp -xop->xo_data.xb_bufp + 1;
+ }
+ }
+
+ if (name) {
+ if (xop->xo_flags & XOF_XPATH) {
+ int i;
+ xo_stack_t *xsp;
+
+ xo_data_append(xop, div_xpath, sizeof(div_xpath) - 1);
+ if (xop->xo_leading_xpath)
+ xo_data_append(xop, xop->xo_leading_xpath,
+ strlen(xop->xo_leading_xpath));
+
+ for (i = 0; i <= xop->xo_depth; i++) {
+ xsp = &xop->xo_stack[i];
+ if (xsp->xs_name == NULL)
+ continue;
+
+ xo_data_append(xop, "/", 1);
+ xo_data_escape(xop, xsp->xs_name, strlen(xsp->xs_name));
+ if (xsp->xs_keys) {
+ /* Don't show keys for the key field */
+ if (i != xop->xo_depth || !(flags & XFF_KEY))
+ xo_data_append(xop, xsp->xs_keys, strlen(xsp->xs_keys));
+ }
+ }
+
+ xo_data_append(xop, "/", 1);
+ xo_data_escape(xop, name, nlen);
+ }
+
+ if ((xop->xo_flags & XOF_INFO) && xop->xo_info) {
+ static char in_type[] = "\" data-type=\"";
+ static char in_help[] = "\" data-help=\"";
+
+ xo_info_t *xip = xo_info_find(xop, name, nlen);
+ if (xip) {
+ if (xip->xi_type) {
+ xo_data_append(xop, in_type, sizeof(in_type) - 1);
+ xo_data_escape(xop, xip->xi_type, strlen(xip->xi_type));
+ }
+ if (xip->xi_help) {
+ xo_data_append(xop, in_help, sizeof(in_help) - 1);
+ xo_data_escape(xop, xip->xi_help, strlen(xip->xi_help));
+ }
+ }
+ }
+
+ if ((flags & XFF_KEY) && (xop->xo_flags & XOF_KEYS))
+ xo_data_append(xop, div_key, sizeof(div_key) - 1);
+ }
+
+ xo_data_append(xop, div_end, sizeof(div_end) - 1);
+
+ xo_format_data(xop, NULL, value, vlen, 0);
+
+ xo_data_append(xop, div_close, sizeof(div_close) - 1);
+
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_data_append(xop, "\n", 1);
+}
+
+static void
+xo_format_text (xo_handle_t *xop, const char *str, int len)
+{
+ switch (xop->xo_style) {
+ case XO_STYLE_TEXT:
+ xo_buf_append_locale(xop, &xop->xo_data, str, len);
+ break;
+
+ case XO_STYLE_HTML:
+ xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0);
+ break;
+ }
+}
+
+static void
+xo_format_title (xo_handle_t *xop, const char *str, int len,
+ const char *fmt, int flen)
+{
+ static char div_open[] = "<div class=\"title\">";
+ static char div_close[] = "</div>";
+
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ case XO_STYLE_JSON:
+ /*
+ * Even though we don't care about text, we need to do
+ * enough parsing work to skip over the right bits of xo_vap.
+ */
+ if (len == 0)
+ xo_format_data(xop, NULL, fmt, flen, XFF_NO_OUTPUT);
+ return;
+ }
+
+ xo_buffer_t *xbp = &xop->xo_data;
+ int start = xbp->xb_curp - xbp->xb_bufp;
+ int left = xbp->xb_size - start;
+ int rc;
+ int need_enc = XF_ENC_LOCALE;
+
+ if (xop->xo_style == XO_STYLE_HTML) {
+ need_enc = XF_ENC_UTF8;
+ xo_line_ensure_open(xop, 0);
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_buf_indent(xop, xop->xo_indent_by);
+ xo_buf_append(&xop->xo_data, div_open, sizeof(div_open) - 1);
+ }
+
+ start = xbp->xb_curp - xbp->xb_bufp; /* Reset start */
+ if (len) {
+ char *newfmt = alloca(flen + 1);
+ memcpy(newfmt, fmt, flen);
+ newfmt[flen] = '\0';
+
+ /* If len is non-zero, the format string apply to the name */
+ char *newstr = alloca(len + 1);
+ memcpy(newstr, str, len);
+ newstr[len] = '\0';
+
+ if (newstr[len - 1] == 's') {
+ int cols;
+ char *bp;
+
+ rc = snprintf(NULL, 0, newfmt, newstr);
+ if (rc > 0) {
+ /*
+ * We have to do this the hard way, since we might need
+ * the columns.
+ */
+ bp = alloca(rc + 1);
+ rc = snprintf(bp, rc + 1, newfmt, newstr);
+ cols = xo_format_string_direct(xop, xbp, 0, NULL, bp, rc, -1,
+ need_enc, XF_ENC_UTF8);
+ if (cols > 0) {
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += cols;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += cols;
+ }
+ }
+ goto move_along;
+
+ } else {
+ rc = snprintf(xbp->xb_curp, left, newfmt, newstr);
+ if (rc > left) {
+ if (!xo_buf_has_room(xbp, rc))
+ return;
+ left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp);
+ rc = snprintf(xbp->xb_curp, left, newfmt, newstr);
+ }
+
+ if (rc > 0) {
+ if (xop->xo_flags & XOF_COLUMNS)
+ xop->xo_columns += rc;
+ if (xop->xo_flags & XOF_ANCHOR)
+ xop->xo_anchor_columns += rc;
+ }
+ }
+
+ } else {
+ xo_format_data(xop, NULL, fmt, flen, 0);
+
+ /* xo_format_data moved curp, so we need to reset it */
+ rc = xbp->xb_curp - (xbp->xb_bufp + start);
+ xbp->xb_curp = xbp->xb_bufp + start;
+ }
+
+ /* If we're styling HTML, then we need to escape it */
+ if (xop->xo_style == XO_STYLE_HTML) {
+ rc = xo_escape_xml(xbp, rc, 0);
+ }
+
+ if (rc > 0)
+ xbp->xb_curp += rc;
+
+ move_along:
+ if (xop->xo_style == XO_STYLE_HTML) {
+ xo_data_append(xop, div_close, sizeof(div_close) - 1);
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_data_append(xop, "\n", 1);
+ }
+}
+
+static void
+xo_format_prep (xo_handle_t *xop, xo_xff_flags_t flags)
+{
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) {
+ xo_data_append(xop, ",", 1);
+ if (!(flags & XFF_LEAF_LIST) && (xop->xo_flags & XOF_PRETTY))
+ xo_data_append(xop, "\n", 1);
+ } else
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+}
+
+#if 0
+/* Useful debugging function */
+void
+xo_arg (xo_handle_t *xop);
+void
+xo_arg (xo_handle_t *xop)
+{
+ xop = xo_default(xop);
+ fprintf(stderr, "0x%x", va_arg(xop->xo_vap, unsigned));
+}
+#endif /* 0 */
+
+static void
+xo_format_value (xo_handle_t *xop, const char *name, int nlen,
+ const char *format, int flen,
+ const char *encoding, int elen, xo_xff_flags_t flags)
+{
+ int pretty = (xop->xo_flags & XOF_PRETTY);
+ int quote;
+ xo_buffer_t *xbp;
+
+ switch (xop->xo_style) {
+ case XO_STYLE_TEXT:
+ if (flags & XFF_ENCODE_ONLY)
+ flags |= XFF_NO_OUTPUT;
+ xo_format_data(xop, NULL, format, flen, flags);
+ break;
+
+ case XO_STYLE_HTML:
+ if (flags & XFF_ENCODE_ONLY)
+ flags |= XFF_NO_OUTPUT;
+ xo_buf_append_div(xop, "data", flags, name, nlen,
+ format, flen, encoding, elen);
+ break;
+
+ case XO_STYLE_XML:
+ /*
+ * Even though we're not making output, we still need to
+ * let the formatting code handle the va_arg popping.
+ */
+ if (flags & XFF_DISPLAY_ONLY) {
+ flags |= XFF_NO_OUTPUT;
+ xo_format_data(xop, NULL, format, flen, flags);
+ break;
+ }
+
+ if (encoding) {
+ format = encoding;
+ flen = elen;
+ } else {
+ char *enc = alloca(flen + 1);
+ memcpy(enc, format, flen);
+ enc[flen] = '\0';
+ format = xo_fix_encoding(xop, enc);
+ flen = strlen(format);
+ }
+
+ if (nlen == 0) {
+ static char missing[] = "missing-field-name";
+ xo_failure(xop, "missing field name: %s", format);
+ name = missing;
+ nlen = sizeof(missing) - 1;
+ }
+
+ if (pretty)
+ xo_buf_indent(xop, -1);
+ xo_data_append(xop, "<", 1);
+ xo_data_escape(xop, name, nlen);
+
+ if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) {
+ xo_data_append(xop, xop->xo_attrs.xb_bufp,
+ xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp);
+ xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp;
+ }
+
+ /*
+ * We indicate 'key' fields using the 'key' attribute. While
+ * this is really committing the crime of mixing meta-data with
+ * data, it's often useful. Especially when format meta-data is
+ * difficult to come by.
+ */
+ if ((flags & XFF_KEY) && (xop->xo_flags & XOF_KEYS)) {
+ static char attr[] = " key=\"key\"";
+ xo_data_append(xop, attr, sizeof(attr) - 1);
+ }
+
+ /*
+ * Save the offset at which we'd place units. See xo_format_units.
+ */
+ if (xop->xo_flags & XOF_UNITS) {
+ xop->xo_flags |= XOF_UNITS_PENDING;
+ xop->xo_units_offset = xop->xo_data.xb_curp -xop->xo_data.xb_bufp;
+ }
+
+ xo_data_append(xop, ">", 1);
+ xo_format_data(xop, NULL, format, flen, flags);
+ xo_data_append(xop, "</", 2);
+ xo_data_escape(xop, name, nlen);
+ xo_data_append(xop, ">", 1);
+ if (pretty)
+ xo_data_append(xop, "\n", 1);
+ break;
+
+ case XO_STYLE_JSON:
+ if (flags & XFF_DISPLAY_ONLY) {
+ flags |= XFF_NO_OUTPUT;
+ xo_format_data(xop, NULL, format, flen, flags);
+ break;
+ }
+
+ if (encoding) {
+ format = encoding;
+ flen = elen;
+ } else {
+ char *enc = alloca(flen + 1);
+ memcpy(enc, format, flen);
+ enc[flen] = '\0';
+ format = xo_fix_encoding(xop, enc);
+ flen = strlen(format);
+ }
+
+ int first = !(xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST);
+
+ xo_format_prep(xop, flags);
+
+ if (flags & XFF_QUOTE)
+ quote = 1;
+ else if (flags & XFF_NOQUOTE)
+ quote = 0;
+ else if (flen == 0) {
+ quote = 0;
+ format = "true"; /* JSON encodes empty tags as a boolean true */
+ flen = 4;
+ } else if (strchr("diouxXDOUeEfFgGaAcCp", format[flen - 1]) == NULL)
+ quote = 1;
+ else
+ quote = 0;
+
+ if (nlen == 0) {
+ static char missing[] = "missing-field-name";
+ xo_failure(xop, "missing field name: %s", format);
+ name = missing;
+ nlen = sizeof(missing) - 1;
+ }
+
+ if (flags & XFF_LEAF_LIST) {
+ if (first && pretty)
+ xo_buf_indent(xop, -1);
+ } else {
+ if (pretty)
+ xo_buf_indent(xop, -1);
+ xo_data_append(xop, "\"", 1);
+
+ xbp = &xop->xo_data;
+ int off = xbp->xb_curp - xbp->xb_bufp;
+
+ xo_data_escape(xop, name, nlen);
+
+ if (xop->xo_flags & XOF_UNDERSCORES) {
+ int now = xbp->xb_curp - xbp->xb_bufp;
+ for ( ; off < now; off++)
+ if (xbp->xb_bufp[off] == '-')
+ xbp->xb_bufp[off] = '_';
+ }
+ xo_data_append(xop, "\":", 2);
+ }
+
+ if (pretty)
+ xo_data_append(xop, " ", 1);
+ if (quote)
+ xo_data_append(xop, "\"", 1);
+
+ xo_format_data(xop, NULL, format, flen, flags);
+
+ if (quote)
+ xo_data_append(xop, "\"", 1);
+ break;
+ }
+}
+
+static void
+xo_format_content (xo_handle_t *xop, const char *class_name,
+ const char *xml_tag, int display_only,
+ const char *str, int len, const char *fmt, int flen)
+{
+ switch (xop->xo_style) {
+ case XO_STYLE_TEXT:
+ if (len) {
+ xo_data_append_content(xop, str, len);
+ } else
+ xo_format_data(xop, NULL, fmt, flen, 0);
+ break;
+
+ case XO_STYLE_HTML:
+ if (len == 0) {
+ str = fmt;
+ len = flen;
+ }
+
+ xo_buf_append_div(xop, class_name, 0, NULL, 0, str, len, NULL, 0);
+ break;
+
+ case XO_STYLE_XML:
+ if (xml_tag) {
+ if (len == 0) {
+ str = fmt;
+ len = flen;
+ }
+
+ xo_open_container_h(xop, xml_tag);
+ xo_format_value(xop, "message", 7, str, len, NULL, 0, 0);
+ xo_close_container_h(xop, xml_tag);
+
+ } else {
+ /*
+ * Even though we don't care about labels, we need to do
+ * enough parsing work to skip over the right bits of xo_vap.
+ */
+ if (len == 0)
+ xo_format_data(xop, NULL, fmt, flen, XFF_NO_OUTPUT);
+ }
+ break;
+
+ case XO_STYLE_JSON:
+ /*
+ * Even though we don't care about labels, we need to do
+ * enough parsing work to skip over the right bits of xo_vap.
+ */
+ if (display_only) {
+ if (len == 0)
+ xo_format_data(xop, NULL, fmt, flen, XFF_NO_OUTPUT);
+ break;
+ }
+ /* XXX need schem for representing errors in JSON */
+ break;
+ }
+}
+
+static void
+xo_format_units (xo_handle_t *xop, const char *str, int len,
+ const char *fmt, int flen)
+{
+ static char units_start_xml[] = " units=\"";
+ static char units_start_html[] = " data-units=\"";
+
+ if (!(xop->xo_flags & XOF_UNITS_PENDING)) {
+ xo_format_content(xop, "units", NULL, 1, str, len, fmt, flen);
+ return;
+ }
+
+ xo_buffer_t *xbp = &xop->xo_data;
+ int start = xop->xo_units_offset;
+ int stop = xbp->xb_curp - xbp->xb_bufp;
+
+ if (xop->xo_style == XO_STYLE_XML)
+ xo_buf_append(xbp, units_start_xml, sizeof(units_start_xml) - 1);
+ else if (xop->xo_style == XO_STYLE_HTML)
+ xo_buf_append(xbp, units_start_html, sizeof(units_start_html) - 1);
+ else
+ return;
+
+ if (len)
+ xo_data_append(xop, str, len);
+ else
+ xo_format_data(xop, NULL, fmt, flen, 0);
+
+ xo_buf_append(xbp, "\"", 1);
+
+ int now = xbp->xb_curp - xbp->xb_bufp;
+ int delta = now - stop;
+ if (delta < 0) { /* Strange; no output to move */
+ xbp->xb_curp = xbp->xb_bufp + stop; /* Reset buffer to prior state */
+ return;
+ }
+
+ /*
+ * Now we're in it alright. We've need to insert the unit value
+ * we just created into the right spot. We make a local copy,
+ * move it and then insert our copy. We know there's room in the
+ * buffer, since we're just moving this around.
+ */
+ char *buf = alloca(delta);
+
+ memcpy(buf, xbp->xb_bufp + stop, delta);
+ memmove(xbp->xb_bufp + start + delta, xbp->xb_bufp + start, stop - start);
+ memmove(xbp->xb_bufp + start, buf, delta);
+}
+
+static int
+xo_find_width (xo_handle_t *xop, const char *str, int len,
+ const char *fmt, int flen)
+{
+ long width = 0;
+ char *bp;
+ char *cp;
+
+ if (len) {
+ bp = alloca(len + 1); /* Make local NUL-terminated copy of str */
+ memcpy(bp, str, len);
+ bp[len] = '\0';
+
+ width = strtol(bp, &cp, 0);
+ if (width == LONG_MIN || width == LONG_MAX
+ || bp == cp || *cp != '\0' ) {
+ width = 0;
+ xo_failure(xop, "invalid width for anchor: '%s'", bp);
+ }
+ } else if (flen) {
+ if (flen != 2 || strncmp("%d", fmt, flen) != 0)
+ xo_failure(xop, "invalid width format: '%*.*s'", flen, flen, fmt);
+ if (!(xop->xo_flags & XOF_NO_VA_ARG))
+ width = va_arg(xop->xo_vap, int);
+ }
+
+ return width;
+}
+
+static void
+xo_anchor_clear (xo_handle_t *xop)
+{
+ xop->xo_flags &= ~XOF_ANCHOR;
+ xop->xo_anchor_offset = 0;
+ xop->xo_anchor_columns = 0;
+ xop->xo_anchor_min_width = 0;
+}
+
+/*
+ * An anchor is a marker used to delay field width implications.
+ * Imagine the format string "{[:10}{min:%d}/{cur:%d}/{max:%d}{:]}".
+ * We are looking for output like " 1/4/5"
+ *
+ * To make this work, we record the anchor and then return to
+ * format it when the end anchor tag is seen.
+ */
+static void
+xo_anchor_start (xo_handle_t *xop, const char *str, int len,
+ const char *fmt, int flen)
+{
+ if (xop->xo_style != XO_STYLE_TEXT && xop->xo_style != XO_STYLE_HTML)
+ return;
+
+ if (xop->xo_flags & XOF_ANCHOR)
+ xo_failure(xop, "the anchor already recording is discarded");
+
+ xop->xo_flags |= XOF_ANCHOR;
+ xo_buffer_t *xbp = &xop->xo_data;
+ xop->xo_anchor_offset = xbp->xb_curp - xbp->xb_bufp;
+ xop->xo_anchor_columns = 0;
+
+ /*
+ * Now we find the width, if possible. If it's not there,
+ * we'll get it on the end anchor.
+ */
+ xop->xo_anchor_min_width = xo_find_width(xop, str, len, fmt, flen);
+}
+
+static void
+xo_anchor_stop (xo_handle_t *xop, const char *str, int len,
+ const char *fmt, int flen)
+{
+ if (xop->xo_style != XO_STYLE_TEXT && xop->xo_style != XO_STYLE_HTML)
+ return;
+
+ if (!(xop->xo_flags & XOF_ANCHOR)) {
+ xo_failure(xop, "no start anchor");
+ return;
+ }
+
+ xop->xo_flags &= ~XOF_UNITS_PENDING;
+
+ int width = xo_find_width(xop, str, len, fmt, flen);
+ if (width == 0)
+ width = xop->xo_anchor_min_width;
+
+ if (width == 0) /* No width given; nothing to do */
+ goto done;
+
+ xo_buffer_t *xbp = &xop->xo_data;
+ int start = xop->xo_anchor_offset;
+ int stop = xbp->xb_curp - xbp->xb_bufp;
+ int abswidth = (width > 0) ? width : -width;
+ int blen = abswidth - xop->xo_anchor_columns;
+
+ if (blen <= 0) /* Already over width */
+ goto done;
+
+ if (abswidth > XO_MAX_ANCHOR_WIDTH) {
+ xo_failure(xop, "width over %u are not supported",
+ XO_MAX_ANCHOR_WIDTH);
+ goto done;
+ }
+
+ /* Make a suitable padding field and emit it */
+ char *buf = alloca(blen);
+ memset(buf, ' ', blen);
+ xo_format_content(xop, "padding", NULL, 1, buf, blen, NULL, 0);
+
+ if (width < 0) /* Already left justified */
+ goto done;
+
+ int now = xbp->xb_curp - xbp->xb_bufp;
+ int delta = now - stop;
+ if (delta < 0) /* Strange; no output to move */
+ goto done;
+
+ /*
+ * Now we're in it alright. We've need to insert the padding data
+ * we just created (which might be an HTML <div> or text) before
+ * the formatted data. We make a local copy, move it and then
+ * insert our copy. We know there's room in the buffer, since
+ * we're just moving this around.
+ */
+ if (delta > blen)
+ buf = alloca(delta); /* Expand buffer if needed */
+
+ memcpy(buf, xbp->xb_bufp + stop, delta);
+ memmove(xbp->xb_bufp + start + delta, xbp->xb_bufp + start, stop - start);
+ memmove(xbp->xb_bufp + start, buf, delta);
+
+ done:
+ xo_anchor_clear(xop);
+}
+
+static int
+xo_do_emit (xo_handle_t *xop, const char *fmt)
+{
+ int rc = 0;
+ const char *cp, *sp, *ep, *basep;
+ char *newp = NULL;
+ int flush = (xop->xo_flags & XOF_FLUSH) ? 1 : 0;
+
+ xop->xo_columns = 0; /* Always reset it */
+
+ for (cp = fmt; *cp; ) {
+ if (*cp == '\n') {
+ xo_line_close(xop);
+ xo_flush_h(xop);
+ cp += 1;
+ continue;
+
+ } else if (*cp == '{') {
+ if (cp[1] == '{') { /* Start of {{escaped braces}} */
+
+ cp += 2; /* Skip over _both_ characters */
+ for (sp = cp; *sp; sp++) {
+ if (*sp == '}' && sp[1] == '}')
+ break;
+ }
+ if (*sp == '\0') {
+ xo_failure(xop, "missing closing '}}': %s", fmt);
+ return -1;
+ }
+
+ xo_format_text(xop, cp, sp - cp);
+
+ /* Move along the string, but don't run off the end */
+ if (*sp == '}' && sp[1] == '}')
+ sp += 2;
+ cp = *sp ? sp + 1 : sp;
+ continue;
+ }
+ /* Else fall thru to the code below */
+
+ } else {
+ /* Normal text */
+ for (sp = cp; *sp; sp++) {
+ if (*sp == '{' || *sp == '\n')
+ break;
+ }
+ xo_format_text(xop, cp, sp - cp);
+
+ cp = sp;
+ continue;
+ }
+
+ basep = cp + 1;
+
+ /*
+ * We are looking at the start of a field definition. The format is:
+ * '{' modifiers ':' content [ '/' print-fmt [ '/' encode-fmt ]] '}'
+ * Modifiers are optional and include the following field types:
+ * 'D': decoration; something non-text and non-data (colons, commmas)
+ * 'E': error message
+ * 'L': label; text preceding data
+ * 'N': note; text following data
+ * 'P': padding; whitespace
+ * 'T': Title, where 'content' is a column title
+ * 'U': Units, where 'content' is the unit label
+ * 'V': value, where 'content' is the name of the field (the default)
+ * 'W': warning message
+ * '[': start a section of anchored text
+ * ']': end a section of anchored text
+ * The following flags are also supported:
+ * 'c': flag: emit a colon after the label
+ * 'd': field is only emitted for display formats (text and html)
+ * 'e': field is only emitted for encoding formats (xml and json)
+ * 'k': this field is a key, suitable for XPath predicates
+ * 'l': a leaf-list, a simple list of values
+ * 'n': no quotes around this field
+ * 'q': add quotes around this field
+ * 't': trim whitespace around the value
+ * 'w': emit a blank after the label
+ * The print-fmt and encode-fmt strings is the printf-style formating
+ * for this data. JSON and XML will use the encoding-fmt, if present.
+ * If the encode-fmt is not provided, it defaults to the print-fmt.
+ * If the print-fmt is not provided, it defaults to 's'.
+ */
+ unsigned ftype = 0, flags = 0;
+ const char *content = NULL, *format = NULL, *encoding = NULL;
+ int clen = 0, flen = 0, elen = 0;
+
+ for (sp = basep; sp; sp++) {
+ if (*sp == ':' || *sp == '/' || *sp == '}')
+ break;
+
+ if (*sp == '\\') {
+ if (sp[1] == '\0') {
+ xo_failure(xop, "backslash at the end of string");
+ return -1;
+ }
+ sp += 1;
+ continue;
+ }
+
+ switch (*sp) {
+ case 'D':
+ case 'E':
+ case 'L':
+ case 'N':
+ case 'P':
+ case 'T':
+ case 'U':
+ case 'V':
+ case 'W':
+ case '[':
+ case ']':
+ if (ftype != 0) {
+ xo_failure(xop, "field descriptor uses multiple types: %s",
+ fmt);
+ return -1;
+ }
+ ftype = *sp;
+ break;
+
+ case 'c':
+ flags |= XFF_COLON;
+ break;
+
+ case 'd':
+ flags |= XFF_DISPLAY_ONLY;
+ break;
+
+ case 'e':
+ flags |= XFF_ENCODE_ONLY;
+ break;
+
+ case 'k':
+ flags |= XFF_KEY;
+ break;
+
+ case 'l':
+ flags |= XFF_LEAF_LIST;
+ break;
+
+ case 'n':
+ flags |= XFF_NOQUOTE;
+ break;
+
+ case 'q':
+ flags |= XFF_QUOTE;
+ break;
+
+ case 't':
+ flags |= XFF_TRIM_WS;
+ break;
+
+ case 'w':
+ flags |= XFF_WS;
+ break;
+
+ default:
+ xo_failure(xop, "field descriptor uses unknown modifier: %s",
+ fmt);
+ /*
+ * No good answer here; a bad format will likely
+ * mean a core file. We just return and hope
+ * the caller notices there's no output, and while
+ * that seems, well, bad. There's nothing better.
+ */
+ return -1;
+ }
+ }
+
+ if (*sp == ':') {
+ for (ep = ++sp; *sp; sp++) {
+ if (*sp == '}' || *sp == '/')
+ break;
+ if (*sp == '\\') {
+ if (sp[1] == '\0') {
+ xo_failure(xop, "backslash at the end of string");
+ return -1;
+ }
+ sp += 1;
+ continue;
+ }
+ }
+ if (ep != sp) {
+ clen = sp - ep;
+ content = ep;
+ }
+ } else {
+ xo_failure(xop, "missing content (':'): %s", fmt);
+ return -1;
+ }
+
+ if (*sp == '/') {
+ for (ep = ++sp; *sp; sp++) {
+ if (*sp == '}' || *sp == '/')
+ break;
+ if (*sp == '\\') {
+ if (sp[1] == '\0') {
+ xo_failure(xop, "backslash at the end of string");
+ return -1;
+ }
+ sp += 1;
+ continue;
+ }
+ }
+ flen = sp - ep;
+ format = ep;
+ }
+
+ if (*sp == '/') {
+ for (ep = ++sp; *sp; sp++) {
+ if (*sp == '}')
+ break;
+ }
+ elen = sp - ep;
+ encoding = ep;
+ }
+
+ if (*sp == '}') {
+ sp += 1;
+ } else {
+ xo_failure(xop, "missing closing '}': %s", fmt);
+ return -1;
+ }
+
+ if (format == NULL && ftype != '[' && ftype != ']' ) {
+ format = "%s";
+ flen = 2;
+ }
+
+ if (ftype == 0 || ftype == 'V')
+ xo_format_value(xop, content, clen, format, flen,
+ encoding, elen, flags);
+ else if (ftype == 'D')
+ xo_format_content(xop, "decoration", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'E')
+ xo_format_content(xop, "error", "error", 0,
+ content, clen, format, flen);
+ else if (ftype == 'L')
+ xo_format_content(xop, "label", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'N')
+ xo_format_content(xop, "note", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'P')
+ xo_format_content(xop, "padding", NULL, 1,
+ content, clen, format, flen);
+ else if (ftype == 'T')
+ xo_format_title(xop, content, clen, format, flen);
+ else if (ftype == 'U') {
+ if (flags & XFF_WS)
+ xo_format_content(xop, "padding", NULL, 1, " ", 1, NULL, 0);
+ xo_format_units(xop, content, clen, format, flen);
+ } else if (ftype == 'W')
+ xo_format_content(xop, "warning", "warning", 0,
+ content, clen, format, flen);
+ else if (ftype == '[')
+ xo_anchor_start(xop, content, clen, format, flen);
+ else if (ftype == ']')
+ xo_anchor_stop(xop, content, clen, format, flen);
+
+ if (flags & XFF_COLON)
+ xo_format_content(xop, "decoration", NULL, 1, ":", 1, NULL, 0);
+ if (ftype != 'U' && (flags & XFF_WS))
+ xo_format_content(xop, "padding", NULL, 1, " ", 1, NULL, 0);
+
+ cp += sp - basep + 1;
+ if (newp) {
+ xo_free(newp);
+ newp = NULL;
+ }
+ }
+
+ /* If we don't have an anchor, write the text out */
+ if (flush && !(xop->xo_flags & XOF_ANCHOR))
+ xo_write(xop);
+
+ return (rc < 0) ? rc : (int) xop->xo_columns;
+}
+
+int
+xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap)
+{
+ int rc;
+
+ xop = xo_default(xop);
+ va_copy(xop->xo_vap, vap);
+ rc = xo_do_emit(xop, fmt);
+ va_end(xop->xo_vap);
+ bzero(&xop->xo_vap, sizeof(xop->xo_vap));
+
+ return rc;
+}
+
+int
+xo_emit_h (xo_handle_t *xop, const char *fmt, ...)
+{
+ int rc;
+
+ xop = xo_default(xop);
+ va_start(xop->xo_vap, fmt);
+ rc = xo_do_emit(xop, fmt);
+ va_end(xop->xo_vap);
+ bzero(&xop->xo_vap, sizeof(xop->xo_vap));
+
+ return rc;
+}
+
+int
+xo_emit (const char *fmt, ...)
+{
+ xo_handle_t *xop = xo_default(NULL);
+ int rc;
+
+ va_start(xop->xo_vap, fmt);
+ rc = xo_do_emit(xop, fmt);
+ va_end(xop->xo_vap);
+ bzero(&xop->xo_vap, sizeof(xop->xo_vap));
+
+ return rc;
+}
+
+int
+xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap)
+{
+ const int extra = 5; /* space, equals, quote, quote, and nul */
+ xop = xo_default(xop);
+
+ if (xop->xo_style != XO_STYLE_XML)
+ return 0;
+
+ int nlen = strlen(name);
+ xo_buffer_t *xbp = &xop->xo_attrs;
+
+ if (!xo_buf_has_room(xbp, nlen + extra))
+ return -1;
+
+ *xbp->xb_curp++ = ' ';
+ memcpy(xbp->xb_curp, name, nlen);
+ xbp->xb_curp += nlen;
+ *xbp->xb_curp++ = '=';
+ *xbp->xb_curp++ = '"';
+
+ int rc = xo_vsnprintf(xop, xbp, fmt, vap);
+
+ if (rc > 0) {
+ rc = xo_escape_xml(xbp, rc, 1);
+ xbp->xb_curp += rc;
+ }
+
+ if (!xo_buf_has_room(xbp, 2))
+ return -1;
+
+ *xbp->xb_curp++ = '"';
+ *xbp->xb_curp = '\0';
+
+ return rc + nlen + extra;
+}
+
+int
+xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...)
+{
+ int rc;
+ va_list vap;
+
+ va_start(vap, fmt);
+ rc = xo_attr_hv(xop, name, fmt, vap);
+ va_end(vap);
+
+ return rc;
+}
+
+int
+xo_attr (const char *name, const char *fmt, ...)
+{
+ int rc;
+ va_list vap;
+
+ va_start(vap, fmt);
+ rc = xo_attr_hv(NULL, name, fmt, vap);
+ va_end(vap);
+
+ return rc;
+}
+
+static void
+xo_stack_set_flags (xo_handle_t *xop)
+{
+ if (xop->xo_flags & XOF_NOT_FIRST) {
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+
+ xsp->xs_flags |= XSF_NOT_FIRST;
+ xop->xo_flags &= ~XOF_NOT_FIRST;
+ }
+}
+
+static void
+xo_depth_change (xo_handle_t *xop, const char *name,
+ int delta, int indent, xo_xsf_flags_t flags)
+{
+ if (xop->xo_flags & XOF_DTRT)
+ flags |= XSF_DTRT;
+
+ if (delta >= 0) { /* Push operation */
+ if (xo_depth_check(xop, xop->xo_depth + delta))
+ return;
+
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth + delta];
+ xsp->xs_flags = flags;
+ xo_stack_set_flags(xop);
+
+ unsigned save = (xop->xo_flags & (XOF_XPATH | XOF_WARN | XOF_DTRT));
+ save |= (flags & XSF_DTRT);
+
+ if (name && save) {
+ int len = strlen(name) + 1;
+ char *cp = xo_realloc(NULL, len);
+ if (cp) {
+ memcpy(cp, name, len);
+ xsp->xs_name = cp;
+ }
+ }
+
+ } else { /* Pop operation */
+ if (xop->xo_depth == 0) {
+ if (!(xop->xo_flags & XOF_IGNORE_CLOSE))
+ xo_failure(xop, "close with empty stack: '%s'", name);
+ return;
+ }
+
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+ if (xop->xo_flags & XOF_WARN) {
+ const char *top = xsp->xs_name;
+ if (top && strcmp(name, top) != 0) {
+ xo_failure(xop, "incorrect close: '%s' .vs. '%s'",
+ name, top);
+ return;
+ }
+ if ((xsp->xs_flags & XSF_LIST) != (flags & XSF_LIST)) {
+ xo_failure(xop, "list close on list confict: '%s'",
+ name);
+ return;
+ }
+ if ((xsp->xs_flags & XSF_INSTANCE) != (flags & XSF_INSTANCE)) {
+ xo_failure(xop, "list close on instance confict: '%s'",
+ name);
+ return;
+ }
+ }
+
+ if (xsp->xs_name) {
+ xo_free(xsp->xs_name);
+ xsp->xs_name = NULL;
+ }
+ if (xsp->xs_keys) {
+ xo_free(xsp->xs_keys);
+ xsp->xs_keys = NULL;
+ }
+ }
+
+ xop->xo_depth += delta; /* Record new depth */
+ xop->xo_indent += indent;
+}
+
+void
+xo_set_depth (xo_handle_t *xop, int depth)
+{
+ xop = xo_default(xop);
+
+ if (xo_depth_check(xop, depth))
+ return;
+
+ xop->xo_depth += depth;
+ xop->xo_indent += depth;
+}
+
+static xo_xsf_flags_t
+xo_stack_flags (unsigned xflags)
+{
+ if (xflags & XOF_DTRT)
+ return XSF_DTRT;
+ return 0;
+}
+
+static int
+xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name)
+{
+ xop = xo_default(xop);
+
+ int rc = 0;
+ const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ const char *pre_nl = "";
+
+ if (name == NULL) {
+ xo_failure(xop, "NULL passed for container name");
+ name = XO_FAILURE_NAME;
+ }
+
+ flags |= xop->xo_flags; /* Pick up handle flags */
+
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ rc = xo_printf(xop, "%*s<%s>%s", xo_indent(xop), "",
+ name, ppn);
+ xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
+ break;
+
+ case XO_STYLE_JSON:
+ xo_stack_set_flags(xop);
+
+ if (!(xop->xo_flags & XOF_NO_TOP)) {
+ if (!(xop->xo_flags & XOF_TOP_EMITTED)) {
+ xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn);
+ xop->xo_flags |= XOF_TOP_EMITTED;
+ }
+ }
+
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", ";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ rc = xo_printf(xop, "%s%*s\"%s\": {%s",
+ pre_nl, xo_indent(xop), "", name, ppn);
+ xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
+ break;
+
+ case XO_STYLE_HTML:
+ case XO_STYLE_TEXT:
+ xo_depth_change(xop, name, 1, 0, xo_stack_flags(flags));
+ break;
+ }
+
+ return rc;
+}
+
+int
+xo_open_container_h (xo_handle_t *xop, const char *name)
+{
+ return xo_open_container_hf(xop, 0, name);
+}
+
+int
+xo_open_container (const char *name)
+{
+ return xo_open_container_hf(NULL, 0, name);
+}
+
+int
+xo_open_container_hd (xo_handle_t *xop, const char *name)
+{
+ return xo_open_container_hf(xop, XOF_DTRT, name);
+}
+
+int
+xo_open_container_d (const char *name)
+{
+ return xo_open_container_hf(NULL, XOF_DTRT, name);
+}
+
+int
+xo_close_container_h (xo_handle_t *xop, const char *name)
+{
+ xop = xo_default(xop);
+
+ int rc = 0;
+ const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ const char *pre_nl = "";
+
+ if (name == NULL) {
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+ if (!(xsp->xs_flags & XSF_DTRT))
+ xo_failure(xop, "missing name without 'dtrt' mode");
+
+ name = xsp->xs_name;
+ if (name) {
+ int len = strlen(name) + 1;
+ /* We need to make a local copy; xo_depth_change will free it */
+ char *cp = alloca(len);
+ memcpy(cp, name, len);
+ name = cp;
+ } else
+ name = XO_FAILURE_NAME;
+ }
+
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ xo_depth_change(xop, name, -1, -1, 0);
+ rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
+ break;
+
+ case XO_STYLE_JSON:
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ ppn = (xop->xo_depth <= 1) ? "\n" : "";
+
+ xo_depth_change(xop, name, -1, -1, 0);
+ rc = xo_printf(xop, "%s%*s}%s", pre_nl, xo_indent(xop), "", ppn);
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+ break;
+
+ case XO_STYLE_HTML:
+ case XO_STYLE_TEXT:
+ xo_depth_change(xop, name, -1, 0, 0);
+ break;
+ }
+
+ return rc;
+}
+
+int
+xo_close_container (const char *name)
+{
+ return xo_close_container_h(NULL, name);
+}
+
+int
+xo_close_container_hd (xo_handle_t *xop)
+{
+ return xo_close_container_h(xop, NULL);
+}
+
+int
+xo_close_container_d (void)
+{
+ return xo_close_container_h(NULL, NULL);
+}
+
+static int
+xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
+{
+ xop = xo_default(xop);
+
+ if (xop->xo_style != XO_STYLE_JSON)
+ return 0;
+
+ int rc = 0;
+ const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ const char *pre_nl = "";
+
+ if (!(xop->xo_flags & XOF_NO_TOP)) {
+ if (!(xop->xo_flags & XOF_TOP_EMITTED)) {
+ xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn);
+ xop->xo_flags |= XOF_TOP_EMITTED;
+ }
+ }
+
+ if (name == NULL) {
+ xo_failure(xop, "NULL passed for list name");
+ name = XO_FAILURE_NAME;
+ }
+
+ xo_stack_set_flags(xop);
+
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", ";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ rc = xo_printf(xop, "%s%*s\"%s\": [%s",
+ pre_nl, xo_indent(xop), "", name, ppn);
+ xo_depth_change(xop, name, 1, 1, XSF_LIST | xo_stack_flags(flags));
+
+ return rc;
+}
+
+int
+xo_open_list_h (xo_handle_t *xop, const char *name UNUSED)
+{
+ return xo_open_list_hf(xop, 0, name);
+}
+
+int
+xo_open_list (const char *name)
+{
+ return xo_open_list_hf(NULL, 0, name);
+}
+
+int
+xo_open_list_hd (xo_handle_t *xop, const char *name UNUSED)
+{
+ return xo_open_list_hf(xop, XOF_DTRT, name);
+}
+
+int
+xo_open_list_d (const char *name)
+{
+ return xo_open_list_hf(NULL, XOF_DTRT, name);
+}
+
+int
+xo_close_list_h (xo_handle_t *xop, const char *name)
+{
+ int rc = 0;
+ const char *pre_nl = "";
+
+ xop = xo_default(xop);
+
+ if (xop->xo_style != XO_STYLE_JSON)
+ return 0;
+
+ if (name == NULL) {
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+ if (!(xsp->xs_flags & XSF_DTRT))
+ xo_failure(xop, "missing name without 'dtrt' mode");
+
+ name = xsp->xs_name;
+ if (name) {
+ int len = strlen(name) + 1;
+ /* We need to make a local copy; xo_depth_change will free it */
+ char *cp = alloca(len);
+ memcpy(cp, name, len);
+ name = cp;
+ } else
+ name = XO_FAILURE_NAME;
+ }
+
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ xo_depth_change(xop, name, -1, -1, XSF_LIST);
+ rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), "");
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ return 0;
+}
+
+int
+xo_close_list (const char *name)
+{
+ return xo_close_list_h(NULL, name);
+}
+
+int
+xo_close_list_hd (xo_handle_t *xop)
+{
+ return xo_close_list_h(xop, NULL);
+}
+
+int
+xo_close_list_d (void)
+{
+ return xo_close_list_h(NULL, NULL);
+}
+
+static int
+xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name)
+{
+ xop = xo_default(xop);
+
+ int rc = 0;
+ const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ const char *pre_nl = "";
+
+ flags |= xop->xo_flags;
+
+ if (name == NULL) {
+ xo_failure(xop, "NULL passed for instance name");
+ name = XO_FAILURE_NAME;
+ }
+
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ rc = xo_printf(xop, "%*s<%s>%s", xo_indent(xop), "", name, ppn);
+ xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
+ break;
+
+ case XO_STYLE_JSON:
+ xo_stack_set_flags(xop);
+
+ if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST)
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? ",\n" : ", ";
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+
+ rc = xo_printf(xop, "%s%*s{%s",
+ pre_nl, xo_indent(xop), "", ppn);
+ xo_depth_change(xop, name, 1, 1, xo_stack_flags(flags));
+ break;
+
+ case XO_STYLE_HTML:
+ case XO_STYLE_TEXT:
+ xo_depth_change(xop, name, 1, 0, xo_stack_flags(flags));
+ break;
+ }
+
+ return rc;
+}
+
+int
+xo_open_instance_h (xo_handle_t *xop, const char *name)
+{
+ return xo_open_instance_hf(xop, 0, name);
+}
+
+int
+xo_open_instance (const char *name)
+{
+ return xo_open_instance_hf(NULL, 0, name);
+}
+
+int
+xo_open_instance_hd (xo_handle_t *xop, const char *name)
+{
+ return xo_open_instance_hf(xop, XOF_DTRT, name);
+}
+
+int
+xo_open_instance_d (const char *name)
+{
+ return xo_open_instance_hf(NULL, XOF_DTRT, name);
+}
+
+int
+xo_close_instance_h (xo_handle_t *xop, const char *name)
+{
+ xop = xo_default(xop);
+
+ int rc = 0;
+ const char *ppn = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+ const char *pre_nl = "";
+
+ if (name == NULL) {
+ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth];
+ if (!(xsp->xs_flags & XSF_DTRT))
+ xo_failure(xop, "missing name without 'dtrt' mode");
+
+ name = xsp->xs_name;
+ if (name) {
+ int len = strlen(name) + 1;
+ /* We need to make a local copy; xo_depth_change will free it */
+ char *cp = alloca(len);
+ memcpy(cp, name, len);
+ name = cp;
+ } else
+ name = XO_FAILURE_NAME;
+ }
+
+ switch (xop->xo_style) {
+ case XO_STYLE_XML:
+ xo_depth_change(xop, name, -1, -1, 0);
+ rc = xo_printf(xop, "%*s</%s>%s", xo_indent(xop), "", name, ppn);
+ break;
+
+ case XO_STYLE_JSON:
+ pre_nl = (xop->xo_flags & XOF_PRETTY) ? "\n" : "";
+
+ xo_depth_change(xop, name, -1, -1, 0);
+ rc = xo_printf(xop, "%s%*s}", pre_nl, xo_indent(xop), "");
+ xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST;
+ break;
+
+ case XO_STYLE_HTML:
+ case XO_STYLE_TEXT:
+ xo_depth_change(xop, name, -1, 0, 0);
+ break;
+ }
+
+ return rc;
+}
+
+int
+xo_close_instance (const char *name)
+{
+ return xo_close_instance_h(NULL, name);
+}
+
+int
+xo_close_instance_hd (xo_handle_t *xop)
+{
+ return xo_close_instance_h(xop, NULL);
+}
+
+int
+xo_close_instance_d (void)
+{
+ return xo_close_instance_h(NULL, NULL);
+}
+
+void
+xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func,
+ xo_close_func_t close_func)
+{
+ xop = xo_default(xop);
+
+ xop->xo_opaque = opaque;
+ xop->xo_write = write_func;
+ xop->xo_close = close_func;
+}
+
+void
+xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func)
+{
+ xo_realloc = realloc_func;
+ xo_free = free_func;
+}
+
+void
+xo_flush_h (xo_handle_t *xop)
+{
+ static char div_close[] = "</div>";
+
+ xop = xo_default(xop);
+
+ switch (xop->xo_style) {
+ case XO_STYLE_HTML:
+ if (xop->xo_flags & XOF_DIV_OPEN) {
+ xop->xo_flags &= ~XOF_DIV_OPEN;
+ xo_data_append(xop, div_close, sizeof(div_close) - 1);
+
+ if (xop->xo_flags & XOF_PRETTY)
+ xo_data_append(xop, "\n", 1);
+ }
+ break;
+ }
+
+ xo_write(xop);
+}
+
+void
+xo_flush (void)
+{
+ xo_flush_h(NULL);
+}
+
+void
+xo_finish_h (xo_handle_t *xop)
+{
+ const char *cp = "";
+ xop = xo_default(xop);
+
+ switch (xop->xo_style) {
+ case XO_STYLE_JSON:
+ if (!(xop->xo_flags & XOF_NO_TOP)) {
+ if (xop->xo_flags & XOF_TOP_EMITTED)
+ xop->xo_flags &= ~XOF_TOP_EMITTED; /* Turn off before output */
+ else
+ cp = "{ ";
+ xo_printf(xop, "%*s%s}\n",xo_indent(xop), "", cp);
+ }
+ break;
+ }
+
+ xo_flush_h(xop);
+}
+
+void
+xo_finish (void)
+{
+ xo_finish_h(NULL);
+}
+
+/*
+ * Generate an error message, such as would be displayed on stderr
+ */
+void
+xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap)
+{
+ xop = xo_default(xop);
+
+ /*
+ * If the format string doesn't end with a newline, we pop
+ * one on ourselves.
+ */
+ int len = strlen(fmt);
+ if (len > 0 && fmt[len - 1] != '\n') {
+ char *newfmt = alloca(len + 2);
+ memcpy(newfmt, fmt, len);
+ newfmt[len] = '\n';
+ newfmt[len] = '\0';
+ fmt = newfmt;
+ }
+
+ switch (xop->xo_style) {
+ case XO_STYLE_TEXT:
+ vfprintf(stderr, fmt, vap);
+ break;
+
+ case XO_STYLE_HTML:
+ va_copy(xop->xo_vap, vap);
+
+ xo_buf_append_div(xop, "error", 0, NULL, 0, fmt, strlen(fmt), NULL, 0);
+
+ if (xop->xo_flags & XOF_DIV_OPEN)
+ xo_line_close(xop);
+
+ xo_write(xop);
+
+ va_end(xop->xo_vap);
+ bzero(&xop->xo_vap, sizeof(xop->xo_vap));
+ break;
+
+ case XO_STYLE_XML:
+ va_copy(xop->xo_vap, vap);
+
+ xo_open_container_h(xop, "error");
+ xo_format_value(xop, "message", 7, fmt, strlen(fmt), NULL, 0, 0);
+ xo_close_container_h(xop, "error");
+
+ va_end(xop->xo_vap);
+ bzero(&xop->xo_vap, sizeof(xop->xo_vap));
+ break;
+ }
+}
+
+void
+xo_error_h (xo_handle_t *xop, const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_error_hv(xop, fmt, vap);
+ va_end(vap);
+}
+
+/*
+ * Generate an error message, such as would be displayed on stderr
+ */
+void
+xo_error (const char *fmt, ...)
+{
+ va_list vap;
+
+ va_start(vap, fmt);
+ xo_error_hv(NULL, fmt, vap);
+ va_end(vap);
+}
+
+int
+xo_parse_args (int argc, char **argv)
+{
+ static char libxo_opt[] = "--libxo";
+ char *cp;
+ int i, save;
+
+ /* Save our program name for xo_err and friends */
+ xo_program = argv[0];
+ cp = strrchr(xo_program, '/');
+ if (cp)
+ xo_program = cp + 1;
+
+ for (save = i = 1; i < argc; i++) {
+ if (argv[i] == NULL
+ || strncmp(argv[i], libxo_opt, sizeof(libxo_opt) - 1) != 0) {
+ if (save != i)
+ argv[save] = argv[i];
+ save += 1;
+ continue;
+ }
+
+ cp = argv[i] + sizeof(libxo_opt) - 1;
+ if (*cp == 0) {
+ cp = argv[++i];
+ if (cp == 0) {
+ xo_warnx("missing libxo option");
+ return -1;
+ }
+
+ if (xo_set_options(NULL, cp) < 0)
+ return -1;
+ } else if (*cp == ':') {
+ if (xo_set_options(NULL, cp) < 0)
+ return -1;
+
+ } else if (*cp == '=') {
+ if (xo_set_options(NULL, ++cp) < 0)
+ return -1;
+
+ } else if (*cp == '-') {
+ cp += 1;
+ if (strcmp(cp, "check") == 0) {
+ exit(XO_HAS_LIBXO);
+
+ } else {
+ xo_warnx("unknown libxo option: '%s'", argv[i]);
+ return -1;
+ }
+ } else {
+ xo_warnx("unknown libxo option: '%s'", argv[i]);
+ return -1;
+ }
+ }
+
+ argv[save] = NULL;
+ return save;
+}
+
+#ifdef UNIT_TEST
+int
+main (int argc, char **argv)
+{
+ static char base_grocery[] = "GRO";
+ static char base_hardware[] = "HRD";
+ struct item {
+ const char *i_title;
+ int i_sold;
+ int i_instock;
+ int i_onorder;
+ const char *i_sku_base;
+ int i_sku_num;
+ };
+ struct item list[] = {
+ { "gum&this&that", 1412, 54, 10, base_grocery, 415 },
+ { "<rope>", 85, 4, 2, base_hardware, 212 },
+ { "ladder", 0, 2, 1, base_hardware, 517 },
+ { "\"bolt\"", 4123, 144, 42, base_hardware, 632 },
+ { "water\\blue", 17, 14, 2, base_grocery, 2331 },
+ { NULL, 0, 0, 0, NULL, 0 }
+ };
+ struct item list2[] = {
+ { "fish", 1321, 45, 1, base_grocery, 533 },
+ { NULL, 0, 0, 0, NULL, 0 }
+ };
+ struct item *ip;
+ xo_info_t info[] = {
+ { "in-stock", "number", "Number of items in stock" },
+ { "name", "string", "Name of the item" },
+ { "on-order", "number", "Number of items on order" },
+ { "sku", "string", "Stock Keeping Unit" },
+ { "sold", "number", "Number of items sold" },
+ { NULL, NULL, NULL },
+ };
+ int info_count = (sizeof(info) / sizeof(info[0])) - 1;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(1);
+
+ xo_set_info(NULL, info, info_count);
+
+ xo_open_container_h(NULL, "top");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ xo_emit("{T:Item/%-15s}{T:Total Sold/%12s}{T:In Stock/%12s}"
+ "{T:On Order/%12s}{T:SKU/%5s}\n");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_emit("{k:name/%-15s/%s}{n:sold/%12u/%u}{:in-stock/%12u/%u}"
+ "{:on-order/%12u/%u} {q:sku/%5s-000-%u/%s-000-%u}\n",
+ ip->i_title, ip->i_sold, ip->i_instock, ip->i_onorder,
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_emit("\n\n");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_attr("fancy", "%s%d", "item", ip - list);
+ xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title);
+ xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}{e:percent/%u}\n",
+ ip->i_sold, ip->i_sold ? ".0" : "", 44);
+ xo_emit("{P: }{Lcw:In stock}{:in-stock/%u}\n", ip->i_instock);
+ xo_emit("{P: }{Lcw:On order}{:on-order/%u}\n", ip->i_onorder);
+ xo_emit("{P: }{L:SKU}: {q:sku/%s-000-%u}\n",
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ for (ip = list2; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title);
+ xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n",
+ ip->i_sold, ip->i_sold ? ".0" : "");
+ xo_emit("{P: }{Lcw:In stock}{:in-stock/%u}\n", ip->i_instock);
+ xo_emit("{P: }{Lcw:On order}{:on-order/%u}\n", ip->i_onorder);
+ xo_emit("{P: }{L:SKU}: {q:sku/%s-000-%u}\n",
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_open_list("month");
+
+ const char *months[] = { "Jan", "Feb", "Mar", NULL };
+ int discounts[] = { 10, 20, 25, 0 };
+ int i;
+ for (i = 0; months[i]; i++) {
+ xo_open_instance("month");
+ xo_emit("{P: }"
+ "{Lwc:Month}{k:month}, {Lwc:Special}{:discount/%d}\n",
+ months[i], discounts[i]);
+ xo_close_instance("month");
+ }
+
+ xo_close_list("month");
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_close_container_h(NULL, "top");
+
+ xo_finish();
+
+ return 0;
+}
+#endif /* UNIT_TEST */
diff --git a/contrib/libxo/libxo/xo.h b/contrib/libxo/libxo/xo.h
new file mode 100644
index 0000000..3a59e4c
--- /dev/null
+++ b/contrib/libxo/libxo/xo.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+/**
+ * libxo provides a means of generating text, XML, and JSON output
+ * using a single set of function calls, maximizing the value of output
+ * while minimizing the cost/impact on the code.
+ */
+
+#ifndef INCLUDE_XO_H
+#define INCLUDE_XO_H
+
+/** Formatting types */
+typedef unsigned xo_style_t;
+#define XO_STYLE_TEXT 0 /** Generate text output */
+#define XO_STYLE_XML 1 /** Generate XML output */
+#define XO_STYLE_JSON 2 /** Generate JSON output */
+#define XO_STYLE_HTML 3 /** Generate HTML output */
+
+/** Flags for libxo */
+typedef unsigned long xo_xof_flags_t;
+#define XOF_CLOSE_FP (1<<0) /** Close file pointer on xo_close() */
+#define XOF_PRETTY (1<<1) /** Make 'pretty printed' output */
+#define XOF_DIV_OPEN (1<<2) /** Internal use only: a <div> is open */
+#define XOF_LINE_OPEN (1<<3) /** Internal use only: a <div class="line"> */
+
+#define XOF_WARN (1<<4) /** Generate warnings for broken calls */
+#define XOF_XPATH (1<<5) /** Emit XPath attributes in HTML */
+#define XOF_INFO (1<<6) /** Emit additional info fields (HTML) */
+#define XOF_WARN_XML (1<<7) /** Emit warnings in XML (on stdout) */
+
+#define XOF_NO_ENV (1<<8) /** Don't look at the LIBXO_OPTIONS env var */
+#define XOF_NO_VA_ARG (1<<9) /** Don't advance va_list w/ va_arg() */
+#define XOF_DTRT (1<<10) /** Enable "do the right thing" mode */
+#define XOF_KEYS (1<<11) /** Flag 'key' fields for xml and json */
+
+#define XOF_IGNORE_CLOSE (1<<12) /** Ignore errors on close tags */
+#define XOF_NOT_FIRST (1<<13) /* Not the first item (JSON) */
+#define XOF_NO_LOCALE (1<<14) /** Don't bother with locale */
+#define XOF_TOP_EMITTED (1<<15) /* The top JSON braces have been emitted */
+
+#define XOF_NO_TOP (1<<16) /** Don't emit the top braces in JSON */
+#define XOF_ANCHOR (1<<17) /** An anchor is in place */
+#define XOF_UNITS (1<<18) /** Encode units in XML */
+#define XOF_UNITS_PENDING (1<<19) /** We have a units-insertion pending */
+
+#define XOF_UNDERSCORES (1<<20) /** Replace dashes with underscores (JSON) */
+#define XOF_COLUMNS (1<<21) /** xo_emit should return a column count */
+#define XOF_FLUSH (1<<22) /** Flush after each xo_emit call */
+
+/*
+ * The xo_info_t structure provides a mapping between names and
+ * additional data emitted via HTML.
+ */
+typedef struct xo_info_s {
+ const char *xi_name; /* Name of the element */
+ const char *xi_type; /* Type of field */
+ const char *xi_help; /* Description of field */
+} xo_info_t;
+
+struct xo_handle_s; /* Opaque structure forward */
+typedef struct xo_handle_s xo_handle_t; /* Handle for XO output */
+
+typedef int (*xo_write_func_t)(void *, const char *);
+typedef void (*xo_close_func_t)(void *);
+typedef void *(*xo_realloc_func_t)(void *, size_t);
+typedef void (*xo_free_func_t)(void *);
+
+/*
+ * The formatter function mirrors "vsnprintf", with an additional argument
+ * of the xo handle. The caller should return the number of bytes _needed_
+ * to fit the data, even if this exceeds 'len'.
+ */
+typedef int (*xo_formatter_t)(xo_handle_t *, char *, int,
+ const char *, va_list);
+typedef void (*xo_checkpointer_t)(xo_handle_t *, va_list, int);
+
+xo_handle_t *
+xo_create (xo_style_t style, xo_xof_flags_t flags);
+
+xo_handle_t *
+xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags);
+
+void
+xo_destroy (xo_handle_t *xop);
+
+void
+xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func,
+ xo_close_func_t close_func);
+
+void
+xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func);
+
+void
+xo_set_style (xo_handle_t *xop, xo_style_t style);
+
+xo_style_t
+xo_get_style (xo_handle_t *xop);
+
+int
+xo_set_style_name (xo_handle_t *xop, const char *style);
+
+int
+xo_set_options (xo_handle_t *xop, const char *input);
+
+xo_xof_flags_t
+xo_get_flags (xo_handle_t *xop);
+
+void
+xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags);
+
+void
+xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags);
+
+void
+xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
+
+void
+xo_set_formatter (xo_handle_t *xop, xo_formatter_t func, xo_checkpointer_t);
+
+void
+xo_set_depth (xo_handle_t *xop, int depth);
+
+int
+xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap);
+
+int
+xo_emit_h (xo_handle_t *xop, const char *fmt, ...);
+
+int
+xo_emit (const char *fmt, ...);
+
+int
+xo_open_container_h (xo_handle_t *xop, const char *name);
+
+int
+xo_open_container (const char *name);
+
+int
+xo_open_container_hd (xo_handle_t *xop, const char *name);
+
+int
+xo_open_container_d (const char *name);
+
+int
+xo_close_container_h (xo_handle_t *xop, const char *name);
+
+int
+xo_close_container (const char *name);
+
+int
+xo_close_container_hd (xo_handle_t *xop);
+
+int
+xo_close_container_d (void);
+
+int
+xo_open_list_h (xo_handle_t *xop, const char *name);
+
+int
+xo_open_list (const char *name);
+
+int
+xo_open_list_hd (xo_handle_t *xop, const char *name);
+
+int
+xo_open_list_d (const char *name);
+
+int
+xo_close_list_h (xo_handle_t *xop, const char *name);
+
+int
+xo_close_list (const char *name);
+
+int
+xo_close_list_hd (xo_handle_t *xop);
+
+int
+xo_close_list_d (void);
+
+int
+xo_open_instance_h (xo_handle_t *xop, const char *name);
+
+int
+xo_open_instance (const char *name);
+
+int
+xo_open_instance_hd (xo_handle_t *xop, const char *name);
+
+int
+xo_open_instance_d (const char *name);
+
+int
+xo_close_instance_h (xo_handle_t *xop, const char *name);
+
+int
+xo_close_instance (const char *name);
+
+int
+xo_close_instance_hd (xo_handle_t *xop);
+
+int
+xo_close_instance_d (void);
+
+int
+xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...);
+
+int
+xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap);
+
+int
+xo_attr (const char *name, const char *fmt, ...);
+
+void
+xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap);
+
+void
+xo_error_h (xo_handle_t *xop, const char *fmt, ...);
+
+void
+xo_error (const char *fmt, ...);
+
+void
+xo_flush_h (xo_handle_t *xop);
+
+void
+xo_flush (void);
+
+void
+xo_finish_h (xo_handle_t *xop);
+
+void
+xo_finish (void);
+
+void
+xo_set_leading_xpath (xo_handle_t *xop, const char *path);
+
+void
+xo_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...);
+
+void
+xo_warn_c (int code, const char *fmt, ...);
+
+void
+xo_warn (const char *fmt, ...);
+
+void
+xo_warnx (const char *fmt, ...);
+
+void
+xo_err (int eval, const char *fmt, ...);
+
+void
+xo_errx (int eval, const char *fmt, ...);
+
+void
+xo_errc (int eval, int code, const char *fmt, ...);
+
+void
+xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap);
+
+void
+xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...);
+
+void
+xo_message_c (int code, const char *fmt, ...);
+
+void
+xo_message (const char *fmt, ...);
+
+void
+xo_no_setlocale (void);
+
+int
+xo_parse_args (int argc, char **argv);
+
+/*
+ * This is the "magic" number returned by libxo-supporting commands
+ * when passed the equally magic "--libxo-check" option. If you
+ * return this, we can assume that since you know the magic handshake,
+ * you'll happily handle future --libxo options and not do something
+ * violent like reboot the box or create another hole in the ozone
+ * layer.
+ */
+#define XO_HAS_LIBXO 121
+
+/*
+ * externs for our version number strings
+ */
+extern const char xo_version[];
+extern const char xo_version_extra[];
+
+#endif /* INCLUDE_XO_H */
diff --git a/contrib/libxo/libxo/xo_attr.3 b/contrib/libxo/libxo/xo_attr.3
new file mode 100644
index 0000000..afd805f
--- /dev/null
+++ b/contrib/libxo/libxo/xo_attr.3
@@ -0,0 +1,77 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft int
+.Fn xo_attr "const char *name" "const char *fmt" "..."
+.Ft int
+.Fn xo_attr_h "xo_handle_t *handle" "const char *name, const char *fmt" "..."
+.Ft int
+.Fn xo_attr_hv "xo_handle_t *handle" "const char *name" "const char *fmt" "va_list vap"
+.Sh DESCRIPTION
+The
+.Fn xo_attr
+function emits attributes for the XML output style. The attribute
+value is recorded in the
+.Fa handle
+and is attached to the next field that is emitted via a
+.Xr xo_emit 3
+call.
+.Pp
+The
+.Fa name
+parameter give the name of the attribute to be encoded. The
+.Fa fmt
+parameter gives a printf-style format string used to format the
+value of the attribute using any remaining arguments, or the
+.Fa vap
+parameter as passed to
+.Fn xo_attr_hv .
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_attr("seconds", "%ld", (unsigned long) login_time);
+ struct tm *tmp = localtime(login_time);
+ strftime(buf, sizeof(buf), "%R", tmp);
+ xo_emit("Logged in at {:login-time}\\n", buf);
+ XML:
+ <login-time seconds="1408336270">00:14</login-time>
+.Ed
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_create.3 b/contrib/libxo/libxo/xo_create.3
new file mode 100644
index 0000000..1e0a69b
--- /dev/null
+++ b/contrib/libxo/libxo/xo_create.3
@@ -0,0 +1,85 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft xo_handle_t *
+.Fn xo_create "unsigned style" "unsigned flags"
+.Ft xo_handle_t *
+.Fn xo_create_to_file "FILE *fp" "unsigned style" "unsigned flags"
+.Ft void
+.Fn xo_destroy "xo_handle_t *handle"
+.Sh DESCRIPTION
+A
+.Em libxo
+handle can be allocated using the
+.Fn xo_create
+function.
+.Bd -literal -offset indent
+ Example:
+ xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN);
+ ....
+ xo_emit_h(xop, "testing\n");
+.Ed
+.Pp
+By default,
+.Em libxo
+writes output to standard output. A convenience
+function is provided for situations when output should be written to
+different file.
+.Pp
+Use the
+.Em XOF_CLOSE_FP
+flag to trigger a call to
+.Em fclose 3
+for the FILE pointer when the handle is destroyed.
+.Pp
+The
+.Fn xo_destroy
+function releases a handle and any resources it is
+using. Calling
+.Fn xo_destroy
+with a
+.Em NULL
+handle will release any
+resources associated with the default handle.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+and
+.Xf xo_set_options 3 .
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_emit.3 b/contrib/libxo/libxo/xo_emit.3
new file mode 100644
index 0000000..1128dc7
--- /dev/null
+++ b/contrib/libxo/libxo/xo_emit.3
@@ -0,0 +1,71 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft int
+.Fn xo_emit "const char *fmt" "..."
+.Ft int
+.Fn xo_emit_h "xo_handle_t *xop" "const char *fmt" "..."
+.Ft int
+.Fn xo_emit_hv "xo_handle_t *xop" "const char *fmt" "va_list vap"
+.Sh DESCRIPTION
+The
+.Fn xo_emit
+function emits formatted output using the description in a format
+string along with a set of zero or more arguments, in a style similar
+to
+.Xr printf 3
+but using a more complex format description string, as described in
+.Xr xo_format 5 .
+.Pp
+.Fn xo_emit
+uses the default output handle, as described in
+.Xf libxo 3 ,
+where
+.Fn xo_emit_h
+uses an explicit handle.
+.Fn xo_emit_hv
+accepts a
+.Fa va_list
+for additional flexibility.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_open_container 3 ,
+.Xr xo_open_list 3 , and
+.Xr xo_format 5 .
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_err.3 b/contrib/libxo/libxo/xo_err.3
new file mode 100644
index 0000000..2445aa7
--- /dev/null
+++ b/contrib/libxo/libxo/xo_err.3
@@ -0,0 +1,84 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_err
+.Nd emit errors and warnings in multiple formats
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_warn "const char *fmt" "..."
+.Ft void
+.Fn xo_warnx "const char *fmt" "..."
+.Ft void
+.Fn xo_warn_c "int code" "const char *fmt" "..."
+.Ft void
+.Fn xo_warn_hc "xo_handle_t *xop" "int code, const char *fmt" "..."
+.Ft void
+.Fn xo_err "int eval" "const char *fmt" "..."
+.Ft void
+.Fn xo_errc "int eval" "int code" "const char *fmt" "..."
+.Ft void
+.Fn xo_errx "int eval" "const char *fmt" "..."
+.Ft void
+.Fn xo_message "const char *fmt" "..."
+.Ft void
+.Fn xo_message_c "int code" "const char *fmt" "..."
+.Ft void
+.Fn xo_message_hc "xo_handle_t *xop" "int code, const char *fmt" "..."
+.Ft void
+.Fn xo_message_hcv "xo_handle_t *xop" "int code" "const char *fmt" "va_list vap"
+.Sh DESCRIPTION
+Many programs make use of the standard library functions
+.Xr err 3
+and
+.Xr warn 3
+to generate errors and warnings for the user.
+.Em libxo
+wants to
+pass that information via the current output style, and provides
+compatible functions to allow this.
+.Pp
+These functions display the program name, a colon, a formatted message
+based on the arguments, and then optionally a colon and an error
+message associated with either "errno" or the "code" parameter.
+.Bd -literal -offset indent
+ EXAMPLE:
+ if (open(filename, O_RDONLY) < 0)
+ xo_err(1, "cannot open file '%s'", filename);
+.Ed
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_finish.3 b/contrib/libxo/libxo/xo_finish.3
new file mode 100644
index 0000000..3b25dc3
--- /dev/null
+++ b/contrib/libxo/libxo/xo_finish.3
@@ -0,0 +1,59 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_finish "void"
+.Ft void
+.Fn xo_finish_h "xo_handle_t *xop"
+.Sh DESCRIPTION
+When the program is ready to exit or close a handle, a call to
+.Fn xo_finish
+is required. This flushes any buffered data, closes
+open
+.Em libxo
+constructs, and completes any pending operations.
+.Pp
+Calling this function is
+.Em vital
+to the proper operation of libxo,
+especially for the non-TEXT output styles.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_flush.3 b/contrib/libxo/libxo/xo_flush.3
new file mode 100644
index 0000000..160f634
--- /dev/null
+++ b/contrib/libxo/libxo/xo_flush.3
@@ -0,0 +1,54 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_flush "void"
+.Ft void
+.Fn xo_flush_h "xo_handle_t *handle"
+.Sh DESCRIPTION
+.Em libxo
+buffers data, both for performance and consistency, but also to
+allow some advanced features to work properly. At various times, the
+caller may wish to flush any data buffered within the library. The
+.Fn xo_flush
+function is used for this.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_format.5 b/contrib/libxo/libxo/xo_format.5
new file mode 100644
index 0000000..62cfeb6
--- /dev/null
+++ b/contrib/libxo/libxo/xo_format.5
@@ -0,0 +1,657 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_format
+.Nd content of format descriptors for xo_emit
+.Sh DESCRIPTION
+.Pp
+.Em libxo
+uses format strings to control the rendering of data into
+various output styles, including
+.Em text ,
+.Em XML ,
+.EM JSON ,
+and
+.Em HTML .
+Each format string contains a set of zero or more
+.Dq field descriptions ,
+which describe independent data fields. Each
+field description contains a set of
+.Dq modifiers ,
+a
+.Dq content string ,
+and zero, one, or two
+.Dq format descriptors .
+The modifiers tell
+.Em libxo
+what the field is and how to treat it, while the format descriptors are
+formatting instructions using
+.Xr printf 3 -style
+format strings, telling
+libxo how to format the field. The field description is placed inside
+a set of braces, with a colon
+.Ql ( \&: )
+after the modifiers and a slash
+.Ql ( \&/ )
+before each format descriptors. Text may be intermixed with
+field descriptions within the format string.
+.Pp
+The field description is given as follows:
+.Bd -literal -offset indent
+ '{' [ role | modifier ]* ':' [ content ]
+ [ '/' field-format [ '/' encoding-format ]] '}'
+.Ed
+.Pp
+The role describes the function of the field, while the modifiers
+enable optional behaviors. The contents, field-format, and
+encoding-format are used in varying ways, based on the role. These
+are described in the following sections.
+.Pp
+In the following example, three field descriptors appear. The first
+is a padding field containing three spaces of padding, the second is a
+label ("In stock"), and the third is a value field ("in-stock"). The
+in-stock field has a "%u" format that will parse the next argument
+passed to the xo_emit function as an unsigned integer.
+.Bd -literal -offset indent
+ xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\\n", 65);
+.Ed
+.Pp
+This single line of code can generate text ("In stock: 65\\n"), XML
+("<in-stock>65</in-stock>"), JSON ('"in-stock": 6'), or HTML (too
+lengthy to be listed here).
+.Ss Modifier Roles
+Modifiers are optional, and indicate the role and formatting of the
+content. The roles are listed below; only one role is permitted:
+.Pp
+.Bl -column "M" "Name12341234"
+.It Sy "M Name Description"
+.It D "decoration " "Field is non-text (e.g. colon, comma)"
+.It E "error " "Field is an error message"
+.It L "label " "Field is text that prefixes a value"
+.It N "note " "Field is text that follows a value"
+.It P "padding " "Field is spaces needed for vertical alignment"
+.It T "title " "Field is a title value for headings"
+.It U "units " "Field is the units for the previous value field"
+.It V "value " "Field is the name of field (the default)"
+.It W "warning " "Field is a warning message"
+.It \&[ "start anchor" "Begin a section of anchored variable-width text"
+.It \&] "stop anchor " "End a section of anchored variable-width text"
+.El
+.Pp
+.Ss The Decoration Role ({D:})
+Decorations are typically punctuation marks such as colons,
+semi-colons, and commas used to decorate the text and make it simpler
+for human readers. By marking these distinctly, HTML usage scenarios
+can use CSS to direct their display parameters.
+.Bd -literal -offset indent
+ xo_emit("{D:((}{:name}{D:))}\\n", name);
+.Ed
+.Ss The Label Role ({L:})
+Labels are text that appears before a value.
+.Bd -literal -offset indent
+ xo_emit("{Lwc:Cost}{:cost/%u}\\n", cost);
+.Ed
+.Ss The Note Role ({N:})
+Notes are text that appears after a value.
+.Bd -literal -offset indent
+ xo_emit("{:cost/%u} {N:per year}\\n", cost);
+.Ed
+.Ss The Padding Role ({P:})
+Padding represents whitespace used before and between fields.
+The padding content can be either static, when placed directly within
+the field descriptor, or a printf-style format descriptor can be used,
+if preceded by a slash ("/"):
+.Bd -literal -offset indent
+ xo_emit("{P: }{Lwc:Cost}{:cost/%u}\\n", cost);
+ xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost);
+.Ed
+.Ss The Title Role ({T:})
+Title are heading or column headers that are meant to be displayed to
+the user. The title can be either static, when placed directly within
+the field descriptor, or a printf-style format descriptor can be used,
+if preceded by a slash ("/"):
+.Bd -literal -offset indent
+ xo_emit("{T:Interface Statistics}\\n");
+ xo_emit("{T:/%20.20s}{T:/%6.6s}\\n", "Item Name", "Cost");
+.Ed
+.Ss The Units Role ({U:})
+Units are the dimension by which values are measured, such as degrees,
+miles, bytes, and decibels. The units field carries this information
+for the previous value field.
+.Bd -literal -offset indent
+ xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles);
+.Ed
+.Pp
+Note that the sense of the 'w' modifier is reversed for units;
+a blank is added before the contents, rather than after it.
+.Pp
+When the
+.Em XOF_UNITS
+flag is set, units are rendered in XML as the
+.Dq units
+attribute:
+.Bd -literal -offset indent
+ <distance units="miles">50</distance>
+.Ed
+.Pp
+Units can also be rendered in HTML as the "data-units" attribute:
+.Bd -literal -offset indent
+ <div class="data" data-tag="distance" data-units="miles"
+ data-xpath="/top/data/distance">50</div>
+.Ed
+.Ss The Value Role ({V:} and {:})
+The value role is used to represent the a data value that is
+interesting for the non-display output styles (XML and JSON). Value
+is the default role; if no other role designation is given, the field
+is a value. The field name must appear within the field descriptor,
+followed by one or two format descriptors. The first format
+descriptor is used for display styles (TEXT and HTML), while the
+second one is used for encoding styles (XML and JSON). If no second
+format is given, the encoding format defaults to the first format,
+with any minimum width removed. If no first format is given, both
+format descriptors default to "%s".
+.Bd -literal -offset indent
+ xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n",
+ length, width, height);
+ xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\\n,
+ author, poem, year);
+.Ed
+.Ss The Anchor Modifiers ({[:} and {]:})
+The anchor roles allow a set of strings by be padded as a group,
+but still be visible to xo_emit as distinct fields. Either the start
+or stop anchor can give a field width and it can be either directly in
+the descriptor or passed as an argument. Any fields between the start
+and stop anchor are padded to meet the minimum width given.
+.Pp
+To give a width directly, encode it as the content of the anchor tag:
+.Bd -literal -offset indent
+ xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\\n", min, max);
+.Ed
+.Pp
+To pass a width as an argument, use "%d" as the format, which must
+appear after the "/". Note that only "%d" is supported for widths.
+Using any other value could ruin your day.
+.Bd -literal -offset indent
+ xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max);
+.Ed
+.Pp
+If the width is negative, padding will be added on the right, suitable
+for left justification. Otherwise the padding will be added to the
+left of the fields between the start and stop anchors, suitable for
+right justification. If the width is zero, nothing happens. If the
+number of columns of output between the start and stop anchors is less
+than the absolute value of the given width, nothing happens.
+.Pp
+Widths over 8k are considered probable errors and not supported. If
+.Em XOF_WARN
+is set, a warning will be generated.
+.Ss Modifier Flags
+The modifiers can also include the following flags, which modify the
+content emitted for some output styles:
+.Pp
+.Bl -column M "Name12341234"
+.It Sy M "Name Description"
+.It c "colon " "A colon (":") is appended after the label"
+.It d "display " "Only emit field for display styles (text/HTML)"
+.It e "encoding " "Only emit for encoding styles (XML/JSON)"
+.It k "key " "Field is a key, suitable for XPath predicates"
+.It n "no-quotes " "Do not quote the field when using JSON style"
+.It q "quotes " "Quote the field when using JSON style"
+.It w "white space " "A blank (" ") is appended after the label"
+.El
+.Pp
+For example, the modifier string "Lwc" means the field has a label
+role (text that describes the next field) and should be followed by a
+colon ('c') and a space ('w'). The modifier string "Vkq" means the
+field is has value role, that it is a key for the current instance, and
+that the value should be quoted when encoded for JSON.
+.Ss The Colon Modifier ({c:})
+The colon modifier appends a single colon to the data value:
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_emit("{Lc:Name}{:name}\\n", "phil");
+ TEXT:
+ Name:phil
+.Ed
+.Pp
+The colon modifier is only used for the TEXT and HTML output
+styles. It is commonly combined with the space modifier ('{w:').
+It is purely a convenience feature.
+.Ss The Display Modifier ({d:})
+The display modifier indicated the field should only be generated for
+the display output styles, TEXT and HTML.
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_emit("{Lcw:Name}{d:name} {:id/%d}\\n", "phil", 1);
+ TEXT:
+ Name: phil 1
+ XML:
+ <id>1</id>
+.Ed
+.Pp
+The display modifier is the opposite of the encoding modifier, and
+they are often used to give to distinct views of the underlying data.
+.Ss The Encoding Modifier ({e:})
+The display modifier indicated the field should only be generated for
+the display output styles, TEXT and HTML.
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_emit("{Lcw:Name}{:name} {e:id/%d}\\n", "phil", 1);
+ TEXT:
+ Name: phil
+ XML:
+ <name>phil</name><id>1</id>
+.Ed
+.Pp
+The encoding modifier is the opposite of the display modifier, and
+they are often used to give to distinct views of the underlying data.
+.Ss The Key Modifier ({k:})
+The key modifier is used to indicate that a particular field helps
+uniquely identify an instance of list data.
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_open_list("user");
+ for (i = 0; i < num_users; i++) {
+ xo_open_instance("user");
+ xo_emit("User {k:name} has {:count} tickets\\n",
+ user[i].u_name, user[i].u_tickets);
+ xo_close_instance("user");
+ }
+ xo_close_list("user");
+.Ed
+.Pp
+Currently the key modifier is only used when generating XPath value
+for the HTML output style when
+.Em XOF_XPATH
+is set, but other uses are likely in the near future.
+.Ss The No-Quotes Modifier ({n:})
+The no-quotes modifier (and its twin, the 'quotes' modifier) affect
+the quoting of values in the JSON output style. JSON uses quotes for
+string value, but no quotes for numeric, boolean, and null data.
+xo_emit applies a simple heuristic to determine whether quotes are
+needed, but often this needs to be controlled by the caller.
+.Bd -literal -offset indent
+ EXAMPLE:
+ const char *bool = is_true ? "true" : "false";
+ xo_emit("{n:fancy/%s}", bool);
+ JSON:
+ "fancy": true
+.Ed
+.Ss The Quotes Modifier ({q:})
+The quotes modifier (and its twin, the 'no-quotes' modifier) affect
+the quoting of values in the JSON output style. JSON uses quotes for
+string value, but no quotes for numeric, boolean, and null data.
+xo_emit applies a simple heuristic to determine whether quotes are
+needed, but often this needs to be controlled by the caller.
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_emit("{q:time/%d}", 2014);
+ JSON:
+ "year": "2014"
+.Ed
+.Ss The White Space Modifier ({w:})
+The white space modifier appends a single space to the data value:
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_emit("{Lw:Name}{:name}\\n", "phil");
+ TEXT:
+ Name phil
+.Ed
+.Pp
+The white space modifier is only used for the TEXT and HTML output
+styles. It is commonly combined with the colon modifier ('{c:').
+It is purely a convenience feature.
+.Pp
+Note that the sense of the 'w' modifier is reversed for the units role
+({Uw:}); a blank is added before the contents, rather than after it.
+.Ss Field Formatting
+The field format is similar to the format string for
+.Xr printf 3 .
+It's used varies based on the role of the field, but generally is used to
+format the field's contents.
+.Pp
+If not provided, the format string defaults to "%s".
+.Pp
+Note a field definition can contain zero or more printf-style
+.Dq directives ,
+which are sequences that start with a '%' and end with a
+one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive
+is matched by one of more arguments to the xo_emit function.
+.Pp
+The format string has the form:
+.Bd -literal -offset indent
+ '%' format-modifier * format-character
+.Ed
+.Pp
+The format- modifier can be:
+.Bl -bullet
+.It
+a '#' character, indicating the output value should be prefixed with
+'0x', typically to indicate a base 16 (hex) value.
+.It
+a minus sign ('-'), indicating the output value should be padded on
+the right instead of the left.
+.It
+a leading zero ('0') indicating the output value should be padded on the
+left with zeroes instead of spaces (' ').
+.It
+one or more digits ('0' - '9') indicating the minimum width of the
+argument. If the width in columns of the output value is less that
+the minumum width, the value will be padded to reach the minimum.
+.It
+a period followed by one or more digits indicating the maximum
+number of bytes which will be examined for a string argument, or the maximum
+width for a non-string argument. When handling ASCII strings this is
+functions as the field width but for multi-byte characters, a single
+character may be composed of multiple bytes.
+xo_emit will never dereference memory beyond the given number of bytes.
+.It
+a second period followed by one or more digits indicating the maximum
+width for a string argument. This modifier cannot be given for non-string
+arguments.
+.It
+one or more 'h' characters, indicating shorter input data.
+.It
+one or more 'l' characters, indicating longer input data.
+.It
+a 'z' character, indicating a 'size_t' argument.
+.It
+a 't' character, indicating a 'ptrdiff_t' argument.
+.It
+a ' ' character, indicating a space should be emitted before
+positive numbers.
+.It
+a '+' character, indicating sign should emitted before any number.
+.El
+.Pp
+Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be
+removed eventually.
+.Pp
+The format character is described in the following table:
+.Pp
+.Bl -column C "Argument Type12"
+.It Sy "C Argument Type Format"
+.It d "int " "base 10 (decimal)"
+.It i "int " "base 10 (decimal)"
+.It o "int " "base 8 (octal)"
+.It u "unsigned " "base 10 (decimal)"
+.It x "unsigned " "base 16 (hex)"
+.It X "unsigned long " "base 16 (hex)"
+.It D "long " "base 10 (decimal)"
+.It O "unsigned long " "base 8 (octal)"
+.It U "unsigned long " "base 10 (decimal)"
+.It e "double " "[-]d.ddde+-dd"
+.It E "double " "[-]d.dddE+-dd"
+.It f "double " "[-]ddd.ddd"
+.It F "double " "[-]ddd.ddd"
+.It g "double " "as 'e' or 'f'"
+.It G "double " "as 'E' or 'F'"
+.It a "double " "[-]0xh.hhhp[+-]d"
+.It A "double " "[-]0Xh.hhhp[+-]d"
+.It c "unsigned char " "a character"
+.It C "wint_t " "a character"
+.It s "char * " "a UTF-8 string"
+.It S "wchar_t * " "a unicode/WCS string"
+.It p "void * " "'%#lx'"
+.El
+.Pp
+The 'h' and 'l' modifiers affect the size and treatment of the
+argument:
+.Bl -column "Mod" "d, i " "o, u, x, X "
+.It Sy "Mod" "d, i " "o, u, x, X"
+.It "hh " "signed char " "unsigned char"
+.It "h " "short " "unsigned short"
+.It "l " "long " "unsigned long"
+.It "ll " "long long " "unsigned long long"
+.It "j " "intmax_t " "uintmax_t"
+.It "t " "ptrdiff_t " "ptrdiff_t"
+.It "z " "size_t " "size_t"
+.It "q " "quad_t " "u_quad_t"
+.El
+.Pp
+.Ss UTF-8 and Locale Strings
+All strings for libxo must be UTF-8. libxo will handle turning them
+into locale-based strings for display to the user.
+.Pp
+For strings, the 'h' and 'l' modifiers affect the interpretation of
+the bytes pointed to argument. The default '%s' string is a 'char *'
+pointer to a string encoded as UTF-8. Since UTF-8 is compatible with
+.Em ASCII
+data, a normal 7-bit
+.Em ASCII
+ string can be used. '%ls' expects a
+'wchar_t *' pointer to a wide-character string, encoded as a 32-bit
+Unicode values. '%hs' expects a 'char *' pointer to a multi-byte
+string encoded with the current locale, as given by the
+.Em LC_CTYPE ,
+.Em LANG ,
+or
+.Em LC_ALL
+environment varibles. The first of this list of
+variables is used and if none of the variables, the locale defaults to
+.Em UTF-8.
+.Pp
+libxo will
+convert these arguments as needed to either UTF-8 (for XML, JSON, and
+HTML styles) or locale-based strings for display in text style.
+.Bd -literal -offset indent
+ xo_emit("Alll strings are utf-8 content {:tag/%ls}",
+ L"except for wide strings");
+.Ed
+.Pp
+"%S" is equivalent to "%ls".
+.Pp
+For example, a function is passed a locale-base name, a hat size,
+and a time value. The hat size is formatted in a UTF-8 (ASCII)
+string, and the time value is formatted into a wchar_t string.
+.Bd -literal -offset indent
+ void print_order (const char *name, int size,
+ struct tm *timep) {
+ char buf[32];
+ const char *size_val = "unknown";
+
+ if (size > 0)
+ snprintf(buf, sizeof(buf), "%d", size);
+ size_val = buf;
+ }
+
+ wchar_t when[32];
+ wcsftime(when, sizeof(when), L"%d%b%y", timep);
+
+ xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n",
+ name, size_val);
+ xo_emit("It was ordered on {:order-time/%ls}.\\n",
+ when);
+ }
+.Ed
+.Pp
+It is important to note that xo_emit will perform the conversion
+required to make appropriate output. Text style output uses the
+current locale (as described above), while XML, JSON, and HTML use
+UTF-8.
+.Pp
+UTF-8 and locale-encoded strings can use multiple bytes to encode one
+column of data. The traditional "precision'" (aka "max-width") value
+for "%s" printf formatting becomes overloaded since it specifies both
+the number of bytes that can be safely referenced and the maximum
+number of columns to emit. xo_emit uses the precision as the former,
+and adds a third value for specifying the maximum number of columns.
+.Pp
+In this example, the name field is printed with a minimum of 3 columns
+and a maximum of 6. Up to ten bytes are in used in filling those
+columns.
+.Bd -literal -offset indent
+ xo_emit("{:name/%3.10.6s}", name);
+.Ed
+.Ss Characters Outside of Field Definitions
+Characters in the format string are not part of a field definition are
+copied to the output for the TEXT style, and are ignored for the JSON
+and XML styles. For HTML, these characters are placed in a <div> with
+class "text".
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_emit("The hat is {:size/%s}.\\n", size_val);
+ TEXT:
+ The hat is extra small.
+ XML:
+ <size>extra small</size>
+ JSON:
+ "size": "extra small"
+ HTML:
+ <div class="text">The hat is </div>
+ <div class="data" data-tag="size">extra small</div>
+ <div class="text">.</div>
+.Ed
+.Ss "%n" is Not Supported
+libxo does not support the '%n' directive. It's a bad idea and we
+just don't do it.
+.Ss The Encoding Format (eformat)
+The "eformat" string is the format string used when encoding the field
+for JSON and XML. If not provided, it defaults to the primary format
+with any minimum width removed. If the primary is not given, both
+default to "%s".
+.Sh EXAMPLE
+In this example, the value for the number of items in stock is emitted:
+.Bd -literal -offset indent
+ xo_emit("{P: }{Lwc:In stock}{:in-stock/%u}\\n",
+ instock);
+.Ed
+.Pp
+This call will generate the following output:
+.Bd -literal -offset indent
+ TEXT:
+ In stock: 144
+ XML:
+ <in-stock>144</in-stock>
+ JSON:
+ "in-stock": 144,
+ HTML:
+ <div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">144</div>
+ </div>
+.Ed
+.Pp
+Clearly HTML wins the verbosity award, and this output does
+not include
+.Em XOF_XPATH
+or
+.Em XOF_INFO
+data, which would expand the penultimate line to:
+.Bd -literal -offset indent
+ <div class="data" data-tag="in-stock"
+ data-xpath="/top/data/item/in-stock"
+ data-type="number"
+ data-help="Number of items in stock">144</div>
+.Ed
+.Sh WHAT MAKES A GOOD FIELD NAME?
+To make useful, consistent field names, follow these guidelines:
+.Pp
+.Ss Use lower case, even for TLAs
+Lower case is more civilized. Even TLAs should be lower case
+to avoid scenarios where the differences between "XPath" and
+"Xpath" drive your users crazy. Using "xpath" is simpler and better.
+.Ss Use hyphens, not underscores
+Use of hyphens is traditional in XML, and the
+.Em XOF_UNDERSCORES
+flag can be used to generate underscores in JSON, if desired.
+But the raw field name should use hyphens.
+.Se Use full words
+Don't abbreviate especially when the abbreviation is not obvious or
+not widely used. Use "data-size", not "dsz" or "dsize". Use
+"interface" instead of "ifname", "if-name", "iface", "if", or "intf".
+.Se Use <verb>-<units>
+Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in
+making consistent, useful names, avoiding the situation where one app
+uses "sent-packet" and another "packets-sent" and another
+"packets-we-have-sent". The <units> can be dropped when it is
+obvious, as can obvious words in the classification.
+Use "receive-after-window-packets" instead of
+"received-packets-of-data-after-window".
+.Se Reuse existing field names
+Nothing's worse than writing expressions like:
+.Bd -literal -offset indent
+ if ($src1/process[pid == $pid]/name ==
+ $src2/proc-table/proc/p[process-id == $pid]/proc-name) {
+ ...
+ }
+.Ed
+.Pp
+Find someone else who is expressing similar data and follow their
+field's and hierarchy. Remember the quote is not
+.Dq Consistency is the hobgoblin of little minds
+but
+.Dq A foolish consistency is the hobgoblin of little minds.
+.Ss Think about your users
+Have empathy for your users, choosing clear and useful fields that
+contain clear and useful data. You may need to augment the display
+content with
+.Xr xo_attr 3
+calls or "{e:}" fields to make the data useful.
+.Ss Don't use an arbitrary number postfix
+What does "errors2" mean? No one will know. "errors-after-restart"
+would be a better choice. Think of you users, and think of the
+future. If you make "errors2", the next guy will happily make
+"errors3" and before you know it, someone will be asking what's the
+difference between errors37 and errors63.
+.Ss Be consistent, uniform, unsurprising, and predictable
+Think of your field vocabulary as an API. You want it useful,
+expressive, meaningful, direct, and obvious. You want the client
+application's programmer to move between without the need to
+understand a variety of opinions on how fields are named. They should
+see the system as a single cohesive whole, not a sack of cats.
+.Pp
+Field names constitute the means by which client programmers interact
+with our system. By choosing wise names now, you are making their
+lives better.
+.Pp
+After using
+.Xr xolint 1
+to find errors in your field descriptors, use
+.Dq "xolint -V"
+to spell check your field names and to detect different
+names for the same data.
+.Dq dropped-short
+and
+.Dq dropped-too-short
+are both reasonable names, but using them both will lead users to ask the
+difference between the two fields. If there isn't a difference,
+use only one of the field names. If there is a difference, change the
+names to make that difference more obvious.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_no_setlocale.3 b/contrib/libxo/libxo/xo_no_setlocale.3
new file mode 100644
index 0000000..94a1264
--- /dev/null
+++ b/contrib/libxo/libxo/xo_no_setlocale.3
@@ -0,0 +1,63 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_no_setlocale
+.Nd prevent implicit call to setlocale()
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_no_setlocale "void"
+.Sh DESCRIPTION
+.Em libxo
+automatically initializes the locale based on setting of the
+environment variables
+.Em LC_CTYPE ,
+.Em LANG ,
+and
+.Em LC_ALL .
+The first of this
+list of variables is used and if none of the variables, the locale
+defaults to
+.Em UTF-8. The caller may wish to avoid this behavior, and
+can do so by calling the
+.Fn xo_no_setlocale
+function.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3 ,
+.Xr xo_open_container 3 ,
+.Xr xo_open_list 3 , and
+.Xr xo_format 5 .
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_open_container.3 b/contrib/libxo/libxo/xo_open_container.3
new file mode 100644
index 0000000..af54d05
--- /dev/null
+++ b/contrib/libxo/libxo/xo_open_container.3
@@ -0,0 +1,216 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Sh NAME
+.Nm xo_open_container
+.Nm xo_open_container_h
+.Nm xo_open_container_hd
+.Nm xo_open_container_d
+.Nm xo_close_container
+.Nm xo_close_container_h
+.Nm xo_close_container_hd
+.Nm xo_close_container_d
+.Nd open and close containers
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.Ft int
+.Fn xo_open_container "const char *name"
+.Ft int
+.Fn xo_open_container_h "xo_handle_t *handle" "const char *name"
+.Ft int
+.Fn xo_open_container_hd "xo_handle_t *handle" "const char *name"
+.Ft int
+.Fn xo_open_container_d "const char *name"
+.Ft int
+.Fn xo_close_container "const char *name"
+.Ft int
+.Fn xo_close_container_h "xo_handle_t *handle" "const char *name"
+.Ft int
+.Fn xo_close_container_hd "xo_handle_t *handle"
+.Ft int
+.Fn xo_close_container_d "void"
+.Sh DESCRIPTION
+.Fa libxo
+represents to types of hierarchy:
+.Dq containers
+and
+.Dq lists .
+A container appears once under a given parent where a list contains
+instances that can appear multiple times. A container is used to hold
+related fields and to give the data organization and scope.
+The container has no value, but serves to
+contain other nodes.
+.Pp
+To open a container, call
+.Fn xo_open_container
+or
+.Fn xo_open_container_h .
+The former uses the default handle and
+the latter accepts a specific handle.
+.Pp
+To close a level, use the
+.Fn xo_close_container
+or
+.Fn xo_close_container_h
+functions.
+.Pp
+Each open call must have a matching close call. If the
+.Fa XOF_WARN
+flag is set and the name given does not match the name of
+the currently open
+container, a warning will be generated.
+.Bd -literal -offset indent -compact
+ Example:
+
+ xo_open_container("top");
+ xo_open_container("system");
+ xo_emit("{:host-name/%s%s%s", hostname,
+ domainname ? "." : "", domainname ?: "");
+ xo_close_container("system");
+ xo_close_container("top");
+
+ Sample Output:
+ Text:
+ my-host.example.org
+ XML:
+ <top>
+ <system>
+ <host-name>my-host.example.org</host-name>
+ </system>
+ </top>
+ JSON:
+ "top" : {
+ "system" : {
+ "host-name": "my-host.example.org"
+ }
+ }
+ HTML:
+ <div class="data"
+ data-tag="host-name">my-host.example.org</div>
+.Ed
+.SH EMITTING HIERARCHY
+To create a container, use the
+.Fn xo_open_container
+and
+.Fn xo_close_container
+set of functions.
+The
+.Fa handle
+parameter contains a handle such as returned by
+.Xr xo_create 3
+or a
+.Em NULL
+to use the default handle.
+The
+.Fa name
+parameter gives the name of the container, encoded in
+.Em UTF-8 .
+Since
+.Em ASCII
+is a proper subset of
+.Em UTF-8 ,
+traditional C strings can be used directly.
+.Pp
+The close functions with the
+.Dq _d
+suffix are used in
+.Dq Do The Right Thing
+mode, where the name of the open containers, lists, and
+instances are maintained internally by
+.Em libxo
+to allow the caller to
+avoid keeping track of the open container name.
+.Pp
+Use the
+.Em XOF_WARN
+flag to generate a warning if the name given on the
+close does not match the current open container.
+.Pp
+For TEXT and HTML output, containers are not rendered into output
+text, though for HTML they are used when the
+.Em XOF_XPATH
+flag is set.
+.Pp
+.Bd -literal -offset indent -compact
+ EXAMPLE:
+ xo_open_container("system");
+ xo_emit("The host name is {:host-name}\n", hn);
+ xo_close_container("system");
+ XML:
+ <system><host-name>foo</host-name></system>
+.Ed
+.Sh DTRT MODE
+Some user may find tracking the names of open containers, lists, and
+instances inconvenient.
+.Em libxo
+offers
+.Dq Do The Right Thing
+mode, where
+.Em libxo
+will track the names of open containers, lists, and instances so
+the close function can be called without a name. To enable
+.Em DTRT
+mode,
+turn on the
+.Em XOF_DTRT
+flag prior to making any other
+.Em libxo
+output.
+.Bd -literal -offset indent -compact
+ xo_set_flags(NULL, XOF_DTRT);
+.Ed
+Each open and close function has a version with the suffix
+.Dq _d ,
+which will close the open container, list, or instance:
+.Bd -literal -offset indent -compact
+ xo_open_container("top");
+ ...
+ xo_close_container_d();
+.Ed
+Note that the
+.Em XOF_WARN
+flag will also cause libxo to track open
+containers, lists, and instances.
+A warning is generated with the name given to the close function
+and the name recorded do not match.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_open_list.3 b/contrib/libxo/libxo/xo_open_list.3
new file mode 100644
index 0000000..9a6a215
--- /dev/null
+++ b/contrib/libxo/libxo/xo_open_list.3
@@ -0,0 +1,169 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Sh NAME
+.Nm xo_open_list
+.Nm xo_open_list_h
+.Nm xo_open_list_hd
+.Nm xo_open_list_d
+.Nm xo_open_instance
+.Nm xo_open_instance_h
+.Nm xo_open_instance_hd
+.Nm xo_open_instance_d
+.Nm xo_close_instance
+.Nm xo_close_instance_h
+.Nm xo_close_instance_hd
+.Nm xo_close_instance_d
+.Nm xo_close_list
+.Nm xo_close_list_h
+.Nm xo_close_list_hd
+.Nm xo_close_list_d
+.Nd open and close lists and instances
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.Ft int
+.Fn xo_open_list_h "xo_handle_t *xop" "const char *name"
+.Ft int
+.Fn xo_open_list "const char *name"
+.Ft int
+.Fn xo_open_list_hd "xo_handle_t *xop" "const char *name"
+.Ft int
+.Fn xo_open_list_d "const char *name"
+.Ft int
+.Fn xo_open_instance_h "xo_handle_t *xop" "const char *name"
+.Ft int
+.Fn xo_open_instance "const char *name"
+.Ft int
+.Fn xo_open_instance_hd "xo_handle_t *xop" "const char *name"
+.Ft int
+.Fn xo_open_instance_d "const char *name"
+.Ft int
+.Fn xo_close_instance_h "xo_handle_t *xop" "const char *name"
+.Ft int
+.Fn xo_close_instance "const char *name"
+.Ft int
+.Fn xo_close_instance_hd "xo_handle_t *xop"
+.Ft int
+.Fn xo_close_instance_d "void"
+.Ft int
+.Fn xo_close_list_h "xo_handle_t *xop" "const char *name"
+.Ft int
+.Fn xo_close_list "const char *name"
+.Ft int
+.Fn xo_close_list_hd "xo_handle_t *xop"
+.Ft int
+.Fn xo_close_list_d "void"
+.Sh DESCRIPTION
+Lists are sequences of instances of homogeneous data objects. Two
+distinct levels of calls are needed to represent them in our output
+styles. Calls must be made to open and close a list, and for each
+instance of data in that list, calls must be make to open and close
+that instance.
+.Pp
+The name given to all calls must be identical, and it is strong
+suggested that the name be singular, not plural, as a matter of
+style and usage expectations.
+.Pp
+A list is set of one or more instances that appear under the same
+parent. The instances contains details about a specific object. One
+can think of instances as objects or records. A call is needed to
+open and close the list, while a distinct call is needed to open and
+close each instance of the list:
+.Bd -literal -offset indent -compact
+ xo_open_list("item");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+ xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+.Ed
+Getting the list and instance calls correct is critical to the proper
+generation of XML and JSON data.
+.Pp
+.Bd -literal -offset indent -compact
+ EXAMPLE:
+ xo_open_list("user");
+ for (i = 0; i < num_users; i++) {
+ xo_open_instance("user");
+ xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n",
+ pw[i].pw_name, pw[i].pw_uid,
+ pw[i].pw_gid, pw[i].pw_dir);
+ xo_close_instance("user");
+ }
+ xo_close_list("user");
+ TEXT:
+ phil:1001:1001:/home/phil
+ pallavi:1002:1002:/home/pallavi
+ XML:
+ <user>
+ <name>phil</name>
+ <uid>1001</uid>
+ <gid>1001</gid>
+ <home>/home/phil</home>
+ </user>
+ <user>
+ <name>pallavi</name>
+ <uid>1002</uid>
+ <gid>1002</gid>
+ <home>/home/pallavi</home>
+ </user>
+ JSON:
+ user: [
+ {
+ "name": "phil",
+ "uid": 1001,
+ "gid": 1001,
+ "home": "/home/phil",
+ },
+ {
+ "name": "pallavi",
+ "uid": 1002,
+ "gid": 1002,
+ "home": "/home/pallavi",
+ }
+ ]
+.Ed
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_parse_args.3 b/contrib/libxo/libxo/xo_parse_args.3
new file mode 100644
index 0000000..a9b4cec
--- /dev/null
+++ b/contrib/libxo/libxo/xo_parse_args.3
@@ -0,0 +1,133 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_parse_args
+.Nd detect, parse, and remove arguments for libxo
+.Sh LIBRARY
+.Nm libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft int
+.Fn xo_parse_args "int argc" "char **argv"
+.Sh DESCRIPTION
+The
+.Fn xo_parse_args
+function is used to process command-line arguments.
+.Em libxo -specific
+options are processed and removed
+from the argument list so the calling application does not
+need to process them. If successful, a new value for argc
+is returned. On failure, a message it emitted and -1 is returned.
+.Bd -literal -offset indent
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ exit(1);
+.Ed
+.Pp
+Following the call to
+.Fn xo_parse_args ,
+the application can process the remaining arguments in a normal manner.
+.Pp
+.Em libxo
+uses command line options to trigger rendering behavior. The
+following options are recognised:
+.Pp
+.Bl -tag -width "--libxo"
+.It
+\-\^\-libxo <options>
+.It
+\-\^\-libxo=<options>
+.It
+\-\^\-libxo:<brief-options>
+.El
+.Pp
+Options is a comma-separated list of tokens that correspond to output
+styles, flags, or features:
+.Pp
+.Bl -tag -width "12345678"
+.It Sy "Token Action"
+.It dtrt
+Enable "Do The Right Thing" mode
+.It html
+Emit HTML output
+.It indent=xx
+Set the indentation level
+.It info
+Add info attributes (HTML)
+.It json
+Emit JSON output
+.It keys
+Emit the key attribute for keys (XML)
+.It no-locale
+Do not initialize the locale setting
+.It no-top
+Do not emit a top set of braces (JSON)
+.It not-first
+Pretend the 1st output item was not 1st (JSON)
+.It pretty
+Emit pretty-printed output
+.It text
+Emit TEXT output
+.It units
+Add the 'units' (XML) or 'data-units (HTML) attribute
+.It warn
+Emit warnings when libxo detects bad calls
+.It warn-xml
+Emit warnings in XML
+.It xml
+Emit XML output
+.It xpath
+Add XPath expressions (HTML)
+.El
+.Pp
+The
+.Dq brief-options
+are single letter commands, designed for those with
+too little patience to use real tokens. No comma separator is used.
+.Bl -column "i<num>"
+.It Sy "Token Action"
+.It "H " "Enable HTML output (XO_STYLE_HTML)"
+.It "I " "Enable info output (XOF_INFO)"
+.It "i<num> " "Indent by <number>"
+.It "J " "Enable JSON output (XO_STYLE_JSON)"
+.It "P " "Enable pretty-printed output (XOF_PRETTY)"
+.It "T " "Enable text output (XO_STYLE_TEXT)"
+.It "W " "Enable warnings (XOF_WARN)"
+.It "X " "Enable XML output (XO_STYLE_XML)"
+.It "x " "Enable XPath data (XOF_XPATH)"
+.El
+.Pp
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_allocator.3 b/contrib/libxo/libxo/xo_set_allocator.3
new file mode 100644
index 0000000..508cc8e
--- /dev/null
+++ b/contrib/libxo/libxo/xo_set_allocator.3
@@ -0,0 +1,73 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Sy typedef void *(*xo_realloc_func_t)(void *, size_t);
+.Pp
+.Sy typedef void (*xo_free_func_t)(void *);
+.Ft void
+.Fn xo_set_allocator "xo_realloc_func_t realloc_func" "xo_free_func_t free_func"
+.Sh DESCRIPTION
+The
+.Fn xo_set_allocator
+function allows libxo to be used in environments
+where the standard
+.Xr realloc 3
+and
+.Xr free 3
+functions are not available.
+.Pp
+.Fa realloc_func
+should expect the same arguments as
+.Xr realloc 3
+and return
+a pointer to memory following the same convention.
+.Fa free_func
+will receive the same argument as
+.Xr free 3
+and should release it, asappropriate for the environment.
+.Pp
+By default, the standard
+.Xr realloc 3
+and
+.Xr free 3
+functions are used.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_flags.3 b/contrib/libxo/libxo/xo_set_flags.3
new file mode 100644
index 0000000..a23de7b
--- /dev/null
+++ b/contrib/libxo/libxo/xo_set_flags.3
@@ -0,0 +1,128 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_set_flags "xo_handle_t *handle" "unsigned flags"
+.Ft void
+.Fn xo_clear_flags "xo_handle_t *handle" "xo_xof_flags_t flags"
+.Sh DESCRIPTION
+Use the
+.Fn xo_set_flags
+function to set the flags for a
+.Em libxo
+handle. To use the default handle, pass a NULL handle.
+.Pp
+The set of valid flags include:
+.Bl -tag -width "XOF_UNDERSCORES"
+.It Sy "Flag Description"
+.It XOF_CLOSE_FP
+Close file pointer on xo_destroy(). This
+flag will trigger the call of the close_func
+(provided via
+.Fn xo_set_writer 3 )
+when the handle is destroyed.
+.It XOF_DTRT
+Enable "do the right thing" mode
+.It XOF_INFO
+Display info data attributes (HTML)
+.It XOF_KEYS
+Emit the key attribute (XML)
+.It XOF_NO_ENV
+Do not use the LIBXO_OPTIONS env var
+.It XOF_PRETTY
+Make 'pretty printed' output, with the
+addition of indentation and newlines to enhance the readability of
+XML, JSON, and HTML output. Text output is not affected.
+.It XOF_UNDERSCORES
+Replaces hyphens with underscores
+.It XOF_UNITS
+Display units (XML and HMTL)
+.It XOF_WARN
+Generate warnings for broken calls, triggering diagnostic
+output (on standard error) when the library notices errors during
+operations, or with arguments to functions. Without warning enabled,
+such conditions are ignored.
+Warnings allow developers to debug their interaction with libxo.
+The function "xo_failure" can used as a breakpoint for a debugger,
+regardless of whether warnings are enabled.
+.It XOF_WARN_XML
+Generate warnings in XML on stdout
+.It XOF_XPATH
+Emit XPath expressions (HTML)
+.It XOF_COLUMNS
+Force xo_emit to return columns used
+.It XOF_FLUSH
+Flush output after each xo_emit call
+.El
+.Pp
+If the style is XO_STYLE_HTML, the following additional flags can be
+used:
+.Bl -tag -width "XOF_UNDERSCORES"
+.It Sy "Flag Description"
+.It XOF_XPATH
+Emit "data-xpath" attributes
+.It XOF_INFO
+Emit additional informational fields for HTML
+output. See
+.Xr xo_set_info 3
+for details.
+.El
+.Pp
+The
+.Em XOF_XPATH
+flag enables the emission of XPath expressions detailing
+the hierarchy of XML elements used to encode the data field, if the
+XPATH style of output were requested.
+.Pp
+If the style is XO_STYLE_XML, the following additional flags can be
+used:
+.Bl -tag -width "XOF_UNDERSCORES"
+.It Sy "Flag Description"
+.It XOF_KEYS
+Add 'key' attribute to the XML encoding for
+field definitions that use the 'k' modifier. The key attribute has
+the value "key".
+.El
+.Pp
+The xo_clear_flags() function turns off the given flags in a specific
+handle.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_info.3 b/contrib/libxo/libxo/xo_set_info.3
new file mode 100644
index 0000000..dbb3c9c
--- /dev/null
+++ b/contrib/libxo/libxo/xo_set_info.3
@@ -0,0 +1,113 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_set_info "xo_handle_t *handle" "xo_info_t *info" "int count"
+.Sh DESCRIPTION
+HTML data can include additional information in attributes that
+begin with "data-". To enable this, three things must occur:
+.Pp
+First the application must build an array of xo_info_t structures,
+one per tag. The array must be sorted by name, since
+.Em libxo
+uses a
+binary search to find the entry that matches names from format
+instructions.
+.Pp
+The
+.Em xo_info_t
+structure is defined in
+.Em <libxo/xo.h> :
+.Bd -literal -offset indent
+ typedef struct xo_info_s {
+ const char *xi_name; /* Name of the element */
+ const char *xi_type; /* Type of field */
+ const char *xi_help; /* Description of field */
+ } xo_info_t;
+.Ed
+.Pp
+Second, the application must inform
+.Em libxo
+about this information using the
+.Fn xo_set_info
+call. Like other libxo calls, passing NULL for the handle tells
+.Em libxo
+to use the default handle.
+.Pp
+If the
+.Fa count
+is -1,
+.Em libxo
+will count the elements of
+.Fa info ,
+but there
+must be an empty element at the end. More typically, the number is
+known to the application:
+.Bd -literal -offset indent
+ xo_info_t info[] = {
+ { "in-stock", "number", "Number of items in stock" },
+ { "name", "string", "Name of the item" },
+ { "on-order", "number", "Number of items on order" },
+ { "sku", "string", "Stock Keeping Unit" },
+ { "sold", "number", "Number of items sold" },
+ };
+ int info_count = (sizeof(info) / sizeof(info[0]));
+ ...
+ xo_set_info(NULL, info, info_count);
+.Ed
+.Pp
+Third, the emitting of info must be triggered with the
+.Em XOF_INFO
+flag
+using either the
+.Fn xo_set_flags
+function or the
+.Dq --libxo=info
+command line argument.
+.Pp
+The type and help values, if present, are emitted as the "data-type"
+and "data-help" attributes:
+.Bd -literal -offset indent
+ <div class="data" data-tag="sku" data-type="string"
+ data-help="Stock Keeping Unit">GRO-000-533</div>
+.Ed
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_options.3 b/contrib/libxo/libxo/xo_set_options.3
new file mode 100644
index 0000000..af7e95c
--- /dev/null
+++ b/contrib/libxo/libxo/xo_set_options.3
@@ -0,0 +1,52 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft int
+.Fn xo_set_options "xo_handle_t *xop" "const char *input"
+.Sh DESCRIPTION
+The
+.Fn xo_set_options
+function accepts a comma-separated list of styles
+and flags and enables them for a specific handle.
+The options are identical to those listed in
+.Xr xo_parse_args 3 .
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_style.3 b/contrib/libxo/libxo/xo_set_style.3
new file mode 100644
index 0000000..83371ac
--- /dev/null
+++ b/contrib/libxo/libxo/xo_set_style.3
@@ -0,0 +1,72 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Fn xo_set_style "xo_handle_t *handle" "unsigned style"
+.Ft int
+.Fn xo_set_style_name "xo_handle_t *handle" "const char *style"
+.Sh DESCRIPTION
+Use the
+.Fn xo_set_style
+function to set the output style for a handle.
+To use the default handle, pass a NULL handle.
+The set of output styles used by
+.Em libxo
+is:
+.Bl -column "XO_STYLE_TEXT12"
+.It Sy "Flag Description"
+.It "XO_STYLE_TEXT Traditional text output"
+.It "XO_STYLE_XML XML encoded data"
+.It "XO_STYLE_JSON JSON encoded data"
+.It "XO_STYLE_HTML HTML encoded data"
+.El
+.Pp
+The
+.Fn xo_set_style_name
+function can be used to set the style based on a name
+encoded as a string.
+The name can be any of the styles: "text", "xml", "json", or "html".
+.Bd -literal -offset indent
+ EXAMPLE:
+ xo_set_style_name(NULL, "html");
+.Ed
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xo_set_writer.3 b/contrib/libxo/libxo/xo_set_writer.3
new file mode 100644
index 0000000..9185f10
--- /dev/null
+++ b/contrib/libxo/libxo/xo_set_writer.3
@@ -0,0 +1,68 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo_emit
+.Nd emit formatted output based on format string and arguments
+.Sh LIBRARY
+.Lb libxo
+.Sh SYNOPSIS
+.In libxo/xo.h
+.Ft void
+.Sy typedef int (*xo_write_func_t)(void *, const char *);
+.Pp
+.Sy typedef void (*xo_close_func_t)(void *);
+.Fn xo_set_writer "xo_handle_t *handle" "void *opaque"
+ "xo_write_func_t write_func"
+ "xo_close_func_t close_func"
+.Sh DESCRIPTION
+The
+.Fn xo_set_writer
+function allows custom
+.Dq write
+functions
+which can tailor how
+.Em libxo
+writes data. An
+.Fa opaque
+argument is
+recorded and passed back to the
+.Fa write_func
+function, allowing the function
+to acquire context information. The
+.Fa close_func
+function can
+release this opaque data and any other resources as needed.
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/libxo/xoconfig.h.in b/contrib/libxo/libxo/xoconfig.h.in
new file mode 100644
index 0000000..3fe7365
--- /dev/null
+++ b/contrib/libxo/libxo/xoconfig.h.in
@@ -0,0 +1,198 @@
+/* libxo/xoconfig.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the `bzero' function. */
+#undef HAVE_BZERO
+
+/* Define to 1 if you have the `ctime' function. */
+#undef HAVE_CTIME
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `dlfunc' function. */
+#undef HAVE_DLFUNC
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the `fdopen' function. */
+#undef HAVE_FDOPEN
+
+/* Define to 1 if you have the `flock' function. */
+#undef HAVE_FLOCK
+
+/* Define to 1 if you have the `getpass' function. */
+#undef HAVE_GETPASS
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Support printflike */
+#undef HAVE_PRINTFLIKE
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the `srand' function. */
+#undef HAVE_SRAND
+
+/* Define to 1 if you have the `sranddev' function. */
+#undef HAVE_SRANDDEV
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <stdtime/tzfile.h> header file. */
+#undef HAVE_STDTIME_TZFILE_H
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strcspn' function. */
+#undef HAVE_STRCSPN
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strspn' function. */
+#undef HAVE_STRSPN
+
+/* Define to 1 if you have the `sysctlbyname' function. */
+#undef HAVE_SYSCTLBYNAME
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <tzfile.h> header file. */
+#undef HAVE_TZFILE_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Enable debugging */
+#undef LIBXO_DEBUG
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/contrib/libxo/libxo/xoversion.h.in b/contrib/libxo/libxo/xoversion.h.in
new file mode 100644
index 0000000..777e83e
--- /dev/null
+++ b/contrib/libxo/libxo/xoversion.h.in
@@ -0,0 +1,38 @@
+/*
+ * $Id$
+ *
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ *
+ * xoversion.h -- compile time constants for libxo
+ * NOTE: This file is generated from xoversion.h.in.
+ */
+
+#ifndef LIBXO_XOVERSION_H
+#define LIBXO_XOVERSION_H
+
+/**
+ * The version string
+ */
+#define LIBXO_VERSION "@PACKAGE_VERSION@"
+
+/**
+ * The version number
+ */
+#define LIBXO_VERSION_NUMBER @LIBXO_VERSION_NUMBER@
+
+/**
+ * The version number as a string
+ */
+#define LIBXO_VERSION_STRING "@LIBXO_VERSION_NUMBER@"
+
+/**
+ * The version number extra info as a string
+ */
+#define LIBXO_VERSION_EXTRA "@LIBXO_VERSION_EXTRA@"
+
+#endif /* LIBXO_XOVERSION_H */
diff --git a/contrib/libxo/m4/libtool.m4 b/contrib/libxo/m4/libtool.m4
new file mode 100644
index 0000000..44e0ecf
--- /dev/null
+++ b/contrib/libxo/m4/libtool.m4
@@ -0,0 +1,7982 @@
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
+# 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING. If not, a copy
+# can be downloaded from http://www.gnu.org/licenses/gpl.html, or
+# obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+])
+
+# serial 57 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+ [m4_default([$3],
+ [m4_fatal([Libtool version $1 or higher is required],
+ 63)])],
+ [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+ *\ * | *\ *)
+ AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ltmain"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+m4_defun([_LT_CC_BASENAME],
+[for cc_temp in $1""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options which allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ _LT_PATH_MAGIC
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from `configure', and `config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
+# `config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain="$ac_aux_dir/ltmain.sh"
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the `libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+ [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME. Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+ [m4_ifval([$1], [$1], [$2])])
+ lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+ m4_ifval([$4],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+ lt_dict_add_subkey([lt_decl_dict], [$2],
+ [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+ [0], [m4_fatal([$0: too few arguments: $#])],
+ [1], [m4_fatal([$0: too few arguments: $#: $1])],
+ [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+ [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+ [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+ m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_if([$2], [],
+ m4_quote(lt_decl_varnames),
+ m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+ lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to `config.status' so that its
+# declaration there will have the same value as in `configure'. VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly. In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+ [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags="_LT_TAGS"dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+# # Some comment about what VAR is for.
+# visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+ [description])))[]dnl
+m4_pushdef([_libtool_name],
+ m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+ [0], [_libtool_name=[$]$1],
+ [1], [_libtool_name=$lt_[]$1],
+ [2], [_libtool_name=$lt_[]$1],
+ [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the `libtool'
+# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+ m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into `config.status', and then the shell code to quote escape them in
+# for loops in `config.status'. Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+ dnl If the libtool generation code has been placed in $CONFIG_LT,
+ dnl instead of duplicating it all over again into config.status,
+ dnl then we will have config.status run $CONFIG_LT later, so it
+ dnl needs to know what name is stored there:
+ [AC_CONFIG_COMMANDS([libtool],
+ [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+ dnl If the libtool generation code is destined for config.status,
+ dnl expand the accumulated commands and init code now:
+ [AC_CONFIG_COMMANDS([libtool],
+ [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\""
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable. If COMMENT is supplied, it is inserted after the
+# `#!' sequence but before initialization text begins. After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script. The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test $lt_write_fail = 0 && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+ echo
+ AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+\`$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test $[#] != 0
+do
+ case $[1] in
+ --version | --v* | -V )
+ echo "$lt_cl_version"; exit 0 ;;
+ --help | --h* | -h )
+ echo "$lt_cl_help"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --quiet | --q* | --silent | --s* | -q )
+ lt_cl_silent=: ;;
+
+ -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try \`$[0] --help' for more information.]) ;;
+
+ *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try \`$[0] --help' for more information.]) ;;
+ esac
+ shift
+done
+
+if $lt_cl_silent; then
+ exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure. Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test "$silent" = yes &&
+ lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars. Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+ m4_if(_LT_TAG, [C], [
+ # See if we are running on zsh, and set the options which allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}" ; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile="${ofile}T"
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+
+# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+ _LT_PROG_LTMAIN
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ _LT_PROG_REPLACE_SHELLFNS
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ TIMESTAMP='$TIMESTAMP'
+ RM='$RM'
+ ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+# autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+ [C], [_LT_LANG(C)],
+ [C++], [_LT_LANG(CXX)],
+ [Go], [_LT_LANG(GO)],
+ [Java], [_LT_LANG(GCJ)],
+ [Fortran 77], [_LT_LANG(F77)],
+ [Fortran], [_LT_LANG(FC)],
+ [Windows Resource], [_LT_LANG(RC)],
+ [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+ [_LT_LANG($1)],
+ [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+ [LT_SUPPORTED_TAG([$1])dnl
+ m4_append([_LT_TAGS], [$1 ])dnl
+ m4_define([_LT_LANG_]$1[_enabled], [])dnl
+ _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_GO. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC], [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+ fi
+fi
+if test -z "$GOC"; then
+ AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [LT_LANG(CXX)],
+ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [LT_LANG(F77)],
+ [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+ [LT_LANG(FC)],
+ [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [m4_ifdef([AC_PROG_GCJ],
+ [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([A][M_PROG_GCJ],
+ [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([LT_PROG_GCJ],
+ [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+ [LT_LANG(GO)],
+ [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+ [LT_LANG(RC)],
+ [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+ case $host_os in
+ rhapsody* | darwin*)
+ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+ AC_CHECK_TOOL([LIPO], [lipo], [:])
+ AC_CHECK_TOOL([OTOOL], [otool], [:])
+ AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+ _LT_DECL([], [DSYMUTIL], [1],
+ [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+ _LT_DECL([], [NMEDIT], [1],
+ [Tool to change global to local symbols on Mac OS X])
+ _LT_DECL([], [LIPO], [1],
+ [Tool to manipulate fat objects and archives on Mac OS X])
+ _LT_DECL([], [OTOOL], [1],
+ [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+ _LT_DECL([], [OTOOL64], [1],
+ [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+ [lt_cv_apple_cc_single_mod=no
+ if test -z "${LT_MULTI_MODULE}"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ # If there is a non-empty error log, and "single_module"
+ # appears in it, assume the flag caused a linker warning
+ if test -s conftest.err && $GREP single_module conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ # Otherwise, if the output was created with a 0 exit code from
+ # the compiler, it worked.
+ elif test -f libconftest.dylib && test $_lt_result -eq 0; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi])
+
+ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+ [lt_cv_ld_exported_symbols_list],
+ [lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [lt_cv_ld_exported_symbols_list=yes],
+ [lt_cv_ld_exported_symbols_list=no])
+ LDFLAGS="$save_LDFLAGS"
+ ])
+
+ AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+ [lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+ echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+ $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+ echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+ $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -s conftest.err && $GREP force_load conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+ ])
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ darwin*) # darwin 5.x on
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ 10.[[012]]*)
+ _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test "$lt_cv_apple_cc_single_mod" = "yes"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test "$lt_cv_ld_exported_symbols_list" = "yes"; then
+ _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}'
+ fi
+ if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+ m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ if test "$lt_cv_ld_force_load" = "yes"; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+ m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+ [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=func_echo_all
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ m4_if([$1], [CXX],
+[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+ fi
+],[])
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test "${lt_cv_aix_libpath+set}" = set; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+ lt_aix_libpath_sed='[
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }]'
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi],[])
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib"
+ fi
+ ])
+ aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script which will find a shell with a builtin
+# printf (which we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+case "$ECHO" in
+ printf*) AC_MSG_RESULT([printf]) ;;
+ print*) AC_MSG_RESULT([print -r]) ;;
+ *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test "X`printf %s $ECHO`" = "X$ECHO" \
+ || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[ --with-sysroot[=DIR] Search for dependent libraries within DIR
+ (or the compiler's sysroot if not specified).],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted. We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case ${with_sysroot} in #(
+ yes)
+ if test "$GCC" = yes; then
+ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+ fi
+ ;; #(
+ /*)
+ lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+ ;; #(
+ no|'')
+ ;; #(
+ *)
+ AC_MSG_RESULT([${with_sysroot}])
+ AC_MSG_ERROR([The sysroot must be an absolute path.])
+ ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and in which our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AS_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE="32"
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE="64"
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out which ABI we are using.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ ppc64-*linux*|powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ ppc*-*linux*|powerpc*-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS="$SAVE_CFLAGS"
+ fi
+ ;;
+*-*solaris*)
+ # Find out which ABI we are using.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*)
+ case $host in
+ i?86-*-solaris*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ sparc*-*-solaris*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
+ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+ LD="${LD-ld}_sol2"
+ fi
+ ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks="$enable_libtool_lock"
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+ [lt_cv_ar_at_file=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [echo conftest.$ac_objext > conftest.lst
+ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([lt_ar_try])
+ if test "$ac_status" -eq 0; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ AC_TRY_EVAL([lt_ar_try])
+ if test "$ac_status" -ne 0; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+ ])
+ ])
+
+if test "x$lt_cv_ar_at_file" = xno; then
+ archiver_list_spec=
+else
+ archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+ [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+ [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+ [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+ [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $RM conftest*
+])
+
+if test x"[$]$2" = xyes; then
+ m4_if([$5], , :, [$5])
+else
+ m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $3"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+ m4_if([$4], , :, [$4])
+else
+ m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring="ABCD"
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ os2*)
+ # The test takes a long time on OS/2.
+ lt_cv_sys_max_cmd_len=8192
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8 ; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test $i != 17 # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+ [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisbility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}]
+_LT_EOF
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen="load_add_on"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen="LoadLibrary"
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen="dlopen"
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+ lt_cv_dlopen="dyld"
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen="shl_load"],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen="dlopen"],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test "x$lt_cv_dlopen" != xno; then
+ enable_dlopen=yes
+ else
+ enable_dlopen=no
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS="$CPPFLAGS"
+ test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS="$LDFLAGS"
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS="$LIBS"
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test "x$lt_cv_dlopen_self" = xyes; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+ [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+ [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+ [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+ [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links="nottested"
+if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test "$hard_links" = no; then
+ AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+ [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/",
+ [Define to the sub-directory in which libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+ test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+ test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$_LT_TAGVAR(hardcode_direct, $1)" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+ test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_TAGVAR(hardcode_action, $1)" = relink ||
+ test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+ [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP" ; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test "$GCC" = yes; then
+ case $host_os in
+ darwin*) lt_awk_arg="/^libraries:/,/LR/" ;;
+ *) lt_awk_arg="/^libraries:/" ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;;
+ *) lt_sed_strip_eq="s,=/,/,g" ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary.
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path/$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir"
+ else
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS=" "; FS="/|\n";} {
+ lt_foo="";
+ lt_count=0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo="/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's,/\([[A-Za-z]]:\),\1,g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[[4-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$cc_basename in
+ yes,*)
+ # gcc
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ ;;
+
+ *,cl*)
+ # Native MSVC
+ libname_spec='$name'
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+ library_names_spec='${libname}.dll.lib'
+
+ case $build_os in
+ mingw*)
+ sys_lib_search_path_spec=
+ lt_save_ifs=$IFS
+ IFS=';'
+ for lt_path in $LIB
+ do
+ IFS=$lt_save_ifs
+ # Let DOS variable expansion print the short 8.3 style file name.
+ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+ done
+ IFS=$lt_save_ifs
+ # Convert to MSYS style.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+ ;;
+ cygwin*)
+ # Convert to unix form, then to dos form, then back to unix form
+ # but this time dos style (no spaces!) so that the unix form looks
+ # like /cygdrive/c/PROGRA~1:/cygdr...
+ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ *)
+ sys_lib_search_path_spec="$LIB"
+ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # FIXME: find the short name or the path components, as spaces are
+ # common. (e.g. "Program Files" -> "PROGRA~1")
+ ;;
+ esac
+
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+ dynamic_linker='Win32 link.exe'
+ ;;
+
+ *)
+ # Assume MSVC wrapper
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ dynamic_linker='Win32 ld.exe'
+ ;;
+ esac
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[23]].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+haiku*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[[3-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+ [lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+ [lt_cv_shlibpath_overrides_runpath=yes])])
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+ ])
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[[89]] | openbsd2.[[89]].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+ [Variables whose values should be saved in libtool wrapper scripts and
+ restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+ [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+ [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+ [[List of archive names. First name is the real one, the rest are links.
+ The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+ [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+ [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+ [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+ [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+ [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+ [[As "finish_cmds", except a single script fragment to be evaled but
+ not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+ [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+ [Compile-time system search path for libraries])
+_LT_DECL([], [sys_lib_dlsearch_path_spec], [2],
+ [Run-time system search path for libraries])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program which can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD="$MAGIC_CMD"
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="m4_if([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$1; then
+ lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS="$lt_save_ifs"
+ MAGIC_CMD="$lt_save_MAGIC_CMD"
+ ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+ [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program which can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ if test "$GCC" != yes; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test "$GCC" = yes; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin.
+ if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ # Keep this pattern in sync with the one in func_win32_libid.
+ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[[3-9]]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+ case $host_os in
+ mingw* | pw32*)
+ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+ want_nocaseglob=yes
+ else
+ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+ fi
+ ;;
+ esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+ [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+ [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+ [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+ [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM="$NM"
+else
+ lt_nm_to_check="${ac_tool_prefix}nm"
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm="$ac_dir/$lt_tmp_nm"
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+ */dev/null* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+ done
+ : ${lt_cv_path_NM=no}
+fi])
+if test "$lt_cv_path_NM" != "no"; then
+ NM="$lt_cv_path_NM"
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+ case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+ AC_SUBST([DUMPBIN])
+ if test "$DUMPBIN" != ":"; then
+ NM="$DUMPBIN"
+ fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+ [lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+ cat conftest.out >&AS_MESSAGE_LOG_FD
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+ # two different shell functions defined in ltmain.sh
+ # decide which to use based on capabilities of $DLLTOOL
+ case `$DLLTOOL --help 2>&1` in
+ *--identify-strict*)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+ ;;
+ *)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+ ;;
+ esac
+ ;;
+*)
+ # fallback: assume linklib IS sharedlib
+ lt_cv_sharedlib_from_linklib_cmd="$ECHO"
+ ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+ [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+ [lt_cv_path_mainfest_tool=no
+ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+ lt_cv_path_mainfest_tool=yes
+ fi
+ rm -f conftest*])
+if test "x$lt_cv_path_mainfest_tool" != xyes; then
+ MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM="-lm")
+ ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+ case $cc_basename in
+ nvcc*)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+ esac
+
+ _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+ [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*)
+ if test "$host_cpu" = ia64; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'"
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function
+ # and D for any global variable.
+ # Also find C++ and __fastcall symbols from MSVC++,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK ['"\
+" {last_section=section; section=\$ 3};"\
+" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\
+" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\
+" s[1]~/^[@?]/{print s[1], s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx]"
+ else
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
+/* DATA imports from DLLs on WIN32 con't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT@&t@_DLSYM_CONST
+#elif defined(__osf__)
+/* This system does not cope well with relocations in const data. */
+# define LT@&t@_DLSYM_CONST
+#else
+# define LT@&t@_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+LT@&t@_DLSYM_CONST struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_globsym_save_LIBS=$LIBS
+ lt_globsym_save_CFLAGS=$CFLAGS
+ LIBS="conftstm.$ac_objext"
+ CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+ pipe_works=yes
+ fi
+ LIBS=$lt_globsym_save_LIBS
+ CFLAGS=$lt_globsym_save_CFLAGS
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test "$pipe_works" = yes; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+ nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+ [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+ [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_c_name_address],
+ [lt_cv_sys_global_symbol_to_c_name_address], [1],
+ [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+ [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([], [nm_file_list_spec], [1],
+ [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[[4-9]]*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64 which still supported -KPIC.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+ # IBM XL 8.0, 9.0 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+ if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+ fi
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ # old Intel for x86_64 which still supported -KPIC.
+ ecc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+ ;;
+ nagfor*)
+ # NAG Fortran compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+ ;;
+ *Sun\ F* | *Sun*Fortran*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ *Intel*\ [[CF]]*Compiler*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ *Portland\ Group*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ rdos*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec ;then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+ [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+ [Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+ [How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+ [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ case $host_os in
+ aix[[4-9]]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ # Also, AIX nm treats weak defined symbols like other global defined
+ # symbols, whereas GNU nm marks them as "W".
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+ ;;
+ cygwin* | mingw* | cegcc*)
+ case $cc_basename in
+ cl*)
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+ ;;
+ esac
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+], [
+ runpath_var=
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(archive_cmds, $1)=
+ _LT_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_TAGVAR(compiler_needs_object, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(hardcode_automatic, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(inherit_rpath, $1)=no
+ _LT_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_TAGVAR(module_cmds, $1)=
+ _LT_TAGVAR(module_expsym_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ` (' and `)$', so one must not match beginning or
+ # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+ # as well as any symbol that contains `d'.
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test "$with_gnu_ld" = yes; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+ *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test "$lt_use_gnu_ld_interface" = yes; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='${wl}'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[[3-9]]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ tmp_diet=no
+ if test "$host_os" = linux-dietlibc; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test "$tmp_diet" = no
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ tmp_sharedflag='--shared' ;;
+ xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then
+ runpath_var=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ # Also, AIX nm treats weak defined symbols like other global
+ # defined symbols, whereas GNU nm marks them as "W".
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ if test "$with_gnu_ld" = yes; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[[45]]*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ case $cc_basename in
+ cl*)
+ # Native MSVC
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+ else
+ sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile="$lt_outputfile.exe"
+ lt_tool_outputfile="$lt_tool_outputfile.exe"
+ ;;
+ esac~
+ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # Assume MSVC wrapper
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+
+ hpux10*)
+ if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test "$GCC" = yes && test "$with_gnu_ld" = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ m4_if($1, [], [
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ _LT_LINKER_OPTION([if $CC understands -b],
+ _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+ [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+ [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+ [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+ ;;
+ esac
+ fi
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ # This should be the same for all languages, so no per-tag cache variable.
+ AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+ [lt_cv_irix_exported_symbol],
+ [save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null"
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE(
+ [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+ [C++], [[int foo (void) { return 0; }]],
+ [Fortran 77], [[
+ subroutine foo
+ end]],
+ [Fortran], [[
+ subroutine foo
+ end]])])],
+ [lt_cv_irix_exported_symbol=yes],
+ [lt_cv_irix_exported_symbol=no])
+ LDFLAGS="$save_LDFLAGS"])
+ if test "$lt_cv_irix_exported_symbol" = yes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib'
+ fi
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ else
+ case $host_os in
+ openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+ ;;
+
+ osf3*)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+ if test "$GCC" = yes; then
+ wlarc='${wl}'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='${wl}'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'. GCC discards it without `$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test "x$host_vendor" = xsequent; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test "$GCC" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ if test x$host_vendor = xsni; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+ [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $_LT_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+ [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+ [$RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+ then
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ ])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+ [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+ [enable_shared_with_static_runtimes], [0],
+ [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+ [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+ [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+ [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+ [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+ [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+ [Commands used to build a loadable module if different from building
+ a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+ [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+ [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+ [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+ [Flag to hardcode $libdir into a binary during linking.
+ This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+ [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+ [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+ DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+ [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes
+ DIR into the resulting binary and the resulting library dependency is
+ "absolute", i.e impossible to change by setting ${shlibpath_var} if the
+ library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+ [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+ [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+ [Set to "yes" if building a shared library automatically hardcodes DIR
+ into the library and all subsequent libraries and executables linked
+ against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+ [Set to yes if linker adds runtime paths of dependent libraries
+ to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+ [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+ [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+ [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+ [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+ [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+ [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+ [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+ [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+ LT_SYS_DLOPEN_SELF
+ _LT_CMD_STRIPLIB
+
+ # Report which library types will actually be built
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC="$lt_save_CC"
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ AC_PROG_CXXCPP
+else
+ _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_CFLAGS=$CFLAGS
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ CFLAGS=$CXXFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+ else
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+ fi
+
+ if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+ LT_PATH_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='${wl}-f,'
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+ if test "$with_gnu_ld" = yes; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ # This is similar to how AIX traditionally builds its shared
+ # libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $GXX,$cc_basename in
+ ,cl* | no,cl*)
+ # Native MSVC
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=".dll"
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp;
+ else
+ $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile="$lt_outputfile.exe"
+ lt_tool_outputfile="$lt_tool_outputfile.exe"
+ ;;
+ esac~
+ func_to_tool_file "$lt_outputfile"~
+ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # g++
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ freebsd2.*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ freebsd-elf*)
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+
+ freebsd* | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ gnu*)
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ hpux9*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib'
+ fi
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+ _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+ _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+ $RANLIB $oldlib'
+ _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ *) # Version 6 and above use weak symbols
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+ ;;
+ xl* | mpixl* | bgxl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=func_echo_all
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~
+ $RM $lib.exp'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+ case $host in
+ osf3*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ fi
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+ '"$_LT_TAGVAR(old_archive_cmds, $1)"
+ _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+ '"$_LT_TAGVAR(reload_cmds, $1)"
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+ test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+ _LT_TAGVAR(GCC, $1)="$GXX"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+ case ${2} in
+ .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;;
+ *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;;
+ esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case ${prev}${p} in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" ||
+ test $p = "-R"; then
+ prev=$p
+ continue
+ fi
+
+ # Expand the sysroot to ease extracting the directories later.
+ if test -z "$prev"; then
+ case $p in
+ -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+ -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+ -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+ esac
+ fi
+ case $p in
+ =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+ esac
+ if test "$pre_test_object_deps_done" = no; then
+ case ${prev} in
+ -L | -R)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+ else
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+ _LT_TAGVAR(postdeps, $1)="${prev}${p}"
+ else
+ _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}"
+ fi
+ fi
+ prev=
+ ;;
+
+ *.lto.$objext) ;; # Ignore GCC LTO objects
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+ _LT_TAGVAR(predep_objects, $1)="$p"
+ else
+ _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+ _LT_TAGVAR(postdep_objects, $1)="$p"
+ else
+ _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_TAGVAR(predep_objects,$1)=
+ _LT_TAGVAR(postdep_objects,$1)=
+ _LT_TAGVAR(postdeps,$1)=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+ [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+ [Dependencies to place before and after the objects being linked to
+ create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+ [The library search path used internally by the compiler when linking
+ a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test "X$F77" = "Xno"; then
+ _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_F77" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC="$CC"
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${F77-"f77"}
+ CFLAGS=$FFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+ GCC=$G77
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)="$G77"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC="$lt_save_CC"
+ CFLAGS="$lt_save_CFLAGS"
+fi # test "$_lt_disable_F77" != yes
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test "X$FC" = "Xno"; then
+ _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_disable_FC" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC="$CC"
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${FC-"f95"}
+ CFLAGS=$FCFLAGS
+ compiler=$CC
+ GCC=$ac_cv_fc_compiler_gnu
+
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test "$can_build_shared" = "no" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test "$enable_shared" = yes && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+ test "$enable_shared" = yes && enable_static=no
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test "$enable_shared" = yes || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu"
+ _LT_TAGVAR(LD, $1)="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+fi # test "$_lt_disable_FC" != yes
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)="$LD"
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to `libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+ :
+ _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+ [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+ [AC_CHECK_TOOL(GCJ, gcj,)
+ test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f $lt_ac_sed && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test $lt_ac_count -gt 10 && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test $lt_ac_count -gt $lt_ac_max; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[AC_MSG_CHECKING([whether the shell understands some XSI constructs])
+# Try some XSI features
+xsi_shell=no
+( _lt_dummy="a/b/c"
+ test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \
+ = c,a/b,b/c, \
+ && eval 'test $(( 1 + 1 )) -eq 2 \
+ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \
+ && xsi_shell=yes
+AC_MSG_RESULT([$xsi_shell])
+_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell'])
+
+AC_MSG_CHECKING([whether the shell understands "+="])
+lt_shell_append=no
+( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \
+ >/dev/null 2>&1 \
+ && lt_shell_append=yes
+AC_MSG_RESULT([$lt_shell_append])
+_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append'])
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY)
+# ------------------------------------------------------
+# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and
+# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY.
+m4_defun([_LT_PROG_FUNCTION_REPLACE],
+[dnl {
+sed -e '/^$1 ()$/,/^} # $1 /c\
+$1 ()\
+{\
+m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1])
+} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+test 0 -eq $? || _lt_function_replace_fail=:
+])
+
+
+# _LT_PROG_REPLACE_SHELLFNS
+# -------------------------
+# Replace existing portable implementations of several shell functions with
+# equivalent extended shell implementations where those features are available..
+m4_defun([_LT_PROG_REPLACE_SHELLFNS],
+[if test x"$xsi_shell" = xyes; then
+ _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac])
+
+ _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl
+ func_basename_result="${1##*/}"])
+
+ _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl
+ case ${1} in
+ */*) func_dirname_result="${1%/*}${2}" ;;
+ * ) func_dirname_result="${3}" ;;
+ esac
+ func_basename_result="${1##*/}"])
+
+ _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary parameter first.
+ func_stripname_result=${3}
+ func_stripname_result=${func_stripname_result#"${1}"}
+ func_stripname_result=${func_stripname_result%"${2}"}])
+
+ _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl
+ func_split_long_opt_name=${1%%=*}
+ func_split_long_opt_arg=${1#*=}])
+
+ _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl
+ func_split_short_opt_arg=${1#??}
+ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}])
+
+ _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl
+ case ${1} in
+ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;
+ *) func_lo2o_result=${1} ;;
+ esac])
+
+ _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo])
+
+ _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))])
+
+ _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}])
+fi
+
+if test x"$lt_shell_append" = xyes; then
+ _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"])
+
+ _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl
+ func_quote_for_eval "${2}"
+dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \
+ eval "${1}+=\\\\ \\$func_quote_for_eval_result"])
+
+ # Save a `func_append' function call where possible by direct use of '+='
+ sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+ test 0 -eq $? || _lt_function_replace_fail=:
+else
+ # Save a `func_append' function call even when '+=' is not available
+ sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \
+ && mv -f "$cfgfile.tmp" "$cfgfile" \
+ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp")
+ test 0 -eq $? || _lt_function_replace_fail=:
+fi
+
+if test x"$_lt_function_replace_fail" = x":"; then
+ AC_MSG_WARN([Unable to substitute extended shell functions in $ofile])
+fi
+])
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine which file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+ ;;
+ esac
+ ;;
+ *-*-cygwin* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+ ;;
+ esac
+ ;;
+ * ) # unhandled hosts (and "normal" native builds)
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+ [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ esac
+ ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+ [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
diff --git a/contrib/libxo/m4/ltoptions.m4 b/contrib/libxo/m4/ltoptions.m4
new file mode 100644
index 0000000..5d9acd8
--- /dev/null
+++ b/contrib/libxo/m4/ltoptions.m4
@@ -0,0 +1,384 @@
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 7 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it. Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+ _LT_MANGLE_DEFUN([$1], [$2]),
+ [m4_warning([Unknown $1 option `$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+ [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME. If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+ dnl
+ dnl Simply set some default values (i.e off) if boolean options were not
+ dnl specified:
+ _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+ ])
+ _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+ ])
+ dnl
+ dnl If no reference was made to various pairs of opposing options, then
+ dnl we run the default mode handler for the pair. For example, if neither
+ dnl `shared' nor `disable-shared' was passed, we enable building of shared
+ dnl archives by default:
+ _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+ _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+ [_LT_ENABLE_FAST_INSTALL])
+ ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS], [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the `shared' and
+# `disable-shared' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+ [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+ _LT_DECL([build_libtool_libs], [enable_shared], [0],
+ [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the `static' and
+# `disable-static' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+ _LT_DECL([build_old_libs], [enable_static], [0],
+ [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the `fast-install'
+# and `disable-fast-install' LT_INIT options.
+# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+ [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+ [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the `disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the `pic-only' and `no-pic'
+# LT_INIT options.
+# MODE is either `yes' or `no'. If omitted, it defaults to `both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+ [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [lt_p=${PACKAGE-default}
+ case $withval in
+ yes|no) pic_mode=$withval ;;
+ *)
+ pic_mode=default
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for lt_pkg in $withval; do
+ IFS="$lt_save_ifs"
+ if test "X$lt_pkg" = "X$lt_p"; then
+ pic_mode=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac],
+ [pic_mode=default])
+
+test -z "$pic_mode" && pic_mode=m4_default([$1], [default])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the `pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+ [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+ [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+ [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+ [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+ [m4_define([_LTDL_TYPE], [convenience])])
diff --git a/contrib/libxo/m4/ltsugar.m4 b/contrib/libxo/m4/ltsugar.m4
new file mode 100644
index 0000000..9000a05
--- /dev/null
+++ b/contrib/libxo/m4/ltsugar.m4
@@ -0,0 +1,123 @@
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+ [$#], [2], [[$2]],
+ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59 which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+ [$#], 1, [],
+ [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+ m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+ [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+ [m4_foreach([_Lt_suffix],
+ ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+ [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+ [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+ [lt_append([$1], [$2], [$3])$4],
+ [$5])],
+ [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+ m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+ m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+ [$5],
+ [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+ [lt_join(m4_quote(m4_default([$4], [[, ]])),
+ lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+ [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
diff --git a/contrib/libxo/m4/ltversion.m4 b/contrib/libxo/m4/ltversion.m4
new file mode 100644
index 0000000..07a8602
--- /dev/null
+++ b/contrib/libxo/m4/ltversion.m4
@@ -0,0 +1,23 @@
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004 Free Software Foundation, Inc.
+# Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 3337 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.2])
+m4_define([LT_PACKAGE_REVISION], [1.3337])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.2'
+macro_revision='1.3337'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
diff --git a/contrib/libxo/m4/lt~obsolete.m4 b/contrib/libxo/m4/lt~obsolete.m4
new file mode 100644
index 0000000..c573da9
--- /dev/null
+++ b/contrib/libxo/m4/lt~obsolete.m4
@@ -0,0 +1,98 @@
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+# Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else. This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
diff --git a/contrib/libxo/packaging/libxo.pc.in b/contrib/libxo/packaging/libxo.pc.in
new file mode 100644
index 0000000..b291d07
--- /dev/null
+++ b/contrib/libxo/packaging/libxo.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+
+Name: libxo
+Version: @VERSION@
+Description: The XML Output Library
+Libs: @LIBXO_LIBDIR@ @LIBXO_LIBS@
+Cflags: @LIBXO_INCLUDEDIR@
diff --git a/contrib/libxo/packaging/libxo.spec.in b/contrib/libxo/packaging/libxo.spec.in
new file mode 100644
index 0000000..e80634c
--- /dev/null
+++ b/contrib/libxo/packaging/libxo.spec.in
@@ -0,0 +1,44 @@
+Name: @PACKAGE_NAME@
+Version: @PACKAGE_VERSION@
+Release: 1%{?dist}
+Summary: The libxo library
+
+Prefix: /usr
+
+Vendor: Juniper Networks, Inc.
+Packager: Phil Shafer <phil@juniper.net>
+License: BSD
+
+Group: Development/Libraries
+URL: https://github.com/Juniper/libxo
+Source0: https://github.com/Juniper/@PACKAGE_NAME@/releases/@PACKAGE_VERSION@/@PACKAGE_NAME@-@PACKAGE_VERSION@.tar.gz
+
+
+%description
+Welcome to libxo, a library that generates text, XML, JSON, and HTML
+from a single source code path.
+
+%prep
+%setup -q
+
+%build
+%configure
+make %{?_smp_mflags}
+
+%install
+rm -rf $RPM_BUILD_ROOT
+%make_install
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+
+%files
+%{_bindir}/*
+%{_includedir}/libxo/*
+%{_libdir}/*
+%{_datadir}/doc/libxo/*
+%docdir %{_datadir}/doc/libxo/*
+%{_mandir}/*/*
+%docdir %{_mandir}/*/*
diff --git a/contrib/libxo/tests/Makefile.am b/contrib/libxo/tests/Makefile.am
new file mode 100644
index 0000000..c69d511
--- /dev/null
+++ b/contrib/libxo/tests/Makefile.am
@@ -0,0 +1,28 @@
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+SUBDIRS=core xo
+
+test tests:
+ @(cur=`pwd` ; for dir in $(SUBDIRS) ; do \
+ cd $$dir ; \
+ $(MAKE) tests ; \
+ cd $$cur ; \
+ done)
+
+accept:
+ @(cur=`pwd` ; for dir in $(SUBDIRS) ; do \
+ cd $$dir ; \
+ $(MAKE) accept ; \
+ cd $$cur ; \
+ done)
+
+valgrind:
+ @echo '## Running the regression tests under Valgrind'
+ @echo '## Go get a cup of coffee it is gonna take a while ...'
+ ${MAKE} VALGRIND='valgrind -q' tests
diff --git a/contrib/libxo/tests/core/Makefile.am b/contrib/libxo/tests/core/Makefile.am
new file mode 100644
index 0000000..a87fcc5
--- /dev/null
+++ b/contrib/libxo/tests/core/Makefile.am
@@ -0,0 +1,107 @@
+#
+# $Id$
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+AM_CFLAGS = -I${top_srcdir} -I${top_srcdir}/libxo
+
+# Ick: maintained by hand!
+TEST_CASES = \
+test_01.c \
+test_02.c \
+test_03.c \
+test_04.c \
+test_05.c \
+test_06.c \
+test_07.c
+
+test_01_test_SOURCES = test_01.c
+test_02_test_SOURCES = test_02.c
+test_03_test_SOURCES = test_03.c
+test_04_test_SOURCES = test_04.c
+test_05_test_SOURCES = test_05.c
+test_06_test_SOURCES = test_06.c
+test_07_test_SOURCES = test_07.c
+
+# TEST_CASES := $(shell cd ${srcdir} ; echo *.c )
+
+bin_PROGRAMS = ${TEST_CASES:.c=.test}
+
+LDADD = \
+ ${top_builddir}/libxo/libxo.la
+
+EXTRA_DIST = \
+ ${TEST_CASES} \
+ ${addprefix saved/, ${TEST_CASES:.c=.T.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.T.out}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.XP.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.XP.out}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.JP.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.JP.out}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.HP.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.HP.out}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.X.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.X.out}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.J.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.J.out}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.H.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.H.out}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.HIPx.err}} \
+ ${addprefix saved/, ${TEST_CASES:.c=.HIPx.out}}
+
+S2O = | ${SED} '1,/@@/d'
+
+all:
+
+valgrind:
+ @echo '## Running the regression tests under Valgrind'
+ ${MAKE} CHECKER='valgrind -q' tests
+
+#TEST_TRACE = set -x ;
+
+TEST_ONE = \
+ LIBXO_OPTIONS=:W$$fmt \
+ ${CHECKER} $$base.test ${TEST_OPTS} \
+ > out/$$base.$$fmt.out 2> out/$$base.$$fmt.err ; \
+ ${DIFF} -Nu ${srcdir}/saved/$$base.$$fmt.out out/$$base.$$fmt.out ${S2O} ; \
+ ${DIFF} -Nu ${srcdir}/saved/$$base.$$fmt.err out/$$base.$$fmt.err ${S2O}
+
+TEST_FORMATS = T XP JP HP X J H HIPx
+
+test tests: ${bin_PROGRAMS}
+ @${MKDIR} -p out
+ -@ ${TEST_TRACE} (for test in ${TEST_CASES} ; do \
+ base=`${BASENAME} $$test .c` ; \
+ (for fmt in ${TEST_FORMATS}; do \
+ echo "... $$test ... $$fmt ..."; \
+ ${TEST_ONE}; \
+ true; \
+ done) \
+ done)
+
+one:
+ -@(test=${TEST_CASE}; data=${TEST_DATA}; ${TEST_ONE} ; true)
+
+accept:
+ -@(for test in ${TEST_CASES} ; do \
+ base=`${BASENAME} $$test .c` ; \
+ (for fmt in ${TEST_FORMATS}; do \
+ echo "... $$test ... $$fmt ..."; \
+ ${CP} out/$$base.$$fmt.out ${srcdir}/saved/$$base.$$fmt.out ; \
+ ${CP} out/$$base.$$fmt.err ${srcdir}/saved/$$base.$$fmt.err ; \
+ done) \
+ done)
+
+.c.test:
+ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -o $@ $<
+
+CLEANFILES = ${TEST_CASES:.c=.test}
+CLEANDIRS = out
+
+clean-local:
+ rm -rf ${CLEANDIRS}
diff --git a/contrib/libxo/tests/core/saved/test_01.H.err b/contrib/libxo/tests/core/saved/test_01.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.H.err
diff --git a/contrib/libxo/tests/core/saved/test_01.H.out b/contrib/libxo/tests/core/saved/test_01.H.out
new file mode 100644
index 0000000..e61eecc
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.H.out
@@ -0,0 +1 @@
+<div class="line"><div class="title">Item </div><div class="title"> Total Sold</div><div class="title"> In Stock</div><div class="title"> On Order</div><div class="title"> SKU</div></div><div class="line"><div class="data" data-tag="name" data-key="key">gum </div><div class="data" data-tag="sold"> 1412</div><div class="data" data-tag="in-stock"> 54</div><div class="data" data-tag="on-order"> 10</div><div class="data" data-tag="sku" data-key="key"> GRO-000-415</div></div><div class="line"><div class="data" data-tag="name" data-key="key">rope </div><div class="data" data-tag="sold"> 85</div><div class="data" data-tag="in-stock"> 4</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> HRD-000-212</div></div><div class="line"><div class="data" data-tag="name" data-key="key">ladder </div><div class="data" data-tag="sold"> 0</div><div class="data" data-tag="in-stock"> 2</div><div class="data" data-tag="on-order"> 1</div><div class="data" data-tag="sku" data-key="key"> HRD-000-517</div></div><div class="line"><div class="data" data-tag="name" data-key="key">bolt </div><div class="data" data-tag="sold"> 4123</div><div class="data" data-tag="in-stock"> 144</div><div class="data" data-tag="on-order"> 42</div><div class="data" data-tag="sku" data-key="key"> HRD-000-632</div></div><div class="line"><div class="data" data-tag="name" data-key="key">water </div><div class="data" data-tag="sold"> 17</div><div class="data" data-tag="in-stock"> 14</div><div class="data" data-tag="on-order"> 2</div><div class="data" data-tag="sku" data-key="key"> GRO-000-2331</div></div><div class="line"></div><div class="line"></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">gum</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1412.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">54</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">10</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-415</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">rope</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">85.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">4</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-212</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">ladder</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">2</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-517</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">bolt</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">4123.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">144</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">42</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">HRD-000-632</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">water</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">17.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">14</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">2</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-2331</div></div><div class="line"><div class="label">Item</div><div class="text"> '</div><div class="data" data-tag="name" data-key="key">fish</div><div class="text">':</div></div><div class="line"><div class="padding"> </div><div class="label">Total sold</div><div class="text">: </div><div class="data" data-tag="sold">1321.0</div></div><div class="line"><div class="padding"> </div><div class="label">In stock</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="in-stock">45</div></div><div class="line"><div class="padding"> </div><div class="label">On order</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="on-order">1</div></div><div class="line"><div class="padding"> </div><div class="label">SKU</div><div class="text">: </div><div class="data" data-tag="sku" data-key="key">GRO-000-533</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_01.HIPx.err b/contrib/libxo/tests/core/saved/test_01.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.HIPx.err
diff --git a/contrib/libxo/tests/core/saved/test_01.HIPx.out b/contrib/libxo/tests/core/saved/test_01.HIPx.out
new file mode 100644
index 0000000..c38eb04
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.HIPx.out
@@ -0,0 +1,238 @@
+<div class="line">
+ <div class="title">Item </div>
+ <div class="title"> Total Sold</div>
+ <div class="title"> In Stock</div>
+ <div class="title"> On Order</div>
+ <div class="title"> SKU</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">gum </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold"> 1412</div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock"> 54</div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order"> 10</div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-415</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">rope </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold"> 85</div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock"> 4</div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-212</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold"> 0</div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock"> 2</div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order"> 1</div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-517</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold"> 4123</div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock"> 144</div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order"> 42</div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> HRD-000-632</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">water </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold"> 17</div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock"> 14</div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order"> 2</div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key"> GRO-000-2331</div>
+</div>
+<div class="line">
+</div>
+<div class="line">
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">gum</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/sold" data-type="number" data-help="Number of items sold">1412.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/in-stock" data-type="number" data-help="Number of items in stock">54</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-415'][name = 'gum']/on-order" data-type="number" data-help="Number of items on order">10</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-415</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">rope</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/sold" data-type="number" data-help="Number of items sold">85.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/in-stock" data-type="number" data-help="Number of items in stock">4</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-212'][name = 'rope']/on-order" data-type="number" data-help="Number of items on order">2</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-212</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">ladder</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/sold" data-type="number" data-help="Number of items sold">0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/in-stock" data-type="number" data-help="Number of items in stock">2</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-517'][name = 'ladder']/on-order" data-type="number" data-help="Number of items on order">1</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-517</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">bolt</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/sold" data-type="number" data-help="Number of items sold">4123.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/in-stock" data-type="number" data-help="Number of items in stock">144</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'HRD-000-632'][name = 'bolt']/on-order" data-type="number" data-help="Number of items on order">42</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">HRD-000-632</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">water</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/sold" data-type="number" data-help="Number of items sold">17.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/in-stock" data-type="number" data-help="Number of items in stock">14</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-2331'][name = 'water']/on-order" data-type="number" data-help="Number of items on order">2</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-2331</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-xpath="/top/data/item/name" data-type="string" data-help="Name of the item" data-key="key">fish</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold" data-xpath="/top/data/item[sku = 'GRO-000-533'][name = 'fish']/sold" data-type="number" data-help="Number of items sold">1321.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock" data-xpath="/top/data/item[sku = 'GRO-000-533'][name = 'fish']/in-stock" data-type="number" data-help="Number of items in stock">45</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order" data-xpath="/top/data/item[sku = 'GRO-000-533'][name = 'fish']/on-order" data-type="number" data-help="Number of items on order">1</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-xpath="/top/data/item/sku" data-type="string" data-help="Stock Keeping Unit" data-key="key">GRO-000-533</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_01.HP.err b/contrib/libxo/tests/core/saved/test_01.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.HP.err
diff --git a/contrib/libxo/tests/core/saved/test_01.HP.out b/contrib/libxo/tests/core/saved/test_01.HP.out
new file mode 100644
index 0000000..a887476
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.HP.out
@@ -0,0 +1,238 @@
+<div class="line">
+ <div class="title">Item </div>
+ <div class="title"> Total Sold</div>
+ <div class="title"> In Stock</div>
+ <div class="title"> On Order</div>
+ <div class="title"> SKU</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-key="key">gum </div>
+ <div class="data" data-tag="sold"> 1412</div>
+ <div class="data" data-tag="in-stock"> 54</div>
+ <div class="data" data-tag="on-order"> 10</div>
+ <div class="data" data-tag="sku" data-key="key"> GRO-000-415</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-key="key">rope </div>
+ <div class="data" data-tag="sold"> 85</div>
+ <div class="data" data-tag="in-stock"> 4</div>
+ <div class="data" data-tag="on-order"> 2</div>
+ <div class="data" data-tag="sku" data-key="key"> HRD-000-212</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-key="key">ladder </div>
+ <div class="data" data-tag="sold"> 0</div>
+ <div class="data" data-tag="in-stock"> 2</div>
+ <div class="data" data-tag="on-order"> 1</div>
+ <div class="data" data-tag="sku" data-key="key"> HRD-000-517</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-key="key">bolt </div>
+ <div class="data" data-tag="sold"> 4123</div>
+ <div class="data" data-tag="in-stock"> 144</div>
+ <div class="data" data-tag="on-order"> 42</div>
+ <div class="data" data-tag="sku" data-key="key"> HRD-000-632</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="name" data-key="key">water </div>
+ <div class="data" data-tag="sold"> 17</div>
+ <div class="data" data-tag="in-stock"> 14</div>
+ <div class="data" data-tag="on-order"> 2</div>
+ <div class="data" data-tag="sku" data-key="key"> GRO-000-2331</div>
+</div>
+<div class="line">
+</div>
+<div class="line">
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-key="key">gum</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">1412.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">54</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">10</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-key="key">GRO-000-415</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-key="key">rope</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">85.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">4</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">2</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-key="key">HRD-000-212</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-key="key">ladder</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">2</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">1</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-key="key">HRD-000-517</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-key="key">bolt</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">4123.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">144</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">42</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-key="key">HRD-000-632</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-key="key">water</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">17.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">14</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">2</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-key="key">GRO-000-2331</div>
+</div>
+<div class="line">
+ <div class="label">Item</div>
+ <div class="text"> '</div>
+ <div class="data" data-tag="name" data-key="key">fish</div>
+ <div class="text">':</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">Total sold</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sold">1321.0</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">In stock</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="in-stock">45</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">On order</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="on-order">1</div>
+</div>
+<div class="line">
+ <div class="padding"> </div>
+ <div class="label">SKU</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="sku" data-key="key">GRO-000-533</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_01.J.err b/contrib/libxo/tests/core/saved/test_01.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.J.err
diff --git a/contrib/libxo/tests/core/saved/test_01.J.out b/contrib/libxo/tests/core/saved/test_01.J.out
new file mode 100644
index 0000000..289a952
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.J.out
@@ -0,0 +1,2 @@
+{"top": {"data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}}
+}
diff --git a/contrib/libxo/tests/core/saved/test_01.JP.err b/contrib/libxo/tests/core/saved/test_01.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.JP.err
diff --git a/contrib/libxo/tests/core/saved/test_01.JP.out b/contrib/libxo/tests/core/saved/test_01.JP.out
new file mode 100644
index 0000000..5675845
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.JP.out
@@ -0,0 +1,93 @@
+{
+ "top": {
+ "data": {
+ "item": [
+ {
+ "sku": "GRO-000-415",
+ "name": "gum",
+ "sold": 1412,
+ "in-stock": 54,
+ "on-order": 10
+ },
+ {
+ "sku": "HRD-000-212",
+ "name": "rope",
+ "sold": 85,
+ "in-stock": 4,
+ "on-order": 2
+ },
+ {
+ "sku": "HRD-000-517",
+ "name": "ladder",
+ "sold": 0,
+ "in-stock": 2,
+ "on-order": 1
+ },
+ {
+ "sku": "HRD-000-632",
+ "name": "bolt",
+ "sold": 4123,
+ "in-stock": 144,
+ "on-order": 42
+ },
+ {
+ "sku": "GRO-000-2331",
+ "name": "water",
+ "sold": 17,
+ "in-stock": 14,
+ "on-order": 2
+ }
+ ]
+ },
+ "data": {
+ "item": [
+ {
+ "sku": "GRO-000-415",
+ "name": "gum",
+ "sold": 1412.0,
+ "in-stock": 54,
+ "on-order": 10
+ },
+ {
+ "sku": "HRD-000-212",
+ "name": "rope",
+ "sold": 85.0,
+ "in-stock": 4,
+ "on-order": 2
+ },
+ {
+ "sku": "HRD-000-517",
+ "name": "ladder",
+ "sold": 0,
+ "in-stock": 2,
+ "on-order": 1
+ },
+ {
+ "sku": "HRD-000-632",
+ "name": "bolt",
+ "sold": 4123.0,
+ "in-stock": 144,
+ "on-order": 42
+ },
+ {
+ "sku": "GRO-000-2331",
+ "name": "water",
+ "sold": 17.0,
+ "in-stock": 14,
+ "on-order": 2
+ }
+ ]
+ },
+ "data": {
+ "item": [
+ {
+ "sku": "GRO-000-533",
+ "name": "fish",
+ "sold": 1321.0,
+ "in-stock": 45,
+ "on-order": 1
+ }
+ ]
+ }
+ }
+}
diff --git a/contrib/libxo/tests/core/saved/test_01.T.err b/contrib/libxo/tests/core/saved/test_01.T.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.T.err
diff --git a/contrib/libxo/tests/core/saved/test_01.T.out b/contrib/libxo/tests/core/saved/test_01.T.out
new file mode 100644
index 0000000..c2ad7a0
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.T.out
@@ -0,0 +1,38 @@
+Item Total Sold In Stock On Order SKU
+gum 1412 54 10 GRO-000-415
+rope 85 4 2 HRD-000-212
+ladder 0 2 1 HRD-000-517
+bolt 4123 144 42 HRD-000-632
+water 17 14 2 GRO-000-2331
+
+
+Item 'gum':
+ Total sold: 1412.0
+ In stock: 54
+ On order: 10
+ SKU: GRO-000-415
+Item 'rope':
+ Total sold: 85.0
+ In stock: 4
+ On order: 2
+ SKU: HRD-000-212
+Item 'ladder':
+ Total sold: 0
+ In stock: 2
+ On order: 1
+ SKU: HRD-000-517
+Item 'bolt':
+ Total sold: 4123.0
+ In stock: 144
+ On order: 42
+ SKU: HRD-000-632
+Item 'water':
+ Total sold: 17.0
+ In stock: 14
+ On order: 2
+ SKU: GRO-000-2331
+Item 'fish':
+ Total sold: 1321.0
+ In stock: 45
+ On order: 1
+ SKU: GRO-000-533
diff --git a/contrib/libxo/tests/core/saved/test_01.X.err b/contrib/libxo/tests/core/saved/test_01.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.X.err
diff --git a/contrib/libxo/tests/core/saved/test_01.X.out b/contrib/libxo/tests/core/saved/test_01.X.out
new file mode 100644
index 0000000..c3e07c8
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.X.out
@@ -0,0 +1 @@
+<top><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-415</sku><name key="key">gum</name><sold>1412.0</sold><in-stock>54</in-stock><on-order>10</on-order></item><item><sku key="key">HRD-000-212</sku><name key="key">rope</name><sold>85.0</sold><in-stock>4</in-stock><on-order>2</on-order></item><item><sku key="key">HRD-000-517</sku><name key="key">ladder</name><sold>0</sold><in-stock>2</in-stock><on-order>1</on-order></item><item><sku key="key">HRD-000-632</sku><name key="key">bolt</name><sold>4123.0</sold><in-stock>144</in-stock><on-order>42</on-order></item><item><sku key="key">GRO-000-2331</sku><name key="key">water</name><sold>17.0</sold><in-stock>14</in-stock><on-order>2</on-order></item></data><data><item><sku key="key">GRO-000-533</sku><name key="key">fish</name><sold>1321.0</sold><in-stock>45</in-stock><on-order>1</on-order></item></data></top> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_01.XP.err b/contrib/libxo/tests/core/saved/test_01.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.XP.err
diff --git a/contrib/libxo/tests/core/saved/test_01.XP.out b/contrib/libxo/tests/core/saved/test_01.XP.out
new file mode 100644
index 0000000..49fc6da
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.XP.out
@@ -0,0 +1,85 @@
+<top>
+ <data>
+ <item>
+ <sku key="key">GRO-000-415</sku>
+ <name key="key">gum</name>
+ <sold>1412</sold>
+ <in-stock>54</in-stock>
+ <on-order>10</on-order>
+ </item>
+ <item>
+ <sku key="key">HRD-000-212</sku>
+ <name key="key">rope</name>
+ <sold>85</sold>
+ <in-stock>4</in-stock>
+ <on-order>2</on-order>
+ </item>
+ <item>
+ <sku key="key">HRD-000-517</sku>
+ <name key="key">ladder</name>
+ <sold>0</sold>
+ <in-stock>2</in-stock>
+ <on-order>1</on-order>
+ </item>
+ <item>
+ <sku key="key">HRD-000-632</sku>
+ <name key="key">bolt</name>
+ <sold>4123</sold>
+ <in-stock>144</in-stock>
+ <on-order>42</on-order>
+ </item>
+ <item>
+ <sku key="key">GRO-000-2331</sku>
+ <name key="key">water</name>
+ <sold>17</sold>
+ <in-stock>14</in-stock>
+ <on-order>2</on-order>
+ </item>
+ </data>
+ <data>
+ <item>
+ <sku key="key">GRO-000-415</sku>
+ <name key="key">gum</name>
+ <sold>1412.0</sold>
+ <in-stock>54</in-stock>
+ <on-order>10</on-order>
+ </item>
+ <item>
+ <sku key="key">HRD-000-212</sku>
+ <name key="key">rope</name>
+ <sold>85.0</sold>
+ <in-stock>4</in-stock>
+ <on-order>2</on-order>
+ </item>
+ <item>
+ <sku key="key">HRD-000-517</sku>
+ <name key="key">ladder</name>
+ <sold>0</sold>
+ <in-stock>2</in-stock>
+ <on-order>1</on-order>
+ </item>
+ <item>
+ <sku key="key">HRD-000-632</sku>
+ <name key="key">bolt</name>
+ <sold>4123.0</sold>
+ <in-stock>144</in-stock>
+ <on-order>42</on-order>
+ </item>
+ <item>
+ <sku key="key">GRO-000-2331</sku>
+ <name key="key">water</name>
+ <sold>17.0</sold>
+ <in-stock>14</in-stock>
+ <on-order>2</on-order>
+ </item>
+ </data>
+ <data>
+ <item>
+ <sku key="key">GRO-000-533</sku>
+ <name key="key">fish</name>
+ <sold>1321.0</sold>
+ <in-stock>45</in-stock>
+ <on-order>1</on-order>
+ </item>
+ </data>
+</top>
diff --git a/contrib/libxo/tests/core/saved/test_01.err b/contrib/libxo/tests/core/saved/test_01.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.err
diff --git a/contrib/libxo/tests/core/saved/test_01.out b/contrib/libxo/tests/core/saved/test_01.out
new file mode 100644
index 0000000..c2ad7a0
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_01.out
@@ -0,0 +1,38 @@
+Item Total Sold In Stock On Order SKU
+gum 1412 54 10 GRO-000-415
+rope 85 4 2 HRD-000-212
+ladder 0 2 1 HRD-000-517
+bolt 4123 144 42 HRD-000-632
+water 17 14 2 GRO-000-2331
+
+
+Item 'gum':
+ Total sold: 1412.0
+ In stock: 54
+ On order: 10
+ SKU: GRO-000-415
+Item 'rope':
+ Total sold: 85.0
+ In stock: 4
+ On order: 2
+ SKU: HRD-000-212
+Item 'ladder':
+ Total sold: 0
+ In stock: 2
+ On order: 1
+ SKU: HRD-000-517
+Item 'bolt':
+ Total sold: 4123.0
+ In stock: 144
+ On order: 42
+ SKU: HRD-000-632
+Item 'water':
+ Total sold: 17.0
+ In stock: 14
+ On order: 2
+ SKU: GRO-000-2331
+Item 'fish':
+ Total sold: 1321.0
+ In stock: 45
+ On order: 1
+ SKU: GRO-000-533
diff --git a/contrib/libxo/tests/core/saved/test_02.H.err b/contrib/libxo/tests/core/saved/test_02.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.H.err
diff --git a/contrib/libxo/tests/core/saved/test_02.H.out b/contrib/libxo/tests/core/saved/test_02.H.out
new file mode 100644
index 0000000..60350b5
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.H.out
@@ -0,0 +1,3 @@
+<div class="line"><div class="data" data-tag="mbuf-current">10</div><div class="text">/</div><div class="data" data-tag="mbuf-cache">20</div><div class="text">/</div><div class="data" data-tag="mbuf-total">30</div><div class="text"> </div><div class="note">mbufs &lt;&amp;&gt; in use (current/cache/total)</div></div><div class="line"><div class="data" data-tag="distance" data-units="miles">50</div><div class="padding"> </div><div class="text"> from </div><div class="data" data-tag="location">Boston</div></div><div class="line"><div class="data" data-tag="memory" data-units="k">64</div><div class="text"> left out of </div><div class="data" data-tag="total" data-units="kb">640</div></div><div class="line"><div class="data" data-tag="memory" data-units="k">64</div><div class="text"> left out of </div><div class="data" data-tag="total" data-units="kilobytes">640</div></div><div class="line"><div class="title">beforeworkingafter:</div></div><div class="line"><div class="data" data-tag="some">string</div><div class="data" data-tag="ten">10</div><div class="data" data-tag="eleven">11</div></div><div class="line"><div class="data" data-tag="unknown">1010</div><div class="text"> </div><div class="note">packets here/there/everywhere</div></div><div class="line"><div class="text">(</div><div class="padding"> </div><div class="data" data-tag="min">15</div><div class="text">/</div><div class="data" data-tag="cur">20</div><div class="text">/</div><div class="data" data-tag="max">125</div><div class="text">)</div></div><div class="line"><div class="text">(</div><div class="padding"> </div><div class="data" data-tag="min">15</div><div class="text">/</div><div class="data" data-tag="cur">20</div><div class="text">/</div><div class="data" data-tag="max">125</div><div class="text">)</div></div><div class="line"><div class="text">(</div><div class="data" data-tag="min">15</div><div class="text">/</div><div class="data" data-tag="cur">20</div><div class="text">/</div><div class="data" data-tag="max">125</div><div class="padding"> </div><div class="text">)</div></div><div class="line"><div class="text">(</div><div class="data" data-tag="min">15</div><div class="text">/</div><div class="data" data-tag="cur">20</div><div class="text">/</div><div class="data" data-tag="max">125</div><div class="padding"> </div><div class="text">)</div></div><div class="line"><div class="data" data-tag="flag">one</div><div class="text"> </div><div class="data" data-tag="flag">two</div><div class="text"> </div><div class="data" data-tag="flag">three</div></div><div class="line"><div class="text">1:</div><div class="data" data-tag="t1"> 1000</div><div class="text"> 2:</div><div class="data" data-tag="t2">test5000 </div><div class="text"> 3:</div><div class="data" data-tag="t3"> ten-longx</div><div class="text"> 4:</div><div class="data" data-tag="t4">xtest </div></div><div class="line"><div class="error">this is an error</div></div><div class="line"><div class="error">two more errors</div></div><div class="line"><div class="warning">this is an warning</div></div><div class="line"><div class="warning">two more warnings</div></div><div class="line"><div class="label">V1/V2 packets</div><div class="text">: </div><div class="data" data-tag="count">10</div></div><div class="line"><div class="data" data-tag="test">0004</div><div class="text"> </div><div class="label">tries</div></div><div class="line"><div class="message">improper use of profanity; ten yard penalty; first down
+</div></div><div class="line"><div class="error">Shut 'er down, Clancey! She's a-pumpin' mud! &lt;&gt;!,"!&lt;&gt;
+</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_02.HIPx.err b/contrib/libxo/tests/core/saved/test_02.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.HIPx.err
diff --git a/contrib/libxo/tests/core/saved/test_02.HIPx.out b/contrib/libxo/tests/core/saved/test_02.HIPx.out
new file mode 100644
index 0000000..f4264f7
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.HIPx.out
@@ -0,0 +1,125 @@
+<div class="line">
+ <div class="data" data-tag="mbuf-current" data-xpath="/top/data/mbuf-current">10</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="mbuf-cache" data-xpath="/top/data/mbuf-cache">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="mbuf-total" data-xpath="/top/data/mbuf-total">30</div>
+ <div class="text"> </div>
+ <div class="note">mbufs &lt;&amp;&gt; in use (current/cache/total)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="distance" data-units="miles" data-xpath="/top/data/distance">50</div>
+ <div class="padding"> </div>
+ <div class="text"> from </div>
+ <div class="data" data-tag="location" data-xpath="/top/data/location">Boston</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="memory" data-units="k" data-xpath="/top/data/memory">64</div>
+ <div class="text"> left out of </div>
+ <div class="data" data-tag="total" data-units="kb" data-xpath="/top/data/total">640</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="memory" data-units="k" data-xpath="/top/data/memory">64</div>
+ <div class="text"> left out of </div>
+ <div class="data" data-tag="total" data-units="kilobytes" data-xpath="/top/data/total">640</div>
+</div>
+<div class="line">
+ <div class="title">beforeworkingafter:</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="some" data-xpath="/top/data/some">string</div>
+ <div class="data" data-tag="ten" data-xpath="/top/data/ten">10</div>
+ <div class="data" data-tag="eleven" data-xpath="/top/data/eleven">11</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="unknown" data-xpath="/top/data/unknown">1010</div>
+ <div class="text"> </div>
+ <div class="note">packets here/there/everywhere</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="min" data-xpath="/top/data/min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur" data-xpath="/top/data/cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max" data-xpath="/top/data/max">125</div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="min" data-xpath="/top/data/min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur" data-xpath="/top/data/cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max" data-xpath="/top/data/max">125</div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="data" data-tag="min" data-xpath="/top/data/min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur" data-xpath="/top/data/cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max" data-xpath="/top/data/max">125</div>
+ <div class="padding"> </div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="data" data-tag="min" data-xpath="/top/data/min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur" data-xpath="/top/data/cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max" data-xpath="/top/data/max">125</div>
+ <div class="padding"> </div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="flag" data-xpath="/top/data/flag">one</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="flag" data-xpath="/top/data/flag">two</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="flag" data-xpath="/top/data/flag">three</div>
+</div>
+<div class="line">
+ <div class="text">1:</div>
+ <div class="data" data-tag="t1" data-xpath="/top/data/t1"> 1000</div>
+ <div class="text"> 2:</div>
+ <div class="data" data-tag="t2" data-xpath="/top/data/t2">test5000 </div>
+ <div class="text"> 3:</div>
+ <div class="data" data-tag="t3" data-xpath="/top/data/t3"> ten-longx</div>
+ <div class="text"> 4:</div>
+ <div class="data" data-tag="t4" data-xpath="/top/data/t4">xtest </div>
+</div>
+<div class="line">
+ <div class="error">this is an error</div>
+</div>
+<div class="line">
+ <div class="error">two more errors</div>
+</div>
+<div class="line">
+ <div class="warning">this is an warning</div>
+</div>
+<div class="line">
+ <div class="warning">two more warnings</div>
+</div>
+<div class="line">
+ <div class="label">V1/V2 packets</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="count" data-xpath="/top/data/count">10</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="test" data-xpath="/top/data/test">0004</div>
+ <div class="text"> </div>
+ <div class="label">tries</div>
+</div>
+<div class="line">
+ <div class="message">improper use of profanity; ten yard penalty; first down
+</div>
+</div>
+<div class="line">
+ <div class="error">Shut 'er down, Clancey! She's a-pumpin' mud! &lt;&gt;!,"!&lt;&gt;
+</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_02.HP.err b/contrib/libxo/tests/core/saved/test_02.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.HP.err
diff --git a/contrib/libxo/tests/core/saved/test_02.HP.out b/contrib/libxo/tests/core/saved/test_02.HP.out
new file mode 100644
index 0000000..1ccf369
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.HP.out
@@ -0,0 +1,125 @@
+<div class="line">
+ <div class="data" data-tag="mbuf-current">10</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="mbuf-cache">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="mbuf-total">30</div>
+ <div class="text"> </div>
+ <div class="note">mbufs &lt;&amp;&gt; in use (current/cache/total)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="distance" data-units="miles">50</div>
+ <div class="padding"> </div>
+ <div class="text"> from </div>
+ <div class="data" data-tag="location">Boston</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="memory" data-units="k">64</div>
+ <div class="text"> left out of </div>
+ <div class="data" data-tag="total" data-units="kb">640</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="memory" data-units="k">64</div>
+ <div class="text"> left out of </div>
+ <div class="data" data-tag="total" data-units="kilobytes">640</div>
+</div>
+<div class="line">
+ <div class="title">beforeworkingafter:</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="some">string</div>
+ <div class="data" data-tag="ten">10</div>
+ <div class="data" data-tag="eleven">11</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="unknown">1010</div>
+ <div class="text"> </div>
+ <div class="note">packets here/there/everywhere</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max">125</div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max">125</div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="data" data-tag="min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max">125</div>
+ <div class="padding"> </div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="text">(</div>
+ <div class="data" data-tag="min">15</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="cur">20</div>
+ <div class="text">/</div>
+ <div class="data" data-tag="max">125</div>
+ <div class="padding"> </div>
+ <div class="text">)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="flag">one</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="flag">two</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="flag">three</div>
+</div>
+<div class="line">
+ <div class="text">1:</div>
+ <div class="data" data-tag="t1"> 1000</div>
+ <div class="text"> 2:</div>
+ <div class="data" data-tag="t2">test5000 </div>
+ <div class="text"> 3:</div>
+ <div class="data" data-tag="t3"> ten-longx</div>
+ <div class="text"> 4:</div>
+ <div class="data" data-tag="t4">xtest </div>
+</div>
+<div class="line">
+ <div class="error">this is an error</div>
+</div>
+<div class="line">
+ <div class="error">two more errors</div>
+</div>
+<div class="line">
+ <div class="warning">this is an warning</div>
+</div>
+<div class="line">
+ <div class="warning">two more warnings</div>
+</div>
+<div class="line">
+ <div class="label">V1/V2 packets</div>
+ <div class="text">: </div>
+ <div class="data" data-tag="count">10</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="test">0004</div>
+ <div class="text"> </div>
+ <div class="label">tries</div>
+</div>
+<div class="line">
+ <div class="message">improper use of profanity; ten yard penalty; first down
+</div>
+</div>
+<div class="line">
+ <div class="error">Shut 'er down, Clancey! She's a-pumpin' mud! &lt;&gt;!,"!&lt;&gt;
+</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_02.J.err b/contrib/libxo/tests/core/saved/test_02.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.J.err
diff --git a/contrib/libxo/tests/core/saved/test_02.J.out b/contrib/libxo/tests/core/saved/test_02.J.out
new file mode 100644
index 0000000..621e061
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.J.out
@@ -0,0 +1,2 @@
+{"top": {"data": {"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125, "flag": ["one","two","three"],"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest","count":10,"test":4}}
+}
diff --git a/contrib/libxo/tests/core/saved/test_02.JP.err b/contrib/libxo/tests/core/saved/test_02.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.JP.err
diff --git a/contrib/libxo/tests/core/saved/test_02.JP.out b/contrib/libxo/tests/core/saved/test_02.JP.out
new file mode 100644
index 0000000..9479817
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.JP.out
@@ -0,0 +1,40 @@
+{
+ "top": {
+ "data": {
+ "mbuf-current": 10,
+ "mbuf-cache": 20,
+ "mbuf-total": 30,
+ "distance": 50,
+ "location": "Boston",
+ "memory": 64,
+ "total": 640,
+ "memory": 64,
+ "total": 640,
+ "ten": 10,
+ "eleven": 11,
+ "unknown": 1010,
+ "min": 15,
+ "cur": 20,
+ "max": 30,
+ "min": 15,
+ "cur": 20,
+ "max": 125,
+ "min": 15,
+ "cur": 20,
+ "max": 125,
+ "min": 15,
+ "cur": 20,
+ "max": 125,
+ "flag": [
+ "one", "two", "three"
+ ],
+ "empty-tag": true,
+ "t1": "1000",
+ "t2": "test5000",
+ "t3": "ten-longx",
+ "t4": "xtest",
+ "count": 10,
+ "test": 4
+ }
+ }
+}
diff --git a/contrib/libxo/tests/core/saved/test_02.T.err b/contrib/libxo/tests/core/saved/test_02.T.err
new file mode 100644
index 0000000..80fabe3
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.T.err
@@ -0,0 +1 @@
+Shut 'er down, Clancey! She's a-pumpin' mud! <>!,"!<>
diff --git a/contrib/libxo/tests/core/saved/test_02.T.out b/contrib/libxo/tests/core/saved/test_02.T.out
new file mode 100644
index 0000000..b37ba00
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.T.out
@@ -0,0 +1,20 @@
+10/20/30 mbufs <&> in use (current/cache/total)
+50 miles from Boston
+64k left out of 640kb
+64k left out of 640kilobytes
+beforeworkingafter:
+string1011
+1010 packets here/there/everywhere
+( 15/20/125)
+( 15/20/125)
+(15/20/125 )
+(15/20/125 )
+one two three
+1: 1000 2:test5000 3: ten-longx 4:xtest
+this is an error
+two more errors
+this is an warning
+two more warnings
+V1/V2 packets: 10
+0004 tries
+improper use of profanity; ten yard penalty; first down
diff --git a/contrib/libxo/tests/core/saved/test_02.X.err b/contrib/libxo/tests/core/saved/test_02.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.X.err
diff --git a/contrib/libxo/tests/core/saved/test_02.X.out b/contrib/libxo/tests/core/saved/test_02.X.out
new file mode 100644
index 0000000..ff6d40c
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.X.out
@@ -0,0 +1,3 @@
+<top><data><mbuf-current>10</mbuf-current><mbuf-cache>20</mbuf-cache><mbuf-total>30</mbuf-total><distance units="miles">50</distance><location>Boston</location><memory units="k">64</memory><total units="kb">640</total><memory units="k">64</memory><total units="kilobytes">640</total><ten>10</ten><eleven>11</eleven><unknown>1010</unknown><min>15</min><cur>20</cur><max>30</max><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><min>15</min><cur>20</cur><max>125</max><flag>one</flag><flag>two</flag><flag>three</flag><empty-tag></empty-tag><t1>1000</t1><t2>test5000</t2><t3>ten-longx</t3><t4>xtest</t4><error><message>this is an error</message></error><error><message>two more errors</message></error><warning><message>this is an warning</message></warning><warning><message>two more warnings</message></warning><count>10</count><test>4</test><message>improper use of profanity; ten yard penalty; first down</message>
+<error><message>Shut 'er down, Clancey! She's a-pumpin' mud! &lt;&gt;!,"!&lt;&gt;
+</message></error></data></top> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_02.XP.err b/contrib/libxo/tests/core/saved/test_02.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.XP.err
diff --git a/contrib/libxo/tests/core/saved/test_02.XP.out b/contrib/libxo/tests/core/saved/test_02.XP.out
new file mode 100644
index 0000000..d32c730
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.XP.out
@@ -0,0 +1,55 @@
+<top>
+ <data>
+ <mbuf-current>10</mbuf-current>
+ <mbuf-cache>20</mbuf-cache>
+ <mbuf-total>30</mbuf-total>
+ <distance units="miles">50</distance>
+ <location>Boston</location>
+ <memory units="k">64</memory>
+ <total units="kb">640</total>
+ <memory units="k">64</memory>
+ <total units="kilobytes">640</total>
+ <ten>10</ten>
+ <eleven>11</eleven>
+ <unknown>1010</unknown>
+ <min>15</min>
+ <cur>20</cur>
+ <max>30</max>
+ <min>15</min>
+ <cur>20</cur>
+ <max>125</max>
+ <min>15</min>
+ <cur>20</cur>
+ <max>125</max>
+ <min>15</min>
+ <cur>20</cur>
+ <max>125</max>
+ <flag>one</flag>
+ <flag>two</flag>
+ <flag>three</flag>
+ <empty-tag></empty-tag>
+ <t1>1000</t1>
+ <t2>test5000</t2>
+ <t3>ten-longx</t3>
+ <t4>xtest</t4>
+ <error>
+ <message>this is an error</message>
+ </error>
+ <error>
+ <message>two more errors</message>
+ </error>
+ <warning>
+ <message>this is an warning</message>
+ </warning>
+ <warning>
+ <message>two more warnings</message>
+ </warning>
+ <count>10</count>
+ <test>4</test>
+ <message>improper use of profanity; ten yard penalty; first down</message>
+ <error>
+ <message>Shut 'er down, Clancey! She's a-pumpin' mud! &lt;&gt;!,"!&lt;&gt;
+</message>
+ </error>
+ </data>
+</top>
diff --git a/contrib/libxo/tests/core/saved/test_02.err b/contrib/libxo/tests/core/saved/test_02.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.err
diff --git a/contrib/libxo/tests/core/saved/test_02.out b/contrib/libxo/tests/core/saved/test_02.out
new file mode 100644
index 0000000..c2ad7a0
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_02.out
@@ -0,0 +1,38 @@
+Item Total Sold In Stock On Order SKU
+gum 1412 54 10 GRO-000-415
+rope 85 4 2 HRD-000-212
+ladder 0 2 1 HRD-000-517
+bolt 4123 144 42 HRD-000-632
+water 17 14 2 GRO-000-2331
+
+
+Item 'gum':
+ Total sold: 1412.0
+ In stock: 54
+ On order: 10
+ SKU: GRO-000-415
+Item 'rope':
+ Total sold: 85.0
+ In stock: 4
+ On order: 2
+ SKU: HRD-000-212
+Item 'ladder':
+ Total sold: 0
+ In stock: 2
+ On order: 1
+ SKU: HRD-000-517
+Item 'bolt':
+ Total sold: 4123.0
+ In stock: 144
+ On order: 42
+ SKU: HRD-000-632
+Item 'water':
+ Total sold: 17.0
+ In stock: 14
+ On order: 2
+ SKU: GRO-000-2331
+Item 'fish':
+ Total sold: 1321.0
+ In stock: 45
+ On order: 1
+ SKU: GRO-000-533
diff --git a/contrib/libxo/tests/core/saved/test_03.H.err b/contrib/libxo/tests/core/saved/test_03.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.H.err
diff --git a/contrib/libxo/tests/core/saved/test_03.H.out b/contrib/libxo/tests/core/saved/test_03.H.out
new file mode 100644
index 0000000..6b9ccc4
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.H.out
@@ -0,0 +1 @@
+<div class="line"><div class="data" data-tag="first-name">Terry</div><div class="text"> </div><div class="data" data-tag="last-name">Jones</div><div class="text"> works in dept #</div><div class="data" data-tag="department">660</div></div><div class="line"><div class="data" data-tag="first-name">Leslie</div><div class="text"> </div><div class="data" data-tag="last-name">Patterson</div><div class="text"> works in dept #</div><div class="data" data-tag="department">341</div></div><div class="line"><div class="data" data-tag="first-name">Ashley</div><div class="text"> </div><div class="data" data-tag="last-name">Smith</div><div class="text"> works in dept #</div><div class="data" data-tag="department">1440</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_03.HIPx.err b/contrib/libxo/tests/core/saved/test_03.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.HIPx.err
diff --git a/contrib/libxo/tests/core/saved/test_03.HIPx.out b/contrib/libxo/tests/core/saved/test_03.HIPx.out
new file mode 100644
index 0000000..bfae221
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.HIPx.out
@@ -0,0 +1,21 @@
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Terry</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Jones</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department">660</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Leslie</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Patterson</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department">341</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Ashley</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Smith</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department">1440</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_03.HP.err b/contrib/libxo/tests/core/saved/test_03.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.HP.err
diff --git a/contrib/libxo/tests/core/saved/test_03.HP.out b/contrib/libxo/tests/core/saved/test_03.HP.out
new file mode 100644
index 0000000..f8b072a
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.HP.out
@@ -0,0 +1,21 @@
+<div class="line">
+ <div class="data" data-tag="first-name">Terry</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name">Jones</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department">660</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Leslie</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name">Patterson</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department">341</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Ashley</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name">Smith</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department">1440</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_03.J.err b/contrib/libxo/tests/core/saved/test_03.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.J.err
diff --git a/contrib/libxo/tests/core/saved/test_03.J.out b/contrib/libxo/tests/core/saved/test_03.J.out
new file mode 100644
index 0000000..4ba1fb1
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.J.out
@@ -0,0 +1,2 @@
+{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
+}
diff --git a/contrib/libxo/tests/core/saved/test_03.JP.err b/contrib/libxo/tests/core/saved/test_03.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.JP.err
diff --git a/contrib/libxo/tests/core/saved/test_03.JP.out b/contrib/libxo/tests/core/saved/test_03.JP.out
new file mode 100644
index 0000000..ff2d5b0
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.JP.out
@@ -0,0 +1,21 @@
+{
+ "employees": {
+ "employee": [
+ {
+ "first-name": "Terry",
+ "last-name": "Jones",
+ "department": 660
+ },
+ {
+ "first-name": "Leslie",
+ "last-name": "Patterson",
+ "department": 341
+ },
+ {
+ "first-name": "Ashley",
+ "last-name": "Smith",
+ "department": 1440
+ }
+ ]
+ }
+}
diff --git a/contrib/libxo/tests/core/saved/test_03.T.err b/contrib/libxo/tests/core/saved/test_03.T.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.T.err
diff --git a/contrib/libxo/tests/core/saved/test_03.T.out b/contrib/libxo/tests/core/saved/test_03.T.out
new file mode 100644
index 0000000..da60fb7
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.T.out
@@ -0,0 +1,3 @@
+Terry Jones works in dept #660
+Leslie Patterson works in dept #341
+Ashley Smith works in dept #1440
diff --git a/contrib/libxo/tests/core/saved/test_03.X.err b/contrib/libxo/tests/core/saved/test_03.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.X.err
diff --git a/contrib/libxo/tests/core/saved/test_03.X.out b/contrib/libxo/tests/core/saved/test_03.X.out
new file mode 100644
index 0000000..a626fb6
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.X.out
@@ -0,0 +1 @@
+<employees><employee><first-name>Terry</first-name><last-name>Jones</last-name><department>660</department></employee><employee><first-name>Leslie</first-name><last-name>Patterson</last-name><department>341</department></employee><employee><first-name>Ashley</first-name><last-name>Smith</last-name><department>1440</department></employee></employees> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_03.XP.err b/contrib/libxo/tests/core/saved/test_03.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.XP.err
diff --git a/contrib/libxo/tests/core/saved/test_03.XP.out b/contrib/libxo/tests/core/saved/test_03.XP.out
new file mode 100644
index 0000000..b6e7641
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.XP.out
@@ -0,0 +1,17 @@
+<employees>
+ <employee>
+ <first-name>Terry</first-name>
+ <last-name>Jones</last-name>
+ <department>660</department>
+ </employee>
+ <employee>
+ <first-name>Leslie</first-name>
+ <last-name>Patterson</last-name>
+ <department>341</department>
+ </employee>
+ <employee>
+ <first-name>Ashley</first-name>
+ <last-name>Smith</last-name>
+ <department>1440</department>
+ </employee>
+</employees>
diff --git a/contrib/libxo/tests/core/saved/test_03.err b/contrib/libxo/tests/core/saved/test_03.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.err
diff --git a/contrib/libxo/tests/core/saved/test_03.out b/contrib/libxo/tests/core/saved/test_03.out
new file mode 100644
index 0000000..da60fb7
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_03.out
@@ -0,0 +1,3 @@
+Terry Jones works in dept #660
+Leslie Patterson works in dept #341
+Ashley Smith works in dept #1440
diff --git a/contrib/libxo/tests/core/saved/test_04.H.err b/contrib/libxo/tests/core/saved/test_04.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.H.err
diff --git a/contrib/libxo/tests/core/saved/test_04.H.out b/contrib/libxo/tests/core/saved/test_04.H.out
new file mode 100644
index 0000000..1758236
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.H.out
@@ -0,0 +1 @@
+<div class="line"><div class="title">Last Name </div><div class="title">First Name </div><div class="title">Department</div></div><div class="line"><div class="data" data-tag="first-name">Terry </div><div class="data" data-tag="last-name">Jones </div><div class="data" data-tag="department"> 660</div></div><div class="line"><div class="data" data-tag="first-name">Leslie </div><div class="data" data-tag="last-name">Patterson </div><div class="data" data-tag="department"> 341</div></div><div class="line"><div class="data" data-tag="first-name">Ashley </div><div class="data" data-tag="last-name">Smith </div><div class="data" data-tag="department"> 1440</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_04.HIPx.err b/contrib/libxo/tests/core/saved/test_04.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.HIPx.err
diff --git a/contrib/libxo/tests/core/saved/test_04.HIPx.out b/contrib/libxo/tests/core/saved/test_04.HIPx.out
new file mode 100644
index 0000000..473113b
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.HIPx.out
@@ -0,0 +1,20 @@
+<div class="line">
+ <div class="title">Last Name </div>
+ <div class="title">First Name </div>
+ <div class="title">Department</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Terry </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Jones </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 660</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Leslie </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Patterson </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 341</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Ashley </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Smith </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 1440</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_04.HP.err b/contrib/libxo/tests/core/saved/test_04.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.HP.err
diff --git a/contrib/libxo/tests/core/saved/test_04.HP.out b/contrib/libxo/tests/core/saved/test_04.HP.out
new file mode 100644
index 0000000..d56f8f4
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.HP.out
@@ -0,0 +1,20 @@
+<div class="line">
+ <div class="title">Last Name </div>
+ <div class="title">First Name </div>
+ <div class="title">Department</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Terry </div>
+ <div class="data" data-tag="last-name">Jones </div>
+ <div class="data" data-tag="department"> 660</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Leslie </div>
+ <div class="data" data-tag="last-name">Patterson </div>
+ <div class="data" data-tag="department"> 341</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Ashley </div>
+ <div class="data" data-tag="last-name">Smith </div>
+ <div class="data" data-tag="department"> 1440</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_04.J.err b/contrib/libxo/tests/core/saved/test_04.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.J.err
diff --git a/contrib/libxo/tests/core/saved/test_04.J.out b/contrib/libxo/tests/core/saved/test_04.J.out
new file mode 100644
index 0000000..4ba1fb1
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.J.out
@@ -0,0 +1,2 @@
+{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
+}
diff --git a/contrib/libxo/tests/core/saved/test_04.JP.err b/contrib/libxo/tests/core/saved/test_04.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.JP.err
diff --git a/contrib/libxo/tests/core/saved/test_04.JP.out b/contrib/libxo/tests/core/saved/test_04.JP.out
new file mode 100644
index 0000000..ff2d5b0
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.JP.out
@@ -0,0 +1,21 @@
+{
+ "employees": {
+ "employee": [
+ {
+ "first-name": "Terry",
+ "last-name": "Jones",
+ "department": 660
+ },
+ {
+ "first-name": "Leslie",
+ "last-name": "Patterson",
+ "department": 341
+ },
+ {
+ "first-name": "Ashley",
+ "last-name": "Smith",
+ "department": 1440
+ }
+ ]
+ }
+}
diff --git a/contrib/libxo/tests/core/saved/test_04.T.err b/contrib/libxo/tests/core/saved/test_04.T.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.T.err
diff --git a/contrib/libxo/tests/core/saved/test_04.T.out b/contrib/libxo/tests/core/saved/test_04.T.out
new file mode 100644
index 0000000..aca80c4
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.T.out
@@ -0,0 +1,4 @@
+Last Name First Name Department
+Terry Jones 660
+Leslie Patterson 341
+Ashley Smith 1440
diff --git a/contrib/libxo/tests/core/saved/test_04.X.err b/contrib/libxo/tests/core/saved/test_04.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.X.err
diff --git a/contrib/libxo/tests/core/saved/test_04.X.out b/contrib/libxo/tests/core/saved/test_04.X.out
new file mode 100644
index 0000000..a626fb6
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.X.out
@@ -0,0 +1 @@
+<employees><employee><first-name>Terry</first-name><last-name>Jones</last-name><department>660</department></employee><employee><first-name>Leslie</first-name><last-name>Patterson</last-name><department>341</department></employee><employee><first-name>Ashley</first-name><last-name>Smith</last-name><department>1440</department></employee></employees> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_04.XP.err b/contrib/libxo/tests/core/saved/test_04.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.XP.err
diff --git a/contrib/libxo/tests/core/saved/test_04.XP.out b/contrib/libxo/tests/core/saved/test_04.XP.out
new file mode 100644
index 0000000..b6e7641
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_04.XP.out
@@ -0,0 +1,17 @@
+<employees>
+ <employee>
+ <first-name>Terry</first-name>
+ <last-name>Jones</last-name>
+ <department>660</department>
+ </employee>
+ <employee>
+ <first-name>Leslie</first-name>
+ <last-name>Patterson</last-name>
+ <department>341</department>
+ </employee>
+ <employee>
+ <first-name>Ashley</first-name>
+ <last-name>Smith</last-name>
+ <department>1440</department>
+ </employee>
+</employees>
diff --git a/contrib/libxo/tests/core/saved/test_05.H.err b/contrib/libxo/tests/core/saved/test_05.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.H.err
diff --git a/contrib/libxo/tests/core/saved/test_05.H.out b/contrib/libxo/tests/core/saved/test_05.H.out
new file mode 100644
index 0000000..b75d728
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.H.out
@@ -0,0 +1 @@
+<div class="line"><div class="text">Οὐχὶ ταὐτὰ παρίσταταί μοι </div><div class="data" data-tag="v1">γιγνώσκειν</div><div class="text">, </div><div class="data" data-tag="v2">ὦ ἄνδρες ᾿Αθηναῖοι</div></div><div class="line"><div class="text">გთხოვთ </div><div class="data" data-tag="v1">ახლავე გაიაროთ რეგისტრაცია</div><div class="text"> </div><div class="data" data-tag="v2">Unicode-ის მეათე საერთაშორისო</div></div><div class="line"><div class="title">First Name </div><div class="title">Last Name </div><div class="title">Department </div><div class="title">Time (%)</div></div><div class="line"><div class="data" data-tag="first-name">Jim</div><div class="text"> (</div><div class="data" data-tag="nic-name">"რეგტ"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">გთხოვთ ახ </div><div class="data" data-tag="department"> 431</div><div class="data" data-tag="percent-time"> 90</div></div><div class="line"><div class="data" data-tag="first-name">Terry</div><div class="text"> (</div><div class="data" data-tag="nic-name">"&lt;one"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">Οὐχὶ ταὐτὰ παρ</div><div class="data" data-tag="department"> 660</div><div class="data" data-tag="percent-time"> 90</div></div><div class="line"><div class="data" data-tag="first-name">Leslie</div><div class="text"> (</div><div class="data" data-tag="nic-name">"Les"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">Patterson </div><div class="data" data-tag="department"> 341</div><div class="data" data-tag="percent-time"> 60</div></div><div class="line"><div class="data" data-tag="first-name">Ashley</div><div class="text"> (</div><div class="data" data-tag="nic-name">"Ash"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">Meter &amp; Smith </div><div class="data" data-tag="department"> 1440</div><div class="data" data-tag="percent-time"> 40</div></div><div class="line"><div class="data" data-tag="first-name">0123456789</div><div class="text"> (</div><div class="data" data-tag="nic-name">"0123456789"</div><div class="text">)</div><div class="data" data-tag="last-name">01234567890123</div><div class="data" data-tag="department"> 1440</div><div class="data" data-tag="percent-time"> 40</div></div><div class="line"><div class="data" data-tag="first-name">ახლა</div><div class="text"> (</div><div class="data" data-tag="nic-name">"გაიარო"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">საერთაშორისო </div><div class="data" data-tag="department"> 123</div><div class="data" data-tag="percent-time"> 90</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_05.HIPx.err b/contrib/libxo/tests/core/saved/test_05.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.HIPx.err
diff --git a/contrib/libxo/tests/core/saved/test_05.HIPx.out b/contrib/libxo/tests/core/saved/test_05.HIPx.out
new file mode 100644
index 0000000..2054de1
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.HIPx.out
@@ -0,0 +1,77 @@
+<div class="line">
+ <div class="text">Οὐχὶ ταὐτὰ παρίσταταί μοι </div>
+ <div class="data" data-tag="v1" data-xpath="/employees/v1">γιγνώσκειν</div>
+ <div class="text">, </div>
+ <div class="data" data-tag="v2" data-xpath="/employees/v2">ὦ ἄνδρες ᾿Αθηναῖοι</div>
+</div>
+<div class="line">
+ <div class="text">გთხოვთ </div>
+ <div class="data" data-tag="v1" data-xpath="/employees/v1">ახლავე გაიაროთ რეგისტრაცია</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="v2" data-xpath="/employees/v2">Unicode-ის მეათე საერთაშორისო</div>
+</div>
+<div class="line">
+ <div class="title">First Name </div>
+ <div class="title">Last Name </div>
+ <div class="title">Department </div>
+ <div class="title">Time (%)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Jim</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"რეგტ"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">გთხოვთ ახ </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 431</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Terry</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"&lt;one"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Οὐχὶ ταὐτὰ παρ</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 660</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Leslie</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"Les"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Patterson </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 341</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 60</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Ashley</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"Ash"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Meter &amp; Smith </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 1440</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">0123456789</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"0123456789"</div>
+ <div class="text">)</div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">01234567890123</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 1440</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">ახლა</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"გაიარო"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">საერთაშორისო </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 123</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 90</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_05.HP.err b/contrib/libxo/tests/core/saved/test_05.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.HP.err
diff --git a/contrib/libxo/tests/core/saved/test_05.HP.out b/contrib/libxo/tests/core/saved/test_05.HP.out
new file mode 100644
index 0000000..1c34b95
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.HP.out
@@ -0,0 +1,77 @@
+<div class="line">
+ <div class="text">Οὐχὶ ταὐτὰ παρίσταταί μοι </div>
+ <div class="data" data-tag="v1">γιγνώσκειν</div>
+ <div class="text">, </div>
+ <div class="data" data-tag="v2">ὦ ἄνδρες ᾿Αθηναῖοι</div>
+</div>
+<div class="line">
+ <div class="text">გთხოვთ </div>
+ <div class="data" data-tag="v1">ახლავე გაიაროთ რეგისტრაცია</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="v2">Unicode-ის მეათე საერთაშორისო</div>
+</div>
+<div class="line">
+ <div class="title">First Name </div>
+ <div class="title">Last Name </div>
+ <div class="title">Department </div>
+ <div class="title">Time (%)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Jim</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"რეგტ"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">გთხოვთ ახ </div>
+ <div class="data" data-tag="department"> 431</div>
+ <div class="data" data-tag="percent-time"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Terry</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"&lt;one"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">Οὐχὶ ταὐτὰ παρ</div>
+ <div class="data" data-tag="department"> 660</div>
+ <div class="data" data-tag="percent-time"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Leslie</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"Les"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">Patterson </div>
+ <div class="data" data-tag="department"> 341</div>
+ <div class="data" data-tag="percent-time"> 60</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Ashley</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"Ash"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">Meter &amp; Smith </div>
+ <div class="data" data-tag="department"> 1440</div>
+ <div class="data" data-tag="percent-time"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">0123456789</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"0123456789"</div>
+ <div class="text">)</div>
+ <div class="data" data-tag="last-name">01234567890123</div>
+ <div class="data" data-tag="department"> 1440</div>
+ <div class="data" data-tag="percent-time"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">ახლა</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"გაიარო"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">საერთაშორისო </div>
+ <div class="data" data-tag="department"> 123</div>
+ <div class="data" data-tag="percent-time"> 90</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_05.J.err b/contrib/libxo/tests/core/saved/test_05.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.J.err
diff --git a/contrib/libxo/tests/core/saved/test_05.J.out b/contrib/libxo/tests/core/saved/test_05.J.out
new file mode 100644
index 0000000..5155489
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.J.out
@@ -0,0 +1,2 @@
+{"employees": {"v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო", "employee": [{"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"benefits":"full"}]}
+}
diff --git a/contrib/libxo/tests/core/saved/test_05.JP.err b/contrib/libxo/tests/core/saved/test_05.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.JP.err
diff --git a/contrib/libxo/tests/core/saved/test_05.JP.out b/contrib/libxo/tests/core/saved/test_05.JP.out
new file mode 100644
index 0000000..7d77d70
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.JP.out
@@ -0,0 +1,56 @@
+{
+ "employees": {
+ "v1": "γιγνώσκειν",
+ "v2": "ὦ ἄνδρες ᾿Αθηναῖοι",
+ "v1": "ახლავე გაიაროთ რეგისტრაცია",
+ "v2": "Unicode-ის მეათე საერთაშორისო",
+ "employee": [
+ {
+ "first-name": "Jim",
+ "nic-name": "\"რეგტ\"",
+ "last-name": "გთხოვთ ახ",
+ "department": 431,
+ "percent-time": 90,
+ "benefits": "full"
+ },
+ {
+ "first-name": "Terry",
+ "nic-name": "\"<one\"",
+ "last-name": "Οὐχὶ ταὐτὰ παρίσταταί μοι Jones",
+ "department": 660,
+ "percent-time": 90,
+ "benefits": "full"
+ },
+ {
+ "first-name": "Leslie",
+ "nic-name": "\"Les\"",
+ "last-name": "Patterson",
+ "department": 341,
+ "percent-time": 60,
+ "benefits": "full"
+ },
+ {
+ "first-name": "Ashley",
+ "nic-name": "\"Ash\"",
+ "last-name": "Meter & Smith",
+ "department": 1440,
+ "percent-time": 40
+ },
+ {
+ "first-name": "0123456789",
+ "nic-name": "\"0123456789\"",
+ "last-name": "012345678901234567890",
+ "department": 1440,
+ "percent-time": 40
+ },
+ {
+ "first-name": "ახლა",
+ "nic-name": "\"გაიარო\"",
+ "last-name": "საერთაშორისო",
+ "department": 123,
+ "percent-time": 90,
+ "benefits": "full"
+ }
+ ]
+ }
+}
diff --git a/contrib/libxo/tests/core/saved/test_05.T.err b/contrib/libxo/tests/core/saved/test_05.T.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.T.err
diff --git a/contrib/libxo/tests/core/saved/test_05.T.out b/contrib/libxo/tests/core/saved/test_05.T.out
new file mode 100644
index 0000000..c709f6c
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.T.out
@@ -0,0 +1,9 @@
+Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι
+გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
+First Name Last Name Department Time (%)
+Jim ("რეგტ") გთხოვთ ახ 431 90
+Terry ("<one") Οὐχὶ ταὐτὰ παρ 660 90
+Leslie ("Les") Patterson 341 60
+Ashley ("Ash") Meter & Smith 1440 40
+0123456789 ("0123456789")01234567890123 1440 40
+ახლა ("გაიარო") საერთაშორისო 123 90
diff --git a/contrib/libxo/tests/core/saved/test_05.X.err b/contrib/libxo/tests/core/saved/test_05.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.X.err
diff --git a/contrib/libxo/tests/core/saved/test_05.X.out b/contrib/libxo/tests/core/saved/test_05.X.out
new file mode 100644
index 0000000..85ecbbc
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.X.out
@@ -0,0 +1 @@
+<employees><v1>γιγνώσκειν</v1><v2>ὦ ἄνδρες ᾿Αθηναῖοι</v2><v1>ახლავე გაიაროთ რეგისტრაცია</v1><v2>Unicode-ის მეათე საერთაშორისო</v2><employee><first-name>Jim</first-name><nic-name>"რეგტ"</nic-name><last-name>გთხოვთ ახ</last-name><department>431</department><percent-time>90</percent-time><benefits full-time="honest &amp; for true">full</benefits></employee><employee><first-name>Terry</first-name><nic-name>"&lt;one"</nic-name><last-name>Οὐχὶ ταὐτὰ παρίσταταί μοι Jones</last-name><department>660</department><percent-time>90</percent-time><benefits full-time="honest &amp; for true">full</benefits></employee><employee><first-name>Leslie</first-name><nic-name>"Les"</nic-name><last-name>Patterson</last-name><department>341</department><percent-time>60</percent-time><benefits full-time="honest &amp; for true">full</benefits></employee><employee><first-name>Ashley</first-name><nic-name>"Ash"</nic-name><last-name>Meter &amp; Smith</last-name><department>1440</department><percent-time>40</percent-time></employee><employee><first-name>0123456789</first-name><nic-name>"0123456789"</nic-name><last-name>012345678901234567890</last-name><department>1440</department><percent-time>40</percent-time></employee><employee><first-name>ახლა</first-name><nic-name>"გაიარო"</nic-name><last-name>საერთაშორისო</last-name><department>123</department><percent-time>90</percent-time><benefits full-time="honest &amp; for true">full</benefits></employee></employees> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_05.XP.err b/contrib/libxo/tests/core/saved/test_05.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.XP.err
diff --git a/contrib/libxo/tests/core/saved/test_05.XP.out b/contrib/libxo/tests/core/saved/test_05.XP.out
new file mode 100644
index 0000000..55507eb
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_05.XP.out
@@ -0,0 +1,52 @@
+<employees>
+ <v1>γιγνώσκειν</v1>
+ <v2>ὦ ἄνδρες ᾿Αθηναῖοι</v2>
+ <v1>ახლავე გაიაროთ რეგისტრაცია</v1>
+ <v2>Unicode-ის მეათე საერთაშორისო</v2>
+ <employee>
+ <first-name>Jim</first-name>
+ <nic-name>"რეგტ"</nic-name>
+ <last-name>გთხოვთ ახ</last-name>
+ <department>431</department>
+ <percent-time>90</percent-time>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+ <employee>
+ <first-name>Terry</first-name>
+ <nic-name>"&lt;one"</nic-name>
+ <last-name>Οὐχὶ ταὐτὰ παρίσταταί μοι Jones</last-name>
+ <department>660</department>
+ <percent-time>90</percent-time>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+ <employee>
+ <first-name>Leslie</first-name>
+ <nic-name>"Les"</nic-name>
+ <last-name>Patterson</last-name>
+ <department>341</department>
+ <percent-time>60</percent-time>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+ <employee>
+ <first-name>Ashley</first-name>
+ <nic-name>"Ash"</nic-name>
+ <last-name>Meter &amp; Smith</last-name>
+ <department>1440</department>
+ <percent-time>40</percent-time>
+ </employee>
+ <employee>
+ <first-name>0123456789</first-name>
+ <nic-name>"0123456789"</nic-name>
+ <last-name>012345678901234567890</last-name>
+ <department>1440</department>
+ <percent-time>40</percent-time>
+ </employee>
+ <employee>
+ <first-name>ახლა</first-name>
+ <nic-name>"გაიარო"</nic-name>
+ <last-name>საერთაშორისო</last-name>
+ <department>123</department>
+ <percent-time>90</percent-time>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+</employees>
diff --git a/contrib/libxo/tests/core/saved/test_06.H.err b/contrib/libxo/tests/core/saved/test_06.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.H.err
diff --git a/contrib/libxo/tests/core/saved/test_06.H.out b/contrib/libxo/tests/core/saved/test_06.H.out
new file mode 100644
index 0000000..6b9ccc4
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.H.out
@@ -0,0 +1 @@
+<div class="line"><div class="data" data-tag="first-name">Terry</div><div class="text"> </div><div class="data" data-tag="last-name">Jones</div><div class="text"> works in dept #</div><div class="data" data-tag="department">660</div></div><div class="line"><div class="data" data-tag="first-name">Leslie</div><div class="text"> </div><div class="data" data-tag="last-name">Patterson</div><div class="text"> works in dept #</div><div class="data" data-tag="department">341</div></div><div class="line"><div class="data" data-tag="first-name">Ashley</div><div class="text"> </div><div class="data" data-tag="last-name">Smith</div><div class="text"> works in dept #</div><div class="data" data-tag="department">1440</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_06.HIPx.err b/contrib/libxo/tests/core/saved/test_06.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.HIPx.err
diff --git a/contrib/libxo/tests/core/saved/test_06.HIPx.out b/contrib/libxo/tests/core/saved/test_06.HIPx.out
new file mode 100644
index 0000000..bfae221
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.HIPx.out
@@ -0,0 +1,21 @@
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Terry</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Jones</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department">660</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Leslie</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Patterson</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department">341</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Ashley</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Smith</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department">1440</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_06.HP.err b/contrib/libxo/tests/core/saved/test_06.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.HP.err
diff --git a/contrib/libxo/tests/core/saved/test_06.HP.out b/contrib/libxo/tests/core/saved/test_06.HP.out
new file mode 100644
index 0000000..f8b072a
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.HP.out
@@ -0,0 +1,21 @@
+<div class="line">
+ <div class="data" data-tag="first-name">Terry</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name">Jones</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department">660</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Leslie</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name">Patterson</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department">341</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Ashley</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="last-name">Smith</div>
+ <div class="text"> works in dept #</div>
+ <div class="data" data-tag="department">1440</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_06.J.err b/contrib/libxo/tests/core/saved/test_06.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.J.err
diff --git a/contrib/libxo/tests/core/saved/test_06.J.out b/contrib/libxo/tests/core/saved/test_06.J.out
new file mode 100644
index 0000000..4ba1fb1
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.J.out
@@ -0,0 +1,2 @@
+{"employees": {"employee": [{"first-name":"Terry","last-name":"Jones","department":660}, {"first-name":"Leslie","last-name":"Patterson","department":341}, {"first-name":"Ashley","last-name":"Smith","department":1440}]}
+}
diff --git a/contrib/libxo/tests/core/saved/test_06.JP.err b/contrib/libxo/tests/core/saved/test_06.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.JP.err
diff --git a/contrib/libxo/tests/core/saved/test_06.JP.out b/contrib/libxo/tests/core/saved/test_06.JP.out
new file mode 100644
index 0000000..ff2d5b0
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.JP.out
@@ -0,0 +1,21 @@
+{
+ "employees": {
+ "employee": [
+ {
+ "first-name": "Terry",
+ "last-name": "Jones",
+ "department": 660
+ },
+ {
+ "first-name": "Leslie",
+ "last-name": "Patterson",
+ "department": 341
+ },
+ {
+ "first-name": "Ashley",
+ "last-name": "Smith",
+ "department": 1440
+ }
+ ]
+ }
+}
diff --git a/contrib/libxo/tests/core/saved/test_06.T.err b/contrib/libxo/tests/core/saved/test_06.T.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.T.err
diff --git a/contrib/libxo/tests/core/saved/test_06.T.out b/contrib/libxo/tests/core/saved/test_06.T.out
new file mode 100644
index 0000000..da60fb7
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.T.out
@@ -0,0 +1,3 @@
+Terry Jones works in dept #660
+Leslie Patterson works in dept #341
+Ashley Smith works in dept #1440
diff --git a/contrib/libxo/tests/core/saved/test_06.X.err b/contrib/libxo/tests/core/saved/test_06.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.X.err
diff --git a/contrib/libxo/tests/core/saved/test_06.X.out b/contrib/libxo/tests/core/saved/test_06.X.out
new file mode 100644
index 0000000..a626fb6
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.X.out
@@ -0,0 +1 @@
+<employees><employee><first-name>Terry</first-name><last-name>Jones</last-name><department>660</department></employee><employee><first-name>Leslie</first-name><last-name>Patterson</last-name><department>341</department></employee><employee><first-name>Ashley</first-name><last-name>Smith</last-name><department>1440</department></employee></employees> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_06.XP.err b/contrib/libxo/tests/core/saved/test_06.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.XP.err
diff --git a/contrib/libxo/tests/core/saved/test_06.XP.out b/contrib/libxo/tests/core/saved/test_06.XP.out
new file mode 100644
index 0000000..b6e7641
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_06.XP.out
@@ -0,0 +1,17 @@
+<employees>
+ <employee>
+ <first-name>Terry</first-name>
+ <last-name>Jones</last-name>
+ <department>660</department>
+ </employee>
+ <employee>
+ <first-name>Leslie</first-name>
+ <last-name>Patterson</last-name>
+ <department>341</department>
+ </employee>
+ <employee>
+ <first-name>Ashley</first-name>
+ <last-name>Smith</last-name>
+ <department>1440</department>
+ </employee>
+</employees>
diff --git a/contrib/libxo/tests/core/saved/test_07.H.err b/contrib/libxo/tests/core/saved/test_07.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.H.err
diff --git a/contrib/libxo/tests/core/saved/test_07.H.out b/contrib/libxo/tests/core/saved/test_07.H.out
new file mode 100644
index 0000000..9fd042b
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.H.out
@@ -0,0 +1 @@
+<div class="line"><div class="text">Οὐχὶ ταὐτὰ παρίσταταί μοι </div><div class="data" data-tag="v1">γιγνώσκειν</div><div class="text">, </div><div class="data" data-tag="v2">ὦ ἄνδρες ᾿Αθηναῖοι</div></div><div class="line"><div class="data" data-tag="columns">56</div></div><div class="line"><div class="data" data-tag="columns">2</div></div><div class="line"><div class="text">გთხოვთ </div><div class="data" data-tag="v1">ახლავე გაიაროთ რეგისტრაცია</div><div class="text"> </div><div class="data" data-tag="v2">Unicode-ის მეათე საერთაშორისო</div></div><div class="line"><div class="data" data-tag="columns">63</div></div><div class="line"><div class="title">First Name </div><div class="title">Last Name </div><div class="title">Department </div><div class="title">Time (%)</div></div><div class="line"><div class="data" data-tag="columns">59</div></div><div class="line"><div class="data" data-tag="first-name">Jim</div><div class="text"> (</div><div class="data" data-tag="nic-name">"რეგტ"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">გთხოვთ ახ </div><div class="data" data-tag="department"> 431</div><div class="data" data-tag="percent-time"> 90</div></div><div class="line"><div class="data" data-tag="columns">55</div></div><div class="line"><div class="data" data-tag="first-name">Terry</div><div class="text"> (</div><div class="data" data-tag="nic-name">"&lt;one"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">Οὐχὶ ταὐτὰ παρ</div><div class="data" data-tag="department"> 660</div><div class="data" data-tag="percent-time"> 90</div></div><div class="line"><div class="data" data-tag="columns">55</div></div><div class="line"><div class="data" data-tag="first-name">Leslie</div><div class="text"> (</div><div class="data" data-tag="nic-name">"Les"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">Patterson </div><div class="data" data-tag="department"> 341</div><div class="data" data-tag="percent-time"> 60</div></div><div class="line"><div class="data" data-tag="columns">55</div></div><div class="line"><div class="data" data-tag="first-name">Ashley</div><div class="text"> (</div><div class="data" data-tag="nic-name">"Ash"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">Meter &amp; Smith </div><div class="data" data-tag="department"> 1440</div><div class="data" data-tag="percent-time"> 40</div></div><div class="line"><div class="data" data-tag="columns">55</div></div><div class="line"><div class="data" data-tag="first-name">0123456789</div><div class="text"> (</div><div class="data" data-tag="nic-name">"0123456789"</div><div class="text">)</div><div class="data" data-tag="last-name">01234567890123</div><div class="data" data-tag="department"> 1440</div><div class="data" data-tag="percent-time"> 40</div></div><div class="line"><div class="data" data-tag="columns">55</div></div><div class="line"><div class="data" data-tag="first-name">ახლა</div><div class="text"> (</div><div class="data" data-tag="nic-name">"გაიარო"</div><div class="text">)</div><div class="padding"> </div><div class="data" data-tag="last-name">საერთაშორისო </div><div class="data" data-tag="department"> 123</div><div class="data" data-tag="percent-time"> 90</div></div><div class="line"><div class="data" data-tag="columns">55</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_07.HIPx.err b/contrib/libxo/tests/core/saved/test_07.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.HIPx.err
diff --git a/contrib/libxo/tests/core/saved/test_07.HIPx.out b/contrib/libxo/tests/core/saved/test_07.HIPx.out
new file mode 100644
index 0000000..197c475
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.HIPx.out
@@ -0,0 +1,107 @@
+<div class="line">
+ <div class="text">Οὐχὶ ταὐτὰ παρίσταταί μοι </div>
+ <div class="data" data-tag="v1" data-xpath="/employees/v1">γιγνώσκειν</div>
+ <div class="text">, </div>
+ <div class="data" data-tag="v2" data-xpath="/employees/v2">ὦ ἄνδρες ᾿Αθηναῖοι</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/columns">56</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/columns">2</div>
+</div>
+<div class="line">
+ <div class="text">გთხოვთ </div>
+ <div class="data" data-tag="v1" data-xpath="/employees/v1">ახლავე გაიაროთ რეგისტრაცია</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="v2" data-xpath="/employees/v2">Unicode-ის მეათე საერთაშორისო</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/columns">63</div>
+</div>
+<div class="line">
+ <div class="title">First Name </div>
+ <div class="title">Last Name </div>
+ <div class="title">Department </div>
+ <div class="title">Time (%)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/columns">59</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Jim</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"რეგტ"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">გთხოვთ ახ </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 431</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/employee/columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Terry</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"&lt;one"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Οὐχὶ ταὐτὰ παρ</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 660</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/employee/columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Leslie</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"Les"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Patterson </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 341</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 60</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/employee/columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">Ashley</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"Ash"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">Meter &amp; Smith </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 1440</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/employee/columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">0123456789</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"0123456789"</div>
+ <div class="text">)</div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">01234567890123</div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 1440</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/employee/columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name" data-xpath="/employees/employee/first-name" data-type="string" data-help="First name of employee">ახლა</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name" data-xpath="/employees/employee/nic-name">"გაიარო"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name" data-xpath="/employees/employee/last-name" data-type="string" data-help="Last name of employee">საერთაშორისო </div>
+ <div class="data" data-tag="department" data-xpath="/employees/employee/department"> 123</div>
+ <div class="data" data-tag="percent-time" data-xpath="/employees/employee/percent-time" data-type="number" data-help="Percentage of full &amp; part time (%)"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns" data-xpath="/employees/employee/columns">55</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_07.HP.err b/contrib/libxo/tests/core/saved/test_07.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.HP.err
diff --git a/contrib/libxo/tests/core/saved/test_07.HP.out b/contrib/libxo/tests/core/saved/test_07.HP.out
new file mode 100644
index 0000000..a5ce61d
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.HP.out
@@ -0,0 +1,107 @@
+<div class="line">
+ <div class="text">Οὐχὶ ταὐτὰ παρίσταταί μοι </div>
+ <div class="data" data-tag="v1">γιγνώσκειν</div>
+ <div class="text">, </div>
+ <div class="data" data-tag="v2">ὦ ἄνδρες ᾿Αθηναῖοι</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">56</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">2</div>
+</div>
+<div class="line">
+ <div class="text">გთხოვთ </div>
+ <div class="data" data-tag="v1">ახლავე გაიაროთ რეგისტრაცია</div>
+ <div class="text"> </div>
+ <div class="data" data-tag="v2">Unicode-ის მეათე საერთაშორისო</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">63</div>
+</div>
+<div class="line">
+ <div class="title">First Name </div>
+ <div class="title">Last Name </div>
+ <div class="title">Department </div>
+ <div class="title">Time (%)</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">59</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Jim</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"რეგტ"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">გთხოვთ ახ </div>
+ <div class="data" data-tag="department"> 431</div>
+ <div class="data" data-tag="percent-time"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Terry</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"&lt;one"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">Οὐχὶ ταὐτὰ παρ</div>
+ <div class="data" data-tag="department"> 660</div>
+ <div class="data" data-tag="percent-time"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Leslie</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"Les"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">Patterson </div>
+ <div class="data" data-tag="department"> 341</div>
+ <div class="data" data-tag="percent-time"> 60</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">Ashley</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"Ash"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">Meter &amp; Smith </div>
+ <div class="data" data-tag="department"> 1440</div>
+ <div class="data" data-tag="percent-time"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">0123456789</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"0123456789"</div>
+ <div class="text">)</div>
+ <div class="data" data-tag="last-name">01234567890123</div>
+ <div class="data" data-tag="department"> 1440</div>
+ <div class="data" data-tag="percent-time"> 40</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">55</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="first-name">ახლა</div>
+ <div class="text"> (</div>
+ <div class="data" data-tag="nic-name">"გაიარო"</div>
+ <div class="text">)</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="last-name">საერთაშორისო </div>
+ <div class="data" data-tag="department"> 123</div>
+ <div class="data" data-tag="percent-time"> 90</div>
+</div>
+<div class="line">
+ <div class="data" data-tag="columns">55</div>
+</div>
diff --git a/contrib/libxo/tests/core/saved/test_07.J.err b/contrib/libxo/tests/core/saved/test_07.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.J.err
diff --git a/contrib/libxo/tests/core/saved/test_07.J.out b/contrib/libxo/tests/core/saved/test_07.J.out
new file mode 100644
index 0000000..2c9a928
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.J.out
@@ -0,0 +1,2 @@
+{"employees": {"v1":"γιγνώσκειν","v2":"ὦ ἄνδρες ᾿Αθηναῖοι","columns":28,"columns":2,"v1":"ახლავე გაიაროთ რეგისტრაცია","v2":"Unicode-ის მეათე საერთაშორისო","columns":55, "employee": ["columns":0, {"first-name":"Jim","nic-name":"\"რეგტ\"","last-name":"გთხოვთ ახ","department":431,"percent-time":90,"columns":23,"benefits":"full"}, {"first-name":"Terry","nic-name":"\"<one\"","last-name":"Οὐχὶ ταὐτὰ παρίσταταί μοι Jones","department":660,"percent-time":90,"columns":47,"benefits":"full"}, {"first-name":"Leslie","nic-name":"\"Les\"","last-name":"Patterson","department":341,"percent-time":60,"columns":25,"benefits":"full"}, {"first-name":"Ashley","nic-name":"\"Ash\"","last-name":"Meter & Smith","department":1440,"percent-time":40,"columns":30}, {"first-name":"0123456789","nic-name":"\"0123456789\"","last-name":"012345678901234567890","department":1440,"percent-time":40,"columns":49}, {"first-name":"ახლა","nic-name":"\"გაიარო\"","last-name":"საერთაშორისო","department":123,"percent-time":90,"columns":29,"benefits":"full"}]}
+}
diff --git a/contrib/libxo/tests/core/saved/test_07.JP.err b/contrib/libxo/tests/core/saved/test_07.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.JP.err
diff --git a/contrib/libxo/tests/core/saved/test_07.JP.out b/contrib/libxo/tests/core/saved/test_07.JP.out
new file mode 100644
index 0000000..f22b9e5
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.JP.out
@@ -0,0 +1,66 @@
+{
+ "employees": {
+ "v1": "γιγνώσκειν",
+ "v2": "ὦ ἄνδρες ᾿Αθηναῖοι",
+ "columns": 28,
+ "columns": 2,
+ "v1": "ახლავე გაიაროთ რეგისტრაცია",
+ "v2": "Unicode-ის მეათე საერთაშორისო",
+ "columns": 55,
+ "employee": [
+ "columns": 0,
+ {
+ "first-name": "Jim",
+ "nic-name": "\"რეგტ\"",
+ "last-name": "გთხოვთ ახ",
+ "department": 431,
+ "percent-time": 90,
+ "columns": 23,
+ "benefits": "full"
+ },
+ {
+ "first-name": "Terry",
+ "nic-name": "\"<one\"",
+ "last-name": "Οὐχὶ ταὐτὰ παρίσταταί μοι Jones",
+ "department": 660,
+ "percent-time": 90,
+ "columns": 47,
+ "benefits": "full"
+ },
+ {
+ "first-name": "Leslie",
+ "nic-name": "\"Les\"",
+ "last-name": "Patterson",
+ "department": 341,
+ "percent-time": 60,
+ "columns": 25,
+ "benefits": "full"
+ },
+ {
+ "first-name": "Ashley",
+ "nic-name": "\"Ash\"",
+ "last-name": "Meter & Smith",
+ "department": 1440,
+ "percent-time": 40,
+ "columns": 30
+ },
+ {
+ "first-name": "0123456789",
+ "nic-name": "\"0123456789\"",
+ "last-name": "012345678901234567890",
+ "department": 1440,
+ "percent-time": 40,
+ "columns": 49
+ },
+ {
+ "first-name": "ახლა",
+ "nic-name": "\"გაიარო\"",
+ "last-name": "საერთაშორისო",
+ "department": 123,
+ "percent-time": 90,
+ "columns": 29,
+ "benefits": "full"
+ }
+ ]
+ }
+}
diff --git a/contrib/libxo/tests/core/saved/test_07.T.err b/contrib/libxo/tests/core/saved/test_07.T.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.T.err
diff --git a/contrib/libxo/tests/core/saved/test_07.T.out b/contrib/libxo/tests/core/saved/test_07.T.out
new file mode 100644
index 0000000..5f4ff5c
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.T.out
@@ -0,0 +1,19 @@
+Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι
+56
+2
+გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
+63
+First Name Last Name Department Time (%)
+59
+Jim ("რეგტ") გთხოვთ ახ 431 90
+55
+Terry ("<one") Οὐχὶ ταὐτὰ παρ 660 90
+55
+Leslie ("Les") Patterson 341 60
+55
+Ashley ("Ash") Meter & Smith 1440 40
+55
+0123456789 ("0123456789")01234567890123 1440 40
+55
+ახლა ("გაიარო") საერთაშორისო 123 90
+55
diff --git a/contrib/libxo/tests/core/saved/test_07.X.err b/contrib/libxo/tests/core/saved/test_07.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.X.err
diff --git a/contrib/libxo/tests/core/saved/test_07.X.out b/contrib/libxo/tests/core/saved/test_07.X.out
new file mode 100644
index 0000000..e5b70e0
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.X.out
@@ -0,0 +1 @@
+<employees><v1>γιγνώσκειν</v1><v2>ὦ ἄνδρες ᾿Αθηναῖοι</v2><columns>28</columns><columns>2</columns><v1>ახლავე გაიაროთ რეგისტრაცია</v1><v2>Unicode-ის მეათე საერთაშორისო</v2><columns>55</columns><columns>0</columns><employee><first-name>Jim</first-name><nic-name>"რეგტ"</nic-name><last-name>გთხოვთ ახ</last-name><department>431</department><percent-time>90</percent-time><columns>23</columns><benefits full-time="honest &amp; for true">full</benefits></employee><employee><first-name>Terry</first-name><nic-name>"&lt;one"</nic-name><last-name>Οὐχὶ ταὐτὰ παρίσταταί μοι Jones</last-name><department>660</department><percent-time>90</percent-time><columns>47</columns><benefits full-time="honest &amp; for true">full</benefits></employee><employee><first-name>Leslie</first-name><nic-name>"Les"</nic-name><last-name>Patterson</last-name><department>341</department><percent-time>60</percent-time><columns>25</columns><benefits full-time="honest &amp; for true">full</benefits></employee><employee><first-name>Ashley</first-name><nic-name>"Ash"</nic-name><last-name>Meter &amp; Smith</last-name><department>1440</department><percent-time>40</percent-time><columns>30</columns></employee><employee><first-name>0123456789</first-name><nic-name>"0123456789"</nic-name><last-name>012345678901234567890</last-name><department>1440</department><percent-time>40</percent-time><columns>49</columns></employee><employee><first-name>ახლა</first-name><nic-name>"გაიარო"</nic-name><last-name>საერთაშორისო</last-name><department>123</department><percent-time>90</percent-time><columns>29</columns><benefits full-time="honest &amp; for true">full</benefits></employee></employees> \ No newline at end of file
diff --git a/contrib/libxo/tests/core/saved/test_07.XP.err b/contrib/libxo/tests/core/saved/test_07.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.XP.err
diff --git a/contrib/libxo/tests/core/saved/test_07.XP.out b/contrib/libxo/tests/core/saved/test_07.XP.out
new file mode 100644
index 0000000..b502650
--- /dev/null
+++ b/contrib/libxo/tests/core/saved/test_07.XP.out
@@ -0,0 +1,62 @@
+<employees>
+ <v1>γιγνώσκειν</v1>
+ <v2>ὦ ἄνδρες ᾿Αθηναῖοι</v2>
+ <columns>28</columns>
+ <columns>2</columns>
+ <v1>ახლავე გაიაროთ რეგისტრაცია</v1>
+ <v2>Unicode-ის მეათე საერთაშორისო</v2>
+ <columns>55</columns>
+ <columns>0</columns>
+ <employee>
+ <first-name>Jim</first-name>
+ <nic-name>"რეგტ"</nic-name>
+ <last-name>გთხოვთ ახ</last-name>
+ <department>431</department>
+ <percent-time>90</percent-time>
+ <columns>23</columns>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+ <employee>
+ <first-name>Terry</first-name>
+ <nic-name>"&lt;one"</nic-name>
+ <last-name>Οὐχὶ ταὐτὰ παρίσταταί μοι Jones</last-name>
+ <department>660</department>
+ <percent-time>90</percent-time>
+ <columns>47</columns>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+ <employee>
+ <first-name>Leslie</first-name>
+ <nic-name>"Les"</nic-name>
+ <last-name>Patterson</last-name>
+ <department>341</department>
+ <percent-time>60</percent-time>
+ <columns>25</columns>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+ <employee>
+ <first-name>Ashley</first-name>
+ <nic-name>"Ash"</nic-name>
+ <last-name>Meter &amp; Smith</last-name>
+ <department>1440</department>
+ <percent-time>40</percent-time>
+ <columns>30</columns>
+ </employee>
+ <employee>
+ <first-name>0123456789</first-name>
+ <nic-name>"0123456789"</nic-name>
+ <last-name>012345678901234567890</last-name>
+ <department>1440</department>
+ <percent-time>40</percent-time>
+ <columns>49</columns>
+ </employee>
+ <employee>
+ <first-name>ახლა</first-name>
+ <nic-name>"გაიარო"</nic-name>
+ <last-name>საერთაშორისო</last-name>
+ <department>123</department>
+ <percent-time>90</percent-time>
+ <columns>29</columns>
+ <benefits full-time="honest &amp; for true">full</benefits>
+ </employee>
+</employees>
diff --git a/contrib/libxo/tests/core/test_01.c b/contrib/libxo/tests/core/test_01.c
new file mode 100644
index 0000000..164a38b
--- /dev/null
+++ b/contrib/libxo/tests/core/test_01.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xo.h"
+
+int
+main (int argc, char **argv)
+{
+ static char base_grocery[] = "GRO";
+ static char base_hardware[] = "HRD";
+ struct item {
+ const char *i_title;
+ int i_sold;
+ int i_instock;
+ int i_onorder;
+ const char *i_sku_base;
+ int i_sku_num;
+ };
+ struct item list[] = {
+ { "gum", 1412, 54, 10, base_grocery, 415 },
+ { "rope", 85, 4, 2, base_hardware, 212 },
+ { "ladder", 0, 2, 1, base_hardware, 517 },
+ { "bolt", 4123, 144, 42, base_hardware, 632 },
+ { "water", 17, 14, 2, base_grocery, 2331 },
+ { NULL, 0, 0, 0, NULL, 0 }
+ };
+ struct item list2[] = {
+ { "fish", 1321, 45, 1, base_grocery, 533 },
+ { NULL, 0, 0, 0, NULL, 0 }
+ };
+ struct item *ip;
+ xo_info_t info[] = {
+ { "in-stock", "number", "Number of items in stock" },
+ { "name", "string", "Name of the item" },
+ { "on-order", "number", "Number of items on order" },
+ { "sku", "string", "Stock Keeping Unit" },
+ { "sold", "number", "Number of items sold" },
+ { NULL, NULL, NULL },
+ };
+ int info_count = (sizeof(info) / sizeof(info[0])) - 1;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ for (argc = 1; argv[argc]; argc++) {
+ if (strcmp(argv[argc], "xml") == 0)
+ xo_set_style(NULL, XO_STYLE_XML);
+ else if (strcmp(argv[argc], "json") == 0)
+ xo_set_style(NULL, XO_STYLE_JSON);
+ else if (strcmp(argv[argc], "text") == 0)
+ xo_set_style(NULL, XO_STYLE_TEXT);
+ else if (strcmp(argv[argc], "html") == 0)
+ xo_set_style(NULL, XO_STYLE_HTML);
+ else if (strcmp(argv[argc], "pretty") == 0)
+ xo_set_flags(NULL, XOF_PRETTY);
+ else if (strcmp(argv[argc], "xpath") == 0)
+ xo_set_flags(NULL, XOF_XPATH);
+ else if (strcmp(argv[argc], "info") == 0)
+ xo_set_flags(NULL, XOF_INFO);
+ }
+
+ xo_set_info(NULL, info, info_count);
+ xo_set_flags(NULL, XOF_KEYS);
+
+ xo_open_container_h(NULL, "top");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ xo_emit("{T:Item/%-10s}{T:Total Sold/%12s}{T:In Stock/%12s}"
+ "{T:On Order/%12s}{T:SKU/%5s}\n");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_emit("{keq:sku/%s-%u/%s-000-%u}"
+ "{k:name/%-10s/%s}{n:sold/%12u/%u}{:in-stock/%12u/%u}"
+ "{:on-order/%12u/%u}{qkd:sku/%5s-000-%u/%s-000-%u}\n",
+ ip->i_sku_base, ip->i_sku_num,
+ ip->i_title, ip->i_sold, ip->i_instock, ip->i_onorder,
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_emit("\n\n");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ for (ip = list; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_emit("{keq:sku/%s-%u/%s-000-%u}", ip->i_sku_base, ip->i_sku_num);
+ xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title);
+ xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n",
+ ip->i_sold, ip->i_sold ? ".0" : "");
+ xo_emit("{P: }{Lcw:In stock}{:in-stock/%u}\n", ip->i_instock);
+ xo_emit("{P: }{Lcw:On order}{:on-order/%u}\n", ip->i_onorder);
+ xo_emit("{P: }{L:SKU}: {qkd:sku/%s-000-%u}\n",
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_open_container("data");
+ xo_open_list("item");
+
+ for (ip = list2; ip->i_title; ip++) {
+ xo_open_instance("item");
+
+ xo_emit("{keq:sku/%s-%u/%s-000-%u}", ip->i_sku_base, ip->i_sku_num);
+ xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title);
+ xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n",
+ ip->i_sold, ip->i_sold ? ".0" : "");
+ xo_emit("{P: }{Lcw:In stock}{:in-stock/%u}\n", ip->i_instock);
+ xo_emit("{P: }{Lcw:On order}{:on-order/%u}\n", ip->i_onorder);
+ xo_emit("{P: }{L:SKU}: {qkd:sku/%s-000-%u}\n",
+ ip->i_sku_base, ip->i_sku_num);
+
+ xo_close_instance("item");
+ }
+
+ xo_close_list("item");
+ xo_close_container("data");
+
+ xo_close_container_h(NULL, "top");
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/tests/core/test_02.c b/contrib/libxo/tests/core/test_02.c
new file mode 100644
index 0000000..abcb14b
--- /dev/null
+++ b/contrib/libxo/tests/core/test_02.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "xo.h"
+
+int
+main (int argc, char **argv)
+{
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ for (argc = 1; argv[argc]; argc++) {
+ if (strcmp(argv[argc], "xml") == 0)
+ xo_set_style(NULL, XO_STYLE_XML);
+ else if (strcmp(argv[argc], "json") == 0)
+ xo_set_style(NULL, XO_STYLE_JSON);
+ else if (strcmp(argv[argc], "text") == 0)
+ xo_set_style(NULL, XO_STYLE_TEXT);
+ else if (strcmp(argv[argc], "html") == 0)
+ xo_set_style(NULL, XO_STYLE_HTML);
+ else if (strcmp(argv[argc], "pretty") == 0)
+ xo_set_flags(NULL, XOF_PRETTY);
+ else if (strcmp(argv[argc], "xpath") == 0)
+ xo_set_flags(NULL, XOF_XPATH);
+ else if (strcmp(argv[argc], "info") == 0)
+ xo_set_flags(NULL, XOF_INFO);
+ }
+
+ xo_set_flags(NULL, XOF_UNITS); /* Always test w/ this */
+
+ xo_open_container_h(NULL, "top");
+
+ xo_open_container("data");
+
+ xo_emit("{:mbuf-current/%u}/{:mbuf-cache/%u}/{:mbuf-total/%u} "
+ "{N:mbufs <&> in use (current\\/cache\\/total)}\n",
+ 10, 20, 30);
+
+ xo_emit("{:distance/%u}{Uw:miles} from {:location}\n", 50, "Boston");
+ xo_emit("{:memory/%u}{U:k} left out of {:total/%u}{U:kb}\n", 64, 640);
+ xo_emit("{:memory/%u}{U:/%s} left out of {:total/%u}{U:/%s}\n",
+ 64, "k", 640, "kilobytes");
+
+ xo_emit("{T:/before%safter:}\n", "working");
+
+ xo_emit("{d:some/%s}{:ten/%ju}{:eleven/%ju}\n",
+ "string", (uintmax_t) 10, (uintmax_t) 11);
+
+ xo_emit("{:unknown/%u} "
+ "{N:/packet%s here\\/there\\/everywhere}\n",
+ 1010, "s");
+
+ xo_emit("({[:/%d}{n:min/15}/{n:cur/20}/{:max/%d}{]:})\n", 30, 125);
+ xo_emit("({[:30}{:min/%u}/{:cur/%u}/{:max/%u}{]:})\n", 15, 20, 125);
+ xo_emit("({[:-30}{n:min/15}/{n:cur/20}/{n:max/125}{]:})\n");
+ xo_emit("({[:}{:min/%u}/{:cur/%u}/{:max/%u}{]:/%d})\n", 15, 20, 125, -30);
+
+ xo_open_list("flag");
+ xo_emit("{lq:flag/one} {lq:flag/two} {lq:flag/three}\n");
+ xo_close_list("flag");
+
+ xo_emit("{e:empty-tag/}");
+ xo_emit("1:{qt:t1/%*d} 2:{qt:t2/test%-*u} 3:{qt:t3/%10sx} 4:{qt:t4/x%-*.*s}\n",
+ 6, 1000, 8, 5000, "ten-long", 10, 10, "test");
+ xo_emit("{E:this is an error}\n");
+ xo_emit("{E:/%s more error%s}\n", "two", "s" );
+ xo_emit("{W:this is an warning}\n");
+ xo_emit("{W:/%s more warning%s}\n", "two", "s" );
+ xo_emit("{L:/V1\\/V2 packet%s}: {:count/%u}\n", "s", 10);
+
+ int test = 4;
+ xo_emit("{:test/%04d} {L:/tr%s}\n", test, (test == 1) ? "y" : "ies");
+
+ xo_message("improper use of profanity; %s; %s",
+ "ten yard penalty", "first down");
+
+ xo_error("Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n");
+
+ xo_close_container("data");
+
+ xo_close_container_h(NULL, "top");
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/tests/core/test_03.c b/contrib/libxo/tests/core/test_03.c
new file mode 100644
index 0000000..0ab9699
--- /dev/null
+++ b/contrib/libxo/tests/core/test_03.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xo.h"
+
+xo_info_t info[] = {
+ { "employee", "object", "Employee data" },
+ { "first-name", "string", "First name of employee" },
+ { "last-name", "string", "Last name of employee" },
+ { "department", "number", "Department number" },
+};
+int info_count = (sizeof(info) / sizeof(info[0]));
+
+int
+main (int argc, char **argv)
+{
+ struct employee {
+ const char *e_first;
+ const char *e_last;
+ unsigned e_dept;
+ } employees[] = {
+ { "Terry", "Jones", 660 },
+ { "Leslie", "Patterson", 341 },
+ { "Ashley", "Smith", 1440 },
+ { NULL, NULL }
+ }, *ep = employees;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ xo_set_info(NULL, info, info_count);
+
+ xo_open_container("employees");
+ xo_open_list("employee");
+
+ for ( ; ep->e_first; ep++) {
+ xo_open_instance("employee");
+ xo_emit("{:first-name} {:last-name} works in dept #{:department/%u}\n",
+ ep->e_first, ep->e_last, ep->e_dept);
+ xo_close_instance("employee");
+ }
+
+ xo_close_list("employee");
+ xo_close_container("employees");
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/tests/core/test_04.c b/contrib/libxo/tests/core/test_04.c
new file mode 100644
index 0000000..5e25302
--- /dev/null
+++ b/contrib/libxo/tests/core/test_04.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xo.h"
+
+xo_info_t info[] = {
+ { "employee", "object", "Employee data" },
+ { "first-name", "string", "First name of employee" },
+ { "last-name", "string", "Last name of employee" },
+ { "department", "number", "Department number" },
+};
+int info_count = (sizeof(info) / sizeof(info[0]));
+
+int
+main (int argc, char **argv)
+{
+ struct employee {
+ const char *e_first;
+ const char *e_last;
+ unsigned e_dept;
+ } employees[] = {
+ { "Terry", "Jones", 660 },
+ { "Leslie", "Patterson", 341 },
+ { "Ashley", "Smith", 1440 },
+ { NULL, NULL }
+ }, *ep = employees;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ xo_set_info(NULL, info, info_count);
+
+ xo_open_container("employees");
+ xo_open_list("employee");
+
+ xo_emit("{T:Last Name/%-12s}{T:First Name/%-14s}{T:Department/%s}\n");
+ for ( ; ep->e_first; ep++) {
+ xo_open_instance("employee");
+ xo_emit("{:first-name/%-12s/%s}{:last-name/%-14s/%s}"
+ "{:department/%8u/%u}\n",
+ ep->e_first, ep->e_last, ep->e_dept);
+ xo_close_instance("employee");
+ }
+
+ xo_close_list("employee");
+ xo_close_container("employees");
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/tests/core/test_05.c b/contrib/libxo/tests/core/test_05.c
new file mode 100644
index 0000000..61241b8
--- /dev/null
+++ b/contrib/libxo/tests/core/test_05.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xo.h"
+
+xo_info_t info[] = {
+ { "employee", "object", "Employee data" },
+ { "first-name", "string", "First name of employee" },
+ { "last-name", "string", "Last name of employee" },
+ { "department", "number", "Department number" },
+ { "percent-time", "number", "Percentage of full & part time (%)" },
+};
+int info_count = (sizeof(info) / sizeof(info[0]));
+
+int
+main (int argc, char **argv)
+{
+ struct employee {
+ const char *e_first;
+ const char *e_nic;
+ const char *e_last;
+ unsigned e_dept;
+ unsigned e_percent;
+ } employees[] = {
+ { "Jim", "რეგტ", "გთხოვთ ახ", 431, 90 },
+ { "Terry", "<one", "Οὐχὶ ταὐτὰ παρίσταταί μοι Jones", 660, 90 },
+ { "Leslie", "Les", "Patterson", 341,60 },
+ { "Ashley", "Ash", "Meter & Smith", 1440, 40 },
+ { "0123456789", "0123456789", "012345678901234567890", 1440, 40 },
+ { "ახლა", "გაიარო", "საერთაშორისო", 123, 90 },
+ { NULL, NULL }
+ }, *ep = employees;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ xo_set_info(NULL, info, info_count);
+
+ xo_open_container("employees");
+
+ xo_emit("Οὐχὶ ταὐτὰ παρίσταταί μοι {:v1/%s}, {:v2/%s}\n",
+ "γιγνώσκειν", "ὦ ἄνδρες ᾿Αθηναῖοι");
+
+ xo_emit("გთხოვთ {:v1/%s} {:v2/%s}\n",
+ "ახლავე გაიაროთ რეგისტრაცია",
+ "Unicode-ის მეათე საერთაშორისო");
+
+ xo_open_list("employee");
+
+ xo_emit("{T:First Name/%-25s}{T:Last Name/%-14s}"
+ "{T:/%-12s}{T:Time (%)}\n", "Department");
+ for ( ; ep->e_first; ep++) {
+ xo_open_instance("employee");
+ xo_emit("{[:-25}{:first-name/%s} ({:nic-name/\"%s\"}){]:}"
+ "{:last-name/%-14..14s/%s}"
+ "{:department/%8u/%u}{:percent-time/%8u/%u}\n",
+ ep->e_first, ep->e_nic, ep->e_last, ep->e_dept, ep->e_percent);
+ if (ep->e_percent > 50) {
+ xo_attr("full-time", "%s", "honest & for true");
+ xo_emit("{e:benefits/%s}", "full");
+ }
+ xo_close_instance("employee");
+ }
+
+ xo_close_list("employee");
+ xo_close_container("employees");
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/tests/core/test_06.c b/contrib/libxo/tests/core/test_06.c
new file mode 100644
index 0000000..82baab8
--- /dev/null
+++ b/contrib/libxo/tests/core/test_06.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xo.h"
+
+xo_info_t info[] = {
+ { "employee", "object", "Employee data" },
+ { "first-name", "string", "First name of employee" },
+ { "last-name", "string", "Last name of employee" },
+ { "department", "number", "Department number" },
+};
+int info_count = (sizeof(info) / sizeof(info[0]));
+
+int
+main (int argc, char **argv)
+{
+ struct employee {
+ const char *e_first;
+ const char *e_last;
+ unsigned e_dept;
+ } employees[] = {
+ { "Terry", "Jones", 660 },
+ { "Leslie", "Patterson", 341 },
+ { "Ashley", "Smith", 1440 },
+ { NULL, NULL }
+ }, *ep = employees;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ xo_set_info(NULL, info, info_count);
+
+ xo_set_flags(NULL, XOF_DTRT);
+
+ xo_open_container("employees");
+ xo_open_list("employee");
+
+ for ( ; ep->e_first; ep++) {
+ xo_open_instance("employee");
+ xo_emit("{:first-name} {:last-name} works in dept #{:department/%u}\n",
+ ep->e_first, ep->e_last, ep->e_dept);
+ xo_close_instance_d();
+ }
+
+ xo_close_list_d();
+ xo_close_container_d();
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/tests/core/test_07.c b/contrib/libxo/tests/core/test_07.c
new file mode 100644
index 0000000..3ceba8e
--- /dev/null
+++ b/contrib/libxo/tests/core/test_07.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xo.h"
+
+xo_info_t info[] = {
+ { "employee", "object", "Employee data" },
+ { "first-name", "string", "First name of employee" },
+ { "last-name", "string", "Last name of employee" },
+ { "department", "number", "Department number" },
+ { "percent-time", "number", "Percentage of full & part time (%)" },
+};
+int info_count = (sizeof(info) / sizeof(info[0]));
+
+int
+main (int argc, char **argv)
+{
+ struct employee {
+ const char *e_first;
+ const char *e_nic;
+ const char *e_last;
+ unsigned e_dept;
+ unsigned e_percent;
+ } employees[] = {
+ { "Jim", "რეგტ", "გთხოვთ ახ", 431, 90 },
+ { "Terry", "<one", "Οὐχὶ ταὐτὰ παρίσταταί μοι Jones", 660, 90 },
+ { "Leslie", "Les", "Patterson", 341,60 },
+ { "Ashley", "Ash", "Meter & Smith", 1440, 40 },
+ { "0123456789", "0123456789", "012345678901234567890", 1440, 40 },
+ { "ახლა", "გაიარო", "საერთაშორისო", 123, 90 },
+ { NULL, NULL }
+ }, *ep = employees;
+ int rc;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ xo_set_info(NULL, info, info_count);
+ xo_set_flags(NULL, XOF_COLUMNS);
+
+ xo_open_container("employees");
+
+ rc = xo_emit("Οὐχὶ ταὐτὰ παρίσταταί μοι {:v1/%s}, {:v2/%s}\n",
+ "γιγνώσκειν", "ὦ ἄνδρες ᾿Αθηναῖοι");
+ rc = xo_emit("{:columns/%d}\n", rc);
+ xo_emit("{:columns/%d}\n", rc);
+
+ rc = xo_emit("გთხოვთ {:v1/%s} {:v2/%s}\n",
+ "ახლავე გაიაროთ რეგისტრაცია",
+ "Unicode-ის მეათე საერთაშორისო");
+ xo_emit("{:columns/%d}\n", rc);
+
+ xo_open_list("employee");
+
+ rc = xo_emit("{T:First Name/%-25s}{T:Last Name/%-14s}"
+ "{T:/%-12s}{T:Time (%)}\n", "Department");
+ xo_emit("{:columns/%d}\n", rc);
+ for ( ; ep->e_first; ep++) {
+ xo_open_instance("employee");
+ rc = xo_emit("{[:-25}{:first-name/%s} ({:nic-name/\"%s\"}){]:}"
+ "{:last-name/%-14..14s/%s}"
+ "{:department/%8u/%u}{:percent-time/%8u/%u}\n",
+ ep->e_first, ep->e_nic, ep->e_last, ep->e_dept, ep->e_percent);
+ xo_emit("{:columns/%d}\n", rc);
+ if (ep->e_percent > 50) {
+ xo_attr("full-time", "%s", "honest & for true");
+ xo_emit("{e:benefits/%s}", "full");
+ }
+ xo_close_instance("employee");
+ }
+
+ xo_close_list("employee");
+ xo_close_container("employees");
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/tests/xo/Makefile.am b/contrib/libxo/tests/xo/Makefile.am
new file mode 100644
index 0000000..1687f09
--- /dev/null
+++ b/contrib/libxo/tests/xo/Makefile.am
@@ -0,0 +1,90 @@
+#
+# $Id$
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+AM_CFLAGS = -I${top_srcdir} -I${top_srcdir}/libxo
+
+# Ick: maintained by hand!
+TEST_CASES = \
+xo_01.sh
+
+X=\
+xo_02.sh \
+xo_03.sh \
+xo_04.sh \
+xo_05.sh \
+xo_06.sh
+
+# TEST_CASES := $(shell cd ${srcdir} ; echo *.c )
+
+EXTRA_DIST = \
+ ${TEST_CASES} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.T.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.T.out}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.XP.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.XP.out}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.JP.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.JP.out}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.HP.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.HP.out}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.X.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.X.out}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.J.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.J.out}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.H.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.H.out}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.HIPx.err}} \
+ ${addprefix saved/, ${TEST_CASES:.sh=.HIPx.out}}
+
+S2O = | ${SED} '1,/@@/d'
+
+all:
+
+#TEST_TRACE = set -x ;
+
+XO=../../xo/xo
+
+TEST_ONE = \
+ LIBXO_OPTIONS=:W$$fmt \
+ ${CHECKER} sh ${srcdir}/$$base.sh ${XO} ${TEST_OPTS} \
+ > out/$$base.$$fmt.out 2> out/$$base.$$fmt.err ; \
+ ${DIFF} -Nu ${srcdir}/saved/$$base.$$fmt.out out/$$base.$$fmt.out ${S2O} ; \
+ ${DIFF} -Nu ${srcdir}/saved/$$base.$$fmt.err out/$$base.$$fmt.err ${S2O}
+
+TEST_FORMATS = T XP JP HP X J H HIPx
+
+test tests: ${bin_PROGRAMS}
+ @${MKDIR} -p out
+ -@ ${TEST_TRACE} (for test in ${TEST_CASES} ; do \
+ base=`${BASENAME} $$test .sh` ; \
+ (for fmt in ${TEST_FORMATS}; do \
+ echo "... $$test ... $$fmt ..."; \
+ ${TEST_ONE}; \
+ true; \
+ done) \
+ done)
+
+one:
+ -@(test=${TEST_CASE}; data=${TEST_DATA}; ${TEST_ONE} ; true)
+
+accept:
+ -@(for test in ${TEST_CASES} ; do \
+ base=`${BASENAME} $$test .sh` ; \
+ (for fmt in ${TEST_FORMATS}; do \
+ echo "... $$test ... $$fmt ..."; \
+ ${CP} out/$$base.$$fmt.out ${srcdir}/saved/$$base.$$fmt.out ; \
+ ${CP} out/$$base.$$fmt.err ${srcdir}/saved/$$base.$$fmt.err ; \
+ done) \
+ done)
+
+CLEANFILES =
+CLEANDIRS = out
+
+clean-local:
+ rm -rf ${CLEANDIRS}
diff --git a/contrib/libxo/tests/xo/saved/xo_01.H.err b/contrib/libxo/tests/xo/saved/xo_01.H.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.H.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.H.out b/contrib/libxo/tests/xo/saved/xo_01.H.out
new file mode 100644
index 0000000..dd82a1c
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.H.out
@@ -0,0 +1 @@
+<div class="line"><div class="text">Item </div><div class="data" data-tag="name">one</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">001</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">red</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">two</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">002</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">blue</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">three</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">003</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">green</div></div><div class="line"><div class="text">Item </div><div class="data" data-tag="name">four</div><div class="text"> is </div><div class="label">number</div><div class="padding"> </div><div class="data" data-tag="value">004</div><div class="text">, </div><div class="label">color</div><div class="decoration">:</div><div class="padding"> </div><div class="data" data-tag="color">yellow</div></div> \ No newline at end of file
diff --git a/contrib/libxo/tests/xo/saved/xo_01.HIPx.err b/contrib/libxo/tests/xo/saved/xo_01.HIPx.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.HIPx.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.HIPx.out b/contrib/libxo/tests/xo/saved/xo_01.HIPx.out
new file mode 100644
index 0000000..12e36b1
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.HIPx.out
@@ -0,0 +1,52 @@
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name" data-xpath="/top/item/name">one</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value" data-xpath="/top/item[name = 'one']/value">001</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color" data-xpath="/top/item[name = 'one']/color">red</div>
+</div>
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name" data-xpath="/top/item/name">two</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value" data-xpath="/top/item[name = 'two']/value">002</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color" data-xpath="/top/item[name = 'two']/color">blue</div>
+</div>
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name" data-xpath="/top/item/name">three</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value" data-xpath="/top/item[name = 'three']/value">003</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color" data-xpath="/top/item[name = 'three']/color">green</div>
+</div>
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name" data-xpath="/top/item/name">four</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value" data-xpath="/top/item[name = 'four']/value">004</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color" data-xpath="/top/item[name = 'four']/color">yellow</div>
+</div>
diff --git a/contrib/libxo/tests/xo/saved/xo_01.HP.err b/contrib/libxo/tests/xo/saved/xo_01.HP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.HP.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.HP.out b/contrib/libxo/tests/xo/saved/xo_01.HP.out
new file mode 100644
index 0000000..de91936
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.HP.out
@@ -0,0 +1,52 @@
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name">one</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value">001</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color">red</div>
+</div>
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name">two</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value">002</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color">blue</div>
+</div>
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name">three</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value">003</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color">green</div>
+</div>
+<div class="line">
+ <div class="text">Item </div>
+ <div class="data" data-tag="name">four</div>
+ <div class="text"> is </div>
+ <div class="label">number</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="value">004</div>
+ <div class="text">, </div>
+ <div class="label">color</div>
+ <div class="decoration">:</div>
+ <div class="padding"> </div>
+ <div class="data" data-tag="color">yellow</div>
+</div>
diff --git a/contrib/libxo/tests/xo/saved/xo_01.J.err b/contrib/libxo/tests/xo/saved/xo_01.J.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.J.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.J.out b/contrib/libxo/tests/xo/saved/xo_01.J.out
new file mode 100644
index 0000000..86ce4ef
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.J.out
@@ -0,0 +1 @@
+"top": {"item": {"name":"one","value":1,"color":"red"}, "item": {"name":"two","value":2,"color":"blue"}, "item": {"name":"three","value":3,"color":"green"}, "item": {"name":"four","value":4,"color":"yellow"}}
diff --git a/contrib/libxo/tests/xo/saved/xo_01.JP.err b/contrib/libxo/tests/xo/saved/xo_01.JP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.JP.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.JP.out b/contrib/libxo/tests/xo/saved/xo_01.JP.out
new file mode 100644
index 0000000..5a25b17
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.JP.out
@@ -0,0 +1,22 @@
+"top": {
+ "item": {
+ "name": "one",
+ "value": 1,
+ "color": "red"
+ },
+ "item": {
+ "name": "two",
+ "value": 2,
+ "color": "blue"
+ },
+ "item": {
+ "name": "three",
+ "value": 3,
+ "color": "green"
+ },
+ "item": {
+ "name": "four",
+ "value": 4,
+ "color": "yellow"
+ }
+}
diff --git a/contrib/libxo/tests/xo/saved/xo_01.T.err b/contrib/libxo/tests/xo/saved/xo_01.T.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.T.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.T.out b/contrib/libxo/tests/xo/saved/xo_01.T.out
new file mode 100644
index 0000000..ed2ea35
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.T.out
@@ -0,0 +1,4 @@
+Item one is number 001, color: red
+Item two is number 002, color: blue
+Item three is number 003, color: green
+Item four is number 004, color: yellow
diff --git a/contrib/libxo/tests/xo/saved/xo_01.X.err b/contrib/libxo/tests/xo/saved/xo_01.X.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.X.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.X.out b/contrib/libxo/tests/xo/saved/xo_01.X.out
new file mode 100644
index 0000000..7539566
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.X.out
@@ -0,0 +1 @@
+<top><item><name>one</name><value>1</value><color>red</color></item><item><name>two</name><value>2</value><color>blue</color></item><item><name>three</name><value>3</value><color>green</color></item><item><name>four</name><value>4</value><color>yellow</color></item></top> \ No newline at end of file
diff --git a/contrib/libxo/tests/xo/saved/xo_01.XP.err b/contrib/libxo/tests/xo/saved/xo_01.XP.err
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.XP.err
diff --git a/contrib/libxo/tests/xo/saved/xo_01.XP.out b/contrib/libxo/tests/xo/saved/xo_01.XP.out
new file mode 100644
index 0000000..7f069c8
--- /dev/null
+++ b/contrib/libxo/tests/xo/saved/xo_01.XP.out
@@ -0,0 +1,22 @@
+<top>
+ <item>
+ <name>one</name>
+ <value>1</value>
+ <color>red</color>
+ </item>
+ <item>
+ <name>two</name>
+ <value>2</value>
+ <color>blue</color>
+ </item>
+ <item>
+ <name>three</name>
+ <value>3</value>
+ <color>green</color>
+ </item>
+ <item>
+ <name>four</name>
+ <value>4</value>
+ <color>yellow</color>
+ </item>
+</top>
diff --git a/contrib/libxo/tests/xo/xo_01.sh b/contrib/libxo/tests/xo/xo_01.sh
new file mode 100755
index 0000000..8de9410
--- /dev/null
+++ b/contrib/libxo/tests/xo/xo_01.sh
@@ -0,0 +1,27 @@
+#
+# $Id$
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+XO=$1
+shift
+
+XOP="${XO} --warn --depth 1 --leading-xpath /top"
+
+${XO} --open top
+
+NF=
+for i in one:1:red two:2:blue three:3:green four:4:yellow ; do
+ set `echo $i | sed 's/:/ /g'`
+ ${XOP} ${NF} --wrap item \
+ 'Item {k:name} is {Lw:number}{:value/%03d/%d}, {Lwc:color}{:color}\n' \
+ $1 $2 $3
+ NF=--not-first
+done
+
+${XO} --close top \ No newline at end of file
diff --git a/contrib/libxo/warnings.mk b/contrib/libxo/warnings.mk
new file mode 100644
index 0000000..c07ac37
--- /dev/null
+++ b/contrib/libxo/warnings.mk
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# Copyright 2011, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+#
+# Commonly used sets of warnings
+#
+
+MIN_WARNINGS?= -W -Wall
+
+LOW_WARNINGS?= ${MIN_WARNINGS} \
+ -Wstrict-prototypes \
+ -Wmissing-prototypes \
+ -Wpointer-arith
+
+MEDIUM_WARNINGS?= ${LOW_WARNINGS} -Werror
+
+HIGH_WARNINGS?= ${MEDIUM_WARNINGS} \
+ -Waggregate-return \
+ -Wcast-align \
+ -Wcast-qual \
+ -Wchar-subscripts \
+ -Wcomment \
+ -Wformat \
+ -Wimplicit \
+ -Wmissing-declarations \
+ -Wnested-externs \
+ -Wparentheses \
+ -Wreturn-type \
+ -Wshadow \
+ -Wswitch \
+ -Wtrigraphs \
+ -Wuninitialized \
+ -Wunused \
+ -Wwrite-strings
+
+HIGHER_WARNINGS?= ${HIGH_WARNINGS} \
+ -Winline \
+ -Wbad-function-cast \
+ -Wpacked \
+ -Wpadded \
+ -Wstrict-aliasing
+
+ifeq "${LIBXO_WARNINGS}" "HIGH"
+WARNINGS += ${HIGH_WARNINGS}
+else
+WARNINGS += ${LOW_WARNINGS}
+endif
+
+ifeq "${GCC_WARNINGS}" "yes"
+WARNINGS += -fno-inline-functions-called-once
+endif
diff --git a/contrib/libxo/xo/Makefile.am b/contrib/libxo/xo/Makefile.am
new file mode 100644
index 0000000..247ef3b
--- /dev/null
+++ b/contrib/libxo/xo/Makefile.am
@@ -0,0 +1,35 @@
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+if LIBXO_WARNINGS_HIGH
+LIBXO_WARNINGS = HIGH
+endif
+include ${top_srcdir}/warnings.mk
+
+AM_CFLAGS = \
+ -DLIBXO_XMLSOFT_NEED_PRIVATE \
+ -I${top_builddir} \
+ -I${top_srcdir} \
+ -I${top_srcdir}/libxo \
+ ${WARNINGS}
+
+LIBS = \
+ ${LIBXO_LIBS}
+
+bin_PROGRAMS = xo
+
+xo_SOURCES = xo.c
+#xo_LDADD = ../libxo/libxo.la
+#xo_LDFLAGS = -static
+
+LDADD = \
+ ${top_builddir}/libxo/libxo.la
+
+man_MANS = xo.1
+
+EXTRA_DIST = xo.1
diff --git a/contrib/libxo/xo/xo.1 b/contrib/libxo/xo/xo.1
new file mode 100644
index 0000000..1833b0a
--- /dev/null
+++ b/contrib/libxo/xo/xo.1
@@ -0,0 +1,190 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xo
+.Nd emit formatted output based on format string and arguments
+.Sh SYNOPSIS
+.Nm xo
+.Op Fl options
+.Op Ar argument...
+.Sh DESCRIPTION
+The
+.Nm xo
+utility allows command line access to the functionality of
+the
+.Em libxo
+library. Using
+.Nm xo ,
+shell scripts can emit
+.Em XML ,
+.Em JSON , or
+.Em HTML
+using the same commands that emit text output.
+.Pp
+.Bl -tag -width "12345678901234567"
+.It Fl "-close <path>"
+Close tags for the given path
+.It Fl "-depth <num>"
+Set the depth for pretty printing
+.It Fl "-help"
+Display this help text
+.It Fl "-html OR -H"
+Generate HTML output
+.It Fl "-json OR -J"
+Generate JSON output
+.It Fl "-leading-xpath <path>"
+Add a prefix to generated XPaths (HTML)
+.It Fl "-open <path>"
+Open tags for the given path
+.It Fl "-pretty OR -p"
+Make 'pretty' output (add indent, newlines)
+.It Fl "-style <style>"
+Generate given style (xml, json, text, html)
+.It Fl "-text OR -T"
+Generate text output (the default style)
+.It Fl "-version"
+Display version information
+.It Fl "-warn OR -W"
+Display warnings in text on stderr
+.It Fl "-warn-xml"
+Display warnings in xml on stdout
+.It Fl "-wrap <path>"
+Wrap output in a set of containers
+.It Fl "-xml OR -X"
+Generate XML output
+.It Fl "-xpath"
+Add XPath data to HTML output);
+.El
+.Pp
+The
+.Nm xo
+utility accepts a format string suitable for
+.Xr xo_emit 3
+and a set of zero or more arguments used to supply data for that string.
+.Bd -literal -offset indent
+ xo "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
+
+ TEXT:
+ The fish weighs 6 pounds.
+ XML:
+ <name>fish</name>
+ <weight>6</weight>
+ JSON:
+ "name": "fish",
+ "weight": 6
+ HTML:
+ <div class="line">
+ <div class="text">The </div>
+ <div class="data" data-tag="name">fish</div>
+ <div class="text"> weighs </div>
+ <div class="data" data-tag="weight">6</div>
+ <div class="text"> pounds.</div>
+ </div>
+.Ed
+.Pp
+The
+.Fl "-wrap <path>"
+option can be used to wrap emitted content in a
+specific hierarchy. The path is a set of hierarchical names separated
+by the '/' character.
+.Bd -literal -offset indent
+ xo --wrap top/a/b/c '{:tag}' value
+
+ XML:
+ <top>
+ <a>
+ <b>
+ <c>
+ <tag>value</tag>
+ </c>
+ </b>
+ </a>
+ </top>
+ JSON:
+ "top": {
+ "a": {
+ "b": {
+ "c": {
+ "tag": "value"
+ }
+ }
+ }
+ }
+.Ed
+.Pp
+The
+.Fl "\-open <path>"
+and
+.Fl "\-close <path>"
+can be used to emit
+hierarchical information without the matching close and open
+tag. This allows a shell script to emit open tags, data, and
+then close tags. The
+.Fl \-depth
+option may be used to set the
+depth for indentation. The
+.Fl "\-leading-xpath"
+may be used to
+prepend data to the XPath values used for HTML output style.
+.Bd -literal -offset indent
+ #!/bin/sh
+ xo --open top/data
+ xo --depth 2 '{tag}' value
+ xo --close top/data
+ XML:
+ <top>
+ <data>
+ <tag>value</tag>
+ </data>
+ </top>
+ JSON:
+ "top": {
+ "data": {
+ "tag": "value"
+ }
+ }
+.Ed
+.Pp
+.Sh EXAMPLE
+.Bd -literal -offset indent
+ % xo 'The {:product} is {:status}\n' stereo "in route"
+ The stereo is in route
+ % xo -p -X 'The {:product} is {:status}\n' stereo "in route"
+ <product>stereo</product>
+ <status>in route</status>
+.Ed
+.Pp
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 11.0.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/xo/xo.c b/contrib/libxo/xo/xo.c
new file mode 100644
index 0000000..698d9d6
--- /dev/null
+++ b/contrib/libxo/xo/xo.c
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2014, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2014
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "xoconfig.h"
+#include "xo.h"
+#include "xoversion.h"
+
+#include <getopt.h> /* Include after xo.h for testing */
+
+#ifndef UNUSED
+#define UNUSED __attribute__ ((__unused__))
+#endif /* UNUSED */
+
+static int opt_warn; /* Enable warnings */
+
+static char **save_argv;
+static char **checkpoint_argv;
+
+static char *
+next_arg (void)
+{
+ char *cp = *save_argv;
+
+ if (cp == NULL)
+ xo_errx(1, "missing argument");
+
+ save_argv += 1;
+ return cp;
+}
+
+static void
+prep_arg (char *fmt)
+{
+ char *cp, *fp;
+
+ for (cp = fp = fmt; *cp; cp++, fp++) {
+ if (*cp != '\\') {
+ if (cp != fp)
+ *fp = *cp;
+ continue;
+ }
+
+ switch (*++cp) {
+ case 'n':
+ *fp = '\n';
+ break;
+
+ case 'r':
+ *fp = '\r';
+ break;
+
+ case 'b':
+ *fp = '\b';
+ break;
+
+ case 'e':
+ *fp = '\e';
+ break;
+
+ default:
+ *fp = *cp;
+ }
+ }
+
+ *fp = '\0';
+}
+
+static void
+checkpoint (xo_handle_t *xop UNUSED, va_list vap UNUSED, int restore)
+{
+ if (restore)
+ save_argv = checkpoint_argv;
+ else
+ checkpoint_argv = save_argv;
+}
+
+/*
+ * Our custom formatter is responsible for combining format string pieces
+ * with our command line arguments to build strings. This involves faking
+ * some printf-style logic.
+ */
+static int
+formatter (xo_handle_t *xop, char *buf, int bufsiz,
+ const char *fmt, va_list vap UNUSED)
+{
+ int lflag = 0, hflag = 0, jflag = 0, tflag = 0,
+ zflag = 0, qflag = 0, star1 = 0, star2 = 0;
+ int rc = 0;
+ int w1 = 0, w2 = 0;
+ const char *cp;
+
+ for (cp = fmt + 1; *cp; cp++) {
+ if (*cp == 'l')
+ lflag += 1;
+ else if (*cp == 'h')
+ hflag += 1;
+ else if (*cp == 'j')
+ jflag += 1;
+ else if (*cp == 't')
+ tflag += 1;
+ else if (*cp == 'z')
+ zflag += 1;
+ else if (*cp == 'q')
+ qflag += 1;
+ else if (*cp == '*') {
+ if (star1 == 0)
+ star1 = 1;
+ else
+ star2 = 1;
+ } else if (strchr("diouxXDOUeEfFgGaAcCsSp", *cp) != NULL)
+ break;
+ else if (*cp == 'n' || *cp == 'v') {
+ if (opt_warn)
+ xo_error_h(xop, "unsupported format: '%s'", fmt);
+ return -1;
+ }
+ }
+
+ char fc = *cp;
+
+ /* Handle "%*.*s" */
+ if (star1)
+ w1 = strtol(next_arg(), NULL, 0);
+ if (star2 > 1)
+ w2 = strtol(next_arg(), NULL, 0);
+
+ if (fc == 'D' || fc == 'O' || fc == 'U')
+ lflag = 1;
+
+ if (strchr("diD", fc) != NULL) {
+ long long value = strtoll(next_arg(), NULL, 0);
+ if (star1 && star2)
+ rc = snprintf(buf, bufsiz, fmt, w1, w2, value);
+ else if (star1)
+ rc = snprintf(buf, bufsiz, fmt, w1, value);
+ else
+ rc = snprintf(buf, bufsiz, fmt, value);
+
+ } else if (strchr("ouxXOUp", fc) != NULL) {
+ unsigned long long value = strtoull(next_arg(), NULL, 0);
+ if (star1 && star2)
+ rc = snprintf(buf, bufsiz, fmt, w1, w2, value);
+ else if (star1)
+ rc = snprintf(buf, bufsiz, fmt, w1, value);
+ else
+ rc = snprintf(buf, bufsiz, fmt, value);
+
+ } else if (strchr("eEfFgGaA", fc) != NULL) {
+ double value = strtold(next_arg(), NULL);
+ if (star1 && star2)
+ rc = snprintf(buf, bufsiz, fmt, w1, w2, value);
+ else if (star1)
+ rc = snprintf(buf, bufsiz, fmt, w1, value);
+ else
+ rc = snprintf(buf, bufsiz, fmt, value);
+
+ } else if (fc == 'C' || fc == 'c' || fc == 'S' || fc == 's') {
+ char *value = next_arg();
+ if (star1 && star2)
+ rc = snprintf(buf, bufsiz, fmt, w1, w2, value);
+ else if (star1)
+ rc = snprintf(buf, bufsiz, fmt, w1, value);
+ else
+ rc = snprintf(buf, bufsiz, fmt, value);
+ }
+
+ return rc;
+}
+
+static void
+print_version (void)
+{
+ fprintf(stderr, "libxo version %s%s\n",
+ xo_version, xo_version_extra);
+ fprintf(stderr, "xo version %s%s\n",
+ LIBXO_VERSION, LIBXO_VERSION_EXTRA);
+}
+
+static void
+print_help (void)
+{
+ fprintf(stderr,
+"Usage: xo [options] format [fields]\n"
+" --close <path> Close tags for the given path\n"
+" --depth <num> Set the depth for pretty printing\n"
+" --help Display this help text\n"
+" --html OR -H Generate HTML output\n"
+" --json OR -J Generate JSON output\n"
+" --leading-xpath <path> OR -l <path> "
+ "Add a prefix to generated XPaths (HTML)\n"
+" --open <path> Open tags for the given path\n"
+" --pretty OR -p Make 'pretty' output (add indent, newlines)\n"
+" --style <style> OR -s <style> "
+ "Generate given style (xml, json, text, html)\n"
+" --text OR -T Generate text output (the default style)\n"
+" --version Display version information\n"
+" --warn OR -W Display warnings in text on stderr\n"
+" --warn-xml Display warnings in xml on stdout\n"
+" --wrap <path> Wrap output in a set of containers\n"
+" --xml OR -X Generate XML output\n"
+" --xpath Add XPath data to HTML output\n");
+}
+
+static struct opts {
+ int o_depth;
+ int o_help;
+ int o_not_first;
+ int o_xpath;
+ int o_version;
+ int o_warn_xml;
+ int o_wrap;
+} opts;
+
+static struct option long_opts[] = {
+ { "close", required_argument, NULL, 'c' },
+ { "depth", required_argument, &opts.o_depth, 1 },
+ { "help", no_argument, &opts.o_help, 1 },
+ { "html", no_argument, NULL, 'H' },
+ { "json", no_argument, NULL, 'J' },
+ { "leading-xpath", required_argument, NULL, 'l' },
+ { "not-first", no_argument, &opts.o_not_first, 1 },
+ { "open", required_argument, NULL, 'o' },
+ { "option", required_argument, NULL, 'O' },
+ { "pretty", no_argument, NULL, 'p' },
+ { "style", required_argument, NULL, 's' },
+ { "text", no_argument, NULL, 'T' },
+ { "xml", no_argument, NULL, 'X' },
+ { "xpath", no_argument, &opts.o_xpath, 1 },
+ { "version", no_argument, &opts.o_version, 1 },
+ { "warn", no_argument, NULL, 'W' },
+ { "warn-xml", no_argument, &opts.o_warn_xml, 1 },
+ { "wrap", required_argument, &opts.o_wrap, 1 },
+ { NULL, 0, NULL, 0 }
+};
+
+int
+main (int argc UNUSED, char **argv)
+{
+ char *fmt = NULL, *cp, *np;
+ char *opt_opener = NULL, *opt_closer = NULL, *opt_wrapper = NULL;
+ char *opt_options = NULL;
+ int opt_depth = 0;
+ int opt_not_first = 0;
+ int rc;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ while ((rc = getopt_long(argc, argv, "c:HJl:ps:TXW",
+ long_opts, NULL)) != -1) {
+ switch (rc) {
+ case 'c':
+ opt_closer = optarg;
+ xo_set_flags(NULL, XOF_IGNORE_CLOSE);
+ break;
+
+ case 'H':
+ xo_set_style(NULL, XO_STYLE_HTML);
+ break;
+
+ case 'J':
+ xo_set_style(NULL, XO_STYLE_JSON);
+ break;
+
+ case 'l':
+ xo_set_leading_xpath(NULL, optarg);
+ break;
+
+ case 'O':
+ opt_options = optarg;
+ break;
+
+ case 'o':
+ opt_opener = optarg;
+ break;
+
+ case 'p':
+ xo_set_flags(NULL, XOF_PRETTY);
+ break;
+
+ case 's':
+ if (xo_set_style_name(NULL, optarg) < 0)
+ xo_errx(1, "unknown style: %s", optarg);
+ break;
+
+ case 'T':
+ xo_set_style(NULL, XO_STYLE_TEXT);
+ break;
+
+ case 'X':
+ xo_set_style(NULL, XO_STYLE_XML);
+ break;
+
+ case 'W':
+ opt_warn = 1;
+ xo_set_flags(NULL, XOF_WARN);
+ break;
+
+ case ':':
+ xo_errx(1, "missing argument");
+ break;
+
+ case 0:
+ if (opts.o_depth) {
+ opt_depth = atoi(optarg);
+
+ } else if (opts.o_help) {
+ print_help();
+ return 1;
+
+ } else if (opts.o_not_first) {
+ opt_not_first = 1;
+
+ } else if (opts.o_xpath) {
+ xo_set_flags(NULL, XOF_XPATH);
+
+ } else if (opts.o_version) {
+ print_version();
+ return 0;
+
+ } else if (opts.o_warn_xml) {
+ opt_warn = 1;
+ xo_set_flags(NULL, XOF_WARN | XOF_WARN_XML);
+
+ } else if (opts.o_wrap) {
+ opt_wrapper = optarg;
+
+ } else {
+ print_help();
+ return 1;
+ }
+
+ bzero(&opts, sizeof(opts)); /* Reset all the options */
+ break;
+
+ default:
+ print_help();
+ return 1;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (opt_options) {
+ rc = xo_set_options(NULL, opt_options);
+ if (rc < 0)
+ xo_errx(1, "invalid options: %s", opt_options);
+ }
+
+ xo_set_formatter(NULL, formatter, checkpoint);
+ xo_set_flags(NULL, XOF_NO_VA_ARG);
+ xo_set_flags(NULL, XOF_NO_TOP);
+
+ fmt = *argv++;
+ if (opt_opener == NULL && opt_closer == NULL && fmt == NULL) {
+ print_help();
+ return 1;
+ }
+
+ if (opt_not_first)
+ xo_set_flags(NULL, XOF_NOT_FIRST);
+
+ if (opt_closer) {
+ opt_depth += 1;
+ for (cp = opt_closer; cp && *cp; cp = np) {
+ np = strchr(cp, '/');
+ if (np == NULL)
+ break;
+ np += 1;
+ opt_depth += 1;
+ }
+ }
+
+ if (opt_depth > 0)
+ xo_set_depth(NULL, opt_depth);
+
+ if (opt_opener) {
+ for (cp = opt_opener; cp && *cp; cp = np) {
+ np = strchr(cp, '/');
+ if (np)
+ *np = '\0';
+ xo_open_container(cp);
+ if (np)
+ *np++ = '/';
+ }
+ }
+
+ if (opt_wrapper) {
+ for (cp = opt_wrapper; cp && *cp; cp = np) {
+ np = strchr(cp, '/');
+ if (np)
+ *np = '\0';
+ xo_open_container(cp);
+ if (np)
+ *np++ = '/';
+ }
+ }
+
+ if (fmt && *fmt) {
+ save_argv = argv;
+ prep_arg(fmt);
+ xo_emit(fmt);
+ }
+
+ while (opt_wrapper) {
+ np = strrchr(opt_wrapper, '/');
+ xo_close_container(np ? np + 1 : opt_wrapper);
+ if (np)
+ *np = '\0';
+ else
+ opt_wrapper = NULL;
+ }
+
+ while (opt_closer) {
+ np = strrchr(opt_closer, '/');
+ xo_close_container(np ? np + 1 : opt_closer);
+ if (np)
+ *np = '\0';
+ else
+ opt_closer = NULL;
+ }
+
+ xo_finish();
+
+ return 0;
+}
diff --git a/contrib/libxo/xohtml/external/jquery.js b/contrib/libxo/xohtml/external/jquery.js
new file mode 100644
index 0000000..eda55db
--- /dev/null
+++ b/contrib/libxo/xohtml/external/jquery.js
@@ -0,0 +1,9300 @@
+/*!
+ * jQuery JavaScript Library v1.7
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Nov 3 16:18:21 2011 -0400
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+ navigator = window.navigator,
+ location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // A simple way to check for HTML strings or ID strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+ // Check if a string has a non-whitespace character in it
+ rnotwhite = /\S/,
+
+ // Used for trimming whitespace
+ trimLeft = /^\s+/,
+ trimRight = /\s+$/,
+
+ // Check for digits
+ rdigit = /\d/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+ // JSON RegExp
+ rvalidchars = /^[\],:{}\s]*$/,
+ rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+ // Useragent RegExp
+ rwebkit = /(webkit)[ \/]([\w.]+)/,
+ ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+ rmsie = /(msie) ([\w.]+)/,
+ rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+ // Matches dashed string for camelizing
+ rdashAlpha = /-([a-z]|[0-9])/ig,
+ rmsPrefix = /^-ms-/,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return ( letter + "" ).toUpperCase();
+ },
+
+ // Keep a UserAgent string for use with jQuery.browser
+ userAgent = navigator.userAgent,
+
+ // For matching the engine and version of the browser
+ browserMatch,
+
+ // The deferred used on DOM ready
+ readyList,
+
+ // The ready event handler
+ DOMContentLoaded,
+
+ // Save a reference to some core methods
+ toString = Object.prototype.toString,
+ hasOwn = Object.prototype.hasOwnProperty,
+ push = Array.prototype.push,
+ slice = Array.prototype.slice,
+ trim = String.prototype.trim,
+ indexOf = Array.prototype.indexOf,
+
+ // [[Class]] -> type pairs
+ class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem, ret, doc;
+
+ // Handle $(""), $(null), or $(undefined)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle $(DOMElement)
+ if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // The body element only exists once, optimize finding it
+ if ( selector === "body" && !context && document.body ) {
+ this.context = document;
+ this[0] = document.body;
+ this.selector = selector;
+ this.length = 1;
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ // Are we dealing with HTML string or an ID?
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = quickExpr.exec( selector );
+ }
+
+ // Verify a match, and that no context was specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+ doc = ( context ? context.ownerDocument || context : document );
+
+ // If a single string is passed in and it's a single tag
+ // just do a createElement and skip the rest
+ ret = rsingleTag.exec( selector );
+
+ if ( ret ) {
+ if ( jQuery.isPlainObject( context ) ) {
+ selector = [ document.createElement( ret[1] ) ];
+ jQuery.fn.attr.call( selector, context, true );
+
+ } else {
+ selector = [ doc.createElement( ret[1] ) ];
+ }
+
+ } else {
+ ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+ selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+ }
+
+ return jQuery.merge( this, selector );
+
+ // HANDLE: $("#id")
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The current version of jQuery being used
+ jquery: "1.7",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ // The number of elements contained in the matched element set
+ size: function() {
+ return this.length;
+ },
+
+ toArray: function() {
+ return slice.call( this, 0 );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems, name, selector ) {
+ // Build a new jQuery matched element set
+ var ret = this.constructor();
+
+ if ( jQuery.isArray( elems ) ) {
+ push.apply( ret, elems );
+
+ } else {
+ jQuery.merge( ret, elems );
+ }
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ ret.context = this.context;
+
+ if ( name === "find" ) {
+ ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+ } else if ( name ) {
+ ret.selector = this.selector + "." + name + "(" + selector + ")";
+ }
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Attach the listeners
+ jQuery.bindReady();
+
+ // Add the callback
+ readyList.add( fn );
+
+ return this;
+ },
+
+ eq: function( i ) {
+ return i === -1 ?
+ this.slice( i ) :
+ this.slice( i, +i + 1 );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ),
+ "slice", slice.call(arguments).join(",") );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+ // Either a released hold or an DOMready/load event and not yet ready
+ if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.fireWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger( "ready" ).unbind( "ready" );
+ }
+ }
+ },
+
+ bindReady: function() {
+ if ( readyList ) {
+ return;
+ }
+
+ readyList = jQuery.Callbacks( "once memory" );
+
+ // Catch cases where $(document).ready() is called after the
+ // browser event has already occurred.
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ return setTimeout( jQuery.ready, 1 );
+ }
+
+ // Mozilla, Opera and webkit nightlies currently support this event
+ if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", jQuery.ready, false );
+
+ // If IE event model is used
+ } else if ( document.attachEvent ) {
+ // ensure firing before onload,
+ // maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", jQuery.ready );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var toplevel = false;
+
+ try {
+ toplevel = window.frameElement == null;
+ } catch(e) {}
+
+ if ( document.documentElement.doScroll && toplevel ) {
+ doScrollCheck();
+ }
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ // A crude way of determining if an object is a window
+ isWindow: function( obj ) {
+ return obj && typeof obj === "object" && "setInterval" in obj;
+ },
+
+ isNumeric: function( obj ) {
+ return obj != null && rdigit.test( obj ) && !isNaN( obj );
+ },
+
+ type: function( obj ) {
+ return obj == null ?
+ String( obj ) :
+ class2type[ toString.call(obj) ] || "object";
+ },
+
+ isPlainObject: function( obj ) {
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+
+ var key;
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ for ( var name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw msg;
+ },
+
+ parseJSON: function( data ) {
+ if ( typeof data !== "string" || !data ) {
+ return null;
+ }
+
+ // Make sure leading/trailing whitespace is removed (IE can't handle it)
+ data = jQuery.trim( data );
+
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ return window.JSON.parse( data );
+ }
+
+ // Make sure the incoming data is actual JSON
+ // Logic borrowed from http://json.org/json2.js
+ if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+ .replace( rvalidtokens, "]" )
+ .replace( rvalidbraces, "")) ) {
+
+ return ( new Function( "return " + data ) )();
+
+ }
+ jQuery.error( "Invalid JSON: " + data );
+ },
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && rnotwhite.test( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+ },
+
+ // args is for internal usage only
+ each: function( object, callback, args ) {
+ var name, i = 0,
+ length = object.length,
+ isObj = length === undefined || jQuery.isFunction( object );
+
+ if ( args ) {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.apply( object[ name ], args ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.apply( object[ i++ ], args ) === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isObj ) {
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( ; i < length; ) {
+ if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return object;
+ },
+
+ // Use native String.trim function wherever possible
+ trim: trim ?
+ function( text ) {
+ return text == null ?
+ "" :
+ trim.call( text );
+ } :
+
+ // Otherwise use our own trimming functionality
+ function( text ) {
+ return text == null ?
+ "" :
+ text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( array, results ) {
+ var ret = results || [];
+
+ if ( array != null ) {
+ // The window, strings (and functions) also have 'length'
+ // The extra typeof function check is to prevent crashes
+ // in Safari 2 (See: #3039)
+ // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+ var type = jQuery.type( array );
+
+ if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+ push.call( ret, array );
+ } else {
+ jQuery.merge( ret, array );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, array, i ) {
+ var len;
+
+ if ( array ) {
+ if ( indexOf ) {
+ return indexOf.call( array, elem, i );
+ }
+
+ len = array.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in array && array[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var i = first.length,
+ j = 0;
+
+ if ( typeof second.length === "number" ) {
+ for ( var l = second.length; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var ret = [], retVal;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( var i = 0, length = elems.length; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value, key, ret = [],
+ i = 0,
+ length = elems.length,
+ // jquery objects are treated as arrays
+ isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( key in elems ) {
+ value = callback( elems[ key ], key, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return ret.concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ if ( typeof context === "string" ) {
+ var tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ var args = slice.call( arguments, 2 ),
+ proxy = function() {
+ return fn.apply( context, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Mutifunctional method to get and set values to a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, key, value, exec, fn, pass ) {
+ var length = elems.length;
+
+ // Setting many attributes
+ if ( typeof key === "object" ) {
+ for ( var k in key ) {
+ jQuery.access( elems, k, key[k], exec, fn, value );
+ }
+ return elems;
+ }
+
+ // Setting one attribute
+ if ( value !== undefined ) {
+ // Optionally, function values get executed if exec is true
+ exec = !pass && exec && jQuery.isFunction(value);
+
+ for ( var i = 0; i < length; i++ ) {
+ fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+ }
+
+ return elems;
+ }
+
+ // Getting an attribute
+ return length ? fn( elems[0], key ) : undefined;
+ },
+
+ now: function() {
+ return ( new Date() ).getTime();
+ },
+
+ // Use of jQuery.browser is frowned upon.
+ // More details: http://docs.jquery.com/Utilities/jQuery.browser
+ uaMatch: function( ua ) {
+ ua = ua.toLowerCase();
+
+ var match = rwebkit.exec( ua ) ||
+ ropera.exec( ua ) ||
+ rmsie.exec( ua ) ||
+ ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+ [];
+
+ return { browser: match[1] || "", version: match[2] || "0" };
+ },
+
+ sub: function() {
+ function jQuerySub( selector, context ) {
+ return new jQuerySub.fn.init( selector, context );
+ }
+ jQuery.extend( true, jQuerySub, this );
+ jQuerySub.superclass = this;
+ jQuerySub.fn = jQuerySub.prototype = this();
+ jQuerySub.fn.constructor = jQuerySub;
+ jQuerySub.sub = this.sub;
+ jQuerySub.fn.init = function init( selector, context ) {
+ if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+ context = jQuerySub( context );
+ }
+
+ return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+ };
+ jQuerySub.fn.init.prototype = jQuerySub.fn;
+ var rootjQuerySub = jQuerySub(document);
+ return jQuerySub;
+ },
+
+ browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+ jQuery.browser[ browserMatch.browser ] = true;
+ jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+ jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+ trimLeft = /^[\s\xA0]+/;
+ trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+ DOMContentLoaded = function() {
+ document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+ jQuery.ready();
+ };
+
+} else if ( document.attachEvent ) {
+ DOMContentLoaded = function() {
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( document.readyState === "complete" ) {
+ document.detachEvent( "onreadystatechange", DOMContentLoaded );
+ jQuery.ready();
+ }
+ };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+ if ( jQuery.isReady ) {
+ return;
+ }
+
+ try {
+ // If IE is used, use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ document.documentElement.doScroll("left");
+ } catch(e) {
+ setTimeout( doScrollCheck, 1 );
+ return;
+ }
+
+ // and execute any waiting functions
+ jQuery.ready();
+}
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+ define( "jquery", [], function () { return jQuery; } );
+}
+
+return jQuery;
+
+})();
+
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+ var object = flagsCache[ flags ] = {},
+ i, length;
+ flags = flags.split( /\s+/ );
+ for ( i = 0, length = flags.length; i < length; i++ ) {
+ object[ flags[i] ] = true;
+ }
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * flags: an optional list of space-separated flags that will change how
+ * the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( flags ) {
+
+ // Convert flags from String-formatted to Object-formatted
+ // (we check in cache first)
+ flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+ var // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = [],
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Add one or several callbacks to the list
+ add = function( args ) {
+ var i,
+ length,
+ elem,
+ type,
+ actual;
+ for ( i = 0, length = args.length; i < length; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ // Inspect recursively
+ add( elem );
+ } else if ( type === "function" ) {
+ // Add if not in unique mode and callback is not in
+ if ( !flags.unique || !self.has( elem ) ) {
+ list.push( elem );
+ }
+ }
+ }
+ },
+ // Fire callbacks
+ fire = function( context, args ) {
+ args = args || [];
+ memory = !flags.memory || [ context, args ];
+ firing = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+ memory = true; // Mark as halted
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( !flags.once ) {
+ if ( stack && stack.length ) {
+ memory = stack.shift();
+ self.fireWith( memory[ 0 ], memory[ 1 ] );
+ }
+ } else if ( memory === true ) {
+ self.disable();
+ } else {
+ list = [];
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ var length = list.length;
+ add( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away, unless previous
+ // firing was halted (stopOnFalse)
+ } else if ( memory && memory !== true ) {
+ firingStart = length;
+ fire( memory[ 0 ], memory[ 1 ] );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ var args = arguments,
+ argIndex = 0,
+ argLength = args.length;
+ for ( ; argIndex < argLength ; argIndex++ ) {
+ for ( var i = 0; i < list.length; i++ ) {
+ if ( args[ argIndex ] === list[ i ] ) {
+ // Handle firingIndex and firingLength
+ if ( firing ) {
+ if ( i <= firingLength ) {
+ firingLength--;
+ if ( i <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ // Remove the element
+ list.splice( i--, 1 );
+ // If we have some unicity property then
+ // we only need to do this once
+ if ( flags.unique ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ return this;
+ },
+ // Control if a given callback is in the list
+ has: function( fn ) {
+ if ( list ) {
+ var i = 0,
+ length = list.length;
+ for ( ; i < length; i++ ) {
+ if ( fn === list[ i ] ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory || memory === true ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( stack ) {
+ if ( firing ) {
+ if ( !flags.once ) {
+ stack.push( [ context, args ] );
+ }
+ } else if ( !( flags.once && memory ) ) {
+ fire( context, args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!memory;
+ }
+ };
+
+ return self;
+};
+
+
+
+
+var // Static reference to slice
+ sliceDeferred = [].slice;
+
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var doneList = jQuery.Callbacks( "once memory" ),
+ failList = jQuery.Callbacks( "once memory" ),
+ progressList = jQuery.Callbacks( "memory" ),
+ state = "pending",
+ lists = {
+ resolve: doneList,
+ reject: failList,
+ notify: progressList
+ },
+ promise = {
+ done: doneList.add,
+ fail: failList.add,
+ progress: progressList.add,
+
+ state: function() {
+ return state;
+ },
+
+ // Deprecated
+ isResolved: doneList.fired,
+ isRejected: failList.fired,
+
+ then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+ deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+ return this;
+ },
+ always: function() {
+ return deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+ },
+ pipe: function( fnDone, fnFail, fnProgress ) {
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( {
+ done: [ fnDone, "resolve" ],
+ fail: [ fnFail, "reject" ],
+ progress: [ fnProgress, "notify" ]
+ }, function( handler, data ) {
+ var fn = data[ 0 ],
+ action = data[ 1 ],
+ returned;
+ if ( jQuery.isFunction( fn ) ) {
+ deferred[ handler ](function() {
+ returned = fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+ }
+ });
+ } else {
+ deferred[ handler ]( newDefer[ action ] );
+ }
+ });
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ if ( obj == null ) {
+ obj = promise;
+ } else {
+ for ( var key in promise ) {
+ obj[ key ] = promise[ key ];
+ }
+ }
+ return obj;
+ }
+ },
+ deferred = promise.promise({}),
+ key;
+
+ for ( key in lists ) {
+ deferred[ key ] = lists[ key ].fire;
+ deferred[ key + "With" ] = lists[ key ].fireWith;
+ }
+
+ // Handle state
+ deferred.done( function() {
+ state = "resolved";
+ }, failList.disable, progressList.lock ).fail( function() {
+ state = "rejected";
+ }, doneList.disable, progressList.lock );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( firstParam ) {
+ var args = sliceDeferred.call( arguments, 0 ),
+ i = 0,
+ length = args.length,
+ pValues = new Array( length ),
+ count = length,
+ pCount = length,
+ deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+ firstParam :
+ jQuery.Deferred(),
+ promise = deferred.promise();
+ function resolveFunc( i ) {
+ return function( value ) {
+ args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ if ( !( --count ) ) {
+ deferred.resolveWith( deferred, args );
+ }
+ };
+ }
+ function progressFunc( i ) {
+ return function( value ) {
+ pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+ deferred.notifyWith( promise, pValues );
+ };
+ }
+ if ( length > 1 ) {
+ for ( ; i < length; i++ ) {
+ if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+ args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+ } else {
+ --count;
+ }
+ }
+ if ( !count ) {
+ deferred.resolveWith( deferred, args );
+ }
+ } else if ( deferred !== firstParam ) {
+ deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+ }
+ return promise;
+ }
+});
+
+
+
+
+jQuery.support = (function() {
+
+ var div = document.createElement( "div" ),
+ documentElement = document.documentElement,
+ all,
+ a,
+ select,
+ opt,
+ input,
+ marginDiv,
+ support,
+ fragment,
+ body,
+ testElementParent,
+ testElement,
+ testElementStyle,
+ tds,
+ events,
+ eventName,
+ i,
+ isSupported;
+
+ // Preliminary tests
+ div.setAttribute("className", "t");
+ div.innerHTML = " <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/><nav></nav>";
+
+
+ all = div.getElementsByTagName( "*" );
+ a = div.getElementsByTagName( "a" )[ 0 ];
+
+ // Can't get basic test support
+ if ( !all || !all.length || !a ) {
+ return {};
+ }
+
+ // First batch of supports tests
+ select = document.createElement( "select" );
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName( "input" )[ 0 ];
+
+ support = {
+ // IE strips leading whitespace when .innerHTML is used
+ leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ tbody: !div.getElementsByTagName( "tbody" ).length,
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ htmlSerialize: !!div.getElementsByTagName( "link" ).length,
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ style: /top/.test( a.getAttribute("style") ),
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
+
+ // Make sure that element opacity exists
+ // (IE uses filter instead)
+ // Use a regex to work around a WebKit issue. See #5145
+ opacity: /^0.55/.test( a.style.opacity ),
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ cssFloat: !!a.style.cssFloat,
+
+ // Make sure unknown elements (like HTML5 elems) are handled appropriately
+ unknownElems: !!div.getElementsByTagName( "nav" ).length,
+
+ // Make sure that if no value is specified for a checkbox
+ // that it defaults to "on".
+ // (WebKit defaults to "" instead)
+ checkOn: ( input.value === "on" ),
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ optSelected: opt.selected,
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ getSetAttribute: div.className !== "t",
+
+ // Tests for enctype support on a form(#6743)
+ enctype: !!document.createElement("form").enctype,
+
+ // Will be defined later
+ submitBubbles: true,
+ changeBubbles: true,
+ focusinBubbles: false,
+ deleteExpando: true,
+ noCloneEvent: true,
+ inlineBlockNeedsLayout: false,
+ shrinkWrapBlocks: false,
+ reliableMarginRight: true
+ };
+
+ // Make sure checked status is properly cloned
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Test to see if it's possible to delete an expando from an element
+ // Fails in Internet Explorer
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+
+ if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+ div.attachEvent( "onclick", function() {
+ // Cloning a node shouldn't copy over any
+ // bound event handlers (IE does this)
+ support.noCloneEvent = false;
+ });
+ div.cloneNode( true ).fireEvent( "onclick" );
+ }
+
+ // Check if a radio maintains its value
+ // after being appended to the DOM
+ input = document.createElement("input");
+ input.value = "t";
+ input.setAttribute("type", "radio");
+ support.radioValue = input.value === "t";
+
+ input.setAttribute("checked", "checked");
+ div.appendChild( input );
+ fragment = document.createDocumentFragment();
+ fragment.appendChild( div.lastChild );
+
+ // WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ div.innerHTML = "";
+
+ // Figure out if the W3C box model works as expected
+ div.style.width = div.style.paddingLeft = "1px";
+
+ // We don't want to do body-related feature tests on frameset
+ // documents, which lack a body. So we use
+ // document.getElementsByTagName("body")[0], which is undefined in
+ // frameset documents, while document.body isn’t. (7398)
+ body = document.getElementsByTagName("body")[ 0 ];
+ // We use our own, invisible, body unless the body is already present
+ // in which case we use a div (#9239)
+ testElement = document.createElement( body ? "div" : "body" );
+ testElementStyle = {
+ visibility: "hidden",
+ width: 0,
+ height: 0,
+ border: 0,
+ margin: 0,
+ background: "none"
+ };
+ if ( body ) {
+ jQuery.extend( testElementStyle, {
+ position: "absolute",
+ left: "-999px",
+ top: "-999px"
+ });
+ }
+ for ( i in testElementStyle ) {
+ testElement.style[ i ] = testElementStyle[ i ];
+ }
+ testElement.appendChild( div );
+ testElementParent = body || documentElement;
+ testElementParent.insertBefore( testElement, testElementParent.firstChild );
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ support.appendChecked = input.checked;
+
+ support.boxModel = div.offsetWidth === 2;
+
+ if ( "zoom" in div.style ) {
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ // (IE < 8 does this)
+ div.style.display = "inline";
+ div.style.zoom = 1;
+ support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
+
+ // Check if elements with layout shrink-wrap their children
+ // (IE 6 does this)
+ div.style.display = "";
+ div.innerHTML = "<div style='width:4px;'></div>";
+ support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
+ }
+
+ div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
+ tds = div.getElementsByTagName( "td" );
+
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ // (only IE 8 fails this test)
+ isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+ tds[ 0 ].style.display = "";
+ tds[ 1 ].style.display = "none";
+
+ // Check if empty table cells still have offsetWidth/Height
+ // (IE < 8 fail this test)
+ support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+ div.innerHTML = "";
+
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. For more
+ // info see bug #3333
+ // Fails in WebKit before Feb 2011 nightlies
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ marginDiv = document.createElement( "div" );
+ marginDiv.style.width = "0";
+ marginDiv.style.marginRight = "0";
+ div.appendChild( marginDiv );
+ support.reliableMarginRight =
+ ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+ }
+
+ // Technique from Juriy Zaytsev
+ // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+ // We only care about the case where non-standard event systems
+ // are used, namely in IE. Short-circuiting here helps us to
+ // avoid an eval call (in setAttribute) which can cause CSP
+ // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+ if ( div.attachEvent ) {
+ for( i in {
+ submit: 1,
+ change: 1,
+ focusin: 1
+ } ) {
+ eventName = "on" + i;
+ isSupported = ( eventName in div );
+ if ( !isSupported ) {
+ div.setAttribute( eventName, "return;" );
+ isSupported = ( typeof div[ eventName ] === "function" );
+ }
+ support[ i + "Bubbles" ] = isSupported;
+ }
+ }
+
+ // Run fixed position tests at doc ready to avoid a crash
+ // related to the invisible body in IE8
+ jQuery(function() {
+ var container, outer, inner, table, td, offsetSupport,
+ conMarginTop = 1,
+ ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",
+ vb = "visibility:hidden;border:0;",
+ style = "style='" + ptlm + "border:5px solid #000;padding:0;'",
+ html = "<div " + style + "><div></div></div>" +
+ "<table " + style + " cellpadding='0' cellspacing='0'>" +
+ "<tr><td></td></tr></table>";
+
+ // Reconstruct a container
+ body = document.getElementsByTagName("body")[0];
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ // These tests cannot be done
+ return;
+ }
+
+ container = document.createElement("div");
+ container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+ body.insertBefore( container, body.firstChild );
+
+ // Construct a test element
+ testElement = document.createElement("div");
+ testElement.style.cssText = ptlm + vb;
+
+ testElement.innerHTML = html;
+ container.appendChild( testElement );
+ outer = testElement.firstChild;
+ inner = outer.firstChild;
+ td = outer.nextSibling.firstChild.firstChild;
+
+ offsetSupport = {
+ doesNotAddBorder: ( inner.offsetTop !== 5 ),
+ doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+ };
+
+ inner.style.position = "fixed";
+ inner.style.top = "20px";
+
+ // safari subtracts parent border width here which is 5px
+ offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+ inner.style.position = inner.style.top = "";
+
+ outer.style.overflow = "hidden";
+ outer.style.position = "relative";
+
+ offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+ offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+ body.removeChild( container );
+ testElement = container = null;
+
+ jQuery.extend( support, offsetSupport );
+ });
+
+ testElement.innerHTML = "";
+ testElementParent.removeChild( testElement );
+
+ // Null connected elements to avoid leaks in IE
+ testElement = fragment = select = opt = body = marginDiv = div = input = null;
+
+ return support;
+})();
+
+// Keep track of boxModel
+jQuery.boxModel = jQuery.support.boxModel;
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+ cache: {},
+
+ // Please use with caution
+ uuid: 0,
+
+ // Unique for each copy of jQuery on the page
+ // Non-digits removed to match rinlinejQuery
+ expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+ // The following elements throw uncatchable exceptions if you
+ // attempt to add expando properties to them.
+ noData: {
+ "embed": true,
+ // Ban all objects except for Flash (which handle expandos)
+ "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+ "applet": true
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var privateCache, thisCache, ret,
+ internalKey = jQuery.expando,
+ getByName = typeof name === "string",
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando,
+ isEvents = name === "events";
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ elem[ jQuery.expando ] = id = ++jQuery.uuid;
+ } else {
+ id = jQuery.expando;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ cache[ id ] = {};
+
+ // Avoids exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ if ( !isNode ) {
+ cache[ id ].toJSON = jQuery.noop;
+ }
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ privateCache = thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Users should not attempt to inspect the internal events object using jQuery.data,
+ // it is undocumented and subject to change. But does anyone listen? No.
+ if ( isEvents && !thisCache[ name ] ) {
+ return privateCache.events;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( getByName ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+ },
+
+ removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i, l,
+
+ // Reference to internal data cache key
+ internalKey = jQuery.expando,
+
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+
+ // See jQuery.data for more information
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support space separated names
+ if ( jQuery.isArray( name ) ) {
+ name = name;
+ } else if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split( " " );
+ }
+ }
+
+ for ( i = 0, l = name.length; i < l; i++ ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject(cache[ id ]) ) {
+ return;
+ }
+ }
+
+ // Browsers that fail expando deletion also refuse to delete expandos on
+ // the window, but it will allow it on all other JS objects; other browsers
+ // don't care
+ // Ensure that `cache` is not a window object #10080
+ if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+ delete cache[ id ];
+ } else {
+ cache[ id ] = null;
+ }
+
+ // We destroyed the cache and need to eliminate the expando on the node to avoid
+ // false lookups in the cache for entries that no longer exist
+ if ( isNode ) {
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( jQuery.support.deleteExpando ) {
+ delete elem[ jQuery.expando ];
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ } else {
+ elem[ jQuery.expando ] = null;
+ }
+ }
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return jQuery.data( elem, name, data, true );
+ },
+
+ // A method for determining if a DOM node can handle the data expando
+ acceptData: function( elem ) {
+ if ( elem.nodeName ) {
+ var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+ if ( match ) {
+ return !(match === true || elem.getAttribute("classid") !== match);
+ }
+ }
+
+ return true;
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var parts, attr, name,
+ data = null;
+
+ if ( typeof key === "undefined" ) {
+ if ( this.length ) {
+ data = jQuery.data( this[0] );
+
+ if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
+ attr = this[0].attributes;
+ for ( var i = 0, l = attr.length; i < l; i++ ) {
+ name = attr[i].name;
+
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.substring(5) );
+
+ dataAttr( this[0], name, data[ name ] );
+ }
+ }
+ jQuery._data( this[0], "parsedAttrs", true );
+ }
+ }
+
+ return data;
+
+ } else if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ parts = key.split(".");
+ parts[1] = parts[1] ? "." + parts[1] : "";
+
+ if ( value === undefined ) {
+ data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+ // Try to fetch any internally stored data first
+ if ( data === undefined && this.length ) {
+ data = jQuery.data( this[0], key );
+ data = dataAttr( this[0], key, data );
+ }
+
+ return data === undefined && parts[1] ?
+ this.data( parts[0] ) :
+ data;
+
+ } else {
+ return this.each(function() {
+ var $this = jQuery( this ),
+ args = [ parts[0], value ];
+
+ $this.triggerHandler( "setData" + parts[1] + "!", args );
+ jQuery.data( this, key, value );
+ $this.triggerHandler( "changeData" + parts[1] + "!", args );
+ });
+ }
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ jQuery.isNumeric( data ) ? parseFloat( data ) :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ for ( var name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+ var deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ defer = jQuery._data( elem, deferDataKey );
+ if ( defer &&
+ ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+ ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+ // Give room for hard-coded callbacks to fire first
+ // and eventually mark/queue something else on the element
+ setTimeout( function() {
+ if ( !jQuery._data( elem, queueDataKey ) &&
+ !jQuery._data( elem, markDataKey ) ) {
+ jQuery.removeData( elem, deferDataKey, true );
+ defer.fire();
+ }
+ }, 0 );
+ }
+}
+
+jQuery.extend({
+
+ _mark: function( elem, type ) {
+ if ( elem ) {
+ type = ( type || "fx" ) + "mark";
+ jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+ }
+ },
+
+ _unmark: function( force, elem, type ) {
+ if ( force !== true ) {
+ type = elem;
+ elem = force;
+ force = false;
+ }
+ if ( elem ) {
+ type = type || "fx";
+ var key = type + "mark",
+ count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+ if ( count ) {
+ jQuery._data( elem, key, count );
+ } else {
+ jQuery.removeData( elem, key, true );
+ handleQueueMarkDefer( elem, type, "mark" );
+ }
+ }
+ },
+
+ queue: function( elem, type, data ) {
+ var q;
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ q = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !q || jQuery.isArray(data) ) {
+ q = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ q.push( data );
+ }
+ }
+ return q || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ fn = queue.shift(),
+ hooks = {};
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ }
+
+ if ( fn ) {
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ jQuery._data( elem, type + ".run", hooks );
+ fn.call( elem, function() {
+ jQuery.dequeue( elem, type );
+ }, hooks );
+ }
+
+ if ( !queue.length ) {
+ jQuery.removeData( elem, type + "queue " + type + ".run", true );
+ handleQueueMarkDefer( elem, type, "queue" );
+ }
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ }
+
+ if ( data === undefined ) {
+ return jQuery.queue( this[0], type );
+ }
+ return this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, object ) {
+ if ( typeof type !== "string" ) {
+ object = type;
+ type = undefined;
+ }
+ type = type || "fx";
+ var defer = jQuery.Deferred(),
+ elements = this,
+ i = elements.length,
+ count = 1,
+ deferDataKey = type + "defer",
+ queueDataKey = type + "queue",
+ markDataKey = type + "mark",
+ tmp;
+ function resolve() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ }
+ while( i-- ) {
+ if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+ ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+ jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+ jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+ count++;
+ tmp.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise();
+ }
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+ rspace = /\s+/,
+ rreturn = /\r/g,
+ rtype = /^(?:button|input)$/i,
+ rfocusable = /^(?:button|input|object|select|textarea)$/i,
+ rclickable = /^a(?:rea)?$/i,
+ rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+ getSetAttribute = jQuery.support.getSetAttribute,
+ nodeHook, boolHook, fixSpecified;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, name, value, true, jQuery.attr );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, name, value, true, jQuery.prop );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ },
+
+ addClass: function( value ) {
+ var classNames, i, l, elem,
+ setClass, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( value && typeof value === "string" ) {
+ classNames = value.split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 ) {
+ if ( !elem.className && classNames.length === 1 ) {
+ elem.className = value;
+
+ } else {
+ setClass = " " + elem.className + " ";
+
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+ setClass += classNames[ c ] + " ";
+ }
+ }
+ elem.className = jQuery.trim( setClass );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classNames, i, l, elem, className, c, cl;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call(this, j, this.className) );
+ });
+ }
+
+ if ( (value && typeof value === "string") || value === undefined ) {
+ classNames = ( value || "" ).split( rspace );
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.nodeType === 1 && elem.className ) {
+ if ( value ) {
+ className = (" " + elem.className + " ").replace( rclass, " " );
+ for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+ className = className.replace(" " + classNames[ c ] + " ", " ");
+ }
+ elem.className = jQuery.trim( className );
+
+ } else {
+ elem.className = "";
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value,
+ isBool = typeof stateVal === "boolean";
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ state = stateVal,
+ classNames = value.split( rspace );
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space seperated list
+ state = isBool ? state : !self.hasClass( className );
+ self[ state ? "addClass" : "removeClass" ]( className );
+ }
+
+ } else if ( type === "undefined" || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // toggle whole className
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return undefined;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var self = jQuery(this), val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, self.val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, i, max, option,
+ index = elem.selectedIndex,
+ values = [],
+ options = elem.options,
+ one = elem.type === "select-one";
+
+ // Nothing was selected
+ if ( index < 0 ) {
+ return null;
+ }
+
+ // Loop through all the selected options
+ i = one ? index : 0;
+ max = one ? index + 1 : options.length;
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Don't return options that are disabled or in a disabled optgroup
+ if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+ (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+ if ( one && !values.length && options.length ) {
+ return jQuery( options[ index ] ).val();
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var values = jQuery.makeArray( value );
+
+ jQuery(elem).find("option").each(function() {
+ this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+ });
+
+ if ( !values.length ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attrFn: {
+ val: true,
+ css: true,
+ html: true,
+ text: true,
+ data: true,
+ width: true,
+ height: true,
+ offset: true
+ },
+
+ attr: function( elem, name, value, pass ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return undefined;
+ }
+
+ if ( pass && name in jQuery.attrFn ) {
+ return jQuery( elem )[ name ]( value );
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( !("getAttribute" in elem) ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( notxml ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return undefined;
+
+ } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, "" + value );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+
+ ret = elem.getAttribute( name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret === null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var propName, attrNames, name, l,
+ i = 0;
+
+ if ( elem.nodeType === 1 ) {
+ attrNames = ( value || "" ).split( rspace );
+ l = attrNames.length;
+
+ for ( ; i < l; i++ ) {
+ name = attrNames[ i ].toLowerCase();
+ propName = jQuery.propFix[ name ] || name;
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ jQuery.attr( elem, name, "" );
+ elem.removeAttribute( getSetAttribute ? name : propName );
+
+ // Set corresponding property to false for boolean attributes
+ if ( rboolean.test( name ) && propName in elem ) {
+ elem[ propName ] = false;
+ }
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ // We can't allow the type property to be changed (since it causes problems in IE)
+ if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+ jQuery.error( "type property can't be changed" );
+ } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to it's default in case type is set after value
+ // This is for element creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ },
+ // Use the value property for back compat
+ // Use the nodeHook for button elements in IE6/7 (#1954)
+ value: {
+ get: function( elem, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.get( elem, name );
+ }
+ return name in elem ?
+ elem.value :
+ null;
+ },
+ set: function( elem, value, name ) {
+ if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+ return nodeHook.set( elem, value, name );
+ }
+ // Does not return so that setAttribute is also used
+ elem.value = value;
+ }
+ }
+ },
+
+ propFix: {
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ "for": "htmlFor",
+ "class": "className",
+ maxlength: "maxLength",
+ cellspacing: "cellSpacing",
+ cellpadding: "cellPadding",
+ rowspan: "rowSpan",
+ colspan: "colSpan",
+ usemap: "useMap",
+ frameborder: "frameBorder",
+ contenteditable: "contentEditable"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return undefined;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ return ( elem[ name ] = value );
+ }
+
+ } else {
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ return elem[ name ];
+ }
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ var attributeNode = elem.getAttributeNode("tabindex");
+
+ return attributeNode && attributeNode.specified ?
+ parseInt( attributeNode.value, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ undefined;
+ }
+ }
+ }
+});
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+boolHook = {
+ get: function( elem, name ) {
+ // Align boolean attributes with corresponding properties
+ // Fall back to attribute presence where some booleans are not supported
+ var attrNode,
+ property = jQuery.prop( elem, name );
+ return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+ name.toLowerCase() :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ var propName;
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ // value is true since we know at this point it's type boolean and not false
+ // Set boolean attributes to the same name and set the DOM property
+ propName = jQuery.propFix[ name ] || name;
+ if ( propName in elem ) {
+ // Only set the IDL specifically if it already exists on the element
+ elem[ propName ] = true;
+ }
+
+ elem.setAttribute( name, name.toLowerCase() );
+ }
+ return name;
+ }
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ fixSpecified = {
+ name: true,
+ id: true
+ };
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret;
+ ret = elem.getAttributeNode( name );
+ return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+ ret.nodeValue :
+ undefined;
+ },
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ ret = document.createAttribute( name );
+ elem.setAttributeNode( ret );
+ }
+ return ( ret.nodeValue = value + "" );
+ }
+ };
+
+ // Apply the nodeHook to tabindex
+ jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ });
+ });
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ get: nodeHook.get,
+ set: function( elem, value, name ) {
+ if ( value === "" ) {
+ value = "false";
+ }
+ nodeHook.set( elem, value, name );
+ }
+ };
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+ jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+ get: function( elem ) {
+ var ret = elem.getAttribute( name, 2 );
+ return ret === null ? undefined : ret;
+ }
+ });
+ });
+}
+
+if ( !jQuery.support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Normalize to lowercase since IE uppercases css property names
+ return elem.style.cssText.toLowerCase() || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = "" + value );
+ }
+ };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+ jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ get: function( elem ) {
+ // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ }
+ };
+ });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ });
+});
+
+
+
+
+var rnamespaces = /\.(.*)$/,
+ rformElems = /^(?:textarea|input|select)$/i,
+ rperiod = /\./g,
+ rspaces = / /g,
+ rescape = /[^\w\s.|`]/g,
+ rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+ rhoverHack = /\bhover(\.\S+)?/,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+ quickParse = function( selector ) {
+ var quick = rquickIs.exec( selector );
+ if ( quick ) {
+ // 0 1 2 3
+ // [ _, tag, id, class ]
+ quick[1] = ( quick[1] || "" ).toLowerCase();
+ quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+ }
+ return quick;
+ },
+ quickIs = function( elem, m ) {
+ return (
+ (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+ (!m[2] || elem.id === m[2]) &&
+ (!m[3] || m[3].test( elem.className ))
+ );
+ },
+ hoverHack = function( events ) {
+ return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+ };
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var elemData, eventHandle, events,
+ t, tns, type, namespaces, handleObj,
+ handleObjIn, quick, handlers, special;
+
+ // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+ if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ events = elemData.events;
+ if ( !events ) {
+ elemData.events = events = {};
+ }
+ eventHandle = elemData.handle;
+ if ( !eventHandle ) {
+ elemData.handle = eventHandle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ // jQuery(...).bind("mouseover mouseout", fn);
+ types = hoverHack(types).split( " " );
+ for ( t = 0; t < types.length; t++ ) {
+
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = tns[1];
+ namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: tns[1],
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Delegated event; pre-analyze selector so it's processed quickly on event dispatch
+ if ( selector ) {
+ handleObj.quick = quickParse( selector );
+ if ( !handleObj.quick && jQuery.expr.match.POS.test( selector ) ) {
+ handleObj.isPositional = true;
+ }
+ }
+
+ // Init the event handler queue if we're the first
+ handlers = events[ type ];
+ if ( !handlers ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ global: {},
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector ) {
+
+ var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+ t, tns, type, namespaces, origCount,
+ j, events, special, handle, eventType, handleObj;
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = hoverHack( types || "" ).split(" ");
+ for ( t = 0; t < types.length; t++ ) {
+ tns = rtypenamespace.exec( types[t] ) || [];
+ type = tns[1];
+ namespaces = tns[2];
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ namespaces = namespaces? "." + namespaces : "";
+ for ( j in events ) {
+ jQuery.event.remove( elem, j + namespaces, handler, selector );
+ }
+ return;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector? special.delegateType : special.bindType ) || type;
+ eventType = events[ type ] || [];
+ origCount = eventType.length;
+ namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+ // Only need to loop for special events or selective removal
+ if ( handler || namespaces || selector || special.remove ) {
+ for ( j = 0; j < eventType.length; j++ ) {
+ handleObj = eventType[ j ];
+
+ if ( !handler || handler.guid === handleObj.guid ) {
+ if ( !namespaces || namespaces.test( handleObj.namespace ) ) {
+ if ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) {
+ eventType.splice( j--, 1 );
+
+ if ( handleObj.selector ) {
+ eventType.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // Removing all events
+ eventType.length = 0;
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( eventType.length === 0 && origCount !== eventType.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ handle = elemData.handle;
+ if ( handle ) {
+ handle.elem = null;
+ }
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery.removeData( elem, [ "events", "handle" ], true );
+ }
+ },
+
+ // Events that are safe to short-circuit if no handlers are attached.
+ // Native DOM events should not be added, they may have inline handlers.
+ customEvent: {
+ "getData": true,
+ "setData": true,
+ "changeData": true
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ // Don't do events on text and comment nodes
+ if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+ return;
+ }
+
+ // Event object or event type
+ var type = event.type || event,
+ namespaces = [],
+ cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+ if ( type.indexOf( "!" ) >= 0 ) {
+ // Exclusive events trigger only for the exact event (no namespaces)
+ type = type.slice(0, -1);
+ exclusive = true;
+ }
+
+ if ( type.indexOf( "." ) >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+
+ if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+ // No jQuery handlers for this event type, and it can't have inline handlers
+ return;
+ }
+
+ // Caller can pass in an Event, Object, or just an event type string
+ event = typeof event === "object" ?
+ // jQuery.Event object
+ event[ jQuery.expando ] ? event :
+ // Object literal
+ new jQuery.Event( type, event ) :
+ // Just the event type (string)
+ new jQuery.Event( type );
+
+ event.type = type;
+ event.isTrigger = true;
+ event.exclusive = exclusive;
+ event.namespace = namespaces.join( "." );
+ event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+ ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+ // triggerHandler() and global events don't bubble or run the default action
+ if ( onlyHandlers || !elem ) {
+ event.preventDefault();
+ }
+
+ // Handle a global trigger
+ if ( !elem ) {
+
+ // TODO: Stop taunting the data cache; remove global events and always attach to document
+ cache = jQuery.cache;
+ for ( i in cache ) {
+ if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+ jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+ }
+ }
+ return;
+ }
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data != null ? jQuery.makeArray( data ) : [];
+ data.unshift( event );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ eventPath = [[ elem, special.bindType || type ]];
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ old = null;
+ for ( cur = elem.parentNode; cur; cur = cur.parentNode ) {
+ eventPath.push([ cur, bubbleType ]);
+ old = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( old && old === elem.ownerDocument ) {
+ eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+ }
+ }
+
+ // Fire handlers on the event path
+ for ( i = 0; i < eventPath.length; i++ ) {
+
+ cur = eventPath[i][0];
+ event.type = eventPath[i][1];
+
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) ) {
+ handle.apply( cur, data );
+ }
+
+ if ( event.isPropagationStopped() ) {
+ break;
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+ !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ // IE<9 dies on focus/blur to hidden element (#1486)
+ if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ old = elem[ ontype ];
+
+ if ( old ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( old ) {
+ elem[ ontype ] = old;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event || window.event );
+
+ var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+ delegateCount = handlers.delegateCount,
+ args = [].slice.call( arguments, 0 ),
+ run_all = !event.exclusive && !event.namespace,
+ specialHandle = ( jQuery.event.special[ event.type ] || {} ).handle,
+ handlerQueue = [],
+ i, j, cur, ret, selMatch, matched, matches, handleObj, sel, hit, related;
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Determine handlers that should run if there are delegated events
+ // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {
+
+ for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+ selMatch = {};
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+ sel = handleObj.selector;
+ hit = selMatch[ sel ];
+
+ if ( handleObj.isPositional ) {
+ // Since .is() does not work for positionals; see http://jsfiddle.net/eJ4yd/3/
+ hit = ( hit || (selMatch[ sel ] = jQuery( sel )) ).index( cur ) >= 0;
+ } else if ( hit === undefined ) {
+ hit = selMatch[ sel ] = ( handleObj.quick ? quickIs( cur, handleObj.quick ) : jQuery( cur ).is( sel ) );
+ }
+ if ( hit ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, matches: matches });
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( handlers.length > delegateCount ) {
+ handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+ }
+
+ // Run delegates first; they may want to stop propagation beneath us
+ for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+ matched = handlerQueue[ i ];
+ event.currentTarget = matched.elem;
+
+ for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+ handleObj = matched.matches[ j ];
+
+ // Triggered event must either 1) be non-exclusive and have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.data = handleObj.data;
+ event.handleObj = handleObj;
+
+ ret = ( specialHandle || handleObj.handler ).apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ event.result = ret;
+ if ( ret === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+ props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement wheelDelta".split(" "),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop,
+ originalEvent = event,
+ fixHook = jQuery.event.fixHooks[ event.type ] || {},
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = jQuery.Event( originalEvent );
+
+ for ( i = copy.length; i; ) {
+ prop = copy[ --i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Target should not be a text node (#504, Safari)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
+ if ( event.metaKey === undefined ) {
+ event.metaKey = event.ctrlKey;
+ }
+
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ ready: {
+ // Make sure the ready event is setup
+ setup: jQuery.bindReady
+ },
+
+ focus: {
+ delegateType: "focusin",
+ noBubble: true
+ },
+ blur: {
+ delegateType: "focusout",
+ noBubble: true
+ },
+
+ beforeunload: {
+ setup: function( data, namespaces, eventHandle ) {
+ // We only want to do this special case on windows
+ if ( jQuery.isWindow( this ) ) {
+ this.onbeforeunload = eventHandle;
+ }
+ },
+
+ teardown: function( namespaces, eventHandle ) {
+ if ( this.onbeforeunload === eventHandle ) {
+ this.onbeforeunload = null;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ { type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ if ( elem.detachEvent ) {
+ elem.detachEvent( "on" + type, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+ return false;
+}
+function returnTrue() {
+ return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // otherwise set the returnValue property of the original event to false (IE)
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ // otherwise set the cancelBubble property of the original event to true (IE)
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = jQuery.event.special[ fix ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj,
+ selector = handleObj.selector,
+ oldType, ret;
+
+ // For a real mouseover/out, always call the handler; for
+ // mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || handleObj.origType === event.type || (related !== target && !jQuery.contains( target, related )) ) {
+ oldType = event.type;
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = oldType;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !form._submit_attached ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ // Form was submitted, bubble the event up the tree
+ if ( this.parentNode ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ });
+ form._submit_attached = true;
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed ) {
+ this._just_changed = false;
+ jQuery.event.simulate( "change", this, event, true );
+ }
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ elem._change_attached = true;
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on.call( this, types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ var handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( var type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ live: function( types, data, fn ) {
+ jQuery( this.context ).on( types, this.selector, data, fn );
+ return this;
+ },
+ die: function( types, fn ) {
+ jQuery( this.context ).off( types, this.selector || "**", fn );
+ return this;
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ if ( this[0] ) {
+ return jQuery.event.trigger( type, data, this[0], true );
+ }
+ },
+
+ toggle: function( fn ) {
+ // Save reference to arguments for access in closure
+ var args = arguments,
+ guid = fn.guid || jQuery.guid++,
+ i = 0,
+ toggler = function( event ) {
+ // Figure out which function to execute
+ var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+ jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+ // Make sure that clicks stop
+ event.preventDefault();
+
+ // and execute the function
+ return args[ lastToggle ].apply( this, arguments ) || false;
+ };
+
+ // link all the functions, so any of them can unbind this click handler
+ toggler.guid = guid;
+ while ( i < args.length ) {
+ args[ i++ ].guid = guid;
+ }
+
+ return this.click( toggler );
+ },
+
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+});
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ if ( fn == null ) {
+ fn = data;
+ data = null;
+ }
+
+ return arguments.length > 0 ?
+ this.bind( name, data, fn ) :
+ this.trigger( name );
+ };
+
+ if ( jQuery.attrFn ) {
+ jQuery.attrFn[ name ] = true;
+ }
+
+ if ( rkeyEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+ }
+
+ if ( rmouseEvent.test( name ) ) {
+ jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+ }
+});
+
+
+
+/*!
+ * Sizzle CSS Selector Engine
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ * More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+ expando = "sizcache" + (Math.random() + '').replace('.', ''),
+ done = 0,
+ toString = Object.prototype.toString,
+ hasDuplicate = false,
+ baseHasDuplicate = true,
+ rBackslash = /\\/g,
+ rReturn = /\r\n/g,
+ rNonWord = /\W/;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+// Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+ baseHasDuplicate = false;
+ return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+ results = results || [];
+ context = context || document;
+
+ var origContext = context;
+
+ if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ var m, set, checkSet, extra, ret, cur, pop, i,
+ prune = true,
+ contextXML = Sizzle.isXML( context ),
+ parts = [],
+ soFar = selector;
+
+ // Reset the position of the chunker regexp (start from head)
+ do {
+ chunker.exec( "" );
+ m = chunker.exec( soFar );
+
+ if ( m ) {
+ soFar = m[3];
+
+ parts.push( m[1] );
+
+ if ( m[2] ) {
+ extra = m[3];
+ break;
+ }
+ }
+ } while ( m );
+
+ if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+ if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+ set = posProcess( parts[0] + parts[1], context, seed );
+
+ } else {
+ set = Expr.relative[ parts[0] ] ?
+ [ context ] :
+ Sizzle( parts.shift(), context );
+
+ while ( parts.length ) {
+ selector = parts.shift();
+
+ if ( Expr.relative[ selector ] ) {
+ selector += parts.shift();
+ }
+
+ set = posProcess( selector, set, seed );
+ }
+ }
+
+ } else {
+ // Take a shortcut and set the context if the root selector is an ID
+ // (but not if it'll be faster if the inner selector is an ID)
+ if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+ Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+ ret = Sizzle.find( parts.shift(), context, contextXML );
+ context = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set )[0] :
+ ret.set[0];
+ }
+
+ if ( context ) {
+ ret = seed ?
+ { expr: parts.pop(), set: makeArray(seed) } :
+ Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+ set = ret.expr ?
+ Sizzle.filter( ret.expr, ret.set ) :
+ ret.set;
+
+ if ( parts.length > 0 ) {
+ checkSet = makeArray( set );
+
+ } else {
+ prune = false;
+ }
+
+ while ( parts.length ) {
+ cur = parts.pop();
+ pop = cur;
+
+ if ( !Expr.relative[ cur ] ) {
+ cur = "";
+ } else {
+ pop = parts.pop();
+ }
+
+ if ( pop == null ) {
+ pop = context;
+ }
+
+ Expr.relative[ cur ]( checkSet, pop, contextXML );
+ }
+
+ } else {
+ checkSet = parts = [];
+ }
+ }
+
+ if ( !checkSet ) {
+ checkSet = set;
+ }
+
+ if ( !checkSet ) {
+ Sizzle.error( cur || selector );
+ }
+
+ if ( toString.call(checkSet) === "[object Array]" ) {
+ if ( !prune ) {
+ results.push.apply( results, checkSet );
+
+ } else if ( context && context.nodeType === 1 ) {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+ results.push( set[i] );
+ }
+ }
+
+ } else {
+ for ( i = 0; checkSet[i] != null; i++ ) {
+ if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+ results.push( set[i] );
+ }
+ }
+ }
+
+ } else {
+ makeArray( checkSet, results );
+ }
+
+ if ( extra ) {
+ Sizzle( extra, origContext, results, seed );
+ Sizzle.uniqueSort( results );
+ }
+
+ return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+ if ( sortOrder ) {
+ hasDuplicate = baseHasDuplicate;
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ for ( var i = 1; i < results.length; i++ ) {
+ if ( results[i] === results[ i - 1 ] ) {
+ results.splice( i--, 1 );
+ }
+ }
+ }
+ }
+
+ return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+ return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+ return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+ var set, i, len, match, type, left;
+
+ if ( !expr ) {
+ return [];
+ }
+
+ for ( i = 0, len = Expr.order.length; i < len; i++ ) {
+ type = Expr.order[i];
+
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+ left = match[1];
+ match.splice( 1, 1 );
+
+ if ( left.substr( left.length - 1 ) !== "\\" ) {
+ match[1] = (match[1] || "").replace( rBackslash, "" );
+ set = Expr.find[ type ]( match, context, isXML );
+
+ if ( set != null ) {
+ expr = expr.replace( Expr.match[ type ], "" );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( !set ) {
+ set = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( "*" ) :
+ [];
+ }
+
+ return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+ var match, anyFound,
+ type, found, item, filter, left,
+ i, pass,
+ old = expr,
+ result = [],
+ curLoop = set,
+ isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+ while ( expr && set.length ) {
+ for ( type in Expr.filter ) {
+ if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+ filter = Expr.filter[ type ];
+ left = match[1];
+
+ anyFound = false;
+
+ match.splice(1,1);
+
+ if ( left.substr( left.length - 1 ) === "\\" ) {
+ continue;
+ }
+
+ if ( curLoop === result ) {
+ result = [];
+ }
+
+ if ( Expr.preFilter[ type ] ) {
+ match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+ if ( !match ) {
+ anyFound = found = true;
+
+ } else if ( match === true ) {
+ continue;
+ }
+ }
+
+ if ( match ) {
+ for ( i = 0; (item = curLoop[i]) != null; i++ ) {
+ if ( item ) {
+ found = filter( item, match, i, curLoop );
+ pass = not ^ found;
+
+ if ( inplace && found != null ) {
+ if ( pass ) {
+ anyFound = true;
+
+ } else {
+ curLoop[i] = false;
+ }
+
+ } else if ( pass ) {
+ result.push( item );
+ anyFound = true;
+ }
+ }
+ }
+ }
+
+ if ( found !== undefined ) {
+ if ( !inplace ) {
+ curLoop = result;
+ }
+
+ expr = expr.replace( Expr.match[ type ], "" );
+
+ if ( !anyFound ) {
+ return [];
+ }
+
+ break;
+ }
+ }
+ }
+
+ // Improper expression
+ if ( expr === old ) {
+ if ( anyFound == null ) {
+ Sizzle.error( expr );
+
+ } else {
+ break;
+ }
+ }
+
+ old = expr;
+ }
+
+ return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+ throw "Syntax error, unrecognized expression: " + msg;
+};
+
+/**
+ * Utility function for retreiving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+var getText = Sizzle.getText = function( elem ) {
+ var i, node,
+ nodeType = elem.nodeType,
+ ret = "";
+
+ if ( nodeType ) {
+ if ( nodeType === 1 ) {
+ // Use textContent || innerText for elements
+ if ( typeof elem.textContent === 'string' ) {
+ return elem.textContent;
+ } else if ( typeof elem.innerText === 'string' ) {
+ // Replace IE's carriage returns
+ return elem.innerText.replace( rReturn, '' );
+ } else {
+ // Traverse it's children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ } else {
+
+ // If no nodeType, this is expected to be an array
+ for ( i = 0; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ if ( node.nodeType !== 8 ) {
+ ret += getText( node );
+ }
+ }
+ }
+ return ret;
+};
+
+var Expr = Sizzle.selectors = {
+ order: [ "ID", "NAME", "TAG" ],
+
+ match: {
+ ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+ NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+ ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
+ TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+ CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
+ POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+ PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+ },
+
+ leftMatch: {},
+
+ attrMap: {
+ "class": "className",
+ "for": "htmlFor"
+ },
+
+ attrHandle: {
+ href: function( elem ) {
+ return elem.getAttribute( "href" );
+ },
+ type: function( elem ) {
+ return elem.getAttribute( "type" );
+ }
+ },
+
+ relative: {
+ "+": function(checkSet, part){
+ var isPartStr = typeof part === "string",
+ isTag = isPartStr && !rNonWord.test( part ),
+ isPartStrNotTag = isPartStr && !isTag;
+
+ if ( isTag ) {
+ part = part.toLowerCase();
+ }
+
+ for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+ if ( (elem = checkSet[i]) ) {
+ while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+ checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+ elem || false :
+ elem === part;
+ }
+ }
+
+ if ( isPartStrNotTag ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ },
+
+ ">": function( checkSet, part ) {
+ var elem,
+ isPartStr = typeof part === "string",
+ i = 0,
+ l = checkSet.length;
+
+ if ( isPartStr && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ var parent = elem.parentNode;
+ checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+ }
+ }
+
+ } else {
+ for ( ; i < l; i++ ) {
+ elem = checkSet[i];
+
+ if ( elem ) {
+ checkSet[i] = isPartStr ?
+ elem.parentNode :
+ elem.parentNode === part;
+ }
+ }
+
+ if ( isPartStr ) {
+ Sizzle.filter( part, checkSet, true );
+ }
+ }
+ },
+
+ "": function(checkSet, part, isXML){
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+ },
+
+ "~": function( checkSet, part, isXML ) {
+ var nodeCheck,
+ doneName = done++,
+ checkFn = dirCheck;
+
+ if ( typeof part === "string" && !rNonWord.test( part ) ) {
+ part = part.toLowerCase();
+ nodeCheck = part;
+ checkFn = dirNodeCheck;
+ }
+
+ checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+ }
+ },
+
+ find: {
+ ID: function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ },
+
+ NAME: function( match, context ) {
+ if ( typeof context.getElementsByName !== "undefined" ) {
+ var ret = [],
+ results = context.getElementsByName( match[1] );
+
+ for ( var i = 0, l = results.length; i < l; i++ ) {
+ if ( results[i].getAttribute("name") === match[1] ) {
+ ret.push( results[i] );
+ }
+ }
+
+ return ret.length === 0 ? null : ret;
+ }
+ },
+
+ TAG: function( match, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( match[1] );
+ }
+ }
+ },
+ preFilter: {
+ CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+ match = " " + match[1].replace( rBackslash, "" ) + " ";
+
+ if ( isXML ) {
+ return match;
+ }
+
+ for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+ if ( elem ) {
+ if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
+ if ( !inplace ) {
+ result.push( elem );
+ }
+
+ } else if ( inplace ) {
+ curLoop[i] = false;
+ }
+ }
+ }
+
+ return false;
+ },
+
+ ID: function( match ) {
+ return match[1].replace( rBackslash, "" );
+ },
+
+ TAG: function( match, curLoop ) {
+ return match[1].replace( rBackslash, "" ).toLowerCase();
+ },
+
+ CHILD: function( match ) {
+ if ( match[1] === "nth" ) {
+ if ( !match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ match[2] = match[2].replace(/^\+|\s*/g, '');
+
+ // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+ var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
+ match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+ !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+ // calculate the numbers (first)n+(last) including if they are negative
+ match[2] = (test[1] + (test[2] || 1)) - 0;
+ match[3] = test[3] - 0;
+ }
+ else if ( match[2] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // TODO: Move to normal caching system
+ match[0] = done++;
+
+ return match;
+ },
+
+ ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+ var name = match[1] = match[1].replace( rBackslash, "" );
+
+ if ( !isXML && Expr.attrMap[name] ) {
+ match[1] = Expr.attrMap[name];
+ }
+
+ // Handle if an un-quoted value was used
+ match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
+
+ if ( match[2] === "~=" ) {
+ match[4] = " " + match[4] + " ";
+ }
+
+ return match;
+ },
+
+ PSEUDO: function( match, curLoop, inplace, result, not ) {
+ if ( match[1] === "not" ) {
+ // If we're dealing with a complex expression, or a simple one
+ if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+ match[3] = Sizzle(match[3], null, null, curLoop);
+
+ } else {
+ var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+ if ( !inplace ) {
+ result.push.apply( result, ret );
+ }
+
+ return false;
+ }
+
+ } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+ return true;
+ }
+
+ return match;
+ },
+
+ POS: function( match ) {
+ match.unshift( true );
+
+ return match;
+ }
+ },
+
+ filters: {
+ enabled: function( elem ) {
+ return elem.disabled === false && elem.type !== "hidden";
+ },
+
+ disabled: function( elem ) {
+ return elem.disabled === true;
+ },
+
+ checked: function( elem ) {
+ return elem.checked === true;
+ },
+
+ selected: function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ parent: function( elem ) {
+ return !!elem.firstChild;
+ },
+
+ empty: function( elem ) {
+ return !elem.firstChild;
+ },
+
+ has: function( elem, i, match ) {
+ return !!Sizzle( match[3], elem ).length;
+ },
+
+ header: function( elem ) {
+ return (/h\d/i).test( elem.nodeName );
+ },
+
+ text: function( elem ) {
+ var attr = elem.getAttribute( "type" ), type = elem.type;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
+ },
+
+ radio: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
+ },
+
+ checkbox: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
+ },
+
+ file: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
+ },
+
+ password: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
+ },
+
+ submit: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "submit" === elem.type;
+ },
+
+ image: function( elem ) {
+ return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
+ },
+
+ reset: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && "reset" === elem.type;
+ },
+
+ button: function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && "button" === elem.type || name === "button";
+ },
+
+ input: function( elem ) {
+ return (/input|select|textarea|button/i).test( elem.nodeName );
+ },
+
+ focus: function( elem ) {
+ return elem === elem.ownerDocument.activeElement;
+ }
+ },
+ setFilters: {
+ first: function( elem, i ) {
+ return i === 0;
+ },
+
+ last: function( elem, i, match, array ) {
+ return i === array.length - 1;
+ },
+
+ even: function( elem, i ) {
+ return i % 2 === 0;
+ },
+
+ odd: function( elem, i ) {
+ return i % 2 === 1;
+ },
+
+ lt: function( elem, i, match ) {
+ return i < match[3] - 0;
+ },
+
+ gt: function( elem, i, match ) {
+ return i > match[3] - 0;
+ },
+
+ nth: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ },
+
+ eq: function( elem, i, match ) {
+ return match[3] - 0 === i;
+ }
+ },
+ filter: {
+ PSEUDO: function( elem, match, i, array ) {
+ var name = match[1],
+ filter = Expr.filters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+
+ } else if ( name === "contains" ) {
+ return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+ } else if ( name === "not" ) {
+ var not = match[3];
+
+ for ( var j = 0, l = not.length; j < l; j++ ) {
+ if ( not[j] === elem ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ } else {
+ Sizzle.error( name );
+ }
+ },
+
+ CHILD: function( elem, match ) {
+ var first, last,
+ doneName, parent, cache,
+ count, diff,
+ type = match[1],
+ node = elem;
+
+ switch ( type ) {
+ case "only":
+ case "first":
+ while ( (node = node.previousSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ if ( type === "first" ) {
+ return true;
+ }
+
+ node = elem;
+
+ case "last":
+ while ( (node = node.nextSibling) ) {
+ if ( node.nodeType === 1 ) {
+ return false;
+ }
+ }
+
+ return true;
+
+ case "nth":
+ first = match[2];
+ last = match[3];
+
+ if ( first === 1 && last === 0 ) {
+ return true;
+ }
+
+ doneName = match[0];
+ parent = elem.parentNode;
+
+ if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
+ count = 0;
+
+ for ( node = parent.firstChild; node; node = node.nextSibling ) {
+ if ( node.nodeType === 1 ) {
+ node.nodeIndex = ++count;
+ }
+ }
+
+ parent[ expando ] = doneName;
+ }
+
+ diff = elem.nodeIndex - last;
+
+ if ( first === 0 ) {
+ return diff === 0;
+
+ } else {
+ return ( diff % first === 0 && diff / first >= 0 );
+ }
+ }
+ },
+
+ ID: function( elem, match ) {
+ return elem.nodeType === 1 && elem.getAttribute("id") === match;
+ },
+
+ TAG: function( elem, match ) {
+ return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
+ },
+
+ CLASS: function( elem, match ) {
+ return (" " + (elem.className || elem.getAttribute("class")) + " ")
+ .indexOf( match ) > -1;
+ },
+
+ ATTR: function( elem, match ) {
+ var name = match[1],
+ result = Sizzle.attr ?
+ Sizzle.attr( elem, name ) :
+ Expr.attrHandle[ name ] ?
+ Expr.attrHandle[ name ]( elem ) :
+ elem[ name ] != null ?
+ elem[ name ] :
+ elem.getAttribute( name ),
+ value = result + "",
+ type = match[2],
+ check = match[4];
+
+ return result == null ?
+ type === "!=" :
+ !type && Sizzle.attr ?
+ result != null :
+ type === "=" ?
+ value === check :
+ type === "*=" ?
+ value.indexOf(check) >= 0 :
+ type === "~=" ?
+ (" " + value + " ").indexOf(check) >= 0 :
+ !check ?
+ value && result !== false :
+ type === "!=" ?
+ value !== check :
+ type === "^=" ?
+ value.indexOf(check) === 0 :
+ type === "$=" ?
+ value.substr(value.length - check.length) === check :
+ type === "|=" ?
+ value === check || value.substr(0, check.length + 1) === check + "-" :
+ false;
+ },
+
+ POS: function( elem, match, i, array ) {
+ var name = match[2],
+ filter = Expr.setFilters[ name ];
+
+ if ( filter ) {
+ return filter( elem, i, match, array );
+ }
+ }
+ }
+};
+
+var origPOS = Expr.match.POS,
+ fescape = function(all, num){
+ return "\\" + (num - 0 + 1);
+ };
+
+for ( var type in Expr.match ) {
+ Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+ Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+ array = Array.prototype.slice.call( array, 0 );
+
+ if ( results ) {
+ results.push.apply( results, array );
+ return results;
+ }
+
+ return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+ Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+ makeArray = function( array, results ) {
+ var i = 0,
+ ret = results || [];
+
+ if ( toString.call(array) === "[object Array]" ) {
+ Array.prototype.push.apply( ret, array );
+
+ } else {
+ if ( typeof array.length === "number" ) {
+ for ( var l = array.length; i < l; i++ ) {
+ ret.push( array[i] );
+ }
+
+ } else {
+ for ( ; array[i]; i++ ) {
+ ret.push( array[i] );
+ }
+ }
+ }
+
+ return ret;
+ };
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+ return a.compareDocumentPosition ? -1 : 1;
+ }
+
+ return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+ };
+
+} else {
+ sortOrder = function( a, b ) {
+ // The nodes are identical, we can exit early
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Fallback to using sourceIndex (in IE) if it's available on both nodes
+ } else if ( a.sourceIndex && b.sourceIndex ) {
+ return a.sourceIndex - b.sourceIndex;
+ }
+
+ var al, bl,
+ ap = [],
+ bp = [],
+ aup = a.parentNode,
+ bup = b.parentNode,
+ cur = aup;
+
+ // If the nodes are siblings (or identical) we can do a quick check
+ if ( aup === bup ) {
+ return siblingCheck( a, b );
+
+ // If no parents were found then the nodes are disconnected
+ } else if ( !aup ) {
+ return -1;
+
+ } else if ( !bup ) {
+ return 1;
+ }
+
+ // Otherwise they're somewhere else in the tree so we need
+ // to build up a full list of the parentNodes for comparison
+ while ( cur ) {
+ ap.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ cur = bup;
+
+ while ( cur ) {
+ bp.unshift( cur );
+ cur = cur.parentNode;
+ }
+
+ al = ap.length;
+ bl = bp.length;
+
+ // Start walking down the tree looking for a discrepancy
+ for ( var i = 0; i < al && i < bl; i++ ) {
+ if ( ap[i] !== bp[i] ) {
+ return siblingCheck( ap[i], bp[i] );
+ }
+ }
+
+ // We ended someplace up the tree so do a sibling check
+ return i === al ?
+ siblingCheck( a, bp[i], -1 ) :
+ siblingCheck( ap[i], b, 1 );
+ };
+
+ siblingCheck = function( a, b, ret ) {
+ if ( a === b ) {
+ return ret;
+ }
+
+ var cur = a.nextSibling;
+
+ while ( cur ) {
+ if ( cur === b ) {
+ return -1;
+ }
+
+ cur = cur.nextSibling;
+ }
+
+ return 1;
+ };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+ // We're going to inject a fake input element with a specified name
+ var form = document.createElement("div"),
+ id = "script" + (new Date()).getTime(),
+ root = document.documentElement;
+
+ form.innerHTML = "<a name='" + id + "'/>";
+
+ // Inject it into the root element, check its status, and remove it quickly
+ root.insertBefore( form, root.firstChild );
+
+ // The workaround has to do additional checks after a getElementById
+ // Which slows things down for other browsers (hence the branching)
+ if ( document.getElementById( id ) ) {
+ Expr.find.ID = function( match, context, isXML ) {
+ if ( typeof context.getElementById !== "undefined" && !isXML ) {
+ var m = context.getElementById(match[1]);
+
+ return m ?
+ m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+ [m] :
+ undefined :
+ [];
+ }
+ };
+
+ Expr.filter.ID = function( elem, match ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+ return elem.nodeType === 1 && node && node.nodeValue === match;
+ };
+ }
+
+ root.removeChild( form );
+
+ // release memory in IE
+ root = form = null;
+})();
+
+(function(){
+ // Check to see if the browser returns only elements
+ // when doing getElementsByTagName("*")
+
+ // Create a fake element
+ var div = document.createElement("div");
+ div.appendChild( document.createComment("") );
+
+ // Make sure no comments are found
+ if ( div.getElementsByTagName("*").length > 0 ) {
+ Expr.find.TAG = function( match, context ) {
+ var results = context.getElementsByTagName( match[1] );
+
+ // Filter out possible comments
+ if ( match[1] === "*" ) {
+ var tmp = [];
+
+ for ( var i = 0; results[i]; i++ ) {
+ if ( results[i].nodeType === 1 ) {
+ tmp.push( results[i] );
+ }
+ }
+
+ results = tmp;
+ }
+
+ return results;
+ };
+ }
+
+ // Check to see if an attribute returns normalized href attributes
+ div.innerHTML = "<a href='#'></a>";
+
+ if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+ div.firstChild.getAttribute("href") !== "#" ) {
+
+ Expr.attrHandle.href = function( elem ) {
+ return elem.getAttribute( "href", 2 );
+ };
+ }
+
+ // release memory in IE
+ div = null;
+})();
+
+if ( document.querySelectorAll ) {
+ (function(){
+ var oldSizzle = Sizzle,
+ div = document.createElement("div"),
+ id = "__sizzle__";
+
+ div.innerHTML = "<p class='TEST'></p>";
+
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode.
+ if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+ return;
+ }
+
+ Sizzle = function( query, context, extra, seed ) {
+ context = context || document;
+
+ // Only use querySelectorAll on non-XML documents
+ // (ID selectors don't work in non-HTML documents)
+ if ( !seed && !Sizzle.isXML(context) ) {
+ // See if we find a selector to speed up
+ var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
+
+ if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
+ // Speed-up: Sizzle("TAG")
+ if ( match[1] ) {
+ return makeArray( context.getElementsByTagName( query ), extra );
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
+ return makeArray( context.getElementsByClassName( match[2] ), extra );
+ }
+ }
+
+ if ( context.nodeType === 9 ) {
+ // Speed-up: Sizzle("body")
+ // The body element only exists once, optimize finding it
+ if ( query === "body" && context.body ) {
+ return makeArray( [ context.body ], extra );
+
+ // Speed-up: Sizzle("#ID")
+ } else if ( match && match[3] ) {
+ var elem = context.getElementById( match[3] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id === match[3] ) {
+ return makeArray( [ elem ], extra );
+ }
+
+ } else {
+ return makeArray( [], extra );
+ }
+ }
+
+ try {
+ return makeArray( context.querySelectorAll(query), extra );
+ } catch(qsaError) {}
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ var oldContext = context,
+ old = context.getAttribute( "id" ),
+ nid = old || id,
+ hasParent = context.parentNode,
+ relativeHierarchySelector = /^\s*[+~]/.test( query );
+
+ if ( !old ) {
+ context.setAttribute( "id", nid );
+ } else {
+ nid = nid.replace( /'/g, "\\$&" );
+ }
+ if ( relativeHierarchySelector && hasParent ) {
+ context = context.parentNode;
+ }
+
+ try {
+ if ( !relativeHierarchySelector || hasParent ) {
+ return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+ }
+
+ } catch(pseudoError) {
+ } finally {
+ if ( !old ) {
+ oldContext.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+
+ return oldSizzle(query, context, extra, seed);
+ };
+
+ for ( var prop in oldSizzle ) {
+ Sizzle[ prop ] = oldSizzle[ prop ];
+ }
+
+ // release memory in IE
+ div = null;
+ })();
+}
+
+(function(){
+ var html = document.documentElement,
+ matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
+
+ if ( matches ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9 fails this)
+ var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
+ pseudoWorks = false;
+
+ try {
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( document.documentElement, "[test!='']:sizzle" );
+
+ } catch( pseudoError ) {
+ pseudoWorks = true;
+ }
+
+ Sizzle.matchesSelector = function( node, expr ) {
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+ if ( !Sizzle.isXML( node ) ) {
+ try {
+ if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+ var ret = matches.call( node, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || !disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9, so check for that
+ node.document && node.document.nodeType !== 11 ) {
+ return ret;
+ }
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle(expr, null, null, [node]).length > 0;
+ };
+ }
+})();
+
+(function(){
+ var div = document.createElement("div");
+
+ div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+ // Opera can't find a second classname (in 9.6)
+ // Also, make sure that getElementsByClassName actually exists
+ if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+ return;
+ }
+
+ // Safari caches class attributes, doesn't catch changes (in 3.2)
+ div.lastChild.className = "e";
+
+ if ( div.getElementsByClassName("e").length === 1 ) {
+ return;
+ }
+
+ Expr.order.splice(1, 0, "CLASS");
+ Expr.find.CLASS = function( match, context, isXML ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+ return context.getElementsByClassName(match[1]);
+ }
+ };
+
+ // release memory in IE
+ div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 && !isXML ){
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( elem.nodeName.toLowerCase() === cur ) {
+ match = elem;
+ break;
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+ for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+ var elem = checkSet[i];
+
+ if ( elem ) {
+ var match = false;
+
+ elem = elem[dir];
+
+ while ( elem ) {
+ if ( elem[ expando ] === doneName ) {
+ match = checkSet[elem.sizset];
+ break;
+ }
+
+ if ( elem.nodeType === 1 ) {
+ if ( !isXML ) {
+ elem[ expando ] = doneName;
+ elem.sizset = i;
+ }
+
+ if ( typeof cur !== "string" ) {
+ if ( elem === cur ) {
+ match = true;
+ break;
+ }
+
+ } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+ match = elem;
+ break;
+ }
+ }
+
+ elem = elem[dir];
+ }
+
+ checkSet[i] = match;
+ }
+ }
+}
+
+if ( document.documentElement.contains ) {
+ Sizzle.contains = function( a, b ) {
+ return a !== b && (a.contains ? a.contains(b) : true);
+ };
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+ Sizzle.contains = function( a, b ) {
+ return !!(a.compareDocumentPosition(b) & 16);
+ };
+
+} else {
+ Sizzle.contains = function() {
+ return false;
+ };
+}
+
+Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context, seed ) {
+ var match,
+ tmpSet = [],
+ later = "",
+ root = context.nodeType ? [context] : context;
+
+ // Position selectors must be done after the filter
+ // And so must :not(positional) so we move all PSEUDOs to the end
+ while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+ later += match[0];
+ selector = selector.replace( Expr.match.PSEUDO, "" );
+ }
+
+ selector = Expr.relative[selector] ? selector + "*" : selector;
+
+ for ( var i = 0, l = root.length; i < l; i++ ) {
+ Sizzle( selector, root[i], tmpSet, seed );
+ }
+
+ return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+Sizzle.selectors.attrMap = {};
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+ rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+ // Note: This RegExp should be improved, or likely pulled from Sizzle
+ rmultiselector = /,/,
+ isSimple = /^.[^:#\[\.,]*$/,
+ slice = Array.prototype.slice,
+ POS = jQuery.expr.match.POS,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var self = this,
+ i, l;
+
+ if ( typeof selector !== "string" ) {
+ return jQuery( selector ).filter(function() {
+ for ( i = 0, l = self.length; i < l; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ });
+ }
+
+ var ret = this.pushStack( "", "find", selector ),
+ length, n, r;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ length = ret.length;
+ jQuery.find( selector, this[i], ret );
+
+ if ( i > 0 ) {
+ // Make sure that the results are unique
+ for ( n = length; n < ret.length; n++ ) {
+ for ( r = 0; r < length; r++ ) {
+ if ( ret[r] === ret[n] ) {
+ ret.splice(n--, 1);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ has: function( target ) {
+ var targets = jQuery( target );
+ return this.filter(function() {
+ for ( var i = 0, l = targets.length; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector, false), "not", selector);
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector, true), "filter", selector );
+ },
+
+ is: function( selector ) {
+ return !!selector && (
+ typeof selector === "string" ?
+ // If this is a positional selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ POS.test( selector ) ?
+ jQuery( selector, this.context ).index( this[0] ) >= 0 :
+ jQuery.filter( selector, this ).length > 0 :
+ this.filter( selector ).length > 0 );
+ },
+
+ closest: function( selectors, context ) {
+ var ret = [], i, l, cur = this[0];
+
+ // Array (deprecated as of jQuery 1.7)
+ if ( jQuery.isArray( selectors ) ) {
+ var level = 1;
+
+ while ( cur && cur.ownerDocument && cur !== context ) {
+ for ( i = 0; i < selectors.length; i++ ) {
+
+ if ( jQuery( cur ).is( selectors[ i ] ) ) {
+ ret.push({ selector: selectors[ i ], elem: cur, level: level });
+ }
+ }
+
+ cur = cur.parentNode;
+ level++;
+ }
+
+ return ret;
+ }
+
+ // String
+ var pos = POS.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( i = 0, l = this.length; i < l; i++ ) {
+ cur = this[i];
+
+ while ( cur ) {
+ if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+ ret.push( cur );
+ break;
+
+ } else {
+ cur = cur.parentNode;
+ if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
+ break;
+ }
+ }
+ }
+ }
+
+ ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+ return this.pushStack( ret, "closest", selectors );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+ all :
+ jQuery.unique( all ) );
+ },
+
+ andSelf: function() {
+ return this.add( this.prevObject );
+ }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+ return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return jQuery.nth( elem, 2, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return jQuery.nth( elem, 2, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( elem.parentNode.firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.makeArray( elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until ),
+ // The variable 'args' was introduced in
+ // https://github.com/jquery/jquery/commit/52a0238
+ // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
+ // http://code.google.com/p/v8/issues/detail?id=1050
+ args = slice.call(arguments);
+
+ if ( !runtil.test( name ) ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+ if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+
+ return this.pushStack( ret, name, args.join(",") );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 ?
+ jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+ jQuery.find.matches(expr, elems);
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ nth: function( cur, result, dir, elem ) {
+ result = result || 1;
+ var num = 0;
+
+ for ( ; cur; cur = cur[dir] ) {
+ if ( cur.nodeType === 1 && ++num === result ) {
+ break;
+ }
+ }
+
+ return cur;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+ // Can't pass null or undefined to indexOf in Firefox 4
+ // Set to 0 to skip string check
+ qualifier = qualifier || 0;
+
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ var retVal = !!qualifier.call( elem, i, elem );
+ return retVal === keep;
+ });
+
+ } else if ( qualifier.nodeType ) {
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( elem === qualifier ) === keep;
+ });
+
+ } else if ( typeof qualifier === "string" ) {
+ var filtered = jQuery.grep(elements, function( elem ) {
+ return elem.nodeType === 1;
+ });
+
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter(qualifier, filtered, !keep);
+ } else {
+ qualifier = jQuery.filter( qualifier, filtered );
+ }
+ }
+
+ return jQuery.grep(elements, function( elem, i ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+ });
+}
+
+
+
+
+function createSafeFragment( document ) {
+ var list = nodeNames.split( " " ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr article aside audio canvas datalist details figcaption figure footer " +
+ "header hgroup mark meter nav output progress section summary time video",
+ rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style)/i,
+ rnocache = /<(?:script|object|embed|option|style)/i,
+ rnoshimcache = new RegExp("<(?:" + nodeNames.replace(" ", "|") + ")", "i"),
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /\/(java|ecma)script/i,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ area: [ 1, "<map>", "</map>" ],
+ _default: [ 0, "", "" ]
+ },
+ safeFragment = createSafeFragment( document );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+ wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+ text: function( text ) {
+ if ( jQuery.isFunction(text) ) {
+ return this.each(function(i) {
+ var self = jQuery( this );
+
+ self.text( text.call(this, i, self.text()) );
+ });
+ }
+
+ if ( typeof text !== "object" && text !== undefined ) {
+ return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+ }
+
+ return jQuery.text( this );
+ },
+
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ return this.each(function() {
+ jQuery( this ).wrapAll( html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ },
+
+ append: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip(arguments, true, function( elem ) {
+ if ( this.nodeType === 1 ) {
+ this.insertBefore( elem, this.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this );
+ });
+ } else if ( arguments.length ) {
+ var set = jQuery(arguments[0]);
+ set.push.apply( set, this.toArray() );
+ return this.pushStack( set, "before", arguments );
+ }
+ },
+
+ after: function() {
+ if ( this[0] && this[0].parentNode ) {
+ return this.domManip(arguments, false, function( elem ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ });
+ } else if ( arguments.length ) {
+ var set = this.pushStack( this, "after", arguments );
+ set.push.apply( set, jQuery(arguments[0]).toArray() );
+ return set;
+ }
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ jQuery.cleanData( [ elem ] );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( elem.getElementsByTagName("*") );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ if ( value === undefined ) {
+ return this[0] && this[0].nodeType === 1 ?
+ this[0].innerHTML.replace(rinlinejQuery, "") :
+ null;
+
+ // See if we can take a shortcut and just use innerHTML
+ } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+ !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+ value = value.replace(rxhtmlTag, "<$1></$2>");
+
+ try {
+ for ( var i = 0, l = this.length; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( this[i].nodeType === 1 ) {
+ jQuery.cleanData( this[i].getElementsByTagName("*") );
+ this[i].innerHTML = value;
+ }
+ }
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {
+ this.empty().append( value );
+ }
+
+ } else if ( jQuery.isFunction( value ) ) {
+ this.each(function(i){
+ var self = jQuery( this );
+
+ self.html( value.call(this, i, self.html()) );
+ });
+
+ } else {
+ this.empty().append( value );
+ }
+
+ return this;
+ },
+
+ replaceWith: function( value ) {
+ if ( this[0] && this[0].parentNode ) {
+ // Make sure that the elements are removed from the DOM before they are inserted
+ // this can help fix replacing a parent with child elements
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function(i) {
+ var self = jQuery(this), old = self.html();
+ self.replaceWith( value.call( this, i, old ) );
+ });
+ }
+
+ if ( typeof value !== "string" ) {
+ value = jQuery( value ).detach();
+ }
+
+ return this.each(function() {
+ var next = this.nextSibling,
+ parent = this.parentNode;
+
+ jQuery( this ).remove();
+
+ if ( next ) {
+ jQuery(next).before( value );
+ } else {
+ jQuery(parent).append( value );
+ }
+ });
+ } else {
+ return this.length ?
+ this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+ this;
+ }
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, table, callback ) {
+ var results, first, fragment, parent,
+ value = args[0],
+ scripts = [];
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+ return this.each(function() {
+ jQuery(this).domManip( args, table, callback, true );
+ });
+ }
+
+ if ( jQuery.isFunction(value) ) {
+ return this.each(function(i) {
+ var self = jQuery(this);
+ args[0] = value.call(this, i, table ? self.html() : undefined);
+ self.domManip( args, table, callback );
+ });
+ }
+
+ if ( this[0] ) {
+ parent = value && value.parentNode;
+
+ // If we're in a fragment, just use that instead of building a new one
+ if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+ results = { fragment: parent };
+
+ } else {
+ results = jQuery.buildFragment( args, this, scripts );
+ }
+
+ fragment = results.fragment;
+
+ if ( fragment.childNodes.length === 1 ) {
+ first = fragment = fragment.firstChild;
+ } else {
+ first = fragment.firstChild;
+ }
+
+ if ( first ) {
+ table = table && jQuery.nodeName( first, "tr" );
+
+ for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
+ callback.call(
+ table ?
+ root(this[i], first) :
+ this[i],
+ // Make sure that we do not leak memory by inadvertently discarding
+ // the original fragment (which might have attached data) instead of
+ // using it; in addition, use the original fragment object for the last
+ // item instead of first because it can end up being emptied incorrectly
+ // in certain situations (Bug #8070).
+ // Fragments from the fragment cache must always be cloned and never used
+ // in place.
+ results.cacheable || ( l > 1 && i < lastIndex ) ?
+ jQuery.clone( fragment, true, true ) :
+ fragment
+ );
+ }
+ }
+
+ if ( scripts.length ) {
+ jQuery.each( scripts, evalScript );
+ }
+ }
+
+ return this;
+ }
+});
+
+function root( elem, cur ) {
+ return jQuery.nodeName(elem, "table") ?
+ (elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+ elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function cloneFixAttributes( src, dest ) {
+ var nodeName;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // clearAttributes removes the attributes, which we don't want,
+ // but also removes the attachEvent events, which we *do* want
+ if ( dest.clearAttributes ) {
+ dest.clearAttributes();
+ }
+
+ // mergeAttributes, in contrast, only merges back on the
+ // original attributes, not the events
+ if ( dest.mergeAttributes ) {
+ dest.mergeAttributes( src );
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 fail to clone children inside object elements that use
+ // the proprietary classid attribute value (rather than the type
+ // attribute) to identify the type of content to display
+ if ( nodeName === "object" ) {
+ dest.outerHTML = src.outerHTML;
+
+ } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+ if ( src.checked ) {
+ dest.defaultChecked = dest.checked = src.checked;
+ }
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+
+ // Event data gets referenced instead of copied if the expando
+ // gets copied too
+ dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+ var fragment, cacheable, cacheresults, doc,
+ first = args[ 0 ];
+
+ // nodes may contain either an explicit document object,
+ // a jQuery collection or context object.
+ // If nodes[0] contains a valid object to assign to doc
+ if ( nodes && nodes[0] ) {
+ doc = nodes[0].ownerDocument || nodes[0];
+ }
+
+ // Ensure that an attr object doesn't incorrectly stand in as a document object
+ // Chrome and Firefox seem to allow this to occur and will throw exception
+ // Fixes #8950
+ if ( !doc.createDocumentFragment ) {
+ doc = document;
+ }
+
+ // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+ // Cloning options loses the selected state, so don't cache them
+ // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+ // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+ // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+ if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
+ first.charAt(0) === "<" && !rnocache.test( first ) &&
+ (jQuery.support.checkClone || !rchecked.test( first )) &&
+ (!jQuery.support.unknownElems && rnoshimcache.test( first )) ) {
+
+ cacheable = true;
+
+ cacheresults = jQuery.fragments[ first ];
+ if ( cacheresults && cacheresults !== 1 ) {
+ fragment = cacheresults;
+ }
+ }
+
+ if ( !fragment ) {
+ fragment = doc.createDocumentFragment();
+ jQuery.clean( args, doc, fragment, scripts );
+ }
+
+ if ( cacheable ) {
+ jQuery.fragments[ first ] = cacheresults ? fragment : 1;
+ }
+
+ return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var ret = [],
+ insert = jQuery( selector ),
+ parent = this.length === 1 && this[0].parentNode;
+
+ if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+ insert[ original ]( this[0] );
+ return this;
+
+ } else {
+ for ( var i = 0, l = insert.length; i < l; i++ ) {
+ var elems = ( i > 0 ? this.clone(true) : this ).get();
+ jQuery( insert[i] )[ original ]( elems );
+ ret = ret.concat( elems );
+ }
+
+ return this.pushStack( ret, name, insert.selector );
+ }
+ };
+});
+
+function getAll( elem ) {
+ if ( typeof elem.getElementsByTagName !== "undefined" ) {
+ return elem.getElementsByTagName( "*" );
+
+ } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+ return elem.querySelectorAll( "*" );
+
+ } else {
+ return [];
+ }
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( elem.type === "checkbox" || elem.type === "radio" ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+// Finds all inputs and passes them to fixDefaultChecked
+function findInputs( elem ) {
+ var nodeName = ( elem.nodeName || "" ).toLowerCase();
+ if ( nodeName === "input" ) {
+ fixDefaultChecked( elem );
+ // Skip scripts, get other children
+ } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
+ jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+ }
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var clone = elem.cloneNode(true),
+ srcElements,
+ destElements,
+ i;
+
+ if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+ // IE copies events bound via attachEvent when using cloneNode.
+ // Calling detachEvent on the clone will also remove the events
+ // from the original. In order to get around this, we use some
+ // proprietary methods to clear the events. Thanks to MooTools
+ // guys for this hotness.
+
+ cloneFixAttributes( elem, clone );
+
+ // Using Sizzle here is crazy slow, so we use getElementsByTagName
+ // instead
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ // Weird iteration because IE will replace the length property
+ // with an element if you are cloning the body and one of the
+ // elements on the page has a name or id of "length"
+ for ( i = 0; srcElements[i]; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ cloneFixAttributes( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ cloneCopyEvent( elem, clone );
+
+ if ( deepDataAndEvents ) {
+ srcElements = getAll( elem );
+ destElements = getAll( clone );
+
+ for ( i = 0; srcElements[i]; ++i ) {
+ cloneCopyEvent( srcElements[i], destElements[i] );
+ }
+ }
+ }
+
+ srcElements = destElements = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ clean: function( elems, context, fragment, scripts ) {
+ var checkScriptType;
+
+ context = context || document;
+
+ // !context.createElement fails in IE with an error but returns typeof 'object'
+ if ( typeof context.createElement === "undefined" ) {
+ context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+ }
+
+ var ret = [], j;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( typeof elem === "number" ) {
+ elem += "";
+ }
+
+ if ( !elem ) {
+ continue;
+ }
+
+ // Convert html string into DOM nodes
+ if ( typeof elem === "string" ) {
+ if ( !rhtml.test( elem ) ) {
+ elem = context.createTextNode( elem );
+ } else {
+ // Fix "XHTML"-style tags in all browsers
+ elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+ // Trim whitespace, otherwise indexOf won't work as expected
+ var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
+ wrap = wrapMap[ tag ] || wrapMap._default,
+ depth = wrap[0],
+ div = context.createElement("div");
+
+ // Append wrapper element to unknown element safe doc fragment
+ if ( context === document ) {
+ // Use the fragment we've already created for this document
+ safeFragment.appendChild( div );
+ } else {
+ // Use a fragment created with the owner document
+ createSafeFragment( context ).appendChild( div );
+ }
+
+ // Go to html and back, then peel off extra wrappers
+ div.innerHTML = wrap[1] + elem + wrap[2];
+
+ // Move to the right depth
+ while ( depth-- ) {
+ div = div.lastChild;
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !jQuery.support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ var hasBody = rtbody.test(elem),
+ tbody = tag === "table" && !hasBody ?
+ div.firstChild && div.firstChild.childNodes :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !hasBody ?
+ div.childNodes :
+ [];
+
+ for ( j = tbody.length - 1; j >= 0 ; --j ) {
+ if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+ tbody[ j ].parentNode.removeChild( tbody[ j ] );
+ }
+ }
+ }
+
+ // IE completely kills leading whitespace when innerHTML is used
+ if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+ }
+
+ elem = div.childNodes;
+ }
+ }
+
+ // Resets defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ var len;
+ if ( !jQuery.support.appendChecked ) {
+ if ( elem[0] && typeof (len = elem.length) === "number" ) {
+ for ( j = 0; j < len; j++ ) {
+ findInputs( elem[j] );
+ }
+ } else {
+ findInputs( elem );
+ }
+ }
+
+ if ( elem.nodeType ) {
+ ret.push( elem );
+ } else {
+ ret = jQuery.merge( ret, elem );
+ }
+ }
+
+ if ( fragment ) {
+ checkScriptType = function( elem ) {
+ return !elem.type || rscriptType.test( elem.type );
+ };
+ for ( i = 0; ret[i]; i++ ) {
+ if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+ scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+
+ } else {
+ if ( ret[i].nodeType === 1 ) {
+ var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
+
+ ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+ }
+ fragment.appendChild( ret[i] );
+ }
+ }
+ }
+
+ return ret;
+ },
+
+ cleanData: function( elems ) {
+ var data, id,
+ cache = jQuery.cache,
+ special = jQuery.event.special,
+ deleteExpando = jQuery.support.deleteExpando;
+
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+ continue;
+ }
+
+ id = elem[ jQuery.expando ];
+
+ if ( id ) {
+ data = cache[ id ];
+
+ if ( data && data.events ) {
+ for ( var type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+
+ // Null the DOM reference to avoid IE6/7/8 leak (#7054)
+ if ( data.handle ) {
+ data.handle.elem = null;
+ }
+ }
+
+ if ( deleteExpando ) {
+ delete elem[ jQuery.expando ];
+
+ } else if ( elem.removeAttribute ) {
+ elem.removeAttribute( jQuery.expando );
+ }
+
+ delete cache[ id ];
+ }
+ }
+ }
+});
+
+function evalScript( i, elem ) {
+ if ( elem.src ) {
+ jQuery.ajax({
+ url: elem.src,
+ async: false,
+ dataType: "script"
+ });
+ } else {
+ jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
+ }
+
+ if ( elem.parentNode ) {
+ elem.parentNode.removeChild( elem );
+ }
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity=([^)]*)/,
+ // fixed for IE9, see #8346
+ rupper = /([A-Z]|^ms)/g,
+ rnumpx = /^-?\d+(?:px)?$/i,
+ rnum = /^-?\d/,
+ rrelNum = /^([\-+])=([\-+.\de]+)/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssWidth = [ "Left", "Right" ],
+ cssHeight = [ "Top", "Bottom" ],
+ curCSS,
+
+ getComputedStyle,
+ currentStyle;
+
+jQuery.fn.css = function( name, value ) {
+ // Setting 'undefined' is a no-op
+ if ( arguments.length === 2 && value === undefined ) {
+ return this;
+ }
+
+ return jQuery.access( this, name, value, true, function( elem, name, value ) {
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ });
+};
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity", "opacity" );
+ return ret === "" ? "1" : ret;
+
+ } else {
+ return elem.style.opacity;
+ }
+ }
+ }
+ },
+
+ // Exclude the following css properties to add px
+ cssNumber: {
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, origName = jQuery.camelCase( name ),
+ style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+ name = jQuery.cssProps[ origName ] || origName;
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+ // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+ // Fixes bug #5509
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra ) {
+ var ret, hooks;
+
+ // Make sure that we're working with the right name
+ name = jQuery.camelCase( name );
+ hooks = jQuery.cssHooks[ name ];
+ name = jQuery.cssProps[ name ] || name;
+
+ // cssFloat needs a special treatment
+ if ( name === "cssFloat" ) {
+ name = "float";
+ }
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+ return ret;
+
+ // Otherwise, if a way to get the computed value exists, use that
+ } else if ( curCSS ) {
+ return curCSS( elem, name );
+ }
+ },
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations
+ swap: function( elem, options, callback ) {
+ var old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( var name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ callback.call( elem );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+ }
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ var val;
+
+ if ( computed ) {
+ if ( elem.offsetWidth !== 0 ) {
+ return getWH( elem, name, extra );
+ } else {
+ jQuery.swap( elem, cssShow, function() {
+ val = getWH( elem, name, extra );
+ });
+ }
+
+ return val;
+ }
+ },
+
+ set: function( elem, value ) {
+ if ( rnumpx.test( value ) ) {
+ // ignore negative width and height values #1599
+ value = parseFloat( value );
+
+ if ( value >= 0 ) {
+ return value + "px";
+ }
+
+ } else {
+ return value;
+ }
+ }
+ };
+});
+
+if ( !jQuery.support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( parseFloat( RegExp.$1 ) / 100 ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there there is no filter style applied in a css rule, we are done
+ if ( currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+jQuery(function() {
+ // This hook cannot be added until DOM ready because the support test
+ // for it is not run until after DOM ready
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ var ret;
+ jQuery.swap( elem, { "display": "inline-block" }, function() {
+ if ( computed ) {
+ ret = curCSS( elem, "margin-right", "marginRight" );
+ } else {
+ ret = elem.style.marginRight;
+ }
+ });
+ return ret;
+ }
+ };
+ }
+});
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+ getComputedStyle = function( elem, name ) {
+ var ret, defaultView, computedStyle;
+
+ name = name.replace( rupper, "-$1" ).toLowerCase();
+
+ if ( !(defaultView = elem.ownerDocument.defaultView) ) {
+ return undefined;
+ }
+
+ if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+ ret = computedStyle.getPropertyValue( name );
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+ }
+
+ return ret;
+ };
+}
+
+if ( document.documentElement.currentStyle ) {
+ currentStyle = function( elem, name ) {
+ var left, rsLeft, uncomputed,
+ ret = elem.currentStyle && elem.currentStyle[ name ],
+ style = elem.style;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret === null && style && (uncomputed = style[ name ]) ) {
+ ret = uncomputed;
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ( ret || 0 );
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ elem.runtimeStyle.left = rsLeft;
+ }
+ }
+
+ return ret === "" ? "auto" : ret;
+ };
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+
+ // Start with offset property
+ var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ which = name === "width" ? cssWidth : cssHeight;
+
+ if ( val > 0 ) {
+ if ( extra !== "border" ) {
+ jQuery.each( which, function() {
+ if ( !extra ) {
+ val -= parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
+ } else {
+ val -= parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
+ }
+ });
+ }
+
+ return val + "px";
+ }
+
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, name );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ] || 0;
+ }
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+
+ // Add padding, border, margin
+ if ( extra ) {
+ jQuery.each( which, function() {
+ val += parseFloat( jQuery.css( elem, "padding" + this ) ) || 0;
+ if ( extra !== "padding" ) {
+ val += parseFloat( jQuery.css( elem, "border" + this + "Width" ) ) || 0;
+ }
+ if ( extra === "margin" ) {
+ val += parseFloat( jQuery.css( elem, extra + this ) ) || 0;
+ }
+ });
+ }
+
+ return val + "px";
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ var width = elem.offsetWidth,
+ height = elem.offsetHeight;
+
+ return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rhash = /#.*$/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rquery = /\?/,
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ rselectTextarea = /^(?:select|textarea)/i,
+ rspacesAjax = /\s+/,
+ rts = /([?&])_=[^&]*/,
+ rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Document location
+ ajaxLocation,
+
+ // Document location segments
+ ajaxLocParts,
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = ["*/"] + ["*"];
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ if ( jQuery.isFunction( func ) ) {
+ var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
+ i = 0,
+ length = dataTypes.length,
+ dataType,
+ list,
+ placeBefore;
+
+ // For each dataType in the dataTypeExpression
+ for ( ; i < length; i++ ) {
+ dataType = dataTypes[ i ];
+ // We control if we're asked to add before
+ // any existing element
+ placeBefore = /^\+/.test( dataType );
+ if ( placeBefore ) {
+ dataType = dataType.substr( 1 ) || "*";
+ }
+ list = structure[ dataType ] = structure[ dataType ] || [];
+ // then we add to the structure accordingly
+ list[ placeBefore ? "unshift" : "push" ]( func );
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+ dataType /* internal */, inspected /* internal */ ) {
+
+ dataType = dataType || options.dataTypes[ 0 ];
+ inspected = inspected || {};
+
+ inspected[ dataType ] = true;
+
+ var list = structure[ dataType ],
+ i = 0,
+ length = list ? list.length : 0,
+ executeOnly = ( structure === prefilters ),
+ selection;
+
+ for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+ selection = list[ i ]( options, originalOptions, jqXHR );
+ // If we got redirected to another dataType
+ // we try there if executing only and not done already
+ if ( typeof selection === "string" ) {
+ if ( !executeOnly || inspected[ selection ] ) {
+ selection = undefined;
+ } else {
+ options.dataTypes.unshift( selection );
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, selection, inspected );
+ }
+ }
+ }
+ // If we're only executing or nothing was selected
+ // we try the catchall dataType if not done already
+ if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+ selection = inspectPrefiltersOrTransports(
+ structure, options, originalOptions, jqXHR, "*", inspected );
+ }
+ // unnecessary when only executing (prefilters)
+ // but it'll be ignored by the caller in that case
+ return selection;
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+}
+
+jQuery.fn.extend({
+ load: function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+
+ // Don't do a request if no elements are being requested
+ } else if ( !this.length ) {
+ return this;
+ }
+
+ var off = url.indexOf( " " );
+ if ( off >= 0 ) {
+ var selector = url.slice( off, url.length );
+ url = url.slice( 0, off );
+ }
+
+ // Default to a GET request
+ var type = "GET";
+
+ // If the second parameter was provided
+ if ( params ) {
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( typeof params === "object" ) {
+ params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+ type = "POST";
+ }
+ }
+
+ var self = this;
+
+ // Request the remote document
+ jQuery.ajax({
+ url: url,
+ type: type,
+ dataType: "html",
+ data: params,
+ // Complete callback (responseText is used internally)
+ complete: function( jqXHR, status, responseText ) {
+ // Store the response as specified by the jqXHR object
+ responseText = jqXHR.responseText;
+ // If successful, inject the HTML into all the matched elements
+ if ( jqXHR.isResolved() ) {
+ // #4825: Get the actual response in case
+ // a dataFilter is present in ajaxSettings
+ jqXHR.done(function( r ) {
+ responseText = r;
+ });
+ // See if a selector was specified
+ self.html( selector ?
+ // Create a dummy div to hold the results
+ jQuery("<div>")
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(responseText.replace(rscript, ""))
+
+ // Locate the specified elements
+ .find(selector) :
+
+ // If not, just inject the full result
+ responseText );
+ }
+
+ if ( callback ) {
+ self.each( callback, [ responseText, status, jqXHR ] );
+ }
+ }
+ });
+
+ return this;
+ },
+
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+
+ serializeArray: function() {
+ return this.map(function(){
+ return this.elements ? jQuery.makeArray( this.elements ) : this;
+ })
+ .filter(function(){
+ return this.name && !this.disabled &&
+ ( this.checked || rselectTextarea.test( this.nodeName ) ||
+ rinput.test( this.type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val, i ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+ jQuery.fn[ o ] = function( f ){
+ return this.bind( o, f );
+ };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ type: method,
+ url: url,
+ data: data,
+ success: callback,
+ dataType: type
+ });
+ };
+});
+
+jQuery.extend({
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ if ( settings ) {
+ // Building a settings object
+ ajaxExtend( target, jQuery.ajaxSettings );
+ } else {
+ // Extending ajaxSettings
+ settings = target;
+ target = jQuery.ajaxSettings;
+ }
+ ajaxExtend( target, settings );
+ return target;
+ },
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ type: "GET",
+ contentType: "application/x-www-form-urlencoded",
+ processData: true,
+ async: true,
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ xml: "application/xml, text/xml",
+ html: "text/html",
+ text: "text/plain",
+ json: "application/json, text/javascript",
+ "*": allTypes
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText"
+ },
+
+ // List of data converters
+ // 1) key format is "source_type destination_type" (a single space in-between)
+ // 2) the catchall symbol "*" can be used for source_type
+ converters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ context: true,
+ url: true
+ }
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events
+ // It's the callbackContext if one was provided in the options
+ // and if it's a DOM node or a jQuery collection
+ globalEventContext = callbackContext !== s &&
+ ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+ jQuery( callbackContext ) : jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // ifModified key
+ ifModifiedKey,
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+ // transport
+ transport,
+ // timeout handle
+ timeoutTimer,
+ // Cross-domain detection vars
+ parts,
+ // The jqXHR state
+ state = 0,
+ // To know if global events are to be dispatched
+ fireGlobals,
+ // Loop variable
+ i,
+ // Fake xhr
+ jqXHR = {
+
+ readyState: 0,
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( !state ) {
+ var lname = name.toLowerCase();
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match === undefined ? null : match;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ statusText = statusText || "abort";
+ if ( transport ) {
+ transport.abort( statusText );
+ }
+ done( 0, statusText );
+ return this;
+ }
+ };
+
+ // Callback for when everything is done
+ // It is defined here because jslint complains if it is declared
+ // at the end of the function (which would be more logical and readable)
+ function done( status, nativeStatusText, responses, headers ) {
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ var isSuccess,
+ success,
+ error,
+ statusText = nativeStatusText,
+ response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
+ lastModified,
+ etag;
+
+ // If successful, handle type chaining
+ if ( status >= 200 && status < 300 || status === 304 ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+
+ if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
+ jQuery.lastModified[ ifModifiedKey ] = lastModified;
+ }
+ if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
+ jQuery.etag[ ifModifiedKey ] = etag;
+ }
+ }
+
+ // If not modified
+ if ( status === 304 ) {
+
+ statusText = "notmodified";
+ isSuccess = true;
+
+ // If we have data
+ } else {
+
+ try {
+ success = ajaxConvert( s, response );
+ statusText = "success";
+ isSuccess = true;
+ } catch(e) {
+ // We have a parsererror
+ statusText = "parsererror";
+ error = e;
+ }
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( !statusText || status ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = "" + ( nativeStatusText || statusText );
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ // Attach deferreds
+ deferred.promise( jqXHR );
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+ jqXHR.complete = completeDeferred.add;
+
+ // Status-dependent callbacks
+ jqXHR.statusCode = function( map ) {
+ if ( map ) {
+ var tmp;
+ if ( state < 2 ) {
+ for ( tmp in map ) {
+ statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+ }
+ } else {
+ tmp = map[ jqXHR.status ];
+ jqXHR.then( tmp, tmp );
+ }
+ }
+ return this;
+ };
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+
+ // Determine if a cross-domain request is in order
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefiler, stop there
+ if ( state === 2 ) {
+ return false;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Get ifModifiedKey before adding the anti-cache parameter
+ ifModifiedKey = s.url;
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+
+ var ts = jQuery.now(),
+ // try replacing _= if it is there
+ ret = s.url.replace( rts, "$1_=" + ts );
+
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ ifModifiedKey = ifModifiedKey || s.url;
+ if ( jQuery.lastModified[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+ }
+ if ( jQuery.etag[ ifModifiedKey ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+ }
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already
+ jqXHR.abort();
+ return false;
+
+ }
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout( function(){
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch (e) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ jQuery.error( e );
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ param: function( a, traditional ) {
+ var s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : value;
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( var prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+ }
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // If array item is non-scalar (array or object), encode its
+ // numeric index to resolve deserialization ambiguity issues.
+ // Note that rack (as of 1.0.0) can't currently deserialize
+ // nested arrays properly, and attempting to do so may cause
+ // a server error. Possible fixes are to modify rack's
+ // deserialization algorithm or to provide an option or flag
+ // to force array serialization to be shallow.
+ buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && obj != null && typeof obj === "object" ) {
+ // Serialize object item.
+ for ( var name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var contents = s.contents,
+ dataTypes = s.dataTypes,
+ responseFields = s.responseFields,
+ ct,
+ type,
+ finalDataType,
+ firstDataType;
+
+ // Fill responseXXX fields
+ for ( type in responseFields ) {
+ if ( type in responses ) {
+ jqXHR[ responseFields[type] ] = responses[ type ];
+ }
+ }
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+ // Apply the dataFilter if provided
+ if ( s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ var dataTypes = s.dataTypes,
+ converters = {},
+ i,
+ key,
+ length = dataTypes.length,
+ tmp,
+ // Current and previous dataTypes
+ current = dataTypes[ 0 ],
+ prev,
+ // Conversion expression
+ conversion,
+ // Conversion function
+ conv,
+ // Conversion functions (transitive conversion)
+ conv1,
+ conv2;
+
+ // For each dataType in the chain
+ for ( i = 1; i < length; i++ ) {
+
+ // Create converters map
+ // with lowercased keys
+ if ( i === 1 ) {
+ for ( key in s.converters ) {
+ if ( typeof key === "string" ) {
+ converters[ key.toLowerCase() ] = s.converters[ key ];
+ }
+ }
+ }
+
+ // Get the dataTypes
+ prev = current;
+ current = dataTypes[ i ];
+
+ // If current is auto dataType, update it to prev
+ if ( current === "*" ) {
+ current = prev;
+ // If no auto and dataTypes are actually different
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Get the converter
+ conversion = prev + " " + current;
+ conv = converters[ conversion ] || converters[ "* " + current ];
+
+ // If there is no direct converter, search transitively
+ if ( !conv ) {
+ conv2 = undefined;
+ for ( conv1 in converters ) {
+ tmp = conv1.split( " " );
+ if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
+ conv2 = converters[ tmp[1] + " " + current ];
+ if ( conv2 ) {
+ conv1 = converters[ conv1 ];
+ if ( conv1 === true ) {
+ conv = conv2;
+ } else if ( conv2 === true ) {
+ conv = conv1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ // If we found no converter, dispatch an error
+ if ( !( conv || conv2 ) ) {
+ jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+ }
+ // If found converter is not an equivalence
+ if ( conv !== true ) {
+ // Convert with 1 or 2 converters accordingly
+ response = conv ? conv( response ) : conv2( conv1(response) );
+ }
+ }
+ }
+ return response;
+}
+
+
+
+
+var jsc = jQuery.now(),
+ jsre = /(\=)\?(&|$)|\?\?/i;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ return jQuery.expando + "_" + ( jsc++ );
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
+ ( typeof s.data === "string" );
+
+ if ( s.dataTypes[ 0 ] === "jsonp" ||
+ s.jsonp !== false && ( jsre.test( s.url ) ||
+ inspectData && jsre.test( s.data ) ) ) {
+
+ var responseContainer,
+ jsonpCallback = s.jsonpCallback =
+ jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+ previous = window[ jsonpCallback ],
+ url = s.url,
+ data = s.data,
+ replace = "$1" + jsonpCallback + "$2";
+
+ if ( s.jsonp !== false ) {
+ url = url.replace( jsre, replace );
+ if ( s.url === url ) {
+ if ( inspectData ) {
+ data = data.replace( jsre, replace );
+ }
+ if ( s.data === data ) {
+ // Add callback manually
+ url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+ }
+ }
+ }
+
+ s.url = url;
+ s.data = data;
+
+ // Install callback
+ window[ jsonpCallback ] = function( response ) {
+ responseContainer = [ response ];
+ };
+
+ // Clean-up function
+ jqXHR.always(function() {
+ // Set callback back to previous value
+ window[ jsonpCallback ] = previous;
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( previous ) ) {
+ window[ jsonpCallback ]( responseContainer[ 0 ] );
+ }
+ });
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( jsonpCallback + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Delegate to script
+ return "script";
+ }
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /javascript|ecmascript/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement( "script" );
+
+ script.async = "async";
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( head && script.parentNode ) {
+ head.removeChild( script );
+ }
+
+ // Dereference the script
+ script = undefined;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+ // Use insertBefore instead of appendChild to circumvent an IE6 bug.
+ // This arises when a base node is used (#2709 and #4378).
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( 0, 1 );
+ }
+ }
+ };
+ }
+});
+
+
+
+
+var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+ xhrOnUnloadAbort = window.ActiveXObject ? function() {
+ // Abort all pending requests
+ for ( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( 0, 1 );
+ }
+ } : false,
+ xhrId = 0,
+ xhrCallbacks;
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+ } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+ /* Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+ function() {
+ return !this.isLocal && createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+ jQuery.extend( jQuery.support, {
+ ajax: !!xhr,
+ cors: !!xhr && ( "withCredentials" in xhr )
+ });
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+ jQuery.ajaxTransport(function( s ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !s.crossDomain || jQuery.support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+
+ // Get a new xhr
+ var xhr = s.xhr(),
+ handle,
+ i;
+
+ // Open the socket
+ // Passing null username, generates a login popup on Opera (#2865)
+ if ( s.username ) {
+ xhr.open( s.type, s.url, s.async, s.username, s.password );
+ } else {
+ xhr.open( s.type, s.url, s.async );
+ }
+
+ // Apply custom fields if provided
+ if ( s.xhrFields ) {
+ for ( i in s.xhrFields ) {
+ xhr[ i ] = s.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( s.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( s.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Need an extra try/catch for cross domain requests in Firefox 3
+ try {
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ } catch( _ ) {}
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( s.hasContent && s.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+
+ var status,
+ statusText,
+ responseHeaders,
+ responses,
+ xml;
+
+ // Firefox throws exceptions when accessing properties
+ // of an xhr when a network error occured
+ // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+ try {
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+ // Only called once
+ callback = undefined;
+
+ // Do not keep as active anymore
+ if ( handle ) {
+ xhr.onreadystatechange = jQuery.noop;
+ if ( xhrOnUnloadAbort ) {
+ delete xhrCallbacks[ handle ];
+ }
+ }
+
+ // If it's an abort
+ if ( isAbort ) {
+ // Abort it manually if needed
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ status = xhr.status;
+ responseHeaders = xhr.getAllResponseHeaders();
+ responses = {};
+ xml = xhr.responseXML;
+
+ // Construct response list
+ if ( xml && xml.documentElement /* #4958 */ ) {
+ responses.xml = xml;
+ }
+ responses.text = xhr.responseText;
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && s.isLocal && !s.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+ } catch( firefoxAccessException ) {
+ if ( !isAbort ) {
+ complete( -1, firefoxAccessException );
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, responseHeaders );
+ }
+ };
+
+ // if we're in sync mode or it's in cache
+ // and has been retrieved directly (IE6 & IE7)
+ // we need to manually fire the callback
+ if ( !s.async || xhr.readyState === 4 ) {
+ callback();
+ } else {
+ handle = ++xhrId;
+ if ( xhrOnUnloadAbort ) {
+ // Create the active xhrs callbacks list if needed
+ // and attach the unload handler
+ if ( !xhrCallbacks ) {
+ xhrCallbacks = {};
+ jQuery( window ).unload( xhrOnUnloadAbort );
+ }
+ // Add to list of active xhrs callbacks
+ xhrCallbacks[ handle ] = callback;
+ }
+ xhr.onreadystatechange = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback(0,1);
+ }
+ }
+ };
+ }
+ });
+}
+
+
+
+
+var elemdisplay = {},
+ iframe, iframeDoc,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
+ timerId,
+ fxAttrs = [
+ // height animations
+ [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+ // width animations
+ [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+ // opacity animations
+ [ "opacity" ]
+ ],
+ fxNow;
+
+jQuery.fn.extend({
+ show: function( speed, easing, callback ) {
+ var elem, display;
+
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("show", 3), speed, easing, callback );
+
+ } else {
+ for ( var i = 0, j = this.length; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
+ display = elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( display === "" && jQuery.css(elem, "display") === "none" ) {
+ jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ elem = this[ i ];
+
+ if ( elem.style ) {
+ display = elem.style.display;
+
+ if ( display === "" || display === "none" ) {
+ elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
+ }
+ }
+ }
+
+ return this;
+ }
+ },
+
+ hide: function( speed, easing, callback ) {
+ if ( speed || speed === 0 ) {
+ return this.animate( genFx("hide", 3), speed, easing, callback);
+
+ } else {
+ var elem, display,
+ i = 0,
+ j = this.length;
+
+ for ( ; i < j; i++ ) {
+ elem = this[i];
+ if ( elem.style ) {
+ display = jQuery.css( elem, "display" );
+
+ if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
+ jQuery._data( elem, "olddisplay", display );
+ }
+ }
+ }
+
+ // Set the display of the elements in a second loop
+ // to avoid the constant reflow
+ for ( i = 0; i < j; i++ ) {
+ if ( this[i].style ) {
+ this[i].style.display = "none";
+ }
+ }
+
+ return this;
+ }
+ },
+
+ // Save the old toggle function
+ _toggle: jQuery.fn.toggle,
+
+ toggle: function( fn, fn2, callback ) {
+ var bool = typeof fn === "boolean";
+
+ if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+ this._toggle.apply( this, arguments );
+
+ } else if ( fn == null || bool ) {
+ this.each(function() {
+ var state = bool ? fn : jQuery(this).is(":hidden");
+ jQuery(this)[ state ? "show" : "hide" ]();
+ });
+
+ } else {
+ this.animate(genFx("toggle", 3), fn, fn2, callback);
+ }
+
+ return this;
+ },
+
+ fadeTo: function( speed, to, easing, callback ) {
+ return this.filter(":hidden").css("opacity", 0).show().end()
+ .animate({opacity: to}, speed, easing, callback);
+ },
+
+ animate: function( prop, speed, easing, callback ) {
+ var optall = jQuery.speed( speed, easing, callback );
+
+ if ( jQuery.isEmptyObject( prop ) ) {
+ return this.each( optall.complete, [ false ] );
+ }
+
+ // Do not change referenced properties as per-property easing will be lost
+ prop = jQuery.extend( {}, prop );
+
+ function doAnimation() {
+ // XXX 'this' does not always have a nodeName when running the
+ // test suite
+
+ if ( optall.queue === false ) {
+ jQuery._mark( this );
+ }
+
+ var opt = jQuery.extend( {}, optall ),
+ isElement = this.nodeType === 1,
+ hidden = isElement && jQuery(this).is(":hidden"),
+ name, val, p, e,
+ parts, start, end, unit,
+ method;
+
+ // will store per property easing and be used to determine when an animation is complete
+ opt.animatedProperties = {};
+
+ for ( p in prop ) {
+
+ // property name normalization
+ name = jQuery.camelCase( p );
+ if ( p !== name ) {
+ prop[ name ] = prop[ p ];
+ delete prop[ p ];
+ }
+
+ val = prop[ name ];
+
+ // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+ if ( jQuery.isArray( val ) ) {
+ opt.animatedProperties[ name ] = val[ 1 ];
+ val = prop[ name ] = val[ 0 ];
+ } else {
+ opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
+ }
+
+ if ( val === "hide" && hidden || val === "show" && !hidden ) {
+ return opt.complete.call( this );
+ }
+
+ if ( isElement && ( name === "height" || name === "width" ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( this, "display" ) === "inline" &&
+ jQuery.css( this, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
+ this.style.display = "inline-block";
+
+ } else {
+ this.style.zoom = 1;
+ }
+ }
+ }
+ }
+
+ if ( opt.overflow != null ) {
+ this.style.overflow = "hidden";
+ }
+
+ for ( p in prop ) {
+ e = new jQuery.fx( this, opt, p );
+ val = prop[ p ];
+
+ if ( rfxtypes.test( val ) ) {
+
+ // Tracks whether to show or hide based on private
+ // data attached to the element
+ method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
+ if ( method ) {
+ jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
+ e[ method ]();
+ } else {
+ e[ val ]();
+ }
+
+ } else {
+ parts = rfxnum.exec( val );
+ start = e.cur();
+
+ if ( parts ) {
+ end = parseFloat( parts[2] );
+ unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
+
+ // We need to compute starting value
+ if ( unit !== "px" ) {
+ jQuery.style( this, p, (end || 1) + unit);
+ start = ( (end || 1) / e.cur() ) * start;
+ jQuery.style( this, p, start + unit);
+ }
+
+ // If a +=/-= token was provided, we're doing a relative animation
+ if ( parts[1] ) {
+ end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
+ }
+
+ e.custom( start, end, unit );
+
+ } else {
+ e.custom( start, val, "" );
+ }
+ }
+ }
+
+ // For JS strict compliance
+ return true;
+ }
+
+ return optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+
+ stop: function( type, clearQueue, gotoEnd ) {
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var i,
+ hadTimers = false,
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ // clear marker counters if we know they won't be
+ if ( !gotoEnd ) {
+ jQuery._unmark( true, this );
+ }
+
+ function stopQueue( elem, data, i ) {
+ var hooks = data[ i ];
+ jQuery.removeData( elem, i, true );
+ hooks.stop( gotoEnd );
+ }
+
+ if ( type == null ) {
+ for ( i in data ) {
+ if ( data[ i ].stop && i.indexOf(".run") === i.length - 4 ) {
+ stopQueue( this, data, i );
+ }
+ }
+ } else if ( data[ i = type + ".run" ] && data[ i ].stop ){
+ stopQueue( this, data, i );
+ }
+
+ for ( i = timers.length; i--; ) {
+ if ( timers[ i ].elem === this && (type == null || timers[ i ].queue === type) ) {
+ if ( gotoEnd ) {
+
+ // force the next step to be the last
+ timers[ i ]( true );
+ } else {
+ timers[ i ].saveState();
+ }
+ hadTimers = true;
+ timers.splice( i, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( !( gotoEnd && hadTimers ) ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ }
+
+});
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout( clearFxNow, 0 );
+ return ( fxNow = jQuery.now() );
+}
+
+function clearFxNow() {
+ fxNow = undefined;
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, num ) {
+ var obj = {};
+
+ jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
+ obj[ this ] = type;
+ });
+
+ return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx( "show", 1 ),
+ slideUp: genFx( "hide", 1 ),
+ slideToggle: genFx( "toggle", 1 ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.extend({
+ speed: function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function( noUnmark ) {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ } else if ( noUnmark !== false ) {
+ jQuery._unmark( this );
+ }
+ };
+
+ return opt;
+ },
+
+ easing: {
+ linear: function( p, n, firstNum, diff ) {
+ return firstNum + diff * p;
+ },
+ swing: function( p, n, firstNum, diff ) {
+ return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
+ }
+ },
+
+ timers: [],
+
+ fx: function( elem, options, prop ) {
+ this.options = options;
+ this.elem = elem;
+ this.prop = prop;
+
+ options.orig = options.orig || {};
+ }
+
+});
+
+jQuery.fx.prototype = {
+ // Simple function for setting a style value
+ update: function() {
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
+ },
+
+ // Get the current size
+ cur: function() {
+ if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
+ return this.elem[ this.prop ];
+ }
+
+ var parsed,
+ r = jQuery.css( this.elem, this.prop );
+ // Empty strings, null, undefined and "auto" are converted to 0,
+ // complex values such as "rotate(1rad)" are returned as is,
+ // simple values such as "10px" are parsed to Float.
+ return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
+ },
+
+ // Start an animation from one number to another
+ custom: function( from, to, unit ) {
+ var self = this,
+ fx = jQuery.fx;
+
+ this.startTime = fxNow || createFxNow();
+ this.end = to;
+ this.now = this.start = from;
+ this.pos = this.state = 0;
+ this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
+
+ function t( gotoEnd ) {
+ return self.step( gotoEnd );
+ }
+
+ t.queue = this.options.queue;
+ t.elem = this.elem;
+ t.saveState = function() {
+ if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
+ jQuery._data( self.elem, "fxshow" + self.prop, self.start );
+ }
+ };
+
+ if ( t() && jQuery.timers.push(t) && !timerId ) {
+ timerId = setInterval( fx.tick, fx.interval );
+ }
+ },
+
+ // Simple 'show' function
+ show: function() {
+ var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
+
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
+ this.options.show = true;
+
+ // Begin the animation
+ // Make sure that we start at a small width/height to avoid any flash of content
+ if ( dataShow !== undefined ) {
+ // This show is picking up where a previous hide or show left off
+ this.custom( this.cur(), dataShow );
+ } else {
+ this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
+ }
+
+ // Start by showing the element
+ jQuery( this.elem ).show();
+ },
+
+ // Simple 'hide' function
+ hide: function() {
+ // Remember where we started, so that we can go back to it later
+ this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
+ this.options.hide = true;
+
+ // Begin the animation
+ this.custom( this.cur(), 0 );
+ },
+
+ // Each step of an animation
+ step: function( gotoEnd ) {
+ var p, n, complete,
+ t = fxNow || createFxNow(),
+ done = true,
+ elem = this.elem,
+ options = this.options;
+
+ if ( gotoEnd || t >= options.duration + this.startTime ) {
+ this.now = this.end;
+ this.pos = this.state = 1;
+ this.update();
+
+ options.animatedProperties[ this.prop ] = true;
+
+ for ( p in options.animatedProperties ) {
+ if ( options.animatedProperties[ p ] !== true ) {
+ done = false;
+ }
+ }
+
+ if ( done ) {
+ // Reset the overflow
+ if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+
+ jQuery.each( [ "", "X", "Y" ], function( index, value ) {
+ elem.style[ "overflow" + value ] = options.overflow[ index ];
+ });
+ }
+
+ // Hide the element if the "hide" operation was done
+ if ( options.hide ) {
+ jQuery( elem ).hide();
+ }
+
+ // Reset the properties, if the item has been hidden or shown
+ if ( options.hide || options.show ) {
+ for ( p in options.animatedProperties ) {
+ jQuery.style( elem, p, options.orig[ p ] );
+ jQuery.removeData( elem, "fxshow" + p, true );
+ // Toggle data is no longer needed
+ jQuery.removeData( elem, "toggle" + p, true );
+ }
+ }
+
+ // Execute the complete function
+ // in the event that the complete function throws an exception
+ // we must ensure it won't be called twice. #5684
+
+ complete = options.complete;
+ if ( complete ) {
+
+ options.complete = false;
+ complete.call( elem );
+ }
+ }
+
+ return false;
+
+ } else {
+ // classical easing cannot be used with an Infinity duration
+ if ( options.duration == Infinity ) {
+ this.now = t;
+ } else {
+ n = t - this.startTime;
+ this.state = n / options.duration;
+
+ // Perform the easing function, defaults to swing
+ this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
+ this.now = this.start + ( (this.end - this.start) * this.pos );
+ }
+ // Perform the next step of the animation
+ this.update();
+ }
+
+ return true;
+ }
+};
+
+jQuery.extend( jQuery.fx, {
+ tick: function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ },
+
+ interval: 13,
+
+ stop: function() {
+ clearInterval( timerId );
+ timerId = null;
+ },
+
+ speeds: {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+ },
+
+ step: {
+ opacity: function( fx ) {
+ jQuery.style( fx.elem, "opacity", fx.now );
+ },
+
+ _default: function( fx ) {
+ if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+ fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+ } else {
+ fx.elem[ fx.prop ] = fx.now;
+ }
+ }
+ }
+});
+
+// Adds width/height step functions
+// Do not set anything below 0
+jQuery.each([ "width", "height" ], function( i, prop ) {
+ jQuery.fx.step[ prop ] = function( fx ) {
+ jQuery.style( fx.elem, prop, Math.max(0, fx.now) );
+ };
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+
+// Try to restore the default display value of an element
+function defaultDisplay( nodeName ) {
+
+ if ( !elemdisplay[ nodeName ] ) {
+
+ var body = document.body,
+ elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
+ display = elem.css( "display" );
+ elem.remove();
+
+ // If the simple way fails,
+ // get element's real default display by attaching it to a temp iframe
+ if ( display === "none" || display === "" ) {
+ // No iframe to use yet, so create it
+ if ( !iframe ) {
+ iframe = document.createElement( "iframe" );
+ iframe.frameBorder = iframe.width = iframe.height = 0;
+ }
+
+ body.appendChild( iframe );
+
+ // Create a cacheable copy of the iframe document on first call.
+ // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+ // document to it; WebKit & Firefox won't allow reusing the iframe document.
+ if ( !iframeDoc || !iframe.createElement ) {
+ iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+ iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
+ iframeDoc.close();
+ }
+
+ elem = iframeDoc.createElement( nodeName );
+
+ iframeDoc.body.appendChild( elem );
+
+ display = jQuery.css( elem, "display" );
+ body.removeChild( iframe );
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+ rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0], box;
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ try {
+ box = elem.getBoundingClientRect();
+ } catch(e) {}
+
+ var doc = elem.ownerDocument,
+ docElem = doc.documentElement;
+
+ // Make sure we're not dealing with a disconnected DOM node
+ if ( !box || !jQuery.contains( docElem, elem ) ) {
+ return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
+ }
+
+ var body = doc.body,
+ win = getWindow(doc),
+ clientTop = docElem.clientTop || body.clientTop || 0,
+ clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
+ scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
+ top = box.top + scrollTop - clientTop,
+ left = box.left + scrollLeft - clientLeft;
+
+ return { top: top, left: left };
+ };
+
+} else {
+ jQuery.fn.offset = function( options ) {
+ var elem = this[0];
+
+ if ( options ) {
+ return this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ if ( !elem || !elem.ownerDocument ) {
+ return null;
+ }
+
+ if ( elem === elem.ownerDocument.body ) {
+ return jQuery.offset.bodyOffset( elem );
+ }
+
+ var computedStyle,
+ offsetParent = elem.offsetParent,
+ prevOffsetParent = elem,
+ doc = elem.ownerDocument,
+ docElem = doc.documentElement,
+ body = doc.body,
+ defaultView = doc.defaultView,
+ prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+ top = elem.offsetTop,
+ left = elem.offsetLeft;
+
+ while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ break;
+ }
+
+ computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+ top -= elem.scrollTop;
+ left -= elem.scrollLeft;
+
+ if ( elem === offsetParent ) {
+ top += elem.offsetTop;
+ left += elem.offsetLeft;
+
+ if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevOffsetParent = offsetParent;
+ offsetParent = elem.offsetParent;
+ }
+
+ if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+ top += parseFloat( computedStyle.borderTopWidth ) || 0;
+ left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+ }
+
+ prevComputedStyle = computedStyle;
+ }
+
+ if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+ top += body.offsetTop;
+ left += body.offsetLeft;
+ }
+
+ if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+ top += Math.max( docElem.scrollTop, body.scrollTop );
+ left += Math.max( docElem.scrollLeft, body.scrollLeft );
+ }
+
+ return { top: top, left: left };
+ };
+}
+
+jQuery.offset = {
+
+ bodyOffset: function( body ) {
+ var top = body.offsetTop,
+ left = body.offsetLeft;
+
+ if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+ top += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+ left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+ }
+
+ return { top: top, left: left };
+ },
+
+ setOffset: function( elem, options, i ) {
+ var position = jQuery.css( elem, "position" );
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ var curElem = jQuery( elem ),
+ curOffset = curElem.offset(),
+ curCSSTop = jQuery.css( elem, "top" ),
+ curCSSLeft = jQuery.css( elem, "left" ),
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+ props = {}, curPosition = {}, curTop, curLeft;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[0] ) {
+ return null;
+ }
+
+ var elem = this[0],
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent(),
+
+ // Get correct offsets
+ offset = this.offset(),
+ parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+ // Subtract element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+ offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+ // Add offsetParent borders
+ parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+ parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+ // Subtract the two offsets
+ return {
+ top: offset.top - parentOffset.top,
+ left: offset.left - parentOffset.left
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || document.body;
+ while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+ var method = "scroll" + name;
+
+ jQuery.fn[ method ] = function( val ) {
+ var elem, win;
+
+ if ( val === undefined ) {
+ elem = this[ 0 ];
+
+ if ( !elem ) {
+ return null;
+ }
+
+ win = getWindow( elem );
+
+ // Return the scroll offset
+ return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+ jQuery.support.boxModel && win.document.documentElement[ method ] ||
+ win.document.body[ method ] :
+ elem[ method ];
+ }
+
+ // Set the scroll offset
+ return this.each(function() {
+ win = getWindow( this );
+
+ if ( win ) {
+ win.scrollTo(
+ !i ? val : jQuery( win ).scrollLeft(),
+ i ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ this[ method ] = val;
+ }
+ });
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+
+
+
+// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+ var type = name.toLowerCase();
+
+ // innerHeight and innerWidth
+ jQuery.fn[ "inner" + name ] = function() {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, "padding" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ // outerHeight and outerWidth
+ jQuery.fn[ "outer" + name ] = function( margin ) {
+ var elem = this[0];
+ return elem ?
+ elem.style ?
+ parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
+ this[ type ]() :
+ null;
+ };
+
+ jQuery.fn[ type ] = function( size ) {
+ // Get window width or height
+ var elem = this[0];
+ if ( !elem ) {
+ return size == null ? null : this;
+ }
+
+ if ( jQuery.isFunction( size ) ) {
+ return this.each(function( i ) {
+ var self = jQuery( this );
+ self[ type ]( size.call( this, i, self[ type ]() ) );
+ });
+ }
+
+ if ( jQuery.isWindow( elem ) ) {
+ // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+ // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
+ var docElemProp = elem.document.documentElement[ "client" + name ],
+ body = elem.document.body;
+ return elem.document.compatMode === "CSS1Compat" && docElemProp ||
+ body && body[ "client" + name ] || docElemProp;
+
+ // Get document width or height
+ } else if ( elem.nodeType === 9 ) {
+ // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+ return Math.max(
+ elem.documentElement["client" + name],
+ elem.body["scroll" + name], elem.documentElement["scroll" + name],
+ elem.body["offset" + name], elem.documentElement["offset" + name]
+ );
+
+ // Get or set width or height on the element
+ } else if ( size === undefined ) {
+ var orig = jQuery.css( elem, type ),
+ ret = parseFloat( orig );
+
+ return jQuery.isNumeric( ret ) ? ret : orig;
+
+ // Set the width or height on the element (default to pixels if value is unitless)
+ } else {
+ return this.css( type, typeof size === "string" ? size : size + "px" );
+ }
+ };
+
+});
+
+
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+})( window );
diff --git a/contrib/libxo/xohtml/external/jquery.qtip.css b/contrib/libxo/xohtml/external/jquery.qtip.css
new file mode 100644
index 0000000..503bd35
--- /dev/null
+++ b/contrib/libxo/xohtml/external/jquery.qtip.css
@@ -0,0 +1,599 @@
+/*
+ * qTip2 - Pretty powerful tooltips - v2.1.1
+ * http://qtip2.com
+ *
+ * Copyright (c) 2013 Craig Michael Thompson
+ * Released under the MIT, GPL licenses
+ * http://jquery.org/license
+ *
+ * Date: Thu Jul 11 2013 02:15 UTC+0000
+ * Plugins: tips viewport
+ * Styles: basic css3
+ */
+.qtip{
+ position: absolute;
+ left: -28000px;
+ top: -28000px;
+ display: none;
+
+ max-width: 280px;
+ min-width: 50px;
+
+ font-size: 10.5px;
+ line-height: 12px;
+
+ direction: ltr;
+
+ box-shadow: none;
+ padding: 0;
+}
+
+ .qtip-content{
+ position: relative;
+ padding: 5px 9px;
+ overflow: hidden;
+
+ text-align: left;
+ word-wrap: break-word;
+ }
+
+ .qtip-titlebar{
+ position: relative;
+ padding: 5px 35px 5px 10px;
+ overflow: hidden;
+
+ border-width: 0 0 1px;
+ font-weight: bold;
+ }
+
+ .qtip-titlebar + .qtip-content{ border-top-width: 0 !important; }
+
+ /* Default close button class */
+ .qtip-close{
+ position: absolute;
+ right: -9px; top: -9px;
+
+ cursor: pointer;
+ outline: medium none;
+
+ border-width: 1px;
+ border-style: solid;
+ border-color: transparent;
+ }
+
+ .qtip-titlebar .qtip-close{
+ right: 4px; top: 50%;
+ margin-top: -9px;
+ }
+
+ * html .qtip-titlebar .qtip-close{ top: 16px; } /* IE fix */
+
+ .qtip-titlebar .ui-icon,
+ .qtip-icon .ui-icon{
+ display: block;
+ text-indent: -1000em;
+ direction: ltr;
+ }
+
+ .qtip-icon, .qtip-icon .ui-icon{
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ text-decoration: none;
+ }
+
+ .qtip-icon .ui-icon{
+ width: 18px;
+ height: 14px;
+
+ line-height: 14px;
+ text-align: center;
+ text-indent: 0;
+ font: normal bold 10px/13px Tahoma,sans-serif;
+
+ color: inherit;
+ background: transparent none no-repeat -100em -100em;
+ }
+
+/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
+.qtip-focus{}
+
+/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
+.qtip-hover{}
+
+/* Default tooltip style */
+.qtip-default{
+ border-width: 1px;
+ border-style: solid;
+ border-color: #F1D031;
+
+ background-color: #FFFFA3;
+ color: #555;
+}
+
+ .qtip-default .qtip-titlebar{
+ background-color: #FFEF93;
+ }
+
+ .qtip-default .qtip-icon{
+ border-color: #CCC;
+ background: #F1F1F1;
+ color: #777;
+ }
+
+ .qtip-default .qtip-titlebar .qtip-close{
+ border-color: #AAA;
+ color: #111;
+ }
+
+
+
+/*! Light tooltip style */
+.qtip-light{
+ background-color: white;
+ border-color: #E2E2E2;
+ color: #454545;
+}
+
+ .qtip-light .qtip-titlebar{
+ background-color: #f1f1f1;
+ }
+
+
+/*! Dark tooltip style */
+.qtip-dark{
+ background-color: #505050;
+ border-color: #303030;
+ color: #f3f3f3;
+}
+
+ .qtip-dark .qtip-titlebar{
+ background-color: #404040;
+ }
+
+ .qtip-dark .qtip-icon{
+ border-color: #444;
+ }
+
+ .qtip-dark .qtip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/*! Cream tooltip style */
+.qtip-cream{
+ background-color: #FBF7AA;
+ border-color: #F9E98E;
+ color: #A27D35;
+}
+
+ .qtip-cream .qtip-titlebar{
+ background-color: #F0DE7D;
+ }
+
+ .qtip-cream .qtip-close .qtip-icon{
+ background-position: -82px 0;
+ }
+
+
+/*! Red tooltip style */
+.qtip-red{
+ background-color: #F78B83;
+ border-color: #D95252;
+ color: #912323;
+}
+
+ .qtip-red .qtip-titlebar{
+ background-color: #F06D65;
+ }
+
+ .qtip-red .qtip-close .qtip-icon{
+ background-position: -102px 0;
+ }
+
+ .qtip-red .qtip-icon{
+ border-color: #D95252;
+ }
+
+ .qtip-red .qtip-titlebar .ui-state-hover{
+ border-color: #D95252;
+ }
+
+
+/*! Green tooltip style */
+.qtip-green{
+ background-color: #CAED9E;
+ border-color: #90D93F;
+ color: #3F6219;
+}
+
+ .qtip-green .qtip-titlebar{
+ background-color: #B0DE78;
+ }
+
+ .qtip-green .qtip-close .qtip-icon{
+ background-position: -42px 0;
+ }
+
+
+/*! Blue tooltip style */
+.qtip-blue{
+ background-color: #E5F6FE;
+ border-color: #ADD9ED;
+ color: #5E99BD;
+}
+
+ .qtip-blue .qtip-titlebar{
+ background-color: #D0E9F5;
+ }
+
+ .qtip-blue .qtip-close .qtip-icon{
+ background-position: -2px 0;
+ }
+
+
+
+.qtip-shadow{
+ -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+ box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+}
+
+/* Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */
+.qtip-rounded,
+.qtip-tipsy,
+.qtip-bootstrap{
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+}
+
+.qtip-rounded .qtip-titlebar{
+ -moz-border-radius: 4px 4px 0 0;
+ -webkit-border-radius: 4px 4px 0 0;
+ border-radius: 4px 4px 0 0;
+}
+
+/* Youtube tooltip style */
+.qtip-youtube{
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+
+ -webkit-box-shadow: 0 0 3px #333;
+ -moz-box-shadow: 0 0 3px #333;
+ box-shadow: 0 0 3px #333;
+
+ color: white;
+ border-width: 0;
+
+ background: #4A4A4A;
+ background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,black));
+ background-image: -webkit-linear-gradient(top,#4A4A4A 0,black 100%);
+ background-image: -moz-linear-gradient(top,#4A4A4A 0,black 100%);
+ background-image: -ms-linear-gradient(top,#4A4A4A 0,black 100%);
+ background-image: -o-linear-gradient(top,#4A4A4A 0,black 100%);
+}
+
+ .qtip-youtube .qtip-titlebar{
+ background-color: #4A4A4A;
+ background-color: rgba(0,0,0,0);
+ }
+
+ .qtip-youtube .qtip-content{
+ padding: .75em;
+ font: 12px arial,sans-serif;
+
+ filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);
+ -ms-filter: "progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);";
+ }
+
+ .qtip-youtube .qtip-icon{
+ border-color: #222;
+ }
+
+ .qtip-youtube .qtip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/* jQuery TOOLS Tooltip style */
+.qtip-jtools{
+ background: #232323;
+ background: rgba(0, 0, 0, 0.7);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323));
+ background-image: -moz-linear-gradient(top, #717171, #232323);
+ background-image: -webkit-linear-gradient(top, #717171, #232323);
+ background-image: -ms-linear-gradient(top, #717171, #232323);
+ background-image: -o-linear-gradient(top, #717171, #232323);
+
+ border: 2px solid #ddd;
+ border: 2px solid rgba(241,241,241,1);
+
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+
+ -webkit-box-shadow: 0 0 12px #333;
+ -moz-box-shadow: 0 0 12px #333;
+ box-shadow: 0 0 12px #333;
+}
+
+ /* IE Specific */
+ .qtip-jtools .qtip-titlebar{
+ background-color: transparent;
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)";
+ }
+ .qtip-jtools .qtip-content{
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)";
+ }
+
+ .qtip-jtools .qtip-titlebar,
+ .qtip-jtools .qtip-content{
+ background: transparent;
+ color: white;
+ border: 0 dashed transparent;
+ }
+
+ .qtip-jtools .qtip-icon{
+ border-color: #555;
+ }
+
+ .qtip-jtools .qtip-titlebar .ui-state-hover{
+ border-color: #333;
+ }
+
+
+/* Cluetip style */
+.qtip-cluetip{
+ -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+ -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+ box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+
+ background-color: #D9D9C2;
+ color: #111;
+ border: 0 dashed transparent;
+}
+
+ .qtip-cluetip .qtip-titlebar{
+ background-color: #87876A;
+ color: white;
+ border: 0 dashed transparent;
+ }
+
+ .qtip-cluetip .qtip-icon{
+ border-color: #808064;
+ }
+
+ .qtip-cluetip .qtip-titlebar .ui-state-hover{
+ border-color: #696952;
+ color: #696952;
+ }
+
+
+/* Tipsy style */
+.qtip-tipsy{
+ background: black;
+ background: rgba(0, 0, 0, .87);
+
+ color: white;
+ border: 0 solid transparent;
+
+ font-size: 11px;
+ font-family: 'Lucida Grande', sans-serif;
+ font-weight: bold;
+ line-height: 16px;
+ text-shadow: 0 1px black;
+}
+
+ .qtip-tipsy .qtip-titlebar{
+ padding: 6px 35px 0 10px;
+ background-color: transparent;
+ }
+
+ .qtip-tipsy .qtip-content{
+ padding: 6px 10px;
+ }
+
+ .qtip-tipsy .qtip-icon{
+ border-color: #222;
+ text-shadow: none;
+ }
+
+ .qtip-tipsy .qtip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/* Tipped style */
+.qtip-tipped{
+ border: 3px solid #959FA9;
+
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+
+ background-color: #F9F9F9;
+ color: #454545;
+
+ font-weight: normal;
+ font-family: serif;
+
+ font-size: 12px;
+}
+
+ .qtip-tipped .qtip-titlebar{
+ border-bottom-width: 0;
+
+ color: white;
+ background: #3A79B8;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D));
+ background-image: -webkit-linear-gradient(top, #3A79B8, #2E629D);
+ background-image: -moz-linear-gradient(top, #3A79B8, #2E629D);
+ background-image: -ms-linear-gradient(top, #3A79B8, #2E629D);
+ background-image: -o-linear-gradient(top, #3A79B8, #2E629D);
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)";
+
+ font-size: 14px;
+ }
+
+ .qtip-tipped .qtip-icon{
+ border: 2px solid #285589;
+ background: #285589;
+ }
+
+ .qtip-tipped .qtip-icon .ui-icon{
+ background-color: #FBFBFB;
+ color: #555;
+ }
+
+
+/**
+ * Twitter Bootstrap style.
+ *
+ * Tested with IE 8, IE 9, Chrome 18, Firefox 9, Opera 11.
+ * Does not work with IE 7.
+ */
+.qtip-bootstrap{
+ /** Taken from Bootstrap body */
+ font-size: 14px;
+ line-height: 20px;
+ color: #333333;
+
+ /** Taken from Bootstrap .popover */
+ padding: 1px;
+ background-color: #ffffff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+ .qtip-bootstrap .qtip-titlebar{
+ /** Taken from Bootstrap .popover-title */
+ padding: 8px 14px;
+ margin: 0;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 18px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ -webkit-border-radius: 5px 5px 0 0;
+ -moz-border-radius: 5px 5px 0 0;
+ border-radius: 5px 5px 0 0;
+ }
+
+ .qtip-bootstrap .qtip-titlebar .qtip-close{
+ /**
+ * Overrides qTip2:
+ * .qtip-titlebar .qtip-close{
+ * [...]
+ * right: 4px;
+ * top: 50%;
+ * [...]
+ * border-style: solid;
+ * }
+ */
+ right: 11px;
+ top: 45%;
+ border-style: none;
+ }
+
+ .qtip-bootstrap .qtip-content{
+ /** Taken from Bootstrap .popover-content */
+ padding: 9px 14px;
+ }
+
+ .qtip-bootstrap .qtip-icon{
+ /**
+ * Overrides qTip2:
+ * .qtip-default .qtip-icon {
+ * border-color: #CCC;
+ * background: #F1F1F1;
+ * color: #777;
+ * }
+ */
+ background: transparent;
+ }
+
+ .qtip-bootstrap .qtip-icon .ui-icon{
+ /**
+ * Overrides qTip2:
+ * .qtip-icon .ui-icon{
+ * width: 18px;
+ * height: 14px;
+ * }
+ */
+ width: auto;
+ height: auto;
+
+ /* Taken from Bootstrap .close */
+ float: right;
+ font-size: 20px;
+ font-weight: bold;
+ line-height: 18px;
+ color: #000000;
+ text-shadow: 0 1px 0 #ffffff;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+ }
+
+ .qtip-bootstrap .qtip-icon .ui-icon:hover{
+ /* Taken from Bootstrap .close:hover */
+ color: #000000;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+ }
+
+
+/* IE9 fix - removes all filters */
+.qtip:not(.ie9haxors) div.qtip-content,
+.qtip:not(.ie9haxors) div.qtip-titlebar{
+ filter: none;
+ -ms-filter: none;
+}
+
+
+
+.qtip .qtip-tip{
+ margin: 0 auto;
+ overflow: hidden;
+ z-index: 10;
+
+}
+
+ /* Opera bug #357 - Incorrect tip position
+ https://github.com/Craga89/qTip2/issues/367 */
+ x:-o-prefocus, .qtip .qtip-tip{
+ visibility: hidden;
+ }
+
+ .qtip .qtip-tip,
+ .qtip .qtip-tip .qtip-vml,
+ .qtip .qtip-tip canvas{
+ position: absolute;
+
+ color: #123456;
+ background: transparent;
+ border: 0 dashed transparent;
+ }
+
+ .qtip .qtip-tip canvas{ top: 0; left: 0; }
+
+ .qtip .qtip-tip .qtip-vml{
+ behavior: url(#default#VML);
+ display: inline-block;
+ visibility: visible;
+ }
diff --git a/contrib/libxo/xohtml/external/jquery.qtip.js b/contrib/libxo/xohtml/external/jquery.qtip.js
new file mode 100644
index 0000000..1159b4e
--- /dev/null
+++ b/contrib/libxo/xohtml/external/jquery.qtip.js
@@ -0,0 +1,2656 @@
+/*
+ * qTip2 - Pretty powerful tooltips - v2.1.1
+ * http://qtip2.com
+ *
+ * Copyright (c) 2013 Craig Michael Thompson
+ * Released under the MIT, GPL licenses
+ * http://jquery.org/license
+ *
+ * Date: Thu Jul 11 2013 02:15 UTC+0000
+ * Plugins: tips viewport
+ * Styles: basic css3
+ */
+/*global window: false, jQuery: false, console: false, define: false */
+
+/* Cache window, document, undefined */
+(function( window, document, undefined ) {
+
+// Uses AMD or browser globals to create a jQuery plugin.
+(function( factory ) {
+ "use strict";
+ if(typeof define === 'function' && define.amd) {
+ define(['jquery', 'imagesloaded'], factory);
+ }
+ else if(jQuery && !jQuery.fn.qtip) {
+ factory(jQuery);
+ }
+}
+(function($) {
+ /* This currently causes issues with Safari 6, so for it's disabled */
+ //"use strict"; // (Dis)able ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
+
+;// Munge the primitives - Paul Irish tip
+var TRUE = true,
+FALSE = false,
+NULL = null,
+
+// Common variables
+X = 'x', Y = 'y',
+WIDTH = 'width',
+HEIGHT = 'height',
+
+// Positioning sides
+TOP = 'top',
+LEFT = 'left',
+BOTTOM = 'bottom',
+RIGHT = 'right',
+CENTER = 'center',
+
+// Position adjustment types
+FLIP = 'flip',
+FLIPINVERT = 'flipinvert',
+SHIFT = 'shift',
+
+// Shortcut vars
+QTIP, PROTOTYPE, CORNER, CHECKS,
+PLUGINS = {},
+NAMESPACE = 'qtip',
+ATTR_HAS = 'data-hasqtip',
+ATTR_ID = 'data-qtip-id',
+WIDGET = ['ui-widget', 'ui-tooltip'],
+SELECTOR = '.'+NAMESPACE,
+INACTIVE_EVENTS = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '),
+
+CLASS_FIXED = NAMESPACE+'-fixed',
+CLASS_DEFAULT = NAMESPACE + '-default',
+CLASS_FOCUS = NAMESPACE + '-focus',
+CLASS_HOVER = NAMESPACE + '-hover',
+CLASS_DISABLED = NAMESPACE+'-disabled',
+
+replaceSuffix = '_replacedByqTip',
+oldtitle = 'oldtitle',
+trackingBound;
+
+// Browser detection
+BROWSER = {
+ /*
+ * IE version detection
+ *
+ * Adapted from: http://ajaxian.com/archives/attack-of-the-ie-conditional-comment
+ * Credit to James Padolsey for the original implemntation!
+ */
+ ie: (function(){
+ var v = 3, div = document.createElement('div');
+ while ((div.innerHTML = '<!--[if gt IE '+(++v)+']><i></i><![endif]-->')) {
+ if(!div.getElementsByTagName('i')[0]) { break; }
+ }
+ return v > 4 ? v : NaN;
+ }()),
+
+ /*
+ * iOS version detection
+ */
+ iOS: parseFloat(
+ ('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1])
+ .replace('undefined', '3_2').replace('_', '.').replace('_', '')
+ ) || FALSE
+};
+
+;function QTip(target, options, id, attr) {
+ // Elements and ID
+ this.id = id;
+ this.target = target;
+ this.tooltip = NULL;
+ this.elements = elements = { target: target };
+
+ // Internal constructs
+ this._id = NAMESPACE + '-' + id;
+ this.timers = { img: {} };
+ this.options = options;
+ this.plugins = {};
+
+ // Cache object
+ this.cache = cache = {
+ event: {},
+ target: $(),
+ disabled: FALSE,
+ attr: attr,
+ onTooltip: FALSE,
+ lastClass: ''
+ };
+
+ // Set the initial flags
+ this.rendered = this.destroyed = this.disabled = this.waiting =
+ this.hiddenDuringWait = this.positioning = this.triggering = FALSE;
+}
+PROTOTYPE = QTip.prototype;
+
+PROTOTYPE.render = function(show) {
+ if(this.rendered || this.destroyed) { return this; } // If tooltip has already been rendered, exit
+
+ var self = this,
+ options = this.options,
+ cache = this.cache,
+ elements = this.elements,
+ text = options.content.text,
+ title = options.content.title,
+ button = options.content.button,
+ posOptions = options.position,
+ namespace = '.'+this._id+' ',
+ deferreds = [];
+
+ // Add ARIA attributes to target
+ $.attr(this.target[0], 'aria-describedby', this._id);
+
+ // Create tooltip element
+ this.tooltip = elements.tooltip = tooltip = $('<div/>', {
+ 'id': this._id,
+ 'class': [ NAMESPACE, CLASS_DEFAULT, options.style.classes, NAMESPACE + '-pos-' + options.position.my.abbrev() ].join(' '),
+ 'width': options.style.width || '',
+ 'height': options.style.height || '',
+ 'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse,
+
+ /* ARIA specific attributes */
+ 'role': 'alert',
+ 'aria-live': 'polite',
+ 'aria-atomic': FALSE,
+ 'aria-describedby': this._id + '-content',
+ 'aria-hidden': TRUE
+ })
+ .toggleClass(CLASS_DISABLED, this.disabled)
+ .attr(ATTR_ID, this.id)
+ .data(NAMESPACE, this)
+ .appendTo(posOptions.container)
+ .append(
+ // Create content element
+ elements.content = $('<div />', {
+ 'class': NAMESPACE + '-content',
+ 'id': this._id + '-content',
+ 'aria-atomic': TRUE
+ })
+ );
+
+ // Set rendered flag and prevent redundant reposition calls for now
+ this.rendered = -1;
+ this.positioning = TRUE;
+
+ // Create title...
+ if(title) {
+ this._createTitle();
+
+ // Update title only if its not a callback (called in toggle if so)
+ if(!$.isFunction(title)) {
+ deferreds.push( this._updateTitle(title, FALSE) );
+ }
+ }
+
+ // Create button
+ if(button) { this._createButton(); }
+
+ // Set proper rendered flag and update content if not a callback function (called in toggle)
+ if(!$.isFunction(text)) {
+ deferreds.push( this._updateContent(text, FALSE) );
+ }
+ this.rendered = TRUE;
+
+ // Setup widget classes
+ this._setWidget();
+
+ // Assign passed event callbacks (before plugins!)
+ $.each(options.events, function(name, callback) {
+ $.isFunction(callback) && tooltip.bind(
+ (name === 'toggle' ? ['tooltipshow','tooltiphide'] : ['tooltip'+name])
+ .join(namespace)+namespace, callback
+ );
+ });
+
+ // Initialize 'render' plugins
+ $.each(PLUGINS, function(name) {
+ var instance;
+ if(this.initialize === 'render' && (instance = this(self))) {
+ self.plugins[name] = instance;
+ }
+ });
+
+ // Assign events
+ this._assignEvents();
+
+ // When deferreds have completed
+ $.when.apply($, deferreds).then(function() {
+ // tooltiprender event
+ self._trigger('render');
+
+ // Reset flags
+ self.positioning = FALSE;
+
+ // Show tooltip if not hidden during wait period
+ if(!self.hiddenDuringWait && (options.show.ready || show)) {
+ self.toggle(TRUE, cache.event, FALSE);
+ }
+ self.hiddenDuringWait = FALSE;
+ });
+
+ // Expose API
+ QTIP.api[this.id] = this;
+
+ return this;
+};
+
+PROTOTYPE.destroy = function(immediate) {
+ // Set flag the signify destroy is taking place to plugins
+ // and ensure it only gets destroyed once!
+ if(this.destroyed) { return this.target; }
+
+ function process() {
+ if(this.destroyed) { return; }
+ this.destroyed = TRUE;
+
+ var target = this.target,
+ title = target.attr(oldtitle);
+
+ // Destroy tooltip if rendered
+ if(this.rendered) {
+ this.tooltip.stop(1,0).find('*').remove().end().remove();
+ }
+
+ // Destroy all plugins
+ $.each(this.plugins, function(name) {
+ this.destroy && this.destroy();
+ });
+
+ // Clear timers and remove bound events
+ clearTimeout(this.timers.show);
+ clearTimeout(this.timers.hide);
+ this._unassignEvents();
+
+ // Remove api object and ARIA attributes
+ target.removeData(NAMESPACE).removeAttr(ATTR_ID)
+ .removeAttr('aria-describedby');
+
+ // Reset old title attribute if removed
+ if(this.options.suppress && title) {
+ target.attr('title', title).removeAttr(oldtitle);
+ }
+
+ // Remove qTip events associated with this API
+ this._unbind(target);
+
+ // Remove ID from used id objects, and delete object references
+ // for better garbage collection and leak protection
+ this.options = this.elements = this.cache = this.timers =
+ this.plugins = this.mouse = NULL;
+
+ // Delete epoxsed API object
+ delete QTIP.api[this.id];
+ }
+
+ // If an immediate destory is needed
+ if(immediate !== TRUE && this.rendered) {
+ tooltip.one('tooltiphidden', $.proxy(process, this));
+ !this.triggering && this.hide();
+ }
+
+ // If we're not in the process of hiding... process
+ else { process.call(this); }
+
+ return this.target;
+};
+
+;function invalidOpt(a) {
+ return a === NULL || $.type(a) !== 'object';
+}
+
+function invalidContent(c) {
+ return !( $.isFunction(c) || (c && c.attr) || c.length || ($.type(c) === 'object' && (c.jquery || c.then) ));
+}
+
+// Option object sanitizer
+function sanitizeOptions(opts) {
+ var content, text, ajax, once;
+
+ if(invalidOpt(opts)) { return FALSE; }
+
+ if(invalidOpt(opts.metadata)) {
+ opts.metadata = { type: opts.metadata };
+ }
+
+ if('content' in opts) {
+ content = opts.content;
+
+ if(invalidOpt(content) || content.jquery || content.done) {
+ content = opts.content = {
+ text: (text = invalidContent(content) ? FALSE : content)
+ };
+ }
+ else { text = content.text; }
+
+ // DEPRECATED - Old content.ajax plugin functionality
+ // Converts it into the proper Deferred syntax
+ if('ajax' in content) {
+ ajax = content.ajax;
+ once = ajax && ajax.once !== FALSE;
+ delete content.ajax;
+
+ content.text = function(event, api) {
+ var loading = text || $(this).attr(api.options.content.attr) || 'Loading...',
+
+ deferred = $.ajax(
+ $.extend({}, ajax, { context: api })
+ )
+ .then(ajax.success, NULL, ajax.error)
+ .then(function(content) {
+ if(content && once) { api.set('content.text', content); }
+ return content;
+ },
+ function(xhr, status, error) {
+ if(api.destroyed || xhr.status === 0) { return; }
+ api.set('content.text', status + ': ' + error);
+ });
+
+ return !once ? (api.set('content.text', loading), deferred) : loading;
+ };
+ }
+
+ if('title' in content) {
+ if(!invalidOpt(content.title)) {
+ content.button = content.title.button;
+ content.title = content.title.text;
+ }
+
+ if(invalidContent(content.title || FALSE)) {
+ content.title = FALSE;
+ }
+ }
+ }
+
+ if('position' in opts && invalidOpt(opts.position)) {
+ opts.position = { my: opts.position, at: opts.position };
+ }
+
+ if('show' in opts && invalidOpt(opts.show)) {
+ opts.show = opts.show.jquery ? { target: opts.show } :
+ opts.show === TRUE ? { ready: TRUE } : { event: opts.show };
+ }
+
+ if('hide' in opts && invalidOpt(opts.hide)) {
+ opts.hide = opts.hide.jquery ? { target: opts.hide } : { event: opts.hide };
+ }
+
+ if('style' in opts && invalidOpt(opts.style)) {
+ opts.style = { classes: opts.style };
+ }
+
+ // Sanitize plugin options
+ $.each(PLUGINS, function() {
+ this.sanitize && this.sanitize(opts);
+ });
+
+ return opts;
+}
+
+// Setup builtin .set() option checks
+CHECKS = PROTOTYPE.checks = {
+ builtin: {
+ // Core checks
+ '^id$': function(obj, o, v, prev) {
+ var id = v === TRUE ? QTIP.nextid : v,
+ new_id = NAMESPACE + '-' + id;
+
+ if(id !== FALSE && id.length > 0 && !$('#'+new_id).length) {
+ this._id = new_id;
+
+ if(this.rendered) {
+ this.tooltip[0].id = this._id;
+ this.elements.content[0].id = this._id + '-content';
+ this.elements.title[0].id = this._id + '-title';
+ }
+ }
+ else { obj[o] = prev; }
+ },
+ '^prerender': function(obj, o, v) {
+ v && !this.rendered && this.render(this.options.show.ready);
+ },
+
+ // Content checks
+ '^content.text$': function(obj, o, v) {
+ this._updateContent(v);
+ },
+ '^content.attr$': function(obj, o, v, prev) {
+ if(this.options.content.text === this.target.attr(prev)) {
+ this._updateContent( this.target.attr(v) );
+ }
+ },
+ '^content.title$': function(obj, o, v) {
+ // Remove title if content is null
+ if(!v) { return this._removeTitle(); }
+
+ // If title isn't already created, create it now and update
+ v && !this.elements.title && this._createTitle();
+ this._updateTitle(v);
+ },
+ '^content.button$': function(obj, o, v) {
+ this._updateButton(v);
+ },
+ '^content.title.(text|button)$': function(obj, o, v) {
+ this.set('content.'+o, v); // Backwards title.text/button compat
+ },
+
+ // Position checks
+ '^position.(my|at)$': function(obj, o, v){
+ 'string' === typeof v && (obj[o] = new CORNER(v, o === 'at'));
+ },
+ '^position.container$': function(obj, o, v){
+ this.tooltip.appendTo(v);
+ },
+
+ // Show checks
+ '^show.ready$': function(obj, o, v) {
+ v && (!this.rendered && this.render(TRUE) || this.toggle(TRUE));
+ },
+
+ // Style checks
+ '^style.classes$': function(obj, o, v, p) {
+ this.tooltip.removeClass(p).addClass(v);
+ },
+ '^style.width|height': function(obj, o, v) {
+ this.tooltip.css(o, v);
+ },
+ '^style.widget|content.title': function() {
+ this._setWidget();
+ },
+ '^style.def': function(obj, o, v) {
+ this.tooltip.toggleClass(CLASS_DEFAULT, !!v);
+ },
+
+ // Events check
+ '^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) {
+ tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v);
+ },
+
+ // Properties which require event reassignment
+ '^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() {
+ var posOptions = this.options.position;
+
+ // Set tracking flag
+ tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse);
+
+ // Reassign events
+ this._unassignEvents();
+ this._assignEvents();
+ }
+ }
+};
+
+// Dot notation converter
+function convertNotation(options, notation) {
+ var i = 0, obj, option = options,
+
+ // Split notation into array
+ levels = notation.split('.');
+
+ // Loop through
+ while( option = option[ levels[i++] ] ) {
+ if(i < levels.length) { obj = option; }
+ }
+
+ return [obj || options, levels.pop()];
+}
+
+PROTOTYPE.get = function(notation) {
+ if(this.destroyed) { return this; }
+
+ var o = convertNotation(this.options, notation.toLowerCase()),
+ result = o[0][ o[1] ];
+
+ return result.precedance ? result.string() : result;
+};
+
+function setCallback(notation, args) {
+ var category, rule, match;
+
+ for(category in this.checks) {
+ for(rule in this.checks[category]) {
+ if(match = (new RegExp(rule, 'i')).exec(notation)) {
+ args.push(match);
+
+ if(category === 'builtin' || this.plugins[category]) {
+ this.checks[category][rule].apply(
+ this.plugins[category] || this, args
+ );
+ }
+ }
+ }
+ }
+}
+
+var rmove = /^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,
+ rrender = /^prerender|show\.ready/i;
+
+PROTOTYPE.set = function(option, value) {
+ if(this.destroyed) { return this; }
+
+ var rendered = this.rendered,
+ reposition = FALSE,
+ options = this.options,
+ checks = this.checks,
+ name;
+
+ // Convert singular option/value pair into object form
+ if('string' === typeof option) {
+ name = option; option = {}; option[name] = value;
+ }
+ else { option = $.extend({}, option); }
+
+ // Set all of the defined options to their new values
+ $.each(option, function(notation, value) {
+ if(!rendered && !rrender.test(notation)) {
+ delete option[notation]; return;
+ }
+
+ // Set new obj value
+ var obj = convertNotation(options, notation.toLowerCase()), previous;
+ previous = obj[0][ obj[1] ];
+ obj[0][ obj[1] ] = value && value.nodeType ? $(value) : value;
+
+ // Also check if we need to reposition
+ reposition = rmove.test(notation) || reposition;
+
+ // Set the new params for the callback
+ option[notation] = [obj[0], obj[1], value, previous];
+ });
+
+ // Re-sanitize options
+ sanitizeOptions(options);
+
+ /*
+ * Execute any valid callbacks for the set options
+ * Also set positioning flag so we don't get loads of redundant repositioning calls.
+ */
+ this.positioning = TRUE;
+ $.each(option, $.proxy(setCallback, this));
+ this.positioning = FALSE;
+
+ // Update position if needed
+ if(this.rendered && this.tooltip[0].offsetWidth > 0 && reposition) {
+ this.reposition( options.position.target === 'mouse' ? NULL : this.cache.event );
+ }
+
+ return this;
+};
+
+;PROTOTYPE._update = function(content, element, reposition) {
+ var self = this,
+ cache = this.cache;
+
+ // Make sure tooltip is rendered and content is defined. If not return
+ if(!this.rendered || !content) { return FALSE; }
+
+ // Use function to parse content
+ if($.isFunction(content)) {
+ content = content.call(this.elements.target, cache.event, this) || '';
+ }
+
+ // Handle deferred content
+ if($.isFunction(content.then)) {
+ cache.waiting = TRUE;
+ return content.then(function(c) {
+ cache.waiting = FALSE;
+ return self._update(c, element);
+ }, NULL, function(e) {
+ return self._update(e, element);
+ });
+ }
+
+ // If content is null... return false
+ if(content === FALSE || (!content && content !== '')) { return FALSE; }
+
+ // Append new content if its a DOM array and show it if hidden
+ if(content.jquery && content.length > 0) {
+ element.children().detach().end().append( content.css({ display: 'block' }) );
+ }
+
+ // Content is a regular string, insert the new content
+ else { element.html(content); }
+
+ // If imagesLoaded is included, ensure images have loaded and return promise
+ cache.waiting = TRUE;
+
+ return ( $.fn.imagesLoaded ? element.imagesLoaded() : $.Deferred().resolve($([])) )
+ .done(function(images) {
+ cache.waiting = FALSE;
+
+ // Reposition if rendered
+ if(images.length && self.rendered && self.tooltip[0].offsetWidth > 0) {
+ self.reposition(cache.event, !images.length);
+ }
+ })
+ .promise();
+};
+
+PROTOTYPE._updateContent = function(content, reposition) {
+ this._update(content, this.elements.content, reposition);
+};
+
+PROTOTYPE._updateTitle = function(content, reposition) {
+ if(this._update(content, this.elements.title, reposition) === FALSE) {
+ this._removeTitle(FALSE);
+ }
+};
+
+PROTOTYPE._createTitle = function()
+{
+ var elements = this.elements,
+ id = this._id+'-title';
+
+ // Destroy previous title element, if present
+ if(elements.titlebar) { this._removeTitle(); }
+
+ // Create title bar and title elements
+ elements.titlebar = $('<div />', {
+ 'class': NAMESPACE + '-titlebar ' + (this.options.style.widget ? createWidgetClass('header') : '')
+ })
+ .append(
+ elements.title = $('<div />', {
+ 'id': id,
+ 'class': NAMESPACE + '-title',
+ 'aria-atomic': TRUE
+ })
+ )
+ .insertBefore(elements.content)
+
+ // Button-specific events
+ .delegate('.qtip-close', 'mousedown keydown mouseup keyup mouseout', function(event) {
+ $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down');
+ })
+ .delegate('.qtip-close', 'mouseover mouseout', function(event){
+ $(this).toggleClass('ui-state-hover', event.type === 'mouseover');
+ });
+
+ // Create button if enabled
+ if(this.options.content.button) { this._createButton(); }
+};
+
+PROTOTYPE._removeTitle = function(reposition)
+{
+ var elements = this.elements;
+
+ if(elements.title) {
+ elements.titlebar.remove();
+ elements.titlebar = elements.title = elements.button = NULL;
+
+ // Reposition if enabled
+ if(reposition !== FALSE) { this.reposition(); }
+ }
+};
+
+;PROTOTYPE.reposition = function(event, effect) {
+ if(!this.rendered || this.positioning || this.destroyed) { return this; }
+
+ // Set positioning flag
+ this.positioning = TRUE;
+
+ var cache = this.cache,
+ tooltip = this.tooltip,
+ posOptions = this.options.position,
+ target = posOptions.target,
+ my = posOptions.my,
+ at = posOptions.at,
+ viewport = posOptions.viewport,
+ container = posOptions.container,
+ adjust = posOptions.adjust,
+ method = adjust.method.split(' '),
+ elemWidth = tooltip.outerWidth(FALSE),
+ elemHeight = tooltip.outerHeight(FALSE),
+ targetWidth = 0,
+ targetHeight = 0,
+ type = tooltip.css('position'),
+ position = { left: 0, top: 0 },
+ visible = tooltip[0].offsetWidth > 0,
+ isScroll = event && event.type === 'scroll',
+ win = $(window),
+ doc = container[0].ownerDocument,
+ mouse = this.mouse,
+ pluginCalculations, offset;
+
+ // Check if absolute position was passed
+ if($.isArray(target) && target.length === 2) {
+ // Force left top and set position
+ at = { x: LEFT, y: TOP };
+ position = { left: target[0], top: target[1] };
+ }
+
+ // Check if mouse was the target
+ else if(target === 'mouse' && ((event && event.pageX) || cache.event.pageX)) {
+ // Force left top to allow flipping
+ at = { x: LEFT, y: TOP };
+
+ // Use cached event if one isn't available for positioning
+ event = mouse && mouse.pageX && (adjust.mouse || !event || !event.pageX) ? mouse :
+ (event && (event.type === 'resize' || event.type === 'scroll') ? cache.event :
+ event && event.pageX && event.type === 'mousemove' ? event :
+ (!adjust.mouse || this.options.show.distance) && cache.origin && cache.origin.pageX ? cache.origin :
+ event) || event || cache.event || mouse || {};
+
+ // Calculate body and container offset and take them into account below
+ if(type !== 'static') { position = container.offset(); }
+ if(doc.body.offsetWidth !== (window.innerWidth || doc.documentElement.clientWidth)) { offset = $(doc.body).offset(); }
+
+ // Use event coordinates for position
+ position = {
+ left: event.pageX - position.left + (offset && offset.left || 0),
+ top: event.pageY - position.top + (offset && offset.top || 0)
+ };
+
+ // Scroll events are a pain, some browsers
+ if(adjust.mouse && isScroll) {
+ position.left -= mouse.scrollX - win.scrollLeft();
+ position.top -= mouse.scrollY - win.scrollTop();
+ }
+ }
+
+ // Target wasn't mouse or absolute...
+ else {
+ // Check if event targetting is being used
+ if(target === 'event' && event && event.target && event.type !== 'scroll' && event.type !== 'resize') {
+ cache.target = $(event.target);
+ }
+ else if(target !== 'event'){
+ cache.target = $(target.jquery ? target : elements.target);
+ }
+ target = cache.target;
+
+ // Parse the target into a jQuery object and make sure there's an element present
+ target = $(target).eq(0);
+ if(target.length === 0) { return this; }
+
+ // Check if window or document is the target
+ else if(target[0] === document || target[0] === window) {
+ targetWidth = BROWSER.iOS ? window.innerWidth : target.width();
+ targetHeight = BROWSER.iOS ? window.innerHeight : target.height();
+
+ if(target[0] === window) {
+ position = {
+ top: (viewport || target).scrollTop(),
+ left: (viewport || target).scrollLeft()
+ };
+ }
+ }
+
+ // Check if the target is an <AREA> element
+ else if(PLUGINS.imagemap && target.is('area')) {
+ pluginCalculations = PLUGINS.imagemap(this, target, at, PLUGINS.viewport ? method : FALSE);
+ }
+
+ // Check if the target is an SVG element
+ else if(PLUGINS.svg && target[0].ownerSVGElement) {
+ pluginCalculations = PLUGINS.svg(this, target, at, PLUGINS.viewport ? method : FALSE);
+ }
+
+ // Otherwise use regular jQuery methods
+ else {
+ targetWidth = target.outerWidth(FALSE);
+ targetHeight = target.outerHeight(FALSE);
+ position = target.offset();
+ }
+
+ // Parse returned plugin values into proper variables
+ if(pluginCalculations) {
+ targetWidth = pluginCalculations.width;
+ targetHeight = pluginCalculations.height;
+ offset = pluginCalculations.offset;
+ position = pluginCalculations.position;
+ }
+
+ // Adjust position to take into account offset parents
+ position = this.reposition.offset(target, position, container);
+
+ // Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2-4.0 & v4.3-4.3.2)
+ if((BROWSER.iOS > 3.1 && BROWSER.iOS < 4.1) ||
+ (BROWSER.iOS >= 4.3 && BROWSER.iOS < 4.33) ||
+ (!BROWSER.iOS && type === 'fixed')
+ ){
+ position.left -= win.scrollLeft();
+ position.top -= win.scrollTop();
+ }
+
+ // Adjust position relative to target
+ if(!pluginCalculations || (pluginCalculations && pluginCalculations.adjustable !== FALSE)) {
+ position.left += at.x === RIGHT ? targetWidth : at.x === CENTER ? targetWidth / 2 : 0;
+ position.top += at.y === BOTTOM ? targetHeight : at.y === CENTER ? targetHeight / 2 : 0;
+ }
+ }
+
+ // Adjust position relative to tooltip
+ position.left += adjust.x + (my.x === RIGHT ? -elemWidth : my.x === CENTER ? -elemWidth / 2 : 0);
+ position.top += adjust.y + (my.y === BOTTOM ? -elemHeight : my.y === CENTER ? -elemHeight / 2 : 0);
+
+ // Use viewport adjustment plugin if enabled
+ if(PLUGINS.viewport) {
+ position.adjusted = PLUGINS.viewport(
+ this, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight
+ );
+
+ // Apply offsets supplied by positioning plugin (if used)
+ if(offset && position.adjusted.left) { position.left += offset.left; }
+ if(offset && position.adjusted.top) { position.top += offset.top; }
+ }
+
+ // Viewport adjustment is disabled, set values to zero
+ else { position.adjusted = { left: 0, top: 0 }; }
+
+ // tooltipmove event
+ if(!this._trigger('move', [position, viewport.elem || viewport], event)) { return this; }
+ delete position.adjusted;
+
+ // If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly
+ if(effect === FALSE || !visible || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) {
+ tooltip.css(position);
+ }
+
+ // Use custom function if provided
+ else if($.isFunction(posOptions.effect)) {
+ posOptions.effect.call(tooltip, this, $.extend({}, position));
+ tooltip.queue(function(next) {
+ // Reset attributes to avoid cross-browser rendering bugs
+ $(this).css({ opacity: '', height: '' });
+ if(BROWSER.ie) { this.style.removeAttribute('filter'); }
+
+ next();
+ });
+ }
+
+ // Set positioning flag
+ this.positioning = FALSE;
+
+ return this;
+};
+
+// Custom (more correct for qTip!) offset calculator
+PROTOTYPE.reposition.offset = function(elem, pos, container) {
+ if(!container[0]) { return pos; }
+
+ var ownerDocument = $(elem[0].ownerDocument),
+ quirks = !!BROWSER.ie && document.compatMode !== 'CSS1Compat',
+ parent = container[0],
+ scrolled, position, parentOffset, overflow;
+
+ function scroll(e, i) {
+ pos.left += i * e.scrollLeft();
+ pos.top += i * e.scrollTop();
+ }
+
+ // Compensate for non-static containers offset
+ do {
+ if((position = $.css(parent, 'position')) !== 'static') {
+ if(position === 'fixed') {
+ parentOffset = parent.getBoundingClientRect();
+ scroll(ownerDocument, -1);
+ }
+ else {
+ parentOffset = $(parent).position();
+ parentOffset.left += (parseFloat($.css(parent, 'borderLeftWidth')) || 0);
+ parentOffset.top += (parseFloat($.css(parent, 'borderTopWidth')) || 0);
+ }
+
+ pos.left -= parentOffset.left + (parseFloat($.css(parent, 'marginLeft')) || 0);
+ pos.top -= parentOffset.top + (parseFloat($.css(parent, 'marginTop')) || 0);
+
+ // If this is the first parent element with an overflow of "scroll" or "auto", store it
+ if(!scrolled && (overflow = $.css(parent, 'overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = $(parent); }
+ }
+ }
+ while((parent = parent.offsetParent));
+
+ // Compensate for containers scroll if it also has an offsetParent (or in IE quirks mode)
+ if(scrolled && (scrolled[0] !== ownerDocument[0] || quirks)) {
+ scroll(scrolled, 1);
+ }
+
+ return pos;
+};
+
+// Corner class
+var C = (CORNER = PROTOTYPE.reposition.Corner = function(corner, forceY) {
+ corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, CENTER).toLowerCase();
+ this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase();
+ this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase();
+ this.forceY = !!forceY;
+
+ var f = corner.charAt(0);
+ this.precedance = (f === 't' || f === 'b' ? Y : X);
+}).prototype;
+
+C.invert = function(z, center) {
+ this[z] = this[z] === LEFT ? RIGHT : this[z] === RIGHT ? LEFT : center || this[z];
+};
+
+C.string = function() {
+ var x = this.x, y = this.y;
+ return x === y ? x : this.precedance === Y || (this.forceY && y !== 'center') ? y+' '+x : x+' '+y;
+};
+
+C.abbrev = function() {
+ var result = this.string().split(' ');
+ return result[0].charAt(0) + (result[1] && result[1].charAt(0) || '');
+};
+
+C.clone = function() {
+ return new CORNER( this.string(), this.forceY );
+};;
+PROTOTYPE.toggle = function(state, event) {
+ var cache = this.cache,
+ options = this.options,
+ tooltip = this.tooltip;
+
+ // Try to prevent flickering when tooltip overlaps show element
+ if(event) {
+ if((/over|enter/).test(event.type) && (/out|leave/).test(cache.event.type) &&
+ options.show.target.add(event.target).length === options.show.target.length &&
+ tooltip.has(event.relatedTarget).length) {
+ return this;
+ }
+
+ // Cache event
+ cache.event = $.extend({}, event);
+ }
+
+ // If we're currently waiting and we've just hidden... stop it
+ this.waiting && !state && (this.hiddenDuringWait = TRUE);
+
+ // Render the tooltip if showing and it isn't already
+ if(!this.rendered) { return state ? this.render(1) : this; }
+ else if(this.destroyed || this.disabled) { return this; }
+
+ var type = state ? 'show' : 'hide',
+ opts = this.options[type],
+ otherOpts = this.options[ !state ? 'show' : 'hide' ],
+ posOptions = this.options.position,
+ contentOptions = this.options.content,
+ width = this.tooltip.css('width'),
+ visible = this.tooltip[0].offsetWidth > 0,
+ animate = state || opts.target.length === 1,
+ sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target,
+ identicalState, allow, showEvent, delay;
+
+ // Detect state if valid one isn't provided
+ if((typeof state).search('boolean|number')) { state = !visible; }
+
+ // Check if the tooltip is in an identical state to the new would-be state
+ identicalState = !tooltip.is(':animated') && visible === state && sameTarget;
+
+ // Fire tooltip(show/hide) event and check if destroyed
+ allow = !identicalState ? !!this._trigger(type, [90]) : NULL;
+
+ // If the user didn't stop the method prematurely and we're showing the tooltip, focus it
+ if(allow !== FALSE && state) { this.focus(event); }
+
+ // If the state hasn't changed or the user stopped it, return early
+ if(!allow || identicalState) { return this; }
+
+ // Set ARIA hidden attribute
+ $.attr(tooltip[0], 'aria-hidden', !!!state);
+
+ // Execute state specific properties
+ if(state) {
+ // Store show origin coordinates
+ cache.origin = $.extend({}, this.mouse);
+
+ // Update tooltip content & title if it's a dynamic function
+ if($.isFunction(contentOptions.text)) { this._updateContent(contentOptions.text, FALSE); }
+ if($.isFunction(contentOptions.title)) { this._updateTitle(contentOptions.title, FALSE); }
+
+ // Cache mousemove events for positioning purposes (if not already tracking)
+ if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) {
+ $(document).bind('mousemove.'+NAMESPACE, this._storeMouse);
+ trackingBound = TRUE;
+ }
+
+ // Update the tooltip position (set width first to prevent viewport/max-width issues)
+ if(!width) { tooltip.css('width', tooltip.outerWidth(FALSE)); }
+ this.reposition(event, arguments[2]);
+ if(!width) { tooltip.css('width', ''); }
+
+ // Hide other tooltips if tooltip is solo
+ if(!!opts.solo) {
+ (typeof opts.solo === 'string' ? $(opts.solo) : $(SELECTOR, opts.solo))
+ .not(tooltip).not(opts.target).qtip('hide', $.Event('tooltipsolo'));
+ }
+ }
+ else {
+ // Clear show timer if we're hiding
+ clearTimeout(this.timers.show);
+
+ // Remove cached origin on hide
+ delete cache.origin;
+
+ // Remove mouse tracking event if not needed (all tracking qTips are hidden)
+ if(trackingBound && !$(SELECTOR+'[tracking="true"]:visible', opts.solo).not(tooltip).length) {
+ $(document).unbind('mousemove.'+NAMESPACE);
+ trackingBound = FALSE;
+ }
+
+ // Blur the tooltip
+ this.blur(event);
+ }
+
+ // Define post-animation, state specific properties
+ after = $.proxy(function() {
+ if(state) {
+ // Prevent antialias from disappearing in IE by removing filter
+ if(BROWSER.ie) { tooltip[0].style.removeAttribute('filter'); }
+
+ // Remove overflow setting to prevent tip bugs
+ tooltip.css('overflow', '');
+
+ // Autofocus elements if enabled
+ if('string' === typeof opts.autofocus) {
+ $(this.options.show.autofocus, tooltip).focus();
+ }
+
+ // If set, hide tooltip when inactive for delay period
+ this.options.show.target.trigger('qtip-'+this.id+'-inactive');
+ }
+ else {
+ // Reset CSS states
+ tooltip.css({
+ display: '',
+ visibility: '',
+ opacity: '',
+ left: '',
+ top: ''
+ });
+ }
+
+ // tooltipvisible/tooltiphidden events
+ this._trigger(state ? 'visible' : 'hidden');
+ }, this);
+
+ // If no effect type is supplied, use a simple toggle
+ if(opts.effect === FALSE || animate === FALSE) {
+ tooltip[ type ]();
+ after();
+ }
+
+ // Use custom function if provided
+ else if($.isFunction(opts.effect)) {
+ tooltip.stop(1, 1);
+ opts.effect.call(tooltip, this);
+ tooltip.queue('fx', function(n) {
+ after(); n();
+ });
+ }
+
+ // Use basic fade function by default
+ else { tooltip.fadeTo(90, state ? 1 : 0, after); }
+
+ // If inactive hide method is set, active it
+ if(state) { opts.target.trigger('qtip-'+this.id+'-inactive'); }
+
+ return this;
+};
+
+PROTOTYPE.show = function(event) { return this.toggle(TRUE, event); };
+
+PROTOTYPE.hide = function(event) { return this.toggle(FALSE, event); };
+
+;PROTOTYPE.focus = function(event) {
+ if(!this.rendered || this.destroyed) { return this; }
+
+ var qtips = $(SELECTOR),
+ tooltip = this.tooltip,
+ curIndex = parseInt(tooltip[0].style.zIndex, 10),
+ newIndex = QTIP.zindex + qtips.length,
+ focusedElem;
+
+ // Only update the z-index if it has changed and tooltip is not already focused
+ if(!tooltip.hasClass(CLASS_FOCUS)) {
+ // tooltipfocus event
+ if(this._trigger('focus', [newIndex], event)) {
+ // Only update z-index's if they've changed
+ if(curIndex !== newIndex) {
+ // Reduce our z-index's and keep them properly ordered
+ qtips.each(function() {
+ if(this.style.zIndex > curIndex) {
+ this.style.zIndex = this.style.zIndex - 1;
+ }
+ });
+
+ // Fire blur event for focused tooltip
+ qtips.filter('.' + CLASS_FOCUS).qtip('blur', event);
+ }
+
+ // Set the new z-index
+ tooltip.addClass(CLASS_FOCUS)[0].style.zIndex = newIndex;
+ }
+ }
+
+ return this;
+};
+
+PROTOTYPE.blur = function(event) {
+ if(!this.rendered || this.destroyed) { return this; }
+
+ // Set focused status to FALSE
+ this.tooltip.removeClass(CLASS_FOCUS);
+
+ // tooltipblur event
+ this._trigger('blur', [ this.tooltip.css('zIndex') ], event);
+
+ return this;
+};
+
+;PROTOTYPE.disable = function(state) {
+ if(this.destroyed) { return this; }
+
+ if('boolean' !== typeof state) {
+ state = !(this.tooltip.hasClass(CLASS_DISABLED) || this.disabled);
+ }
+
+ if(this.rendered) {
+ this.tooltip.toggleClass(CLASS_DISABLED, state)
+ .attr('aria-disabled', state);
+ }
+
+ this.disabled = !!state;
+
+ return this;
+};
+
+PROTOTYPE.enable = function() { return this.disable(FALSE); };
+
+;PROTOTYPE._createButton = function()
+{
+ var self = this,
+ elements = this.elements,
+ tooltip = elements.tooltip,
+ button = this.options.content.button,
+ isString = typeof button === 'string',
+ close = isString ? button : 'Close tooltip';
+
+ if(elements.button) { elements.button.remove(); }
+
+ // Use custom button if one was supplied by user, else use default
+ if(button.jquery) {
+ elements.button = button;
+ }
+ else {
+ elements.button = $('<a />', {
+ 'class': 'qtip-close ' + (this.options.style.widget ? '' : NAMESPACE+'-icon'),
+ 'title': close,
+ 'aria-label': close
+ })
+ .prepend(
+ $('<span />', {
+ 'class': 'ui-icon ui-icon-close',
+ 'html': '&times;'
+ })
+ );
+ }
+
+ // Create button and setup attributes
+ elements.button.appendTo(elements.titlebar || tooltip)
+ .attr('role', 'button')
+ .click(function(event) {
+ if(!tooltip.hasClass(CLASS_DISABLED)) { self.hide(event); }
+ return FALSE;
+ });
+};
+
+PROTOTYPE._updateButton = function(button)
+{
+ // Make sure tooltip is rendered and if not, return
+ if(!this.rendered) { return FALSE; }
+
+ var elem = this.elements.button;
+ if(button) { this._createButton(); }
+ else { elem.remove(); }
+};
+
+;// Widget class creator
+function createWidgetClass(cls) {
+ return WIDGET.concat('').join(cls ? '-'+cls+' ' : ' ');
+}
+
+// Widget class setter method
+PROTOTYPE._setWidget = function()
+{
+ var on = this.options.style.widget,
+ elements = this.elements,
+ tooltip = elements.tooltip,
+ disabled = tooltip.hasClass(CLASS_DISABLED);
+
+ tooltip.removeClass(CLASS_DISABLED);
+ CLASS_DISABLED = on ? 'ui-state-disabled' : 'qtip-disabled';
+ tooltip.toggleClass(CLASS_DISABLED, disabled);
+
+ tooltip.toggleClass('ui-helper-reset '+createWidgetClass(), on).toggleClass(CLASS_DEFAULT, this.options.style.def && !on);
+
+ if(elements.content) {
+ elements.content.toggleClass( createWidgetClass('content'), on);
+ }
+ if(elements.titlebar) {
+ elements.titlebar.toggleClass( createWidgetClass('header'), on);
+ }
+ if(elements.button) {
+ elements.button.toggleClass(NAMESPACE+'-icon', !on);
+ }
+};;function showMethod(event) {
+ if(this.tooltip.hasClass(CLASS_DISABLED)) { return FALSE; }
+
+ // Clear hide timers
+ clearTimeout(this.timers.show);
+ clearTimeout(this.timers.hide);
+
+ // Start show timer
+ var callback = $.proxy(function(){ this.toggle(TRUE, event); }, this);
+ if(this.options.show.delay > 0) {
+ this.timers.show = setTimeout(callback, this.options.show.delay);
+ }
+ else{ callback(); }
+}
+
+function hideMethod(event) {
+ if(this.tooltip.hasClass(CLASS_DISABLED)) { return FALSE; }
+
+ // Check if new target was actually the tooltip element
+ var relatedTarget = $(event.relatedTarget),
+ ontoTooltip = relatedTarget.closest(SELECTOR)[0] === this.tooltip[0],
+ ontoTarget = relatedTarget[0] === this.options.show.target[0];
+
+ // Clear timers and stop animation queue
+ clearTimeout(this.timers.show);
+ clearTimeout(this.timers.hide);
+
+ // Prevent hiding if tooltip is fixed and event target is the tooltip.
+ // Or if mouse positioning is enabled and cursor momentarily overlaps
+ if(this !== relatedTarget[0] &&
+ (this.options.position.target === 'mouse' && ontoTooltip) ||
+ (this.options.hide.fixed && (
+ (/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget))
+ ))
+ {
+ try {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ } catch(e) {}
+
+ return;
+ }
+
+ // If tooltip has displayed, start hide timer
+ var callback = $.proxy(function(){ this.toggle(FALSE, event); }, this);
+ if(this.options.hide.delay > 0) {
+ this.timers.hide = setTimeout(callback, this.options.hide.delay);
+ }
+ else{ callback(); }
+}
+
+function inactiveMethod(event) {
+ if(this.tooltip.hasClass(CLASS_DISABLED) || !this.options.hide.inactive) { return FALSE; }
+
+ // Clear timer
+ clearTimeout(this.timers.inactive);
+ this.timers.inactive = setTimeout(
+ $.proxy(function(){ this.hide(event); }, this), this.options.hide.inactive
+ );
+}
+
+function repositionMethod(event) {
+ if(this.rendered && this.tooltip[0].offsetWidth > 0) { this.reposition(event); }
+}
+
+// Store mouse coordinates
+PROTOTYPE._storeMouse = function(event) {
+ this.mouse = {
+ pageX: event.pageX,
+ pageY: event.pageY,
+ type: 'mousemove',
+ scrollX: window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft,
+ scrollY: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
+ };
+};
+
+// Bind events
+PROTOTYPE._bind = function(targets, events, method, suffix, context) {
+ var ns = '.' + this._id + (suffix ? '-'+suffix : '');
+ events.length && $(targets).bind(
+ (events.split ? events : events.join(ns + ' ')) + ns,
+ $.proxy(method, context || this)
+ );
+};
+PROTOTYPE._unbind = function(targets, suffix) {
+ $(targets).unbind('.' + this._id + (suffix ? '-'+suffix : ''));
+};
+
+// Apply common event handlers using delegate (avoids excessive .bind calls!)
+var ns = '.'+NAMESPACE;
+function delegate(selector, events, method) {
+ $(document.body).delegate(selector,
+ (events.split ? events : events.join(ns + ' ')) + ns,
+ function() {
+ var api = QTIP.api[ $.attr(this, ATTR_ID) ];
+ api && !api.disabled && method.apply(api, arguments);
+ }
+ );
+}
+
+$(function() {
+ delegate(SELECTOR, ['mouseenter', 'mouseleave'], function(event) {
+ var state = event.type === 'mouseenter',
+ tooltip = $(event.currentTarget),
+ target = $(event.relatedTarget || event.target),
+ options = this.options;
+
+ // On mouseenter...
+ if(state) {
+ // Focus the tooltip on mouseenter (z-index stacking)
+ this.focus(event);
+
+ // Clear hide timer on tooltip hover to prevent it from closing
+ tooltip.hasClass(CLASS_FIXED) && !tooltip.hasClass(CLASS_DISABLED) && clearTimeout(this.timers.hide);
+ }
+
+ // On mouseleave...
+ else {
+ // Hide when we leave the tooltip and not onto the show target (if a hide event is set)
+ if(options.position.target === 'mouse' && options.hide.event &&
+ options.show.target && !target.closest(options.show.target[0]).length) {
+ this.hide(event);
+ }
+ }
+
+ // Add hover class
+ tooltip.toggleClass(CLASS_HOVER, state);
+ });
+
+ // Define events which reset the 'inactive' event handler
+ delegate('['+ATTR_ID+']', INACTIVE_EVENTS, inactiveMethod);
+});
+
+// Event trigger
+PROTOTYPE._trigger = function(type, args, event) {
+ var callback = $.Event('tooltip'+type);
+ callback.originalEvent = (event && $.extend({}, event)) || this.cache.event || NULL;
+
+ this.triggering = TRUE;
+ this.tooltip.trigger(callback, [this].concat(args || []));
+ this.triggering = FALSE;
+
+ return !callback.isDefaultPrevented();
+};
+
+// Event assignment method
+PROTOTYPE._assignEvents = function() {
+ var options = this.options,
+ posOptions = options.position,
+
+ tooltip = this.tooltip,
+ showTarget = options.show.target,
+ hideTarget = options.hide.target,
+ containerTarget = posOptions.container,
+ viewportTarget = posOptions.viewport,
+ documentTarget = $(document),
+ bodyTarget = $(document.body),
+ windowTarget = $(window),
+
+ showEvents = options.show.event ? $.trim('' + options.show.event).split(' ') : [],
+ hideEvents = options.hide.event ? $.trim('' + options.hide.event).split(' ') : [],
+ toggleEvents = [];
+
+ // Hide tooltips when leaving current window/frame (but not select/option elements)
+ if(/mouse(out|leave)/i.test(options.hide.event) && options.hide.leave === 'window') {
+ this._bind(documentTarget, ['mouseout', 'blur'], function(event) {
+ if(!/select|option/.test(event.target.nodeName) && !event.relatedTarget) {
+ this.hide(event);
+ }
+ });
+ }
+
+ // Enable hide.fixed by adding appropriate class
+ if(options.hide.fixed) {
+ hideTarget = hideTarget.add( tooltip.addClass(CLASS_FIXED) );
+ }
+
+ /*
+ * Make sure hoverIntent functions properly by using mouseleave to clear show timer if
+ * mouseenter/mouseout is used for show.event, even if it isn't in the users options.
+ */
+ else if(/mouse(over|enter)/i.test(options.show.event)) {
+ this._bind(hideTarget, 'mouseleave', function() {
+ clearTimeout(this.timers.show);
+ });
+ }
+
+ // Hide tooltip on document mousedown if unfocus events are enabled
+ if(('' + options.hide.event).indexOf('unfocus') > -1) {
+ this._bind(containerTarget.closest('html'), ['mousedown', 'touchstart'], function(event) {
+ var elem = $(event.target),
+ enabled = this.rendered && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0,
+ isAncestor = elem.parents(SELECTOR).filter(this.tooltip[0]).length > 0;
+
+ if(elem[0] !== this.target[0] && elem[0] !== this.tooltip[0] && !isAncestor &&
+ !this.target.has(elem[0]).length && enabled
+ ) {
+ this.hide(event);
+ }
+ });
+ }
+
+ // Check if the tooltip hides when inactive
+ if('number' === typeof options.hide.inactive) {
+ // Bind inactive method to show target(s) as a custom event
+ this._bind(showTarget, 'qtip-'+this.id+'-inactive', inactiveMethod);
+
+ // Define events which reset the 'inactive' event handler
+ this._bind(hideTarget.add(tooltip), QTIP.inactiveEvents, inactiveMethod, '-inactive');
+ }
+
+ // Apply hide events (and filter identical show events)
+ hideEvents = $.map(hideEvents, function(type) {
+ var showIndex = $.inArray(type, showEvents);
+
+ // Both events and targets are identical, apply events using a toggle
+ if((showIndex > -1 && hideTarget.add(showTarget).length === hideTarget.length)) {
+ toggleEvents.push( showEvents.splice( showIndex, 1 )[0] ); return;
+ }
+
+ return type;
+ });
+
+ // Apply show/hide/toggle events
+ this._bind(showTarget, showEvents, showMethod);
+ this._bind(hideTarget, hideEvents, hideMethod);
+ this._bind(showTarget, toggleEvents, function(event) {
+ (this.tooltip[0].offsetWidth > 0 ? hideMethod : showMethod).call(this, event);
+ });
+
+
+ // Mouse movement bindings
+ this._bind(showTarget.add(tooltip), 'mousemove', function(event) {
+ // Check if the tooltip hides when mouse is moved a certain distance
+ if('number' === typeof options.hide.distance) {
+ var origin = this.cache.origin || {},
+ limit = this.options.hide.distance,
+ abs = Math.abs;
+
+ // Check if the movement has gone beyond the limit, and hide it if so
+ if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) {
+ this.hide(event);
+ }
+ }
+
+ // Cache mousemove coords on show targets
+ this._storeMouse(event);
+ });
+
+ // Mouse positioning events
+ if(posOptions.target === 'mouse') {
+ // If mouse adjustment is on...
+ if(posOptions.adjust.mouse) {
+ // Apply a mouseleave event so we don't get problems with overlapping
+ if(options.hide.event) {
+ // Track if we're on the target or not
+ this._bind(showTarget, ['mouseenter', 'mouseleave'], function(event) {
+ this.cache.onTarget = event.type === 'mouseenter';
+ });
+ }
+
+ // Update tooltip position on mousemove
+ this._bind(documentTarget, 'mousemove', function(event) {
+ // Update the tooltip position only if the tooltip is visible and adjustment is enabled
+ if(this.rendered && this.cache.onTarget && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0) {
+ this.reposition(event);
+ }
+ });
+ }
+ }
+
+ // Adjust positions of the tooltip on window resize if enabled
+ if(posOptions.adjust.resize || viewportTarget.length) {
+ this._bind( $.event.special.resize ? viewportTarget : windowTarget, 'resize', repositionMethod );
+ }
+
+ // Adjust tooltip position on scroll of the window or viewport element if present
+ if(posOptions.adjust.scroll) {
+ this._bind( windowTarget.add(posOptions.container), 'scroll', repositionMethod );
+ }
+};
+
+// Un-assignment method
+PROTOTYPE._unassignEvents = function() {
+ var targets = [
+ this.options.show.target[0],
+ this.options.hide.target[0],
+ this.rendered && this.tooltip[0],
+ this.options.position.container[0],
+ this.options.position.viewport[0],
+ this.options.position.container.closest('html')[0], // unfocus
+ window,
+ document
+ ];
+
+ // Check if tooltip is rendered
+ if(this.rendered) {
+ this._unbind($([]).pushStack( $.grep(targets, function(i) {
+ return typeof i === 'object';
+ })));
+ }
+
+ // Tooltip isn't yet rendered, remove render event
+ else { $(targets[0]).unbind('.'+this._id+'-create'); }
+};
+
+;// Initialization method
+function init(elem, id, opts)
+{
+ var obj, posOptions, attr, config, title,
+
+ // Setup element references
+ docBody = $(document.body),
+
+ // Use document body instead of document element if needed
+ newTarget = elem[0] === document ? docBody : elem,
+
+ // Grab metadata from element if plugin is present
+ metadata = (elem.metadata) ? elem.metadata(opts.metadata) : NULL,
+
+ // If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise
+ metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL,
+
+ // Grab data from metadata.name (or data-qtipopts as fallback) using .data() method,
+ html5 = elem.data(opts.metadata.name || 'qtipopts');
+
+ // If we don't get an object returned attempt to parse it manualyl without parseJSON
+ try { html5 = typeof html5 === 'string' ? $.parseJSON(html5) : html5; } catch(e) {}
+
+ // Merge in and sanitize metadata
+ config = $.extend(TRUE, {}, QTIP.defaults, opts,
+ typeof html5 === 'object' ? sanitizeOptions(html5) : NULL,
+ sanitizeOptions(metadata5 || metadata));
+
+ // Re-grab our positioning options now we've merged our metadata and set id to passed value
+ posOptions = config.position;
+ config.id = id;
+
+ // Setup missing content if none is detected
+ if('boolean' === typeof config.content.text) {
+ attr = elem.attr(config.content.attr);
+
+ // Grab from supplied attribute if available
+ if(config.content.attr !== FALSE && attr) { config.content.text = attr; }
+
+ // No valid content was found, abort render
+ else { return FALSE; }
+ }
+
+ // Setup target options
+ if(!posOptions.container.length) { posOptions.container = docBody; }
+ if(posOptions.target === FALSE) { posOptions.target = newTarget; }
+ if(config.show.target === FALSE) { config.show.target = newTarget; }
+ if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); }
+ if(config.hide.target === FALSE) { config.hide.target = newTarget; }
+ if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; }
+
+ // Ensure we only use a single container
+ posOptions.container = posOptions.container.eq(0);
+
+ // Convert position corner values into x and y strings
+ posOptions.at = new CORNER(posOptions.at, TRUE);
+ posOptions.my = new CORNER(posOptions.my);
+
+ // Destroy previous tooltip if overwrite is enabled, or skip element if not
+ if(elem.data(NAMESPACE)) {
+ if(config.overwrite) {
+ elem.qtip('destroy');
+ }
+ else if(config.overwrite === FALSE) {
+ return FALSE;
+ }
+ }
+
+ // Add has-qtip attribute
+ elem.attr(ATTR_HAS, id);
+
+ // Remove title attribute and store it if present
+ if(config.suppress && (title = elem.attr('title'))) {
+ // Final attr call fixes event delegatiom and IE default tooltip showing problem
+ elem.removeAttr('title').attr(oldtitle, title).attr('title', '');
+ }
+
+ // Initialize the tooltip and add API reference
+ obj = new QTip(elem, config, id, !!attr);
+ elem.data(NAMESPACE, obj);
+
+ // Catch remove/removeqtip events on target element to destroy redundant tooltip
+ elem.one('remove.qtip-'+id+' removeqtip.qtip-'+id, function() {
+ var api; if((api = $(this).data(NAMESPACE))) { api.destroy(); }
+ });
+
+ return obj;
+}
+
+// jQuery $.fn extension method
+QTIP = $.fn.qtip = function(options, notation, newValue)
+{
+ var command = ('' + options).toLowerCase(), // Parse command
+ returned = NULL,
+ args = $.makeArray(arguments).slice(1),
+ event = args[args.length - 1],
+ opts = this[0] ? $.data(this[0], NAMESPACE) : NULL;
+
+ // Check for API request
+ if((!arguments.length && opts) || command === 'api') {
+ return opts;
+ }
+
+ // Execute API command if present
+ else if('string' === typeof options)
+ {
+ this.each(function()
+ {
+ var api = $.data(this, NAMESPACE);
+ if(!api) { return TRUE; }
+
+ // Cache the event if possible
+ if(event && event.timeStamp) { api.cache.event = event; }
+
+ // Check for specific API commands
+ if(notation && (command === 'option' || command === 'options')) {
+ if(newValue !== undefined || $.isPlainObject(notation)) {
+ api.set(notation, newValue);
+ }
+ else {
+ returned = api.get(notation);
+ return FALSE;
+ }
+ }
+
+ // Execute API command
+ else if(api[command]) {
+ api[command].apply(api, args);
+ }
+ });
+
+ return returned !== NULL ? returned : this;
+ }
+
+ // No API commands. validate provided options and setup qTips
+ else if('object' === typeof options || !arguments.length)
+ {
+ opts = sanitizeOptions($.extend(TRUE, {}, options));
+
+ // Bind the qTips
+ return QTIP.bind.call(this, opts, event);
+ }
+};
+
+// $.fn.qtip Bind method
+QTIP.bind = function(opts, event)
+{
+ return this.each(function(i) {
+ var options, targets, events, namespace, api, id;
+
+ // Find next available ID, or use custom ID if provided
+ id = $.isArray(opts.id) ? opts.id[i] : opts.id;
+ id = !id || id === FALSE || id.length < 1 || QTIP.api[id] ? QTIP.nextid++ : id;
+
+ // Setup events namespace
+ namespace = '.qtip-'+id+'-create';
+
+ // Initialize the qTip and re-grab newly sanitized options
+ api = init($(this), id, opts);
+ if(api === FALSE) { return TRUE; }
+ else { QTIP.api[id] = api; }
+ options = api.options;
+
+ // Initialize plugins
+ $.each(PLUGINS, function() {
+ if(this.initialize === 'initialize') { this(api); }
+ });
+
+ // Determine hide and show targets
+ targets = { show: options.show.target, hide: options.hide.target };
+ events = {
+ show: $.trim('' + options.show.event).replace(/ /g, namespace+' ') + namespace,
+ hide: $.trim('' + options.hide.event).replace(/ /g, namespace+' ') + namespace
+ };
+
+ /*
+ * Make sure hoverIntent functions properly by using mouseleave as a hide event if
+ * mouseenter/mouseout is used for show.event, even if it isn't in the users options.
+ */
+ if(/mouse(over|enter)/i.test(events.show) && !/mouse(out|leave)/i.test(events.hide)) {
+ events.hide += ' mouseleave' + namespace;
+ }
+
+ /*
+ * Also make sure initial mouse targetting works correctly by caching mousemove coords
+ * on show targets before the tooltip has rendered.
+ *
+ * Also set onTarget when triggered to keep mouse tracking working
+ */
+ targets.show.bind('mousemove'+namespace, function(event) {
+ api._storeMouse(event);
+ api.cache.onTarget = TRUE;
+ });
+
+ // Define hoverIntent function
+ function hoverIntent(event) {
+ function render() {
+ // Cache mouse coords,render and render the tooltip
+ api.render(typeof event === 'object' || options.show.ready);
+
+ // Unbind show and hide events
+ targets.show.add(targets.hide).unbind(namespace);
+ }
+
+ // Only continue if tooltip isn't disabled
+ if(api.disabled) { return FALSE; }
+
+ // Cache the event data
+ api.cache.event = $.extend({}, event);
+ api.cache.target = event ? $(event.target) : [undefined];
+
+ // Start the event sequence
+ if(options.show.delay > 0) {
+ clearTimeout(api.timers.show);
+ api.timers.show = setTimeout(render, options.show.delay);
+ if(events.show !== events.hide) {
+ targets.hide.bind(events.hide, function() { clearTimeout(api.timers.show); });
+ }
+ }
+ else { render(); }
+ }
+
+ // Bind show events to target
+ targets.show.bind(events.show, hoverIntent);
+
+ // Prerendering is enabled, create tooltip now
+ if(options.show.ready || options.prerender) { hoverIntent(event); }
+ });
+};
+
+// Populated in render method
+QTIP.api = {};
+;$.each({
+ /* Allow other plugins to successfully retrieve the title of an element with a qTip applied */
+ attr: function(attr, val) {
+ if(this.length) {
+ var self = this[0],
+ title = 'title',
+ api = $.data(self, 'qtip');
+
+ if(attr === title && api && 'object' === typeof api && api.options.suppress) {
+ if(arguments.length < 2) {
+ return $.attr(self, oldtitle);
+ }
+
+ // If qTip is rendered and title was originally used as content, update it
+ if(api && api.options.content.attr === title && api.cache.attr) {
+ api.set('content.text', val);
+ }
+
+ // Use the regular attr method to set, then cache the result
+ return this.attr(oldtitle, val);
+ }
+ }
+
+ return $.fn['attr'+replaceSuffix].apply(this, arguments);
+ },
+
+ /* Allow clone to correctly retrieve cached title attributes */
+ clone: function(keepData) {
+ var titles = $([]), title = 'title',
+
+ // Clone our element using the real clone method
+ elems = $.fn['clone'+replaceSuffix].apply(this, arguments);
+
+ // Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false
+ if(!keepData) {
+ elems.filter('['+oldtitle+']').attr('title', function() {
+ return $.attr(this, oldtitle);
+ })
+ .removeAttr(oldtitle);
+ }
+
+ return elems;
+ }
+}, function(name, func) {
+ if(!func || $.fn[name+replaceSuffix]) { return TRUE; }
+
+ var old = $.fn[name+replaceSuffix] = $.fn[name];
+ $.fn[name] = function() {
+ return func.apply(this, arguments) || old.apply(this, arguments);
+ };
+});
+
+/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar).
+ * This snippet is taken directly from jQuery UI source code found here:
+ * http://code.jquery.com/ui/jquery-ui-git.js
+ */
+if(!$.ui) {
+ $['cleanData'+replaceSuffix] = $.cleanData;
+ $.cleanData = function( elems ) {
+ for(var i = 0, elem; (elem = $( elems[i] )).length; i++) {
+ if(elem.attr(ATTR_HAS)) {
+ try { elem.triggerHandler('removeqtip'); }
+ catch( e ) {}
+ }
+ }
+ $['cleanData'+replaceSuffix].apply(this, arguments);
+ };
+}
+
+;// qTip version
+QTIP.version = '2.1.1';
+
+// Base ID for all qTips
+QTIP.nextid = 0;
+
+// Inactive events array
+QTIP.inactiveEvents = INACTIVE_EVENTS;
+
+// Base z-index for all qTips
+QTIP.zindex = 15000;
+
+// Define configuration defaults
+QTIP.defaults = {
+ prerender: FALSE,
+ id: FALSE,
+ overwrite: TRUE,
+ suppress: TRUE,
+ content: {
+ text: TRUE,
+ attr: 'title',
+ title: FALSE,
+ button: FALSE
+ },
+ position: {
+ my: 'top left',
+ at: 'bottom right',
+ target: FALSE,
+ container: FALSE,
+ viewport: FALSE,
+ adjust: {
+ x: 0, y: 0,
+ mouse: TRUE,
+ scroll: TRUE,
+ resize: TRUE,
+ method: 'flipinvert flipinvert'
+ },
+ effect: function(api, pos, viewport) {
+ $(this).animate(pos, {
+ duration: 200,
+ queue: FALSE
+ });
+ }
+ },
+ show: {
+ target: FALSE,
+ event: 'mouseenter',
+ effect: TRUE,
+ delay: 90,
+ solo: FALSE,
+ ready: FALSE,
+ autofocus: FALSE
+ },
+ hide: {
+ target: FALSE,
+ event: 'mouseleave',
+ effect: TRUE,
+ delay: 0,
+ fixed: FALSE,
+ inactive: FALSE,
+ leave: 'window',
+ distance: FALSE
+ },
+ style: {
+ classes: '',
+ widget: FALSE,
+ width: FALSE,
+ height: FALSE,
+ def: TRUE
+ },
+ events: {
+ render: NULL,
+ move: NULL,
+ show: NULL,
+ hide: NULL,
+ toggle: NULL,
+ visible: NULL,
+ hidden: NULL,
+ focus: NULL,
+ blur: NULL
+ }
+};
+
+;var TIP,
+
+// .bind()/.on() namespace
+TIPNS = '.qtip-tip',
+
+// Common CSS strings
+MARGIN = 'margin',
+BORDER = 'border',
+COLOR = 'color',
+BG_COLOR = 'background-color',
+TRANSPARENT = 'transparent',
+IMPORTANT = ' !important',
+
+// Check if the browser supports <canvas/> elements
+HASCANVAS = !!document.createElement('canvas').getContext,
+
+// Invalid colour values used in parseColours()
+INVALID = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i;
+
+// Camel-case method, taken from jQuery source
+// http://code.jquery.com/jquery-1.8.0.js
+function camel(s) { return s.charAt(0).toUpperCase() + s.slice(1); }
+
+/*
+ * Modified from Modernizr's testPropsAll()
+ * http://modernizr.com/downloads/modernizr-latest.js
+ */
+var cssProps = {}, cssPrefixes = ["Webkit", "O", "Moz", "ms"];
+function vendorCss(elem, prop) {
+ var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
+ props = (prop + ' ' + cssPrefixes.join(ucProp + ' ') + ucProp).split(' '),
+ cur, val, i = 0;
+
+ // If the property has already been mapped...
+ if(cssProps[prop]) { return elem.css(cssProps[prop]); }
+
+ while((cur = props[i++])) {
+ if((val = elem.css(cur)) !== undefined) {
+ return cssProps[prop] = cur, val;
+ }
+ }
+}
+
+// Parse a given elements CSS property into an int
+function intCss(elem, prop) {
+ return parseInt(vendorCss(elem, prop), 10);
+}
+
+
+// VML creation (for IE only)
+if(!HASCANVAS) {
+ createVML = function(tag, props, style) {
+ return '<qtipvml:'+tag+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(props||'')+
+ ' style="behavior: url(#default#VML); '+(style||'')+ '" />';
+ };
+}
+
+
+
+function Tip(qtip, options) {
+ this._ns = 'tip';
+ this.options = options;
+ this.offset = options.offset;
+ this.size = [ options.width, options.height ];
+
+ // Initialize
+ this.init( (this.qtip = qtip) );
+}
+
+$.extend(Tip.prototype, {
+ init: function(qtip) {
+ var context, tip;
+
+ // Create tip element and prepend to the tooltip
+ tip = this.element = qtip.elements.tip = $('<div />', { 'class': NAMESPACE+'-tip' }).prependTo(qtip.tooltip);
+
+ // Create tip drawing element(s)
+ if(HASCANVAS) {
+ // save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()!
+ context = $('<canvas />').appendTo(this.element)[0].getContext('2d');
+
+ // Setup constant parameters
+ context.lineJoin = 'miter';
+ context.miterLimit = 100;
+ context.save();
+ }
+ else {
+ context = createVML('shape', 'coordorigin="0,0"', 'position:absolute;');
+ this.element.html(context + context);
+
+ // Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML
+ qtip._bind( $('*', tip).add(tip), ['click', 'mousedown'], function(event) { event.stopPropagation(); }, this._ns);
+ }
+
+ // Bind update events
+ qtip._bind(qtip.tooltip, 'tooltipmove', this.reposition, this._ns, this);
+
+ // Create it
+ this.create();
+ },
+
+ _swapDimensions: function() {
+ this.size[0] = this.options.height;
+ this.size[1] = this.options.width;
+ },
+ _resetDimensions: function() {
+ this.size[0] = this.options.width;
+ this.size[1] = this.options.height;
+ },
+
+ _useTitle: function(corner) {
+ var titlebar = this.qtip.elements.titlebar;
+ return titlebar && (
+ corner.y === TOP || (corner.y === CENTER && this.element.position().top + (this.size[1] / 2) + this.options.offset < titlebar.outerHeight(TRUE))
+ );
+ },
+
+ _parseCorner: function(corner) {
+ var my = this.qtip.options.position.my;
+
+ // Detect corner and mimic properties
+ if(corner === FALSE || my === FALSE) {
+ corner = FALSE;
+ }
+ else if(corner === TRUE) {
+ corner = new CORNER( my.string() );
+ }
+ else if(!corner.string) {
+ corner = new CORNER(corner);
+ corner.fixed = TRUE;
+ }
+
+ return corner;
+ },
+
+ _parseWidth: function(corner, side, use) {
+ var elements = this.qtip.elements,
+ prop = BORDER + camel(side) + 'Width';
+
+ return (use ? intCss(use, prop) : (
+ intCss(elements.content, prop) ||
+ intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) ||
+ intCss(tooltip, prop)
+ )) || 0;
+ },
+
+ _parseRadius: function(corner) {
+ var elements = this.qtip.elements,
+ prop = BORDER + camel(corner.y) + camel(corner.x) + 'Radius';
+
+ return BROWSER.ie < 9 ? 0 :
+ intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) ||
+ intCss(elements.tooltip, prop) || 0;
+ },
+
+ _invalidColour: function(elem, prop, compare) {
+ var val = elem.css(prop);
+ return !val || (compare && val === elem.css(compare)) || INVALID.test(val) ? FALSE : val;
+ },
+
+ _parseColours: function(corner) {
+ var elements = this.qtip.elements,
+ tip = this.element.css('cssText', ''),
+ borderSide = BORDER + camel(corner[ corner.precedance ]) + camel(COLOR),
+ colorElem = this._useTitle(corner) && elements.titlebar || elements.content,
+ css = this._invalidColour, color = [];
+
+ // Attempt to detect the background colour from various elements, left-to-right precedance
+ color[0] = css(tip, BG_COLOR) || css(colorElem, BG_COLOR) || css(elements.content, BG_COLOR) ||
+ css(tooltip, BG_COLOR) || tip.css(BG_COLOR);
+
+ // Attempt to detect the correct border side colour from various elements, left-to-right precedance
+ color[1] = css(tip, borderSide, COLOR) || css(colorElem, borderSide, COLOR) ||
+ css(elements.content, borderSide, COLOR) || css(tooltip, borderSide, COLOR) || tooltip.css(borderSide);
+
+ // Reset background and border colours
+ $('*', tip).add(tip).css('cssText', BG_COLOR+':'+TRANSPARENT+IMPORTANT+';'+BORDER+':0'+IMPORTANT+';');
+
+ return color;
+ },
+
+ _calculateSize: function(corner) {
+ var y = corner.precedance === Y,
+ width = this.options[ y ? 'height' : 'width' ],
+ height = this.options[ y ? 'width' : 'height' ],
+ isCenter = corner.abbrev() === 'c',
+ base = width * (isCenter ? 0.5 : 1),
+ pow = Math.pow,
+ round = Math.round,
+ bigHyp, ratio, result,
+
+ smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ),
+ hyp = [ (this.border / base) * smallHyp, (this.border / height) * smallHyp ];
+
+ hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(this.border, 2) );
+ hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(this.border, 2) );
+
+ bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]);
+ ratio = bigHyp / smallHyp;
+
+ result = [ round(ratio * width), round(ratio * height) ];
+
+ return y ? result : result.reverse();
+ },
+
+ // Tip coordinates calculator
+ _calculateTip: function(corner) {
+ var width = this.size[0], height = this.size[1],
+ width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2),
+
+ // Define tip coordinates in terms of height and width values
+ tips = {
+ br: [0,0, width,height, width,0],
+ bl: [0,0, width,0, 0,height],
+ tr: [0,height, width,0, width,height],
+ tl: [0,0, 0,height, width,height],
+ tc: [0,height, width2,0, width,height],
+ bc: [0,0, width,0, width2,height],
+ rc: [0,0, width,height2, 0,height],
+ lc: [width,0, width,height, 0,height2]
+ };
+
+ // Set common side shapes
+ tips.lt = tips.br; tips.rt = tips.bl;
+ tips.lb = tips.tr; tips.rb = tips.tl;
+
+ return tips[ corner.abbrev() ];
+ },
+
+ create: function() {
+ // Determine tip corner
+ var c = this.corner = (HASCANVAS || BROWSER.ie) && this._parseCorner(this.options.corner);
+
+ // If we have a tip corner...
+ if( (this.enabled = !!this.corner && this.corner.abbrev() !== 'c') ) {
+ // Cache it
+ this.qtip.cache.corner = c.clone();
+
+ // Create it
+ this.update();
+ }
+
+ // Toggle tip element
+ this.element.toggle(this.enabled);
+
+ return this.corner;
+ },
+
+ update: function(corner, position) {
+ if(!this.enabled) { return this; }
+
+ var elements = this.qtip.elements,
+ tip = this.element,
+ inner = tip.children(),
+ options = this.options,
+ size = this.size,
+ mimic = options.mimic,
+ round = Math.round,
+ color, precedance, context,
+ coords, translate, newSize, border;
+
+ // Re-determine tip if not already set
+ if(!corner) { corner = this.qtip.cache.corner || this.corner; }
+
+ // Use corner property if we detect an invalid mimic value
+ if(mimic === FALSE) { mimic = corner; }
+
+ // Otherwise inherit mimic properties from the corner object as necessary
+ else {
+ mimic = new CORNER(mimic);
+ mimic.precedance = corner.precedance;
+
+ if(mimic.x === 'inherit') { mimic.x = corner.x; }
+ else if(mimic.y === 'inherit') { mimic.y = corner.y; }
+ else if(mimic.x === mimic.y) {
+ mimic[ corner.precedance ] = corner[ corner.precedance ];
+ }
+ }
+ precedance = mimic.precedance;
+
+ // Ensure the tip width.height are relative to the tip position
+ if(corner.precedance === X) { this._swapDimensions(); }
+ else { this._resetDimensions(); }
+
+ // Update our colours
+ color = this.color = this._parseColours(corner);
+
+ // Detect border width, taking into account colours
+ if(color[1] !== TRANSPARENT) {
+ // Grab border width
+ border = this.border = this._parseWidth(corner, corner[corner.precedance]);
+
+ // If border width isn't zero, use border color as fill (1.0 style tips)
+ if(options.border && border < 1) { color[0] = color[1]; }
+
+ // Set border width (use detected border width if options.border is true)
+ this.border = border = options.border !== TRUE ? options.border : border;
+ }
+
+ // Border colour was invalid, set border to zero
+ else { this.border = border = 0; }
+
+ // Calculate coordinates
+ coords = this._calculateTip(mimic);
+
+ // Determine tip size
+ newSize = this.size = this._calculateSize(corner);
+ tip.css({
+ width: newSize[0],
+ height: newSize[1],
+ lineHeight: newSize[1]+'px'
+ });
+
+ // Calculate tip translation
+ if(corner.precedance === Y) {
+ translate = [
+ round(mimic.x === LEFT ? border : mimic.x === RIGHT ? newSize[0] - size[0] - border : (newSize[0] - size[0]) / 2),
+ round(mimic.y === TOP ? newSize[1] - size[1] : 0)
+ ];
+ }
+ else {
+ translate = [
+ round(mimic.x === LEFT ? newSize[0] - size[0] : 0),
+ round(mimic.y === TOP ? border : mimic.y === BOTTOM ? newSize[1] - size[1] - border : (newSize[1] - size[1]) / 2)
+ ];
+ }
+
+ // Canvas drawing implementation
+ if(HASCANVAS) {
+ // Set the canvas size using calculated size
+ inner.attr(WIDTH, newSize[0]).attr(HEIGHT, newSize[1]);
+
+ // Grab canvas context and clear/save it
+ context = inner[0].getContext('2d');
+ context.restore(); context.save();
+ context.clearRect(0,0,3000,3000);
+
+ // Set properties
+ context.fillStyle = color[0];
+ context.strokeStyle = color[1];
+ context.lineWidth = border * 2;
+
+ // Draw the tip
+ context.translate(translate[0], translate[1]);
+ context.beginPath();
+ context.moveTo(coords[0], coords[1]);
+ context.lineTo(coords[2], coords[3]);
+ context.lineTo(coords[4], coords[5]);
+ context.closePath();
+
+ // Apply fill and border
+ if(border) {
+ // Make sure transparent borders are supported by doing a stroke
+ // of the background colour before the stroke colour
+ if(tooltip.css('background-clip') === 'border-box') {
+ context.strokeStyle = color[0];
+ context.stroke();
+ }
+ context.strokeStyle = color[1];
+ context.stroke();
+ }
+ context.fill();
+ }
+
+ // VML (IE Proprietary implementation)
+ else {
+ // Setup coordinates string
+ coords = 'm' + coords[0] + ',' + coords[1] + ' l' + coords[2] +
+ ',' + coords[3] + ' ' + coords[4] + ',' + coords[5] + ' xe';
+
+ // Setup VML-specific offset for pixel-perfection
+ translate[2] = border && /^(r|b)/i.test(corner.string()) ?
+ BROWSER.ie === 8 ? 2 : 1 : 0;
+
+ // Set initial CSS
+ inner.css({
+ coordsize: (size[0]+border) + ' ' + (size[1]+border),
+ antialias: ''+(mimic.string().indexOf(CENTER) > -1),
+ left: translate[0] - (translate[2] * Number(precedance === X)),
+ top: translate[1] - (translate[2] * Number(precedance === Y)),
+ width: size[0] + border,
+ height: size[1] + border
+ })
+ .each(function(i) {
+ var $this = $(this);
+
+ // Set shape specific attributes
+ $this[ $this.prop ? 'prop' : 'attr' ]({
+ coordsize: (size[0]+border) + ' ' + (size[1]+border),
+ path: coords,
+ fillcolor: color[0],
+ filled: !!i,
+ stroked: !i
+ })
+ .toggle(!!(border || i));
+
+ // Check if border is enabled and add stroke element
+ !i && $this.html( createVML(
+ 'stroke', 'weight="'+(border*2)+'px" color="'+color[1]+'" miterlimit="1000" joinstyle="miter"'
+ ) );
+ });
+ }
+
+ // Position if needed
+ if(position !== FALSE) { this.calculate(corner); }
+ },
+
+ calculate: function(corner) {
+ if(!this.enabled) { return FALSE; }
+
+ var self = this,
+ elements = this.qtip.elements,
+ tip = this.element,
+ userOffset = this.options.offset,
+ isWidget = this.qtip.tooltip.hasClass('ui-widget'),
+ position = { },
+ precedance, size, corners;
+
+ // Inherit corner if not provided
+ corner = corner || this.corner;
+ precedance = corner.precedance;
+
+ // Determine which tip dimension to use for adjustment
+ size = this._calculateSize(corner);
+
+ // Setup corners and offset array
+ corners = [ corner.x, corner.y ];
+ if(precedance === X) { corners.reverse(); }
+
+ // Calculate tip position
+ $.each(corners, function(i, side) {
+ var b, bc, br;
+
+ if(side === CENTER) {
+ b = precedance === Y ? LEFT : TOP;
+ position[ b ] = '50%';
+ position[MARGIN+'-' + b] = -Math.round(size[ precedance === Y ? 0 : 1 ] / 2) + userOffset;
+ }
+ else {
+ b = self._parseWidth(corner, side, elements.tooltip);
+ bc = self._parseWidth(corner, side, elements.content);
+ br = self._parseRadius(corner);
+
+ position[ side ] = Math.max(-self.border, i ? bc : (userOffset + (br > b ? br : -b)));
+ }
+ });
+
+ // Adjust for tip size
+ position[ corner[precedance] ] -= size[ precedance === X ? 0 : 1 ];
+
+ // Set and return new position
+ tip.css({ margin: '', top: '', bottom: '', left: '', right: '' }).css(position);
+ return position;
+ },
+
+ reposition: function(event, api, pos, viewport) {
+ if(!this.enabled) { return; }
+
+ var cache = api.cache,
+ newCorner = this.corner.clone(),
+ adjust = pos.adjusted,
+ method = api.options.position.adjust.method.split(' '),
+ horizontal = method[0],
+ vertical = method[1] || method[0],
+ shift = { left: FALSE, top: FALSE, x: 0, y: 0 },
+ offset, css = {}, props;
+
+ // If our tip position isn't fixed e.g. doesn't adjust with viewport...
+ if(this.corner.fixed !== TRUE) {
+ // Horizontal - Shift or flip method
+ if(horizontal === SHIFT && newCorner.precedance === X && adjust.left && newCorner.y !== CENTER) {
+ newCorner.precedance = newCorner.precedance === X ? Y : X;
+ }
+ else if(horizontal !== SHIFT && adjust.left){
+ newCorner.x = newCorner.x === CENTER ? (adjust.left > 0 ? LEFT : RIGHT) : (newCorner.x === LEFT ? RIGHT : LEFT);
+ }
+
+ // Vertical - Shift or flip method
+ if(vertical === SHIFT && newCorner.precedance === Y && adjust.top && newCorner.x !== CENTER) {
+ newCorner.precedance = newCorner.precedance === Y ? X : Y;
+ }
+ else if(vertical !== SHIFT && adjust.top) {
+ newCorner.y = newCorner.y === CENTER ? (adjust.top > 0 ? TOP : BOTTOM) : (newCorner.y === TOP ? BOTTOM : TOP);
+ }
+
+ // Update and redraw the tip if needed (check cached details of last drawn tip)
+ if(newCorner.string() !== cache.corner.string() && (cache.cornerTop !== adjust.top || cache.cornerLeft !== adjust.left)) {
+ this.update(newCorner, FALSE);
+ }
+ }
+
+ // Setup tip offset properties
+ offset = this.calculate(newCorner, adjust);
+
+ // Readjust offset object to make it left/top
+ if(offset.right !== undefined) { offset.left = -offset.right; }
+ if(offset.bottom !== undefined) { offset.top = -offset.bottom; }
+ offset.user = this.offset;
+
+ // Viewport "shift" specific adjustments
+ if(shift.left = (horizontal === SHIFT && !!adjust.left)) {
+ if(newCorner.x === CENTER) {
+ css[MARGIN+'-left'] = shift.x = offset[MARGIN+'-left'] - adjust.left;
+ }
+ else {
+ props = offset.right !== undefined ?
+ [ adjust.left, -offset.left ] : [ -adjust.left, offset.left ];
+
+ if( (shift.x = Math.max(props[0], props[1])) > props[0] ) {
+ pos.left -= adjust.left;
+ shift.left = FALSE;
+ }
+
+ css[ offset.right !== undefined ? RIGHT : LEFT ] = shift.x;
+ }
+ }
+ if(shift.top = (vertical === SHIFT && !!adjust.top)) {
+ if(newCorner.y === CENTER) {
+ css[MARGIN+'-top'] = shift.y = offset[MARGIN+'-top'] - adjust.top;
+ }
+ else {
+ props = offset.bottom !== undefined ?
+ [ adjust.top, -offset.top ] : [ -adjust.top, offset.top ];
+
+ if( (shift.y = Math.max(props[0], props[1])) > props[0] ) {
+ pos.top -= adjust.top;
+ shift.top = FALSE;
+ }
+
+ css[ offset.bottom !== undefined ? BOTTOM : TOP ] = shift.y;
+ }
+ }
+
+ /*
+ * If the tip is adjusted in both dimensions, or in a
+ * direction that would cause it to be anywhere but the
+ * outer border, hide it!
+ */
+ this.element.css(css).toggle(
+ !((shift.x && shift.y) || (newCorner.x === CENTER && shift.y) || (newCorner.y === CENTER && shift.x))
+ );
+
+ // Adjust position to accomodate tip dimensions
+ pos.left -= offset.left.charAt ? offset.user : horizontal !== SHIFT || shift.top || !shift.left && !shift.top ? offset.left : 0;
+ pos.top -= offset.top.charAt ? offset.user : vertical !== SHIFT || shift.left || !shift.left && !shift.top ? offset.top : 0;
+
+ // Cache details
+ cache.cornerLeft = adjust.left; cache.cornerTop = adjust.top;
+ cache.corner = newCorner.clone();
+ },
+
+ destroy: function() {
+ // Unbind events
+ this.qtip._unbind(this.qtip.tooltip, this._ns);
+
+ // Remove the tip element(s)
+ if(this.qtip.elements.tip) {
+ this.qtip.elements.tip.find('*')
+ .remove().end().remove();
+ }
+ }
+});
+
+TIP = PLUGINS.tip = function(api) {
+ return new Tip(api, api.options.style.tip);
+};
+
+// Initialize tip on render
+TIP.initialize = 'render';
+
+// Setup plugin sanitization options
+TIP.sanitize = function(options) {
+ if(options.style && 'tip' in options.style) {
+ opts = options.style.tip;
+ if(typeof opts !== 'object') { opts = options.style.tip = { corner: opts }; }
+ if(!(/string|boolean/i).test(typeof opts.corner)) { opts.corner = TRUE; }
+ }
+};
+
+// Add new option checks for the plugin
+CHECKS.tip = {
+ '^position.my|style.tip.(corner|mimic|border)$': function() {
+ // Make sure a tip can be drawn
+ this.create();
+
+ // Reposition the tooltip
+ this.qtip.reposition();
+ },
+ '^style.tip.(height|width)$': function(obj) {
+ // Re-set dimensions and redraw the tip
+ this.size = size = [ obj.width, obj.height ];
+ this.update();
+
+ // Reposition the tooltip
+ this.qtip.reposition();
+ },
+ '^content.title|style.(classes|widget)$': function() {
+ this.update();
+ }
+};
+
+// Extend original qTip defaults
+$.extend(TRUE, QTIP.defaults, {
+ style: {
+ tip: {
+ corner: TRUE,
+ mimic: FALSE,
+ width: 6,
+ height: 6,
+ border: TRUE,
+ offset: 0
+ }
+ }
+});
+
+;PLUGINS.viewport = function(api, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight)
+{
+ var target = posOptions.target,
+ tooltip = api.elements.tooltip,
+ my = posOptions.my,
+ at = posOptions.at,
+ adjust = posOptions.adjust,
+ method = adjust.method.split(' '),
+ methodX = method[0],
+ methodY = method[1] || method[0],
+ viewport = posOptions.viewport,
+ container = posOptions.container,
+ cache = api.cache,
+ tip = api.plugins.tip,
+ adjusted = { left: 0, top: 0 },
+ fixed, newMy, newClass;
+
+ // If viewport is not a jQuery element, or it's the window/document or no adjustment method is used... return
+ if(!viewport.jquery || target[0] === window || target[0] === document.body || adjust.method === 'none') {
+ return adjusted;
+ }
+
+ // Cache our viewport details
+ fixed = tooltip.css('position') === 'fixed';
+ viewport = {
+ elem: viewport,
+ width: viewport[0] === window ? viewport.width() : viewport.outerWidth(FALSE),
+ height: viewport[0] === window ? viewport.height() : viewport.outerHeight(FALSE),
+ scrollleft: fixed ? 0 : viewport.scrollLeft(),
+ scrolltop: fixed ? 0 : viewport.scrollTop(),
+ offset: viewport.offset() || { left: 0, top: 0 }
+ };
+ container = {
+ elem: container,
+ scrollLeft: container.scrollLeft(),
+ scrollTop: container.scrollTop(),
+ offset: container.offset() || { left: 0, top: 0 }
+ };
+
+ // Generic calculation method
+ function calculate(side, otherSide, type, adjust, side1, side2, lengthName, targetLength, elemLength) {
+ var initialPos = position[side1],
+ mySide = my[side], atSide = at[side],
+ isShift = type === SHIFT,
+ viewportScroll = -container.offset[side1] + viewport.offset[side1] + viewport['scroll'+side1],
+ myLength = mySide === side1 ? elemLength : mySide === side2 ? -elemLength : -elemLength / 2,
+ atLength = atSide === side1 ? targetLength : atSide === side2 ? -targetLength : -targetLength / 2,
+ tipLength = tip && tip.size ? tip.size[lengthName] || 0 : 0,
+ tipAdjust = tip && tip.corner && tip.corner.precedance === side && !isShift ? tipLength : 0,
+ overflow1 = viewportScroll - initialPos + tipAdjust,
+ overflow2 = initialPos + elemLength - viewport[lengthName] - viewportScroll + tipAdjust,
+ offset = myLength - (my.precedance === side || mySide === my[otherSide] ? atLength : 0) - (atSide === CENTER ? targetLength / 2 : 0);
+
+ // shift
+ if(isShift) {
+ tipAdjust = tip && tip.corner && tip.corner.precedance === otherSide ? tipLength : 0;
+ offset = (mySide === side1 ? 1 : -1) * myLength - tipAdjust;
+
+ // Adjust position but keep it within viewport dimensions
+ position[side1] += overflow1 > 0 ? overflow1 : overflow2 > 0 ? -overflow2 : 0;
+ position[side1] = Math.max(
+ -container.offset[side1] + viewport.offset[side1] + (tipAdjust && tip.corner[side] === CENTER ? tip.offset : 0),
+ initialPos - offset,
+ Math.min(
+ Math.max(-container.offset[side1] + viewport.offset[side1] + viewport[lengthName], initialPos + offset),
+ position[side1]
+ )
+ );
+ }
+
+ // flip/flipinvert
+ else {
+ // Update adjustment amount depending on if using flipinvert or flip
+ adjust *= (type === FLIPINVERT ? 2 : 0);
+
+ // Check for overflow on the left/top
+ if(overflow1 > 0 && (mySide !== side1 || overflow2 > 0)) {
+ position[side1] -= offset + adjust;
+ newMy.invert(side, side1);
+ }
+
+ // Check for overflow on the bottom/right
+ else if(overflow2 > 0 && (mySide !== side2 || overflow1 > 0) ) {
+ position[side1] -= (mySide === CENTER ? -offset : offset) + adjust;
+ newMy.invert(side, side2);
+ }
+
+ // Make sure we haven't made things worse with the adjustment and reset if so
+ if(position[side1] < viewportScroll && -position[side1] > overflow2) {
+ position[side1] = initialPos; newMy = my.clone();
+ }
+ }
+
+ return position[side1] - initialPos;
+ }
+
+ // Set newMy if using flip or flipinvert methods
+ if(methodX !== 'shift' || methodY !== 'shift') { newMy = my.clone(); }
+
+ // Adjust position based onviewport and adjustment options
+ adjusted = {
+ left: methodX !== 'none' ? calculate( X, Y, methodX, adjust.x, LEFT, RIGHT, WIDTH, targetWidth, elemWidth ) : 0,
+ top: methodY !== 'none' ? calculate( Y, X, methodY, adjust.y, TOP, BOTTOM, HEIGHT, targetHeight, elemHeight ) : 0
+ };
+
+ // Set tooltip position class if it's changed
+ if(newMy && cache.lastClass !== (newClass = NAMESPACE + '-pos-' + newMy.abbrev())) {
+ tooltip.removeClass(api.cache.lastClass).addClass( (api.cache.lastClass = newClass) );
+ }
+
+ return adjusted;
+};;}));
+}( window, document ));
+
+
diff --git a/contrib/libxo/xohtml/xohtml.css b/contrib/libxo/xohtml/xohtml.css
new file mode 100644
index 0000000..655bf12
--- /dev/null
+++ b/contrib/libxo/xohtml/xohtml.css
@@ -0,0 +1,1016 @@
+/*
+ * $Id$
+ *
+ * Copyright 2000, All rights reserved
+ * See ../Copyright for more information
+ */
+
+#content-wrapper {
+ margin: 0 4px;
+}
+
+#target-history .empty {
+ color: #d0d0d0;
+ text-align:center;
+}
+
+#command-history .empty {
+ color: grey;
+ padding-left: 20px;
+}
+
+#prefs {
+ font-size: 70%;
+}
+
+div[data-key] {
+ color: red;
+}
+
+div.decoration, div.default, div.header-line {
+ color: #505050;
+ font-family: monospace;
+ white-space: pre-wrap;
+}
+
+div.line:first-child {
+ padding-top: 10px;
+}
+
+div.padding {
+ white-space: pre-wrap;
+ font-family: monospace;
+ display: inline;
+}
+
+div.label, div.note, div.text {
+ font-family: monospace;
+ white-space: pre-wrap;
+ display: inline;
+ vertical-align: middle;
+/*
+ * font-weight: bold;
+ * color: #606060;
+ */
+}
+
+div.blank-line {
+ padding-top: 40px;
+}
+
+div.title {
+ border-bottom: 2px solid black;
+ border-top: 2px solid #f0f0ff;
+ border-radius: 3px;
+ margin-top: 10px;
+ color: #1010a0;
+ background-color: #e0e0ff;
+ font-family: monospace;
+ display: inline;
+ vertical-align: middle;
+ white-space: pre-wrap;
+}
+
+div.data {
+ font-family: monospace;
+}
+
+div.line {
+ display: block;
+}
+
+div.indented {
+ display: inline;
+}
+
+div.indent {
+ display: inline;
+}
+
+/* BEGIN LINES */
+div.line {
+ border: none;
+}
+
+div.item {
+ border: none;
+}
+
+div.pad {
+ border: none;
+}
+
+div.blank-line {
+ border: 1px inset;
+}
+
+div.item {
+ white-space: pre;
+}
+/* END LINES */
+
+div.muxer-prompt {
+ padding: 2em;
+}
+
+div.muxer-message, div.muxer-prompt form {
+ white-space: pre;
+ display: inline-block;
+ vertical-align: middle;
+}
+
+div.muxer-buttons {
+ display: inline-block;
+ padding: 20px;
+}
+
+div.text, div.decoration, div.data, div.header, div.pad, div.item {
+ font-family: monospace;
+ display: inline;
+ vertical-align: middle;
+ white-space: pre-wrap;
+}
+
+div.blank-line {
+ margin: 5px;
+}
+
+div.indentxxx {
+ padding-left: 2em;
+}
+
+div.output, configuration-output, configuration-information {
+ font-family: monospace;
+ white-space: pre-wrap;
+}
+
+div.header-line {
+ color: #ffffff;
+ background: none repeat scroll 0 0 #0D5995;
+ margin-top: 4px;
+ padding-top: 4px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+
+div.header-line-empty {
+ color: #ffffff;
+ background: none repeat scroll 0 0 #0D5995;
+ padding-top: 4px;
+ padding-bottom: 2px;
+}
+
+
+/*
+ * juise rendering
+ */
+
+div.hidden,
+img.hidden,
+button.hidden {
+ display: none;
+}
+
+div.keeper-active div.icon-box img.keeper {
+ border: 1px solid #966535;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+}
+
+div.icon-box img.keeper {
+ border: 1px solid #ffffff;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+}
+
+div#debug-container {
+ background-color: #ccc;
+ border: 1px solid #d0d0ff;
+ bottom: 0;
+ color: blue;
+ display: none;
+ font-size: 70%;
+ position: fixed;
+ width: 100%;
+}
+
+div#debug-log {
+ background-color: #ffffff;
+ max-height: 200px;
+ overflow-y: auto;
+ padding: 0 5px;
+ white-space: pre-wrap;
+}
+
+div#header {
+ height: 30px;
+ padding: 0px 0px 40px 30px ;
+}
+
+div#header-logo {
+ display: inline-block;
+ background: url(/images/logo.png) no-repeat;
+ height: 60px;
+ width: 150px;
+}
+
+div#header-info {
+ display: table-cell;
+ height: 60px;
+ width: 60%;
+ background-color: #ffffff;
+ font-size: 80%;
+ padding-left: 10px;
+}
+
+.prefsbtn {
+ background: rgb(230, 230, 230) url(/images/gear.png) no-repeat center;
+ margin-top: 5px;
+ min-height: 40px;
+ width: 40px;
+ border-radius: 2px;
+ cursor: pointer;
+ float: right;
+ box-shadow: 0 1px 1px #fff,
+ 0 -1px 1px #666,
+ inset 0 -1px 1px rgba(0,0,0,0.5),
+ inset 0 1px 1px rgba(255,255,255,0.8);
+}
+
+.prefsbtn:hover {
+ background-color: #dde;
+}
+
+div#header-actions {
+ height: 60px;
+ width: 200px;
+ display: table-cell;
+ padding-left: 10px;
+}
+
+xdiv#header-actions div,
+xdiv#header-info div {
+ display: inline-block;
+}
+
+div#target-list {
+ display: none;
+ clear: both;
+}
+
+div#target-title {
+ display: table-cell;
+ padding: 6px 1px 6px 0px;
+}
+
+div#target-history {
+ border: 1px solid #659635;
+ position: absolute;
+ width: 25%;
+ padding-left: 0px;
+ padding-right: 0px;
+}
+
+form#target-history-form {
+ margin-bottom: 0px;
+}
+
+input#target-history-submit {
+ background: url(none);
+ margin-left: 2px;
+}
+
+div.target-history-name {
+ display: inline-block;
+}
+
+div.target-history-entry-parent:hover {
+ background: #659635;
+}
+
+div.target-history-entry-parent:first-child {
+ border-top: 0px none;
+}
+
+div.target-history-entry-parent {
+ border-top: 1px solid #659635;
+ padding-left: 8px;
+ padding-right: 8px;
+}
+div.target-history-entry {
+ display: inline-block;
+}
+
+div.target-info {
+ display: inline-block;
+ font-family: Helvetica, Arial, sans-serif;
+ font-weight: bold;
+ font-size: 12px;
+ margin-right: 10px;
+ margin-left: 10px;
+ padding: 5px 10px 5px 10px;
+}
+
+div#target-contents,
+div#target-contents-none {
+ display: table-cell;
+ font-family: Verdana, Arial, Helvetica, sans-serif ;
+}
+
+div#target-contents-none {
+ padding-left: 10px;
+ font-size: 70%;
+}
+
+div.target {
+ display: inline-block;
+ margin-left: 2px;
+ margin-right: 2px;
+}
+
+div#command-history {
+ border: 1px solid #c0c0ff;
+ position: absolute;
+ width: 60em;
+ font-family: Verdana, Arial, Helvetica, sans-serif ;
+ font-family: monospace;
+ font-size: 12px;
+ background: #e0e0ff;
+ padding-left: 0px;
+ padding-right: 0px;
+}
+
+div.command-history-entry:hover {
+ background: #c0c0ff;
+}
+
+div.command-history-entry:first-child {
+ border-top: 0px none;
+}
+
+div.command-history-entry {
+ border-top: 1px solid #c0c0ff;
+ padding-left: 8px;
+ padding-right: 8px;
+}
+
+div#footer {
+ padding-top: 100px;
+ clear: both;
+ display: block;
+ height: 100px;
+ width: 100%;
+ font-size: 8;
+ text-align: center;
+}
+
+div#input-history {
+ display: inline-block;
+ float: left;
+ margin-right: 5px;
+ position: relative;
+ width: 70%;
+}
+
+div#input-top {
+ display: block;
+ height: 70px;
+ padding: 10px;
+ margin-bottom: 10px;
+ background-color: rgb(245, 245, 245);
+ border-bottom: rgb(200, 200, 200) solid 1px;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+
+div#input-history .pulldown {
+ border: solid 1px rgb(180, 180, 200);
+ max-height: 300px;
+ overflow-y: auto;
+ padding: 0px;
+ width: 100%;
+}
+
+div#mru-pulldown {
+ margin-top: 40px;
+ position: absolute;
+ width: 100%;
+ z-index: 9999;
+}
+
+div#mru-pulldown .mru-item {
+ padding: 5px;
+}
+
+div#mru-pulldown .mru-item:hover {
+ background: rgb(242, 244, 255);
+ cursor: pointer;
+ font-weight: 700;
+}
+
+div#recent-devices {
+ margin-top: 10px;
+}
+
+div#recent-devices a {
+ color: rgb(0, 50, 112);
+ cursor: pointer;
+ text-decoration: underline;
+}
+
+div#input-top .logo {
+ float: left;
+ margin: 0px 10px 0px 10px;
+}
+
+form#target-input-form,
+form#command-input-form {
+ display: inline-block;
+}
+
+div#target-top,
+div#command-top {
+ display: inline-block;
+ float: left;
+ margin: 10px 5px 0px 0px;
+ width: 100%;
+}
+
+div#command-top .input-box {
+ height: 32px;
+ min-width: 500px;
+ padding: 1px;
+ background-color: #fff;
+ width: 100%;
+}
+
+div#command-top .focus-off {
+ border: solid 1px rgb(180, 180, 200);
+}
+
+div#command-top .focus-on {
+ border: solid 1px rgb(180, 180, 200);
+ box-shadow: 0px 0px 8px rgba(100, 100, 200, 0.5);
+}
+
+div#input-top .input-enter {
+ margin: 10px 0px 10px 0px;
+ float: left;
+}
+
+input.command-input {
+ font-family: Verdana, Arial, Helvetica, sans-serif ;
+ font-family: monospace;
+ font-size: 12px;
+}
+
+div#output-top {
+ margin-bottom: 20px;
+}
+
+div.output-wrapper {
+/* border: 1px solid blue; */
+ margin-top: 5px;
+ background: white;
+ padding: 0px;
+}
+
+div.output-header button {
+ margin-right: 4px;
+}
+
+div.output-header {
+ padding: 4px;
+}
+
+div.output-header div.target-value {
+ margin-left: 4px;
+}
+
+div.output-header div.command-value {
+ margin-right: 4px;
+}
+
+div.output-header div.target-value,
+div.output-header div.command-value {
+ font-weight: normal;
+ font-size: 12px;
+}
+
+div.target-value,
+input.target-value {
+ display: inline-block;
+ font-size: 12px;
+ font-family: Verdana, Arial, Helvetica, sans-serif ;
+}
+
+div.label, div.note {
+ display: inline;
+/*
+ padding-left: 3px;
+ padding-right: 3px;
+*/
+ font-size: 12px;
+}
+
+div.command-value,
+input.command-value {
+ display: inline-block;
+ font-size: 14px;
+}
+
+div.command-number {
+ display: inline-block;
+ font-size: 70%;
+ float: right;
+}
+
+div#ember-view .output-content {
+ float: left;
+ position: relative;
+}
+
+div.output-content {
+ display: block;
+ font-size: 12px;
+ padding: 10px;
+}
+
+div.icon-box {
+ display: inline-block;
+ margin-right: 5px;
+}
+
+div#debug-title {
+ display: inline-block;
+}
+
+img.icon {
+ height: 16px;
+ vertical-align: middle;
+}
+
+.buttonish {
+ text-align: center;
+ text-decoration: none;
+ text-shadow: -1px -1px 2px #777777;
+ text-shadow: rgba(10, 10, 10, 0.5) 1px 2px 2px;
+}
+
+input.text-entry {
+ border: 0;
+ outline: 0;
+ height: 20px;
+ width: 100%;
+}
+
+.rounded {
+ border: 1px solid #659635;
+ background: #99ca28;
+ padding: 2px 8px 2px 8px;
+
+ border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+}
+
+.green {
+ color: #ffffff;
+ background: linear-gradient(top,
+ #5da331 0%, #659635 2%, #9bcb2a 97%, #cfe782 100%);
+ background: -moz-linear-gradient(top,
+ #5da331 0%, #659635 2%, #9bcb2a 97%, #cfe782 100%);
+ background: -webkit-linear-gradient(top,
+ #5da331 0%, #659635 2%, #9bcb2a 97%, #cfe782 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,
+ startColorstr='#659635', endColorstr='#9bcb2a');
+}
+
+.blue {
+ color: #0c0c0c;
+/*
+ background: linear-gradient(top,
+ #a0a0ff 0%, #c8c8ff 10%, #d8d8ff 90%, #f0f0ff 100%);
+ background: -moz-linear-gradient(top,
+ #a0a0ff 0%, #c8c8ff 10%, #d8d8ff 90%, #f0f0ff 100%);
+ background: -webkit-linear-gradient(top,
+ #a0a0ff 0%, #c8c8ff 10%, #d8d8ff 90%, #f0f0ff 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,
+ startColorstr='#a0a0ff', endColorstr='#f0f0ff');
+*/
+}
+
+.jquery-checkbox {
+ line-height: 24px;
+}
+
+ul.setupgrid {
+ padding: 0;
+ list-style: none;
+ margin: 0 auto;
+}
+
+ul.setupgrid li {
+ float: left;
+ padding: 10px;
+ border: 1px solid #cbcad0;
+ margin: 0 5px 10px 5px;
+}
+
+div.setupgrid {
+ font-family: 'GraublauWeb', arial, serif;
+ text-align: center;
+}
+
+.setupgrid a {
+ height: 32px;
+ width: 64px;
+ display: block;
+ padding-top: 32px;
+ text-decoration: none;
+}
+
+.setupgrid a#prefs-devices {
+ background: url(/images/prefs-devices.png) no-repeat center top;
+}
+
+.setupgrid a#prefs-groups {
+ background: url(/images/prefs-groups.png) no-repeat center top;
+}
+
+.setupgrid a#prefs-general {
+ background: url(/images/prefs-general.png) no-repeat center top;
+}
+
+div.input {
+ background: #e0e0ff;
+ padding: 10px;
+}
+
+div.parse {
+ background: #b0b0b0;
+ border: 1px solid black;
+}
+
+div.input-debug {
+ background: #ffe0e0;
+ border-bottom: 1px solid black;
+ padding: 10px;
+ font-weight: bold;
+}
+
+div.possibility-debug {
+ background: #ffe0e0;
+ padding: 10px;
+ border-bottom: 1px dotted red;
+}
+
+div.match-debug {
+ display: inline-block;
+ padding: 5px;
+}
+
+div.command-token,
+div.command-token div {
+ display: inline-block;
+}
+
+div.parse-details {
+/* display: none; */
+}
+
+div.command-line {
+ font-weight: bold;
+}
+
+div.match-details {
+ display: inline-block;
+}
+
+div.possibility {
+/* background: #ffe0e0; */
+ padding: 10px;
+ border-bottom: 1px dotted red;
+}
+
+div.parse-implicit-keyword,
+div.parse-token,
+div.parse-trailing,
+div.parse-missing {
+ display: inline-block;
+}
+
+div.parse-implicit-keyword,
+div.parse-trailing,
+div.parse-missing {
+ font-style: italic;
+ font-weight: normal;
+}
+
+div.parse-token {
+ font-weight: bold;
+}
+
+div.parse-mandatory {
+ color: red;
+ display: inline-block;
+}
+
+div.parse-mandatory-value {
+ color: red;
+ font-style: italic;
+ display: inline-block;
+}
+
+div.output-content div.parse:first-of-type {
+ display: none;
+}
+
+div.command-help {
+ font-size: smaller;
+ font-style: italic;
+ padding-left: 20px;
+ padding-bottom: 5px;
+}
+
+img.rendered {
+ float: left;
+ margin-right: 5px;
+ max-width: 16px;
+ vertical-align: middle;
+}
+
+div.map-small {
+ width: 300px;
+ height: 200px;
+}
+
+div.inline-dialog {
+ box-shadow: none;
+ margin-left: 20px;
+ position: relative;
+}
+
+.inline-dialog .ui-dialog-titlebar-close {
+ display: none;
+}
+
+div#prefs-title {
+ font-size: 120%;
+ font-weight: 600;
+}
+
+div.prefs-item,
+div.ui-yf-item {
+ display: table-row;
+}
+
+div.prefs-item label,
+div.ui-yf-item label {
+ padding-left: 10px;
+ padding-right: 5px;
+}
+
+div.prefs-item label,
+div.prefs-item input,
+div.prefs-item div,
+div.ui-yf-item label,
+div.ui-yf-item input,
+div.ui-yf-item div {
+ display: table-cell;
+}
+
+div.dyn-form {
+ padding: 5px;
+ width: auto;
+}
+
+div.dyn-form-wrapper {
+ display: inline-block;
+ border: 1px solid #ccc;
+ min-width: 400px;
+}
+
+div.dyn-form-title {
+ background-color: #1478dc;
+ padding: 10px;
+ color: white;
+ font-size: 1.1em;
+}
+
+div.dyn-form-item {
+ display: inline-block;
+ text-align: center;
+ padding: 2px 10px 2px 10px;
+}
+
+div.dyn-form-message {
+ text-align: left;
+ padding: 5px 10px 5px 10px;
+}
+
+div.dyn-form-item label {
+ float: left;
+ padding-left: 10px;
+ padding-right: 5px;
+}
+
+div.dyn-form-buttons {
+ text-align: center;
+ padding: 5px 10px 10px 10px;
+}
+
+div.dyn-form-item label,
+div.dyn-form-item input,
+div.dyn-form-item select,
+div.dyn-form-item div {
+ float: left;
+ line-height: 20px;
+ margin-top: 5px;
+ min-width: 100px;
+ text-align: left;
+}
+
+div.dyn-form-item input,
+div.dyn-form-item select {
+ border: solid 1px #CCC;
+ margin-top: 5px;
+ width: auto;
+}
+
+div.dyn-form-item .mandatory {
+ border-color: rgb(213, 119, 0);
+}
+
+div.dyn-form-item .is-error {
+ border-color: rgb(213, 11, 0);
+}
+
+div.dyn-form-item .is-error:focus {
+ border-color: rgb(213, 11, 0);
+}
+
+div.dyn-form-item input:focus {
+ border: solid 1px rgb(180, 180, 200);
+ box-shadow: 0px 0px 3px rgba(100, 100, 200, 0.8);
+}
+
+div.dyn-form-boolean {
+ margin-left: -40px;
+ text-align: left;
+ vertical-align: middle;
+}
+
+div.dyn-form-item .dyn-radio-button {
+ margin-left: -30px;
+ margin-right: -40px;
+}
+
+div.dyn-radiogroup {
+ border-bottom: 1px solid rgb(230, 230, 230);
+ border-top: 1px solid rgb(230, 230, 230);
+ padding: 5px;
+}
+
+.dyn-dropdown-item {
+ max-height: 200px;
+ overflow-y: auto;
+}
+
+.history-element .command {
+ font-size: 16px;
+}
+
+.history-element .date {
+ color: rgb(130, 130, 130);
+ font-style: italic;
+}
+
+.node {
+ stroke: #fff;
+ stroke-width: 1.5px;
+}
+
+.link {
+ stroke: #444;
+ stroke-opacity: 0.6;
+ stroke-width: 2px;
+}
+
+g.node text {
+ pointer-events: none;
+ font: 8px;
+ stroke: #000080;
+}
+
+some.day {
+ background: -moz-linear-gradient(center top , #4B90C3, #0D63A3)
+ repeat scroll 0 0 transparent;
+}
+
+.ui-autocomplete-divider {
+ border-bottom: 1px solid black;
+}
+
+.ui-autocomplete {
+ max-height: 400px;
+ overflow-y: auto;
+ overflow-x: hidden;
+ padding-right: 20px;
+ width: 650px;
+}
+
+ul.ui-autocomplete li.ui-menu-item {
+ font-family: monospace;
+}
+
+ul.ui-autocomplete li.ui-menu-item a.label {
+ float: left;
+ font-weight: bold;
+}
+
+ul.ui-autocomplete li.ui-menu-item a.help {
+ float: right;
+}
+
+a.xpath-link {
+ text-decoration: none;
+}
+
+div.xpath-wrapper {
+ margin-top: 8px;
+ padding-top: 5px;
+ border-top: solid 1px #c8c8c8;
+}
+
+div.xpath {
+ display: none;
+ margin-top: 8px;
+}
+
+/*
+ * Additional styles for messages
+ */
+.ui-state-info {
+ color: rgb(0, 94, 196);
+}
+
+.ui-state-info .ui-icon {
+ background-image:url(/themes/clira/images/ui-icons_ffcf29_256x240.png);
+}
+
+.ui-state-success {
+ color: rgb(45, 126, 0);
+}
+
+.ui-state-success .ui-icon {
+ background-image:url(/themes/clira/images/ui-icons_ffcf29_256x240.png);
+}
+
+.ui-state-warning {
+ color: rgb(179, 146, 14);
+}
+
+.ui-state-warning .ui-icon {
+ background-image:url(/themes/clira/images/ui-icons_ffcf29_256x240.png);
+}
+
+.stop_button {
+ background-color: #f24537;
+ background: -moz-linear-gradient( center top, #f24537 5%, #c62d1f 100% );
+ background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #f24537), color-stop(1, #c62d1f) );
+ border: 1px solid #d02718;
+ border-bottom-left-radius: 6px;
+ border-bottom-right-radius: 6px;
+ border-top-left-radius: 6px;
+ border-top-right-radius: 6px;
+ box-shadow: inset 0px 1px 0px 0px #f5978e;
+ color: #ffffff;
+ display: inline-block;
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f24537', endColorstr='#c62d1f');
+ font-family: Courier New;
+ font-size: 10px;
+ font-style: normal;
+ font-weight: bold;
+ height: 16px;
+ line-height: 16px;
+ margin-left: 5px;
+ text-align: center;
+ text-decoration: none;
+ text-indent: 0.4px;
+ text-shadow: 1px 1px 0px #810e05;
+ width: 37px;
+}
+
+.stop_button:hover {
+ background-color: #c62d1f;
+ background: -moz-linear-gradient( center top, #c62d1f 5%, #f24537 100% );
+ background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #c62d1f), color-stop(1, #f24537) );
+ filter:progid: DXImageTransform.Microsoft.gradient(startColorstr='#c62d1f', endColorstr='#f24537');
+}
+
+.stop_button:active {
+ position: relative;
+ top: 1px;
+}
diff --git a/contrib/libxo/xohtml/xohtml.js b/contrib/libxo/xohtml/xohtml.js
new file mode 100644
index 0000000..9e3d836
--- /dev/null
+++ b/contrib/libxo/xohtml/xohtml.js
@@ -0,0 +1,54 @@
+jQuery(function($) {
+ setTimeout(function() {
+ var $top = $("html body");
+ $top.find('[class~="data"]').each(function() {
+ var help = $(this).attr('data-help'),
+ type = $(this).attr('data-type'),
+ xpath = $(this).attr('data-xpath'),
+ tag = $(this).attr('data-tag'),
+ output = "";
+ if (help) {
+ output += "<b>Help</b>: " + help + "<br/>";
+ }
+ if (type) {
+ output += "<b>Type</b>: " + type + "<br/>";
+ }
+ if (xpath) {
+ output += "<div class='xpath-wrapper'>"
+ + "<a class='xpath-link' href='#'>"
+ + "show xpath</a><div class='xpath'>"
+ + xpath + "</div></div><br/>";
+ }
+ if (output.length > 0) {
+ output = "<div>" + output + "</div>";
+ }
+
+ $(this).qtip({
+ content: {
+ title: "<b>" + tag + "</b>",
+ text: function () {
+ var div = $(output);
+ div.find(".xpath-link")
+ .click(function() {
+ var xpath = $(this).next();
+ if (xpath.is(":hidden")) {
+ xpath.show();
+ $(this).text("hide xpath");
+ } else {
+ xpath.hide();
+ $(this).text("show xpath");
+ }
+ return false;
+ });
+ return div;
+ }
+ },
+ hide: {
+ fixed: true,
+ delay: 300
+ },
+ style: "qtip-tipped"
+ });
+ });
+ }, 0);
+}); \ No newline at end of file
diff --git a/contrib/libxo/xohtml/xohtml.sh.in b/contrib/libxo/xohtml/xohtml.sh.in
new file mode 100644
index 0000000..cbd3066
--- /dev/null
+++ b/contrib/libxo/xohtml/xohtml.sh.in
@@ -0,0 +1,55 @@
+#!/bin/sh
+#
+# Copyright (c) 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+# Phil Shafer, July 2014
+#
+
+BASE=@XO_SHAREDIR@
+CMD=cat
+DONE=
+
+while [ -z "$DONE" -a ! -z "$1" ]; do
+ case "$1" in
+ -b|--base)
+ shift;
+ BASE="$1";
+ shift;
+ ;;
+ -c|--command)
+ shift;
+ CMD="$1";
+ shift;
+ ;;
+ -f|--file)
+ shift;
+ FILE="$1";
+ shift;
+ exec > "$FILE";
+ ;;
+ *)
+ DONE=1;
+ ;;
+ esac
+done
+
+echo "<html>\n<head>\n"
+echo '<meta http-equiv="content-type" content="text/html; charset=utf-8"/>'
+echo '<link rel="stylesheet" href="'$BASE'/xohtml.css">'
+echo '<link rel="stylesheet" href="'$BASE'/external/jquery.qtip.css"/>'
+echo '<script type="text/javascript" src="'$BASE'/external/jquery.js"></script>'
+echo '<script type="text/javascript" src="'$BASE'/external/jquery.qtip.js"></script>'
+echo '<script type="text/javascript" src="'$BASE'/xohtml.js"></script>'
+echo '<script>'
+echo '</script>'
+echo "</head>\n<body>\n"
+
+$CMD
+
+echo "</body>\n</html>\n"
+
+exit 0
diff --git a/contrib/libxo/xolint/Makefile.am b/contrib/libxo/xolint/Makefile.am
new file mode 100644
index 0000000..0f8ef62
--- /dev/null
+++ b/contrib/libxo/xolint/Makefile.am
@@ -0,0 +1,14 @@
+#
+# Copyright 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+
+man_MANS = xolint.1
+
+EXTRA_DIST = xolint.1 xolint.pl
+
+install-exec-hook:
+ install ${srcdir}/xolint.pl ${bindir}/xolint
diff --git a/contrib/libxo/xolint/xolint.1 b/contrib/libxo/xolint/xolint.1
new file mode 100644
index 0000000..b7ed130
--- /dev/null
+++ b/contrib/libxo/xolint/xolint.1
@@ -0,0 +1,89 @@
+.\" #
+.\" # Copyright (c) 2014, Juniper Networks, Inc.
+.\" # All rights reserved.
+.\" # This SOFTWARE is licensed under the LICENSE provided in the
+.\" # ../Copyright file. By downloading, installing, copying, or
+.\" # using the SOFTWARE, you agree to be bound by the terms of that
+.\" # LICENSE.
+.\" # Phil Shafer, July 2014
+.\"
+.Dd July, 2014
+.Dt LIBXO 3
+.Os
+.Sh NAME
+.Nm xolint
+.Nd detect errors in programs using xo_emit
+.Sh SYNOPSIS
+.Nm xolint
+.Op Fl c
+.Op Fl "C <flags>"
+.Op Fl "d"
+.Op Fl "D"
+.Op Fl "I"
+.Op Fl "p"
+.Op Fl "V"
+.Op Fl "X"
+.Op Ar files...
+.Sh DESCRIPTION
+xolint is a tool for reporting common mistakes in format strings
+in source code that invokes xo_emit(). It allows these errors
+to be diagnosed at build time, rather than waiting until runtime.
+.Pp
+xolint takes the one or more C files as arguments, and reports
+and errors, warning, or informational messages as needed.
+.Bl -tag -width "C <flags>"
+.It Fl c
+Invoke 'cpp' against the input file
+.It Fl "C <flags>"
+Flags that are passed to 'cpp
+.It Fl "d"
+Enable debug output
+.It Fl "D"
+Generate documentation for all xolint messages
+.It Fl "I"
+Generate a table of xo_info_t structures.
+.It Fl "p"
+Print the offending lines after the error message is displayed
+.It Fl "V"
+Do not report errors, but instead print a complete list of
+all field names, sorted alphabetically. The output can help spot
+inconsistencies and spelling errors.
+.It Fl "X"
+Extract samples from xolint, suitable for internal testing.
+.El
+.Pp
+Output message contain the source filename and line number, the
+class of the message, the message, and, if
+.Fl p
+is given, the
+line that contains the error:
+.Bd -literal -offset indent
+ % xolint -t xolint.c
+ xolint.c: 16: error: anchor format should be "%d"
+ 16 xo_emit("{[:/%s}");
+.Ed
+.Pp
+.Sh ADDITIONAL DOCUMENTATION
+.Pp
+Complete documentation can be found on github:
+.Bd -literal -offset indent
+http://juniper.github.io/libxo/libxo-manual.html
+.Ed
+.Pp
+libxo lives on github as:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo
+.Ed
+.Pp
+The latest release of libxo is available at:
+.Bd -literal -offset indent
+https://github.com/Juniper/libxo/releases
+.Ed
+.Sh SEE ALSO
+.Xr xo_emit 3
+.Sh HISTORY
+The
+.Fa libxo
+library was added in FreeBSD 10.1.
+.Sh AUTHOR
+Phil Shafer
diff --git a/contrib/libxo/xolint/xolint.pl b/contrib/libxo/xolint/xolint.pl
new file mode 100755
index 0000000..8693e62
--- /dev/null
+++ b/contrib/libxo/xolint/xolint.pl
@@ -0,0 +1,556 @@
+#!/usr/bin/env perl
+#
+# Copyright (c) 2014, Juniper Networks, Inc.
+# All rights reserved.
+# This SOFTWARE is licensed under the LICENSE provided in the
+# ../Copyright file. By downloading, installing, copying, or otherwise
+# using the SOFTWARE, you agree to be bound by the terms of that
+# LICENSE.
+# Phil Shafer, August 2014
+#
+#
+# xolint -- a lint for inspecting xo_emit format strings
+#
+# Yes, that's a long way to go for a pun.
+
+%vocabulary = ();
+
+sub main {
+ while ($ARGV[0] =~ /^-/) {
+ $_ = shift @ARGV;
+ $opt_cpp = 1 if /^-c/;
+ $opt_cflags .= shift @ARGV if /^-C/;
+ $opt_debug = 1 if /^-d/;
+ extract_docs() if /^-D/;
+ $opt_info = $opt_vocabulary = 1 if /^-I/;
+ $opt_print = 1 if /^-p/;
+ $opt_vocabulary = 1 if /^-V/;
+ extract_samples() if /^-X/;
+ }
+
+ for $file (@ARGV) {
+ parse_file($file);
+ }
+
+ if ($opt_info) {
+ print "static xo_info_t xo_info_table[] = {\n";
+ for $name (sort(keys(%vocabulary))) {
+ print " { \"", $name, "\", \"type\", \"desc\" },\n";
+ }
+ print "};\n";
+ print "static int xo_info_count = "
+ . "(sizeof(xo_info_table) / sizeof(xo_info_table[0]));\n\n";
+ print "#define XO_SET_INFO() \\\n";
+ print " xo_set_info(NULL, xo_info_table, xo_info_count)\n";
+ } elsif ($opt_vocabulary) {
+ for $name (sort(keys(%vocabulary))) {
+ print $name, "\n";
+ }
+ }
+}
+
+sub extract_samples {
+ my $x = "\#" . "\@";
+ my $cmd = "grep -B1 -i '$x Should be' $0 | grep xo_emit | sed 's/.*\#*\@//'";
+ system($cmd);
+ exit(0);
+}
+
+sub extract_docs {
+ my $x = "\#" . "\@";
+ my $cmd = "grep -B1 '$x' $0";
+ open INPUT, "$cmd |";
+ local @input = <INPUT>;
+ close INPUT;
+ my $ln, $new = 0, $first = 1, $need_nl;
+
+ for ($ln = 0; $ln <= $#input; $ln++) {
+ chomp($_ = $input[$ln]);
+ if (/^--/) {
+ $ln += 1;
+ $new = 1;
+ next;
+ }
+ if ($first) {
+ $new = 1;
+ $first = 0;
+ next;
+ }
+
+ s/\s*\#\@\s*//;
+
+ if ($new) {
+ if ($need_nl) {
+ print "\n\n";
+ $need_nl = 0;
+ }
+
+ print "*** '$_'\n\n";
+ print "The message \"$_\" can be caused by code like:\n\n";
+ $new = 0;
+
+ } elsif (/xo_emit\s*\(/) {
+ s/^\s+//;
+ print " $_\n\n";
+
+ } elsif (/^Should be/i) {
+ print "This code should be replaced with code like:\n\n";
+
+ } else {
+ print "$_\n";
+ $need_nl = 1;
+ }
+ }
+
+ exit(0);
+}
+
+sub parse_file {
+ local($file) = @_;
+ local($errors, $warnings, $info) = (0, 0, 0);
+ local $curfile = $file;
+ local $curln = 0;
+
+ if ($opt_cpp) {
+ die "no such file" unless -f $file;
+ open INPUT, "cpp $opt_cflags $file |";
+ } else {
+ open INPUT, $file || die "cannot open input file '$file'";
+ }
+ local @input = <INPUT>;
+ close INPUT;
+
+ local $ln, $rln, $line, $replay;
+
+ for ($ln = 0; $ln < $#input; $ln++) {
+ $line = $input[$ln];
+ $curln += 1;
+
+ if ($line =~ /^\#/) {
+ my($num, $fn) = ($line =~ /\#\s*(\d+)\s+"(.+)"/);
+ ($curfile, $curln) = ($fn, $num) if $num;
+ next;
+ }
+
+ next unless $line =~ /xo_emit\(/;
+
+ @tokens = parse_tokens();
+ print "token:\n '" . join("'\n '", @tokens) . "'\n"
+ if $opt_debug;
+ check_format($tokens[0]);
+ }
+
+ print $file . ": $errors errors, $warnings warnings, $info info\n"
+ unless $opt_vocabulary;
+}
+
+sub parse_tokens {
+ my $full = "$'";
+ my @tokens = ();
+ my %pairs = ( "{" => "}", "[" => "]", "(" => ")" );
+ my %quotes = ( "\"" => "\"", "'" => "'" );
+ local @data = split(//, $full);
+ local @open = ();
+ local $current = "";
+ my $quote = "";
+ local $off = 0;
+ my $ch;
+
+ $replay = $curln . " " . $line;
+ $rln = $ln + 1;
+
+ for (;;) {
+ get_tokens() if $off > $#data;
+ die "out of data" if $off > $#data;
+ $ch = $data[$off++];
+
+ print "'$ch' ($quote) ($#open) [" . join("", @open) . "]\n"
+ if $opt_debug;
+
+ last if $ch eq ";" && $#open < 0;
+
+ if ($ch eq "," && $quote eq "" && $#open < 0) {
+ print "[$current]\n" if $opt_debug;
+ push @tokens, $current;
+ $current = "";
+ next;
+ }
+
+ next if $ch =~ /[ \t\n\r]/ && $quote eq "" && $#open < 0;
+
+ $current .= $ch;
+
+ if ($quote) {
+ if ($ch eq $quote) {
+ $quote = "";
+ }
+ next;
+ }
+ if ($quotes{$ch}) {
+ $quote = $quotes{$ch};
+ $current = substr($current, 0, -2) if $current =~ /""$/;
+ next;
+ }
+
+ if ($pairs{$ch}) {
+ push @open, $pairs{$ch};
+ next;
+ }
+
+ if ($#open >= 0 && $ch eq $open[$#open]) {
+ pop @open;
+ next;
+ }
+ }
+
+ push @tokens, substr($current, 0, -1);
+ return @tokens;
+}
+
+sub get_tokens {
+ if ($ln + 1 < $#input) {
+ $line = $input[++$ln];
+ $curln += 1;
+ $replay .= $curln . " " . $line;
+ @data = split(//, $line);
+ $off = 0;
+ }
+}
+
+sub check_format {
+ my($format) = @_;
+
+ return unless $format =~ /^".*"$/;
+
+ my @data = split(//, $format);
+ my $ch;
+ my $braces = 0;
+ local $count = 0;
+ my $content = "";
+ my $off;
+ my $phase = 0;
+ my @build = ();
+ local $last, $prev = "";
+
+ # Nukes quotes
+ pop @data;
+ shift @data;
+
+ for (;;) {
+ last if $off > $#data;
+ $ch = $data[$off++];
+
+ if ($ch eq "\\") {
+ $ch = $data[$off++];
+ $off += 1 if $ch eq "\\"; # double backslash: "\\/"
+ next;
+ }
+
+ if ($braces) {
+ if ($ch eq "}") {
+ check_field(@build);
+ $braces = 0;
+ @build = ();
+ $phase = 0;
+ next;
+ } elsif ($phase == 0 && $ch eq ":") {
+ $phase += 1;
+ next;
+ } elsif ($ch eq "/") {
+ $phase += 1;
+ next;
+ }
+
+ } else {
+ if ($ch eq "{") {
+ check_text($build[0]) if length($build[0]);
+ $braces = 1;
+ @build = ();
+ $last = $prev;
+ next;
+ }
+ }
+
+ $prev = $ch;
+ $build[$phase] .= $ch;
+ }
+
+ if ($braces) {
+ error("missing closing brace");
+ check_field(@build);
+ } else {
+ check_text($build[0]) if length($build[0]);
+ }
+}
+
+sub check_text {
+ my($text) = @_;
+
+ print "checking text: [$text]\n" if $opt_debug;
+
+ #@ A percent sign appearing in text is a literal
+ #@ xo_emit("cost: %d", cost);
+ #@ Should be:
+ #@ xo_emit("{L:cost}: {:cost/%d}", cost);
+ #@ This can be a bit surprising and could be a field that was not
+ #@ properly converted to a libxo-style format string.
+ info("a percent sign appearing in text is a literal") if $text =~ /%/;
+}
+
+sub check_field {
+ my(@field) = @_;
+ print "checking field: [" . join("][", @field) . "]\n" if $opt_debug;
+
+ if ($opt_vocabulary) {
+ $vocabulary{$field[1]} = 1
+ if $field[1] && $field[0] !~ /[DELNPTUW\[\]]/;
+ return;
+ }
+
+ #@ Last character before field definition is a field type
+ #@ A common typo:
+ #@ xo_emit("{T:Min} T{:Max}");
+ #@ Should be:
+ #@ xo_emit("{T:Min} {T:Max}");
+ #@ Twiddling the "{" and the field role is a common typo.
+ info("last character before field definition is a field type ($last)")
+ if $last =~ /[DELNPTUVW\[\]]/ && $field[0] !~ /[DELNPTUVW\[\]]/;
+
+ #@ Encoding format uses different number of arguments
+ #@ xo_emit("{:name/%6.6s %%04d/%s}", name, number);
+ #@ Should be:
+ #@ xo_emit("{:name/%6.6s %04d/%s-%d}", name, number);
+ #@ Both format should consume the same number of arguments off the stack
+ my $cf = count_args($field[2]);
+ my $ce = count_args($field[3]);
+ warn("encoding format uses different number of arguments ($cf/$ce)")
+ if $ce >= 0 && $cf >= 0 && $ce != $cf;
+
+ #@ Only one field role can be used
+ #@ xo_emit("{LT:Max}");
+ #@ Should be:
+ #@ xo_emit("{T:Max}");
+ my(@roles) = ($field[0] !~ /([DELNPTUVW\[\]]).*([DELNPTUVW\[\]])/);
+ error("only one field role can be used (" . join(", ", @roles) . ")")
+ if $#roles > 0;
+
+ # Field is a note, label, or title
+ if ($field[0] =~ /[DLNT]/) {
+
+ #@ Potential missing slash after N, L, or T with format
+ #@ xo_emit("{T:%6.6s}\n", "Max");
+ #@ should be:
+ #@ xo_emit("{T:/%6.6s}\n", "Max");
+ #@ The "%6.6s" will be a literal, not a field format. While
+ #@ it's possibly valid, it's likely a missing "/".
+ info("potential missing slash after N, L, or T with format")
+ if $field[1] =~ /%/;
+
+ #@ Format cannot be given when content is present (roles: DNLT)
+ #@ xo_emit("{T:Max/%6.6s}", "Max");
+ #@ Fields with the D, N, L, or T roles can't have both
+ #@ static literal content ("{T:Title}") and a
+ #@ format ("{T:/%s}").
+ #@ This error will also occur when the content has a backslash
+ #@ in it, like "{N:Type of I/O}"; backslashes should be escaped,
+ #@ like "{N:Type of I\\/O}". Note the double backslash, one for
+ #@ handling 'C' strings, and one for libxo.
+ error("format cannot be given when content is present")
+ if $field[1] && $field[2];
+
+ #@ An encoding format cannot be given (roles: DNLT)
+ #@ xo_emit("{T:Max//%s}", "Max");
+ #@ Fields with the D, N, L, and T roles are not emitted in
+ #@ the 'encoding' style (JSON, XML), so an encoding format
+ #@ would make no sense.
+ error("encoding format cannot be given when content is present")
+ if $field[3];
+ }
+
+ # A value field
+ if (length($field[0]) == 0 || $field[0] =~ /V/) {
+
+ #@ Value field must have a name (as content)")
+ #@ xo_emit("{:/%s}", "value");
+ #@ Should be:
+ #@ xo_emit("{:tag-name/%s}", "value");
+ #@ The field name is used for XML and JSON encodings. These
+ #@ tags names are static and must appear directly in the
+ #@ field descriptor.
+ error("value field must have a name (as content)")
+ unless $field[1];
+
+ #@ Use hyphens, not underscores, for value field name
+ #@ xo_emit("{:no_under_scores}", "bad");
+ #@ Should be:
+ #@ xo_emit("{:no-under-scores}", "bad");
+ #@ Use of hyphens is traditional in XML, and the XOF_UNDERSCORES
+ #@ flag can be used to generate underscores in JSON, if desired.
+ #@ But the raw field name should use hyphens.
+ error("use hyphens, not underscores, for value field name")
+ if $field[1] =~ /_/;
+
+ #@ Value field name cannot start with digit
+ #@ xo_emit("{:10-gig/}");
+ #@ Should be:
+ #@ xo_emit("{:ten-gig/}");
+ #@ XML element names cannot start with a digit.
+ error("value field name cannot start with digit")
+ if $field[1] =~ /^[0-9]/;
+
+ #@ Value field name should be lower case
+ #@ xo_emit("{:WHY-ARE-YOU-SHOUTING}", "NO REASON");
+ #@ Should be:
+ #@ xo_emit("{:why-are-you-shouting}", "no reason");
+ #@ Lower case is more civilized. Even TLAs should be lower case
+ #@ to avoid scenarios where the differences between "XPath" and
+ #@ "Xpath" drive your users crazy. Lower case rules the seas.
+ error("value field name should be lower case")
+ if $field[1] =~ /[A-Z]/;
+
+ #@ Value field name should be longer than two characters
+ #@ xo_emit("{:x}", "mumble");
+ #@ Should be:
+ #@ xo_emit("{:something-meaningful}", "mumble");
+ #@ Field names should be descriptive, and it's hard to
+ #@ be descriptive in less than two characters. Consider
+ #@ your users and try to make something more useful.
+ #@ Note that this error often occurs when the field type
+ #@ is placed after the colon ("{:T/%20s}"), instead of before
+ #@ it ("{T:/20s}").
+ error("value field name should be longer than two characters")
+ if $field[1] =~ /[A-Z]/;
+
+ #@ Value field name contains invalid character
+ #@ xo_emit("{:cost-in-$$/%u}", 15);
+ #@ Should be:
+ #@ xo_emit("{:cost-in-dollars/%u}", 15);
+ #@ An invalid character is often a sign of a typo, like "{:]}"
+ #@ instead of "{]:}". Field names are restricted to lower-case
+ #@ characters, digits, and hyphens.
+ error("value field name contains invalid character (" . $field[1] . ")")
+ unless $field[1] =~ /^[0-9a-z-]*$/;
+ }
+
+ # A decoration field
+ if ($field[0] =~ /D/) {
+
+ #@decoration field contains invalid character
+ #@ xo_emit("{D:not good}");
+ #@ Should be:
+ #@ xo_emit("{D:((}{:good}{D:))}", "yes");
+ #@ This is minor, but fields should use proper roles. Decoration
+ #@ fields are meant to hold puncuation and other characters used
+ #@ to decorate the content, typically to make it more readable
+ #@ to human readers.
+ warn("decoration field contains invalid character")
+ unless $field[1] =~ m:^[~!\@\#\$%^&\*\(\);\:\[\]\{\} ]+$:;
+ }
+
+ if ($field[0] =~ /[\[\]]/) {
+ #@ Anchor content should be decimal width
+ #@ xo_emit("{[:mumble}");
+ #@ Should be:
+ #@ xo_emit("{[:32}");
+ #@ Anchors need an integer value to specify the width of
+ #@ the set of anchored fields. The value can be positive
+ #@ (for left padding/right justification) or negative (for
+ #@ right padding/left justification) and can appear in
+ #@ either the start or stop anchor field descriptor.
+ error("anchor content should be decimal width")
+ if $field[1] && $field[1] !~ /^-?\d+$/ ;
+
+ #@ Anchor format should be "%d"
+ #@ xo_emit("{[:/%s}");
+ #@ Should be:
+ #@ xo_emit("{[:/%d}");
+ #@ Anchors only grok integer values, and if the value is not static,
+ #@ if must be in an 'int' argument, represented by the "%d" format.
+ #@ Anything else is an error.
+ error("anchor format should be \"%d\"")
+ if $field[2] && $field[2] ne "%d";
+
+ #@ Anchor cannot have both format and encoding format")
+ #@ xo_emit("{[:32/%d}");
+ #@ Should be:
+ #@ xo_emit("{[:32}");
+ #@ Anchors can have a static value or argument for the width,
+ #@ but cannot have both.
+ error("anchor cannot have both format and encoding format")
+ if $field[1] && $field[2];
+ }
+}
+
+sub count_args {
+ my($format) = @_;
+
+ return -1 unless $format;
+
+ my $in;
+ my($text, $ff, $fc, $rest);
+ for ($in = $format; $in; $in = $rest) {
+ ($text, $ff, $fc, $rest) =
+ ($in =~ /^([^%]*)(%[^%diouxXDOUeEfFgGaAcCsSp]*)([diouxXDOUeEfFgGaAcCsSp])(.*)$/);
+ unless ($ff) {
+ # Might be a "%%"
+ ($text, $ff, $rest) = ($in =~ /^([^%]*)(%%)(.*)$/);
+ if ($ff) {
+ check_text($text);
+ } else {
+ # Not sure what's going on here, but something's wrong...
+ error("invalid field format") if $in =~ /%/;
+ }
+ next;
+ }
+
+ check_text($text);
+ check_field_format($ff, $fc);
+ }
+
+ return 0;
+}
+
+sub check_field_format {
+ my($ff, $fc) = @_;
+
+ print "check_field_format: [$ff] [$fc]\n" if $opt_debug;
+
+ my(@chunks) = split(/\./, $ff);
+
+ #@ Max width only valid for strings
+ #@ xo_emit("{:tag/%2.4.6d}", 55);
+ #@ Should be:
+ #@ xo_emit("{:tag/%2.6d}", 55);
+ #@ libxo allows a true 'max width' in addition to the traditional
+ #@ printf-style 'max number of bytes to use for input'. But this
+ #@ is supported only for string values, since it makes no sense
+ #@ for non-strings. This error may occur from a typo,
+ #@ like "{:tag/%6..6d}" where only one period should be used.
+ error("max width only valid for strings")
+ if $#chunks >= 2 && $fc =~ /[sS]/;
+}
+
+sub error {
+ return if $opt_vocabulary;
+ print STDERR $curfile . ": " .$curln . ": error: " . join(" ", @_) . "\n";
+ print STDERR $replay . "\n" if $opt_print;
+ $errors += 1;
+}
+
+sub warn {
+ return if $opt_vocabulary;
+ print STDERR $curfile . ": " .$curln . ": warning: " . join(" ", @_) . "\n";
+ print STDERR $replay . "\n" if $opt_print;
+ $warnings += 1;
+}
+
+sub info {
+ return if $opt_vocabulary;
+ print STDERR $curfile . ": " .$curln . ": info: " . join(" ", @_) . "\n";
+ print STDERR $replay . "\n" if $opt_print;
+ $info += 1;
+}
+
+main: {
+ main();
+}
OpenPOWER on IntegriCloud