From b6ea204317dc217a95bc3f73681c594b7e23ab07 Mon Sep 17 00:00:00 2001
From: Mario Fetka <mario.fetka@gmail.com>
Date: Mon, 4 Mar 2013 08:18:13 +0100
Subject: [PATCH] add admintools

---
 bin/opsi-administration.sh                    |  141 +++
 doc/.svn/entries                              |    1 +
 doc/.svn/format                               |    1 +
 ...b3d37f5fee64e007f46ad6cdefab2240d.svn-base |   78 ++
 ...f0e0b5be40731b2f7b303e7ad62c7b156.svn-base |   10 +
 ...dceb17119ed5174fe0b955586fb59fdbe.svn-base |  111 ++
 ...bcf71a8d2bad728c8affb0d47d3a8e7e4.svn-base |  132 +++
 ...2948c31a4a218bf635321d2ef7574b628.svn-base |   72 ++
 ...3f78309fd8928266200ada48199f244a4.svn-base |   81 ++
 ...15c5f4bbcd6eae35d95bbff44dcdc7048.svn-base |  292 +++++
 ...d3a7d7540063081f71a4d8d3fe36f0b93.svn-base |   72 ++
 ...44017e0f7b03ef06b8366b743ab6a6c66.svn-base |    4 +
 ...9cd54518240f199dc0e828651e5c12a13.svn-base |   94 ++
 ...80886f95df9c9ee36992b8edabec00bcc.svn-base |  504 ++++++++
 doc/.svn/wc.db                                |  Bin 0 -> 40960 bytes
 doc/CHANGES-1.0.txt                           |  132 +++
 doc/LGPL-2.1                                  |  504 ++++++++
 doc/LICENSE.shunit2                           |  504 ++++++++
 doc/RELEASE_NOTES-1.0.0.txt                   |   72 ++
 doc/RELEASE_NOTES-1.0.1.txt                   |   72 ++
 doc/RELEASE_NOTES-1.0.2.txt                   |   78 ++
 doc/RELEASE_NOTES-1.0.3.txt                   |   94 ++
 doc/RELEASE_NOTES-1.0.4.txt                   |   81 ++
 doc/TODO.txt                                  |   10 +
 doc/coding_standards.txt                      |  111 ++
 doc/contributors.txt                          |    4 +
 doc/rst2html.css                              |  292 +++++
 lib/.svn/entries                              |    1 +
 lib/.svn/format                               |    1 +
 ...f4b507800b3a3d7a26481237369ab67de.svn-base | 1048 +++++++++++++++++
 ...d368239d9aacb1190e335d34582da4be7.svn-base | 1011 ++++++++++++++++
 ...e0fedbae13cef2f056b63aa4e6647ad3e.svn-base |  227 ++++
 ...8826f139bdb4525ac17ad338fc3200f22.svn-base |   40 +
 lib/.svn/wc.db                                |  Bin 0 -> 36864 bytes
 lib/shflags                                   | 1011 ++++++++++++++++
 lib/shlib                                     |   40 +
 lib/shunit2                                   | 1048 +++++++++++++++++
 lib/versions                                  |  227 ++++
 38 files changed, 8201 insertions(+)
 create mode 100755 bin/opsi-administration.sh
 create mode 100644 doc/.svn/entries
 create mode 100644 doc/.svn/format
 create mode 100644 doc/.svn/pristine/21/21f009fb3d37f5fee64e007f46ad6cdefab2240d.svn-base
 create mode 100644 doc/.svn/pristine/24/241107df0e0b5be40731b2f7b303e7ad62c7b156.svn-base
 create mode 100644 doc/.svn/pristine/27/27390dedceb17119ed5174fe0b955586fb59fdbe.svn-base
 create mode 100644 doc/.svn/pristine/30/30089b9bcf71a8d2bad728c8affb0d47d3a8e7e4.svn-base
 create mode 100644 doc/.svn/pristine/37/379e0ef2948c31a4a218bf635321d2ef7574b628.svn-base
 create mode 100644 doc/.svn/pristine/4d/4deb5853f78309fd8928266200ada48199f244a4.svn-base
 create mode 100644 doc/.svn/pristine/50/506d60c15c5f4bbcd6eae35d95bbff44dcdc7048.svn-base
 create mode 100644 doc/.svn/pristine/79/7973171d3a7d7540063081f71a4d8d3fe36f0b93.svn-base
 create mode 100644 doc/.svn/pristine/79/79de1af44017e0f7b03ef06b8366b743ab6a6c66.svn-base
 create mode 100644 doc/.svn/pristine/9c/9cbc81f9cd54518240f199dc0e828651e5c12a13.svn-base
 create mode 100644 doc/.svn/pristine/e6/e60c2e780886f95df9c9ee36992b8edabec00bcc.svn-base
 create mode 100644 doc/.svn/wc.db
 create mode 100644 doc/CHANGES-1.0.txt
 create mode 100644 doc/LGPL-2.1
 create mode 100644 doc/LICENSE.shunit2
 create mode 100644 doc/RELEASE_NOTES-1.0.0.txt
 create mode 100644 doc/RELEASE_NOTES-1.0.1.txt
 create mode 100644 doc/RELEASE_NOTES-1.0.2.txt
 create mode 100644 doc/RELEASE_NOTES-1.0.3.txt
 create mode 100644 doc/RELEASE_NOTES-1.0.4.txt
 create mode 100644 doc/TODO.txt
 create mode 100644 doc/coding_standards.txt
 create mode 100644 doc/contributors.txt
 create mode 100644 doc/rst2html.css
 create mode 100644 lib/.svn/entries
 create mode 100644 lib/.svn/format
 create mode 100644 lib/.svn/pristine/58/584ab94f4b507800b3a3d7a26481237369ab67de.svn-base
 create mode 100644 lib/.svn/pristine/71/7116094d368239d9aacb1190e335d34582da4be7.svn-base
 create mode 100644 lib/.svn/pristine/76/763a881e0fedbae13cef2f056b63aa4e6647ad3e.svn-base
 create mode 100644 lib/.svn/pristine/a4/a40bdb88826f139bdb4525ac17ad338fc3200f22.svn-base
 create mode 100644 lib/.svn/wc.db
 create mode 100644 lib/shflags
 create mode 100644 lib/shlib
 create mode 100644 lib/shunit2
 create mode 100755 lib/versions

