Version 0 of autosetup

Updated 2010-12-14 22:54:05 by steveb

On the page Jim Tcl as a basis for configure and build system there has been discussion about replacing bash -> m4 -> autoconf -> automake -> make with a Tcl-based system.

autosetup (https://github.com/msteveb/github ) is a piece of that puzzle.

It is a Tcl-based replacement for autoconf. One interesting feature is that it solves the bootstrap problem by including a single-sourcefile version of Jim Tcl which will automatically be compiled and uses if an appropriate Tcl interpreter isn't found.

Below is the autosetup manual for easy access (but I may remove this at some point since it is also available at http://msteveb.github.com/autosetup/ )

Comment is welcome here.


autosetup v0.6.0 -- User Manual

1. Introduction

'autosetup' is a tool, similar to 'autoconf', to configure a build system for the appropriate environment, according to the system capabilities and the user configuration.

autosetup is designed to be light-weight, fast, simple and flexible.

Notable features include:

  • Easily check for headers, functions, types for C/C++
  • Easily support user configuration options
  • Can generate files based on templates, such as Makefile.in => Makefile
  • Can generate header files based on checked features
  • Excellent support for cross compilation
  • Replacement for autoconf in many situations
  • Runs with either Tcl 8.5+, Jim Tcl or just a C compiler (using the included Jim Tcl source code!)
  • autosetup is intended to be distributed with projects - no version issues

autosetup is particularly targeted towards building C/C++ applications on Unix systems, however it can be extended for other environments as needed.

autosetup is *not*:

  • A build system
  • A replacement for automake
  • Intended to replace all possible uses of autoconf

2. Usage

autosetup accepts both standard options as well as local options defined in the 'auto.def' file, and options for modules. Use 'autosetup --help' to show all available options.

  
          autosetup ?options? ?settings?

Some important core options are:

  
          -C dir           change to the given directory before running autosetup
          --help           display help and options
          --version        display the version of autosetup
          --manual?=text?  display the autosetup manual. Alternative formats are 'wiki' and 'asciidoc'
          --install        install autosetup to the current directory
          --init           create an initial 'configure' script if none exists

Settings are of the form 'name=value' and must be after any options. These settings allow the default values to be overridded for variables such as CC and CFLAGS.

Optional modules may support additional options. For example, the cc module supports the following additional options.

  
          --host=host-alias     a complete or partial cpu-vendor-opsys for the system where the
                                application will run (defaults to the same value as --build)
          --build=build-alias   a complete or partial cpu-vendor-opsys for the system where the
                                application will be built (defaults to the result of running
                                config.guess)
          --prefix=dir          the target directory for the build (defaults to /usr/local)

Typically, autosetup is invoked via a simpler wrapper script, 'configure'. This provides for compatibility with autoconf. For example:

  
          ./configure --host=arm-linux --utf8 --prefix=/usr CFLAGS="-g -Os"

3. Features

3.1. Configuration descriptions are Tcl

Configuration requirements are given in an 'auto.def' file and are written in 'Tcl', a language slightly less obscure than 'm4'! As a full language, there are no additional dependencies on the host system such as 'awk', 'sed' and 'bash'.

Tcl is widely available on modern development platforms.

3.2. Simple Configuration Descriptions

A typical, simple auto.def file is:

  
          use cc
  
          options {
              shared => "build a shared library"
              lineedit=1 => "disable line editing"
              utf8 => "enabled UTF-8 support"
              with-regexp regexp => "use regexp"
          }
  
          cc-check-types "long long"
          cc-check-includes sys/un.h dlfcn.h
          cc-check-functions ualarm sysinfo lstat fork vfork
          cc-check-function-in-lib sqlite3_open sqlite3
  
          if {[opt-bool utf8] && [have-feature fork]} {
              msg-result "Enabling UTF-8"
              define JIM_UTF8
          }
          make-autoconf-h config.h
          make-template Makefile.in

3.3. Fast

All the processing occurs in a single process, aside from invocations of the C compiler. Here are the results of a typical configure for a small project. 'autoconf' is particularly slow on 'cygwin'.

  
                        autoconf     autosetup
                        ---------    ---------
          Linux          4.1s         1.3s
          Mac OS X       6.4s         2.8s
          cygwin        91.5s         9.9s

3.4. Deploys directly within a project

autosetup is deployed as a single subdirectory, autosetup, at the top level of a project, containing a handful of files. This approach means that there are no dependency issues with different versions of autosetup since an appropriate version is part of the project.

autosetup is written in Tcl, but can run under any of the following Tcl interpreters:

  • Tcl 8.5 or later (which is widely deployed
  • Jim Tcl - small footprint, portable Tcl interpreter

The source code for Jim Tcl is included directly within autosetup and is automatically built if no other Tcl interpreter is available.

  
          $ ./configure --help
          No installed jimsh or tclsh, building local bootstrap jimsh0
          Usage: configure [options]
  
             This is autosetup, a faster, better alternative to autoconf.
             Use the --manual option for the full autosetup manual, including
             standard autosetup options.
  
          Local options:
            --shared            Create a shared library
            --disable-utf8      Disable utf8 support

3.5. No separate generate/run step

autosetup parses 'auto.def' and updates the configuration in a single step. This simplifies and speeds development.

4. Writing auto.def files

auto.def files are generally simple to write, but have the full power of Tcl if required for implementing complex checks or option processing. The 'auto.def' file is structured as follows:

  • 'use' modules
  • 'options' declaration
  • checks and option processing
  • template, header file and other output generation

4.1. Optional modules

autosetup includes the common, optional modules 'cc' and 'cc-shared'. If these modules are required, declared *before* 'options' so that any module-specific options can be recognised.

  
          # This project checks for C/C++ features
          use cc
          # And supports shared libraries/shared objects
          use cc-shared
  
          options { ... }

4.2. Declaring User Options

Allowed options are defined using the 'options' declaration in the 'auto.def' file.

*Note*: Every auto.def *must* have an 'options' declaration immediately after any 'use' declarations, even if it is empty. This ensures that 'configure --help' behaves correctly.

Options are declared as follows.

  
          options {
              boolopt            => "a boolean option which defaults to disabled"
              boolopt2=1         => "a boolean option which defaults to enabled"
              stringopt:         => "an option which takes an argument, e.g. --stringopt=value"
              stringopt2:=value  => "an option where the argument is optional and defaults to 'value'"
              optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help"
              boolopt4 => {
                  Multiline description for this option
                  which is carefully formatted.
              }
          }

The '=>' syntax is used to indicate the help description for the option. If an option is not followed by '=>', the option is not displayed in '--help' but is still available.

If the first character of the help description is a newline (as for 'boolopt4'), the description will not be reformatted.

String options can be specified multiple times, and all given values are available. If there is no default value, the value must be specified.

Within auto.def, options are checked with the commands 'opt-bool' and 'opt-val'.

4.3. Setting Options

Boolean options can be enabled or disabled with one of the following forms (some of which are for autoconf compatibility):

  
          Enable the option:
          --boolopt
          --enable-boolopt
          --boolopt=1
          --boolopt=yes
          Disable the option:
          --disable-boolopt
          --boolopt=0
          --boolopt=no

String options must have a value specified, unless the option has a default value.

  
          --stropt          - OK if a default values is given for stropt
          --stropt=value    - Adds the given value for the option

4.4. Configuration Variables

At it's heart, autosetup is about examining user options, performing checks and setting configuration variables representing the options and environment. These variables are set either directly with the 'define' or 'define-feature' commands, or indirectly via one of the test commands such as 'cc-check-includes'.

All configuration variables are available for template substitution ('make-template'), header file generation ('make-autoconf-h') or can be tested and set within 'auto.def'. Certain naming conventions are used to provide expected behaviour.

All commands which check for the existence of a feature, use HAVE_xxx as the name of the corresponding variable (this is autoconf compatible). See 'feature-define-name' for the rules used to convert a feature name to a variable name.

  
          cc-check-includes time.h sys/types.h      => HAVE_TIME_H HAVE_SYS_TYPES_H
          cc-check-functions strlcat                => HAVE_STRLCAT
          cc-check-types "long long" "struct stat"  => HAVE_LONG_LONG HAVE_STRUCT_STAT

These two are equivalent:

  
          have-feature sys/types.h
          get-define HAVE_SYS_TYPE_H

'cc-check-sizeof' uses the SIZEOF_ prefix rather than the HAVE_ prefix.

Variables used to store command names are simply the uppercase of the base command.

  
          CC              - The C compiler
          LD              - The linker
          AR              - ar
          RANLIB          - ranlib

4.5. configure

In order to provide compatibility with autoconf, and to simplify out-of-tree builds, autosetup can be run via a simple 'configure' script. The following script is created by 'autosetup --init'.

  
          #!/bin/sh
          dir="$(dirname "$0")/autosetup"
          WRAPPER="$0" exec $("$dir/find-tclsh" || echo false) "$dir/autosetup" "$@"

This script invokes autosetup in the autosetup/ subdirectory after setting the WRAPPER environment variable.

'autosetup --init' will create this script if it doesn't exist.

4.6. Checking Features

Apart from checking user options, the primary purpose of autosetup and 'auto.def' is to check for the availablity of features in the environment. The 'cc' module provides commands to check various settings by compiling small test programs with the specified C compiler. The following is a typical example:

  
          use cc
          options {}
          cc-check-types "long long"
          cc-check-includes sys/un.h
          cc-check-functions regcomp waitpid sigaction
          cc-check-tools ar ranlib strip

See the command reference for details of these builtin checks.

4.7. Controlling the build

Once the user options have been processed and the environment checked for supported features, it is necessary to use this information to control the build. The 'cc' module provides two mechanisms for this:

  • 'make-template' creates a file from a template by applying substitutions based on the configuration variables. For example, replacing '@CC@' with 'arm-linux-gcc'.
  • 'make-autoconf-h' creates a C/C++ header file based on the configuration variables

It is easy to create other file formats based on configuration variables. For example, one system produces configuration files in the Linux kconfig format. It is also possible to output configuration variables in Makefile format.

autosetup has far more control over generating files to control the build since the configuration variables are directly accessible in 'Tcl' from 'auto.def'.

4.8. A "standard" Makefile.in

If autosetup is being used to control a make-based build system, the use of a a 'Makefile.in' with a standard structure will provide behaviour similar to that provided by autoconf/automake systems. autosetup provides a typical 'Makefile.in' in 'examples/typical/Makefile.in'. This example provides the following:

  • Use CC, AR, RANLIB as determined by cross compiler settings or user overrides
  • Install to --prefix, overridable with DESTDIR
  • Use of VPATH to support out-of-tree builds
  • Dummy automake targets to allow for use as a subproject with automake
  • Automatically reconfigure if auto.def changes

5. Command Reference

autosetup provides a number of builtin commands which are documented below. These may be used from 'auto.def' to test for features, define variables create files from templates and other similar actions.

This commands are all implemented as Tcl procedures. Custom commands may be added simpy by defining additional Tcl procedures in the 'auto.def' file.

opt-bool option ...

Check each of the named, boolean options and return 1 if any of them have been set by the user.

opt-val option-list ?default=""?

Returns a list containing all the values given for the non-boolean options in 'option-list'. There will be one entry in the list for each option given by the user, including if the same option was used multiple times. If only a single value is required, use something like:

  lindex [opt-val $names] end

If no options were set, $default is returned (exactly, not as a list).

define name ?value=1?

Defines the named variable to the given value. These name, values pairs represent the results of the configuration check and are available to be checked, modified and substituted.

define-append name value

Appends the given value to the given 'defined' variable. If the variable is not defined or empty, it is set to $value. Otherwise the value is appended, separated by a space.

get-define name ?default=0?

Returns the current value of the 'defined' variable, or $default if not set.

is-defined name

Returns 1 if the given variable is defined.

get-env name default

If $name was specified on the command line, return it. If $name was set in the environment, return it. Otherwise return $default.

readfile filename ?default=""?

Return the contents of the file, without the trailing newline. If the doesn't exist or can't be read, returns $default.

writefile filename value

Creates the given file containing $value. Does not add an extra newline.

find-executable name

Searches the path for an executable with the given name. Returns 1 if found, or 0 if not.

find-an-executable ?-required? name ...

Given a list of possible executable names, searches for one of these on the path. Returns the name found, or "" if none found. If the first parameter is '-required', an error is generated if no executable is found.

configlog msg

Writes the given message to the configuration log, config.log

msg-checking msg

Writes the message with no newline to stdout.

msg-result msg

Writes the message to stdout.

user-error msg

Indicate incorrect usage to the user, including if required components or features are not found. autosetup exits with a non-zero return code.

user-notice msg

Output the given message to stderr.

use module ...

Load the given library modules. e.g. use cc cc-shared

MODULE: use cc-shared

Module which provides support for shared libraries and shared objects. Defines the following variables:

  SH_CFLAGS         Flags to use compiling sources destined for a shared library
  SH_LDFLAGS        Flags to use linking a shared library
  SHOBJ_CFLAGS      Flags to use compiling sources destined for a shared object
  SHOBJ_LDFLAGS     Flags to use linking a shared object
  SH_LINKFLAGS      Flags to use linking an executable which will load shared objects
  LD_LIBRARY_PATH   Environment variable which specifies path to shared libraries
MODULE: use cc

This module supports checking various 'features' of the C compiler/linker environment. Common commands are cc-check-includes, cc-check-types, cc-check-functions, make-autoconf-h and make-template.

have-feature name ?default=0?

Returns the value of the feature if defined, or $default if not.

define-feature name ?value=1?

Sets the feature 'define' to the given value.

feature-checked name

Returns 1 if the feature has been checked, whether true or not

feature-define-name name ?prefix=HAVE_?

Converts a name to the corresponding define, e.g. sys/stat.h becomes HAVE_SYS_STAT_H. Converts * to P and all non-alphanumumeric to underscore.

cc-check-sizeof ?-args? type ...

Checks the size of the given types (between 2 and 32). Defines a variable with the size determined, or "unknown" otherwise. e.g. for type 'long long', defines SIZEOF_LONG_LONG. Returns the size of the last type. The first arg may be a list of additional arguments to cctest.

cc-check-includes ?-args? includes ...

Checks that the given include files can be used The first arg may be a list of additional arguments to cctest.

cc-check-types ?-args? type ...

Checks that the types exist. The first arg may be a list of additional arguments to cctest.

cc-check-functions ?-args? function ...

Checks that the given functions exist (can be linked) The first arg may be a list of additional arguments to cctest.

cc-check-members ?-args? type.member ...

Checks that the given type/structure members exist. A structure member is of the form "struct stat.st_mtime" The first arg may be a list of additional arguments to cctest.

cc-check-function-in-lib function libs ?otherlibs?

Checks that the given given function can be found on one of the libs. First checks for no library required, then checks each of the libraries in turn. If the function is found, the feature is defined and lib_$function is defined to -l$lib where the function was found, or "" if no library required. In addition, -l$lib is added to the LIBS define. If additional libraries may be needed to linked, they should be specified as $extralibs as "-lotherlib1 -lotherlib2". These libraries are not automatically added to LIBS. Returns 1 if found or 0 if not.

cc-check-tools tool ...

Checks for existence of the given compiler tools, taking into account any cross compilation prefix. For example, when checking for "ar", first AR is checked on the command line and then in the environment. If not found, "${host}-ar" or simply "ar" is assumed depending upone whether cross compiling. The path is searched for this executable, and if found AR is defined to the executable name. It is an error if the executable is not found.

cc-check-progs prog ...

Checks for existence of the given executables on the path. For example, when checking for "grep", the path is searched for the executable, 'grep', and if found GREP is defined as "grep". It the executable is not found, the variable is defined as false. Returns 1 if all programs were found, or 0 otherwise.

cctest ?settings?

Low level C compiler checker. Compiles and or links a small C program according to the arguments and returns 1 if OK, or 0 if not.

  Supported settings are:
  
  -cflags cflags      A list of flags to pass to the compiler
  -includes list      A list of includes, e.g. {stdlib.h stdio.h}
  -declare code       Code to declare before main()
  -link 1             Don't just compile, link too
  -libs liblist       List of libraries to link, e.g. {-ldl -lm}
  -code code          Code to compile in the body of main()
  -source code        Compile a complete program. Ignore -includes, -declare and -code
  -sourcefile file    Shorthand for -source [readfile [get-define srcdir]/$file]
  #include <firstinclude>   /* same for remaining includes in the list */
  
  declare-code              /* any code in -declare, verbatim */
  
  int main(void) {
    code                    /* any code in -code, verbatim */
    return 0;
  }

Any failures are recorded in 'config.log'

6. Examples

autosetup includes a number of examples, including:

  • typical - A simple, but full feature example
  • minimal - A minimal example
  • jim - The Jim Tcl project uses autosetup

These examples can be found along with the autosetup source at https://github.com/msteveb/autosetup

7. Tips on moving from autoconf

autosetup attempts to be reasonably compatible with an autoconf-generated 'configure' script. Some differences are noted below.

7.1. No --target, no need for --build

While autosetup has good cross compile support with '--host', it has no explicit support for '--target' (which is almost never needed).

Additionally, --build is rarely needed since the build system can be guessed with 'config.guess'.

7.2. Single variable namespace

All variables defined with 'define' and 'define-feature' use a single namespace. This essentially means that AC_SUBST and AC_DEFINE are equivalent, which simplifies configuration in practice.

7.3. No autoheader

autosetup has no need for 'autoheader' since a configuration header file can simply be generated directly (see 'make-autoconf-h') without a template.

7.4. No subdirectory support

autoconf supports configuring subdirectories with AC_CONFIG_SUBDIRS. autosetup has no explicit support for this feature.

7.5. No automake

autosetup is not designed to be used with automake. autosetup is flexible enough to be used with plain 'make', or other builds systems.

7.6. No AC_TRY_RUN

autosetup has no equivalent of AC_TRY_RUN which attempts to run a test program. This feature is often used unnecessarily, and is useless when cross compiling, which is a core feature of autosetup.

7.7. Modern Platform Assumption

autoconf includes support for many old and obsolete platforms. Most of these are no longer relevant. autosetup assumes that the build environment is somewhat POSIX compliant. This includes both cygwin and mingw on Windows.

7.8. Thus, no need to check for standard headers

such as stdlib.h, string.h, etc.

7.9. No AC_PROG_xxxx

Use the generic 'cc-check-progs'

  
          if {![cc-check-progs grep]} {
              user-error "You don't have grep, but we need it"
          }
          foreach prog {gawk mawk nawk awk} {
              if {[cc-check-progs $prog]} {
                  define AWK $prog
                  break
              }
          }
          # If not found, AWK is defined as false

7.10. No AC_FUNC_xxx

Use the generic 'cc-check-functions' instead

7.11. No special commands to use replacement functions

Instead consider something like the following.

  
          # auto.def: Check all functions
          cc-check-functions strtod backtrace
  
          /* replacements.c */
          #include "config.h"
          #ifndef HAVE_STRTOD
          double strtod(...) { /* implementation */ }
          #endif

Alternatively, implement each missing function in it's own file.

  
          define EXTRA_OBJS ""
          foreach f {strtod backtrace} {
              if {![cc-check-functions $f]} {
                  define-append EXTRA_OBJS $f.o
              }
          }

7.12. Default checks do not use any include files.

autoconf normally adds certain include files to every test build, such as stdio.h. This can cause problems where declarations in these standard headers conflict with the code being tested. For this reason, autosetup compile tests uses no standard headers. If headers are required, they should be added explicitly.

7.13. Checking for includes

When adding includes with '-includes', these are not checked for existence first

8. Cross Compiling

In general, cross compilation works the same way as autoconf. Generally this simply means specifying --host=<target-alias>. For example, if you have arm-linux-gcc and related tools, run:

  
          ./configure --host=arm-linux

If additional compiler options are needed, such as -mbig-endian, these can be specfied with CFLAGS. In this case, the default CFLAGS of "-g -O2" won't be used so the desired debugging and optimisation flags should also be added.

  
          ./configure --host=arm-linux CFLAGS="-mbig-endian -msoft-float -static-libgcc -g -Os"

If the compiler and related tools have a non-standard prefix, it may be necessary to set CROSS in addition to --host.

  
          ./configure --host=arm-linux CROSS=my-

In this case, C the compiler should be named my-cc or my-gcc, and similarly for the other tools. This is usually simpler than specifying CC, AR, RANLIB, STRIP, etc.

9. Installing

Like autoconf, autosetup uses a combination of '--prefix' and 'DESTDIR' to determine where the project is installed.

The '--prefix' option is used during with './configure' to specify the top level installation directory. It defaults to '/usr/local'. Use '--prefix=' to install at the top level (e.g. '/bin'). The application may use this value (via '@prefix@' or one of the related values such as '@bindir@') to find files at runtime.

The 'DESTDIR' Makefile variable may be used at installation time to specify an different install root directory. This is especially useful to stage the installed files in a temporary location before they are installed to their final location (e.g. when building a filesystem for an embedded target). It defaults to the empty string (i.e. files are installed to '--prefix').

  
          ./configure --prefix=/usr
          make DESTDIR=/tmp/staging install

autosetup has no special support for installing other than providing '--prefix'. The use of 'DESTDIR' is by convention. In order to provide expected behaviour, Makefile.in should contain something like:

  
          prefix = @prefix@
          ...
          install: all
              @echo Installing from @srcdir@ and `pwd` to $(DESTDIR)$(prefix)

10. Automatic remaking

It is convenient for configure to be rerun automatically if any of the input files change (for example autosetup or any of the template files). This can be achieved by adding the following to Makefile.in.

  
          ifeq ($(findstring clean,$(MAKECMDGOALS)),)
          Makefile: @AUTODEPS@ @srcdir@/Makefile.in
                  @@AUTOREMAKE@
          endif

It may also be convenient to add a target to force reconfiguring with the same options.

  
          reconfig:
                  @AUTOREMAKE@

11. Shipping autosetup

autosetup is designed to be deployed directly as part of a project. It is installed as a single subdirectory, autosetup, at the top level of a project.

In addition to autosetup, the following files are required for an autosetup-enabled project.

  • auto.def
  • configure (generated by autosetup --init)
  • Makefile.in (and any other template specified in auto.def)

12. Extending autosetup

Local modules can be added directly to the autosetup directory and loaded with the 'use' command.

13. Future Features/Changes

Some features are not yet implemented, but are candidates for including in an existing module, or adding to a new module. Others may require changes to the core 'autosetup'.

  • Explicit C++ support
  • pkg-config support
  • More fully-featured shared library support
  • Support for additional languages
  • libtool support (if we must!)
  • Subdirectory support. Need to resolve how options are parsed, and how variables interact between subdirectories.

14. Motivation

autoconf does the job and supports many platforms, but it suffers from at least the following problems:

  • Requires configuration descriptions in a combination of m4 and shell scripts
  • Creates 10,000 line shell scripts which are slow to run and impossible to debug
  • Requires a multi-stage process of aclocal => autoheader => autoconf => configure => Makefile + config.h

autosetup attempts to address these issues as follows by directly parsing a simple 'auto.def' file, written in Tcl, and directly generating output files such as config.h and Makefile.

autosetup runs under either Tcl 8.5, which is available on almost any modern system, or Jim Tcl. Jim Tcl is very easy to build on almost any system in the case where Tcl is not available.

15. References

15.1. Comments on autoconf

16. Alternative autoconf Alternatives

17. Copyright, Author and Licence

autosetup is Copyright (c) 2010 WorkWare Systems http://workware.net.au/

autosetup was written by Steve Bennett <[email protected]>

autosetup is released under the "2-clause FreeBSD Licence" as follows.

  
          autosetup - An environment autoconfigurator
  
          Copyright 2010 Steve Bennett <[email protected]>
  
          Redistribution and use in source and binary forms, with or without
          modification, are permitted provided that the following conditions
          are met:
  
          1) Redistributions of source code must retain the above copyright
             notice, this list of conditions and the following disclaimer.
          2) Redistributions in binary form must reproduce the above
             copyright notice, this list of conditions and the following
             disclaimer in the documentation and/or other materials
             provided with the distribution.
  
          THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY
          EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
          PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE
          SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
          INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
          (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
          OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
          HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
          STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
          ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
          ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
          The views and conclusions contained in the software and documentation
          are those of the authors and should not be interpreted as representing
          official policies, either expressed or implied, of WorkWare Systems.