diff --git a/bin/opsi-administration.sh b/bin/opsi-administration.sh
new file mode 100755
index 0000000..8101e5f
--- /dev/null
+++ b/bin/opsi-administration.sh
@@ -0,0 +1,141 @@
+#! /bin/sh
+# $Id$
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# This script runs the provided unit tests and sends the output to the
+# appropriate file.
+#
+
+# treat unset variables as an error
+set -u
+
+die()
+{
+  [ $# -gt 0 ] && echo "error: $@" | boxes -d shell >&2
+  exit 1
+}
+
+BASE_DIR="`dirname $0`/.."
+LIB_DIR="${BASE_DIR}/lib"
+
+# load libraries
+. ${LIB_DIR}/shflags || die 'unable to load shflags library'
+. ${LIB_DIR}/shlib || die 'unable to load shlib library'
+. ${LIB_DIR}/versions || die 'unable to load versions library'
+
+#  Source local build configuration (must be done AFTER sourcing the builder-product.cfg.cfg)
+test -f $HOME/.opsi-administration.cfg && . $HOME/.opsi-administration.cfg
+
+
+# define flags
+DEFINE_string 'name' '' 'the name of the package' 'n'
+DEFINE_string 'version' 'latest' 'the version of the package' 'v'
+DEFINE_string 'type' 'public' 'type of package' 'y'
+DEFINE_string 'from' '' 'source level of package' 'f'
+DEFINE_string 'to' '' 'output file to write to' 't'
+DEFINE_string 'root' '' 'output file to write to' 'r'
+DEFINE_string 'show' 'integration' 'show a list of the' 's'
+DEFINE_boolean 'delete' true 'delete old versions of the package' 'd'
+
+FLAGS_HELP="USAGE: ${ARGV0} [flags]"
+
+if [ `which 7z` ] || exit
+
+show()
+{
+  local show_dir=$1
+  local show_name=$2
+  # Find all revision files and sort them
+  local file_list=`mktemp /tmp/opsi-administration.show.XXXXXXXXXXX`
+  local file_list_version=`mktemp /tmp/opsi-administration.show.version.XXXXXXXXXXX`
+  local file_list_release=`mktemp /tmp/opsi-administration.show.release.XXXXXXXXXXX`
+  local file_list_final=`mktemp /tmp/opsi-administration.show.final.XXXXXXXXXXX`
+  local show_list=`mktemp /tmp/opsi-administration.show.list.XXXXXXXXXXX`
+  echo "Web Root: ${show_dir}    Package Name: ${show_name}" >> $show_list
+  echo "" >> $show_list
+  for cfg_file in `find ${show_dir} -name "${show_name}-*.cfg" -print ` ; do
+   . ${cfg_file}
+    echo $REV_VERSION >> ${file_list}
+  done
+  sort -V ${file_list} | uniq > ${file_list_version}
+  for pkg_version in `cat ${file_list_version}` ; do
+    for cfg_file_ver in ${show_dir}/${show_name}-${pkg_version}-*.cfg ; do
+	. ${cfg_file_ver}
+	echo ${pkg_version}-$REV_CREATOR_TAG$REV_RELEASE >> ${file_list_release}
+    done
+  done
+    sort -n ${file_list_release} | uniq > ${file_list_final}
+    for release_file_list in `cat ${file_list_final}` ; do
+	. ${show_dir}/${show_name}-${release_file_list}.cfg
+	echo $REV_PN-$REV_VERSION-$REV_CREATOR_TAG$REV_RELEASE >> $show_list
+    done
+    boxes -d shell  $show_list
+    
+#  rm -f ${show_list}
+#  rm -f ${file_list}
+#  rm -f ${file_list_final}
+#  rm -f ${file_list_version}
+#  rm -f ${file_list_release}
+}
+
+
+main()
+{
+  if [ -n "${FLAGS_root:-}" ];then
+    OPSI_WEB_ROOT=${FLAGS_root:}
+  fi
+  # determine package dir
+  local show_dir="${OPSI_WEB_ROOT}/${FLAGS_type:+${FLAGS_type}/}${FLAGS_show:+${FLAGS_show}/}"
+
+  # checks
+  [ -n "${FLAGS_name:-}" ] || die 'name flag missing'
+  
+  if [ -z "${FLAGS_from:-}" ]; then
+    if [ -z "${FLAGS_from:-}" ]; then
+      show $show_dir ${FLAGS_name:-}
+    fi
+  elif [ -z "${FLAGS_show:-}" ]; then
+      show $show_dir ${FLAGS_name:-}
+  fi
+
+
+
+
+
+#  if [ ${FLAGS_dry_run} -eq ${FLAGS_FALSE} -a -f "${output}" ]; then
+#    if [ ${FLAGS_force} -eq ${FLAGS_TRUE} ]; then
+#      rm -f "${output}"
+#    else
+#      echo "not overwriting '${output}'" >&2
+#      exit ${FLAGS_ERROR}
+#    fi
+#  fi
+#  if [ ${FLAGS_dry_run} -eq ${FLAGS_FALSE} ]; then
+#    touch "${output}" 2>/dev/null || die "unable to write to '${output}'"
+#  fi
+  
+  # run tests
+#  (
+#    cd "${SRC_DIR}";
+#    if [ ${FLAGS_dry_run} -eq ${FLAGS_FALSE} ]; then
+#      ./${FLAGS_suite} |tee "${output}"
+#    else
+#      ./${FLAGS_suite}
+#    fi
+ # )
+  
+#  if [ ! ${FLAGS_dry_run} ]; then
+#    echo >&2
+#    echo "output written to '${output}'" >&2
+#  fi
+}
+
+FLAGS "$@" || exit $?
+[ ${FLAGS_help} -eq ${FALSE} ] || exit
+eval set -- "${FLAGS_ARGV}"
+main "$@"
diff --git a/doc/.svn/entries b/doc/.svn/entries
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/doc/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/doc/.svn/format b/doc/.svn/format
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/doc/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/doc/.svn/pristine/21/21f009fb3d37f5fee64e007f46ad6cdefab2240d.svn-base b/doc/.svn/pristine/21/21f009fb3d37f5fee64e007f46ad6cdefab2240d.svn-base
new file mode 100644
index 0000000..f8154c7
--- /dev/null
+++ b/doc/.svn/pristine/21/21f009fb3d37f5fee64e007f46ad6cdefab2240d.svn-base
@@ -0,0 +1,78 @@
+------------------------------
+shFlags.sh 1.0.1 Release Notes
+------------------------------
+
+Preface
+-------
+Copyright 2008 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+
+Author: Kate Ward (kate.ward@forestent.com)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+General info
+------------
+
+This is both a minor bug fix release, and a minor new feature release of
+shFlags. It adds several warning messages, fixes three issues, and now displays
+the default value behind the help string when help is requested. Additionally,
+the coding standards have been modified slightly and officially documented.
+They were taken from the standards used by shUnit2 (the unit testing framework
+used for the unit testing).
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of **getopt**.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of **getopt** is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+To see the test results for the various OSes tested, please visit
+http://forestent.com/projects/shflags/testresults/.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various **getopt** variants.
+
++-------------------------+---+---+
+|Feature                  |std|enh|
++=========================+===+===+
+|short option names       | Y | Y |
+|long option names        | N | Y |
+|spaces in string options | N | Y |
++-------------------------+---+---+
+
+Known Issues
+------------
+
+The **getopt** version provided by default with all versions of Mac OS X (up to
+and including 10.5.5) is the standard version. As such, only short flags are
+supported.
+
+The **getopt** version provided by default with all versions of Solaris (up to
+and including Solaris 10 and OpenSolaris) is the standard version. As such,
+only short flags are supported.
+
+Workarounds
+-----------
+
+The Zsh shell requires the ``shwordsplit`` option to be set, and the special
+``FLAGS_PARENT`` variable must be defined.
+
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
diff --git a/doc/.svn/pristine/24/241107df0e0b5be40731b2f7b303e7ad62c7b156.svn-base b/doc/.svn/pristine/24/241107df0e0b5be40731b2f7b303e7ad62c7b156.svn-base
new file mode 100644
index 0000000..515c851
--- /dev/null
+++ b/doc/.svn/pristine/24/241107df0e0b5be40731b2f7b303e7ad62c7b156.svn-base
@@ -0,0 +1,10 @@
+improve zsh, automatically ... (pulled from configure)
+
+  if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+    emulate sh
+    NULLCMD=:
+    # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+    # is contrary to our usage.  Disable this feature.
+    alias -g '${1+"$@"}'='"$@"'
+    setopt NO_GLOB_SUBST
+  else
diff --git a/doc/.svn/pristine/27/27390dedceb17119ed5174fe0b955586fb59fdbe.svn-base b/doc/.svn/pristine/27/27390dedceb17119ed5174fe0b955586fb59fdbe.svn-base
new file mode 100644
index 0000000..b2904f5
--- /dev/null
+++ b/doc/.svn/pristine/27/27390dedceb17119ed5174fe0b955586fb59fdbe.svn-base
@@ -0,0 +1,111 @@
+Coding Standards
+================
+
+shFlags is more than just a simple 20 line shell script. It is a pretty
+significant library of shell code that at first glance is not that easy to
+understand. To improve code readability and usability, some guidelines have
+been set down to make the code more understandable for anyone who wants to read
+or modify it.
+
+Function Documentation
+----------------------
+
+Each function should be preceded by a header that provides the following:
+
+#. A one-sentence summary of what the function does
+#. (optional) A longer description of what the function does, and perhaps some
+   special information that helps convey its usage better.
+#. Args: a one-line summary of each argument of the form:
+   ``name: type: description``
+#. Output: a one-line summary of the output provided. Only output to STDOUT
+   must be documented, unless the output to STDERR is of significance (i.e. not
+   just an error message). The output should be of the form:
+   ``type: description``
+#. Returns: a one-line summary of the value returned. Returns in shell are
+   always integers, but if the output is a true/false for success (i.e. a
+   boolean), it should be noted. The output should be of the form:
+   ``type: description``
+
+Here is a sample header: ::
+
+  # Return valid getopt options using currently defined list of long options.
+  #
+  # This function builds a proper getopt option string for short (and long)
+  # options, using the current list of long options for reference.
+  #
+  # Args:
+  #   _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
+  # Output:
+  #   string: generated option string for getopt
+  # Returns:
+  #   boolean: success of operation (always returns True)
+
+Variable and Function Names
+---------------------------
+
+All shFlags specific constants, variables, and functions will be prefixed
+appropriately with 'flags'. This is to distinguish usage in the shFlags code
+from users own scripts so that the shell name space remains predictable to
+users. The exceptions here are the standard ``assertEquals``, etc. functions.
+
+All non built-in constants and variables will be surrouned with squiggle
+brackets, e.g. '${flags_someVariable}' to improve code readability.
+
+Due to some shells not supporting local variables in functions, care in the
+naming and use of variables, both public and private, is very important.
+Accidental overriding of the variables can occur easily if care is not taken as
+all variables are technically global variables in some shells.
+
+================================  ========================
+**type**                          **sample**
+global public constant            ``FLAGS_TRUE``
+global private constant           ``__FLAGS_SHELL_FLAGS``
+global public variable            not used
+global private variable           ``__flags_someVariable``
+global macro                      ``_FLAGS_SOME_MACRO_``
+public function                   ``assertEquals``
+public function, local variable   ``flags_someVariable_``
+private function                  ``_flags_someFunction``
+private function, local variable  ``_flags_someVariable_``
+================================  ========================
+
+Where it makes sense, variables can have the first letter of the second and
+later words capitalized. For example, the local variable name for the total
+number of test cases seen might be ``flags_totalTestsSeen_``.
+
+Local Variable Cleanup
+----------------------
+
+As many shells do not support local variables, no support for cleanup of
+variables is present either. As such, all variables local to a function must be
+cleared up with the ``unset`` command at the end of each function.
+
+Indentation
+-----------
+
+Code block indentation is two (2) spaces, and tabs may not be used. ::
+
+  if [ -z 'some string' ]; then
+    someFunction
+  fi
+
+Lines of code should be no longer than 80 characters unless absolutely
+necessary. When lines are wrapped using the backslash character '\', subsequent
+lines should be indented with four (4) spaces so as to differentiate from the
+standard spacing of two characters, and tabs may not be used. ::
+
+  for x in some set of very long set of arguments that make for a very long \
+      that extends much too long for one line
+  do
+    echo ${x}
+  done
+
+When a conditional expression is written using the builtin [ command, and that
+line must be wrapped, place the control || or && operators on the same line as
+the expression where possible, with the list to be executed on its own line. ::
+
+  [ -n 'some really long expression' -a -n 'some other long expr' ] && \
+      echo 'that was actually true!'
+
+.. vim:spell
+.. $Id$
diff --git a/doc/.svn/pristine/30/30089b9bcf71a8d2bad728c8affb0d47d3a8e7e4.svn-base b/doc/.svn/pristine/30/30089b9bcf71a8d2bad728c8affb0d47d3a8e7e4.svn-base
new file mode 100644
index 0000000..70e229f
--- /dev/null
+++ b/doc/.svn/pristine/30/30089b9bcf71a8d2bad728c8affb0d47d3a8e7e4.svn-base
@@ -0,0 +1,132 @@
+Changes in shFlags 1.0.x
+========================
+
+Changes with 1.0.4
+------------------
+
+Fixed issue #10. Usage of ``expr`` under FreeBSD 7.2 (FreeNAS 0.7.1) and FreeBSD
+8.0 that was causing many unit tests to fail.
+
+Fixed issue where booleans were sometimes mis-configured to require additional
+values like other flags.
+
+Changed _flags_fatal() to exit with FLAGS_ERROR immediately.
+
+Fixed issue #11. When help is requested, the help flag is no longer prefixed
+with [no].
+
+Upgraded shUnit2 to 2.1.6.
+
+Fixed issue #12. Requesting help shouldn't be considered an error.
+
+Added the ability to override the use of the OS default 'getopt' command by
+defining the FLAGS_GETOPT_CMD variable.
+
+Updated gen_test_results.sh and versions from shUnit2 source.
+
+Fixed issues# 13, 14. Added support for dashes ('-') in long flag names. The
+defined flag will still be declared with underscores ('_') due to shell
+limitations, so only one of a dashed flag name or an underscored flag name are
+allowed, not both.
+
+Changes with 1.0.3
+------------------
+
+MAJOR CHANGE! ``FLAGS_ARGC`` is now obsolete, and is replaced by
+``FLAGS_ARGV``. See below for more info.
+
+Fixed issue# 7 where long flags defined with '=' (e.g. --abc=123) made it
+impossible for the user to know how many non-flag command-line arguments were
+available because the value returned by ``FLAGS_ARGC`` was wrong. The
+``FLAGS_ARGC`` value is now obsolete, but will be maintained for backwards
+compatibility. The new method of getting the non-flag arguments is by executing
+``eval set -- "${FLAGS_ARGV}"`` after the **FLAGS** call. The arguments will
+then be available using the standard shell $#, $@, $*, $1, etc. variables.
+
+Due to above fix for issue# 7, there is now proper support for mixing flags
+with non-flag arguments on the command-line. Previously, all non-flag arguments
+had to be at the end of the command-line.
+
+Renamed ``_flags_standardGetopt()`` and ``_flags_enhancedGetopt()`` functions to
+``_flags_getoptStandard()`` and ``_flags_getoptEnhanced()``.
+
+Took out the setting and restoration of the '-u' shell flag to treat unset
+variables as an error. No point in having it in this library as it is verified
+in the unit tests, and provides basically no benefit.
+
+Fixed bug under Solaris where the generated help was adding extra 'x'
+characters.
+
+Added checks for reserved flag variables (e.g. FLAGS_TRUE).
+
+Fixed some unset variable bugs.
+
+Now report the actual getopt error if there is one.
+
+All tests now properly enable skipping based on whether a standard or enhanced
+getopt is found.
+
+Added the OS version to OS release for Solaris.
+
+Fixed flags_reset() so it unsets the default value environment vars.
+
+
+Changes with 1.0.2
+------------------
+
+FLAGS_PARENT no longer transforms into a constant so that it can be defined at
+run time in scripts.
+
+Added warning about short flags being unsupported when there are problems
+parsing the options with **getopt**.
+
+Add default values to end of description strings.
+
+Fixed bug that returned an error instead of success when recalling the default
+values for empty strings.
+
+Added warning when a duplicate flag definition is attempted.
+
+Improved ``assert[Warn|Error]Msg()`` test helper grepping.
+
+Replaced shell_versions.sh with a new versions library and created
+**gen_test_results.sh** to make releases easier.
+
+Copied the coding standards from shUnit2, but haven't fully implemented them
+in shFlags yet.
+
+Issue# 1: When a user defines their own --help flag, no more warning is thrown
+when FLAGS() is called stating that the help flag already defined.
+
+Issue# 2: Passing the --nohelp option no longer gives help output.
+
+Issue# 3: Added support for screen width detection.
+
+
+Changes with 1.0.1
+------------------
+
+Fixed bug where the help output added [no] to all flag names
+
+Added additional example files that are referenced by the documentation.
+
+Improved zsh version and option checking.
+
+Upgraded shUnit2 to 2.1.4
+
+Added unit testing for the help output.
+
+When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually
+execute the code in-line, but later. As such, variables that are defined in the
+library cannot be used until functions are called from the main code. This
+required the 'help' flag definition to be moved inside the FLAGS command.
+
+
+Changes with 1.0.0
+------------------
+
+This is the first official release, so everything is new.
+
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
+.. $Id$
diff --git a/doc/.svn/pristine/37/379e0ef2948c31a4a218bf635321d2ef7574b628.svn-base b/doc/.svn/pristine/37/379e0ef2948c31a4a218bf635321d2ef7574b628.svn-base
new file mode 100644
index 0000000..651e204
--- /dev/null
+++ b/doc/.svn/pristine/37/379e0ef2948c31a4a218bf635321d2ef7574b628.svn-base
@@ -0,0 +1,72 @@
+------------------------------
+shFlags.sh 1.0.1 Release Notes
+------------------------------
+
+Preface
+-------
+Copyright 2008 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+
+Author: Kate Ward (kate.ward@forestent.com)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+General info
+------------
+
+This is a minor bugfix release of shFlags. It mainly fixes poor output of the
+automated help system, but it also includes a couple more examples that are
+referenced by the documentation.
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+Disclamer
+---------
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various getopt variants.
+
++-------------------------+---+---+
+|Feature                  |std|enh|
++=========================+===+===+
+|short option names       | Y | Y |
+|long option names        | N | Y |
+|spaces in string options | N | Y |
++-------------------------+---+---+
+
+Known Issues
+------------
+
+The getopt version provided by default with all versions of Mac OS X (up to and
+including 10.5) is the standard version. As such, only short flags are
+supported.
+
+The getopt version provided by default with all versions of Solaris (up to and
+including Solaris 10) is the standard version. As such, only short flags are
+supported.
+
+Workarounds
+-----------
+
+The zsh shell requires the 'shwordsplit' option to be set, and the special
+FLAGS_PARENT variable must be defined.
diff --git a/doc/.svn/pristine/4d/4deb5853f78309fd8928266200ada48199f244a4.svn-base b/doc/.svn/pristine/4d/4deb5853f78309fd8928266200ada48199f244a4.svn-base
new file mode 100644
index 0000000..06cca0d
--- /dev/null
+++ b/doc/.svn/pristine/4d/4deb5853f78309fd8928266200ada48199f244a4.svn-base
@@ -0,0 +1,81 @@
+------------------------------
+shFlags.sh 1.0.4 Release Notes
+------------------------------
+
+Preface
+=======
+Copyright 2008-2009 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+Author: kate.ward@forestent.com (Kate Ward)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+Release info
+============
+
+This is a minor bug fix release.
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+Major changes
+-------------
+
+Obsolete items
+--------------
+
+Bug fixes
+---------
+
+Issue #10 - Changed the internal usage of the ``expn`` command to fix issues
+under FreeBSD.
+
+General info
+============
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various **getopt** variants.
+
++=========================================+=====+=====+
+| Feature                                 | std | enh |
++-----------------------------------------+-----+-----+
+| short option names                      |  Y  |  Y  |
+| long option names                       |  N  |  Y  |
+| spaces in string options                |  N  |  Y  |
+| intermixing of flag and non-flag values |  N  |  Y  |
++=========================================+=====+=====+
+
+Known Issues
+------------
+
+The **getopt** version provided by default with all versions of Mac OS X (up to
+and including 10.5.6) and Solaris (up to and including Solaris 10 and
+OpenSolaris) is the standard version.
+
+Workarounds
+-----------
+
+The Zsh shell requires the ``shwordsplit`` option to be set and the special
+``FLAGS_PARENT`` variable must be defined. See ``src/shflags_test_helpers`` to
+see how the unit tests do this.
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
diff --git a/doc/.svn/pristine/50/506d60c15c5f4bbcd6eae35d95bbff44dcdc7048.svn-base b/doc/.svn/pristine/50/506d60c15c5f4bbcd6eae35d95bbff44dcdc7048.svn-base
new file mode 100644
index 0000000..01983a5
--- /dev/null
+++ b/doc/.svn/pristine/50/506d60c15c5f4bbcd6eae35d95bbff44dcdc7048.svn-base
@@ -0,0 +1,292 @@
+/*
+:Author: David Goodger
+:Contact: goodger@users.sourceforge.net
+:Date: $Date: 2007-04-11 11:48:16 +0100 (Wed, 11 Apr 2007) $
+:Revision: $Revision: 2791 $
+:Copyright: This stylesheet has been placed in the public domain.
+:Modified by: Kate Ward <kate.ward@forestent.com>
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin-left: 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left {
+  clear: left }
+
+img.align-right {
+  clear: right }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font-family: serif ;
+  font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+  margin-left: 2em ;
+  margin-right: 2em ;
+  background-color: #eeeeee }
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+/*
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+*/
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px ;
+  font-size: 80% }
+  }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+/*
+tt.docutils {
+  background-color: #eeeeee }
+*/
+
+ul.auto-toc {
+  list-style-type: none }
+
+/* customizations by kward */
+
+h1 { font-size: 133%; border-top:1px solid #CCCCFF; }
+h1.title { font-size: 150%; border-top:0px; padding-top: 1em; }
+/* div.document { font-size: 90% } */
diff --git a/doc/.svn/pristine/79/7973171d3a7d7540063081f71a4d8d3fe36f0b93.svn-base b/doc/.svn/pristine/79/7973171d3a7d7540063081f71a4d8d3fe36f0b93.svn-base
new file mode 100644
index 0000000..e489cf5
--- /dev/null
+++ b/doc/.svn/pristine/79/7973171d3a7d7540063081f71a4d8d3fe36f0b93.svn-base
@@ -0,0 +1,72 @@
+------------------------------
+shFlags.sh 1.0.0 Release Notes
+------------------------------
+
+Preface
+-------
+Copyright 2008 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+
+Author: Kate Ward (kate.ward@forestent.com)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+General info
+------------
+
+This is the first official release of shFlags. The project is modeled after the
+gflags code released by Google on http://code.google.com/p/google-gflags/. Many
+thanks for the code they have provided.
+
+As this is the first release, there are bound to be issues. Feel free
+
+Disclamer
+---------
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various getopt variants.
+
++-------------------------+---+---+
+|Feature                  |std|enh|
++=========================+===+===+
+|short option names       | Y | Y |
+|long option names        | N | Y |
+|spaces in string options | N | Y |
++-------------------------+---+---+
+
+Known Issues
+------------
+
+The getopt version provided by default with all versions of Solaris (up to and
+including Solaris 10) is the standard version. As such, only short flags are
+supported.
+
+The getopt version provided by default with all versions of Mac OS X (up to and
+including 10.5) is the standard version. As such, only short flags are
+supported.
+
+Workarounds
+-----------
+
+The zsh shell requires the 'shwordsplit' option to be set, and the special
+FLAGS_PARENT variable must be defined.
diff --git a/doc/.svn/pristine/79/79de1af44017e0f7b03ef06b8366b743ab6a6c66.svn-base b/doc/.svn/pristine/79/79de1af44017e0f7b03ef06b8366b743ab6a6c66.svn-base
new file mode 100644
index 0000000..146c0c0
--- /dev/null
+++ b/doc/.svn/pristine/79/79de1af44017e0f7b03ef06b8366b743ab6a6c66.svn-base
@@ -0,0 +1,4 @@
+I'd like to thank these people for their contributisons to shFlags.
+
+Maciej BliziƄski <blizinski@google.com> -- _many_ code reviews
+Bjarni Einarsson <bre@google.com> -- bug reports
diff --git a/doc/.svn/pristine/9c/9cbc81f9cd54518240f199dc0e828651e5c12a13.svn-base b/doc/.svn/pristine/9c/9cbc81f9cd54518240f199dc0e828651e5c12a13.svn-base
new file mode 100644
index 0000000..edfb1e2
--- /dev/null
+++ b/doc/.svn/pristine/9c/9cbc81f9cd54518240f199dc0e828651e5c12a13.svn-base
@@ -0,0 +1,94 @@
+------------------------------
+shFlags.sh 1.0.3 Release Notes
+------------------------------
+
+Preface
+=======
+Copyright 2008-2009 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+Author: kate.ward@forestent.com (Kate Ward)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+Release info
+============
+
+This is a major bug fix release. The biggest fix is in how non-flag arguments are
+made available to the script.
+
+Major changes
+-------------
+
+The use of the ``FLAGS_ARGC`` variable is now obsolete. It will be maintained
+for backwards compatibility with old scripts, but its value is known to be
+wrong when flag and non-flag arguments are mixed together on the command-line.
+
+To gain access to the non-flag arguments, replace the following snippet of code
+in your scripts with the updated version.
+
+old ::
+  shift ${FLAGS_ARGC}
+
+new ::
+  eval set -- "${FLAGS_ARGV}"
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+Obsolete items
+--------------
+
+Bug fixes
+---------
+
+Issue# 7 Flags set with '=' result in off-by-one shifting error
+
+General info
+============
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various **getopt** variants.
+
++=========================================+=====+=====+
+| Feature                                 | std | enh |
++-----------------------------------------+-----+-----+
+| short option names                      |  Y  |  Y  |
+| long option names                       |  N  |  Y  |
+| spaces in string options                |  N  |  Y  |
+| intermixing of flag and non-flag values |  N  |  Y  |
++=========================================+=====+=====+
+
+Known Issues
+------------
+
+The **getopt** version provided by default with all versions of Mac OS X (up to
+and including 10.5.6) and Solaris (up to and including Solaris 10 and
+OpenSolaris) is the standard version.
+
+Workarounds
+-----------
+
+The Zsh shell requires the ``shwordsplit`` option to be set and the special
+``FLAGS_PARENT`` variable must be defined. See ``src/shflags_test_helpers`` to
+see how the unit tests do this.
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
diff --git a/doc/.svn/pristine/e6/e60c2e780886f95df9c9ee36992b8edabec00bcc.svn-base b/doc/.svn/pristine/e6/e60c2e780886f95df9c9ee36992b8edabec00bcc.svn-base
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/doc/.svn/pristine/e6/e60c2e780886f95df9c9ee36992b8edabec00bcc.svn-base
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/doc/.svn/wc.db b/doc/.svn/wc.db
new file mode 100644
index 0000000000000000000000000000000000000000..620e57781fcc95533c2feb958e600b24d6f8541c
GIT binary patch
literal 40960
zcmeHQdu$xXd7s%m-ti$SvSsQh%Ziq@6!R>R-1pvDRbq-f$+W4X#D^t0Wv}~~B`-SO
zDR)OnZqWp!oHl4tv~U8XiDR^BS_1|8N`Sb9{|O58ffh)OrUi@?ErPginm>ZJMvEkc
zTeRQ4?sk`Z<kFI3Q{E+SZ*JzB+4+9++;6^bX5rFor9~LC-dIyxjDS)IWAr$~AcQW!
zXB0l(bqE~T`{BBe`hG__FQBp4M|vP6O}}o1{{;OO{R8?<`up_1(y!x#_+V6|ciC^E
zKb@UAiczIzkXy}<R{@{0y56eWzsncrXBHM`O2sngxdzI;ne55Kcq3y|%#>&6rY2|0
zlV=w$PA)!id1`)cZn1A_zBsv9WR^-ZmzIjmOli7!g$YqIb0x;1W=5-ZU9FZ?t$AH-
zt>$i}GugxNfTvojRwWLNbI-WxE>51EEw*Db3{x=}c*<h&d~u$Ej9!?WzsfvSyvj^2
zEzZr9Al8LqY4H>g2A;$)i^VI8UM?9XcQTXCe&ldBESx-)Ip@1~x+k4IJc5^97%aZ$
zix=k>W)|n>ucqCcdaPTa7RMb5X0%bSw{p{|Kq^a1Gt(WKo=_@QXgHPi^@@?ZNT;(W
zPvWaKVs0Te$;a18O(&tBsQ`wdz|oqzMovM@+{S}AlN}ks8=th(?BuEAq5>&({Fzaw
zL}C?)1wybKN`O>pX?E5sE{i!g)bj@4oIs_s=SL#T30l+9hv4?mgK&G$YQzs%t?mQ+
z;kK`D5bl`%8iN1iN)Sj8*b4~E;1rr$T5YwiKQ=MZTs5oeN^^XrUSFvay>5_ky}mZl
zyiqF{imv5FVazZ^bBq-^b}X+dg)vddODd66L1d+V;1|>XfZ#v55(E+i?imD5&~tdl
zE&^NQKTZEVqW^<_1HO_gK_Ee3k0Y?3rbqDQx%sEc@UFR3+}BUhhq3dHhWBF#>%5s@
zXZ(K+(XZ`srjzU^2qXx22#nH8IL`FnZU4#q-vciBP7t^^5Qsnj$MjnW{*x;~AVJ{$
zg8+?bgq-<*(*EB+#h!4QAYdbqqG7E+Y5z%WNDz2mB4D?FOE<@w|HCy(zePPqoxp#A
zS8y--UG(JcP+9IzR}h7-9&fIy+;OE~5Kc8kk>wP^nu^8>#AIbHFUYc{h=Qugs;tX0
zdKn*IGbHA?pztOs2#UmUs%FARmNb@dipnVhFYD}bpFeqtl?|EIIZ2mHQPXroCMppm
zqabOT2~Rb2LswWaf9UIO@~o~CmKd_AYn-A;qRjJrp5%36Wrirqa<4ymUJ(kcK@14y
z6pkwpL*f+CB&=4DBq=YOnp7|ijohDdlb1v@Uw}1LInSD0zMyHW$toPLY2a4ng1VgX
zCodXAlk$>aDtUp0gz^PG&&x8;vZ|qqd9F|}c~Mlw{-&EeQHW_4Oo7i!x{y~OO+hcH
zx*!RJs0EQ*PWzKD=$fAA%z|!6qQvES5%N?h7&=Sxd|s9~BIz8ja>Blno4g^gnxH~H
zAiq46150F90FHH8)Hs8X<sN_XyvT8^VgMDZNg5GZMc_0ZidcX$R#Zdgbw%SO89(hN
zpD#ec3k6L!p^#)%CpyOpP*|!Yv8u!w%PD{I0?Ptu1x+^<PR$#<rWy*L*Ym1rYOEnD
zhM?vF5AnWBZt_3~x#fAuR0Ne*0B%#3lmg&S%z~^4%d|gvo-<j%ToVjIF(s1_StKm0
zn4%0h*9~H-8V`sW17|#Nh$(5JVd!~91ipw-P*hbF1*i~;%u3oa<xgHv3Q*5Xz98mx
zfm215=kl5<LrL+R!4p%F6j77;eBYPd<W-d?geS75>bzhYVqTGTsF<W+iY!rNZ5jKM
zR|){O!T|<~0kxQAWr2mF2BbtIZwMw4WD_c>(Dzk0d8J?#2V0P2LoZ0W3V|%A8iHo#
zp?N>jZ;k&0_*F!&(3o1KMfwZW3zS5EgQBRv0q^A6TL|!U1v?!uG+~`5N}kO_cU6!K
z=ne`5sz;%~Yk6X*8qrx+)AfN)l(>C%e<w=Zez>m_C2rr^+ldmlzsz)^#O(vqohWhp
zwVqCtxP4Ws6D4l{LwBOY?Ng{ul(_wbz5d^aZXt9F58)^A7xC-VDD_*^t29f$il*XK
z{(-*Cu9YKq9ig*k`L1eHl3V3YPRd-zP2YWu)4QVydv~;Q_lOGeJFbeoaiK4hJ$e*x
zuGw0^o({P8-5<~Z_I&LctFIFMT629Zti9{g&bAbML3i(ZgEX6!dabR&ZTUAVKTFyk
zjHml+g*1q%*Vk*HH0<dY`$J)JUGDa1P#m`Oe?aL!xe^2t1m1@TSo8m+{l5<jK4CdQ
z01&Xo{~q)lg8#2k|3#mqKZh>E-<@8M97tzR4@KG|!3-J<<en;X*4?s1O6}U<?zx{F
z$YdXW7=QXB_9Sd_YH<k+?n-mhMW1spFctF!*t4;ldf9Ix=gpYF9PM0jzF3+nF0`%b
zz?#gOW;up(4N|pC@<Nk1EBw0JAhlLGKw$ef>eor5RUu7=IXgRd*7DQqHM3gLTjhGy
zwdM-=*2qog0Ri8e^~SYIZKV@(9a4tpeT?X?!I(|Hs@7IWwbJzYwaBejd9ChyRI5Qq
zxt$9`ZK<7PL*8DVA*-Yjo=W=Q>P&XM>81l4F<ZNj)u^njzKv+Uxim9s7xAfJx#a--
zoU|{Uoq4!h<@D8*GUxlT|6_w-=J_z*IOy6px?vY5p}s8o2oJaw&$Dz4&{@WcKH7FJ
zgS98OvOkj*;8{JvXH7jZSvp^w1q)PP8uvv%uS2`#nR>g9<dX6KPP@7!euBW>MIdSa
zd$;V8oF@p}DFTW7?@kd+;wK2~T?CTxfA5xElJf+CJ4L{j|6v7Tg_@?;sPEH%i+&nU
zAp!onUAduj_Dr^$_{5UJEtEO?>+ptle<pk62)=#97SvsyvPFOH*P(!b&h^|@IJcv8
z&Zsnk0=U3JDM;|H5u;osH%JwPapBccX1aK8a%pyv8RINLT6b9zJY}>01DWj55WaoW
zX3P?0TA%v^ELlD_KMiud-rP~%*wH0mMqQbs6EPrC+`>`0Rli1Ht=QhV%adbT3|Q=z
z>o;qp(UI-hez3&62BON4F9-oU3(Q*p@K`tn%gq)uZk}v;T5MtO&)?_lpjC8gL)${V
zW2-(C0I=h4!{`^-`b%fao@SP$)DgC}(X!-z_iSzSl}2vtU^+W_q+9EBTbZ?Go81(%
z-uxebJNmC%Cy@B>5d^4_E2CzmO2#U+W=pMBnc11CVrii`-dtU;Ra!j5F)Vzz9O!}n
z;K>l_`HQn-{5XVmXukPOkOo!@T8)YZ`y)1*<E>jQKkZBNLE1*M#jm#3s^faI>8JaI
z7NmnstYD#|4Ee1YYQxx)ZfP}0KVO_JPA(K-1!%FjFvg9u<6<}~M|O-NgrcDDh0s`>
zo1P2P{8<QGN9gY4AqWQg{Ej)`!>OA)M&ZIygdL->fhb=4r+>6Z>T{CK1c3yByMaLO
zAjbdaz5mnyeK(R!(nt_U5ZEgSWH82-{U1%gX=V9C&feVH=YI2KY8ao!gP2f<5gN*)
z3c~5r2yL80u&r2l8fMRE5N<WrYu6^4_4S5MCSZCtVbt}BZq%QtS$mOJtvTx`Y-0Kt
zsaMCEt!Jx*sj02X4U%*0TjJVLTtlgke)mF=>$wK+x8pZqI{7$kc21ftcmuXJO0}PH
zQ-7?XmJRjBV>d{{QoSBqZ&VqXXRK{hCq}Fr1WbV0+r(~o$!$JLN24_zg_b>;i;b2;
z9TTm%CM3sD>e3&5XZkl!ybZLt5LyBk7c83<0E^lMSoSnFHdqdIOt9h_&kUf{+z-<~
zB{l8>SX^wdY*upTa26UN!V)!t&_QJF!|&|P4}MWq6n&;rvrG%BKzPC$^p9uY_HfE_
z4pOfm`iJx<sc%xR(67;dOn;6p(c^TDzK{B6>VJSBxe^54a|mR6@JSfJLgEZGc%TO#
zwftS#1==^<gU7%lET}*O5A@&@5a5?ep#Fz?uw+wj6+xiBV?8kT;fR6GmN%f@uHm+D
z0cG60d6EQ_c9{r?4Ny<lgq#sI)ivB173i+vPDe=f_CW7}G1_mv|I_Fz2z`ZKqkkR!
z{(G*NLm5has_;N2o6X{1x?~HH?R5tGHXINg+g{r)CiqlWoxM@pQum!SeL?HiAlE?&
zIJ|;jNzH?boE;gvCqVD4JNPotRrKG{HMY`jkQ<dPhGCYqn02Z}#0tP#{RXUetdd4h
zu<v-c>YdDiUUB$T37eM))n$isd$qwL@pOINr~7#7q7U4BcCA{eT`RZL#tQMRK{z_8
z28gmFc=Q6DH41pF2fdR8OXJzF&S+V!!&*m&tyV*=HLEc1Gs*$;IV)CGZQ44~<yK`a
z2oFpH%eo4Tb@a8Z$!Hmrs7a%yRy*nY7a=0mjZZONU9lHRcCm719?E2MS-f%BRRFf@
zbJ@`~w%teE>h5V7`w1+CU$+6cO3=Yt>C2Wq{?or~jsO2f{|o((^xx5cP5&wVC-fiE
zFVQd3pM{|0N)Sj8c;^xD#^gcIvCnf1c#eM0(dRjOJx9iKq&-KE=SX=D+H+XrKWzTx
zj{hn2Erh;>-=LnPPv8-BZuhKiTzN2aM9NxL(O|i;0^KAWL(+s%vP$6aEWaP}M(O#P
z^VZo^QH0FoxkU(?25|x$nFW2BO~hP&qF7?)W~ay7W6sP%XMOi<@%&5)`t_xY)7C*-
z*Ef5!nW0A>!M88nsF0gZ?>MzIZ`o=Des~#rdZu{U=`_nO88f*6=`BDmrWTn;nRD}V
z7u=jc04%t}1zDOew)=SI3^VGIUzofy+Ufd3QF%M=)|-=BjURW6lg=<T*R_?@@tG`5
zGe91kuUOFnJ~?AJGh`iHHPk`kEG(BfFj%e#3@q>N07P)kZd^GWRR>_%5v-qL)PW$O
zTL)%frE=arC(Ks|O2y0Z>Ocdmpei*2Ww;1)C)Y~;OviZ=79l-W+Lh`I<4^xIQ!Gut
z2dno^tc^vp=5IbWYu5aqLa_P&Yt$q3H;^2!?N>jT$#Tb_M!B;SI5e&}Uz(g<aAzp(
z-%Mzh(hhJ5t=8T4>t+nKdErRr$oVXOuITSc%Invy>0sNoEKtSXMij3RECza}E)Q|5
zr`y@go$JhlgWZ+CDlu+%<u3y!+->btuCc0Yrx)BQxwzHj_R|k#vd50$U-&uut*c#R
zZN~?_e%(HZu<iX0y@3U%v+lcxU-xP2+m;vV*CC5|?b_yTs>@3fY#CM#^tbKadW%Mu
zMH*0_+Md+18wHVf9o{*7uSHg>)(ec2nD?^OP6-?y#g4Bhxn%#3c>P^Ml^}3$BH*q6
z-<#YeTqOu32yBNy(*CzYCkaasxVI5V+W);>z6o~;0^1>Aum4l9aesySB5ijD+fgTB
z2?B2u0q$rzTRhgyF0CyvEOTw=u^+FLd82s@_S`y#Z;xydYJ*|uOsP2C&e@17>|83%
zzzMscivU5)Ot~Fib|XYfxBa5J`0g!YMoR|xcCLV|(%%1<M$aJXukiEm#qM0XSc|9s
zyD3F!3RCGlt0_Ei2BltkW%xV)uD`Q7!(x=qFyOXVb%y)C90#{M)*cq4w1>OFwg<F_
z`@ZVH_T4MnRktu~yVWCh^#7WOdKv#7YVO?n?*hf9oC)iBQ|Z&)ItE8`GE%2G!i2z~
zj;ZGz_lyX18>K4G|MuzO+g%jB_m$$*@GaH^@fGB4wsM=9^f2hQ4&w8E+Y12hLkPE3
zN~4i#2giga?pYYX_(xy(HC}tO3o`iW7|4in$Z|l*M_UefT;w*-_Z$Z8-$A@&BeBs7
zW++Y_k`WFo(?%l_rrHS@#<E4ZMxKSe1&k)c3(TaWZa8gin=oTA^RC{aYn~GKWDxW`
zO1<>wFZ}1{f1?Y6_kA`7f|3|QkQ3!-2t#bU<Nq3>{u0;F+FfYf+a<B_iT+_wxgNxG
zcCj6BjEA5CpF%+`?C2s3C~Eu5%f&qIVKfxjZG8J@ju!s63*?8s?m+&d+BQ9}SO`JR
zM+5H9bZ+zMzQdqiK8VZVdiyv61@#D(^JpX@N&SdK8BXo82FE?82mLBa{m#`t`1H^h
zy1;q=Yz#Q1Fr1tyL<1Vddu~(i-Nl&VXzNEqyVWesq238yw+_ZVstElGN^QRJi$gsx
zc0sMb83VPg7HVQ_J0hDcyZxsShp2zT-$NV*OTHbh&CKAiuj}o!VIFO<#fU~YY_Z`-
z)<rSy;Z-}e<dqNGAij>D-KHf=;eokJOAh5bxAExyVQ9*h4HlR}9y|axSTF{GDdZtA
z#foGdxvatlLZi7#&8)x%9MA4J0&J6YAs_05y7l|HjmAFz+@Vu!$D!CfQ<=z2Pqc&I
z?Sc}e5Vze5%H=1w$qWpG?av^-Y<IV=u_}x=d8@Y#?pqRFViQ}){2)a2vThBIdzM-q
zrOanuJUPdA=?2itF}eXM3=G%pH6YB6-TwRGs89M!^jWa>OV0naPcMx-_9f?kCg*?d
z+4Da&$>2om{U6g`g7&||xSs?k2qXyn_z_qh@Sp!1cVfKqVahpHTQN0V5UgXS;kf9$
U2}Tfb2DZk+nb`$6tyvKNA0iFL3IG5A

literal 0
HcmV?d00001

diff --git a/doc/CHANGES-1.0.txt b/doc/CHANGES-1.0.txt
new file mode 100644
index 0000000..0092b4d
--- /dev/null
+++ b/doc/CHANGES-1.0.txt
@@ -0,0 +1,132 @@
+Changes in shFlags 1.0.x
+========================
+
+Changes with 1.0.4
+------------------
+
+Fixed issue #10. Usage of ``expr`` under FreeBSD 7.2 (FreeNAS 0.7.1) and FreeBSD
+8.0 that was causing many unit tests to fail.
+
+Fixed issue where booleans were sometimes mis-configured to require additional
+values like other flags.
+
+Changed _flags_fatal() to exit with FLAGS_ERROR immediately.
+
+Fixed issue #11. When help is requested, the help flag is no longer prefixed
+with [no].
+
+Upgraded shUnit2 to 2.1.6.
+
+Fixed issue #12. Requesting help shouldn't be considered an error.
+
+Added the ability to override the use of the OS default 'getopt' command by
+defining the FLAGS_GETOPT_CMD variable.
+
+Updated gen_test_results.sh and versions from shUnit2 source.
+
+Fixed issues# 13, 14. Added support for dashes ('-') in long flag names. The
+defined flag will still be declared with underscores ('_') due to shell
+limitations, so only one of a dashed flag name or an underscored flag name are
+allowed, not both.
+
+Changes with 1.0.3
+------------------
+
+MAJOR CHANGE! ``FLAGS_ARGC`` is now obsolete, and is replaced by
+``FLAGS_ARGV``. See below for more info.
+
+Fixed issue# 7 where long flags defined with '=' (e.g. --abc=123) made it
+impossible for the user to know how many non-flag command-line arguments were
+available because the value returned by ``FLAGS_ARGC`` was wrong. The
+``FLAGS_ARGC`` value is now obsolete, but will be maintained for backwards
+compatibility. The new method of getting the non-flag arguments is by executing
+``eval set -- "${FLAGS_ARGV}"`` after the **FLAGS** call. The arguments will
+then be available using the standard shell $#, $@, $*, $1, etc. variables.
+
+Due to above fix for issue# 7, there is now proper support for mixing flags
+with non-flag arguments on the command-line. Previously, all non-flag arguments
+had to be at the end of the command-line.
+
+Renamed ``_flags_standardGetopt()`` and ``_flags_enhancedGetopt()`` functions to
+``_flags_getoptStandard()`` and ``_flags_getoptEnhanced()``.
+
+Took out the setting and restoration of the '-u' shell flag to treat unset
+variables as an error. No point in having it in this library as it is verified
+in the unit tests, and provides basically no benefit.
+
+Fixed bug under Solaris where the generated help was adding extra 'x'
+characters.
+
+Added checks for reserved flag variables (e.g. FLAGS_TRUE).
+
+Fixed some unset variable bugs.
+
+Now report the actual getopt error if there is one.
+
+All tests now properly enable skipping based on whether a standard or enhanced
+getopt is found.
+
+Added the OS version to OS release for Solaris.
+
+Fixed flags_reset() so it unsets the default value environment vars.
+
+
+Changes with 1.0.2
+------------------
+
+FLAGS_PARENT no longer transforms into a constant so that it can be defined at
+run time in scripts.
+
+Added warning about short flags being unsupported when there are problems
+parsing the options with **getopt**.
+
+Add default values to end of description strings.
+
+Fixed bug that returned an error instead of success when recalling the default
+values for empty strings.
+
+Added warning when a duplicate flag definition is attempted.
+
+Improved ``assert[Warn|Error]Msg()`` test helper grepping.
+
+Replaced shell_versions.sh with a new versions library and created
+**gen_test_results.sh** to make releases easier.
+
+Copied the coding standards from shUnit2, but haven't fully implemented them
+in shFlags yet.
+
+Issue# 1: When a user defines their own --help flag, no more warning is thrown
+when FLAGS() is called stating that the help flag already defined.
+
+Issue# 2: Passing the --nohelp option no longer gives help output.
+
+Issue# 3: Added support for screen width detection.
+
+
+Changes with 1.0.1
+------------------
+
+Fixed bug where the help output added [no] to all flag names
+
+Added additional example files that are referenced by the documentation.
+
+Improved zsh version and option checking.
+
+Upgraded shUnit2 to 2.1.4
+
+Added unit testing for the help output.
+
+When including a library (e.g. shflags) in a script, zsh 3.0.8 doesn't actually
+execute the code in-line, but later. As such, variables that are defined in the
+library cannot be used until functions are called from the main code. This
+required the 'help' flag definition to be moved inside the FLAGS command.
+
+
+Changes with 1.0.0
+------------------
+
+This is the first official release, so everything is new.
+
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
+.. $Id: CHANGES-1.0.txt 146 2011-06-28 13:26:02Z kate.ward@forestent.com $
diff --git a/doc/LGPL-2.1 b/doc/LGPL-2.1
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/doc/LGPL-2.1
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/doc/LICENSE.shunit2 b/doc/LICENSE.shunit2
new file mode 100644
index 0000000..b1e3f5a
--- /dev/null
+++ b/doc/LICENSE.shunit2
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/doc/RELEASE_NOTES-1.0.0.txt b/doc/RELEASE_NOTES-1.0.0.txt
new file mode 100644
index 0000000..e489cf5
--- /dev/null
+++ b/doc/RELEASE_NOTES-1.0.0.txt
@@ -0,0 +1,72 @@
+------------------------------
+shFlags.sh 1.0.0 Release Notes
+------------------------------
+
+Preface
+-------
+Copyright 2008 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+
+Author: Kate Ward (kate.ward@forestent.com)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+General info
+------------
+
+This is the first official release of shFlags. The project is modeled after the
+gflags code released by Google on http://code.google.com/p/google-gflags/. Many
+thanks for the code they have provided.
+
+As this is the first release, there are bound to be issues. Feel free
+
+Disclamer
+---------
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various getopt variants.
+
++-------------------------+---+---+
+|Feature                  |std|enh|
++=========================+===+===+
+|short option names       | Y | Y |
+|long option names        | N | Y |
+|spaces in string options | N | Y |
++-------------------------+---+---+
+
+Known Issues
+------------
+
+The getopt version provided by default with all versions of Solaris (up to and
+including Solaris 10) is the standard version. As such, only short flags are
+supported.
+
+The getopt version provided by default with all versions of Mac OS X (up to and
+including 10.5) is the standard version. As such, only short flags are
+supported.
+
+Workarounds
+-----------
+
+The zsh shell requires the 'shwordsplit' option to be set, and the special
+FLAGS_PARENT variable must be defined.
diff --git a/doc/RELEASE_NOTES-1.0.1.txt b/doc/RELEASE_NOTES-1.0.1.txt
new file mode 100644
index 0000000..651e204
--- /dev/null
+++ b/doc/RELEASE_NOTES-1.0.1.txt
@@ -0,0 +1,72 @@
+------------------------------
+shFlags.sh 1.0.1 Release Notes
+------------------------------
+
+Preface
+-------
+Copyright 2008 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+
+Author: Kate Ward (kate.ward@forestent.com)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+General info
+------------
+
+This is a minor bugfix release of shFlags. It mainly fixes poor output of the
+automated help system, but it also includes a couple more examples that are
+referenced by the documentation.
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+Disclamer
+---------
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various getopt variants.
+
++-------------------------+---+---+
+|Feature                  |std|enh|
++=========================+===+===+
+|short option names       | Y | Y |
+|long option names        | N | Y |
+|spaces in string options | N | Y |
++-------------------------+---+---+
+
+Known Issues
+------------
+
+The getopt version provided by default with all versions of Mac OS X (up to and
+including 10.5) is the standard version. As such, only short flags are
+supported.
+
+The getopt version provided by default with all versions of Solaris (up to and
+including Solaris 10) is the standard version. As such, only short flags are
+supported.
+
+Workarounds
+-----------
+
+The zsh shell requires the 'shwordsplit' option to be set, and the special
+FLAGS_PARENT variable must be defined.
diff --git a/doc/RELEASE_NOTES-1.0.2.txt b/doc/RELEASE_NOTES-1.0.2.txt
new file mode 100644
index 0000000..f8154c7
--- /dev/null
+++ b/doc/RELEASE_NOTES-1.0.2.txt
@@ -0,0 +1,78 @@
+------------------------------
+shFlags.sh 1.0.1 Release Notes
+------------------------------
+
+Preface
+-------
+Copyright 2008 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+
+Author: Kate Ward (kate.ward@forestent.com)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+General info
+------------
+
+This is both a minor bug fix release, and a minor new feature release of
+shFlags. It adds several warning messages, fixes three issues, and now displays
+the default value behind the help string when help is requested. Additionally,
+the coding standards have been modified slightly and officially documented.
+They were taken from the standards used by shUnit2 (the unit testing framework
+used for the unit testing).
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of **getopt**.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of **getopt** is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+To see the test results for the various OSes tested, please visit
+http://forestent.com/projects/shflags/testresults/.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various **getopt** variants.
+
++-------------------------+---+---+
+|Feature                  |std|enh|
++=========================+===+===+
+|short option names       | Y | Y |
+|long option names        | N | Y |
+|spaces in string options | N | Y |
++-------------------------+---+---+
+
+Known Issues
+------------
+
+The **getopt** version provided by default with all versions of Mac OS X (up to
+and including 10.5.5) is the standard version. As such, only short flags are
+supported.
+
+The **getopt** version provided by default with all versions of Solaris (up to
+and including Solaris 10 and OpenSolaris) is the standard version. As such,
+only short flags are supported.
+
+Workarounds
+-----------
+
+The Zsh shell requires the ``shwordsplit`` option to be set, and the special
+``FLAGS_PARENT`` variable must be defined.
+
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
diff --git a/doc/RELEASE_NOTES-1.0.3.txt b/doc/RELEASE_NOTES-1.0.3.txt
new file mode 100644
index 0000000..edfb1e2
--- /dev/null
+++ b/doc/RELEASE_NOTES-1.0.3.txt
@@ -0,0 +1,94 @@
+------------------------------
+shFlags.sh 1.0.3 Release Notes
+------------------------------
+
+Preface
+=======
+Copyright 2008-2009 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+Author: kate.ward@forestent.com (Kate Ward)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+Release info
+============
+
+This is a major bug fix release. The biggest fix is in how non-flag arguments are
+made available to the script.
+
+Major changes
+-------------
+
+The use of the ``FLAGS_ARGC`` variable is now obsolete. It will be maintained
+for backwards compatibility with old scripts, but its value is known to be
+wrong when flag and non-flag arguments are mixed together on the command-line.
+
+To gain access to the non-flag arguments, replace the following snippet of code
+in your scripts with the updated version.
+
+old ::
+  shift ${FLAGS_ARGC}
+
+new ::
+  eval set -- "${FLAGS_ARGV}"
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+Obsolete items
+--------------
+
+Bug fixes
+---------
+
+Issue# 7 Flags set with '=' result in off-by-one shifting error
+
+General info
+============
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various **getopt** variants.
+
++=========================================+=====+=====+
+| Feature                                 | std | enh |
++-----------------------------------------+-----+-----+
+| short option names                      |  Y  |  Y  |
+| long option names                       |  N  |  Y  |
+| spaces in string options                |  N  |  Y  |
+| intermixing of flag and non-flag values |  N  |  Y  |
++=========================================+=====+=====+
+
+Known Issues
+------------
+
+The **getopt** version provided by default with all versions of Mac OS X (up to
+and including 10.5.6) and Solaris (up to and including Solaris 10 and
+OpenSolaris) is the standard version.
+
+Workarounds
+-----------
+
+The Zsh shell requires the ``shwordsplit`` option to be set and the special
+``FLAGS_PARENT`` variable must be defined. See ``src/shflags_test_helpers`` to
+see how the unit tests do this.
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
diff --git a/doc/RELEASE_NOTES-1.0.4.txt b/doc/RELEASE_NOTES-1.0.4.txt
new file mode 100644
index 0000000..06cca0d
--- /dev/null
+++ b/doc/RELEASE_NOTES-1.0.4.txt
@@ -0,0 +1,81 @@
+------------------------------
+shFlags.sh 1.0.4 Release Notes
+------------------------------
+
+Preface
+=======
+Copyright 2008-2009 Kate Ward. All Rights Reserved.
+Released under the LGPL (GNU Lesser General Public License)
+Author: kate.ward@forestent.com (Kate Ward)
+
+This document covers any known issues and workarounds for the stated release of
+shFlags.
+
+Release info
+============
+
+This is a minor bug fix release.
+
+Please see the CHANGES-1.0.txt file for a complete list of changes.
+
+Major changes
+-------------
+
+Obsolete items
+--------------
+
+Bug fixes
+---------
+
+Issue #10 - Changed the internal usage of the ``expn`` command to fix issues
+under FreeBSD.
+
+General info
+============
+
+The unit tests
+--------------
+
+shFlags is designed to work on as many environments as possible, but not all
+environments are created equal. As such, not all of the unit tests will succeed
+on every platform. The unit tests are therefore designed to fail, indicating to
+the tester that the supported functionality is not present, but an additional
+test is present to verify that shFlags properly caught the limitation and
+presented the user with an appropriate error message.
+
+shFlags tries to support both the standard and enhanced versions of ``getopt``.
+As each responds differently, and not everything is supported on the standard
+version, some unit tests will be skipped (i.e. ASSERTS will not be thrown) when
+the standard version of ``getopt`` is detected. The reason being that there is
+no point testing for functionality that is positively known not to exist. A
+tally of skipped tests will be kept for later reference.
+
+Standard vs Enhanced getopt
+---------------------------
+
+Here is a matrix of the supported features of the various **getopt** variants.
+
++=========================================+=====+=====+
+| Feature                                 | std | enh |
++-----------------------------------------+-----+-----+
+| short option names                      |  Y  |  Y  |
+| long option names                       |  N  |  Y  |
+| spaces in string options                |  N  |  Y  |
+| intermixing of flag and non-flag values |  N  |  Y  |
++=========================================+=====+=====+
+
+Known Issues
+------------
+
+The **getopt** version provided by default with all versions of Mac OS X (up to
+and including 10.5.6) and Solaris (up to and including Solaris 10 and
+OpenSolaris) is the standard version.
+
+Workarounds
+-----------
+
+The Zsh shell requires the ``shwordsplit`` option to be set and the special
+``FLAGS_PARENT`` variable must be defined. See ``src/shflags_test_helpers`` to
+see how the unit tests do this.
+
+.. vim:fileencoding=latin1:ft=rst:spell:tw=80
diff --git a/doc/TODO.txt b/doc/TODO.txt
new file mode 100644
index 0000000..515c851
--- /dev/null
+++ b/doc/TODO.txt
@@ -0,0 +1,10 @@
+improve zsh, automatically ... (pulled from configure)
+
+  if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+    emulate sh
+    NULLCMD=:
+    # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+    # is contrary to our usage.  Disable this feature.
+    alias -g '${1+"$@"}'='"$@"'
+    setopt NO_GLOB_SUBST
+  else
diff --git a/doc/coding_standards.txt b/doc/coding_standards.txt
new file mode 100644
index 0000000..1f6aec3
--- /dev/null
+++ b/doc/coding_standards.txt
@@ -0,0 +1,111 @@
+Coding Standards
+================
+
+shFlags is more than just a simple 20 line shell script. It is a pretty
+significant library of shell code that at first glance is not that easy to
+understand. To improve code readability and usability, some guidelines have
+been set down to make the code more understandable for anyone who wants to read
+or modify it.
+
+Function Documentation
+----------------------
+
+Each function should be preceded by a header that provides the following:
+
+#. A one-sentence summary of what the function does
+#. (optional) A longer description of what the function does, and perhaps some
+   special information that helps convey its usage better.
+#. Args: a one-line summary of each argument of the form:
+   ``name: type: description``
+#. Output: a one-line summary of the output provided. Only output to STDOUT
+   must be documented, unless the output to STDERR is of significance (i.e. not
+   just an error message). The output should be of the form:
+   ``type: description``
+#. Returns: a one-line summary of the value returned. Returns in shell are
+   always integers, but if the output is a true/false for success (i.e. a
+   boolean), it should be noted. The output should be of the form:
+   ``type: description``
+
+Here is a sample header: ::
+
+  # Return valid getopt options using currently defined list of long options.
+  #
+  # This function builds a proper getopt option string for short (and long)
+  # options, using the current list of long options for reference.
+  #
+  # Args:
+  #   _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
+  # Output:
+  #   string: generated option string for getopt
+  # Returns:
+  #   boolean: success of operation (always returns True)
+
+Variable and Function Names
+---------------------------
+
+All shFlags specific constants, variables, and functions will be prefixed
+appropriately with 'flags'. This is to distinguish usage in the shFlags code
+from users own scripts so that the shell name space remains predictable to
+users. The exceptions here are the standard ``assertEquals``, etc. functions.
+
+All non built-in constants and variables will be surrouned with squiggle
+brackets, e.g. '${flags_someVariable}' to improve code readability.
+
+Due to some shells not supporting local variables in functions, care in the
+naming and use of variables, both public and private, is very important.
+Accidental overriding of the variables can occur easily if care is not taken as
+all variables are technically global variables in some shells.
+
+================================  ========================
+**type**                          **sample**
+global public constant            ``FLAGS_TRUE``
+global private constant           ``__FLAGS_SHELL_FLAGS``
+global public variable            not used
+global private variable           ``__flags_someVariable``
+global macro                      ``_FLAGS_SOME_MACRO_``
+public function                   ``assertEquals``
+public function, local variable   ``flags_someVariable_``
+private function                  ``_flags_someFunction``
+private function, local variable  ``_flags_someVariable_``
+================================  ========================
+
+Where it makes sense, variables can have the first letter of the second and
+later words capitalized. For example, the local variable name for the total
+number of test cases seen might be ``flags_totalTestsSeen_``.
+
+Local Variable Cleanup
+----------------------
+
+As many shells do not support local variables, no support for cleanup of
+variables is present either. As such, all variables local to a function must be
+cleared up with the ``unset`` command at the end of each function.
+
+Indentation
+-----------
+
+Code block indentation is two (2) spaces, and tabs may not be used. ::
+
+  if [ -z 'some string' ]; then
+    someFunction
+  fi
+
+Lines of code should be no longer than 80 characters unless absolutely
+necessary. When lines are wrapped using the backslash character '\', subsequent
+lines should be indented with four (4) spaces so as to differentiate from the
+standard spacing of two characters, and tabs may not be used. ::
+
+  for x in some set of very long set of arguments that make for a very long \
+      that extends much too long for one line
+  do
+    echo ${x}
+  done
+
+When a conditional expression is written using the builtin [ command, and that
+line must be wrapped, place the control || or && operators on the same line as
+the expression where possible, with the list to be executed on its own line. ::
+
+  [ -n 'some really long expression' -a -n 'some other long expr' ] && \
+      echo 'that was actually true!'
+
+.. vim:spell
+.. $Id: coding_standards.txt 143 2011-06-10 11:15:05Z kate.ward@forestent.com $
diff --git a/doc/contributors.txt b/doc/contributors.txt
new file mode 100644
index 0000000..146c0c0
--- /dev/null
+++ b/doc/contributors.txt
@@ -0,0 +1,4 @@
+I'd like to thank these people for their contributisons to shFlags.
+
+Maciej BliziƄski <blizinski@google.com> -- _many_ code reviews
+Bjarni Einarsson <bre@google.com> -- bug reports
diff --git a/doc/rst2html.css b/doc/rst2html.css
new file mode 100644
index 0000000..01983a5
--- /dev/null
+++ b/doc/rst2html.css
@@ -0,0 +1,292 @@
+/*
+:Author: David Goodger
+:Contact: goodger@users.sourceforge.net
+:Date: $Date: 2007-04-11 11:48:16 +0100 (Wed, 11 Apr 2007) $
+:Revision: $Revision: 2791 $
+:Copyright: This stylesheet has been placed in the public domain.
+:Modified by: Kate Ward <kate.ward@forestent.com>
+
+Default cascading style sheet for the HTML output of Docutils.
+
+See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
+customize this style sheet.
+*/
+
+/* used to remove borders from tables and images */
+.borderless, table.borderless td, table.borderless th {
+  border: 0 }
+
+table.borderless td, table.borderless th {
+  /* Override padding for "table.docutils td" with "! important".
+     The right padding separates the table cells. */
+  padding: 0 0.5em 0 0 ! important }
+
+.first {
+  /* Override more specific margin styles with "! important". */
+  margin-top: 0 ! important }
+
+.last, .with-subtitle {
+  margin-bottom: 0 ! important }
+
+.hidden {
+  display: none }
+
+a.toc-backref {
+  text-decoration: none ;
+  color: black }
+
+blockquote.epigraph {
+  margin: 2em 5em ; }
+
+dl.docutils dd {
+  margin-bottom: 0.5em }
+
+/* Uncomment (and remove this text!) to get bold-faced definition list terms
+dl.docutils dt {
+  font-weight: bold }
+*/
+
+div.abstract {
+  margin: 2em 5em }
+
+div.abstract p.topic-title {
+  font-weight: bold ;
+  text-align: center }
+
+div.admonition, div.attention, div.caution, div.danger, div.error,
+div.hint, div.important, div.note, div.tip, div.warning {
+  margin: 2em ;
+  border: medium outset ;
+  padding: 1em }
+
+div.admonition p.admonition-title, div.hint p.admonition-title,
+div.important p.admonition-title, div.note p.admonition-title,
+div.tip p.admonition-title {
+  font-weight: bold ;
+  font-family: sans-serif }
+
+div.attention p.admonition-title, div.caution p.admonition-title,
+div.danger p.admonition-title, div.error p.admonition-title,
+div.warning p.admonition-title {
+  color: red ;
+  font-weight: bold ;
+  font-family: sans-serif }
+
+/* Uncomment (and remove this text!) to get reduced vertical space in
+   compound paragraphs.
+div.compound .compound-first, div.compound .compound-middle {
+  margin-bottom: 0.5em }
+
+div.compound .compound-last, div.compound .compound-middle {
+  margin-top: 0.5em }
+*/
+
+div.dedication {
+  margin: 2em 5em ;
+  text-align: center ;
+  font-style: italic }
+
+div.dedication p.topic-title {
+  font-weight: bold ;
+  font-style: normal }
+
+div.figure {
+  margin-left: 2em ;
+  margin-right: 2em }
+
+div.footer, div.header {
+  clear: both;
+  font-size: smaller }
+
+div.line-block {
+  display: block ;
+  margin-top: 1em ;
+  margin-bottom: 1em }
+
+div.line-block div.line-block {
+  margin-top: 0 ;
+  margin-bottom: 0 ;
+  margin-left: 1.5em }
+
+div.sidebar {
+  margin-left: 1em ;
+  border: medium outset ;
+  padding: 1em ;
+  background-color: #ffffee ;
+  width: 40% ;
+  float: right ;
+  clear: right }
+
+div.sidebar p.rubric {
+  font-family: sans-serif ;
+  font-size: medium }
+
+div.system-messages {
+  margin: 5em }
+
+div.system-messages h1 {
+  color: red }
+
+div.system-message {
+  border: medium outset ;
+  padding: 1em }
+
+div.system-message p.system-message-title {
+  color: red ;
+  font-weight: bold }
+
+div.topic {
+  margin: 2em }
+
+h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
+h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
+  margin-top: 0.4em }
+
+h1.title {
+  text-align: center }
+
+h2.subtitle {
+  text-align: center }
+
+hr.docutils {
+  width: 75% }
+
+img.align-left {
+  clear: left }
+
+img.align-right {
+  clear: right }
+
+ol.simple, ul.simple {
+  margin-bottom: 1em }
+
+ol.arabic {
+  list-style: decimal }
+
+ol.loweralpha {
+  list-style: lower-alpha }
+
+ol.upperalpha {
+  list-style: upper-alpha }
+
+ol.lowerroman {
+  list-style: lower-roman }
+
+ol.upperroman {
+  list-style: upper-roman }
+
+p.attribution {
+  text-align: right ;
+  margin-left: 50% }
+
+p.caption {
+  font-style: italic }
+
+p.credits {
+  font-style: italic ;
+  font-size: smaller }
+
+p.label {
+  white-space: nowrap }
+
+p.rubric {
+  font-weight: bold ;
+  font-size: larger ;
+  color: maroon ;
+  text-align: center }
+
+p.sidebar-title {
+  font-family: sans-serif ;
+  font-weight: bold ;
+  font-size: larger }
+
+p.sidebar-subtitle {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+p.topic-title {
+  font-weight: bold }
+
+pre.address {
+  margin-bottom: 0 ;
+  margin-top: 0 ;
+  font-family: serif ;
+  font-size: 100% }
+
+pre.literal-block, pre.doctest-block {
+  margin-left: 2em ;
+  margin-right: 2em ;
+  background-color: #eeeeee }
+
+span.classifier {
+  font-family: sans-serif ;
+  font-style: oblique }
+
+span.classifier-delimiter {
+  font-family: sans-serif ;
+  font-weight: bold }
+
+span.interpreted {
+  font-family: sans-serif }
+
+span.option {
+  white-space: nowrap }
+
+span.pre {
+  white-space: pre }
+
+span.problematic {
+  color: red }
+
+span.section-subtitle {
+  /* font-size relative to parent (h1..h6 element) */
+  font-size: 80% }
+
+table.citation {
+  border-left: solid 1px gray;
+  margin-left: 1px }
+
+table.docinfo {
+  margin: 2em 4em }
+
+/*
+table.docutils {
+  margin-top: 0.5em ;
+  margin-bottom: 0.5em }
+*/
+
+table.footnote {
+  border-left: solid 1px black;
+  margin-left: 1px ;
+  font-size: 80% }
+  }
+
+table.docutils td, table.docutils th,
+table.docinfo td, table.docinfo th {
+  padding-left: 0.5em ;
+  padding-right: 0.5em ;
+  vertical-align: top }
+
+table.docutils th.field-name, table.docinfo th.docinfo-name {
+  font-weight: bold ;
+  text-align: left ;
+  white-space: nowrap ;
+  padding-left: 0 }
+
+h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
+h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
+  font-size: 100% }
+
+/*
+tt.docutils {
+  background-color: #eeeeee }
+*/
+
+ul.auto-toc {
+  list-style-type: none }
+
+/* customizations by kward */
+
+h1 { font-size: 133%; border-top:1px solid #CCCCFF; }
+h1.title { font-size: 150%; border-top:0px; padding-top: 1em; }
+/* div.document { font-size: 90% } */
diff --git a/lib/.svn/entries b/lib/.svn/entries
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/lib/.svn/entries
@@ -0,0 +1 @@
+12
diff --git a/lib/.svn/format b/lib/.svn/format
new file mode 100644
index 0000000..48082f7
--- /dev/null
+++ b/lib/.svn/format
@@ -0,0 +1 @@
+12
diff --git a/lib/.svn/pristine/58/584ab94f4b507800b3a3d7a26481237369ab67de.svn-base b/lib/.svn/pristine/58/584ab94f4b507800b3a3d7a26481237369ab67de.svn-base
new file mode 100644
index 0000000..590a5a8
--- /dev/null
+++ b/lib/.svn/pristine/58/584ab94f4b507800b3a3d7a26481237369ab67de.svn-base
@@ -0,0 +1,1048 @@
+#! /bin/sh
+# $Id: shunit2 322 2011-04-24 00:09:45Z kate.ward@forestent.com $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# shUnit2 -- Unit testing framework for Unix shell scripts.
+# http://code.google.com/p/shunit2/
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# shUnit2 is a xUnit based unit test framework for Bourne shell scripts. It is
+# based on the popular JUnit unit testing framework for Java.
+
+# return if shunit already loaded
+[ -n "${SHUNIT_VERSION:-}" ] && exit 0
+
+SHUNIT_VERSION='2.1.6'
+
+SHUNIT_TRUE=0
+SHUNIT_FALSE=1
+SHUNIT_ERROR=2
+
+# enable strict mode by default
+SHUNIT_STRICT=${SHUNIT_STRICT:-${SHUNIT_TRUE}}
+
+_shunit_warn() { echo "shunit2:WARN $@" >&2; }
+_shunit_error() { echo "shunit2:ERROR $@" >&2; }
+_shunit_fatal() { echo "shunit2:FATAL $@" >&2; exit ${SHUNIT_ERROR}; }
+
+# specific shell checks
+if [ -n "${ZSH_VERSION:-}" ]; then
+  setopt |grep "^shwordsplit$" >/dev/null
+  if [ $? -ne ${SHUNIT_TRUE} ]; then
+    _shunit_fatal 'zsh shwordsplit option is required for proper operation'
+  fi
+  if [ -z "${SHUNIT_PARENT:-}" ]; then
+    _shunit_fatal "zsh does not pass \$0 through properly. please declare \
+\"SHUNIT_PARENT=\$0\" before calling shUnit2"
+  fi
+fi
+
+#
+# constants
+#
+
+__SHUNIT_ASSERT_MSG_PREFIX='ASSERT:'
+__SHUNIT_MODE_SOURCED='sourced'
+__SHUNIT_MODE_STANDALONE='standalone'
+__SHUNIT_PARENT=${SHUNIT_PARENT:-$0}
+
+# set the constants readonly
+shunit_constants_=`set |grep '^__SHUNIT_' |cut -d= -f1`
+echo "${shunit_constants_}" |grep '^Binary file' >/dev/null && \
+    shunit_constants_=`set |grep -a '^__SHUNIT_' |cut -d= -f1`
+for shunit_constant_ in ${shunit_constants_}; do
+  shunit_ro_opts_=''
+  case ${ZSH_VERSION:-} in
+    '') ;;  # this isn't zsh
+    [123].*) ;;  # early versions (1.x, 2.x, 3.x)
+    *) shunit_ro_opts_='-g' ;;  # all later versions. declare readonly globally
+  esac
+  readonly ${shunit_ro_opts_} ${shunit_constant_}
+done
+unset shunit_constant_ shunit_constants_ shunit_ro_opts_
+
+# variables
+__shunit_lineno=''  # line number of executed test
+__shunit_mode=${__SHUNIT_MODE_SOURCED}  # operating mode
+__shunit_reportGenerated=${SHUNIT_FALSE}  # is report generated
+__shunit_script=''  # filename of unittest script (standalone mode)
+__shunit_skip=${SHUNIT_FALSE}  # is skipping enabled
+__shunit_suite=''  # suite of tests to execute
+
+# counts of tests
+__shunit_testSuccess=${SHUNIT_TRUE}
+__shunit_testsTotal=0
+__shunit_testsPassed=0
+__shunit_testsFailed=0
+
+# counts of asserts
+__shunit_assertsTotal=0
+__shunit_assertsPassed=0
+__shunit_assertsFailed=0
+__shunit_assertsSkipped=0
+
+# macros
+_SHUNIT_LINENO_='eval __shunit_lineno=""; if [ "${1:-}" = "--lineno" ]; then [ -n "$2" ] && __shunit_lineno="[$2] "; shift 2; fi'
+
+#-----------------------------------------------------------------------------
+# assert functions
+#
+
+# Assert that two values are equal to one another.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertEquals()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertEquals() requires two or three arguments; $# given"
+    _shunit_error "1: ${1:+$1} 2: ${2:+$2} 3: ${3:+$3}"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_expected_=$1
+  shunit_actual_=$2
+
+  shunit_return=${SHUNIT_TRUE}
+  if [ "${shunit_expected_}" = "${shunit_actual_}" ]; then
+    _shunit_assertPass
+  else
+    failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}"
+    shunit_return=${SHUNIT_FALSE}
+  fi
+
+  unset shunit_message_ shunit_expected_ shunit_actual_
+  return ${shunit_return}
+}
+_ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"'
+
+# Assert that two values are not equal to one another.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNotEquals()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertNotEquals() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_expected_=$1
+  shunit_actual_=$2
+
+  shunit_return=${SHUNIT_TRUE}
+  if [ "${shunit_expected_}" != "${shunit_actual_}" ]; then
+    _shunit_assertPass
+  else
+    failSame "${shunit_message_}" "$@"
+    shunit_return=${SHUNIT_FALSE}
+  fi
+
+  unset shunit_message_ shunit_expected_ shunit_actual_
+  return ${shunit_return}
+}
+_ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"'
+
+# Assert that a value is null (i.e. an empty string)
+#
+# Args:
+#   message: string: failure message [optional]
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNull()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 1 -o $# -gt 2 ]; then
+    _shunit_error "assertNull() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  assertTrue "${shunit_message_}" "[ -z '$1' ]"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"'
+
+# Assert that a value is not null (i.e. a non-empty string)
+#
+# Args:
+#   message: string: failure message [optional]
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNotNull()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -gt 2 ]; then  # allowing 0 arguments as $1 might actually be null
+    _shunit_error "assertNotNull() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_actual_=`_shunit_escapeCharactersInString "${1:-}"`
+  test -n "${shunit_actual_}"
+  assertTrue "${shunit_message_}" $?
+  shunit_return=$?
+
+  unset shunit_actual_ shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"'
+
+# Assert that two values are the same (i.e. equal to one another).
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertSame() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  assertEquals "${shunit_message_}" "$1" "$2"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"'
+
+# Assert that two values are not the same (i.e. not equal to one another).
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNotSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertNotSame() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_:-}$1"
+    shift
+  fi
+  assertNotEquals "${shunit_message_}" "$1" "$2"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"'
+
+# Assert that a value or shell test condition is true.
+#
+# In shell, a value of 0 is true and a non-zero value is false. Any integer
+# value passed can thereby be tested.
+#
+# Shell supports much more complicated tests though, and a means to support
+# them was needed. As such, this function tests that conditions are true or
+# false through evaluation rather than just looking for a true or false.
+#
+# The following test will succeed:
+#   assertTrue 0
+#   assertTrue "[ 34 -gt 23 ]"
+# The folloing test will fail with a message:
+#   assertTrue 123
+#   assertTrue "test failed" "[ -r '/non/existant/file' ]"
+#
+# Args:
+#   message: string: failure message [optional]
+#   condition: string: integer value or shell conditional statement
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertTrue()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -gt 2 ]; then
+    _shunit_error "assertTrue() takes one two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_condition_=$1
+
+  # see if condition is an integer, i.e. a return value
+  shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
+  shunit_return=${SHUNIT_TRUE}
+  if [ -z "${shunit_condition_}" ]; then
+    # null condition
+    shunit_return=${SHUNIT_FALSE}
+  elif [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]
+  then
+    # possible return value. treating 0 as true, and non-zero as false.
+    [ ${shunit_condition_} -ne 0 ] && shunit_return=${SHUNIT_FALSE}
+  else
+    # (hopefully) a condition
+    ( eval ${shunit_condition_} ) >/dev/null 2>&1
+    [ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE}
+  fi
+
+  # record the test
+  if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
+    _shunit_assertPass
+  else
+    _shunit_assertFail "${shunit_message_}"
+  fi
+
+  unset shunit_message_ shunit_condition_ shunit_match_
+  return ${shunit_return}
+}
+_ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"'
+
+# Assert that a value or shell test condition is false.
+#
+# In shell, a value of 0 is true and a non-zero value is false. Any integer
+# value passed can thereby be tested.
+#
+# Shell supports much more complicated tests though, and a means to support
+# them was needed. As such, this function tests that conditions are true or
+# false through evaluation rather than just looking for a true or false.
+#
+# The following test will succeed:
+#   assertFalse 1
+#   assertFalse "[ 'apples' = 'oranges' ]"
+# The folloing test will fail with a message:
+#   assertFalse 0
+#   assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]"
+#
+# Args:
+#   message: string: failure message [optional]
+#   condition: string: integer value or shell conditional statement
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertFalse()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 1 -o $# -gt 2 ]; then
+    _shunit_error "assertFalse() quires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_condition_=$1
+
+  # see if condition is an integer, i.e. a return value
+  shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
+  shunit_return=${SHUNIT_TRUE}
+  if [ -z "${shunit_condition_}" ]; then
+    # null condition
+    shunit_return=${SHUNIT_FALSE}
+  elif [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]
+  then
+    # possible return value. treating 0 as true, and non-zero as false.
+    [ ${shunit_condition_} -eq 0 ] && shunit_return=${SHUNIT_FALSE}
+  else
+    # (hopefully) a condition
+    ( eval ${shunit_condition_} ) >/dev/null 2>&1
+    [ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE}
+  fi
+
+  # record the test
+  if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
+    _shunit_assertPass
+  else
+    _shunit_assertFail "${shunit_message_}"
+  fi
+
+  unset shunit_message_ shunit_condition_ shunit_match_
+  return ${shunit_return}
+}
+_ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"'
+
+#-----------------------------------------------------------------------------
+# failure functions
+#
+
+# Records a test failure.
+#
+# Args:
+#   message: string: failure message [optional]
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+fail()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -gt 1 ]; then
+    _shunit_error "fail() requires zero or one arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 1 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+
+  _shunit_assertFail "${shunit_message_}"
+
+  unset shunit_message_
+  return ${SHUNIT_FALSE}
+}
+_FAIL_='eval fail --lineno "${LINENO:-}"'
+
+# Records a test failure, stating two values were not equal.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+failNotEquals()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "failNotEquals() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_expected_=$1
+  shunit_actual_=$2
+
+  _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected:<${shunit_expected_}> but was:<${shunit_actual_}>"
+
+  unset shunit_message_ shunit_expected_ shunit_actual_
+  return ${SHUNIT_FALSE}
+}
+_FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"'
+
+# Records a test failure, stating two values should have been the same.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+failSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "failSame() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+
+  _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected not same"
+
+  unset shunit_message_
+  return ${SHUNIT_FALSE}
+}
+_FAIL_SAME_='eval failSame --lineno "${LINENO:-}"'
+
+# Records a test failure, stating two values were not equal.
+#
+# This is functionally equivalent to calling failNotEquals().
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+failNotSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "failNotEquals() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  failNotEquals "${shunit_message_}" "$1" "$2"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"'
+
+#-----------------------------------------------------------------------------
+# skipping functions
+#
+
+# Force remaining assert and fail functions to be "skipped".
+#
+# This function forces the remaining assert and fail functions to be "skipped",
+# i.e. they will have no effect. Each function skipped will be recorded so that
+# the total of asserts and fails will not be altered.
+#
+# Args:
+#   None
+startSkipping()
+{
+  __shunit_skip=${SHUNIT_TRUE}
+}
+
+# Resume the normal recording behavior of assert and fail calls.
+#
+# Args:
+#   None
+endSkipping()
+{
+  __shunit_skip=${SHUNIT_FALSE}
+}
+
+# Returns the state of assert and fail call skipping.
+#
+# Args:
+#   None
+# Returns:
+#   boolean: (TRUE/FALSE constant)
+isSkipping()
+{
+  return ${__shunit_skip}
+}
+
+#-----------------------------------------------------------------------------
+# suite functions
+#
+
+# Stub. This function should contains all unit test calls to be made.
+#
+# DEPRECATED (as of 2.1.0)
+#
+# This function can be optionally overridden by the user in their test suite.
+#
+# If this function exists, it will be called when shunit2 is sourced. If it
+# does not exist, shunit2 will search the parent script for all functions
+# beginning with the word 'test', and they will be added dynamically to the
+# test suite.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#suite() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+# Adds a function name to the list of tests schedule for execution.
+#
+# This function should only be called from within the suite() function.
+#
+# Args:
+#   function: string: name of a function to add to current unit test suite
+suite_addTest()
+{
+  shunit_func_=${1:-}
+
+  __shunit_suite="${__shunit_suite:+${__shunit_suite} }${shunit_func_}"
+  __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
+
+  unset shunit_func_
+}
+
+# Stub. This function will be called once before any tests are run.
+#
+# Common one-time environment preparation tasks shared by all tests can be
+# defined here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#oneTimeSetUp() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+# Stub. This function will be called once after all tests are finished.
+#
+# Common one-time environment cleanup tasks shared by all tests can be defined
+# here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#oneTimeTearDown() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+# Stub. This function will be called before each test is run.
+#
+# Common environment preparation tasks shared by all tests can be defined here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#setUp() { :; }
+
+# Note: see _shunit_mktempFunc() for actual implementation
+# Stub. This function will be called after each test is run.
+#
+# Common environment cleanup tasks shared by all tests can be defined here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#tearDown() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+#------------------------------------------------------------------------------
+# internal shUnit2 functions
+#
+
+# Create a temporary directory to store various run-time files in.
+#
+# This function is a cross-platform temporary directory creation tool. Not all
+# OSes have the mktemp function, so one is included here.
+#
+# Args:
+#   None
+# Outputs:
+#   string: the temporary directory that was created
+_shunit_mktempDir()
+{
+  # try the standard mktemp function
+  ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return
+
+  # the standard mktemp didn't work.  doing our own.
+  if [ -r '/dev/urandom' -a -x '/usr/bin/od' ]; then
+    _shunit_random_=`/usr/bin/od -vAn -N4 -tx4 </dev/urandom \
+        |sed 's/^[^0-9a-f]*//'`
+  elif [ -n "${RANDOM:-}" ]; then
+    # $RANDOM works
+    _shunit_random_=${RANDOM}${RANDOM}${RANDOM}$$
+  else
+    # $RANDOM doesn't work
+    _shunit_date_=`date '+%Y%m%d%H%M%S'`
+    _shunit_random_=`expr ${_shunit_date_} / $$`
+  fi
+
+  _shunit_tmpDir_="${TMPDIR:-/tmp}/shunit.${_shunit_random_}"
+  ( umask 077 && mkdir "${_shunit_tmpDir_}" ) || \
+      _shunit_fatal 'could not create temporary directory! exiting'
+
+  echo ${_shunit_tmpDir_}
+  unset _shunit_date_ _shunit_random_ _shunit_tmpDir_
+}
+
+# This function is here to work around issues in Cygwin.
+#
+# Args:
+#   None
+_shunit_mktempFunc()
+{
+  for _shunit_func_ in oneTimeSetUp oneTimeTearDown setUp tearDown suite noexec
+  do
+    _shunit_file_="${__shunit_tmpDir}/${_shunit_func_}"
+    cat <<EOF >"${_shunit_file_}"
+#! /bin/sh
+exit ${SHUNIT_TRUE}
+EOF
+    chmod +x "${_shunit_file_}"
+  done
+
+  unset _shunit_file_
+}
+
+# Final cleanup function to leave things as we found them.
+#
+# Besides removing the temporary directory, this function is in charge of the
+# final exit code of the unit test. The exit code is based on how the script
+# was ended (e.g. normal exit, or via Ctrl-C).
+#
+# Args:
+#   name: string: name of the trap called (specified when trap defined)
+_shunit_cleanup()
+{
+  _shunit_name_=$1
+
+  case ${_shunit_name_} in
+    EXIT) _shunit_signal_=0 ;;
+    INT) _shunit_signal_=2 ;;
+    TERM) _shunit_signal_=15 ;;
+    *)
+      _shunit_warn "unrecognized trap value (${_shunit_name_})"
+      _shunit_signal_=0
+      ;;
+  esac
+
+  # do our work
+  rm -fr "${__shunit_tmpDir}"
+
+  # exit for all non-EXIT signals
+  if [ ${_shunit_name_} != 'EXIT' ]; then
+    _shunit_warn "trapped and now handling the (${_shunit_name_}) signal"
+    # disable EXIT trap
+    trap 0
+    # add 128 to signal and exit
+    exit `expr ${_shunit_signal_} + 128`
+  elif [ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ] ; then
+    _shunit_assertFail 'Unknown failure encountered running a test'
+    _shunit_generateReport
+    exit ${SHUNIT_ERROR}
+  fi
+
+  unset _shunit_name_ _shunit_signal_
+}
+
+# The actual running of the tests happens here.
+#
+# Args:
+#   None
+_shunit_execSuite()
+{
+  for _shunit_test_ in ${__shunit_suite}; do
+    __shunit_testSuccess=${SHUNIT_TRUE}
+
+    # disable skipping
+    endSkipping
+
+    # execute the per-test setup function
+    setUp
+
+    # execute the test
+    echo "${_shunit_test_}"
+    eval ${_shunit_test_}
+
+    # execute the per-test tear-down function
+    tearDown
+
+    # update stats
+    if [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then
+      __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1`
+    else
+      __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1`
+    fi
+  done
+
+  unset _shunit_test_
+}
+
+# Generates the user friendly report with appropriate OK/FAILED message.
+#
+# Args:
+#   None
+# Output:
+#   string: the report of successful and failed tests, as well as totals.
+_shunit_generateReport()
+{
+  _shunit_ok_=${SHUNIT_TRUE}
+
+  # if no exit code was provided one, determine an appropriate one
+  [ ${__shunit_testsFailed} -gt 0 \
+      -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ] \
+          && _shunit_ok_=${SHUNIT_FALSE}
+
+  echo
+  if [ ${__shunit_testsTotal} -eq 1 ]; then
+    echo "Ran ${__shunit_testsTotal} test."
+  else
+    echo "Ran ${__shunit_testsTotal} tests."
+  fi
+
+  _shunit_failures_=''
+  _shunit_skipped_=''
+  [ ${__shunit_assertsFailed} -gt 0 ] \
+      && _shunit_failures_="failures=${__shunit_assertsFailed}"
+  [ ${__shunit_assertsSkipped} -gt 0 ] \
+      && _shunit_skipped_="skipped=${__shunit_assertsSkipped}"
+
+  if [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then
+    _shunit_msg_='OK'
+    [ -n "${_shunit_skipped_}" ] \
+        && _shunit_msg_="${_shunit_msg_} (${_shunit_skipped_})"
+  else
+    _shunit_msg_="FAILED (${_shunit_failures_}"
+    [ -n "${_shunit_skipped_}" ] \
+        && _shunit_msg_="${_shunit_msg_},${_shunit_skipped_}"
+    _shunit_msg_="${_shunit_msg_})"
+  fi
+
+  echo
+  echo ${_shunit_msg_}
+  __shunit_reportGenerated=${SHUNIT_TRUE}
+
+  unset _shunit_failures_ _shunit_msg_ _shunit_ok_ _shunit_skipped_
+}
+
+# Test for whether a function should be skipped.
+#
+# Args:
+#   None
+# Returns:
+#   boolean: whether the test should be skipped (TRUE/FALSE constant)
+_shunit_shouldSkip()
+{
+  [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE}
+  _shunit_assertSkip
+}
+
+# Records a successful test.
+#
+# Args:
+#   None
+_shunit_assertPass()
+{
+  __shunit_assertsPassed=`expr ${__shunit_assertsPassed} + 1`
+  __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
+}
+
+# Records a test failure.
+#
+# Args:
+#   message: string: failure message to provide user
+_shunit_assertFail()
+{
+  _shunit_msg_=$1
+
+  __shunit_testSuccess=${SHUNIT_FALSE}
+  __shunit_assertsFailed=`expr ${__shunit_assertsFailed} + 1`
+  __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
+  echo "${__SHUNIT_ASSERT_MSG_PREFIX}${_shunit_msg_}"
+
+  unset _shunit_msg_
+}
+
+# Records a skipped test.
+#
+# Args:
+#   None
+_shunit_assertSkip()
+{
+  __shunit_assertsSkipped=`expr ${__shunit_assertsSkipped} + 1`
+  __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
+}
+
+# Prepare a script filename for sourcing.
+#
+# Args:
+#   script: string: path to a script to source
+# Returns:
+#   string: filename prefixed with ./ (if necessary)
+_shunit_prepForSourcing()
+{
+  _shunit_script_=$1
+  case "${_shunit_script_}" in
+    /*|./*) echo "${_shunit_script_}" ;;
+    *) echo "./${_shunit_script_}" ;;
+  esac
+  unset _shunit_script_
+}
+
+# Escape a character in a string.
+#
+# Args:
+#   c: string: unescaped character
+#   s: string: to escape character in
+# Returns:
+#   string: with escaped character(s)
+_shunit_escapeCharInStr()
+{
+  [ -n "$2" ] || return  # no point in doing work on an empty string
+
+  # Note: using shorter variable names to prevent conflicts with
+  # _shunit_escapeCharactersInString().
+  _shunit_c_=$1
+  _shunit_s_=$2
+
+
+  # escape the character
+  echo ''${_shunit_s_}'' |sed 's/\'${_shunit_c_}'/\\\'${_shunit_c_}'/g'
+
+  unset _shunit_c_ _shunit_s_
+}
+
+# Escape a character in a string.
+#
+# Args:
+#   str: string: to escape characters in
+# Returns:
+#   string: with escaped character(s)
+_shunit_escapeCharactersInString()
+{
+  [ -n "$1" ] || return  # no point in doing work on an empty string
+
+  _shunit_str_=$1
+
+  # Note: using longer variable names to prevent conflicts with
+  # _shunit_escapeCharInStr().
+  for _shunit_char_ in '"' '$' "'" '`'; do
+    _shunit_str_=`_shunit_escapeCharInStr "${_shunit_char_}" "${_shunit_str_}"`
+  done
+
+  echo "${_shunit_str_}"
+  unset _shunit_char_ _shunit_str_
+}
+
+# Extract list of functions to run tests against.
+#
+# Args:
+#   script: string: name of script to extract functions from
+# Returns:
+#   string: of function names
+_shunit_extractTestFunctions()
+{
+  _shunit_script_=$1
+
+  # extract the lines with test function names, strip of anything besides the
+  # function name, and output everything on a single line.
+  _shunit_regex_='^[ 	]*(function )*test[A-Za-z0-9_]* *\(\)'
+  egrep "${_shunit_regex_}" "${_shunit_script_}" \
+  |sed 's/^[^A-Za-z0-9_]*//;s/^function //;s/\([A-Za-z0-9_]*\).*/\1/g' \
+  |xargs
+
+  unset _shunit_regex_ _shunit_script_
+}
+
+#------------------------------------------------------------------------------
+# main
+#
+
+# determine the operating mode
+if [ $# -eq 0 ]; then
+  __shunit_script=${__SHUNIT_PARENT}
+  __shunit_mode=${__SHUNIT_MODE_SOURCED}
+else
+  __shunit_script=$1
+  [ -r "${__shunit_script}" ] || \
+      _shunit_fatal "unable to read from ${__shunit_script}"
+  __shunit_mode=${__SHUNIT_MODE_STANDALONE}
+fi
+
+# create a temporary storage location
+__shunit_tmpDir=`_shunit_mktempDir`
+
+# provide a public temporary directory for unit test scripts
+# TODO(kward): document this
+SHUNIT_TMPDIR="${__shunit_tmpDir}/tmp"
+mkdir "${SHUNIT_TMPDIR}"
+
+# setup traps to clean up after ourselves
+trap '_shunit_cleanup EXIT' 0
+trap '_shunit_cleanup INT' 2
+trap '_shunit_cleanup TERM' 15
+
+# create phantom functions to work around issues with Cygwin
+_shunit_mktempFunc
+PATH="${__shunit_tmpDir}:${PATH}"
+
+# make sure phantom functions are executable. this will bite if /tmp (or the
+# current $TMPDIR) points to a path on a partition that was mounted with the
+# 'noexec' option. the noexec command was created with _shunit_mktempFunc().
+noexec 2>/dev/null || _shunit_fatal \
+    'please declare TMPDIR with path on partition with exec permission'
+
+# we must manually source the tests in standalone mode
+if [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]; then
+  . "`_shunit_prepForSourcing \"${__shunit_script}\"`"
+fi
+
+# execute the oneTimeSetUp function (if it exists)
+oneTimeSetUp
+
+# execute the suite function defined in the parent test script
+# deprecated as of 2.1.0
+suite
+
+# if no suite function was defined, dynamically build a list of functions
+if [ -z "${__shunit_suite}" ]; then
+  shunit_funcs_=`_shunit_extractTestFunctions "${__shunit_script}"`
+  for shunit_func_ in ${shunit_funcs_}; do
+    suite_addTest ${shunit_func_}
+  done
+fi
+unset shunit_func_ shunit_funcs_
+
+# execute the tests
+_shunit_execSuite
+
+# execute the oneTimeTearDown function (if it exists)
+oneTimeTearDown
+
+# generate the report
+_shunit_generateReport
+
+# that's it folks
+[ ${__shunit_testsFailed} -eq 0 ]
+exit $?
diff --git a/lib/.svn/pristine/71/7116094d368239d9aacb1190e335d34582da4be7.svn-base b/lib/.svn/pristine/71/7116094d368239d9aacb1190e335d34582da4be7.svn-base
new file mode 100644
index 0000000..d09867e
--- /dev/null
+++ b/lib/.svn/pristine/71/7116094d368239d9aacb1190e335d34582da4be7.svn-base
@@ -0,0 +1,1011 @@
+# $Id: shflags 138 2010-03-18 00:25:34Z kate.ward@forestent.com $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# shFlags -- Advanced command-line flag library for Unix shell scripts.
+# http://code.google.com/p/shflags/
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# This module implements something like the google-gflags library available
+# from http://code.google.com/p/google-gflags/.
+#
+# FLAG TYPES: This is a list of the DEFINE_*'s that you can do.  All flags take
+# a name, default value, help-string, and optional 'short' name (one-letter
+# name).  Some flags have other arguments, which are described with the flag.
+#
+# DEFINE_string: takes any input, and intreprets it as a string.
+#
+# DEFINE_boolean: typically does not take any argument: say --myflag to set
+#   FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
+#   Alternately, you can say
+#     --myflag=true  or --myflag=t or --myflag=0  or
+#     --myflag=false or --myflag=f or --myflag=1
+#   Passing an option has the same affect as passing the option once.
+#
+# DEFINE_float: takes an input and intreprets it as a floating point number. As
+#   shell does not support floats per-se, the input is merely validated as
+#   being a valid floating point value.
+#
+# DEFINE_integer: takes an input and intreprets it as an integer.
+#
+# SPECIAL FLAGS: There are a few flags that have special meaning:
+#   --help (or -?)  prints a list of all the flags in a human-readable fashion
+#   --flagfile=foo  read flags from foo.  (not implemented yet)
+#   --              as in getopt(), terminates flag-processing
+#
+# EXAMPLE USAGE:
+#
+#   -- begin hello.sh --
+#   #! /bin/sh
+#   . ./shflags
+#   DEFINE_string name 'world' "somebody's name" n
+#   FLAGS "$@" || exit $?
+#   eval set -- "${FLAGS_ARGV}"
+#   echo "Hello, ${FLAGS_name}."
+#   -- end hello.sh --
+#
+#   $ ./hello.sh -n Kate
+#   Hello, Kate.
+#
+# NOTE: Not all systems include a getopt version that supports long flags. On
+# these systems, only short flags are recognized.
+
+#==============================================================================
+# shFlags
+#
+# Shared attributes:
+#   flags_error: last error message
+#   flags_return: last return value
+#
+#   __flags_longNames: list of long names for all flags
+#   __flags_shortNames: list of short names for all flags
+#   __flags_boolNames: list of boolean flag names
+#
+#   __flags_opts: options parsed by getopt
+#
+# Per-flag attributes:
+#   FLAGS_<flag_name>: contains value of flag named 'flag_name'
+#   __flags_<flag_name>_default: the default flag value
+#   __flags_<flag_name>_help: the flag help string
+#   __flags_<flag_name>_short: the flag short name
+#   __flags_<flag_name>_type: the flag type
+#
+# Notes:
+# - lists of strings are space separated, and a null value is the '~' char.
+
+# return if FLAGS already loaded
+[ -n "${FLAGS_VERSION:-}" ] && return 0
+FLAGS_VERSION='1.0.4pre'
+
+# return values
+FLAGS_TRUE=0
+FLAGS_FALSE=1
+FLAGS_ERROR=2
+
+# reserved flag names
+FLAGS_RESERVED='ARGC ARGV ERROR FALSE HELP PARENT RESERVED TRUE VERSION'
+
+_flags_debug() { echo "flags:DEBUG $@" >&2; }
+_flags_warn() { echo "flags:WARN $@" >&2; }
+_flags_error() { echo "flags:ERROR $@" >&2; }
+_flags_fatal() { echo "flags:FATAL $@" >&2; }
+
+# specific shell checks
+if [ -n "${ZSH_VERSION:-}" ]; then
+  setopt |grep "^shwordsplit$" >/dev/null
+  if [ $? -ne ${FLAGS_TRUE} ]; then
+    _flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
+    exit ${FLAGS_ERROR}
+  fi
+  if [ -z "${FLAGS_PARENT:-}" ]; then
+    _flags_fatal "zsh does not pass \$0 through properly. please declare' \
+\"FLAGS_PARENT=\$0\" before calling shFlags"
+    exit ${FLAGS_ERROR}
+  fi
+fi
+
+#
+# constants
+#
+
+# getopt version
+__FLAGS_GETOPT_VERS_STD=0
+__FLAGS_GETOPT_VERS_ENH=1
+__FLAGS_GETOPT_VERS_BSD=2
+
+getopt >/dev/null 2>&1
+case $? in
+  0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;;  # bsd getopt
+  2)
+    # TODO(kward): look into '-T' option to test the internal getopt() version
+    if [ "`getopt --version`" = '-- ' ]; then
+      __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
+    else
+      __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
+    fi
+    ;;
+  *)
+    _flags_fatal 'unable to determine getopt version'
+    exit ${FLAGS_ERROR}
+    ;;
+esac
+
+# getopt optstring lengths
+__FLAGS_OPTSTR_SHORT=0
+__FLAGS_OPTSTR_LONG=1
+
+__FLAGS_NULL='~'
+
+# flag info strings
+__FLAGS_INFO_DEFAULT='default'
+__FLAGS_INFO_HELP='help'
+__FLAGS_INFO_SHORT='short'
+__FLAGS_INFO_TYPE='type'
+
+# flag lengths
+__FLAGS_LEN_SHORT=0
+__FLAGS_LEN_LONG=1
+
+# flag types
+__FLAGS_TYPE_NONE=0
+__FLAGS_TYPE_BOOLEAN=1
+__FLAGS_TYPE_FLOAT=2
+__FLAGS_TYPE_INTEGER=3
+__FLAGS_TYPE_STRING=4
+
+# set the constants readonly
+__flags_constants=`set |awk -F= '/^FLAGS_/ || /^__FLAGS_/ {print $1}'`
+for __flags_const in ${__flags_constants}; do
+  # skip certain flags
+  case ${__flags_const} in
+    FLAGS_HELP) continue ;;
+    FLAGS_PARENT) continue ;;
+  esac
+  # set flag readonly
+  if [ -z "${ZSH_VERSION:-}" ]; then
+    readonly ${__flags_const}
+  else  # handle zsh
+    case ${ZSH_VERSION} in
+      [123].*) readonly ${__flags_const} ;;
+      *) readonly -g ${__flags_const} ;;  # declare readonly constants globally
+    esac
+  fi
+done
+unset __flags_const __flags_constants
+
+#
+# internal variables
+#
+
+__flags_boolNames=' '  # space separated list of boolean flag names
+__flags_longNames=' '  # space separated list of long flag names
+__flags_shortNames=' '  # space separated list of short flag names
+
+__flags_columns=''  # screen width in columns
+__flags_opts=''  # temporary storage for parsed getopt flags
+
+#------------------------------------------------------------------------------
+# private functions
+#
+
+# Define a flag.
+#
+# Calling this function will define the following info variables for the
+# specified flag:
+#   FLAGS_flagname - the name for this flag (based upon the long flag name)
+#   __flags_<flag_name>_default - the default value
+#   __flags_flagname_help - the help string
+#   __flags_flagname_short - the single letter alias
+#   __flags_flagname_type - the type of flag (one of __FLAGS_TYPE_*)
+#
+# Args:
+#   _flags__type: integer: internal type of flag (__FLAGS_TYPE_*)
+#   _flags__name: string: long flag name
+#   _flags__default: default flag value
+#   _flags__help: string: help string
+#   _flags__short: string: (optional) short flag name
+# Returns:
+#   integer: success of operation, or error
+_flags_define()
+{
+  if [ $# -lt 4 ]; then
+    flags_error='DEFINE error: too few arguments'
+    flags_return=${FLAGS_ERROR}
+    _flags_error "${flags_error}"
+    return ${flags_return}
+  fi
+
+  _flags_type_=$1
+  _flags_name_=$2
+  _flags_default_=$3
+  _flags_help_=$4
+  _flags_short_=${5:-${__FLAGS_NULL}}
+
+  _flags_return_=${FLAGS_TRUE}
+
+  # TODO(kward): check for validity of the flag name (e.g. dashes)
+
+  # check whether the flag name is reserved
+  echo " ${FLAGS_RESERVED} " |grep " ${_flags_name_} " >/dev/null
+  if [ $? -eq 0 ]; then
+    flags_error="flag name (${_flags_name_}) is reserved"
+    _flags_return_=${FLAGS_ERROR}
+  fi
+
+  # require short option for getopt that don't support long options
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
+      -a ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} \
+      -a "${_flags_short_}" = "${__FLAGS_NULL}" ]
+  then
+    flags_error="short flag required for (${_flags_name_}) on this platform"
+    _flags_return_=${FLAGS_ERROR}
+  fi
+
+  # check for existing long name definition
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+    if _flags_itemInList "${_flags_name_}" \
+        ${__flags_longNames} ${__flags_boolNames}
+    then
+      flags_error="flag name ([no]${_flags_name_}) already defined"
+      _flags_warn "${flags_error}"
+      _flags_return_=${FLAGS_FALSE}
+    fi
+  fi
+
+  # check for existing short name definition
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
+      -a "${_flags_short_}" != "${__FLAGS_NULL}" ]
+  then
+    if _flags_itemInList "${_flags_short_}" ${__flags_shortNames}; then
+      flags_error="flag short name (${_flags_short_}) already defined"
+      _flags_warn "${flags_error}"
+      _flags_return_=${FLAGS_FALSE}
+    fi
+  fi
+
+  # handle default value. note, on several occasions the 'if' portion of an
+  # if/then/else contains just a ':' which does nothing. a binary reversal via
+  # '!' is not done because it does not work on all shells.
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+    case ${_flags_type_} in
+      ${__FLAGS_TYPE_BOOLEAN})
+        if _flags_validateBoolean "${_flags_default_}"; then
+          case ${_flags_default_} in
+            true|t|0) _flags_default_=${FLAGS_TRUE} ;;
+            false|f|1) _flags_default_=${FLAGS_FALSE} ;;
+          esac
+        else
+          flags_error="invalid default flag value '${_flags_default_}'"
+          _flags_return_=${FLAGS_ERROR}
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_FLOAT})
+        if _flags_validateFloat "${_flags_default_}"; then
+          :
+        else
+          flags_error="invalid default flag value '${_flags_default_}'"
+          _flags_return_=${FLAGS_ERROR}
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_INTEGER})
+        if _flags_validateInteger "${_flags_default_}"; then
+          :
+        else
+          flags_error="invalid default flag value '${_flags_default_}'"
+          _flags_return_=${FLAGS_ERROR}
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_STRING}) ;;  # everything in shell is a valid string
+
+      *)
+        flags_error="unrecognized flag type '${_flags_type_}'"
+        _flags_return_=${FLAGS_ERROR}
+        ;;
+    esac
+  fi
+
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+    # store flag information
+    eval "FLAGS_${_flags_name_}='${_flags_default_}'"
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}=\
+\"${_flags_default_}\""
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
+
+    # append flag name(s) to list of names
+    __flags_longNames="${__flags_longNames}${_flags_name_} "
+    __flags_shortNames="${__flags_shortNames}${_flags_short_} "
+    [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
+        __flags_boolNames="${__flags_boolNames}no${_flags_name_} "
+  fi
+
+  flags_return=${_flags_return_}
+  unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ _flags_short_ \
+      _flags_type_
+  [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
+  return ${flags_return}
+}
+
+# Return valid getopt options using currently defined list of long options.
+#
+# This function builds a proper getopt option string for short (and long)
+# options, using the current list of long options for reference.
+#
+# Args:
+#   _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
+# Output:
+#   string: generated option string for getopt
+# Returns:
+#   boolean: success of operation (always returns True)
+_flags_genOptStr()
+{
+  _flags_optStrType_=$1
+
+  _flags_opts_=''
+
+  for _flags_flag_ in ${__flags_longNames}; do
+    _flags_type_=`_flags_getFlagInfo ${_flags_flag_} ${__FLAGS_INFO_TYPE}`
+    case ${_flags_optStrType_} in
+      ${__FLAGS_OPTSTR_SHORT})
+        _flags_shortName_=`_flags_getFlagInfo \
+            ${_flags_flag_} ${__FLAGS_INFO_SHORT}`
+        if [ "${_flags_shortName_}" != "${__FLAGS_NULL}" ]; then
+          _flags_opts_="${_flags_opts_}${_flags_shortName_}"
+          # getopt needs a trailing ':' to indicate a required argument
+          [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
+              _flags_opts_="${_flags_opts_}:"
+        fi
+        ;;
+
+      ${__FLAGS_OPTSTR_LONG})
+        _flags_opts_="${_flags_opts_:+${_flags_opts_},}${_flags_flag_}"
+        # getopt needs a trailing ':' to indicate a required argument
+        [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
+            _flags_opts_="${_flags_opts_}:"
+        ;;
+    esac
+  done
+
+  echo "${_flags_opts_}"
+  unset _flags_flag_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
+      _flags_type_
+  return ${FLAGS_TRUE}
+}
+
+# Returns flag details based on a flag name and flag info.
+#
+# Args:
+#   string: long flag name
+#   string: flag info (see the _flags_define function for valid info types)
+# Output:
+#   string: value of dereferenced flag variable
+# Returns:
+#   integer: one of FLAGS_{TRUE|FALSE|ERROR}
+_flags_getFlagInfo()
+{
+  _flags_name_=$1
+  _flags_info_=$2
+
+  _flags_nameVar_="__flags_${_flags_name_}_${_flags_info_}"
+  _flags_strToEval_="_flags_value_=\"\${${_flags_nameVar_}:-}\""
+  eval "${_flags_strToEval_}"
+  if [ -n "${_flags_value_}" ]; then
+    flags_return=${FLAGS_TRUE}
+  else
+    # see if the _flags_name_ variable is a string as strings can be empty...
+    # note: the DRY principle would say to have this function call itself for
+    # the next three lines, but doing so results in an infinite loop as an
+    # invalid _flags_name_ will also not have the associated _type variable.
+    # Because it doesn't (it will evaluate to an empty string) the logic will
+    # try to find the _type variable of the _type variable, and so on. Not so
+    # good ;-)
+    _flags_typeVar_="__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}"
+    _flags_strToEval_="_flags_type_=\"\${${_flags_typeVar_}:-}\""
+    eval "${_flags_strToEval_}"
+    if [ "${_flags_type_}" = "${__FLAGS_TYPE_STRING}" ]; then
+      flags_return=${FLAGS_TRUE}
+    else
+      flags_return=${FLAGS_ERROR}
+      flags_error="invalid flag name (${_flags_nameVar_})"
+    fi
+  fi
+
+  echo "${_flags_value_}"
+  unset _flags_info_ _flags_name_ _flags_strToEval_ _flags_type_ _flags_value_ \
+      _flags_nameVar_ _flags_typeVar_
+  [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
+  return ${flags_return}
+}
+
+# check for presense of item in a list. passed a string (e.g. 'abc'), this
+# function will determine if the string is present in the list of strings (e.g.
+# ' foo bar abc ').
+#
+# Args:
+#   _flags__str: string: string to search for in a list of strings
+#   unnamed: list: list of strings
+# Returns:
+#   boolean: true if item is in the list
+_flags_itemInList()
+{
+  _flags_str_=$1
+  shift
+
+  echo " ${*:-} " |grep " ${_flags_str_} " >/dev/null
+  if [ $? -eq 0 ]; then
+    flags_return=${FLAGS_TRUE}
+  else
+    flags_return=${FLAGS_FALSE}
+  fi
+
+  unset _flags_str_
+  return ${flags_return}
+}
+
+# Returns the width of the current screen.
+#
+# Output:
+#   integer: width in columns of the current screen.
+_flags_columns()
+{
+  if [ -z "${__flags_columns}" ]; then
+    # determine the value and store it
+    if eval stty size >/dev/null 2>&1; then
+      # stty size worked :-)
+      set -- `stty size`
+      __flags_columns=$2
+    elif eval tput cols >/dev/null 2>&1; then
+      set -- `tput cols`
+      __flags_columns=$1
+    else
+      __flags_columns=80  # default terminal width
+    fi
+  fi
+  echo ${__flags_columns}
+}
+
+# Validate a boolean.
+#
+# Args:
+#   _flags__bool: boolean: value to validate
+# Returns:
+#   bool: true if the value is a valid boolean
+_flags_validateBoolean()
+{
+  _flags_bool_=$1
+
+  flags_return=${FLAGS_TRUE}
+  case "${_flags_bool_}" in
+    true|t|0) ;;
+    false|f|1) ;;
+    *) flags_return=${FLAGS_FALSE} ;;
+  esac
+
+  unset _flags_bool_
+  return ${flags_return}
+}
+
+# Validate a float.
+#
+# Args:
+#   _flags__float: float: value to validate
+# Returns:
+#   bool: true if the value is a valid float
+_flags_validateFloat()
+{
+  _flags_float_=$1
+
+  if _flags_validateInteger ${_flags_float_}; then
+    flags_return=${FLAGS_TRUE}
+  else
+    flags_return=${FLAGS_TRUE}
+    case ${_flags_float_} in
+      -*)  # negative floats
+        _flags_test_=`expr -- "${_flags_float_}" :\
+            '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
+        ;;
+      *)  # positive floats
+        _flags_test_=`expr -- "${_flags_float_}" :\
+            '\([0-9][0-9]*\.[0-9][0-9]*\)'`
+        ;;
+    esac
+    [ "${_flags_test_}" != "${_flags_float_}" ] && flags_return=${FLAGS_FALSE}
+  fi
+
+  unset _flags_float_ _flags_test_
+  return ${flags_return}
+}
+
+# Validate an integer.
+#
+# Args:
+#   _flags__integer: interger: value to validate
+# Returns:
+#   bool: true if the value is a valid integer
+_flags_validateInteger()
+{
+  _flags_int_=$1
+
+  flags_return=${FLAGS_TRUE}
+  case ${_flags_int_} in
+    -*)  # negative ints
+      _flags_test_=`expr -- "${_flags_int_}" : '\(-[0-9][0-9]*\)'`
+      ;;
+    *)  # positive ints
+      _flags_test_=`expr -- "${_flags_int_}" : '\([0-9][0-9]*\)'`
+      ;;
+  esac
+  [ "${_flags_test_}" != "${_flags_int_}" ] && flags_return=${FLAGS_FALSE}
+
+  unset _flags_int_ _flags_test_
+  return ${flags_return}
+}
+
+# Parse command-line options using the standard getopt.
+#
+# Note: the flag options are passed around in the global __flags_opts so that
+# the formatting is not lost due to shell parsing and such.
+#
+# Args:
+#   @: varies: command-line options to parse
+# Returns:
+#   integer: a FLAGS success condition
+_flags_getoptStandard()
+{
+  flags_return=${FLAGS_TRUE}
+  _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
+
+  # check for spaces in passed options
+  for _flags_opt_ in "$@"; do
+    # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
+    _flags_match_=`echo "x${_flags_opt_}x" |sed 's/ //g'`
+    if [ "${_flags_match_}" != "x${_flags_opt_}x" ]; then
+      flags_error='the available getopt does not support spaces in options'
+      flags_return=${FLAGS_ERROR}
+      break
+    fi
+  done
+
+  if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
+    __flags_opts=`getopt ${_flags_shortOpts_} $@ 2>&1`
+    _flags_rtrn_=$?
+    if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
+      _flags_warn "${__flags_opts}"
+      flags_error='unable to parse provided options with getopt.'
+      flags_return=${FLAGS_ERROR}
+    fi
+  fi
+
+  unset _flags_match_ _flags_opt_ _flags_rtrn_ _flags_shortOpts_
+  return ${flags_return}
+}
+
+# Parse command-line options using the enhanced getopt.
+#
+# Note: the flag options are passed around in the global __flags_opts so that
+# the formatting is not lost due to shell parsing and such.
+#
+# Args:
+#   @: varies: command-line options to parse
+# Returns:
+#   integer: a FLAGS success condition
+_flags_getoptEnhanced()
+{
+  flags_return=${FLAGS_TRUE}
+  _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
+  _flags_boolOpts_=`echo "${__flags_boolNames}" \
+      |sed 's/^ *//;s/ *$//;s/ /,/g'`
+  _flags_longOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
+
+  __flags_opts=`getopt \
+      -o ${_flags_shortOpts_} \
+      -l "${_flags_longOpts_},${_flags_boolOpts_}" \
+      -- "$@" 2>&1`
+  _flags_rtrn_=$?
+  if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
+    _flags_warn "${__flags_opts}"
+    flags_error='unable to parse provided options with getopt.'
+    flags_return=${FLAGS_ERROR}
+  fi
+
+  unset _flags_boolOpts_ _flags_longOpts_ _flags_rtrn_ _flags_shortOpts_
+  return ${flags_return}
+}
+
+# Dynamically parse a getopt result and set appropriate variables.
+#
+# This function does the actual conversion of getopt output and runs it through
+# the standard case structure for parsing. The case structure is actually quite
+# dynamic to support any number of flags.
+#
+# Args:
+#   argc: int: original command-line argument count
+#   @: varies: output from getopt parsing
+# Returns:
+#   integer: a FLAGS success condition
+_flags_parseGetopt()
+{
+  _flags_argc_=$1
+  shift
+
+  flags_return=${FLAGS_TRUE}
+
+  if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
+    set -- $@
+  else
+    # note the quotes around the `$@' -- they are essential!
+    eval set -- "$@"
+  fi
+
+  # provide user with number of arguments to shift by later
+  # NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not
+  # properly give user access to non-flag arguments mixed in between flag
+  # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only
+  # for backwards compatibility reasons.
+  FLAGS_ARGC=`expr $# - 1 - ${_flags_argc_}`
+
+  # handle options. note options with values must do an additional shift
+  while true; do
+    _flags_opt_=$1
+    _flags_arg_=${2:-}
+    _flags_type_=${__FLAGS_TYPE_NONE}
+    _flags_name_=''
+
+    # determine long flag name
+    case "${_flags_opt_}" in
+      --) shift; break ;;  # discontinue option parsing
+
+      --*)  # long option
+        _flags_opt_=`expr -- "${_flags_opt_}" : '--\(.*\)'`
+        _flags_len_=${__FLAGS_LEN_LONG}
+        if _flags_itemInList "${_flags_opt_}" ${__flags_longNames}; then
+          _flags_name_=${_flags_opt_}
+        else
+          # check for negated long boolean version
+          if _flags_itemInList "${_flags_opt_}" ${__flags_boolNames}; then
+            _flags_name_=`expr -- "${_flags_opt_}" : 'no\(.*\)'`
+            _flags_type_=${__FLAGS_TYPE_BOOLEAN}
+            _flags_arg_=${__FLAGS_NULL}
+          fi
+        fi
+        ;;
+
+      -*)  # short option
+        _flags_opt_=`expr -- "${_flags_opt_}" : '-\(.*\)'`
+        _flags_len_=${__FLAGS_LEN_SHORT}
+        if _flags_itemInList "${_flags_opt_}" ${__flags_shortNames}; then
+          # yes. match short name to long name. note purposeful off-by-one
+          # (too high) with awk calculations.
+          _flags_pos_=`echo "${__flags_shortNames}" \
+              |awk 'BEGIN{RS=" ";rn=0}$0==e{rn=NR}END{print rn}' \
+                  e=${_flags_opt_}`
+          _flags_name_=`echo "${__flags_longNames}" \
+              |awk 'BEGIN{RS=" "}rn==NR{print $0}' rn="${_flags_pos_}"`
+        fi
+        ;;
+    esac
+
+    # die if the flag was unrecognized
+    if [ -z "${_flags_name_}" ]; then
+      flags_error="unrecognized option (${_flags_opt_})"
+      flags_return=${FLAGS_ERROR}
+      break
+    fi
+
+    # set new flag value
+    [ ${_flags_type_} -eq ${__FLAGS_TYPE_NONE} ] && \
+        _flags_type_=`_flags_getFlagInfo \
+            "${_flags_name_}" ${__FLAGS_INFO_TYPE}`
+    case ${_flags_type_} in
+      ${__FLAGS_TYPE_BOOLEAN})
+        if [ ${_flags_len_} -eq ${__FLAGS_LEN_LONG} ]; then
+          if [ "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
+            eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
+          else
+            eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
+          fi
+        else
+          _flags_strToEval_="_flags_val_=\
+\${__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}}"
+          eval "${_flags_strToEval_}"
+          if [ ${_flags_val_} -eq ${FLAGS_FALSE} ]; then
+            eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
+          else
+            eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
+          fi
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_FLOAT})
+        if _flags_validateFloat "${_flags_arg_}"; then
+          eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+        else
+          flags_error="invalid float value (${_flags_arg_})"
+          flags_return=${FLAGS_ERROR}
+          break
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_INTEGER})
+        if _flags_validateInteger "${_flags_arg_}"; then
+          eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+        else
+          flags_error="invalid integer value (${_flags_arg_})"
+          flags_return=${FLAGS_ERROR}
+          break
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_STRING})
+        eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+        ;;
+    esac
+
+    # handle special case help flag
+    if [ "${_flags_name_}" = 'help' ]; then
+      if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then
+        flags_help
+        flags_error='help requested'
+        flags_return=${FLAGS_FALSE}
+        break
+      fi
+    fi
+
+    # shift the option and non-boolean arguements out.
+    shift
+    [ ${_flags_type_} != ${__FLAGS_TYPE_BOOLEAN} ] && shift
+  done
+
+  # give user back non-flag arguments
+  FLAGS_ARGV=''
+  while [ $# -gt 0 ]; do
+    FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} }'$1'"
+    shift
+  done
+
+  unset _flags_arg_ _flags_len_ _flags_name_ _flags_opt_ _flags_pos_ \
+      _flags_strToEval_ _flags_type_ _flags_val_
+  return ${flags_return}
+}
+
+#------------------------------------------------------------------------------
+# public functions
+#
+
+# A basic boolean flag. Boolean flags do not take any arguments, and their
+# value is either 1 (false) or 0 (true). For long flags, the false value is
+# specified on the command line by prepending the word 'no'. With short flags,
+# the presense of the flag toggles the current value between true and false.
+# Specifying a short boolean flag twice on the command results in returning the
+# value back to the default value.
+#
+# A default value is required for boolean flags.
+#
+# For example, lets say a Boolean flag was created whose long name was 'update'
+# and whose short name was 'x', and the default value was 'false'. This flag
+# could be explicitly set to 'true' with '--update' or by '-x', and it could be
+# explicitly set to 'false' with '--noupdate'.
+DEFINE_boolean() { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@"; }
+
+# Other basic flags.
+DEFINE_float()   { _flags_define ${__FLAGS_TYPE_FLOAT} "$@"; }
+DEFINE_integer() { _flags_define ${__FLAGS_TYPE_INTEGER} "$@"; }
+DEFINE_string()  { _flags_define ${__FLAGS_TYPE_STRING} "$@"; }
+
+# Parse the flags.
+#
+# Args:
+#   unnamed: list: command-line flags to parse
+# Returns:
+#   integer: success of operation, or error
+FLAGS()
+{
+  # define a standard 'help' flag if one isn't already defined
+  [ -z "${__flags_help_type:-}" ] && \
+      DEFINE_boolean 'help' false 'show this help' 'h'
+
+  # parse options
+  if [ $# -gt 0 ]; then
+    if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
+      _flags_getoptStandard "$@"
+    else
+      _flags_getoptEnhanced "$@"
+    fi
+    flags_return=$?
+  else
+    # nothing passed; won't bother running getopt
+    __flags_opts='--'
+    flags_return=${FLAGS_TRUE}
+  fi
+
+  if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
+    _flags_parseGetopt $# "${__flags_opts}"
+    flags_return=$?
+  fi
+
+  [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}"
+  return ${flags_return}
+}
+
+# This is a helper function for determining the `getopt` version for platforms
+# where the detection isn't working. It simply outputs debug information that
+# can be included in a bug report.
+#
+# Args:
+#   none
+# Output:
+#   debug info that can be included in a bug report
+# Returns:
+#   nothing
+flags_getoptInfo()
+{
+  # platform info
+  _flags_debug "uname -a: `uname -a`"
+  _flags_debug "PATH: ${PATH}"
+
+  # shell info
+  if [ -n "${BASH_VERSION:-}" ]; then
+    _flags_debug 'shell: bash'
+    _flags_debug "BASH_VERSION: ${BASH_VERSION}"
+  elif [ -n "${ZSH_VERSION:-}" ]; then
+    _flags_debug 'shell: zsh'
+    _flags_debug "ZSH_VERSION: ${ZSH_VERSION}"
+  fi
+
+  # getopt info
+  getopt >/dev/null
+  _flags_getoptReturn=$?
+  _flags_debug "getopt return: ${_flags_getoptReturn}"
+  _flags_debug "getopt --version: `getopt --version 2>&1`"
+
+  unset _flags_getoptReturn
+}
+
+# Returns whether the detected getopt version is the enhanced version.
+#
+# Args:
+#   none
+# Output:
+#   none
+# Returns:
+#   bool: true if getopt is the enhanced version
+flags_getoptIsEnh()
+{
+  test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH}
+}
+
+# Returns whether the detected getopt version is the standard version.
+#
+# Args:
+#   none
+# Returns:
+#   bool: true if getopt is the standard version
+flags_getoptIsStd()
+{
+  test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD}
+}
+
+# This is effectively a 'usage()' function. It prints usage information and
+# exits the program with ${FLAGS_FALSE} if it is ever found in the command line
+# arguments. Note this function can be overridden so other apps can define
+# their own --help flag, replacing this one, if they want.
+#
+# Args:
+#   none
+# Returns:
+#   integer: success of operation (always returns true)
+flags_help()
+{
+  if [ -n "${FLAGS_HELP:-}" ]; then
+    echo "${FLAGS_HELP}" >&2
+  else
+    echo "USAGE: ${FLAGS_PARENT:-$0} [flags] args" >&2
+  fi
+  if [ -n "${__flags_longNames}" ]; then
+    echo 'flags:' >&2
+    for flags_name_ in ${__flags_longNames}; do
+      flags_flagStr_=''
+      flags_boolStr_=''
+
+      flags_default_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_DEFAULT}`
+      flags_help_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_HELP}`
+      flags_short_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_SHORT}`
+      flags_type_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_TYPE}`
+
+      [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
+          && flags_flagStr_="-${flags_short_}"
+
+      if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
+        [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
+            && flags_flagStr_="${flags_flagStr_},"
+        [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] \
+            && flags_boolStr_='[no]'
+        flags_flagStr_="${flags_flagStr_}--${flags_boolStr_}${flags_name_}:"
+      fi
+
+      case ${flags_type_} in
+        ${__FLAGS_TYPE_BOOLEAN})
+          if [ ${flags_default_} -eq ${FLAGS_TRUE} ]; then
+            flags_defaultStr_='true'
+          else
+            flags_defaultStr_='false'
+          fi
+          ;;
+        ${__FLAGS_TYPE_FLOAT}|${__FLAGS_TYPE_INTEGER})
+          flags_defaultStr_=${flags_default_} ;;
+        ${__FLAGS_TYPE_STRING}) flags_defaultStr_="'${flags_default_}'" ;;
+      esac
+      flags_defaultStr_="(default: ${flags_defaultStr_})"
+
+      flags_helpStr_="  ${flags_flagStr_}  ${flags_help_} ${flags_defaultStr_}"
+      flags_helpStrLen_=`expr -- "${flags_helpStr_}" : '.*'`
+      flags_columns_=`_flags_columns`
+      if [ ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
+        echo "${flags_helpStr_}" >&2
+      else
+        echo "  ${flags_flagStr_}  ${flags_help_}" >&2
+        # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
+        # because it doesn't like empty strings when used in this manner.
+        flags_emptyStr_="`echo \"x${flags_flagStr_}x\" \
+            |awk '{printf "%"length($0)-2"s", ""}'`"
+        flags_helpStr_="  ${flags_emptyStr_}  ${flags_defaultStr_}"
+        flags_helpStrLen_=`expr -- "${flags_helpStr_}" : '.*'`
+        if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} \
+            -o ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
+          # indented to match help string
+          echo "${flags_helpStr_}" >&2
+        else
+          # indented four from left to allow for longer defaults as long flag
+          # names might be used too, making things too long
+          echo "    ${flags_defaultStr_}" >&2
+        fi
+      fi
+    done
+  fi
+
+  unset flags_boolStr_ flags_default_ flags_defaultStr_ flags_emptyStr_ \
+      flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
+      flags_columns_ flags_short_ flags_type_
+  return ${FLAGS_TRUE}
+}
+
+# Reset shflags back to an uninitialized state.
+#
+# Args:
+#   none
+# Returns:
+#   nothing
+flags_reset()
+{
+  for flags_name_ in ${__flags_longNames}; do
+    flags_strToEval_="unset FLAGS_${flags_name_}"
+    for flags_type_ in \
+        ${__FLAGS_INFO_DEFAULT} \
+        ${__FLAGS_INFO_HELP} \
+        ${__FLAGS_INFO_SHORT} \
+        ${__FLAGS_INFO_TYPE}
+    do
+      flags_strToEval_=\
+"${flags_strToEval_} __flags_${flags_name_}_${flags_type_}"
+    done
+    eval ${flags_strToEval_}
+  done
+
+  # reset internal variables
+  __flags_boolNames=' '
+  __flags_longNames=' '
+  __flags_shortNames=' '
+
+  unset flags_name_ flags_type_ flags_strToEval_
+}
diff --git a/lib/.svn/pristine/76/763a881e0fedbae13cef2f056b63aa4e6647ad3e.svn-base b/lib/.svn/pristine/76/763a881e0fedbae13cef2f056b63aa4e6647ad3e.svn-base
new file mode 100644
index 0000000..20f2088
--- /dev/null
+++ b/lib/.svn/pristine/76/763a881e0fedbae13cef2f056b63aa4e6647ad3e.svn-base
@@ -0,0 +1,227 @@
+#! /bin/sh
+# $Id$
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# This library provides reusable functions that determine actual names and
+# versions of installed shells and the OS. The library can also be run as a
+# script if set execuatable.
+
+ARGV0=`basename "$0"`
+LSB_RELEASE='/etc/lsb-release'
+VERSIONS_SHELLS="/bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/sh /bin/zsh"
+
+TRUE=0
+FALSE=1
+ERROR=2
+
+__versions_haveStrings=${ERROR}
+
+#------------------------------------------------------------------------------
+# functions
+#
+
+versions_osName()
+{
+  os_name_='unrecognized'
+  os_system_=`uname -s`
+  case ${os_system_} in
+    CYGWIN_NT-*) os_name_='Cygwin' ;;
+    Darwin) os_name_='Mac OS X' ;;
+    FreeBSD) os_name_='FreeBSD' ;;
+    Linux) os_name_='Linux' ;;
+    SunOS)
+      if grep 'OpenSolaris' /etc/release >/dev/null; then
+        os_name_='OpenSolaris'
+      else
+        os_name_='Solaris'
+      fi
+      ;;
+  esac
+  echo ${os_name_}
+  unset os_name_ os_system_
+}
+
+versions_osVersion()
+{
+  os_version_='unrecognized'
+  os_system_=`uname -s`
+  os_release_=`uname -r`
+  case ${os_system_} in
+    CYGWIN_NT-*)
+      os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]\.[0-9]*\).*'`
+      ;;
+    Darwin)
+      major_='10'
+      sub_=`echo ${os_release_} |sed 's/^[0-9]*\.\([0-9]*\)\.[0-9]*$/\1/'`
+      case ${os_release_} in
+        8.*) minor_='4' ;;
+        9.*) minor_='5' ;;
+        10.*) minor_='6' ;;
+        *) minor_='X'; sub_='X' ;;
+      esac
+      os_version_="${major_}.${minor_}.${sub_}"
+      ;;
+    FreeBSD)
+      os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]*\)-.*'`
+      ;;
+    Linux)
+      if [ -r "${LSB_RELEASE}" ]; then
+        if grep -q 'DISTRIB_ID=Ubuntu' "${LSB_RELEASE}"; then
+          os_version_=`cat "${LSB_RELEASE}" \
+            |awk -F= '$1~/DISTRIB_DESCRIPTION/{print $2}' \
+            |sed 's/"//g;s/ /-/g'`
+        fi
+      elif [ -r '/etc/redhat-release' ]; then
+        os_version_=`cat /etc/redhat-release`
+      fi
+      ;;
+    SunOS)
+      if grep 'OpenSolaris' /etc/release >/dev/null; then
+        os_version_=`grep 'OpenSolaris' /etc/release |awk '{print $2"("$3")"}'`
+      else
+        major_=`echo ${os_release_} |sed 's/[0-9]*\.\([0-9]*\)/\1/'`
+        minor_=`grep Solaris /etc/release |sed 's/[^u]*\(u[0-9]*\).*/\1/'`
+        os_version_="${major_}${minor_}"
+      fi
+      ;;
+  esac
+  echo ${os_version_}
+  unset os_name_ os_release_ os_version_ major_ minor_ sub_
+}
+
+versions_shellVersion()
+{
+  shell_=$1
+
+  if [ ! -x "${shell_}" ]; then
+    echo 'not installed'
+    return
+  fi
+
+  version_=''
+  case ${shell_} in
+    */sh)
+      # TODO(kward): fix this
+      ## this could be one of any number of shells. try until one fits.
+      #version_=`versions_shell_bash ${shell_}`
+      ## dash cannot be self determined yet
+      #[ -z "${version_}" ] && version_=`versions_shell_ksh ${shell_}`
+      ## pdksh is covered in versions_shell_ksh()
+      #[ -z "${version_}" ] && version_=`versions_shell_zsh ${shell_}`
+      ;;
+    */bash) version_=`versions_shell_bash ${shell_}` ;;
+    */dash)
+      # simply assuming Ubuntu Linux until somebody comes up with a better
+      # test. the following test will return an empty string if dash is not
+      # installed.
+      version_=`versions_shell_dash`
+      ;;
+    */ksh) version_=`versions_shell_ksh ${shell_}` ;;
+    */pdksh) version_=`versions_shell_pdksh ${shell_}` ;;
+    */zsh) version_=`versions_shell_zsh ${shell_}` ;;
+    *) version_='invalid'
+  esac
+
+  echo ${version_:-unknown}
+  unset shell_ version_
+}
+
+versions_shell_bash()
+{
+  $1 --version 2>&1 |grep 'GNU bash' |sed 's/.*version \([^ ]*\).*/\1/'
+}
+
+versions_shell_dash()
+{
+  eval dpkg >/dev/null 2>&1
+  [ $? -eq 127 ] && return  # return if dpkg not found
+
+  dpkg -l |grep ' dash ' |awk '{print $3}'
+}
+
+versions_shell_ksh()
+{
+  versions_shell_=$1
+
+  # see if --version gives a result
+  versions_version_=`${versions_shell_} --version 2>&1 \
+    |sed 's/.*\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\).*/\1/'`
+
+  # --version didn't work... look into the binary
+  if [ $? -ne ${TRUE} ]; then 
+    _versions_have_strings
+    versions_version_=`strings ${versions_shell_} 2>&1 \
+      |grep Version \
+      |sed 's/^.*Version \(.*\)$/\1/;s/ s+ \$$//;s/ /-/g'`
+    [ -z "${versions_version_}" ] \
+        && versions_version_=`versions_shell_pdksh ${versions_shell_}`
+  fi
+
+  echo ${versions_version_}
+
+  unset versions_shell_ versions_version_
+}
+
+versions_shell_pdksh()
+{
+  _versions_have_strings
+  strings $1 2>&1 \
+  |grep 'PD KSH' \
+  |sed -e 's/.*PD KSH \(.*\)/\1/;s/ /-/g'
+}
+
+versions_shell_zsh()
+{
+  versions_shell_=$1
+
+  versions_version_=`${versions_shell_} --version 2>&1 |awk '{print $2}'`
+
+  if [ $? -ne ${TRUE} ]; then
+    versions_version_=`echo 'echo ${ZSH_VERSION}' |${versions_shell_}`
+  fi
+
+  echo ${versions_version_}
+
+  unset versions_shell_ versions_version_
+}
+
+# Determine if the 'strings' binary installed.
+_versions_have_strings()
+{
+  [ ${__versions_haveStrings} -ne ${ERROR} ] && return
+  eval strings /dev/null >/dev/null 2>&1
+  if [ $? -eq 0 ]; then
+    __versions_haveStrings=${TRUE}
+  else
+    echo 'WARN: strings not installed. try installing binutils?' >&2
+    __versions_haveStrings=${FALSE}
+  fi
+}
+
+#------------------------------------------------------------------------------
+# main
+#
+
+versions_main()
+{
+  # treat unset variables as an error
+  set -u
+
+  os_name=`versions_osName`
+  os_version=`versions_osVersion`
+  echo "os: ${os_name} version: ${os_version}"
+
+  for shell in ${VERSIONS_SHELLS}; do
+    shell_version=`versions_shellVersion ${shell}`
+    echo "shell: ${shell} version: ${shell_version}"
+  done
+}
+
+if [ "${ARGV0}" = 'versions' ]; then
+  versions_main "$@"
+fi
diff --git a/lib/.svn/pristine/a4/a40bdb88826f139bdb4525ac17ad338fc3200f22.svn-base b/lib/.svn/pristine/a4/a40bdb88826f139bdb4525ac17ad338fc3200f22.svn-base
new file mode 100644
index 0000000..d294636
--- /dev/null
+++ b/lib/.svn/pristine/a4/a40bdb88826f139bdb4525ac17ad338fc3200f22.svn-base
@@ -0,0 +1,40 @@
+# $Id: shlib 14 2007-02-18 19:43:41Z sfsetse $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2011 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License).
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# Library of shell functions.
+
+# Convert a relative path into it's absolute equivalent.
+#
+# This function will automatically prepend the current working directory if the
+# path is not already absolute. It then removes all parent references (../) to
+# reconstruct the proper absolute path.
+#
+# Args:
+#   shlib_path_: string: relative path
+# Outputs:
+#   string: absolute path
+shlib_relToAbsPath()
+{
+  shlib_path_=$1
+
+  # prepend current directory to relative paths
+  echo "${shlib_path_}" |grep '^/' >/dev/null 2>&1 \
+      || shlib_path_="`pwd`/${shlib_path_}"
+
+  # clean up the path. if all seds supported true regular expressions, then
+  # this is what it would be:
+  shlib_old_=${shlib_path_}
+  while true; do
+    shlib_new_=`echo "${shlib_old_}" |sed 's/[^/]*\/\.\.\/*//g;s/\/\.\//\//'`
+    [ "${shlib_old_}" = "${shlib_new_}" ] && break
+    shlib_old_=${shlib_new_}
+  done
+  echo "${shlib_new_}"
+
+  unset shlib_path_ shlib_old_ shlib_new_
+}
diff --git a/lib/.svn/wc.db b/lib/.svn/wc.db
new file mode 100644
index 0000000000000000000000000000000000000000..acbd7744357b457efa655dfc5219fd0bf21252da
GIT binary patch
literal 36864
zcmeHQduUtN89zr?mXfr2w5fCBIBBk%bg`P)*87nxw2F0;sBz>(mYZadUaoYHY}K;l
zUdeW{F@}?DjBX6J4mL)iY_JUq`=fspO4&c#UxQJ~=%94$udM4BD`SJP2Ze3lx$i4W
zww$<0?3`=s>gc?`-+A2ceCPYlowztwX%eAaS7+s>5J6sqF?voA5JJQ7ISe23+5--3
z{xIAJ9KYK+htbgOfgT9)akpvsQ{1QAKe@kipKyQTZsXl}ce_OQ*>7Z<j~_jNQKhDk
zYmJwyfR7~4H|yGO=|Vm`QOM>*DP+1Hk+%5xqkVYEuf@npW8<UgF)4j&;zGJ`_R?s6
ze7vxAG%uzLqA;1uUYrz#Y%U{S7FuEo<2gZ(EeuxcCAlie#m1c6oDN*``T0I5;9OHK
zR*4=*zx$1R3+Yp1qLo?@go+|SDFyM2m=~a;=hOKs!a4DZke)1zXLFG1yqGH-gNUw@
z1fd{aE||3xguqe1kAJqW6Bc?Mq>%o-CDY^M`v&k;0|rWWUc4|qku8kpulS6bnxxZE
zO0gY77*y-^W+3Br<uW;$&De2zT5_SGt+~w4SCqg7&c`1;imzyh8I9N=FVB-&iM0Im
zx-e`B9IVN+<QSw3EbYU7eqaDEeMQUDu9NNZxN@@ng+aYVx@r&#g1a4ZfK+aBY>YM+
zCC&&ny}>sS@%Z>N18v(0M$>`)aNEBRZu{sUeu9p=ojc(6=+^CU$J|>8{@KM4U<hmk
z1hUwR#wVwn&AH<vBaP{DRi0`LPu1&FRZ^-eWVlqH9ce7oQc9v!OhzL^N;z5{3PwZ0
zp`@Hh4Mh{lm`q}FBpQru19~y{I|TpiVhAt<HVpz#bK`i`DFV~yKgazRaew1Jf-iP4
z1Q-Gv9DyAiH-ImV=g&#7)|?c*+dNz!*4Jow2Zk_vWrFqR{|AWsV1pCQs?QK$2$%>A
za+A0l_TL!)jQ=-*W8Vyc&4EDo{6FSCMexrqh5$q0;X#1I96~z(&&L15)9j2=hJc2E
zmxH~2HvU;}U<f>v2x#M<%KyEdTZsE1cgphzaIlLZaE}qV>h)ES2VXhdn3h9_W67vo
zOhwDlVl0?Q27|?j98nT-I37)g!jVKIo|234ghJ+G`0%U}6Anic@VgvLg^JOVoC+%C
zNHCs=hNIC$A{<mA;j5f8`$Rk<CzBx(EEA<DlTf5Y%HeV_7B51893}C1G$AVyvgemZ
z_9RhC6oasnUQCq25GAe@Ni<R{%H>ihS`J69dR*CuLh)cKszl<+a3rOqWVuufg;GHh
ziNushG?ol2a<oVi*FQG052lK-WIPp*Bw$aT(iKXPWIR?%Lb0(TiCo3b?B!^%s1%dQ
zWH??9MN;67#=<eV6ry#GB+I2pI2bI4!`|18?Bl7h9F57*aHJfMrQ%RPqEw0}k|d>s
z5@oqapZ{Jiinu8E18$0Y_Z~MrD~=(s;SdOO6}+~&%4;X-cK+cUNxGa<Ja&?9=Lv29
ze=E9%&^6qPpU1D^+nzzsk38>jLGC>?+FjE;vemz4<;XQBu=gzQt2QOMCfPNSLbjV*
ze~r`i(S%(et=tWwg8Z4QVlSQF>gNv}z&B<!Enrgz-2C3=(f~GnwH{lVCZ(Ci{A{cC
zu0uPUD)@r#-keGrjY_>{X>e2jM&*md@(@hjUmBv4a;ZLF1Epb8zt|ZHERxizXiyxc
z{68rDvx_0X5O@d?p!`1@{|{lqGm;qsfB=2|_aG4a-9m49{=psPzK1Ts-`!qEcKP@d
zy>0E0fP)4DxpPv8-l-*$cg+TOw?6-fpFea6fBjjF2}_R_Cc)q?H=Yq4&h0K%%n_h*
zV~ZupX(DHGOkj?7TFi^NQE|eurUPp-%4X??aw@4(le`utj)u?4DycOkR|L&pt<Mp)
zSs@KUI5jqYiu#r6wQ{vmYD)F0Va?_8t&v5&0GID#U7e}artFY8$QjCeiIfb3F)jME
zT$>`*O2gsTB-fhKY~4{*Qzb;QYN5zY+0M4b+pIHGm8h+(qysLS*)`cs9X3*Ku054n
znVP<XWDZ_h7}T2hn7iEq0Dd6$sE^Mc>eM+MJw*yRe(ZQ@JD7PM!b`gi`$i+|LK^x@
z!4Ywn(eX@6M^`**tmueq)zaO20#iHud<4qsahElEHk~^oj)4WLBag@0muJUaR%XfS
zBLVjOzuT#frDq6iTm;zo-?(kZYR(Y2TLhT=?`{!f=@|kW7XkMC-?(kZYR(Y2TLd)u
zA5I{g@MJu*o=>>npcnBdiojo|E70rXPx76_CsYbIA%(QBzNO;he!jmS-|W`}b(cmp
z(Vy|P$0eXMJXaLXtty>UDymxm=h`R*3Em7*q$*h;RS?Ft?v@G}@pO7}tRM`9s35Jg
zED1`vv2CZH@9o7m7d67DD3g93cacPWG<sArS8uE;Z?ts@gh4~*s3&xZ6qivXHS043
z_KLNWyG%JIC4iDE)fa0-wPkynA8awtf~c~^7leTJ2J<oiOcIX4b~7c$sFNm7>sr|R
z<;V0Bv_!o(SQhHGt$MEuK-*t~(J8QXw$8FM&8VbQ7q(hxQMuoy?TwDs2n_A^@#+3f
zqth5=^vE`CDDo!%&&}(9od!MgX9zF^)(?SioE<Dzs${5AYc%C*RcK7l*DB4h5E6p$
z2?d~}>F3>17Klo<f*Q^^nPu5%hk-ex3}oEdG^VSSq7}g!|NmY;+E`8u0fxW>kHD7g
z82`^)|8xI&;OomO$Pi!%tRn(`j4?f%o1Xsx*J1d2V;!?!=d5m=@b=*YcsoAh=|iY@
zX&8agnC}EaOM?iTyb;1pb-p$;(x}g?B{C8k4vqk~Ghzk5TB8S@S1Ic?2q&Z-C-v%3
zqj|kbgqqx}ED(Wu&XDV{f>atpI3lFyo6~hw$k4@cRuS@Kp`xi~Yl*Ls(!92m1$OG0
zfNm1ft$hdjHuC=X3;SOA`FCa@@8LyRRi1-W*h!-aOLKaHt5(0o(s5Om6nWveLBi0y
zS{0%Rfu8R=GC*$-FcON!Mph&|ur$r>#r=SusG+yZ0`GGO8z;ziz|IVHLTA$2rC|#C
zCi33+=+@$q@7@8e@ny6I+tX@P6qfm(y_g45(=DVvMM;J3(2-CY)`rY(jcM+xNu$fi
z?9ikd34zlZg$Tzy0|@O#^c;TuY<}FHI`nF#MokN<q)9-2RjHLLkmQh;KL2~Tw-NU*
z?nCa++}qr*)_K^n>=*(Jfpte<XAjKg80IrgY=C-p^}w?c+s{F-6+sgSAZ~jP%osEQ
zo#Z@QdSHIU82RY>pF?jV^d>jUeINa7-7C7z8G65(dcx21JbvY(_T<&}8MND8m*`mY
zT5&VMp}MM{jcQ5VSJU(bty?fZ2PNRv9Rw;hcPnz*GImpdZtpudD$r5%Z|fS<yj7F?
zFiX}71fGGu)uPP~z-)a1_B*DD>K5$l-p#sQInXO^eXE3?^>Wo^opNorfkrWPeT~u`
zG<DDiZd{+OR%$a+Q&y*lV-G^tNmW3UZE#pl8qGj`j{=Hq7YOfYp{yEQbSs2buBpnk
zMitmAMRJ+X(XguA&~&1uW@Xk54{%#jNe04feQnAwN}xnd)S6ti^LK7Sv{g4gCYXIi
z+bCJX&RKbnpAYbOsn1XV*7~!g>l$nBextjaTE@-@RN>bc0EQB@yH`4@r9c1Qr_cYt
za)0E0&%M9S1D0jS5MT)0O9aekdynbxnhwr%(C0rK{$)J>z34-PKExk+p68y%1L*YH
zE4y@gpT9rGQ>$pO+?axC5?({nfTtu~Zb(i)WIm<y*)#OrRP7=P>C*)W%7|kkyfO>s
zGA)vD>8zL&#>X<l)-xwNVejvr63=9FFt1Nu$j}#U&E43-`+JWZ!8b21RLG(}JC07~
zsjY_VhgqQ)vf?Fu(v*y7LV5!7n}Ax37KCSn)A{l9Mol09Hr(NYD&<9Mju%b}gGTi8
z>C1!m)ZdactfgIk({rnZhjrtmlS0jKEsv`Eq;nYoqPzJOn#|=BQ1<$J>5Hp+Z6r>m
zCqx|v>S}`l_3jKn8_I)Am;2iF0odRI>!&XIfIFhm2eP>dF|WNR%+UvO;-&8TfC^Sn
zl^TIIECBChSjnHXoku}#W0GQZs*{2<{}Y0k%RGSHdo|LA+LPuSJ{oD1|Mws`{Qm>b
z5jg!P-rd-*KI!K}2cbt9+zIeoVm_B1n=m*O>$lLtrC0$*L^`@HzfQ(bH_rF_`_J(B
zmgt;Gr1?3@4qCQlt}b>5Nz6e|aLr5|3NgB;G1-itw)tT9bmi<yf-zk=+dycYwpMG`
zuDYx}3$B)3x83CC3;X^2!Gri~U(!}xR+CwdC(U_Xdl8}K{TZ#m-0ZBe_HgPxEnjV!
zp-vsLHp?!0_C|-*REI^9LdueBzO`oSWg1yDs!M%p<*0P=1yboctT`OZB6D%0XJ#&z
zten7M##nWE5@6?lbT{9zSPX&9iGaEPzd5O6R51h?0xKcF#{Wv_urP+e=0<>x|IOXL
zj5>zEN(gBC{~pk!t9V}Hw8>zl*er}8aEAzl4)}QSU?;mYOJFF4Ea$;{D`j449E3Bs
z4&s{w%Y@os7@EzA8LMUkhOl!omxVX%f-V9C30cVsmy87MrQ1$XUH9%~Vn(XOa3_~b
zR;iu;%OQCG_hX*@@b$(Ww(dPihSl!$e{YCwHHAICO{yup=fBAN&O5%>CV#QcI>Tx^
zone6SfzTPg{&6={uU&h%+D>~Ih`#UI!`|1sA$W~?#M`-Ec=bvHG^0J!_hb;WLYCB?
zHmdmMu+sH8+nX_%+MaE6)VqCa4*C|D9bEb8Pu@M=K^1>4ruVWJf4$OVvV2&DJ1OOB
z1O=9!@$ChbQ>w5I)*HKbfx^0Oys-!L*4t8RYT|>o`e1<StAl;)^}A8Ak0iTPv8Tqj
Pf9Y&2alcz=UEAgVAUYMn

literal 0
HcmV?d00001

diff --git a/lib/shflags b/lib/shflags
new file mode 100644
index 0000000..d09867e
--- /dev/null
+++ b/lib/shflags
@@ -0,0 +1,1011 @@
+# $Id: shflags 138 2010-03-18 00:25:34Z kate.ward@forestent.com $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# shFlags -- Advanced command-line flag library for Unix shell scripts.
+# http://code.google.com/p/shflags/
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# This module implements something like the google-gflags library available
+# from http://code.google.com/p/google-gflags/.
+#
+# FLAG TYPES: This is a list of the DEFINE_*'s that you can do.  All flags take
+# a name, default value, help-string, and optional 'short' name (one-letter
+# name).  Some flags have other arguments, which are described with the flag.
+#
+# DEFINE_string: takes any input, and intreprets it as a string.
+#
+# DEFINE_boolean: typically does not take any argument: say --myflag to set
+#   FLAGS_myflag to true, or --nomyflag to set FLAGS_myflag to false.
+#   Alternately, you can say
+#     --myflag=true  or --myflag=t or --myflag=0  or
+#     --myflag=false or --myflag=f or --myflag=1
+#   Passing an option has the same affect as passing the option once.
+#
+# DEFINE_float: takes an input and intreprets it as a floating point number. As
+#   shell does not support floats per-se, the input is merely validated as
+#   being a valid floating point value.
+#
+# DEFINE_integer: takes an input and intreprets it as an integer.
+#
+# SPECIAL FLAGS: There are a few flags that have special meaning:
+#   --help (or -?)  prints a list of all the flags in a human-readable fashion
+#   --flagfile=foo  read flags from foo.  (not implemented yet)
+#   --              as in getopt(), terminates flag-processing
+#
+# EXAMPLE USAGE:
+#
+#   -- begin hello.sh --
+#   #! /bin/sh
+#   . ./shflags
+#   DEFINE_string name 'world' "somebody's name" n
+#   FLAGS "$@" || exit $?
+#   eval set -- "${FLAGS_ARGV}"
+#   echo "Hello, ${FLAGS_name}."
+#   -- end hello.sh --
+#
+#   $ ./hello.sh -n Kate
+#   Hello, Kate.
+#
+# NOTE: Not all systems include a getopt version that supports long flags. On
+# these systems, only short flags are recognized.
+
+#==============================================================================
+# shFlags
+#
+# Shared attributes:
+#   flags_error: last error message
+#   flags_return: last return value
+#
+#   __flags_longNames: list of long names for all flags
+#   __flags_shortNames: list of short names for all flags
+#   __flags_boolNames: list of boolean flag names
+#
+#   __flags_opts: options parsed by getopt
+#
+# Per-flag attributes:
+#   FLAGS_<flag_name>: contains value of flag named 'flag_name'
+#   __flags_<flag_name>_default: the default flag value
+#   __flags_<flag_name>_help: the flag help string
+#   __flags_<flag_name>_short: the flag short name
+#   __flags_<flag_name>_type: the flag type
+#
+# Notes:
+# - lists of strings are space separated, and a null value is the '~' char.
+
+# return if FLAGS already loaded
+[ -n "${FLAGS_VERSION:-}" ] && return 0
+FLAGS_VERSION='1.0.4pre'
+
+# return values
+FLAGS_TRUE=0
+FLAGS_FALSE=1
+FLAGS_ERROR=2
+
+# reserved flag names
+FLAGS_RESERVED='ARGC ARGV ERROR FALSE HELP PARENT RESERVED TRUE VERSION'
+
+_flags_debug() { echo "flags:DEBUG $@" >&2; }
+_flags_warn() { echo "flags:WARN $@" >&2; }
+_flags_error() { echo "flags:ERROR $@" >&2; }
+_flags_fatal() { echo "flags:FATAL $@" >&2; }
+
+# specific shell checks
+if [ -n "${ZSH_VERSION:-}" ]; then
+  setopt |grep "^shwordsplit$" >/dev/null
+  if [ $? -ne ${FLAGS_TRUE} ]; then
+    _flags_fatal 'zsh shwordsplit option is required for proper zsh operation'
+    exit ${FLAGS_ERROR}
+  fi
+  if [ -z "${FLAGS_PARENT:-}" ]; then
+    _flags_fatal "zsh does not pass \$0 through properly. please declare' \
+\"FLAGS_PARENT=\$0\" before calling shFlags"
+    exit ${FLAGS_ERROR}
+  fi
+fi
+
+#
+# constants
+#
+
+# getopt version
+__FLAGS_GETOPT_VERS_STD=0
+__FLAGS_GETOPT_VERS_ENH=1
+__FLAGS_GETOPT_VERS_BSD=2
+
+getopt >/dev/null 2>&1
+case $? in
+  0) __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD} ;;  # bsd getopt
+  2)
+    # TODO(kward): look into '-T' option to test the internal getopt() version
+    if [ "`getopt --version`" = '-- ' ]; then
+      __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_STD}
+    else
+      __FLAGS_GETOPT_VERS=${__FLAGS_GETOPT_VERS_ENH}
+    fi
+    ;;
+  *)
+    _flags_fatal 'unable to determine getopt version'
+    exit ${FLAGS_ERROR}
+    ;;
+esac
+
+# getopt optstring lengths
+__FLAGS_OPTSTR_SHORT=0
+__FLAGS_OPTSTR_LONG=1
+
+__FLAGS_NULL='~'
+
+# flag info strings
+__FLAGS_INFO_DEFAULT='default'
+__FLAGS_INFO_HELP='help'
+__FLAGS_INFO_SHORT='short'
+__FLAGS_INFO_TYPE='type'
+
+# flag lengths
+__FLAGS_LEN_SHORT=0
+__FLAGS_LEN_LONG=1
+
+# flag types
+__FLAGS_TYPE_NONE=0
+__FLAGS_TYPE_BOOLEAN=1
+__FLAGS_TYPE_FLOAT=2
+__FLAGS_TYPE_INTEGER=3
+__FLAGS_TYPE_STRING=4
+
+# set the constants readonly
+__flags_constants=`set |awk -F= '/^FLAGS_/ || /^__FLAGS_/ {print $1}'`
+for __flags_const in ${__flags_constants}; do
+  # skip certain flags
+  case ${__flags_const} in
+    FLAGS_HELP) continue ;;
+    FLAGS_PARENT) continue ;;
+  esac
+  # set flag readonly
+  if [ -z "${ZSH_VERSION:-}" ]; then
+    readonly ${__flags_const}
+  else  # handle zsh
+    case ${ZSH_VERSION} in
+      [123].*) readonly ${__flags_const} ;;
+      *) readonly -g ${__flags_const} ;;  # declare readonly constants globally
+    esac
+  fi
+done
+unset __flags_const __flags_constants
+
+#
+# internal variables
+#
+
+__flags_boolNames=' '  # space separated list of boolean flag names
+__flags_longNames=' '  # space separated list of long flag names
+__flags_shortNames=' '  # space separated list of short flag names
+
+__flags_columns=''  # screen width in columns
+__flags_opts=''  # temporary storage for parsed getopt flags
+
+#------------------------------------------------------------------------------
+# private functions
+#
+
+# Define a flag.
+#
+# Calling this function will define the following info variables for the
+# specified flag:
+#   FLAGS_flagname - the name for this flag (based upon the long flag name)
+#   __flags_<flag_name>_default - the default value
+#   __flags_flagname_help - the help string
+#   __flags_flagname_short - the single letter alias
+#   __flags_flagname_type - the type of flag (one of __FLAGS_TYPE_*)
+#
+# Args:
+#   _flags__type: integer: internal type of flag (__FLAGS_TYPE_*)
+#   _flags__name: string: long flag name
+#   _flags__default: default flag value
+#   _flags__help: string: help string
+#   _flags__short: string: (optional) short flag name
+# Returns:
+#   integer: success of operation, or error
+_flags_define()
+{
+  if [ $# -lt 4 ]; then
+    flags_error='DEFINE error: too few arguments'
+    flags_return=${FLAGS_ERROR}
+    _flags_error "${flags_error}"
+    return ${flags_return}
+  fi
+
+  _flags_type_=$1
+  _flags_name_=$2
+  _flags_default_=$3
+  _flags_help_=$4
+  _flags_short_=${5:-${__FLAGS_NULL}}
+
+  _flags_return_=${FLAGS_TRUE}
+
+  # TODO(kward): check for validity of the flag name (e.g. dashes)
+
+  # check whether the flag name is reserved
+  echo " ${FLAGS_RESERVED} " |grep " ${_flags_name_} " >/dev/null
+  if [ $? -eq 0 ]; then
+    flags_error="flag name (${_flags_name_}) is reserved"
+    _flags_return_=${FLAGS_ERROR}
+  fi
+
+  # require short option for getopt that don't support long options
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
+      -a ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} \
+      -a "${_flags_short_}" = "${__FLAGS_NULL}" ]
+  then
+    flags_error="short flag required for (${_flags_name_}) on this platform"
+    _flags_return_=${FLAGS_ERROR}
+  fi
+
+  # check for existing long name definition
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+    if _flags_itemInList "${_flags_name_}" \
+        ${__flags_longNames} ${__flags_boolNames}
+    then
+      flags_error="flag name ([no]${_flags_name_}) already defined"
+      _flags_warn "${flags_error}"
+      _flags_return_=${FLAGS_FALSE}
+    fi
+  fi
+
+  # check for existing short name definition
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} \
+      -a "${_flags_short_}" != "${__FLAGS_NULL}" ]
+  then
+    if _flags_itemInList "${_flags_short_}" ${__flags_shortNames}; then
+      flags_error="flag short name (${_flags_short_}) already defined"
+      _flags_warn "${flags_error}"
+      _flags_return_=${FLAGS_FALSE}
+    fi
+  fi
+
+  # handle default value. note, on several occasions the 'if' portion of an
+  # if/then/else contains just a ':' which does nothing. a binary reversal via
+  # '!' is not done because it does not work on all shells.
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+    case ${_flags_type_} in
+      ${__FLAGS_TYPE_BOOLEAN})
+        if _flags_validateBoolean "${_flags_default_}"; then
+          case ${_flags_default_} in
+            true|t|0) _flags_default_=${FLAGS_TRUE} ;;
+            false|f|1) _flags_default_=${FLAGS_FALSE} ;;
+          esac
+        else
+          flags_error="invalid default flag value '${_flags_default_}'"
+          _flags_return_=${FLAGS_ERROR}
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_FLOAT})
+        if _flags_validateFloat "${_flags_default_}"; then
+          :
+        else
+          flags_error="invalid default flag value '${_flags_default_}'"
+          _flags_return_=${FLAGS_ERROR}
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_INTEGER})
+        if _flags_validateInteger "${_flags_default_}"; then
+          :
+        else
+          flags_error="invalid default flag value '${_flags_default_}'"
+          _flags_return_=${FLAGS_ERROR}
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_STRING}) ;;  # everything in shell is a valid string
+
+      *)
+        flags_error="unrecognized flag type '${_flags_type_}'"
+        _flags_return_=${FLAGS_ERROR}
+        ;;
+    esac
+  fi
+
+  if [ ${_flags_return_} -eq ${FLAGS_TRUE} ]; then
+    # store flag information
+    eval "FLAGS_${_flags_name_}='${_flags_default_}'"
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}=${_flags_type_}"
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}=\
+\"${_flags_default_}\""
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_HELP}=\"${_flags_help_}\""
+    eval "__flags_${_flags_name_}_${__FLAGS_INFO_SHORT}='${_flags_short_}'"
+
+    # append flag name(s) to list of names
+    __flags_longNames="${__flags_longNames}${_flags_name_} "
+    __flags_shortNames="${__flags_shortNames}${_flags_short_} "
+    [ ${_flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] && \
+        __flags_boolNames="${__flags_boolNames}no${_flags_name_} "
+  fi
+
+  flags_return=${_flags_return_}
+  unset _flags_default_ _flags_help_ _flags_name_ _flags_return_ _flags_short_ \
+      _flags_type_
+  [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
+  return ${flags_return}
+}
+
+# Return valid getopt options using currently defined list of long options.
+#
+# This function builds a proper getopt option string for short (and long)
+# options, using the current list of long options for reference.
+#
+# Args:
+#   _flags_optStr: integer: option string type (__FLAGS_OPTSTR_*)
+# Output:
+#   string: generated option string for getopt
+# Returns:
+#   boolean: success of operation (always returns True)
+_flags_genOptStr()
+{
+  _flags_optStrType_=$1
+
+  _flags_opts_=''
+
+  for _flags_flag_ in ${__flags_longNames}; do
+    _flags_type_=`_flags_getFlagInfo ${_flags_flag_} ${__FLAGS_INFO_TYPE}`
+    case ${_flags_optStrType_} in
+      ${__FLAGS_OPTSTR_SHORT})
+        _flags_shortName_=`_flags_getFlagInfo \
+            ${_flags_flag_} ${__FLAGS_INFO_SHORT}`
+        if [ "${_flags_shortName_}" != "${__FLAGS_NULL}" ]; then
+          _flags_opts_="${_flags_opts_}${_flags_shortName_}"
+          # getopt needs a trailing ':' to indicate a required argument
+          [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
+              _flags_opts_="${_flags_opts_}:"
+        fi
+        ;;
+
+      ${__FLAGS_OPTSTR_LONG})
+        _flags_opts_="${_flags_opts_:+${_flags_opts_},}${_flags_flag_}"
+        # getopt needs a trailing ':' to indicate a required argument
+        [ ${_flags_type_} -ne ${__FLAGS_TYPE_BOOLEAN} ] && \
+            _flags_opts_="${_flags_opts_}:"
+        ;;
+    esac
+  done
+
+  echo "${_flags_opts_}"
+  unset _flags_flag_ _flags_opts_ _flags_optStrType_ _flags_shortName_ \
+      _flags_type_
+  return ${FLAGS_TRUE}
+}
+
+# Returns flag details based on a flag name and flag info.
+#
+# Args:
+#   string: long flag name
+#   string: flag info (see the _flags_define function for valid info types)
+# Output:
+#   string: value of dereferenced flag variable
+# Returns:
+#   integer: one of FLAGS_{TRUE|FALSE|ERROR}
+_flags_getFlagInfo()
+{
+  _flags_name_=$1
+  _flags_info_=$2
+
+  _flags_nameVar_="__flags_${_flags_name_}_${_flags_info_}"
+  _flags_strToEval_="_flags_value_=\"\${${_flags_nameVar_}:-}\""
+  eval "${_flags_strToEval_}"
+  if [ -n "${_flags_value_}" ]; then
+    flags_return=${FLAGS_TRUE}
+  else
+    # see if the _flags_name_ variable is a string as strings can be empty...
+    # note: the DRY principle would say to have this function call itself for
+    # the next three lines, but doing so results in an infinite loop as an
+    # invalid _flags_name_ will also not have the associated _type variable.
+    # Because it doesn't (it will evaluate to an empty string) the logic will
+    # try to find the _type variable of the _type variable, and so on. Not so
+    # good ;-)
+    _flags_typeVar_="__flags_${_flags_name_}_${__FLAGS_INFO_TYPE}"
+    _flags_strToEval_="_flags_type_=\"\${${_flags_typeVar_}:-}\""
+    eval "${_flags_strToEval_}"
+    if [ "${_flags_type_}" = "${__FLAGS_TYPE_STRING}" ]; then
+      flags_return=${FLAGS_TRUE}
+    else
+      flags_return=${FLAGS_ERROR}
+      flags_error="invalid flag name (${_flags_nameVar_})"
+    fi
+  fi
+
+  echo "${_flags_value_}"
+  unset _flags_info_ _flags_name_ _flags_strToEval_ _flags_type_ _flags_value_ \
+      _flags_nameVar_ _flags_typeVar_
+  [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_error "${flags_error}"
+  return ${flags_return}
+}
+
+# check for presense of item in a list. passed a string (e.g. 'abc'), this
+# function will determine if the string is present in the list of strings (e.g.
+# ' foo bar abc ').
+#
+# Args:
+#   _flags__str: string: string to search for in a list of strings
+#   unnamed: list: list of strings
+# Returns:
+#   boolean: true if item is in the list
+_flags_itemInList()
+{
+  _flags_str_=$1
+  shift
+
+  echo " ${*:-} " |grep " ${_flags_str_} " >/dev/null
+  if [ $? -eq 0 ]; then
+    flags_return=${FLAGS_TRUE}
+  else
+    flags_return=${FLAGS_FALSE}
+  fi
+
+  unset _flags_str_
+  return ${flags_return}
+}
+
+# Returns the width of the current screen.
+#
+# Output:
+#   integer: width in columns of the current screen.
+_flags_columns()
+{
+  if [ -z "${__flags_columns}" ]; then
+    # determine the value and store it
+    if eval stty size >/dev/null 2>&1; then
+      # stty size worked :-)
+      set -- `stty size`
+      __flags_columns=$2
+    elif eval tput cols >/dev/null 2>&1; then
+      set -- `tput cols`
+      __flags_columns=$1
+    else
+      __flags_columns=80  # default terminal width
+    fi
+  fi
+  echo ${__flags_columns}
+}
+
+# Validate a boolean.
+#
+# Args:
+#   _flags__bool: boolean: value to validate
+# Returns:
+#   bool: true if the value is a valid boolean
+_flags_validateBoolean()
+{
+  _flags_bool_=$1
+
+  flags_return=${FLAGS_TRUE}
+  case "${_flags_bool_}" in
+    true|t|0) ;;
+    false|f|1) ;;
+    *) flags_return=${FLAGS_FALSE} ;;
+  esac
+
+  unset _flags_bool_
+  return ${flags_return}
+}
+
+# Validate a float.
+#
+# Args:
+#   _flags__float: float: value to validate
+# Returns:
+#   bool: true if the value is a valid float
+_flags_validateFloat()
+{
+  _flags_float_=$1
+
+  if _flags_validateInteger ${_flags_float_}; then
+    flags_return=${FLAGS_TRUE}
+  else
+    flags_return=${FLAGS_TRUE}
+    case ${_flags_float_} in
+      -*)  # negative floats
+        _flags_test_=`expr -- "${_flags_float_}" :\
+            '\(-[0-9][0-9]*\.[0-9][0-9]*\)'`
+        ;;
+      *)  # positive floats
+        _flags_test_=`expr -- "${_flags_float_}" :\
+            '\([0-9][0-9]*\.[0-9][0-9]*\)'`
+        ;;
+    esac
+    [ "${_flags_test_}" != "${_flags_float_}" ] && flags_return=${FLAGS_FALSE}
+  fi
+
+  unset _flags_float_ _flags_test_
+  return ${flags_return}
+}
+
+# Validate an integer.
+#
+# Args:
+#   _flags__integer: interger: value to validate
+# Returns:
+#   bool: true if the value is a valid integer
+_flags_validateInteger()
+{
+  _flags_int_=$1
+
+  flags_return=${FLAGS_TRUE}
+  case ${_flags_int_} in
+    -*)  # negative ints
+      _flags_test_=`expr -- "${_flags_int_}" : '\(-[0-9][0-9]*\)'`
+      ;;
+    *)  # positive ints
+      _flags_test_=`expr -- "${_flags_int_}" : '\([0-9][0-9]*\)'`
+      ;;
+  esac
+  [ "${_flags_test_}" != "${_flags_int_}" ] && flags_return=${FLAGS_FALSE}
+
+  unset _flags_int_ _flags_test_
+  return ${flags_return}
+}
+
+# Parse command-line options using the standard getopt.
+#
+# Note: the flag options are passed around in the global __flags_opts so that
+# the formatting is not lost due to shell parsing and such.
+#
+# Args:
+#   @: varies: command-line options to parse
+# Returns:
+#   integer: a FLAGS success condition
+_flags_getoptStandard()
+{
+  flags_return=${FLAGS_TRUE}
+  _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
+
+  # check for spaces in passed options
+  for _flags_opt_ in "$@"; do
+    # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
+    _flags_match_=`echo "x${_flags_opt_}x" |sed 's/ //g'`
+    if [ "${_flags_match_}" != "x${_flags_opt_}x" ]; then
+      flags_error='the available getopt does not support spaces in options'
+      flags_return=${FLAGS_ERROR}
+      break
+    fi
+  done
+
+  if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
+    __flags_opts=`getopt ${_flags_shortOpts_} $@ 2>&1`
+    _flags_rtrn_=$?
+    if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
+      _flags_warn "${__flags_opts}"
+      flags_error='unable to parse provided options with getopt.'
+      flags_return=${FLAGS_ERROR}
+    fi
+  fi
+
+  unset _flags_match_ _flags_opt_ _flags_rtrn_ _flags_shortOpts_
+  return ${flags_return}
+}
+
+# Parse command-line options using the enhanced getopt.
+#
+# Note: the flag options are passed around in the global __flags_opts so that
+# the formatting is not lost due to shell parsing and such.
+#
+# Args:
+#   @: varies: command-line options to parse
+# Returns:
+#   integer: a FLAGS success condition
+_flags_getoptEnhanced()
+{
+  flags_return=${FLAGS_TRUE}
+  _flags_shortOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_SHORT}`
+  _flags_boolOpts_=`echo "${__flags_boolNames}" \
+      |sed 's/^ *//;s/ *$//;s/ /,/g'`
+  _flags_longOpts_=`_flags_genOptStr ${__FLAGS_OPTSTR_LONG}`
+
+  __flags_opts=`getopt \
+      -o ${_flags_shortOpts_} \
+      -l "${_flags_longOpts_},${_flags_boolOpts_}" \
+      -- "$@" 2>&1`
+  _flags_rtrn_=$?
+  if [ ${_flags_rtrn_} -ne ${FLAGS_TRUE} ]; then
+    _flags_warn "${__flags_opts}"
+    flags_error='unable to parse provided options with getopt.'
+    flags_return=${FLAGS_ERROR}
+  fi
+
+  unset _flags_boolOpts_ _flags_longOpts_ _flags_rtrn_ _flags_shortOpts_
+  return ${flags_return}
+}
+
+# Dynamically parse a getopt result and set appropriate variables.
+#
+# This function does the actual conversion of getopt output and runs it through
+# the standard case structure for parsing. The case structure is actually quite
+# dynamic to support any number of flags.
+#
+# Args:
+#   argc: int: original command-line argument count
+#   @: varies: output from getopt parsing
+# Returns:
+#   integer: a FLAGS success condition
+_flags_parseGetopt()
+{
+  _flags_argc_=$1
+  shift
+
+  flags_return=${FLAGS_TRUE}
+
+  if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
+    set -- $@
+  else
+    # note the quotes around the `$@' -- they are essential!
+    eval set -- "$@"
+  fi
+
+  # provide user with number of arguments to shift by later
+  # NOTE: the FLAGS_ARGC variable is obsolete as of 1.0.3 because it does not
+  # properly give user access to non-flag arguments mixed in between flag
+  # arguments. Its usage was replaced by FLAGS_ARGV, and it is being kept only
+  # for backwards compatibility reasons.
+  FLAGS_ARGC=`expr $# - 1 - ${_flags_argc_}`
+
+  # handle options. note options with values must do an additional shift
+  while true; do
+    _flags_opt_=$1
+    _flags_arg_=${2:-}
+    _flags_type_=${__FLAGS_TYPE_NONE}
+    _flags_name_=''
+
+    # determine long flag name
+    case "${_flags_opt_}" in
+      --) shift; break ;;  # discontinue option parsing
+
+      --*)  # long option
+        _flags_opt_=`expr -- "${_flags_opt_}" : '--\(.*\)'`
+        _flags_len_=${__FLAGS_LEN_LONG}
+        if _flags_itemInList "${_flags_opt_}" ${__flags_longNames}; then
+          _flags_name_=${_flags_opt_}
+        else
+          # check for negated long boolean version
+          if _flags_itemInList "${_flags_opt_}" ${__flags_boolNames}; then
+            _flags_name_=`expr -- "${_flags_opt_}" : 'no\(.*\)'`
+            _flags_type_=${__FLAGS_TYPE_BOOLEAN}
+            _flags_arg_=${__FLAGS_NULL}
+          fi
+        fi
+        ;;
+
+      -*)  # short option
+        _flags_opt_=`expr -- "${_flags_opt_}" : '-\(.*\)'`
+        _flags_len_=${__FLAGS_LEN_SHORT}
+        if _flags_itemInList "${_flags_opt_}" ${__flags_shortNames}; then
+          # yes. match short name to long name. note purposeful off-by-one
+          # (too high) with awk calculations.
+          _flags_pos_=`echo "${__flags_shortNames}" \
+              |awk 'BEGIN{RS=" ";rn=0}$0==e{rn=NR}END{print rn}' \
+                  e=${_flags_opt_}`
+          _flags_name_=`echo "${__flags_longNames}" \
+              |awk 'BEGIN{RS=" "}rn==NR{print $0}' rn="${_flags_pos_}"`
+        fi
+        ;;
+    esac
+
+    # die if the flag was unrecognized
+    if [ -z "${_flags_name_}" ]; then
+      flags_error="unrecognized option (${_flags_opt_})"
+      flags_return=${FLAGS_ERROR}
+      break
+    fi
+
+    # set new flag value
+    [ ${_flags_type_} -eq ${__FLAGS_TYPE_NONE} ] && \
+        _flags_type_=`_flags_getFlagInfo \
+            "${_flags_name_}" ${__FLAGS_INFO_TYPE}`
+    case ${_flags_type_} in
+      ${__FLAGS_TYPE_BOOLEAN})
+        if [ ${_flags_len_} -eq ${__FLAGS_LEN_LONG} ]; then
+          if [ "${_flags_arg_}" != "${__FLAGS_NULL}" ]; then
+            eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
+          else
+            eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
+          fi
+        else
+          _flags_strToEval_="_flags_val_=\
+\${__flags_${_flags_name_}_${__FLAGS_INFO_DEFAULT}}"
+          eval "${_flags_strToEval_}"
+          if [ ${_flags_val_} -eq ${FLAGS_FALSE} ]; then
+            eval "FLAGS_${_flags_name_}=${FLAGS_TRUE}"
+          else
+            eval "FLAGS_${_flags_name_}=${FLAGS_FALSE}"
+          fi
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_FLOAT})
+        if _flags_validateFloat "${_flags_arg_}"; then
+          eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+        else
+          flags_error="invalid float value (${_flags_arg_})"
+          flags_return=${FLAGS_ERROR}
+          break
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_INTEGER})
+        if _flags_validateInteger "${_flags_arg_}"; then
+          eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+        else
+          flags_error="invalid integer value (${_flags_arg_})"
+          flags_return=${FLAGS_ERROR}
+          break
+        fi
+        ;;
+
+      ${__FLAGS_TYPE_STRING})
+        eval "FLAGS_${_flags_name_}='${_flags_arg_}'"
+        ;;
+    esac
+
+    # handle special case help flag
+    if [ "${_flags_name_}" = 'help' ]; then
+      if [ ${FLAGS_help} -eq ${FLAGS_TRUE} ]; then
+        flags_help
+        flags_error='help requested'
+        flags_return=${FLAGS_FALSE}
+        break
+      fi
+    fi
+
+    # shift the option and non-boolean arguements out.
+    shift
+    [ ${_flags_type_} != ${__FLAGS_TYPE_BOOLEAN} ] && shift
+  done
+
+  # give user back non-flag arguments
+  FLAGS_ARGV=''
+  while [ $# -gt 0 ]; do
+    FLAGS_ARGV="${FLAGS_ARGV:+${FLAGS_ARGV} }'$1'"
+    shift
+  done
+
+  unset _flags_arg_ _flags_len_ _flags_name_ _flags_opt_ _flags_pos_ \
+      _flags_strToEval_ _flags_type_ _flags_val_
+  return ${flags_return}
+}
+
+#------------------------------------------------------------------------------
+# public functions
+#
+
+# A basic boolean flag. Boolean flags do not take any arguments, and their
+# value is either 1 (false) or 0 (true). For long flags, the false value is
+# specified on the command line by prepending the word 'no'. With short flags,
+# the presense of the flag toggles the current value between true and false.
+# Specifying a short boolean flag twice on the command results in returning the
+# value back to the default value.
+#
+# A default value is required for boolean flags.
+#
+# For example, lets say a Boolean flag was created whose long name was 'update'
+# and whose short name was 'x', and the default value was 'false'. This flag
+# could be explicitly set to 'true' with '--update' or by '-x', and it could be
+# explicitly set to 'false' with '--noupdate'.
+DEFINE_boolean() { _flags_define ${__FLAGS_TYPE_BOOLEAN} "$@"; }
+
+# Other basic flags.
+DEFINE_float()   { _flags_define ${__FLAGS_TYPE_FLOAT} "$@"; }
+DEFINE_integer() { _flags_define ${__FLAGS_TYPE_INTEGER} "$@"; }
+DEFINE_string()  { _flags_define ${__FLAGS_TYPE_STRING} "$@"; }
+
+# Parse the flags.
+#
+# Args:
+#   unnamed: list: command-line flags to parse
+# Returns:
+#   integer: success of operation, or error
+FLAGS()
+{
+  # define a standard 'help' flag if one isn't already defined
+  [ -z "${__flags_help_type:-}" ] && \
+      DEFINE_boolean 'help' false 'show this help' 'h'
+
+  # parse options
+  if [ $# -gt 0 ]; then
+    if [ ${__FLAGS_GETOPT_VERS} -ne ${__FLAGS_GETOPT_VERS_ENH} ]; then
+      _flags_getoptStandard "$@"
+    else
+      _flags_getoptEnhanced "$@"
+    fi
+    flags_return=$?
+  else
+    # nothing passed; won't bother running getopt
+    __flags_opts='--'
+    flags_return=${FLAGS_TRUE}
+  fi
+
+  if [ ${flags_return} -eq ${FLAGS_TRUE} ]; then
+    _flags_parseGetopt $# "${__flags_opts}"
+    flags_return=$?
+  fi
+
+  [ ${flags_return} -eq ${FLAGS_ERROR} ] && _flags_fatal "${flags_error}"
+  return ${flags_return}
+}
+
+# This is a helper function for determining the `getopt` version for platforms
+# where the detection isn't working. It simply outputs debug information that
+# can be included in a bug report.
+#
+# Args:
+#   none
+# Output:
+#   debug info that can be included in a bug report
+# Returns:
+#   nothing
+flags_getoptInfo()
+{
+  # platform info
+  _flags_debug "uname -a: `uname -a`"
+  _flags_debug "PATH: ${PATH}"
+
+  # shell info
+  if [ -n "${BASH_VERSION:-}" ]; then
+    _flags_debug 'shell: bash'
+    _flags_debug "BASH_VERSION: ${BASH_VERSION}"
+  elif [ -n "${ZSH_VERSION:-}" ]; then
+    _flags_debug 'shell: zsh'
+    _flags_debug "ZSH_VERSION: ${ZSH_VERSION}"
+  fi
+
+  # getopt info
+  getopt >/dev/null
+  _flags_getoptReturn=$?
+  _flags_debug "getopt return: ${_flags_getoptReturn}"
+  _flags_debug "getopt --version: `getopt --version 2>&1`"
+
+  unset _flags_getoptReturn
+}
+
+# Returns whether the detected getopt version is the enhanced version.
+#
+# Args:
+#   none
+# Output:
+#   none
+# Returns:
+#   bool: true if getopt is the enhanced version
+flags_getoptIsEnh()
+{
+  test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH}
+}
+
+# Returns whether the detected getopt version is the standard version.
+#
+# Args:
+#   none
+# Returns:
+#   bool: true if getopt is the standard version
+flags_getoptIsStd()
+{
+  test ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD}
+}
+
+# This is effectively a 'usage()' function. It prints usage information and
+# exits the program with ${FLAGS_FALSE} if it is ever found in the command line
+# arguments. Note this function can be overridden so other apps can define
+# their own --help flag, replacing this one, if they want.
+#
+# Args:
+#   none
+# Returns:
+#   integer: success of operation (always returns true)
+flags_help()
+{
+  if [ -n "${FLAGS_HELP:-}" ]; then
+    echo "${FLAGS_HELP}" >&2
+  else
+    echo "USAGE: ${FLAGS_PARENT:-$0} [flags] args" >&2
+  fi
+  if [ -n "${__flags_longNames}" ]; then
+    echo 'flags:' >&2
+    for flags_name_ in ${__flags_longNames}; do
+      flags_flagStr_=''
+      flags_boolStr_=''
+
+      flags_default_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_DEFAULT}`
+      flags_help_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_HELP}`
+      flags_short_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_SHORT}`
+      flags_type_=`_flags_getFlagInfo \
+          "${flags_name_}" ${__FLAGS_INFO_TYPE}`
+
+      [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
+          && flags_flagStr_="-${flags_short_}"
+
+      if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_ENH} ]; then
+        [ "${flags_short_}" != "${__FLAGS_NULL}" ] \
+            && flags_flagStr_="${flags_flagStr_},"
+        [ ${flags_type_} -eq ${__FLAGS_TYPE_BOOLEAN} ] \
+            && flags_boolStr_='[no]'
+        flags_flagStr_="${flags_flagStr_}--${flags_boolStr_}${flags_name_}:"
+      fi
+
+      case ${flags_type_} in
+        ${__FLAGS_TYPE_BOOLEAN})
+          if [ ${flags_default_} -eq ${FLAGS_TRUE} ]; then
+            flags_defaultStr_='true'
+          else
+            flags_defaultStr_='false'
+          fi
+          ;;
+        ${__FLAGS_TYPE_FLOAT}|${__FLAGS_TYPE_INTEGER})
+          flags_defaultStr_=${flags_default_} ;;
+        ${__FLAGS_TYPE_STRING}) flags_defaultStr_="'${flags_default_}'" ;;
+      esac
+      flags_defaultStr_="(default: ${flags_defaultStr_})"
+
+      flags_helpStr_="  ${flags_flagStr_}  ${flags_help_} ${flags_defaultStr_}"
+      flags_helpStrLen_=`expr -- "${flags_helpStr_}" : '.*'`
+      flags_columns_=`_flags_columns`
+      if [ ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
+        echo "${flags_helpStr_}" >&2
+      else
+        echo "  ${flags_flagStr_}  ${flags_help_}" >&2
+        # note: the silliness with the x's is purely for ksh93 on Ubuntu 6.06
+        # because it doesn't like empty strings when used in this manner.
+        flags_emptyStr_="`echo \"x${flags_flagStr_}x\" \
+            |awk '{printf "%"length($0)-2"s", ""}'`"
+        flags_helpStr_="  ${flags_emptyStr_}  ${flags_defaultStr_}"
+        flags_helpStrLen_=`expr -- "${flags_helpStr_}" : '.*'`
+        if [ ${__FLAGS_GETOPT_VERS} -eq ${__FLAGS_GETOPT_VERS_STD} \
+            -o ${flags_helpStrLen_} -lt ${flags_columns_} ]; then
+          # indented to match help string
+          echo "${flags_helpStr_}" >&2
+        else
+          # indented four from left to allow for longer defaults as long flag
+          # names might be used too, making things too long
+          echo "    ${flags_defaultStr_}" >&2
+        fi
+      fi
+    done
+  fi
+
+  unset flags_boolStr_ flags_default_ flags_defaultStr_ flags_emptyStr_ \
+      flags_flagStr_ flags_help_ flags_helpStr flags_helpStrLen flags_name_ \
+      flags_columns_ flags_short_ flags_type_
+  return ${FLAGS_TRUE}
+}
+
+# Reset shflags back to an uninitialized state.
+#
+# Args:
+#   none
+# Returns:
+#   nothing
+flags_reset()
+{
+  for flags_name_ in ${__flags_longNames}; do
+    flags_strToEval_="unset FLAGS_${flags_name_}"
+    for flags_type_ in \
+        ${__FLAGS_INFO_DEFAULT} \
+        ${__FLAGS_INFO_HELP} \
+        ${__FLAGS_INFO_SHORT} \
+        ${__FLAGS_INFO_TYPE}
+    do
+      flags_strToEval_=\
+"${flags_strToEval_} __flags_${flags_name_}_${flags_type_}"
+    done
+    eval ${flags_strToEval_}
+  done
+
+  # reset internal variables
+  __flags_boolNames=' '
+  __flags_longNames=' '
+  __flags_shortNames=' '
+
+  unset flags_name_ flags_type_ flags_strToEval_
+}
diff --git a/lib/shlib b/lib/shlib
new file mode 100644
index 0000000..d294636
--- /dev/null
+++ b/lib/shlib
@@ -0,0 +1,40 @@
+# $Id: shlib 14 2007-02-18 19:43:41Z sfsetse $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2011 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License).
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# Library of shell functions.
+
+# Convert a relative path into it's absolute equivalent.
+#
+# This function will automatically prepend the current working directory if the
+# path is not already absolute. It then removes all parent references (../) to
+# reconstruct the proper absolute path.
+#
+# Args:
+#   shlib_path_: string: relative path
+# Outputs:
+#   string: absolute path
+shlib_relToAbsPath()
+{
+  shlib_path_=$1
+
+  # prepend current directory to relative paths
+  echo "${shlib_path_}" |grep '^/' >/dev/null 2>&1 \
+      || shlib_path_="`pwd`/${shlib_path_}"
+
+  # clean up the path. if all seds supported true regular expressions, then
+  # this is what it would be:
+  shlib_old_=${shlib_path_}
+  while true; do
+    shlib_new_=`echo "${shlib_old_}" |sed 's/[^/]*\/\.\.\/*//g;s/\/\.\//\//'`
+    [ "${shlib_old_}" = "${shlib_new_}" ] && break
+    shlib_old_=${shlib_new_}
+  done
+  echo "${shlib_new_}"
+
+  unset shlib_path_ shlib_old_ shlib_new_
+}
diff --git a/lib/shunit2 b/lib/shunit2
new file mode 100644
index 0000000..590a5a8
--- /dev/null
+++ b/lib/shunit2
@@ -0,0 +1,1048 @@
+#! /bin/sh
+# $Id: shunit2 322 2011-04-24 00:09:45Z kate.ward@forestent.com $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# shUnit2 -- Unit testing framework for Unix shell scripts.
+# http://code.google.com/p/shunit2/
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# shUnit2 is a xUnit based unit test framework for Bourne shell scripts. It is
+# based on the popular JUnit unit testing framework for Java.
+
+# return if shunit already loaded
+[ -n "${SHUNIT_VERSION:-}" ] && exit 0
+
+SHUNIT_VERSION='2.1.6'
+
+SHUNIT_TRUE=0
+SHUNIT_FALSE=1
+SHUNIT_ERROR=2
+
+# enable strict mode by default
+SHUNIT_STRICT=${SHUNIT_STRICT:-${SHUNIT_TRUE}}
+
+_shunit_warn() { echo "shunit2:WARN $@" >&2; }
+_shunit_error() { echo "shunit2:ERROR $@" >&2; }
+_shunit_fatal() { echo "shunit2:FATAL $@" >&2; exit ${SHUNIT_ERROR}; }
+
+# specific shell checks
+if [ -n "${ZSH_VERSION:-}" ]; then
+  setopt |grep "^shwordsplit$" >/dev/null
+  if [ $? -ne ${SHUNIT_TRUE} ]; then
+    _shunit_fatal 'zsh shwordsplit option is required for proper operation'
+  fi
+  if [ -z "${SHUNIT_PARENT:-}" ]; then
+    _shunit_fatal "zsh does not pass \$0 through properly. please declare \
+\"SHUNIT_PARENT=\$0\" before calling shUnit2"
+  fi
+fi
+
+#
+# constants
+#
+
+__SHUNIT_ASSERT_MSG_PREFIX='ASSERT:'
+__SHUNIT_MODE_SOURCED='sourced'
+__SHUNIT_MODE_STANDALONE='standalone'
+__SHUNIT_PARENT=${SHUNIT_PARENT:-$0}
+
+# set the constants readonly
+shunit_constants_=`set |grep '^__SHUNIT_' |cut -d= -f1`
+echo "${shunit_constants_}" |grep '^Binary file' >/dev/null && \
+    shunit_constants_=`set |grep -a '^__SHUNIT_' |cut -d= -f1`
+for shunit_constant_ in ${shunit_constants_}; do
+  shunit_ro_opts_=''
+  case ${ZSH_VERSION:-} in
+    '') ;;  # this isn't zsh
+    [123].*) ;;  # early versions (1.x, 2.x, 3.x)
+    *) shunit_ro_opts_='-g' ;;  # all later versions. declare readonly globally
+  esac
+  readonly ${shunit_ro_opts_} ${shunit_constant_}
+done
+unset shunit_constant_ shunit_constants_ shunit_ro_opts_
+
+# variables
+__shunit_lineno=''  # line number of executed test
+__shunit_mode=${__SHUNIT_MODE_SOURCED}  # operating mode
+__shunit_reportGenerated=${SHUNIT_FALSE}  # is report generated
+__shunit_script=''  # filename of unittest script (standalone mode)
+__shunit_skip=${SHUNIT_FALSE}  # is skipping enabled
+__shunit_suite=''  # suite of tests to execute
+
+# counts of tests
+__shunit_testSuccess=${SHUNIT_TRUE}
+__shunit_testsTotal=0
+__shunit_testsPassed=0
+__shunit_testsFailed=0
+
+# counts of asserts
+__shunit_assertsTotal=0
+__shunit_assertsPassed=0
+__shunit_assertsFailed=0
+__shunit_assertsSkipped=0
+
+# macros
+_SHUNIT_LINENO_='eval __shunit_lineno=""; if [ "${1:-}" = "--lineno" ]; then [ -n "$2" ] && __shunit_lineno="[$2] "; shift 2; fi'
+
+#-----------------------------------------------------------------------------
+# assert functions
+#
+
+# Assert that two values are equal to one another.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertEquals()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertEquals() requires two or three arguments; $# given"
+    _shunit_error "1: ${1:+$1} 2: ${2:+$2} 3: ${3:+$3}"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_expected_=$1
+  shunit_actual_=$2
+
+  shunit_return=${SHUNIT_TRUE}
+  if [ "${shunit_expected_}" = "${shunit_actual_}" ]; then
+    _shunit_assertPass
+  else
+    failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}"
+    shunit_return=${SHUNIT_FALSE}
+  fi
+
+  unset shunit_message_ shunit_expected_ shunit_actual_
+  return ${shunit_return}
+}
+_ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"'
+
+# Assert that two values are not equal to one another.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNotEquals()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertNotEquals() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_expected_=$1
+  shunit_actual_=$2
+
+  shunit_return=${SHUNIT_TRUE}
+  if [ "${shunit_expected_}" != "${shunit_actual_}" ]; then
+    _shunit_assertPass
+  else
+    failSame "${shunit_message_}" "$@"
+    shunit_return=${SHUNIT_FALSE}
+  fi
+
+  unset shunit_message_ shunit_expected_ shunit_actual_
+  return ${shunit_return}
+}
+_ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"'
+
+# Assert that a value is null (i.e. an empty string)
+#
+# Args:
+#   message: string: failure message [optional]
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNull()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 1 -o $# -gt 2 ]; then
+    _shunit_error "assertNull() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  assertTrue "${shunit_message_}" "[ -z '$1' ]"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"'
+
+# Assert that a value is not null (i.e. a non-empty string)
+#
+# Args:
+#   message: string: failure message [optional]
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNotNull()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -gt 2 ]; then  # allowing 0 arguments as $1 might actually be null
+    _shunit_error "assertNotNull() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_actual_=`_shunit_escapeCharactersInString "${1:-}"`
+  test -n "${shunit_actual_}"
+  assertTrue "${shunit_message_}" $?
+  shunit_return=$?
+
+  unset shunit_actual_ shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"'
+
+# Assert that two values are the same (i.e. equal to one another).
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertSame() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  assertEquals "${shunit_message_}" "$1" "$2"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"'
+
+# Assert that two values are not the same (i.e. not equal to one another).
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertNotSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "assertNotSame() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_:-}$1"
+    shift
+  fi
+  assertNotEquals "${shunit_message_}" "$1" "$2"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"'
+
+# Assert that a value or shell test condition is true.
+#
+# In shell, a value of 0 is true and a non-zero value is false. Any integer
+# value passed can thereby be tested.
+#
+# Shell supports much more complicated tests though, and a means to support
+# them was needed. As such, this function tests that conditions are true or
+# false through evaluation rather than just looking for a true or false.
+#
+# The following test will succeed:
+#   assertTrue 0
+#   assertTrue "[ 34 -gt 23 ]"
+# The folloing test will fail with a message:
+#   assertTrue 123
+#   assertTrue "test failed" "[ -r '/non/existant/file' ]"
+#
+# Args:
+#   message: string: failure message [optional]
+#   condition: string: integer value or shell conditional statement
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertTrue()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -gt 2 ]; then
+    _shunit_error "assertTrue() takes one two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_condition_=$1
+
+  # see if condition is an integer, i.e. a return value
+  shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
+  shunit_return=${SHUNIT_TRUE}
+  if [ -z "${shunit_condition_}" ]; then
+    # null condition
+    shunit_return=${SHUNIT_FALSE}
+  elif [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]
+  then
+    # possible return value. treating 0 as true, and non-zero as false.
+    [ ${shunit_condition_} -ne 0 ] && shunit_return=${SHUNIT_FALSE}
+  else
+    # (hopefully) a condition
+    ( eval ${shunit_condition_} ) >/dev/null 2>&1
+    [ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE}
+  fi
+
+  # record the test
+  if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
+    _shunit_assertPass
+  else
+    _shunit_assertFail "${shunit_message_}"
+  fi
+
+  unset shunit_message_ shunit_condition_ shunit_match_
+  return ${shunit_return}
+}
+_ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"'
+
+# Assert that a value or shell test condition is false.
+#
+# In shell, a value of 0 is true and a non-zero value is false. Any integer
+# value passed can thereby be tested.
+#
+# Shell supports much more complicated tests though, and a means to support
+# them was needed. As such, this function tests that conditions are true or
+# false through evaluation rather than just looking for a true or false.
+#
+# The following test will succeed:
+#   assertFalse 1
+#   assertFalse "[ 'apples' = 'oranges' ]"
+# The folloing test will fail with a message:
+#   assertFalse 0
+#   assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]"
+#
+# Args:
+#   message: string: failure message [optional]
+#   condition: string: integer value or shell conditional statement
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+assertFalse()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 1 -o $# -gt 2 ]; then
+    _shunit_error "assertFalse() quires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 2 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_condition_=$1
+
+  # see if condition is an integer, i.e. a return value
+  shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'`
+  shunit_return=${SHUNIT_TRUE}
+  if [ -z "${shunit_condition_}" ]; then
+    # null condition
+    shunit_return=${SHUNIT_FALSE}
+  elif [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ]
+  then
+    # possible return value. treating 0 as true, and non-zero as false.
+    [ ${shunit_condition_} -eq 0 ] && shunit_return=${SHUNIT_FALSE}
+  else
+    # (hopefully) a condition
+    ( eval ${shunit_condition_} ) >/dev/null 2>&1
+    [ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE}
+  fi
+
+  # record the test
+  if [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then
+    _shunit_assertPass
+  else
+    _shunit_assertFail "${shunit_message_}"
+  fi
+
+  unset shunit_message_ shunit_condition_ shunit_match_
+  return ${shunit_return}
+}
+_ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"'
+
+#-----------------------------------------------------------------------------
+# failure functions
+#
+
+# Records a test failure.
+#
+# Args:
+#   message: string: failure message [optional]
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+fail()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -gt 1 ]; then
+    _shunit_error "fail() requires zero or one arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 1 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+
+  _shunit_assertFail "${shunit_message_}"
+
+  unset shunit_message_
+  return ${SHUNIT_FALSE}
+}
+_FAIL_='eval fail --lineno "${LINENO:-}"'
+
+# Records a test failure, stating two values were not equal.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+failNotEquals()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "failNotEquals() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  shunit_expected_=$1
+  shunit_actual_=$2
+
+  _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected:<${shunit_expected_}> but was:<${shunit_actual_}>"
+
+  unset shunit_message_ shunit_expected_ shunit_actual_
+  return ${SHUNIT_FALSE}
+}
+_FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"'
+
+# Records a test failure, stating two values should have been the same.
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+failSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "failSame() requires two or three arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+
+  _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected not same"
+
+  unset shunit_message_
+  return ${SHUNIT_FALSE}
+}
+_FAIL_SAME_='eval failSame --lineno "${LINENO:-}"'
+
+# Records a test failure, stating two values were not equal.
+#
+# This is functionally equivalent to calling failNotEquals().
+#
+# Args:
+#   message: string: failure message [optional]
+#   expected: string: expected value
+#   actual: string: actual value
+# Returns:
+#   integer: success (TRUE/FALSE/ERROR constant)
+failNotSame()
+{
+  ${_SHUNIT_LINENO_}
+  if [ $# -lt 2 -o $# -gt 3 ]; then
+    _shunit_error "failNotEquals() requires one or two arguments; $# given"
+    return ${SHUNIT_ERROR}
+  fi
+  _shunit_shouldSkip && return ${SHUNIT_TRUE}
+
+  shunit_message_=${__shunit_lineno}
+  if [ $# -eq 3 ]; then
+    shunit_message_="${shunit_message_}$1"
+    shift
+  fi
+  failNotEquals "${shunit_message_}" "$1" "$2"
+  shunit_return=$?
+
+  unset shunit_message_
+  return ${shunit_return}
+}
+_FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"'
+
+#-----------------------------------------------------------------------------
+# skipping functions
+#
+
+# Force remaining assert and fail functions to be "skipped".
+#
+# This function forces the remaining assert and fail functions to be "skipped",
+# i.e. they will have no effect. Each function skipped will be recorded so that
+# the total of asserts and fails will not be altered.
+#
+# Args:
+#   None
+startSkipping()
+{
+  __shunit_skip=${SHUNIT_TRUE}
+}
+
+# Resume the normal recording behavior of assert and fail calls.
+#
+# Args:
+#   None
+endSkipping()
+{
+  __shunit_skip=${SHUNIT_FALSE}
+}
+
+# Returns the state of assert and fail call skipping.
+#
+# Args:
+#   None
+# Returns:
+#   boolean: (TRUE/FALSE constant)
+isSkipping()
+{
+  return ${__shunit_skip}
+}
+
+#-----------------------------------------------------------------------------
+# suite functions
+#
+
+# Stub. This function should contains all unit test calls to be made.
+#
+# DEPRECATED (as of 2.1.0)
+#
+# This function can be optionally overridden by the user in their test suite.
+#
+# If this function exists, it will be called when shunit2 is sourced. If it
+# does not exist, shunit2 will search the parent script for all functions
+# beginning with the word 'test', and they will be added dynamically to the
+# test suite.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#suite() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+# Adds a function name to the list of tests schedule for execution.
+#
+# This function should only be called from within the suite() function.
+#
+# Args:
+#   function: string: name of a function to add to current unit test suite
+suite_addTest()
+{
+  shunit_func_=${1:-}
+
+  __shunit_suite="${__shunit_suite:+${__shunit_suite} }${shunit_func_}"
+  __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
+
+  unset shunit_func_
+}
+
+# Stub. This function will be called once before any tests are run.
+#
+# Common one-time environment preparation tasks shared by all tests can be
+# defined here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#oneTimeSetUp() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+# Stub. This function will be called once after all tests are finished.
+#
+# Common one-time environment cleanup tasks shared by all tests can be defined
+# here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#oneTimeTearDown() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+# Stub. This function will be called before each test is run.
+#
+# Common environment preparation tasks shared by all tests can be defined here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#setUp() { :; }
+
+# Note: see _shunit_mktempFunc() for actual implementation
+# Stub. This function will be called after each test is run.
+#
+# Common environment cleanup tasks shared by all tests can be defined here.
+#
+# This function should be overridden by the user in their unit test suite.
+# Note: see _shunit_mktempFunc() for actual implementation
+#
+# Args:
+#   None
+#tearDown() { :; }  # DO NOT UNCOMMENT THIS FUNCTION
+
+#------------------------------------------------------------------------------
+# internal shUnit2 functions
+#
+
+# Create a temporary directory to store various run-time files in.
+#
+# This function is a cross-platform temporary directory creation tool. Not all
+# OSes have the mktemp function, so one is included here.
+#
+# Args:
+#   None
+# Outputs:
+#   string: the temporary directory that was created
+_shunit_mktempDir()
+{
+  # try the standard mktemp function
+  ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return
+
+  # the standard mktemp didn't work.  doing our own.
+  if [ -r '/dev/urandom' -a -x '/usr/bin/od' ]; then
+    _shunit_random_=`/usr/bin/od -vAn -N4 -tx4 </dev/urandom \
+        |sed 's/^[^0-9a-f]*//'`
+  elif [ -n "${RANDOM:-}" ]; then
+    # $RANDOM works
+    _shunit_random_=${RANDOM}${RANDOM}${RANDOM}$$
+  else
+    # $RANDOM doesn't work
+    _shunit_date_=`date '+%Y%m%d%H%M%S'`
+    _shunit_random_=`expr ${_shunit_date_} / $$`
+  fi
+
+  _shunit_tmpDir_="${TMPDIR:-/tmp}/shunit.${_shunit_random_}"
+  ( umask 077 && mkdir "${_shunit_tmpDir_}" ) || \
+      _shunit_fatal 'could not create temporary directory! exiting'
+
+  echo ${_shunit_tmpDir_}
+  unset _shunit_date_ _shunit_random_ _shunit_tmpDir_
+}
+
+# This function is here to work around issues in Cygwin.
+#
+# Args:
+#   None
+_shunit_mktempFunc()
+{
+  for _shunit_func_ in oneTimeSetUp oneTimeTearDown setUp tearDown suite noexec
+  do
+    _shunit_file_="${__shunit_tmpDir}/${_shunit_func_}"
+    cat <<EOF >"${_shunit_file_}"
+#! /bin/sh
+exit ${SHUNIT_TRUE}
+EOF
+    chmod +x "${_shunit_file_}"
+  done
+
+  unset _shunit_file_
+}
+
+# Final cleanup function to leave things as we found them.
+#
+# Besides removing the temporary directory, this function is in charge of the
+# final exit code of the unit test. The exit code is based on how the script
+# was ended (e.g. normal exit, or via Ctrl-C).
+#
+# Args:
+#   name: string: name of the trap called (specified when trap defined)
+_shunit_cleanup()
+{
+  _shunit_name_=$1
+
+  case ${_shunit_name_} in
+    EXIT) _shunit_signal_=0 ;;
+    INT) _shunit_signal_=2 ;;
+    TERM) _shunit_signal_=15 ;;
+    *)
+      _shunit_warn "unrecognized trap value (${_shunit_name_})"
+      _shunit_signal_=0
+      ;;
+  esac
+
+  # do our work
+  rm -fr "${__shunit_tmpDir}"
+
+  # exit for all non-EXIT signals
+  if [ ${_shunit_name_} != 'EXIT' ]; then
+    _shunit_warn "trapped and now handling the (${_shunit_name_}) signal"
+    # disable EXIT trap
+    trap 0
+    # add 128 to signal and exit
+    exit `expr ${_shunit_signal_} + 128`
+  elif [ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ] ; then
+    _shunit_assertFail 'Unknown failure encountered running a test'
+    _shunit_generateReport
+    exit ${SHUNIT_ERROR}
+  fi
+
+  unset _shunit_name_ _shunit_signal_
+}
+
+# The actual running of the tests happens here.
+#
+# Args:
+#   None
+_shunit_execSuite()
+{
+  for _shunit_test_ in ${__shunit_suite}; do
+    __shunit_testSuccess=${SHUNIT_TRUE}
+
+    # disable skipping
+    endSkipping
+
+    # execute the per-test setup function
+    setUp
+
+    # execute the test
+    echo "${_shunit_test_}"
+    eval ${_shunit_test_}
+
+    # execute the per-test tear-down function
+    tearDown
+
+    # update stats
+    if [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then
+      __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1`
+    else
+      __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1`
+    fi
+  done
+
+  unset _shunit_test_
+}
+
+# Generates the user friendly report with appropriate OK/FAILED message.
+#
+# Args:
+#   None
+# Output:
+#   string: the report of successful and failed tests, as well as totals.
+_shunit_generateReport()
+{
+  _shunit_ok_=${SHUNIT_TRUE}
+
+  # if no exit code was provided one, determine an appropriate one
+  [ ${__shunit_testsFailed} -gt 0 \
+      -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ] \
+          && _shunit_ok_=${SHUNIT_FALSE}
+
+  echo
+  if [ ${__shunit_testsTotal} -eq 1 ]; then
+    echo "Ran ${__shunit_testsTotal} test."
+  else
+    echo "Ran ${__shunit_testsTotal} tests."
+  fi
+
+  _shunit_failures_=''
+  _shunit_skipped_=''
+  [ ${__shunit_assertsFailed} -gt 0 ] \
+      && _shunit_failures_="failures=${__shunit_assertsFailed}"
+  [ ${__shunit_assertsSkipped} -gt 0 ] \
+      && _shunit_skipped_="skipped=${__shunit_assertsSkipped}"
+
+  if [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then
+    _shunit_msg_='OK'
+    [ -n "${_shunit_skipped_}" ] \
+        && _shunit_msg_="${_shunit_msg_} (${_shunit_skipped_})"
+  else
+    _shunit_msg_="FAILED (${_shunit_failures_}"
+    [ -n "${_shunit_skipped_}" ] \
+        && _shunit_msg_="${_shunit_msg_},${_shunit_skipped_}"
+    _shunit_msg_="${_shunit_msg_})"
+  fi
+
+  echo
+  echo ${_shunit_msg_}
+  __shunit_reportGenerated=${SHUNIT_TRUE}
+
+  unset _shunit_failures_ _shunit_msg_ _shunit_ok_ _shunit_skipped_
+}
+
+# Test for whether a function should be skipped.
+#
+# Args:
+#   None
+# Returns:
+#   boolean: whether the test should be skipped (TRUE/FALSE constant)
+_shunit_shouldSkip()
+{
+  [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE}
+  _shunit_assertSkip
+}
+
+# Records a successful test.
+#
+# Args:
+#   None
+_shunit_assertPass()
+{
+  __shunit_assertsPassed=`expr ${__shunit_assertsPassed} + 1`
+  __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
+}
+
+# Records a test failure.
+#
+# Args:
+#   message: string: failure message to provide user
+_shunit_assertFail()
+{
+  _shunit_msg_=$1
+
+  __shunit_testSuccess=${SHUNIT_FALSE}
+  __shunit_assertsFailed=`expr ${__shunit_assertsFailed} + 1`
+  __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
+  echo "${__SHUNIT_ASSERT_MSG_PREFIX}${_shunit_msg_}"
+
+  unset _shunit_msg_
+}
+
+# Records a skipped test.
+#
+# Args:
+#   None
+_shunit_assertSkip()
+{
+  __shunit_assertsSkipped=`expr ${__shunit_assertsSkipped} + 1`
+  __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1`
+}
+
+# Prepare a script filename for sourcing.
+#
+# Args:
+#   script: string: path to a script to source
+# Returns:
+#   string: filename prefixed with ./ (if necessary)
+_shunit_prepForSourcing()
+{
+  _shunit_script_=$1
+  case "${_shunit_script_}" in
+    /*|./*) echo "${_shunit_script_}" ;;
+    *) echo "./${_shunit_script_}" ;;
+  esac
+  unset _shunit_script_
+}
+
+# Escape a character in a string.
+#
+# Args:
+#   c: string: unescaped character
+#   s: string: to escape character in
+# Returns:
+#   string: with escaped character(s)
+_shunit_escapeCharInStr()
+{
+  [ -n "$2" ] || return  # no point in doing work on an empty string
+
+  # Note: using shorter variable names to prevent conflicts with
+  # _shunit_escapeCharactersInString().
+  _shunit_c_=$1
+  _shunit_s_=$2
+
+
+  # escape the character
+  echo ''${_shunit_s_}'' |sed 's/\'${_shunit_c_}'/\\\'${_shunit_c_}'/g'
+
+  unset _shunit_c_ _shunit_s_
+}
+
+# Escape a character in a string.
+#
+# Args:
+#   str: string: to escape characters in
+# Returns:
+#   string: with escaped character(s)
+_shunit_escapeCharactersInString()
+{
+  [ -n "$1" ] || return  # no point in doing work on an empty string
+
+  _shunit_str_=$1
+
+  # Note: using longer variable names to prevent conflicts with
+  # _shunit_escapeCharInStr().
+  for _shunit_char_ in '"' '$' "'" '`'; do
+    _shunit_str_=`_shunit_escapeCharInStr "${_shunit_char_}" "${_shunit_str_}"`
+  done
+
+  echo "${_shunit_str_}"
+  unset _shunit_char_ _shunit_str_
+}
+
+# Extract list of functions to run tests against.
+#
+# Args:
+#   script: string: name of script to extract functions from
+# Returns:
+#   string: of function names
+_shunit_extractTestFunctions()
+{
+  _shunit_script_=$1
+
+  # extract the lines with test function names, strip of anything besides the
+  # function name, and output everything on a single line.
+  _shunit_regex_='^[ 	]*(function )*test[A-Za-z0-9_]* *\(\)'
+  egrep "${_shunit_regex_}" "${_shunit_script_}" \
+  |sed 's/^[^A-Za-z0-9_]*//;s/^function //;s/\([A-Za-z0-9_]*\).*/\1/g' \
+  |xargs
+
+  unset _shunit_regex_ _shunit_script_
+}
+
+#------------------------------------------------------------------------------
+# main
+#
+
+# determine the operating mode
+if [ $# -eq 0 ]; then
+  __shunit_script=${__SHUNIT_PARENT}
+  __shunit_mode=${__SHUNIT_MODE_SOURCED}
+else
+  __shunit_script=$1
+  [ -r "${__shunit_script}" ] || \
+      _shunit_fatal "unable to read from ${__shunit_script}"
+  __shunit_mode=${__SHUNIT_MODE_STANDALONE}
+fi
+
+# create a temporary storage location
+__shunit_tmpDir=`_shunit_mktempDir`
+
+# provide a public temporary directory for unit test scripts
+# TODO(kward): document this
+SHUNIT_TMPDIR="${__shunit_tmpDir}/tmp"
+mkdir "${SHUNIT_TMPDIR}"
+
+# setup traps to clean up after ourselves
+trap '_shunit_cleanup EXIT' 0
+trap '_shunit_cleanup INT' 2
+trap '_shunit_cleanup TERM' 15
+
+# create phantom functions to work around issues with Cygwin
+_shunit_mktempFunc
+PATH="${__shunit_tmpDir}:${PATH}"
+
+# make sure phantom functions are executable. this will bite if /tmp (or the
+# current $TMPDIR) points to a path on a partition that was mounted with the
+# 'noexec' option. the noexec command was created with _shunit_mktempFunc().
+noexec 2>/dev/null || _shunit_fatal \
+    'please declare TMPDIR with path on partition with exec permission'
+
+# we must manually source the tests in standalone mode
+if [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]; then
+  . "`_shunit_prepForSourcing \"${__shunit_script}\"`"
+fi
+
+# execute the oneTimeSetUp function (if it exists)
+oneTimeSetUp
+
+# execute the suite function defined in the parent test script
+# deprecated as of 2.1.0
+suite
+
+# if no suite function was defined, dynamically build a list of functions
+if [ -z "${__shunit_suite}" ]; then
+  shunit_funcs_=`_shunit_extractTestFunctions "${__shunit_script}"`
+  for shunit_func_ in ${shunit_funcs_}; do
+    suite_addTest ${shunit_func_}
+  done
+fi
+unset shunit_func_ shunit_funcs_
+
+# execute the tests
+_shunit_execSuite
+
+# execute the oneTimeTearDown function (if it exists)
+oneTimeTearDown
+
+# generate the report
+_shunit_generateReport
+
+# that's it folks
+[ ${__shunit_testsFailed} -eq 0 ]
+exit $?
diff --git a/lib/versions b/lib/versions
new file mode 100755
index 0000000..1a1270f
--- /dev/null
+++ b/lib/versions
@@ -0,0 +1,227 @@
+#! /bin/sh
+# $Id: versions 145 2011-06-10 11:45:17Z kate.ward@forestent.com $
+# vim:et:ft=sh:sts=2:sw=2
+#
+# Copyright 2008 Kate Ward. All Rights Reserved.
+# Released under the LGPL (GNU Lesser General Public License)
+#
+# Author: kate.ward@forestent.com (Kate Ward)
+#
+# This library provides reusable functions that determine actual names and
+# versions of installed shells and the OS. The library can also be run as a
+# script if set execuatable.
+
+ARGV0=`basename "$0"`
+LSB_RELEASE='/etc/lsb-release'
+VERSIONS_SHELLS="/bin/bash /bin/dash /bin/ksh /bin/pdksh /bin/sh /bin/zsh"
+
+TRUE=0
+FALSE=1
+ERROR=2
+
+__versions_haveStrings=${ERROR}
+
+#------------------------------------------------------------------------------
+# functions
+#
+
+versions_osName()
+{
+  os_name_='unrecognized'
+  os_system_=`uname -s`
+  case ${os_system_} in
+    CYGWIN_NT-*) os_name_='Cygwin' ;;
+    Darwin) os_name_='Mac OS X' ;;
+    FreeBSD) os_name_='FreeBSD' ;;
+    Linux) os_name_='Linux' ;;
+    SunOS)
+      if grep 'OpenSolaris' /etc/release >/dev/null; then
+        os_name_='OpenSolaris'
+      else
+        os_name_='Solaris'
+      fi
+      ;;
+  esac
+  echo ${os_name_}
+  unset os_name_ os_system_
+}
+
+versions_osVersion()
+{
+  os_version_='unrecognized'
+  os_system_=`uname -s`
+  os_release_=`uname -r`
+  case ${os_system_} in
+    CYGWIN_NT-*)
+      os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]\.[0-9]*\).*'`
+      ;;
+    Darwin)
+      major_='10'
+      sub_=`echo ${os_release_} |sed 's/^[0-9]*\.\([0-9]*\)\.[0-9]*$/\1/'`
+      case ${os_release_} in
+        8.*) minor_='4' ;;
+        9.*) minor_='5' ;;
+        10.*) minor_='6' ;;
+        *) minor_='X'; sub_='X' ;;
+      esac
+      os_version_="${major_}.${minor_}.${sub_}"
+      ;;
+    FreeBSD)
+      os_version_=`expr "${os_release_}" : '\([0-9]*\.[0-9]*\)-.*'`
+      ;;
+    Linux)
+      if [ -r "${LSB_RELEASE}" ]; then
+        if grep -q 'DISTRIB_ID=Ubuntu' "${LSB_RELEASE}"; then
+          os_version_=`cat "${LSB_RELEASE}" \
+            |awk -F= '$1~/DISTRIB_DESCRIPTION/{print $2}' \
+            |sed 's/"//g;s/ /-/g'`
+        fi
+      elif [ -r '/etc/redhat-release' ]; then
+        os_version_=`cat /etc/redhat-release`
+      fi
+      ;;
+    SunOS)
+      if grep 'OpenSolaris' /etc/release >/dev/null; then
+        os_version_=`grep 'OpenSolaris' /etc/release |awk '{print $2"("$3")"}'`
+      else
+        major_=`echo ${os_release_} |sed 's/[0-9]*\.\([0-9]*\)/\1/'`
+        minor_=`grep Solaris /etc/release |sed 's/[^u]*\(u[0-9]*\).*/\1/'`
+        os_version_="${major_}${minor_}"
+      fi
+      ;;
+  esac
+  echo ${os_version_}
+  unset os_name_ os_release_ os_version_ major_ minor_ sub_
+}
+
+versions_shellVersion()
+{
+  shell_=$1
+
+  if [ ! -x "${shell_}" ]; then
+    echo 'not installed'
+    return
+  fi
+
+  version_=''
+  case ${shell_} in
+    */sh)
+      # TODO(kward): fix this
+      ## this could be one of any number of shells. try until one fits.
+      #version_=`versions_shell_bash ${shell_}`
+      ## dash cannot be self determined yet
+      #[ -z "${version_}" ] && version_=`versions_shell_ksh ${shell_}`
+      ## pdksh is covered in versions_shell_ksh()
+      #[ -z "${version_}" ] && version_=`versions_shell_zsh ${shell_}`
+      ;;
+    */bash) version_=`versions_shell_bash ${shell_}` ;;
+    */dash)
+      # simply assuming Ubuntu Linux until somebody comes up with a better
+      # test. the following test will return an empty string if dash is not
+      # installed.
+      version_=`versions_shell_dash`
+      ;;
+    */ksh) version_=`versions_shell_ksh ${shell_}` ;;
+    */pdksh) version_=`versions_shell_pdksh ${shell_}` ;;
+    */zsh) version_=`versions_shell_zsh ${shell_}` ;;
+    *) version_='invalid'
+  esac
+
+  echo ${version_:-unknown}
+  unset shell_ version_
+}
+
+versions_shell_bash()
+{
+  $1 --version 2>&1 |grep 'GNU bash' |sed 's/.*version \([^ ]*\).*/\1/'
+}
+
+versions_shell_dash()
+{
+  eval dpkg >/dev/null 2>&1
+  [ $? -eq 127 ] && return  # return if dpkg not found
+
+  dpkg -l |grep ' dash ' |awk '{print $3}'
+}
+
+versions_shell_ksh()
+{
+  versions_shell_=$1
+
+  # see if --version gives a result
+  versions_version_=`${versions_shell_} --version 2>&1 \
+    |sed 's/.*\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]\).*/\1/'`
+
+  # --version didn't work... look into the binary
+  if [ $? -ne ${TRUE} ]; then 
+    _versions_have_strings
+    versions_version_=`strings ${versions_shell_} 2>&1 \
+      |grep Version \
+      |sed 's/^.*Version \(.*\)$/\1/;s/ s+ \$$//;s/ /-/g'`
+    [ -z "${versions_version_}" ] \
+        && versions_version_=`versions_shell_pdksh ${versions_shell_}`
+  fi
+
+  echo ${versions_version_}
+
+  unset versions_shell_ versions_version_
+}
+
+versions_shell_pdksh()
+{
+  _versions_have_strings
+  strings $1 2>&1 \
+  |grep 'PD KSH' \
+  |sed -e 's/.*PD KSH \(.*\)/\1/;s/ /-/g'
+}
+
+versions_shell_zsh()
+{
+  versions_shell_=$1
+
+  versions_version_=`${versions_shell_} --version 2>&1 |awk '{print $2}'`
+
+  if [ $? -ne ${TRUE} ]; then
+    versions_version_=`echo 'echo ${ZSH_VERSION}' |${versions_shell_}`
+  fi
+
+  echo ${versions_version_}
+
+  unset versions_shell_ versions_version_
+}
+
+# Determine if the 'strings' binary installed.
+_versions_have_strings()
+{
+  [ ${__versions_haveStrings} -ne ${ERROR} ] && return
+  eval strings /dev/null >/dev/null 2>&1
+  if [ $? -eq 0 ]; then
+    __versions_haveStrings=${TRUE}
+  else
+    echo 'WARN: strings not installed. try installing binutils?' >&2
+    __versions_haveStrings=${FALSE}
+  fi
+}
+
+#------------------------------------------------------------------------------
+# main
+#
+
+versions_main()
+{
+  # treat unset variables as an error
+  set -u
+
+  os_name=`versions_osName`
+  os_version=`versions_osVersion`
+  echo "os: ${os_name} version: ${os_version}"
+
+  for shell in ${VERSIONS_SHELLS}; do
+    shell_version=`versions_shellVersion ${shell}`
+    echo "shell: ${shell} version: ${shell_version}"
+  done
+}
+
+if [ "${ARGV0}" = 'versions' ]; then
+  versions_main "$@"
+fi