[med-svn] [r-cran-rniftilib] 05/11: Imported Upstream version 0.0-32

Andreas Tille tille at debian.org
Sat Jan 23 07:53:56 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository r-cran-rniftilib.

commit 0754c0664c55e604da6b0d81b817f879b5146c78
Author: Andreas Tille <tille at debian.org>
Date:   Sat Jan 23 08:47:50 2016 +0100

    Imported Upstream version 0.0-32
---
 DESCRIPTION                       |   18 +
 MD5                               |   31 +
 NAMESPACE                         |   10 +
 R/FirstLib.R                      |   17 +
 R/nifti.R                         |  174 +
 aclocal.m4                        |   14 +
 ax_check_zlib.m4                  |  124 +
 config.h.in                       |   62 +
 configure                         | 5655 +++++++++++++++++++++++++++
 debian/README.test                |    7 -
 debian/changelog                  |    5 -
 debian/compat                     |    1 -
 debian/control                    |   19 -
 debian/copyright                  |   28 -
 debian/rules                      |   13 -
 debian/source/format              |    1 -
 debian/watch                      |    2 -
 man/nifti.Rd                      |  126 +
 man/nifti_compiled_with_zlib.Rd   |   28 +
 man/nifti_datatype_string.Rd      |   31 +
 man/nifti_disp_lib_version.Rd     |   24 +
 man/nifti_image_alloc_data.Rd     |   35 +
 man/nifti_image_copy_info.Rd      |   36 +
 man/nifti_image_free.Rd           |   32 +
 man/nifti_image_new.Rd            |   36 +
 man/nifti_image_read.Rd           |   50 +
 man/nifti_image_setdatatype.Rd    |   69 +
 man/nifti_image_unload.Rd         |   31 +
 man/nifti_image_write.Rd          |   32 +
 man/nifti_interpolate3D.Rd        |   42 +
 man/nifti_read_subregion_image.Rd |   43 +
 man/nifti_set_filenames.Rd        |   38 +
 man/nifti_units_string.Rd         |   31 +
 src/Makevars.in                   |    2 +
 src/Rnifti.c                      | 1687 +++++++++
 src/nifti1.h                      | 1490 ++++++++
 src/nifti1_io.c                   | 7569 +++++++++++++++++++++++++++++++++++++
 src/nifti1_io.h                   |  555 +++
 src/znzlib.c                      |  327 ++
 src/znzlib.h                      |  129 +
 40 files changed, 18548 insertions(+), 76 deletions(-)

diff --git a/DESCRIPTION b/DESCRIPTION
new file mode 100644
index 0000000..f951338
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,18 @@
+Package: Rniftilib
+Version: 0.0-32
+Date: 2012-02-28
+Title: Rniftilib - R Interface to NIFTICLIB (V2.0.0: 2010-07-20)
+Author: Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+Maintainer: Oliver Granert <o.granert at neurologie.uni-kiel.de>
+Depends: R (>= 1.8.0)
+Suggests:
+Description: R interface to nifticlib (nifticlib-2.0.0) (read/write
+        ANALYZE(TM)7.5/NIfTI-1 volume images)
+License: GPL (>= 2)
+URL: http://rniftilib.r-forge.r-project.org/
+Repository: CRAN
+Repository/R-Forge/Project: rniftilib
+Repository/R-Forge/Revision: 56
+Repository/R-Forge/DateTimeStamp: 2013-01-09 08:02:10
+Date/Publication: 2013-01-09 22:53:32
+Packaged: 2013-01-09 11:17:13 UTC; rforge
diff --git a/MD5 b/MD5
new file mode 100644
index 0000000..5bf9df8
--- /dev/null
+++ b/MD5
@@ -0,0 +1,31 @@
+884c037c94842902da2a3c8a0c65d0f6 *DESCRIPTION
+76e0dcf8e7f673276552a8716f8a0dcb *NAMESPACE
+242236e11d4a2cd05c4b9b12491d44a9 *R/FirstLib.R
+77a59777688961dc624920f16efbb0b4 *R/nifti.R
+273c6e72840b936f5344c4f86e5ff14f *aclocal.m4
+b1aa4ae453e5e1977ac0499b8b063239 *ax_check_zlib.m4
+8ff747358eb34ea32927437a911ad4a2 *config.h.in
+2c560e99c34240970cc606923ee44ac9 *configure
+0a296d28c735d73c45dc405c35fdeb7c *man/nifti.Rd
+646418076b2ece81a187867f9ad7e0f5 *man/nifti_compiled_with_zlib.Rd
+fff00980dc6554bfd269740fd5050eb5 *man/nifti_datatype_string.Rd
+e7b2e14e203d6e445d82866164ead19d *man/nifti_disp_lib_version.Rd
+5e49bd6a3dbcf915b37fc04c86b8e84a *man/nifti_image_alloc_data.Rd
+6e9695d6e29816a883e2053b9648636c *man/nifti_image_copy_info.Rd
+900db6e48804ebf0a57cb08cbeb5d38b *man/nifti_image_free.Rd
+37900ab79fec037a1915854c96e28cda *man/nifti_image_new.Rd
+dbb7f78a624af299f39c396379f2ac2c *man/nifti_image_read.Rd
+dca29b72df0b858cbd3511474c4283a6 *man/nifti_image_setdatatype.Rd
+a3a92959c7f6806f681283c4fd427538 *man/nifti_image_unload.Rd
+87d7526759fe7d1c091fe2fbfcc4c538 *man/nifti_image_write.Rd
+0f1d716c3f6237f006ab37c88078da2b *man/nifti_interpolate3D.Rd
+f3980cbeedddc3204acb559a52d6b4a9 *man/nifti_read_subregion_image.Rd
+c19b86a1ebb48e09b8ad54f619b73994 *man/nifti_set_filenames.Rd
+5e403154b3dde7ffeda36f528809a3e5 *man/nifti_units_string.Rd
+57bed97ab321fc58adda3494b98176b6 *src/Makevars.in
+2f8293076dac8388836c9ce0fd3c13fe *src/Rnifti.c
+1bc087b9e954b8b395d9379d43158f6e *src/nifti1.h
+4e47ac05ed5c500902736b7f7fe8c78d *src/nifti1_io.c
+3ffa2b1885d2ed474f2f0bca5fa6d4af *src/nifti1_io.h
+9d845690f5382b6c3bea879e91821b09 *src/znzlib.c
+582b9f5d055aad992611f091fc13a26b *src/znzlib.h
diff --git a/NAMESPACE b/NAMESPACE
new file mode 100644
index 0000000..0f8ac48
--- /dev/null
+++ b/NAMESPACE
@@ -0,0 +1,10 @@
+useDynLib(Rniftilib)
+export(nifti.image.new, nifti.image.alloc.data, nifti.image.unload, nifti.image.free)
+export(nifti.image.copy.info, nifti.set.filenames)
+export(nifti.image.read, nifti.image.write)
+export(is.nifti, nifti.image.setdatatype)
+export(nifti.read.subregion.image, nifti.interpolate3d)
+export(plot.nifti, print.nifti)
+export(nifti.compiled.with.zlib, nifti.disp.lib.version)
+export(nifti.units.string, nifti.datatype.string)
+export("$.nifti","$<-.nifti","[.nifti","[<-.nifti","dim.nifti","dim<-.nifti")
diff --git a/R/FirstLib.R b/R/FirstLib.R
new file mode 100644
index 0000000..bfc68fd
--- /dev/null
+++ b/R/FirstLib.R
@@ -0,0 +1,17 @@
+## FirstLib: initialization of Rniftilib
+##.First.lib <- function(lib, pkg) 
+##{ 
+## library.dynam("Rniftilib", pkg, lib)   
+##}
+
+## LastLib: cleanup of Rniftilib
+##.Last.lib <- function(libpath) 
+##{ 
+##  library.dynam.unload("Rniftilib", libpath) 
+##}
+
+.onLoad <- function(libname, pkgname)
+{
+  .Call("Rnifti_init", libname, PACKAGE=pkgname)
+}
+
diff --git a/R/nifti.R b/R/nifti.R
new file mode 100644
index 0000000..5276bfe
--- /dev/null
+++ b/R/nifti.R
@@ -0,0 +1,174 @@
+nifti.image.new <- function()
+{
+  .Call("Rnifti_image_new", PACKAGE="Rniftilib") 
+}
+
+nifti.image.alloc.data <- function(nim)
+{
+  .Call("Rnifti_image_alloc_data", nim, PACKAGE="Rniftilib")
+}
+
+nifti.image.unload <- function(nim)
+{
+  .Call("Rnifti_image_unload", nim, PACKAGE="Rniftilib")
+}
+
+nifti.image.free <- function(nim)
+{
+  .Call("Rnifti_image_free", nim, PACKAGE="Rniftilib")
+}
+
+nifti.image.copy.info <- function(nim)
+{
+  .Call("Rnifti_image_copy_info", nim, PACKAGE="Rniftilib")
+}
+
+nifti.set.filenames <- function(nim, prefix, check=1, set_byte_order=1)
+{
+  .Call("Rnifti_set_filenames", nim, prefix, check, set_byte_order,
+        PACKAGE="Rniftilib")
+}
+
+nifti.image.read <- function(file, read_data=1, rm.NaN=TRUE) 
+{
+  .Call("Rnifti_image_read", file, read_data, rm.NaN, PACKAGE="Rniftilib") 
+}
+
+nifti.image.write <- function(nim) 
+{
+  .Call("Rnifti_image_write", nim, PACKAGE="Rniftilib") 
+}
+
+nifti.image.getdim.save <- function(nim, index)
+{
+  d <- dim(nim)
+  retval <- 1
+  if (length(d) >= index)
+    retval <- d[index]
+  retval   
+}
+
+is.nifti <- function(x)
+{
+  is(x,"nifti")
+}
+
+"[.nifti" <- function(x, 
+                      dim1=1:nifti.image.getdim.save(x,1),
+                      dim2=1:nifti.image.getdim.save(x,2),
+                      dim3=1:nifti.image.getdim.save(x,3),
+                      dim4=1:nifti.image.getdim.save(x,4),
+                      dim5=1:nifti.image.getdim.save(x,5),
+                      dim6=1:nifti.image.getdim.save(x,6),
+                      dim7=1:nifti.image.getdim.save(x,7))
+{
+  .Call("Rnifti_image_getpixel", x, dim1-1, dim2-1, dim3-1, dim4-1, dim5-1, dim6-1, dim7-1,
+        PACKAGE="Rniftilib")
+}
+
+"[<-.nifti" <- function(x, 
+                        dim1=1:nifti.image.getdim.save(x,1),
+                        dim2=1:nifti.image.getdim.save(x,2),
+                        dim3=1:nifti.image.getdim.save(x,3),
+                        dim4=1:nifti.image.getdim.save(x,4),
+                        dim5=1:nifti.image.getdim.save(x,5),
+                        dim6=1:nifti.image.getdim.save(x,6),
+                        dim7=1:nifti.image.getdim.save(x,7),
+                        value)
+{
+  .Call("Rnifti_image_setpixel", x, dim1-1, dim2-1, dim3-1, dim4-1, dim5-1, dim6-1, dim7-1, value,
+        PACKAGE="Rniftilib")
+}
+
+"$.nifti" <- function(x, sym)
+{
+  .Call("Rnifti_image_getattribute", x, sym, PACKAGE="Rniftilib")
+}
+
+"$<-.nifti" <- function(x, sym, value)
+{
+  .Call("Rnifti_image_setattribute", x, sym, value, PACKAGE="Rniftilib")
+}
+
+nifti.image.setdatatype <- function(nim, value)
+{
+  .Call("Rnifti_image_setdatatype", nim, value, PACKAGE="Rniftilib")
+}
+
+# EXPERIMENTAL function
+nifti.read.subregion.image <- function(nim, start_index, region_size)
+{
+  .Call("Rnifti_read_subregion_image", nim, start_index, region_size, PACKAGE="Rniftilib")
+}
+
+nifti.interpolate3d <- function(nim, x, y, z, t=1)
+{
+  iX <- floor(x)
+  iY <- floor(y)
+  iZ <- floor(z)
+  coex <- x-iX
+  coey <- y-iY
+  coez <- z-iZ
+        
+  if (iX <=0 || iY <= 0 || iZ <= 0 
+      || iX+1 > nifti.image.getdim.save(nim,1)
+      || iY+1 > nifti.image.getdim.save(nim,2)
+      || iZ+1 > nifti.image.getdim.save(nim,3))
+    return(0)
+      
+  p1 <- (1-coex)*(1-coey)*(1-coez)*nim[iX,iY,iZ,t]
+  p2 <- (1-coex)*(1-coey)*(  coez)*nim[iX,iY,iZ+1,t]
+  p3 <- (1-coex)*(  coey)*(1-coez)*nim[iX,iY+1,iZ,t]
+  p4 <- (1-coex)*(  coey)*(  coez)*nim[iX,iY+1,iZ+1,t]
+  p5 <- (  coex)*(1-coey)*(1-coez)*nim[iX+1,iY,iZ,t]
+  p6 <- (  coex)*(1-coey)*(  coez)*nim[iX+1,iY,iZ+1,t]
+  p7 <- (  coex)*(  coey)*(1-coez)*nim[iX+1,iY+1,iZ,t]
+  p8 <- (  coex)*(  coey)*(  coez)*nim[iX+1,iY+1,iZ+1,t]
+  return(p1+p2+p3+p4+p5+p6+p7+p8)
+}
+
+# generic functions to integrate the nifti methods into R environment
+plot.nifti <- function(x, 
+		       dim1=1:nifti.image.getdim.save(x,1),
+               dim2=1:nifti.image.getdim.save(x,2),
+               dim3=1,
+               dim4=1,...)
+{
+  image(dim1,dim2,x[dim1,dim2,dim3,dim4],col=gray(1:255/255),...)
+}
+
+print.nifti <- function(x, ...)
+{
+  .Call("Rnifti_image_printinfo", x, PACKAGE="Rniftilib")
+}
+
+"dim.nifti" <- function(x)
+{
+  .Call("Rnifti_image_getattribute", x, "dim", PACKAGE="Rniftilib")
+}
+
+"dim<-.nifti" <- function(x, value)
+{
+  .Call("Rnifti_image_setattribute", x, "dim", value, PACKAGE="Rniftilib")
+}
+
+nifti.compiled.with.zlib <- function()
+{
+  .Call("Rnifti_compiled_with_zlib", PACKAGE="Rniftilib")
+}
+
+nifti.disp.lib.version <- function()
+{
+  .Call("Rnifti_disp_lib_version", PACKAGE="Rniftilib")
+}
+
+nifti.units.string <- function(value)
+{
+  .Call("Rnifti_units_string", value, PACKAGE="Rniftilib")
+}
+
+nifti.datatype.string <- function(value)
+{
+  .Call("Rnifti_datatype_string", value, PACKAGE="Rniftilib")
+}
+
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..24e6a83
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,14 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_include([ax_check_zlib.m4])
diff --git a/ax_check_zlib.m4 b/ax_check_zlib.m4
new file mode 100644
index 0000000..8ba2f5d
--- /dev/null
+++ b/ax_check_zlib.m4
@@ -0,0 +1,124 @@
+# ===========================================================================
+#       http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CHECK_ZLIB()
+#
+# DESCRIPTION
+#
+#   This macro searches for an installed zlib library. If nothing was
+#   specified when calling configure, it searches first in /usr/local and
+#   then in /usr. If the --with-zlib=DIR is specified, it will try to find
+#   it in DIR/include/zlib.h and DIR/lib/libz.a. If --without-zlib is
+#   specified, the library is not searched at all.
+#
+#   If either the header file (zlib.h) or the library (libz) is not found,
+#   the configuration exits on error, asking for a valid zlib installation
+#   directory or --without-zlib.
+#
+#   The macro defines the symbol HAVE_LIBZ if the library is found. You
+#   should use autoheader to include a definition for this symbol in a
+#   config.h file. Sample usage in a C/C++ source is as follows:
+#
+#     #ifdef HAVE_LIBZ
+#     #include <zlib.h>
+#     #endif /* HAVE_LIBZ */
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Loic Dachary <loic at senga.org>
+#
+#   This program is free software; you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation; either version 2 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 7
+
+AU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB])
+AC_DEFUN([AX_CHECK_ZLIB],
+#
+# Handle user hints
+#
+[AC_MSG_CHECKING(if zlib is wanted)
+AC_ARG_WITH(zlib,
+[  --with-zlib=DIR root directory path of zlib installation [defaults to
+                    /usr/local or /usr if not found in /usr/local]
+  --without-zlib to disable zlib usage completely],
+[if test "$withval" != no ; then
+  AC_MSG_RESULT(yes)
+  if test -d "$withval"
+  then
+    ZLIB_HOME="$withval"
+  else
+    AC_MSG_WARN([Sorry, $withval does not exist, checking usual places])
+  fi
+else
+  AC_MSG_RESULT(no)
+fi],
+[AC_MSG_RESULT(yes)])
+
+ZLIB_HOME=/usr/local
+if test ! -f "${ZLIB_HOME}/include/zlib.h"
+then
+        ZLIB_HOME=/usr
+fi
+
+#
+# Locate zlib, if wanted
+#
+if test -n "${ZLIB_HOME}"
+then
+        ZLIB_OLD_LDFLAGS=$LDFLAGS
+        ZLIB_OLD_CPPFLAGS=$LDFLAGS
+        LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib"
+        CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include"
+        AC_LANG_SAVE
+        AC_LANG_C
+        AC_CHECK_LIB(z, inflateEnd, [zlib_cv_libz=yes], [zlib_cv_libz=no])
+        AC_CHECK_HEADER(zlib.h, [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no])
+        AC_LANG_RESTORE
+        if test "$zlib_cv_libz" = "yes" -a "$zlib_cv_zlib_h" = "yes"
+        then
+                #
+                # If both library and header were found, use them
+                #
+                AC_CHECK_LIB(z, inflateEnd)
+                AC_MSG_CHECKING(zlib in ${ZLIB_HOME})
+                AC_MSG_RESULT(ok)
+        else
+                #
+                # If either header or library was not found, revert and bomb
+                #
+                AC_MSG_CHECKING(zlib in ${ZLIB_HOME})
+                LDFLAGS="$ZLIB_OLD_LDFLAGS"
+                CPPFLAGS="$ZLIB_OLD_CPPFLAGS"
+                AC_MSG_RESULT(failed)
+                AC_MSG_ERROR(either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib)
+        fi
+fi
+
+])
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..f76e3b8
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,62 @@
+/* config.h.in.  Generated from configure.in by autoheader.  */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `z' library (-lz). */
+#undef HAVE_LIBZ
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+   to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
diff --git a/configure b/configure
new file mode 100755
index 0000000..fe54a7d
--- /dev/null
+++ b/configure
@@ -0,0 +1,5655 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.63 for Rniftilib configuration script 0.0.30.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&	 (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+	   done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+	 # Try only shells that exist, to save several forks.
+	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		{ ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+	       as_have_required=yes
+	       if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+	do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+	done
+	export CONFIG_SHELL
+	exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell bug-autoconf at gnu.org about your system,
+  echo including any error possibly output before this message.
+  echo This can help us improve future autoconf versions.
+  echo Configuration will now proceed without shell functions.
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='Rniftilib configuration script'
+PACKAGE_TARNAME='rniftilib-configuration-script'
+PACKAGE_VERSION='0.0.30'
+PACKAGE_STRING='Rniftilib configuration script 0.0.30'
+PACKAGE_BUGREPORT=''
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+INCLUDE
+LIBOBJS
+EGREP
+GREP
+CPP
+ac_ct_CC
+CFLAGS
+CC
+OBJEXT
+EXEEXT
+ac_ct_CXX
+CPPFLAGS
+LDFLAGS
+CXXFLAGS
+CXX
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_zlib
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CXX
+CXXFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CCC
+CC
+CFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)	ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { $as_echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { $as_echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2
+   { (exit 1); exit 1; }; } ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { $as_echo "$as_me: error: working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { $as_echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures Rniftilib configuration script 0.0.30 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root
+                          [DATAROOTDIR/doc/rniftilib-configuration-script]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of Rniftilib configuration script 0.0.30:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-zlib=DIR root directory path of zlib installation defaults to
+                    /usr/local or /usr if not found in /usr/local
+  --without-zlib to disable zlib usage completely
+
+Some influential environment variables:
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+Rniftilib configuration script configure 0.0.30
+generated by GNU Autoconf 2.63
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by Rniftilib configuration script $as_me 0.0.30, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  $as_echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:$LINENO:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:$LINENO:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+: ${R_HOME=`R RHOME`}
+if test -z "${R_HOME}"; then
+  echo "could not determine R_HOME"
+  exit 1
+fi
+CC=`"${R_HOME}/bin/R" CMD config CC`
+CFLAGS=`"${R_HOME}/bin/R" CMD config CFLAGS`
+CPPFLAGS=`"${R_HOME}/bin/R" CMD config CPPFLAGS`
+
+# Checks for programs.
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:$LINENO: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:$LINENO: checking for C++ compiler default output file name" >&5
+$as_echo_n "checking for C++ compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5
+$as_echo_n "checking whether the C++ compiler works... " >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CXXFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:$LINENO: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:$LINENO: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:$LINENO: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Checks for header files.
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:$LINENO: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+# Checks for libraries.
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ $as_echo "$as_me:$LINENO: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_inline=$ac_kw
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+
+# Checks for library functions.
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+for ac_header in stdlib.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5
+$as_echo_n "checking $ac_header usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5
+$as_echo_n "checking $ac_header presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+	       { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+
+fi
+as_val=`eval 'as_val=${'$as_ac_Header'}
+		 $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:$LINENO: checking for GNU libc compatible malloc" >&5
+$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
+if test "${ac_cv_func_malloc_0_nonnull+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_func_malloc_0_nonnull=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_malloc_0_nonnull=yes
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_func_malloc_0_nonnull=no
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_func_malloc_0_nonnull" >&5
+$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 1
+_ACEOF
+
+else
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_MALLOC 0
+_ACEOF
+
+   case " $LIBOBJS " in
+  *" malloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+cat >>confdefs.h <<\_ACEOF
+#define malloc rpl_malloc
+_ACEOF
+
+fi
+
+
+
+
+#
+# Handle user hints
+#
+{ $as_echo "$as_me:$LINENO: checking if zlib is wanted" >&5
+$as_echo_n "checking if zlib is wanted... " >&6; }
+
+# Check whether --with-zlib was given.
+if test "${with_zlib+set}" = set; then
+  withval=$with_zlib; if test "$withval" != no ; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+  if test -d "$withval"
+  then
+    ZLIB_HOME="$withval"
+  else
+    { $as_echo "$as_me:$LINENO: WARNING: Sorry, $withval does not exist, checking usual places" >&5
+$as_echo "$as_me: WARNING: Sorry, $withval does not exist, checking usual places" >&2;}
+  fi
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+else
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+
+
+ZLIB_HOME=/usr/local
+if test ! -f "${ZLIB_HOME}/include/zlib.h"
+then
+        ZLIB_HOME=/usr
+fi
+
+#
+# Locate zlib, if wanted
+#
+if test -n "${ZLIB_HOME}"
+then
+        ZLIB_OLD_LDFLAGS=$LDFLAGS
+        ZLIB_OLD_CPPFLAGS=$LDFLAGS
+        LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib"
+        CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include"
+
+        ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+        { $as_echo "$as_me:$LINENO: checking for inflateEnd in -lz" >&5
+$as_echo_n "checking for inflateEnd in -lz... " >&6; }
+if test "${ac_cv_lib_z_inflateEnd+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inflateEnd ();
+int
+main ()
+{
+return inflateEnd ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_z_inflateEnd=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_z_inflateEnd=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_inflateEnd" >&5
+$as_echo "$ac_cv_lib_z_inflateEnd" >&6; }
+if test "x$ac_cv_lib_z_inflateEnd" = x""yes; then
+  zlib_cv_libz=yes
+else
+  zlib_cv_libz=no
+fi
+
+        if test "${ac_cv_header_zlib_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for zlib.h" >&5
+$as_echo_n "checking for zlib.h... " >&6; }
+if test "${ac_cv_header_zlib_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+$as_echo "$ac_cv_header_zlib_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking zlib.h usability" >&5
+$as_echo_n "checking zlib.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <zlib.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking zlib.h presence" >&5
+$as_echo_n "checking zlib.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <zlib.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: zlib.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: zlib.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for zlib.h" >&5
+$as_echo_n "checking for zlib.h... " >&6; }
+if test "${ac_cv_header_zlib_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_zlib_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
+$as_echo "$ac_cv_header_zlib_h" >&6; }
+
+fi
+if test "x$ac_cv_header_zlib_h" = x""yes; then
+  zlib_cv_zlib_h=yes
+else
+  zlib_cv_zlib_h=no
+fi
+
+
+        ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+        if test "$zlib_cv_libz" = "yes" -a "$zlib_cv_zlib_h" = "yes"
+        then
+                #
+                # If both library and header were found, use them
+                #
+
+{ $as_echo "$as_me:$LINENO: checking for inflateEnd in -lz" >&5
+$as_echo_n "checking for inflateEnd in -lz... " >&6; }
+if test "${ac_cv_lib_z_inflateEnd+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lz  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inflateEnd ();
+int
+main ()
+{
+return inflateEnd ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_z_inflateEnd=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_z_inflateEnd=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_z_inflateEnd" >&5
+$as_echo "$ac_cv_lib_z_inflateEnd" >&6; }
+if test "x$ac_cv_lib_z_inflateEnd" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBZ 1
+_ACEOF
+
+  LIBS="-lz $LIBS"
+
+fi
+
+                { $as_echo "$as_me:$LINENO: checking zlib in ${ZLIB_HOME}" >&5
+$as_echo_n "checking zlib in ${ZLIB_HOME}... " >&6; }
+                { $as_echo "$as_me:$LINENO: result: ok" >&5
+$as_echo "ok" >&6; }
+        else
+                #
+                # If either header or library was not found, revert and bomb
+                #
+                { $as_echo "$as_me:$LINENO: checking zlib in ${ZLIB_HOME}" >&5
+$as_echo_n "checking zlib in ${ZLIB_HOME}... " >&6; }
+                LDFLAGS="$ZLIB_OLD_LDFLAGS"
+                CPPFLAGS="$ZLIB_OLD_CPPFLAGS"
+                { $as_echo "$as_me:$LINENO: result: failed" >&5
+$as_echo "failed" >&6; }
+                { { $as_echo "$as_me:$LINENO: error: either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib" >&5
+$as_echo "$as_me: error: either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib" >&2;}
+   { (exit 1); exit 1; }; }
+        fi
+fi
+
+
+
+
+
+ac_config_files="$ac_config_files src/Makevars"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+	test -d "$1/.";
+      else
+	case $1 in
+	-*)set "./$1";;
+	esac;
+	case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+	???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by Rniftilib configuration script $as_me 0.0.30, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTION]... [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf at gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+Rniftilib configuration script config.status 0.0.30
+configured by $0, generated by GNU Autoconf 2.63,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    CONFIG_FILES="$CONFIG_FILES '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { $as_echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { $as_echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;;
+
+  *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   $as_echo "$as_me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr='
'
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5
+$as_echo "$as_me: error: could not setup config files machinery" >&2;}
+   { (exit 1); exit 1; }; }
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[	 ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  { { $as_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5
+$as_echo "$as_me: error: could not setup config headers machinery" >&2;}
+   { (exit 1); exit 1; }; }
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5
+$as_echo "$as_me: error: invalid tag $ac_tag" >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      ac_file_inputs="$ac_file_inputs '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:$LINENO: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; } ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+	|| { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5
+$as_echo "$as_me: error: could not create -" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+ ;;
+
+
+  esac
+
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/debian/README.test b/debian/README.test
deleted file mode 100644
index f994348..0000000
--- a/debian/README.test
+++ /dev/null
@@ -1,7 +0,0 @@
-r-cran-niftilib for Debian
---------------------------
-
-This package can be tested by loading it into R with the command
-'library(Rniftilib)' in order to confirm its integrity.
-
- -- Andreas Tille <tille at debian.org>  Wed, 24 Jul 2013 08:14:10 +0200
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 9ceb995..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,5 +0,0 @@
-r-cran-rniftilib (0.0-32-1) unstable; urgency=low
-
-  * Initial release (closes: #717715)
-
- -- Andreas Tille <tille at debian.org>  Wed, 24 Jul 2013 08:14:10 +0200
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index ec63514..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-9
diff --git a/debian/control b/debian/control
deleted file mode 100644
index d60f881..0000000
--- a/debian/control
+++ /dev/null
@@ -1,19 +0,0 @@
-Source: r-cran-rniftilib
-Section: gnu-r
-Priority: optional
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Andreas Tille <tille at debian.org>
-Build-Depends: debhelper (>= 9), r-base-dev, cdbs
-Standards-Version: 3.9.4
-Homepage: http://cran.r-project.org/web/packages/Rniftilib
-Vcs-Browser: http://anonscm.debian.org/viewvc/debian-med/trunk/packages/R/r-cran-rniftilib/trunk/
-Vcs-Svn: svn://anonscm.debian.org/debian-med/trunk/packages/R/r-cran-rniftilib/trunk/
-
-Package: r-cran-rniftilib
-Architecture: any
-Depends: ${shlibs:Depends},
-         ${misc:Depends},
-         ${R:Depends}
-Description: GNU/R interface to NIFTICLIB
- R interface to nifticlib (nifticlib-2.0.0) (read/write
- ANALYZE(TM)7.5/NIfTI-1 volume images)
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index 2cd903b..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,28 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: Rniftilib
-Source: http://cran.r-project.org/src/contrib/
-
-Files: *
-Copyright: 2011-2013 Oliver Granert <o.granert at neurologie.uni-kiel.de>
-License: GPL-2.0+
-
-Files: debian/*
-Copyright: 2013 Andreas Tille <tille at debian.org>
-License: GPL-2.0+
-
-License: GPL-2.0+
- This package is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- .
- This package is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- GNU General Public License for more details.
- .
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
- .
- On Debian systems, the complete text of the GNU General
- Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index f1e58a0..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-
-### unfortunately this does not enable hardening
-# export DEB_BUILD_MAINT_OPTIONS = hardening=+all
-# DPKG_EXPORT_BUILDFLAGS = 1
-# include /usr/share/dpkg/buildflags.mk
-
-include /usr/share/R/debian/r-cran.mk
-
-get-orig-source:
-	mkdir -p ../tarballs
-	uscan --verbose --force-download --destdir=../tarballs
diff --git a/debian/source/format b/debian/source/format
deleted file mode 100644
index 163aaf8..0000000
--- a/debian/source/format
+++ /dev/null
@@ -1 +0,0 @@
-3.0 (quilt)
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index ad73784..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,2 +0,0 @@
-version=3
-http://cran.r-project.org/src/contrib/Rniftilib_([\d.-]*)\.tar\.gz
diff --git a/man/nifti.Rd b/man/nifti.Rd
new file mode 100644
index 0000000..43c43de
--- /dev/null
+++ b/man/nifti.Rd
@@ -0,0 +1,126 @@
+\name{nifti}
+\alias{nifti}
+\alias{[.nifti}
+\alias{dim.nifti}
+\alias{dim<-.nifti}
+\alias{$.nifti}
+\alias{print.nifti}
+\alias{plot.nifti}
+\alias{[<-.nifti}
+\alias{$<-.nifti}
+\alias{is.nifti}
+\alias{nifti.image.getdim.save}
+\title{NIfTI object}
+\description{
+  A NIfTI object contains the image description and data of an image
+  volume.
+  Voxels can be accessed by the bracket [dim1,dim2,dim3,...,dim7] operator.
+}
+\usage{
+  \method{[}{nifti}(x,
+       dim1=1:nifti.image.getdim.save(x,1),
+       dim2=1:nifti.image.getdim.save(x,2),
+       dim3=1:nifti.image.getdim.save(x,3),
+       dim4=1:nifti.image.getdim.save(x,4),
+       dim5=1:nifti.image.getdim.save(x,5),
+       dim6=1:nifti.image.getdim.save(x,6),
+       dim7=1:nifti.image.getdim.save(x,7))      
+  \method{$}{nifti}(x, sym)
+  \method{dim}{nifti}(x)
+  \method{print}{nifti}(x,...)
+  \method{plot}{nifti}(x, dim1=1:nifti.image.getdim.save(x,1), dim2=1:nifti.image.getdim.save(x,2),dim3=1, dim4=1,...)
+  is.nifti(x)
+}
+\arguments{
+  \item{x}{NIfTI image object (class nifti)}
+  \item{sym}{  \tabular{rl}{
+  \code{qto.xyz}\tab voxel to mm transformation (R style indexing!)\cr 
+  \code{qto.ijk}\tab mm to voxel transformation (R style indexing!)\cr
+  \code{sto.xyz}\tab voxel to mm transformation (R style indexing!)\cr
+  \code{sto.ijk}\tab mm to voxel transformation (R style indexing!)\cr
+  \code{qto_xyz}\tab voxel to mm transformation (C style indexing!)\cr 
+  \code{qto_ijk}\tab mm to voxel transformation (C style indexing!)\cr
+  \code{sto_xyz}\tab voxel to mm transformation (C style indexing!)\cr
+  \code{sto_ijk}\tab mm to voxel transformation (C style indexing!)\cr
+  \code{toffset}\tab \cr
+  \code{descrip}\tab description (up to 80 characters)\cr
+  \code{fname}\tab header filename (store image information)\cr
+  \code{iname}\tab image filename (store image data)\cr
+  \code{slice.duration}\tab time for 1 slice\cr
+  \code{qform.code}\tab \code{NIFTI.XFORM.UNKNOWN} (0) \cr
+                   \tab \code{NIFTI.XFORM.SCANNER.ANAT} (1) \cr
+                   \tab \code{NIFTI.XFORM.ALIGNED.ANAT} (2) \cr
+                   \tab \code{NIFTI.XFORM.TALAIRACH} (3) \cr
+                   \tab \code{NIFTI.XFORM.MNI.152} (4)\cr
+                   \tab \code{qform code: >No<} for unknown tags \cr
+  \code{sform.code}\tab \code{NIFTI.XFORM.UNKNOWN} (0) \cr
+                   \tab \code{NIFTI.XFORM.SCANNER.ANAT} (1)\cr
+                   \tab \code{NIFTI.XFORM.ALIGNED.ANAT} (2)\cr
+                   \tab \code{NIFTI.XFORM.TALAIRACH} (3) \cr
+                   \tab \code{NIFTI.XFORM.MNI.152} (4) \cr
+                   \tab \code{sform code: >No<} for unknown tags \cr
+  \code{quatern.b}\tab \cr
+  \code{quatern.c}\tab \cr
+  \code{quatern.d}\tab \cr
+  \code{qoffset.x}\tab \cr
+  \code{qoffset.y}\tab \cr
+  \code{qoffset.z}\tab \cr
+  \code{qfac}\tab \cr
+  \code{dim}\tab image volume size in voxel \cr
+  \code{pixdim}\tab grid spacings. \cr
+  \code{datatype}\tab data type (set also field \code{nbyper})\cr
+  \code{nbyper}\tab bytes per voxel, matches datatype (read only) \cr
+  \code{nifti.type}\tab \code{NIFTI.FTYPE.ANALYZE} (0)  : .hdr + .img  files \cr
+                   \tab \code{NIFTI.FTYPE.NIFTI1.1}(1)  : .nii file \cr
+                   \tab \code{NIFTI.FTYPE.NIFTI1.2} (2) : .hdr + .img files \cr
+                   \tab \code{NIFTI.FTYPE.ASCII} (3)    : ? \cr
+  \code{sizeof_hdr}\tab MUST be 348\cr
+  \code{scl.slope} \tab nifti1: Data scaling: slope.  analyze 7.5: float funused1 \cr
+  \code{scl.inter} \tab nifti1: Data scaling: offset. analyze 7.5: float funused2 \cr
+  \code{xyz_units} \tab \code{NIFTI_UNITS_UNKNOWN} ""     (0) \cr
+                   \tab \code{NIFTI_UNITS_METER}  "m"     (1) \cr
+                   \tab \code{NIFTI_UNITS_MM}     "mm"    (2) \cr     
+                   \tab \code{NIFTI_UNITS_MICRON} "um"    (3) \cr
+                   \tab \code{NIFTI_UNITS_SEC}    "s"     (8) \cr
+                   \tab \code{NIFTI_UNITS_MSEC}   "ms"    (16) \cr
+                   \tab \code{NIFTI_UNITS_USEC}   "us"    (24) \cr
+                   \tab \code{NIFTI_UNITS_HZ}     "Hz"    (32) \cr
+                   \tab \code{NIFTI_UNITS_PPM}    "ppm"   (40) \cr
+                   \tab \code{NIFTI_UNITS_RADS}   "rad/s" (48) \cr
+                   \tab see also \code{\link{nifti.units.string}}\cr                   
+  \code{time_units}\tab \code{NIFTI_UNITS_UNKNOWN} ""     (0) \cr
+                   \tab \code{NIFTI_UNITS_METER}  "m"     (1) \cr
+                   \tab \code{NIFTI_UNITS_MM}     "mm"    (2) \cr     
+                   \tab \code{NIFTI_UNITS_MICRON} "um"    (3) \cr
+                   \tab \code{NIFTI_UNITS_SEC}    "s"     (8) \cr
+                   \tab \code{NIFTI_UNITS_MSEC}   "ms"    (16) \cr
+                   \tab \code{NIFTI_UNITS_USEC}   "us"    (24) \cr
+                   \tab \code{NIFTI_UNITS_HZ}     "Hz"    (32) \cr
+                   \tab \code{NIFTI_UNITS_PPM}    "ppm"   (40) \cr
+                   \tab \code{NIFTI_UNITS_RADS}   "rad/s" (48) \cr
+                   \tab see also \code{\link{nifti.units.string}}
+  }}
+  \item{dim1}{vector of voxel indices (x)}
+  \item{dim2}{vector of voxel indices (y)}
+  \item{dim3}{vector of voxel indices (z)}
+  \item{dim4}{vector of voxel indices (t)}
+  \item{dim5}{vector of voxel indices}
+  \item{dim6}{vector of voxel indices}
+  \item{dim7}{vector of voxel indices}
+  \item{...}{additional arguments for plotting (e.g. \code{\link{image}}) and printing}
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+\seealso{ 
+  \code{\link{nifti.image.read}},
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.new}}
+}
+\keyword{package}
+\keyword{data}
+\keyword{manip}
diff --git a/man/nifti_compiled_with_zlib.Rd b/man/nifti_compiled_with_zlib.Rd
new file mode 100644
index 0000000..0ca2da7
--- /dev/null
+++ b/man/nifti_compiled_with_zlib.Rd
@@ -0,0 +1,28 @@
+\name{nifti.compiled.with.zlib}
+\alias{nifti.compiled.with.zlib}
+\title{Check support for compressed NIfTI files.}
+\description{
+Return whether the given Rniftilib C-library was compiled with \code{HAVE_ZLIB} set.
+}
+\usage{
+nifti.compiled.with.zlib()
+}
+\value{
+ \item{TRUE}{library supports compressed files (.gz)} 
+ \item{FALSE}{compressed files are not supported} 
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\seealso{ 
+  \code{\link{nifti.image.new}},
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+}
+
+\examples{
+nifti.compiled.with.zlib() # return logical value (TRUE or FALSE)
+}
+\keyword{manip}
+\keyword{data}
\ No newline at end of file
diff --git a/man/nifti_datatype_string.Rd b/man/nifti_datatype_string.Rd
new file mode 100644
index 0000000..f31f8d0
--- /dev/null
+++ b/man/nifti_datatype_string.Rd
@@ -0,0 +1,31 @@
+\name{nifti.datatype.string}
+\alias{nifti.datatype.string}
+\title{Return string for NIfTI-1 datatype code value.}
+\description{
+Return a string for the datatype of a NIFTI data type.
+}
+\usage{
+nifti.datatype.string(value) 
+}
+\arguments{
+ \item{value}{NIfTI-1 datatype}
+}
+\details{
+Return a string for the datatype of a NIFTI data type (e.g. "INT8" signed integer data type).   
+}
+\value{
+String for the given data type value.
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+
+\seealso{ 
+  \code{\link{nifti.units.string}},
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+}
+
+\keyword{manip}
+\keyword{data}
diff --git a/man/nifti_disp_lib_version.Rd b/man/nifti_disp_lib_version.Rd
new file mode 100644
index 0000000..1951972
--- /dev/null
+++ b/man/nifti_disp_lib_version.Rd
@@ -0,0 +1,24 @@
+\name{nifti.disp.lib.version}
+\alias{nifti.disp.lib.version}
+\title{NIfTI library version.}
+\description{
+Return NIfTI library version and date as a character string.
+}
+\usage{
+nifti.disp.lib.version()
+}
+\value{
+ String containing library version and compilation date.
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\seealso{ 
+  \code{\link{nifti.image.new}},
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+}
+\keyword{manip}
+\keyword{data}
+
diff --git a/man/nifti_image_alloc_data.Rd b/man/nifti_image_alloc_data.Rd
new file mode 100644
index 0000000..d995a10
--- /dev/null
+++ b/man/nifti_image_alloc_data.Rd
@@ -0,0 +1,35 @@
+\name{nifti.image.alloc.data}
+\alias{nifti.image.alloc.data}
+\title{Allocate data block for NIfTI image}
+\description{
+Allocate data block for NIfTI image using the information from the header.
+}
+\usage{
+nifti.image.alloc.data(nim)
+}
+\arguments{
+  \item{nim}{the nifti object}
+}
+\details{
+  The function return the number of bytes allocated.
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+
+\seealso{ 
+  \code{\link{nifti.image.new}},
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+}
+
+\examples{
+nim=nifti.image.new()
+no.of.bytes=nifti.image.alloc.data(nim)
+}
+\keyword{manip}
+\keyword{data}
diff --git a/man/nifti_image_copy_info.Rd b/man/nifti_image_copy_info.Rd
new file mode 100644
index 0000000..6d08cbf
--- /dev/null
+++ b/man/nifti_image_copy_info.Rd
@@ -0,0 +1,36 @@
+\name{nifti.image.copy.info}
+\alias{nifti.image.copy.info}
+\title{Copy NIFTI image (info) without voxel data.}
+\description{
+Copy the nifti.image structure, without data.
+
+Duplicate the structure, including fname, iname and extensions.
+Leave the data pointer as NULL.
+}
+\usage{
+nifti.image.copy.info(nim) 
+}
+\arguments{
+ \item{nim}{the nifti object}
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+
+\seealso{ 
+  \code{\link{nifti.image.new}},
+  \code{\link{nifti.image.read}},
+  \code{\link{nifti.image.write}}
+}
+
+\examples{
+\dontrun{
+nim <- nifti.image.read(file.choose())
+nim_copy <- nifti.image.copy.info(nim)
+}
+}
+\keyword{manip}
diff --git a/man/nifti_image_free.Rd b/man/nifti_image_free.Rd
new file mode 100644
index 0000000..9636ec3
--- /dev/null
+++ b/man/nifti_image_free.Rd
@@ -0,0 +1,32 @@
+\name{nifti.image.free}
+\alias{nifti.image.free}
+\title{Free NIfTI image data structure}
+\description{
+Free image data (everything!).
+}
+\usage{
+nifti.image.free(nim) 
+}
+\arguments{
+ \item{nim}{the nifti object}
+}
+\details{
+Free 'everything' about a nifti struct (including the passed struct):
+(fname and iname, data, extensions, nim)
+}
+\value{
+A \code{\link{nifti}} object
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+
+\seealso{ 
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+  \code{\link{nifti.image.unload}}
+}
+
+\keyword{manip}
+\keyword{data}
\ No newline at end of file
diff --git a/man/nifti_image_new.Rd b/man/nifti_image_new.Rd
new file mode 100644
index 0000000..9b9cd5f
--- /dev/null
+++ b/man/nifti_image_new.Rd
@@ -0,0 +1,36 @@
+\name{nifti.image.new}
+\alias{nifti.image.new}
+\title{Create new NIfTI image}
+\description{
+  Basic initialization of a nifti.image structure (to a 1x1x1 image)
+}
+\usage{
+nifti.image.new() 
+}
+\details{
+Creates an image of size 1x1x1. 
+}
+\value{
+A \code{\link{nifti}} object
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+
+\seealso{ 
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+}
+
+\examples{
+# create 1x1x1 nifti volume
+nim=nifti.image.new() 
+# resize nifti volume to 15x15x15 
+nim$dim<-c(15,15,15) 
+}
+\keyword{manip}
+\keyword{data}
diff --git a/man/nifti_image_read.Rd b/man/nifti_image_read.Rd
new file mode 100644
index 0000000..9d0a6f6
--- /dev/null
+++ b/man/nifti_image_read.Rd
@@ -0,0 +1,50 @@
+\name{nifti.image.read}
+\alias{nifti.image.read}
+\title{Read data from NIfTI (Analyze) files}
+\description{
+  This function reads the meta and image data from a nifti file.
+}
+\usage{
+nifti.image.read(file, read_data=1, rm.NaN=TRUE) 
+}
+\arguments{
+  \item{file}{name of the nifti file}
+  \item{read_data}{0=do not read image data, 1=read image data}
+  \item{rm.NaN}{logical value indicating whether NA and NaN values should be stripped (default in niftilib C library)}
+}
+\details{
+If \code{read_data=0} only the header info is loaded.  
+}
+\value{
+\code{\link{nifti}} object
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+
+\seealso{ 
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.new}}
+}
+\examples{
+\dontrun{
+nim <- nifti.image.read(file.choose())
+# access to attributes...
+nim$qto.xyz        # voxel to mm transformation matrix (q-form)
+nim$qto.ijk        # mm to voxel transformation matrix (q-form)
+nim$sto.xyz        # voxel to mm transformation matrix (s-form)
+nim$sto.ijk        # mm to voxel transformation matrix (s-form)
+nim$toffset        #
+nim$descrip        # description
+nim$fname          # header filename (store image information)
+nim$iname          # image filename (store image data)
+nim$slice.duration
+# access to voxel values...
+nim[10,11,12]      # voxel value at x=10, y=11, z=12
+}
+}
+\keyword{IO}
diff --git a/man/nifti_image_setdatatype.Rd b/man/nifti_image_setdatatype.Rd
new file mode 100644
index 0000000..a0035cf
--- /dev/null
+++ b/man/nifti_image_setdatatype.Rd
@@ -0,0 +1,69 @@
+\name{nifti.image.setdatatype}
+\alias{nifti.image.setdatatype}
+\title{Change data type of nifti object.}
+\description{
+Set \code{datatype} and \code{nbyper} fields.
+}
+\usage{
+nifti.image.setdatatype(nim, value)
+}
+\arguments{
+  \item{nim}{ nifti image object }
+  \item{value}{data type as string, e.g. "NIFTI_TYPE_UINT8", or numeric type id, e.g. 2. See details section for a list of possible values.}
+}
+\details{
+\tabular{rcl}{
+\bold{original ANALYZE 7.5 type codes} \tab \bold{numeric type id} \tab \bold{description} \cr
+\code{DT_NONE}         \tab 0 \tab   unknown/none data format\cr
+\code{DT_UNKNOWN}      \tab 0 \tab   unknown/none data format \cr         
+\code{DT_BINARY}       \tab 1 \tab   binary (1 bit/voxel) \cr       
+\code{DT_UNSIGNED_CHAR}\tab 2 \tab   unsigned char (8 bits/voxel) \cr
+\code{DT_SIGNED_SHORT} \tab 4 \tab   signed short (16 bits/voxel) \cr
+\code{DT_SIGNED_INT}   \tab 8 \tab   signed int (32 bits/voxel)   \cr
+\code{DT_FLOAT}        \tab 16 \tab  float (32 bits/voxel) \cr
+\code{DT_COMPLEX}      \tab 32 \tab  complex (64 bits/voxel) \cr
+\code{DT_DOUBLE}       \tab 64 \tab  double (64 bits/voxel) \cr
+\code{DT_RGB}          \tab 128 \tab RGB triple (24 bits/voxel) \cr
+\code{DT_ALL}          \tab 255 \tab not very useful (?) \cr
+ \tab \tab \cr
+\code{DT_UINT8}        \tab 2 \tab \cr
+\code{DT_INT16}        \tab 4 \tab \cr
+\code{DT_INT32}        \tab 8 \tab \cr
+\code{DT_FLOAT32}      \tab 16 \tab \cr
+\code{DT_COMPLEX64}    \tab 32 \tab \cr
+\code{DT_FLOAT64}      \tab 64 \tab \cr
+\code{DT_RGB24}        \tab 128 \tab \cr
+ \tab \tab \cr
+\code{DT_INT8}         \tab 256 \tab signed char (8 bits) \cr
+\code{DT_UINT16}       \tab 512 \tab unsigned short (16 bits) \cr
+\code{DT_UINT32}       \tab 768 \tab unsigned int (32 bits) \cr
+\code{DT_INT64}        \tab 1024 \tab long long (64 bits) \cr
+\code{DT_UINT64}       \tab 1280 \tab unsigned long long (64 bits) \cr
+\code{DT_FLOAT128}     \tab 1536 \tab long double (128 bits) \cr
+\code{DT_COMPLEX128}   \tab 1792 \tab double pair (128 bits) \cr
+\code{DT_COMPLEX256}   \tab 2048 \tab long double pair (256 bits) \cr
+\code{DT_RGBA32}       \tab 2304 \tab 4 byte RGBA (32 bits/voxel) \cr
+\bold{new codes for NIFTI} \tab \tab \cr
+\code{NIFTI_TYPE_UINT8}      \tab 2 \tab unsigned char \cr
+\code{NIFTI_TYPE_INT16}      \tab 4 \tab signed short \cr 
+\code{NIFTI_TYPE_INT32}      \tab 8 \tab signed int \cr
+\code{NIFTI_TYPE_FLOAT32}    \tab 16 \tab 32 bit float \cr
+\code{NIFTI_TYPE_COMPLEX64}  \tab 32 \tab 64 bit complex = 2x32 bit floats \cr
+\code{NIFTI_TYPE_FLOAT64}    \tab 64 \tab 64 bit float = double \cr
+\code{NIFTI_TYPE_RGB24}      \tab 128 \tab 3x8 bit bytes \cr
+\code{NIFTI_TYPE_INT8}       \tab 256 \tab signed char \cr
+\code{NIFTI_TYPE_UINT16}     \tab 512 \tab unsigned short \cr
+\code{NIFTI_TYPE_UINT32}     \tab 768 \tab unsigned int \cr 
+\code{NIFTI_TYPE_INT64}      \tab 1024 \tab signed long long \cr
+\code{NIFTI_TYPE_UINT64}     \tab 1280 \tab unsigned long long. \cr
+\code{NIFTI_TYPE_FLOAT128}   \tab 1536 \tab 128 bit float = long double \cr
+\code{NIFTI_TYPE_COMPLEX128} \tab 1792 \tab 128 bit complex = 2 64 bit floats \cr
+\code{NIFTI_TYPE_COMPLEX256} \tab 2048 \tab 256 bit complex = 2 128 bit floats \cr
+\code{NIFTI_TYPE_RGBA32}     \tab 2304 \tab 4x8 bit bytes (32bits/voxel) \cr
+}}
+\seealso{ 
+  \code{\link{nifti.image.unload}},
+  \code{\link{nifti.image.alloc.data}}
+}
+ 
+\keyword{IO}
diff --git a/man/nifti_image_unload.Rd b/man/nifti_image_unload.Rd
new file mode 100644
index 0000000..5330064
--- /dev/null
+++ b/man/nifti_image_unload.Rd
@@ -0,0 +1,31 @@
+\name{nifti.image.unload}
+\alias{nifti.image.unload}
+\title{Unload NIfTI image data}
+\description{
+Unload the image data in nifti struct, but keep the metadata.
+}
+\usage{
+nifti.image.unload(nim) 
+}
+\arguments{
+ \item{nim}{the nifti object}
+}
+\details{
+Unload image data, but keep header information and other metadata.
+}
+\value{
+A \code{\link{nifti}} object
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+
+\seealso{ 
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+  \code{\link{nifti.image.free}}
+}
+
+\keyword{manip}
+\keyword{data}
\ No newline at end of file
diff --git a/man/nifti_image_write.Rd b/man/nifti_image_write.Rd
new file mode 100644
index 0000000..32df131
--- /dev/null
+++ b/man/nifti_image_write.Rd
@@ -0,0 +1,32 @@
+\name{nifti.image.write}
+\alias{nifti.image.write}
+\title{Write data to NIfTI (Analyze) files}
+\description{
+  This function writes volume data to a NIfTI file.
+}
+\usage{
+nifti.image.write(nim) 
+}
+\arguments{
+  \item{nim}{the nifti object}
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+
+\seealso{
+  \code{\link{nifti.image.read}},
+  \code{\link{nifti.image.new}}
+}
+
+\examples{
+\dontrun{
+nim <- nifti.image.read(file.choose())
+nifti.image.write(nim)
+}
+}
+\keyword{IO}
diff --git a/man/nifti_interpolate3D.Rd b/man/nifti_interpolate3D.Rd
new file mode 100644
index 0000000..8ceed9a
--- /dev/null
+++ b/man/nifti_interpolate3D.Rd
@@ -0,0 +1,42 @@
+\name{nifti.interpolate3d}
+\alias{nifti.interpolate3d}
+\title{Interpolation between voxels}
+\description{
+  This function interpolates in 3d between voxels (in volume data).
+}
+\usage{
+nifti.interpolate3d(nim, x, y, z, t=1) 
+}
+\arguments{
+  \item{nim}{the nifti object}
+  \item{x}{x coordinate (subpixel/floating point)}
+  \item{y}{y coordinate (subpixel/floating point)}
+  \item{z}{z coordinate (subpixel/floating point)}
+  \item{t}{t coordinate (subpixel/floating point)}
+}
+\references{
+\url{http://nifti.nimh.nih.gov}
+\url{http://niftilib.sourceforge.net}
+}
+\author{
+Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+
+\seealso{
+  \code{\link{nifti.image.read}},
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.new}}
+}
+
+\examples{
+\dontrun{
+nim <- nifti.image.read(file.choose())
+plot(c(nifti.interpolate3d(nim,100,100,3),
+       nifti.interpolate3d(nim,100.25,100,3),
+       nifti.interpolate3d(nim,100.5,100,3),
+       nifti.interpolate3d(nim,100.75,100,3),
+       nifti.interpolate3d(nim,101,100,3)),
+       xlab="position x", ylab="interpolation")
+}
+}
+\keyword{utilities}
diff --git a/man/nifti_read_subregion_image.Rd b/man/nifti_read_subregion_image.Rd
new file mode 100644
index 0000000..e57e58a
--- /dev/null
+++ b/man/nifti_read_subregion_image.Rd
@@ -0,0 +1,43 @@
+\name{nifti.read.subregion.image}
+\alias{nifti.read.subregion.image}
+\title{Read a subregion from a NIfTI image}
+\description{
+EXPERIMENTAL (unstable interface!): Read a single arbitary subregion of any rectangular size from a NIfTI dataset.
+}
+\usage{
+nifti.read.subregion.image(nim, start_index, region_size)
+}
+\arguments{
+ \item{nim}{the nifti object}
+ \item{start_index}{start_index the index location of the first voxel that will be returned}
+ \item{region_size}{region_size the size of the subregion to be returned}
+}
+\details{
+ This function may be used to read a single arbitary subregion of any
+ rectangular size from a nifti dataset, such as a small 5x5x5 subregion
+ around the center of a 3D image.
+
+    Example: given  nim$dim = c(64, 64, 64) (3-D dataset)
+
+      if start_index = c( 29,  29, 29) and
+         region_size = c( 5,   5,  5)
+         -> read 5x5x5 region starting with the first voxel location at (29,29,29)
+}
+\value{
+The subregion data in a vector.
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+
+\seealso{ 
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+}
+
+\keyword{manip}
+\keyword{data}
diff --git a/man/nifti_set_filenames.Rd b/man/nifti_set_filenames.Rd
new file mode 100644
index 0000000..ffc27ae
--- /dev/null
+++ b/man/nifti_set_filenames.Rd
@@ -0,0 +1,38 @@
+\name{nifti.set.filenames}
+\alias{nifti.set.filenames}
+\title{Set filenames for a NIFTI image}
+\description{
+  Set filenames (image and header filename) for a NIfTI image.
+}
+\usage{
+nifti.set.filenames(nim, prefix, check=1, set_byte_order=1)
+}
+\arguments{
+  \item{nim}{the nifti object}
+  \item{prefix}{(required) prefix for output filenames}
+  \item{check}{check for previous existence of filename (existence is an
+    error condition)}
+  \item{set_byte_order}{flag to set nim->byteorder here (if
+    set\_byte\_order=1 then byteorder is set based on the CPU type)}
+}
+
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+\author{
+  Oliver Granert <o.granert <at> neurologie.uni-kiel.de>
+}
+\seealso{ 
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}},
+  \code{\link{nifti.image.new}}
+}
+\examples{
+nim <- nifti.image.new()
+nifti.set.filenames(nim, "testvolume")
+# show the result
+nim$fname
+nim$iname
+}
+\keyword{manip}
diff --git a/man/nifti_units_string.Rd b/man/nifti_units_string.Rd
new file mode 100644
index 0000000..0307dc4
--- /dev/null
+++ b/man/nifti_units_string.Rd
@@ -0,0 +1,31 @@
+\name{nifti.units.string}
+\alias{nifti.units.string}
+\title{Return string for NIfTI-1 unit code value.}
+\description{
+Return a string holding the name of a NIFTI units type.
+}
+\usage{
+nifti.units.string(value) 
+}
+\arguments{
+ \item{value}{NIfTI-1 unit code}
+}
+\details{
+Return a string holding the name of a NIFTI units type.    
+}
+\value{
+String for the given unit type value.
+}
+\references{
+  \url{http://nifti.nimh.nih.gov}
+  \url{http://niftilib.sourceforge.net}
+}
+
+\seealso{ 
+  \code{\link{nifti.datatype.string}},
+  \code{\link{nifti.image.write}},
+  \code{\link{nifti.image.read}}
+}
+
+\keyword{manip}
+\keyword{data}
diff --git a/src/Makevars.in b/src/Makevars.in
new file mode 100644
index 0000000..f5c4f1c
--- /dev/null
+++ b/src/Makevars.in
@@ -0,0 +1,2 @@
+PKG_CPPFLAGS=-I.. @CFLAGS@ @CPPFLAGS@ @INCLUDE@ @DEFS@
+PKG_LIBS=@LDFLAGS@ @LIBS@
diff --git a/src/Rnifti.c b/src/Rnifti.c
new file mode 100644
index 0000000..6ace6f1
--- /dev/null
+++ b/src/Rnifti.c
@@ -0,0 +1,1687 @@
+#include "nifti1_io.h"   /* directly include I/O library functions */
+#include "nifti1.h"
+#include <R.h>
+#include <Rdefines.h>
+
+//#include "International.h"
+
+extern char *gni_version;
+
+SEXP NIFTI_type_tag;
+#define SEXP2NIFTI(nim) ((TYPEOF(nim) != EXTPTRSXP || R_ExternalPtrTag(nim) != NIFTI_type_tag)?NULL:(nifti_image *)R_ExternalPtrAddr(nim))
+
+SEXP Rnifti_image_setdatatype(SEXP nim, SEXP value);
+
+/*
+  library(Rniftilib)
+  a=nifti_image_read("C:\\ffmri_L2409-00001-00001-0.img")
+
+  for(s in 1:(dim(a)[2])) image(a[1,s,,],col=gray(1:255/255))
+  for(s in 1:(dim(a)[3])) image(a[1,,s,],col=gray(1:255/255))
+*/
+
+SEXP Rnifti_init(SEXP libpath)
+{
+  NIFTI_type_tag = install("NIFTI_TYPE_TAG");
+  return R_NilValue;
+}
+
+char *Rnifti_attributes[] =
+  {
+    "qto.xyz", 			/* 0 */
+    "qto.ijk", 			/* 1 */
+    "sto.xyz", 			/* 2 */
+    "sto.ijk", 			/* 3 */
+    "toffset", 			/* 4 */
+    "descrip", 			/* 5 */
+    "fname",   			/* 6 */
+    "iname",   			/* 7 */
+    "slice.duration", 	/* 8 */
+    "qform.code", 		/* 9 */
+    "sform.code", 		/* 10 */
+    "quatern.b", 		/* 11 */
+    "quatern.c", 		/* 12 */
+    "quatern.d", 		/* 13 */
+    "qoffset.x", 		/* 14 */
+    "qoffset.y", 		/* 15 */
+    "qoffset.z", 		/* 16 */
+    "qfac",			    /* 17 */
+    "pixdim",			/* 18 */
+    "nifti.type",		/* 19 */
+    "sizeof.hdr",	    /* 20 */
+    "datatype",         /* 21 */
+    "scl.slope",        /* 22 nifti1: Data scaling: slope.  analyze 7.5: float funused1; */
+    "scl.inter",        /* 23 nifti1: Data scaling: offset. analyze 7.5: float funused2; */
+    "qto_xyz", 			/* 24 */
+    "qto_ijk", 			/* 25 */
+    "sto_xyz", 			/* 26 */
+    "sto_ijk", 			/* 27 */
+    "dim",              /* 28 */
+    "nbyper",           /* 29 */
+    "xyz_units",	    /* 30 */
+    "time_units",       /* 31 */
+    NULL
+  };
+
+SEXP Rnifti_mat44_SEXP(mat44 *mat)
+{
+  SEXP ret_val;
+  int c,r;
+  PROTECT(ret_val = NEW_NUMERIC(4*4));
+  for(r=0;r<4;++r)
+    for(c=0;c<4;++c)
+      NUMERIC_POINTER(ret_val)[r+c*4]=(double)(mat->m[r][c]);
+
+  SEXP dim;
+  PROTECT(dim=NEW_INTEGER(2));
+  INTEGER_POINTER(dim)[0]=4;
+  INTEGER_POINTER(dim)[1]=4;
+  SET_DIM(ret_val,dim);
+
+  UNPROTECT(2);
+  return ret_val;
+}
+
+void Rnifti_SEXP_mat44(SEXP val,mat44 *mat)
+{
+  int c,r;
+  PROTECT(val = AS_NUMERIC(val));
+  if(LENGTH(val)==16)
+    {
+      for(r=0;r<4;++r)
+	for(c=0;c<4;++c)
+	  (mat->m[r][c])=(float)NUMERIC_POINTER(val)[r+c*4];
+    }
+  else
+    error("matrix must be 4x4\n");
+  UNPROTECT(1);
+}
+
+SEXP Rnifti_mat33_SEXP(mat33 *mat)
+{
+  SEXP ret_val;
+  int c,r;
+  PROTECT(ret_val = NEW_NUMERIC(4*4));
+  for(r=0;r<3;++r)
+    for(c=0;c<3;++c)
+      NUMERIC_POINTER(ret_val)[r+c*4]=(double)mat->m[r][c];
+
+  SEXP dim;
+  PROTECT(dim=NEW_INTEGER(2));
+  INTEGER_POINTER(dim)[0]=3;
+  INTEGER_POINTER(dim)[1]=3;
+  SET_DIM(ret_val,dim);
+
+  UNPROTECT(2);
+  return ret_val;
+}
+
+void Rnifti_SEXP_mat33(SEXP val,mat33 *mat)
+{
+  int c,r;
+  PROTECT(val = AS_NUMERIC(val));
+  if(LENGTH(val)==9)
+    {
+      for(r=0;r<3;++r)
+	for(c=0;c<3;++c)
+	  (mat->m[r][c])=(float)NUMERIC_POINTER(val)[r+c*4];
+    }
+  else
+    error("matrix must be 3x3\n");
+  UNPROTECT(1);
+}
+
+SEXP Rnifti_float_SEXP(float val)
+{
+  SEXP ret_val;
+  PROTECT(ret_val=NEW_NUMERIC(1));
+  NUMERIC_POINTER(ret_val)[0]=val;
+  UNPROTECT(1);
+  return ret_val;
+}
+
+void Rnifti_SEXP_float(SEXP val_sexp, float *val)
+{
+  PROTECT(val_sexp=AS_NUMERIC(val_sexp));
+  *val=(float)NUMERIC_POINTER(val_sexp)[0];
+  UNPROTECT(1);
+}
+
+SEXP Rnifti_int_SEXP(int val)
+{
+  SEXP ret_val;
+  PROTECT(ret_val=NEW_INTEGER(1));
+  INTEGER_POINTER(ret_val)[0]=val;
+  UNPROTECT(1);
+  return ret_val;
+}
+
+void Rnifti_SEXP_int(SEXP val_sexp, int *val)
+{
+  PROTECT(val_sexp=AS_INTEGER(val_sexp));
+  *val=(int)INTEGER_POINTER(val_sexp)[0];
+  UNPROTECT(1);
+}
+
+void Rnifti_SEXP_short(SEXP val_sexp, short *val)
+{
+  PROTECT(val_sexp=AS_INTEGER(val_sexp));
+  *val=(short)INTEGER_POINTER(val_sexp)[0];
+  UNPROTECT(1);
+}
+
+SEXP Rnifti_pchar_SEXP(const char* val)
+{
+  SEXP ret_val;
+  PROTECT(ret_val=NEW_CHARACTER(1));
+  if(val!=NULL)
+    SET_STRING_ELT(ret_val, 0, mkChar(val));
+  else
+    SET_STRING_ELT(ret_val, 0, mkChar(""));
+  UNPROTECT(1);
+  return ret_val;
+}
+
+void Rnifti_SEXP_pchar(SEXP val_sexp, char* val, int max_num)
+{
+  PROTECT(val_sexp=AS_CHARACTER(val_sexp));
+  const char *pcstring = CHAR(CHARACTER_POINTER(val_sexp)[0]);
+  if(strlen(pcstring)<max_num)
+    strcpy(val,pcstring);
+  else
+    error("character string to long\n");
+  UNPROTECT(1);
+}
+
+SEXP Rnifti_image_free(SEXP nim)
+{
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      /*Rprintf("Delete nifti %p\n",pnim);*/
+      nifti_image_free(pnim);
+      R_ClearExternalPtr(nim);
+    }
+  else
+    error("Rnifti_image_free: not a nifti pointer.\n");
+  return R_NilValue;
+}
+
+SEXP Rnifti_image_new()
+{
+  nifti_image *pnim;
+
+  /* create nifti image of size 1x1x1 */
+  pnim = nifti_simple_init_nim();
+
+  /*- if the data pointer is not yet set, get memory space for the image */
+  if( pnim->data == NULL )
+    {
+  	int ntot = nifti_get_volsize(pnim);
+    pnim->data = (void *)calloc(1,ntot) ;  /* create image memory */
+    if( pnim->data == NULL )
+    {
+        error("** failed to alloc %d bytes for image data\n",(int)ntot);
+    }
+  }
+
+  SEXP nim = R_MakeExternalPtr(pnim,NIFTI_type_tag, R_NilValue);
+  R_RegisterCFinalizer(nim,(R_CFinalizer_t) Rnifti_image_free);
+
+  /* set class attribute to nifti */
+  SEXP classattrib;
+  PROTECT(classattrib = allocVector(STRSXP, 1));
+  SET_STRING_ELT(classattrib, 0, mkChar("nifti"));
+  classgets(nim, classattrib);
+  UNPROTECT(1);
+  return nim;
+}
+
+SEXP Rnifti_image_alloc_data(SEXP nim)
+{
+  int ntot=0;
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim != NULL)
+    {
+      if( pnim->data != NULL )
+	{
+	  free(pnim->data);
+	  pnim->data = NULL;
+	}
+      /*- if the data pointer is not yet set, get memory space for the image */
+      if( pnim->data == NULL )
+	{
+	  ntot = nifti_get_volsize(pnim);
+	  pnim->data = (void *)calloc(1,ntot) ;  /* create image memory */
+	  if( pnim->data == NULL )
+	    {
+	      error("failed to alloc %d bytes for image data\n",(int)ntot);
+	    }
+	}
+    }
+  return Rnifti_int_SEXP(ntot);
+}
+
+SEXP Rnifti_image_unload(SEXP nim)
+{
+	nifti_image *pnim=SEXP2NIFTI(nim);
+	nifti_image_unload( pnim );
+	return nim;
+}
+
+/* EXPERIMENTAL function ...*/
+SEXP Rnifti_read_subregion_image(SEXP nim, SEXP start_index, SEXP region_index)
+{
+	SEXP ret_val=R_NilValue;
+        int i,region_size_in_voxel=0,region_size_in_bytes=0;
+	void *data=NULL;
+	SEXP start_index_sexp,region_index_sexp;
+
+	nifti_image *pnim=SEXP2NIFTI(nim);
+
+	PROTECT(start_index_sexp=AS_INTEGER(start_index));
+	PROTECT(region_index_sexp=AS_INTEGER(region_index));
+	if(LENGTH(start_index_sexp)<pnim->dim[0] || LENGTH(region_index)<pnim->dim[0])
+        { 
+          UNPROTECT(2); 
+          error("ERROR: start_index and region_index must have length >= no. of image dimensions!"); 
+          return ret_val;
+        }
+
+  	int *start_index_int=INTEGER_POINTER(start_index_sexp);
+  	int *region_index_int=INTEGER_POINTER(region_index_sexp);
+
+	for(i=0;i<pnim->dim[0];++i)
+           region_size_in_voxel=region_index_int[i]*region_size_in_voxel;
+	region_size_in_bytes=region_size_in_voxel*pnim->nbyper;
+
+	switch(pnim->datatype)
+        {
+		case DT_NONE:          
+		case DT_BINARY:        
+		case DT_UNSIGNED_CHAR: PROTECT(ret_val=NEW_CHARACTER(region_size_in_voxel)); data=(void*)CHARACTER_POINTER(ret_val); break;
+		case DT_SIGNED_INT:    PROTECT(ret_val=NEW_INTEGER(region_size_in_voxel)); data=(void*)INTEGER_POINTER(ret_val); break;
+		case DT_DOUBLE:        PROTECT(ret_val=NEW_NUMERIC(region_size_in_voxel)); data=(void*)NUMERIC_POINTER(ret_val); break;
+		case DT_INT8:          
+		case DT_UINT16:        
+		case DT_SIGNED_SHORT:  
+		case DT_UINT32:        
+		case DT_INT64: 	       
+		case DT_UINT64:	       
+		case DT_FLOAT:         
+		case DT_FLOAT128:      
+		case DT_COMPLEX:       
+		case DT_COMPLEX128:    
+		case DT_COMPLEX256:    
+		case DT_RGB: 	       
+		case DT_RGBA32:        
+		default: warning("Unsupported or unknown data type!"); break;
+	}
+	if(data!=NULL)
+        {
+	  if(region_size_in_bytes != nifti_read_subregion_image(pnim, start_index_int, region_index_int,&data ))
+  	    error("ERROR: calculated region size different from returned region size!"); 
+	  UNPROTECT(3);  // unprotect start_index_sexp and region_index_sexp and ret_val
+        }
+	else
+  	  UNPROTECT(2); // unprotect start_index_sexp and region_index_sexp
+	return ret_val;
+}
+
+SEXP Rnifti_set_filenames(SEXP nim, SEXP prefix, SEXP check, SEXP set_byte_order)
+{
+  SEXP ret_val=Rnifti_int_SEXP(1);
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      int icheck;
+      int iset_byte_order;
+      char prefix_buffer[500];
+
+      Rnifti_SEXP_pchar(prefix, prefix_buffer, 500);
+      Rnifti_SEXP_int(check, &icheck);
+      Rnifti_SEXP_int(set_byte_order, &iset_byte_order);
+      ret_val = Rnifti_int_SEXP(nifti_set_filenames( pnim, prefix_buffer, icheck, iset_byte_order));
+    }
+  return ret_val;
+}
+
+
+SEXP Rnifti_image_listattributes(SEXP nim)
+{
+  SEXP Rstring;
+  PROTECT( Rstring= NEW_CHARACTER(9));
+  int iIndex;
+  for(iIndex=0;Rnifti_attributes[iIndex]!=NULL;++iIndex)
+    SET_STRING_ELT(Rstring, iIndex, mkChar(Rnifti_attributes[iIndex]));
+  UNPROTECT(1);
+  return Rstring;
+}
+
+SEXP Rnifti_image_setattribute(SEXP nim, SEXP sym, SEXP value)
+{
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      SEXP Rstring;
+      PROTECT( Rstring= AS_CHARACTER(sym));
+      int iIndex;
+      for(iIndex=0;Rnifti_attributes[iIndex]!=NULL;++iIndex)
+	if(strcmp(Rnifti_attributes[iIndex],CHAR(STRING_ELT(Rstring,0)))==0)
+	  break;
+      UNPROTECT(1);
+      switch(iIndex)
+	{
+    case 0: /*qto.xyz*/
+	  //Rnifti_SEXP_mat44(value,&(pnim->qto_xyz));
+	  error("set attribute qto.xyz not implemented use qto_xyz!"); break;
+	case 1: /*qto.ijk*/
+	  //Rnifti_SEXP_mat44(value,&(pnim->qto_ijk)); break;
+	  error("set attribute qto.ijk not implemented use qto_ijk!"); break;
+	case 2: /*sto.xyz*/
+	  //Rnifti_SEXP_mat44(value,&(pnim->sto_xyz)); break;
+	  error("set attribute sto.xyz not implemented use sto_xyz!"); break;
+	case 3: /*sto.ijk*/
+	  //Rnifti_SEXP_mat44(value,&(pnim->sto_ijk)); break;
+	  error("set attribute sto.ijk not implemented use sto_ijk!"); break;
+  	case 24: /*qto_xyz*/
+  	  Rnifti_SEXP_mat44(value,&(pnim->qto_xyz)); break;
+  	case 25: /*qto_ijk*/
+  	  Rnifti_SEXP_mat44(value,&(pnim->qto_ijk)); break;
+  	case 26: /*sto_xyz*/
+  	  Rnifti_SEXP_mat44(value,&(pnim->sto_xyz)); break;
+  	case 27: /*sto_ijk*/
+  	  Rnifti_SEXP_mat44(value,&(pnim->sto_ijk)); break;
+	case 4: /*toffset*/
+	  Rnifti_SEXP_float(value,&pnim->toffset); break;
+	case 5: /*descrip*/
+	  Rnifti_SEXP_pchar(value,pnim->descrip,80); break;
+	case 6: /*fname*/
+	  /* Rnifti_SEXP_pchar(value,pnim->fname,0); break; */
+	  warning("Can not set this attribute directly! Please use the nifti.set.filenames function.\n"); break;
+	case 7: /*iname*/
+	  /* Rnifti_SEXP_pchar(value,pnim->iname,0); break; */
+	  warning("Can not set this attribute directly! Please use the nifti.set.filenames function.\n"); break;
+	case 8: /*slice_duration*/
+	  Rnifti_SEXP_float(value,&(pnim->slice_duration)); break;
+	case 9: /* qform.code */
+	  Rnifti_SEXP_int(value, &(pnim->qform_code)); break;
+	case 10: /* sform.code */
+	  Rnifti_SEXP_int(value, &(pnim->sform_code)); break;
+	case 11: /* quatern_b 11 */
+	  Rnifti_SEXP_float(value,&(pnim->quatern_b)); break;
+	case 12: /* quatern_c 12 */
+	  Rnifti_SEXP_float(value,&(pnim->quatern_c)); break;
+	case 13: /* quatern_d 13 */
+	  Rnifti_SEXP_float(value,&(pnim->quatern_d)); break;
+	case 14: /* qoffset_x 14 */
+	  Rnifti_SEXP_float(value,&(pnim->qoffset_x)); break;
+	case 15: /* qoffset_y 15 */
+	  Rnifti_SEXP_float(value,&(pnim->qoffset_y)); break;
+	case 16: /* qoffset_z 16 */
+	  Rnifti_SEXP_float(value,&(pnim->qoffset_z)); break;
+	case 17: /* qfac 17 */
+	  Rnifti_SEXP_float(value,&(pnim->qfac)); break;
+	case 18: /* pixdim 18 */
+	  if(length(value)<=pnim->dim[0])
+	    {
+	      int iIndex;
+	      PROTECT(value=AS_NUMERIC(value));
+	      for(iIndex=0;iIndex<length(value);++iIndex)
+		{
+		  pnim->pixdim[iIndex+1]=NUMERIC_POINTER(value)[iIndex];
+		}
+	      UNPROTECT(1);
+	    }
+	  else
+	    error("Length of pixdim greater than number of dimensions (dim[0])\n");
+	  break;
+	case 19: /* nifti_type 19 */
+	  if(IS_NUMERIC(value))
+	    {
+		  Rnifti_SEXP_int(value,&pnim->nifti_type);
+	    }
+	  else
+	    error("Only nummeric values are allowed to set nifti_type.\n");
+	  break;
+	case 21: /* datatype */
+	  if(IS_NUMERIC(value))
+	    {
+	      /*SEXP_to_int(value,&pnim->datatype);*/
+	      Rnifti_image_setdatatype(nim, value);
+	    }
+	  else
+	    error("Only nummeric values are allowed to set nifti_datatype.\n");
+	  break;
+	case 22: /* scl_slope nifti1: Data scaling: slope.  analyze 7.5: float funused1 */
+	  if(IS_NUMERIC(value))
+	    {
+	      Rnifti_SEXP_float(value,&(pnim->scl_slope));
+	    }
+	  else
+	    error("Only nummeric values are allowed to set scl_slope.\n");
+	  break;
+	case 23: /* scl_inter nifti1: Data scaling: offset. analyze 7.5: float funused2 */
+	  if(IS_NUMERIC(value))
+	    {
+	      Rnifti_SEXP_float(value,&(pnim->scl_inter));
+	    }
+	  else
+	    error("Only nummeric values are allowed to set scl_inter.\n");
+	  break;
+	case 28: /* dim */
+		PROTECT(value = AS_INTEGER(value));
+		if(length(value)>1 && length(value)<=7)
+		{
+		   int iIndex;
+		   pnim->dim[0]=length(value);
+		   for(iIndex=0;iIndex<length(value);++iIndex)
+		   {
+			  pnim->dim[iIndex+1]=INTEGER_POINTER(value)[iIndex];
+		   }
+		   // correct dependend structure entries
+		   nifti_update_dims_from_array(pnim);
+		   // correct size of data array if necessary
+		   if( pnim->data != NULL )
+		     Rnifti_image_alloc_data(nim);
+		 }
+		 else
+		    error("Length of vector not compatible with the number of dimensions.\n");
+		 UNPROTECT(1);
+		 break;
+	case 30: /* xyz_units */
+		if((IS_NUMERIC(value) || IS_INTEGER(value)) && length(value)==1)
+		{
+		  PROTECT(value = AS_INTEGER(value));
+		  pnim->xyz_units=INTEGER_POINTER(value)[0];
+		  UNPROTECT(1);
+		}
+		else
+		  error("Length of input vector not compatible with xyz_units.\n");
+		break;
+	case 31: /* time_units */
+		if((IS_NUMERIC(value) || IS_INTEGER(value)) && length(value)==1)
+		{
+		  PROTECT(value = AS_INTEGER(value));
+		  pnim->time_units=INTEGER_POINTER(value)[0];
+		  UNPROTECT(1);
+		}
+		else
+		  error("Length of input vector not compatible with time_units.\n");
+		break;
+	default:
+	  error("Rnifti_image_setattribute: unknown attribute\n");
+	  break;
+	}
+      //Rprintf("symbol: %d\n",is_symbol(sym));
+    }
+  else
+    error("Rnifti_image_setattribute: not a pointer to a nifti object.\n");
+  return nim;
+}
+
+SEXP Rnifti_image_getattribute(SEXP nim, SEXP sym)
+{
+  SEXP ret_val=R_NilValue;
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      SEXP Rstring;
+      PROTECT( Rstring= AS_CHARACTER(sym));
+      int iIndex;
+      for(iIndex=0;Rnifti_attributes[iIndex]!=NULL;++iIndex)
+	if(strcmp(Rnifti_attributes[iIndex],CHAR(STRING_ELT(Rstring,0)))==0)
+	  break;
+      UNPROTECT(1);
+      switch(iIndex)
+	{
+      /* R comaptible transformation matrices */
+      case 0: /*qto.xyz*/
+  	  // old: return Rnifti_mat44_SEXP(&(pnim->qto_xyz)); break;
+  	  {   // generate a matrix compatible with R indexing (voxel start index at 1)
+  		  mat44 Rqto_xyz;
+  		  for(int r=0;r<4;++r)
+  		  {
+  			  for(int c=0;c<4;++c)
+  			  {
+  				  Rqto_xyz.m[r][c]=pnim->qto_xyz.m[r][c];
+  			  }
+  			  Rqto_xyz.m[r][3]=Rqto_xyz.m[r][3]-Rqto_xyz.m[r][0]-Rqto_xyz.m[r][1]-Rqto_xyz.m[r][2];
+  	      }
+  		  return Rnifti_mat44_SEXP(&Rqto_xyz);
+  	  }
+  	  break;
+  	case 1: /*qto.ijk*/
+  	  // old: return Rnifti_mat44_SEXP(&(pnim->qto_ijk)); break;
+  	  {   // generate a matrix compatible with R indexing (voxel start index at 1)
+  		  mat44 Rqto_ijk;
+  		  for(int r=0;r<3;++r)
+  		  {
+  			  for(int c=0;c<4;++c)
+  			  {
+  				  Rqto_ijk.m[r][c]=pnim->qto_ijk.m[r][c]+pnim->qto_ijk.m[3][c];
+  			  }
+  	      }
+  		  for(int c=0;c<4;++c)
+  		  {
+  			  Rqto_ijk.m[3][c]=pnim->qto_ijk.m[3][c];
+  		  }
+  		  return Rnifti_mat44_SEXP(&Rqto_ijk);
+  	  }
+  	  break;
+  	case 2: /*sto.xyz*/
+  	  // old: return Rnifti_mat44_SEXP(&(pnim->sto_xyz)); break;
+  	  {   // generate a matrix compatible with R indexing (voxel start index at 1)
+  		  mat44 Rsto_xyz;
+  		  for(int r=0;r<4;++r)
+  		  {
+  			  for(int c=0;c<4;++c)
+  			  {
+  				  Rsto_xyz.m[r][c]=pnim->sto_xyz.m[r][c];
+  			  }
+  			  Rsto_xyz.m[r][3]=Rsto_xyz.m[r][3]-Rsto_xyz.m[r][0]-Rsto_xyz.m[r][1]-Rsto_xyz.m[r][2];
+  	      }
+  		  return Rnifti_mat44_SEXP(&Rsto_xyz);
+  	  }
+  	  break;
+  	case 3: /*sto.ijk*/
+  	  // old: return Rnifti_mat44_SEXP(&(pnim->sto_ijk)); break;
+  	  {   // generate a matrix compatible with R indexing (voxel index start at 1)
+  		  mat44 Rsto_ijk;
+  		  for(int r=0;r<3;++r)
+  		  {
+  			  for(int c=0;c<4;++c)
+  			  {
+  				  Rsto_ijk.m[r][c]=pnim->sto_ijk.m[r][c]+pnim->sto_ijk.m[3][c];
+  			  }
+  	      }
+  		  for(int c=0;c<4;++c)
+  		  {
+  			  Rsto_ijk.m[3][c]=pnim->sto_ijk.m[3][c];
+  		  }
+  		  return Rnifti_mat44_SEXP(&Rsto_ijk);
+  	  }
+  	  break;
+      /* C comaptible transformation matrices (voxel index start at 0)*/
+  	case 24: /*qto_xyz*/
+  	  return Rnifti_mat44_SEXP(&(pnim->qto_xyz)); break;
+  	case 25: /*qto_ijk*/
+  	  return Rnifti_mat44_SEXP(&(pnim->qto_ijk)); break;
+  	case 26: /*sto_xyz*/
+  	  return Rnifti_mat44_SEXP(&(pnim->sto_xyz)); break;
+  	case 27: /*sto_ijk*/
+  	  return Rnifti_mat44_SEXP(&(pnim->sto_ijk)); break;
+  	case 4: /*toffset*/
+	  return Rnifti_float_SEXP(pnim->toffset); break;
+	case 5: /*descrip*/
+	  return Rnifti_pchar_SEXP(pnim->descrip); break;
+	case 6: /*fname*/
+	  return Rnifti_pchar_SEXP(pnim->fname); break;
+	case 7: /*iname*/
+	  return Rnifti_pchar_SEXP(pnim->iname); break;
+	case 8: /*slice_duration*/
+	  return Rnifti_float_SEXP(pnim->slice_duration); break;
+	case 9: /* qform_code */
+	  switch(pnim->qform_code)
+	    {
+	    case NIFTI_XFORM_UNKNOWN:
+	      /*! Arbitrary coordinates (Method 1). */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.UNKNOWN");
+	      break;
+	    case NIFTI_XFORM_SCANNER_ANAT:
+	      /*! Scanner-based anatomical coordinates */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.SCANNER_ANAT");
+	      break;
+	    case NIFTI_XFORM_ALIGNED_ANAT:
+	      /*! Coordinates aligned to another file's,
+		or to anatomical "truth".            */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.ALIGNED_ANAT");
+	      break;
+	    case NIFTI_XFORM_TALAIRACH:
+	      /*! Coordinates aligned to Talairach-
+		Tournoux Atlas; (0,0,0)=AC, etc. */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.TALAIRACH");
+	      break;
+	    case NIFTI_XFORM_MNI_152:
+	      /*! MNI 152 normalized coordinates. */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.MNI.152");
+	      break;
+	    default:
+	      {
+		char buffer[100];
+		snprintf(buffer,100,"qform code: %d",pnim->qform_code);
+		return Rnifti_pchar_SEXP(buffer);
+	      }
+	      break;
+	    }
+	  break;
+	case 10: /* sform_code */
+	  switch(pnim->sform_code)
+	    {
+	    case NIFTI_XFORM_UNKNOWN:
+	      /*! Arbitrary coordinates (Method 1). */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.UNKNOWN");
+	      break;
+	    case NIFTI_XFORM_SCANNER_ANAT:
+	      /*! Scanner-based anatomical coordinates */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.SCANNER_ANAT");
+	      break;
+	    case NIFTI_XFORM_ALIGNED_ANAT:
+	      /*! Coordinates aligned to another file's,
+		or to anatomical "truth".            */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.ALIGNED.ANAT");
+	      break;
+	    case NIFTI_XFORM_TALAIRACH:
+	      /*! Coordinates aligned to Talairach-
+		Tournoux Atlas; (0,0,0)=AC, etc. */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.TALAIRACH");
+	      break;
+	    case NIFTI_XFORM_MNI_152:
+	      /*! MNI 152 normalized coordinates. */
+	      return Rnifti_pchar_SEXP("NIFTI.XFORM.MNI.152");
+	      break;
+	    default:
+	      {
+		char buffer[100];
+		snprintf(buffer,100,"qform code: %d",pnim->qform_code);
+		return Rnifti_pchar_SEXP(buffer);
+	      }
+	      break;
+	    }
+	  break;
+	case 11: /* quatern_b 11 */
+	  return Rnifti_float_SEXP(pnim->quatern_b); break;
+	case 12: /* quatern_c 12 */
+	  return Rnifti_float_SEXP(pnim->quatern_c); break;
+	case 13: /* quatern_d 13 */
+	  return Rnifti_float_SEXP(pnim->quatern_d); break;
+	case 14: /* qoffset_x 14 */
+	  return Rnifti_float_SEXP(pnim->qoffset_x); break;
+	case 15: /* qoffset_y 15 */
+	  return Rnifti_float_SEXP(pnim->qoffset_y); break;
+	case 16: /* qoffset_z 16 */
+	  return Rnifti_float_SEXP(pnim->qoffset_z); break;
+	case 17: /* qfac 17 */
+	  return Rnifti_float_SEXP(pnim->qfac); break;
+	case 18: /* pixdim 18 */
+	  if(pnim->dim[0]<8)
+	    {
+	      PROTECT(ret_val=NEW_NUMERIC(pnim->dim[0]));
+	      for(iIndex=0;iIndex<pnim->dim[0];++iIndex)
+		{
+		  NUMERIC_POINTER(ret_val)[iIndex]=pnim->pixdim[iIndex+1];
+		}
+	      UNPROTECT(1);
+	    }
+	  else
+	    error("number of dimensions (dim[0]) > 7!\n");
+	  break;
+	case 19: /* nifti_type 19 */
+	  switch(pnim->nifti_type)
+	    {
+	    case NIFTI_FTYPE_ANALYZE:
+	      return Rnifti_pchar_SEXP("NIFTI.FTYPE.ANALYZE"); break;
+	    case NIFTI_FTYPE_NIFTI1_1:
+	      return Rnifti_pchar_SEXP("NIFTI.FTYPE.NIFTI1.1"); break;
+	    case NIFTI_FTYPE_NIFTI1_2:
+	      return Rnifti_pchar_SEXP("NIFTI.FTYPE.NIFTI1.2"); break;
+	    case NIFTI_FTYPE_ASCII:
+	      return Rnifti_pchar_SEXP("NIFTI.FTYPE.ASCII"); break;
+	    default:
+	      return Rnifti_pchar_SEXP("NIFTI.FTYPE.UNKNOWN"); break;
+	    }
+	  break;
+	case 20: /* sizeof_hdr 20 */
+	  {
+	    struct nifti_1_header hdr = nifti_convert_nim2nhdr(pnim);
+	    return Rnifti_int_SEXP(hdr.sizeof_hdr);
+	  }
+	  break;
+	case 21: /* datatype */
+	  return Rnifti_int_SEXP(pnim->datatype);
+	  break;
+	case 22: /* scl_slope nifti1: Data scaling: slope.  analyze 7.5: float funused1 */
+	  return Rnifti_float_SEXP(pnim->scl_slope);
+	  break;
+	case 23: /* scl_inter nifti1: Data scaling: offset. analyze 7.5: float funused2 */
+	  return Rnifti_float_SEXP(pnim->scl_inter);
+	  break;
+	case 28: /* dim */
+	  if(pnim->dim[0]>0 && pnim->dim[0]<8)
+	  {
+	    PROTECT(ret_val=NEW_INTEGER(pnim->dim[0]));
+	    for(iIndex=0;iIndex<pnim->dim[0];++iIndex)
+	    {
+		  INTEGER_POINTER(ret_val)[iIndex]=pnim->dim[iIndex+1];
+	    }
+	    UNPROTECT(1);
+	  }
+	  else
+	    error("Rnifti_image_getattribute: incorrect number of dimensions in dim[0]!\n");
+	  break;
+	case 29: /* nbyper */
+	  return Rnifti_int_SEXP(pnim->nbyper);
+	  break;
+	case 30: /* xyz_units */
+		return Rnifti_int_SEXP(pnim->xyz_units);
+	    break;
+	case 31: /* time_units */
+		return Rnifti_int_SEXP(pnim->time_units);
+	    break;
+	default:
+	  error("Rnifti_image_getattribute: unknown symbol\n"); break;
+
+	}
+      //Rprintf("symbol: %d\n",is_symbol(sym));
+    }
+  else
+    error("Rnifti_image_getattribute: not a pointer to a nifti object.\n");
+  return ret_val;
+}
+
+/** @brief Copy the nifti_image structure, without data.
+
+    Duplicate the structure, including fname, iname and extensions.
+    Leave the data pointer as NULL.
+*/
+SEXP Rnifti_image_copy_info(SEXP nim)
+{
+  SEXP ret_val=R_NilValue;
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      nifti_image *pnew_nim=nifti_copy_nim_info(pnim);
+      ret_val = R_MakeExternalPtr(pnew_nim,NIFTI_type_tag, R_NilValue);
+      R_RegisterCFinalizer(ret_val,(R_CFinalizer_t) Rnifti_image_free);
+
+      // set class attribute to nifti
+      SEXP classattrib;
+      PROTECT(classattrib = allocVector(STRSXP, 1));
+      SET_STRING_ELT(classattrib, 0, mkChar("nifti"));
+      classgets(ret_val, classattrib);
+      UNPROTECT(1);
+    }
+  else
+    error("nifti_image_copy_info: object is not a nifti image");
+  return ret_val;
+}
+
+SEXP Rnifti_image_read(SEXP file, SEXP read_data, SEXP rmNaN)
+{
+  nifti_image *pnim;
+  PROTECT(read_data = AS_INTEGER(read_data));
+  PROTECT(file = AS_CHARACTER(file));
+  PROTECT(rmNaN = AS_LOGICAL(rmNaN));
+  if(!isString(file) || length(file) != 1)
+  {  error("Rnifti_image_read: file is not a single string\n"); return R_NilValue; }
+  if(!isLogical(rmNaN) || length(rmNaN) != 1)
+  {  error("Rnifti_image_read: rm.NaN is not a single logical\n"); return R_NilValue; }
+  int int_rmNaN = (int)(LOGICAL_POINTER(rmNaN)[0]);
+  if(int_rmNaN<0)
+  {  error("Rnifti_image_read: rm.NaN is not a valid logical\n"); return R_NilValue; }
+  if(length(read_data) != 1)
+  {  error("Rnifti_image_read: read_data is not a single integer\n"); return R_NilValue; }
+  int *piread_data = INTEGER_POINTER(read_data);
+  const char *pcfilename  = CHAR(STRING_ELT(file , 0));
+  
+  
+  
+  pnim = nifti_image_read_NaN( pcfilename , piread_data[0], int_rmNaN ) ;
+  if(pnim==NULL)
+    {
+      error("Rnifti_image_read: Can not open file \"%s\"",pcfilename);
+      UNPROTECT(3);
+      return R_NilValue;
+    }
+
+  SEXP nim = R_MakeExternalPtr(pnim,NIFTI_type_tag, R_NilValue);
+  R_RegisterCFinalizer(nim,(R_CFinalizer_t) Rnifti_image_free);
+
+  // set class attribute to PAC::ImageBase
+  SEXP classattrib;
+  PROTECT(classattrib = allocVector(STRSXP, 1));
+  SET_STRING_ELT(classattrib, 0, mkChar("nifti"));
+  classgets(nim, classattrib);
+  UNPROTECT(4);
+  return nim;
+}
+
+SEXP Rnifti_image_write(SEXP nim)
+{
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      nifti_image_write(pnim);
+    }
+  return R_NilValue;
+}
+
+/*SEXP Rnifti_image_getdim(SEXP nim)
+{
+  SEXP ret_val=R_NilValue;
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      int i;
+      PROTECT(ret_val = NEW_INTEGER(pnim->dim[0]));
+      for(i=0;i<pnim->dim[0];++i)
+	INTEGER(ret_val)[i]=pnim->dim[i+1];
+      UNPROTECT(1);
+    }
+  return ret_val;
+}*/
+
+SEXP Rnifti_image_getpixel2(SEXP sexp_args)
+{
+	SEXP ret_val=R_NilValue;
+    // skip function name
+ 	sexp_args = CDR(sexp_args);
+
+ 	// check first argument (should be a nifti object)
+	if(sexp_args == R_NilValue)
+	{
+		warning("First argument must be a nifti object.");
+		return ret_val;
+    }
+	// grab nifti object
+ 	SEXP nim = CAR(sexp_args);
+	nifti_image *pnim=SEXP2NIFTI(nim);
+	if(pnim!=NULL)
+	{
+		int i;
+		for(i = 0; sexp_args != R_NilValue; i++)
+		{
+			Rprintf("arg %04d: ",i);
+			SEXP value = CAR(sexp_args);
+
+			if(value == NULL_USER_OBJECT)
+			  Rprintf("NULL");
+			if(IS_LOGICAL(value) && LENGTH(value)>0)
+			  Rprintf("%s ",LOGICAL_POINTER(value)[0]?"TRUE":"FALSE");
+			if(IS_NUMERIC(value) && LENGTH(value)>0)
+			  Rprintf("%f ",NUMERIC_POINTER(value)[0]);
+			if(IS_INTEGER(value) && LENGTH(value)>0)
+			  Rprintf("%d ",INTEGER_POINTER(value)[0]);
+			if(IS_CHARACTER(value) && LENGTH(value)>0)
+			{
+				Rprintf("%s ",CHAR(STRING_ELT(value , 0)));
+			}
+			// the name of the argument
+			{
+				SEXP printname = PRINTNAME(TAG(sexp_args));
+				if(printname != NULL_USER_OBJECT)
+					Rprintf(" (%s) ",CHAR(printname));
+			}
+			Rprintf("\n");
+
+			sexp_args = CDR(sexp_args);
+		}
+	}
+	else
+	  warning("First argument must be a nifti object.");
+	return ret_val;
+}
+
+#define REALDIM(iDim) ((iDim<(pnim->dim[0]))?pnim->dim[iDim+1]:1)
+
+SEXP Rnifti_image_getpixel(SEXP nim,
+			SEXP sexp_x, SEXP sexp_y,
+			SEXP sexp_z, SEXP sexp_t,
+			SEXP sexp_dim5, SEXP sexp_dim6, SEXP sexp_dim7)
+{
+  SEXP ret_val=R_NilValue;
+  char buffer[10];
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(IS_LOGICAL(sexp_x) || IS_LOGICAL(sexp_y) || IS_LOGICAL(sexp_z) || IS_LOGICAL(sexp_t) ||
+     IS_LOGICAL(sexp_dim5) || IS_LOGICAL(sexp_dim6) || IS_LOGICAL(sexp_dim7))
+  {
+	  error("logical indices are not supported yet!");
+	  return nim;
+  }
+
+  if(pnim!=NULL)
+  {
+    SEXP coord[7];
+    PROTECT(coord[0] = AS_INTEGER(sexp_x));
+    PROTECT(coord[1] = AS_INTEGER(sexp_y));
+    PROTECT(coord[2] = AS_INTEGER(sexp_z));
+    PROTECT(coord[3] = AS_INTEGER(sexp_t));
+
+    PROTECT(coord[4] = AS_INTEGER(sexp_dim5));
+    PROTECT(coord[5] = AS_INTEGER(sexp_dim6));
+    PROTECT(coord[6] = AS_INTEGER(sexp_dim7));
+
+    int iDim,outdim=0;
+    int *iCoord[7];
+    // determine number of dimensions in output matrix
+    for(iDim=0;iDim<7;++iDim)
+    {
+	  if(LENGTH(coord[iDim])>1) outdim++;
+	  iCoord[iDim]=INTEGER(coord[iDim]);
+    }
+    // check if indices are valid (out of bounds?)
+    int iCoordCounter;
+    for(iDim=0;iDim<7;++iDim)
+	  for(iCoordCounter=0;iCoordCounter<LENGTH(coord[iDim]);++iCoordCounter)
+	    if(   iCoord[iDim][iCoordCounter]<0 || iCoord[iDim][iCoordCounter]>=REALDIM(iDim))
+	    {
+	      error("nifti: index out of range (dimension %d index %d dim: %d) \n",iDim,iCoord[iDim][iCoordCounter],REALDIM(iDim));
+	      UNPROTECT(7);
+	      return nim;
+	    }
+
+    if(pnim->datatype==DT_RGB || pnim->datatype==DT_RGBA32)
+      PROTECT(ret_val = NEW_CHARACTER(LENGTH(sexp_x)*LENGTH(sexp_y)*LENGTH(sexp_z)*LENGTH(sexp_t)));
+    else
+      PROTECT(ret_val = NEW_NUMERIC(LENGTH(sexp_x)*LENGTH(sexp_y)*LENGTH(sexp_z)*LENGTH(sexp_t)));
+    int iIndex[7], iTOffset=0, iSOffset=0;
+    /* do type checking outside the main loop to speedup processing...*/
+    switch(pnim->datatype)
+	{
+	/* uchar (8 bits) */
+	case DT_UNSIGNED_CHAR:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+                                 + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+                                 + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((unsigned char*)pnim->data)[iSOffset];
+		            	++iTOffset;
+		            }
+		break;
+	/* signed char (8 bits) */
+	case DT_INT8:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+	                                + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+	                                + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((signed char*)pnim->data)[iSOffset];
+		            	++iTOffset;
+		            }
+		break;
+	/* unsigned short (16 bits) */
+	case DT_UINT16:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+	                             + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+	                             + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((unsigned short*)pnim->data)[iSOffset];
+	                    ++iTOffset;
+		            }
+	     break;
+	/* signed short (16 bits) */
+	case DT_SIGNED_SHORT:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+                                 + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+                                 + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((short*)pnim->data)[iSOffset];
+                        ++iTOffset;
+		            }
+	     break;
+	/* unsigned int (32 bits) */
+	case DT_UINT32:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+	                             + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+	                             + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((unsigned int*)pnim->data)[iSOffset];
+		            	++iTOffset;
+		            }
+		  break;
+	/* signed int (32 bits) */
+	case DT_SIGNED_INT:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+                                 + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+                                 + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((int*)pnim->data)[iSOffset];
+		            	++iTOffset;
+		            }
+	  break;
+	/* float (32 bits) */
+	case DT_FLOAT:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+                                 + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+                                 + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((float*)pnim->data)[iSOffset];
+		            	++iTOffset;
+		            }
+	  break;
+	/* double (64 bits) */
+	case DT_DOUBLE:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+		    for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+	          for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+	            for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+	              for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+		            for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+		            {
+		            	iSOffset=  iCoord[0][iIndex[0]]
+		            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+		            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+		            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+		            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+                                 + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+                                 + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+		            	NUMERIC_POINTER(ret_val)[iTOffset] = (double)((double*)pnim->data)[iSOffset];
+		            	++iTOffset;
+		            }
+	  break;
+	  /* rgb (24 bits) */
+	  case DT_RGB:
+		for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+		  for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+			for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+			  for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+				for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+				  for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+					for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+					{
+						iSOffset=  iCoord[0][iIndex[0]]
+								 + iCoord[1][iIndex[1]]*pnim->dim[1]
+								 + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+								 + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+								 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+								 + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+								 + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+						sprintf(buffer,"#%02X%02X%02X",((unsigned char*)pnim->data)[iSOffset*3],((unsigned char*)pnim->data)[iSOffset*3+1],((unsigned char*)pnim->data)[iSOffset*3+2]);
+						SET_STRING_ELT(ret_val, iTOffset, mkChar(buffer));
+						++iTOffset;
+					}
+			  break;
+		/* rgba (32 bits) */
+		case DT_RGBA32:
+			for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6])
+				for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5])
+					for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4])
+						for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3])
+							for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2])
+								for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1])
+									for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0])
+						            {
+						            	iSOffset=  iCoord[0][iIndex[0]]
+						            	         + iCoord[1][iIndex[1]]*pnim->dim[1]
+						            	         + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2]
+						            	         + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]
+						            			 + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]
+				                                 + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]
+				                                 + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+						            	sprintf(buffer,"#%02X%02X%02X%02X",((unsigned char*)pnim->data)[iSOffset*4],((unsigned char*)pnim->data)[iSOffset*4+1],((unsigned char*)pnim->data)[iSOffset*4+2],((unsigned char*)pnim->data)[iSOffset*4+3]);
+						            	SET_STRING_ELT(ret_val, iTOffset, mkChar(buffer));
+						            	++iTOffset;
+						            }
+					  break;
+	default:
+	  warning("unsupported data format (identifier %d)",pnim->datatype);
+	}
+    /*Rprintf("outdim=%d\n",outdim);*/
+    /* set the dimension attribute */
+    if(outdim>1)
+	{
+	  SEXP dim;
+	  PROTECT(dim=NEW_INTEGER(outdim));
+	  int iDimCount=0;
+	  for(iDim=0;iDim<7;++iDim)
+	  {
+	      /*Rprintf("length[%d]=%d\n",iDim,LENGTH(coord[iDim]));*/
+	      if(LENGTH(coord[iDim])>1)
+	      {
+		    INTEGER_POINTER(dim)[iDimCount++]=LENGTH(coord[iDim]);
+		  }
+	  }
+	  SET_DIM(ret_val,dim);
+	  UNPROTECT(1);
+	}
+    UNPROTECT(8);
+  }
+  return ret_val;
+}
+
+SEXP Rnifti_image_printinfo(SEXP nim)
+{
+  int iIndex;
+  SEXP ret_val=R_NilValue;
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      Rprintf("dimension: ");
+      for(iIndex=0;iIndex<pnim->dim[0];++iIndex)
+	    Rprintf("%d ",pnim->dim[iIndex+1]);
+      Rprintf("\n");
+
+      Rprintf("dimensions: freq = %d, phase = %d, slice = %d\n",
+	      pnim->freq_dim, pnim->phase_dim, pnim->slice_dim);
+      if(pnim->qform_code!=NIFTI_XFORM_UNKNOWN)
+	{
+	  int icod, jcod, kcod;
+	  nifti_mat44_to_orientation( pnim->qto_xyz , &icod, &jcod, &kcod );
+	  Rprintf("i orientation (voxel x-axis): %s\n",nifti_orientation_string(icod));
+	  Rprintf("j orientation (voxel y-axis): %s\n",nifti_orientation_string(jcod));
+	  Rprintf("k orientation (voxel z-axis): %s\n",nifti_orientation_string(kcod));
+	}
+      int c;
+      Rprintf("number of nifti ext. : %d\n",pnim->num_ext);
+      for (c = 0; c < pnim->num_ext; c++ )
+	{
+	  Rprintf("%d] size: %d code: %d",c,pnim->ext_list[c].esize,pnim->ext_list[c].ecode);
+	  switch(pnim->ext_list[c].ecode)
+	    {
+	    case NIFTI_ECODE_IGNORE:
+	      Rprintf("(ignore /unknown)\n");
+	      break;
+	    case NIFTI_ECODE_DICOM:
+	      Rprintf("(raw DICOM attributes)\n");
+	      break;
+	    case NIFTI_ECODE_AFNI:
+	      Rprintf("(Robert W Cox: http://afni.nimh.nih.gov/afni)\n");
+	      break;
+	    case NIFTI_ECODE_COMMENT:
+	      Rprintf("(plain ASCII text)\n");
+	      break;
+	    case NIFTI_ECODE_XCEDE:
+	      Rprintf("(David B Keator: http://www.nbirn.net/Resources/Users/Applications/xcede/index.htm)\n");
+	      break;
+	    case NIFTI_ECODE_JIMDIMINFO:
+	      Rprintf("(Mark A Horsfield: http://someplace/something)\n");
+	      break;
+	    case NIFTI_ECODE_WORKFLOW_FWDS:
+	      Rprintf("(Kate Fissell: http://kraepelin.wpic.pitt.edu)\n");
+	      break;
+	    default:
+	      Rprintf("(unknown NIFTI_ECODE)\n");
+	      break;
+	    }
+	}
+      Rprintf("data type: %s (%d)\n",nifti_datatype_to_string(pnim->datatype),pnim->datatype);
+      /*switch(pnim->datatype)
+	{
+	  //--- the original ANALYZE 7.5 type codes ---
+	case  DT_BINARY:           //  1      binary (1 bit/voxel)
+	  Rprintf(" data type: 1 binary (1 bit/voxel)\n");
+	  break;
+	case  DT_UNSIGNED_CHAR:    //  2      unsigned char (8 bits/voxel)
+	  Rprintf(" data type: 2 unsigned char (8 bits/voxel)\n");
+	  break;
+	case  DT_SIGNED_SHORT:     //  4      signed short (16 bits/voxel)
+	  Rprintf(" data type: 4 signed short (16 bits/voxel)\n");
+	  break;
+	case  DT_SIGNED_INT:       //  8      signed int (32 bits/voxel)
+	  Rprintf(" data type: 8 signed int (32 bits/voxel)\n");
+	  break;
+	case  DT_FLOAT:            // 16      float (32 bits/voxel)
+	  Rprintf(" data type: 16 float (32 bits/voxel)\n");
+	  break;
+	case  DT_COMPLEX:          // 32      complex (64 bits/voxel)
+	  Rprintf(" data type: 32 complex (64 bits/voxel)\n");
+	  break;
+	case  DT_DOUBLE:           // 64      double (64 bits/voxel)
+	  Rprintf(" data type: 64 double (64 bits/voxel) \n");
+	  break;
+	case  DT_RGB:              //128      RGB triple (24 bits/voxel)
+	  Rprintf(" data type: 128 RGB triple (24 bits/voxel)\n");
+	  break;
+	  //------------------- new codes for NIFTI ---
+	case  DT_INT8:             // 256      signed char (8 bits)
+	  Rprintf(" data type: 256 signed char (8 bits)\n");
+	  break;
+	case  DT_UINT16:           // 512      unsigned short (16 bits)
+	  Rprintf(" data type: 512 unsigned short (16 bits)\n");
+	  break;
+	case  DT_UINT32:           // 768      unsigned int (32 bits)
+	  Rprintf(" data type: 768 unsigned int (32 bits)\n");
+	  break;
+	case  DT_INT64:            //1024      long long (64 bits)
+	  Rprintf(" data type: 1024 long long (64 bits)\n");
+	  break;
+	case  DT_UINT64:           //1280      unsigned long long (64 bits)
+	  Rprintf(" data type: 1280 unsigned long long (64 bits)\n");
+	  break;
+	case  DT_FLOAT128:         //1536      long double (128 bits)
+	  Rprintf(" data type: 1536 long double (128 bits)\n");
+	  break;
+	case  DT_COMPLEX128:       //1792      double pair (128 bits)
+	  Rprintf(" data type: 1792 double pair (128 bits)\n");
+	  break;
+	case  DT_COMPLEX256:       //2048      long double pair (256 bits)
+	  Rprintf(" data type: 2048 long double pair (256 bits)\n");
+	  break;
+	case  DT_RGBA32:           //2304      RGBA  (32 bits/voxel)
+	  Rprintf(" data type: 2304 RGBA32 (32 bits/voxel)\n");
+	  break;
+	default:              	   //         what it says, dude
+	  Rprintf(" data type: %u what it says, dude\n",pnim->datatype);
+	  break;
+	}*/
+    }
+  Rprintf("intent: %s\n",nifti_intent_string(pnim->intent_code));
+  Rprintf("attributes: (accessible via $ operator)\n");
+  for(iIndex=0;Rnifti_attributes[iIndex]!=NULL;++iIndex)
+    {
+      if(iIndex!=0)
+	{
+	  if(iIndex%5==0)
+	    Rprintf("\n");
+	  else
+	    Rprintf("; ");
+	}
+      Rprintf("\"%s\"",Rnifti_attributes[iIndex]);
+    }
+  Rprintf("\n");
+  return ret_val;
+}
+
+SEXP Rnifti_image_setpixel(
+		SEXP nim,
+		SEXP sexp_x, SEXP sexp_y,
+		SEXP sexp_z, SEXP sexp_t,
+		SEXP sexp_dim5, SEXP sexp_dim6, SEXP sexp_dim7,
+		SEXP value)
+{
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(IS_LOGICAL(sexp_x) || IS_LOGICAL(sexp_y) || IS_LOGICAL(sexp_z) || IS_LOGICAL(sexp_t) ||
+     IS_LOGICAL(sexp_dim5) || IS_LOGICAL(sexp_dim6) || IS_LOGICAL(sexp_dim7))
+  {
+	  error("logical indices are not supported");
+	  return nim;
+  }
+
+  /*PROTECT(value = AS_NUMERIC(value));*/
+  if(pnim!=NULL)
+  {
+    SEXP coord[7];
+    PROTECT(coord[0] = AS_INTEGER(sexp_x));
+    PROTECT(coord[1] = AS_INTEGER(sexp_y));
+    PROTECT(coord[2] = AS_INTEGER(sexp_z));
+    PROTECT(coord[3] = AS_INTEGER(sexp_t));
+
+    PROTECT(coord[4] = AS_INTEGER(sexp_dim5));
+    PROTECT(coord[5] = AS_INTEGER(sexp_dim6));
+    PROTECT(coord[6] = AS_INTEGER(sexp_dim7));
+
+    int iDim,outdim=0;
+    int *iCoord[7];
+
+    // determine number of dimensions in output matrix
+    for(iDim=0;iDim<7;++iDim)
+	{
+	  if(LENGTH(coord[iDim])>1) outdim++;
+	  iCoord[iDim]=INTEGER(coord[iDim]);
+	}
+    // check if indices are valid (out of bounds?)
+    int iCoordCounter;
+    for(iDim=0;iDim<7;++iDim)
+	  for(iCoordCounter=0;iCoordCounter<LENGTH(coord[iDim]);++iCoordCounter)
+	    if(   iCoord[iDim][iCoordCounter]<0 || iCoord[iDim][iCoordCounter]>=REALDIM(iDim))
+	    {
+	      error("nifti: index out of range (dimension %d index %d)",iDim+1,iCoord[iDim][iCoordCounter]+1);
+	      UNPROTECT(8);
+	      return nim;
+	    }
+
+    int iIndex[7], iTOffset=0, iSOffset=0;
+
+    int total=LENGTH(coord[0]);
+    for(iDim=1;iDim<7;++iDim)
+      total*=LENGTH(coord[iDim]);
+
+    if(LENGTH(value)>total || total%LENGTH(value)!=0)
+    {
+      UNPROTECT(7);
+      error("Number of items to replace is not a multiple of replacement length!");
+      return nim;
+    }
+
+#define LOOP_START   for(iIndex[6]=0;iIndex[6]<LENGTH(coord[6]);++iIndex[6]) \
+			for(iIndex[5]=0;iIndex[5]<LENGTH(coord[5]);++iIndex[5]) \
+			  for(iIndex[4]=0;iIndex[4]<LENGTH(coord[4]);++iIndex[4]) \
+				for(iIndex[3]=0;iIndex[3]<LENGTH(coord[3]);++iIndex[3]) \
+				  for(iIndex[2]=0;iIndex[2]<LENGTH(coord[2]);++iIndex[2]) \
+					for(iIndex[1]=0;iIndex[1]<LENGTH(coord[1]);++iIndex[1]) \
+					  for(iIndex[0]=0;iIndex[0]<LENGTH(coord[0]);++iIndex[0]) \
+					  { \
+						iTOffset =  iCoord[0][iIndex[0]] \
+								  + iCoord[1][iIndex[1]]*pnim->dim[1] \
+								  + iCoord[2][iIndex[2]]*pnim->dim[1]*pnim->dim[2] \
+								  + iCoord[3][iIndex[3]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3] \
+								  + iCoord[4][iIndex[4]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4] \
+								  + iCoord[5][iIndex[5]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5] \
+								  + iCoord[6][iIndex[6]]*pnim->dim[1]*pnim->dim[2]*pnim->dim[3]*pnim->dim[4]*pnim->dim[5]*pnim->dim[6];
+
+#define LOOP_END 				++iSOffset; if(iSOffset==LENGTH(value)) iSOffset=0; } break; 
+
+    if(IS_NUMERIC(value))
+    {
+		switch(pnim->datatype)
+		{
+		/* uchar (8 bits) */
+		case DT_UNSIGNED_CHAR:
+                  LOOP_START
+		    ((unsigned char*)pnim->data)[iTOffset]=(unsigned char)(NUMERIC_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* signed char (8 bits) */
+		case DT_INT8:
+                  LOOP_START
+		    ((signed char*)pnim->data)[iTOffset]=(signed char)(NUMERIC_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* unsigned short (16 bits) */
+		case DT_UINT16:
+                  LOOP_START
+		    ((unsigned short*)pnim->data)[iTOffset]=(unsigned short)(NUMERIC_POINTER(value)[iSOffset]);
+		  LOOP_END
+		// signed short (16 bits)
+		case DT_SIGNED_SHORT:
+		  LOOP_START
+		    ((short*)pnim->data)[iTOffset]=(short)(NUMERIC_POINTER(value)[iSOffset]);
+                  LOOP_END		
+                // signed int (32 bits)
+		case DT_SIGNED_INT:
+                  LOOP_START
+		    ((int*)pnim->data)[iTOffset]=(int)(NUMERIC_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* unsigned int (32 bits) */
+		case DT_UINT32:
+                  LOOP_START
+	            ((unsigned int*)pnim->data)[iTOffset]=(unsigned int)(NUMERIC_POINTER(value)[iSOffset]);
+                  LOOP_END
+		/* float (32 bits) */
+		case DT_FLOAT:
+		  LOOP_START
+		    ((float*)pnim->data)[iTOffset]=(float)(NUMERIC_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* double (64 bits) */
+		case DT_DOUBLE:
+                  LOOP_START
+		    ((double*)pnim->data)[iTOffset]=(double)(NUMERIC_POINTER(value)[iSOffset]);
+                  LOOP_END
+		/* rgb (24 bits) 
+		case DT_RGB:
+                  LOOP_START
+		    unsigned r,g,b;
+		    Rprintf("%s\n",CHAR(CHARACTER_POINTER(value)[iSOffset]));
+		    sscanf(CHAR(CHARACTER_POINTER(value)[iSOffset]),"#%2X%2X%2X",&r,&g,&b);
+		    Rprintf("%d %d %d\n",r,g,b);
+		    ((unsigned char *)pnim->data)[iTOffset*3+0]=(unsigned char)r;
+		    ((unsigned char *)pnim->data)[iTOffset*3+1]=(unsigned char)g;
+		    ((unsigned char *)pnim->data)[iTOffset*3+2]=(unsigned char)b;
+		  LOOP_END*/
+		/* rgba (32 bits) 
+		case DT_RGBA32:
+                  LOOP_START
+		    unsigned r,g,b,a;
+		    sscanf(CHAR(CHARACTER_POINTER(value)[iSOffset]),"#%2X%2X%2X%2X",&r,&g,&b,&a);
+		    ((unsigned char *)pnim->data)[iTOffset*4+0]=(unsigned char)r;
+		    ((unsigned char *)pnim->data)[iTOffset*4+1]=(unsigned char)g;
+		    ((unsigned char *)pnim->data)[iTOffset*4+2]=(unsigned char)b;
+		    ((unsigned char *)pnim->data)[iTOffset*4+3]=(unsigned char)a;
+		  LOOP_END */
+		default:
+		  warning("Unsupported data format for input type NUMERIC (nifti image datatype is %d)!",pnim->datatype);
+		}
+    }
+    else if(IS_INTEGER(value))
+    {
+ 		switch(pnim->datatype)
+		{
+		/* uchar (8 bits) */
+		case DT_UNSIGNED_CHAR:
+		  LOOP_START
+				((unsigned char*)pnim->data)[iTOffset]=(unsigned char)(INTEGER_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* signed char (8 bits) */
+		case DT_INT8:
+		  LOOP_START
+		    ((signed char*)pnim->data)[iTOffset]=(signed char)(INTEGER_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* unsigned short (16 bits) */
+		case DT_UINT16:
+		  LOOP_START
+		    ((unsigned short*)pnim->data)[iTOffset]=(unsigned short)(INTEGER_POINTER(value)[iSOffset]);
+		  LOOP_END
+		// signed short (16 bits)
+		case DT_SIGNED_SHORT:
+		  LOOP_START
+ 		    ((short*)pnim->data)[iTOffset]=(short)(INTEGER_POINTER(value)[iSOffset]);
+	          LOOP_END
+		// signed int (32 bits)
+		case DT_SIGNED_INT:
+		  LOOP_START
+		    ((int*)pnim->data)[iTOffset]=(int)(INTEGER_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* unsigned int (32 bits) */
+		case DT_UINT32:
+		  LOOP_START
+		    ((unsigned int*)pnim->data)[iTOffset]=(unsigned int)(INTEGER_POINTER(value)[iSOffset]);
+	          LOOP_END
+		/* float (32 bits) */
+		case DT_FLOAT:
+		  LOOP_START
+		    ((float*)pnim->data)[iTOffset]=(float)(INTEGER_POINTER(value)[iSOffset]);
+		  LOOP_END
+		/* double (64 bits) */
+		case DT_DOUBLE:
+                  LOOP_START
+		    ((double*)pnim->data)[iTOffset]=(double)(INTEGER_POINTER(value)[iSOffset]);
+                  LOOP_END
+		default:
+		  warning("Unsupported data format for input of type INTEGER (nifti image datatype is %d)!",pnim->datatype);
+                }
+        }
+	else if(IS_CHARACTER(value))
+	{
+		switch(pnim->datatype)
+		{
+		  /* rgb (24 bits) */
+			case DT_RGB:
+			  LOOP_START
+			    unsigned r,g,b;
+			    /*Rprintf("%s\n",CHAR(CHARACTER_POINTER(value)[iSOffset]));*/
+			    sscanf(CHAR(CHARACTER_POINTER(value)[iSOffset]),"#%2X%2X%2X",&r,&g,&b);
+			    /*Rprintf("%d %d %d\n",r,g,b);*/
+			    ((unsigned char *)pnim->data)[iTOffset*3+0]=(unsigned char)r;
+			    ((unsigned char *)pnim->data)[iTOffset*3+1]=(unsigned char)g;
+			    ((unsigned char *)pnim->data)[iTOffset*3+2]=(unsigned char)b;
+			  LOOP_END
+			/* rgba (32 bits) */
+			case DT_RGBA32:
+			  LOOP_START
+			    unsigned r,g,b,a;
+			    sscanf(CHAR(CHARACTER_POINTER(value)[iSOffset]),"#%2X%2X%2X%2X",&r,&g,&b,&a);
+			    ((unsigned char *)pnim->data)[iTOffset*4+0]=(unsigned char)r;
+			    ((unsigned char *)pnim->data)[iTOffset*4+1]=(unsigned char)g;
+			    ((unsigned char *)pnim->data)[iTOffset*4+2]=(unsigned char)b;
+			    ((unsigned char *)pnim->data)[iTOffset*4+3]=(unsigned char)a;
+			  LOOP_END
+		default:
+		  warning("Unsupported data format for input type CHARACTER (nifti image datatype is %d)",pnim->datatype);
+		}
+	}
+	else
+	  error("Unsupported input data format (need NUMERIC, INTEGER or CHARACTER vectors)!");
+    UNPROTECT(7);
+  }
+  return nim;
+}
+
+SEXP Rnifti_image_setdatatype(SEXP nim, SEXP value)
+{
+  nifti_image *pnim=SEXP2NIFTI(nim);
+
+  if(pnim!=NULL)
+    {
+      int itype=DT_UNKNOWN;
+      if(IS_NUMERIC(value) || IS_INTEGER(value))
+      {
+        PROTECT(value = AS_INTEGER(value));
+        itype=INTEGER(value)[0];
+        UNPROTECT(1);
+      }
+      else if(isString(value) || length(value) != 1)
+      {
+         const char *pctype  = CHAR(STRING_ELT(value , 0));
+         itype=nifti_datatype_from_string(pctype);
+      }
+      else
+         warning("Unsupported or unknown second argument (type set to DT_UNKNOWN)!");
+      switch(itype)
+        {
+	case DT_NONE:          pnim->nbyper=0; break;
+	case DT_BINARY:        pnim->nbyper=0; break;
+	case DT_UNSIGNED_CHAR: pnim->nbyper=1; break;
+	case DT_INT8:          pnim->nbyper=1; break;
+	case DT_UINT16:        pnim->nbyper=2; break;
+	case DT_SIGNED_SHORT:  pnim->nbyper=2; break;
+	case DT_SIGNED_INT:    pnim->nbyper=4; break;
+	case DT_UINT32:        pnim->nbyper=4; break;
+	case DT_INT64: 	       pnim->nbyper=8; break;
+	case DT_UINT64:	       pnim->nbyper=8; break;
+	case DT_FLOAT:         pnim->nbyper=4; break;
+	case DT_FLOAT128:      pnim->nbyper=16; break;
+	case DT_DOUBLE:        pnim->nbyper=8; break;
+	case DT_COMPLEX:       pnim->nbyper=8; break;
+	case DT_COMPLEX128:    pnim->nbyper=16; break;
+	case DT_COMPLEX256:    pnim->nbyper=32; break;
+	case DT_RGB: 	       pnim->nbyper=3; break;
+	case DT_RGBA32:        pnim->nbyper=4; break;
+        default: warning("Unsupported or unknown data type!"); break;
+        }
+      pnim->datatype=itype;
+    }
+  return nim;
+}
+
+
+SEXP Rnifti_compiled_with_zlib(void)
+{
+  SEXP ret_val=R_NilValue;
+
+  PROTECT(ret_val=NEW_LOGICAL(1));
+  LOGICAL_POINTER(ret_val)[0]=nifti_compiled_with_zlib();
+  UNPROTECT(1);
+
+  return ret_val;
+}
+
+SEXP Rnifti_disp_lib_version(void)
+{
+	SEXP ret_val=R_NilValue;
+	char buffer[200];
+
+    snprintf(buffer, 200, "%s, compiled %s", nifti_lib_version(), __DATE__);
+
+	PROTECT(ret_val = NEW_CHARACTER(1));
+    SET_STRING_ELT(ret_val, 0, mkChar(buffer));
+	UNPROTECT(1);
+
+	return ret_val;
+}
+
+SEXP Rnifti_units_string(SEXP value)
+{
+	SEXP ret_val=R_NilValue;
+	PROTECT(value=AS_INTEGER(value));
+	if(IS_INTEGER(value) && LENGTH(value)==1)
+	  ret_val = Rnifti_pchar_SEXP(nifti_units_string(INTEGER_POINTER(value)[0]));
+	UNPROTECT(1);
+	return ret_val;
+}
+
+SEXP Rnifti_datatype_string(SEXP value)
+{
+	SEXP ret_val=R_NilValue;
+	PROTECT(value=AS_INTEGER(value));
+	if(IS_INTEGER(value) && LENGTH(value)==1)          
+	  ret_val = Rnifti_pchar_SEXP(nifti_datatype_string(INTEGER_POINTER(value)[0]));
+	UNPROTECT(1);
+	return ret_val;
+}
+
diff --git a/src/nifti1.h b/src/nifti1.h
new file mode 100644
index 0000000..06d3665
--- /dev/null
+++ b/src/nifti1.h
@@ -0,0 +1,1490 @@
+/** \file nifti1.h
+    \brief Official definition of the nifti1 header.  Written by Bob Cox, SSCC, NIMH.
+
+    HISTORY:
+
+        29 Nov 2007 [rickr]
+           - added DT_RGBA32 and NIFTI_TYPE_RGBA32
+           - added NIFTI_INTENT codes:
+                TIME_SERIES, NODE_INDEX, RGB_VECTOR, RGBA_VECTOR, SHAPE
+ */
+
+#ifndef _NIFTI_HEADER_
+#define _NIFTI_HEADER_
+
+/*****************************************************************************
+      ** This file defines the "NIFTI-1" header format.               **
+      ** It is derived from 2 meetings at the NIH (31 Mar 2003 and    **
+      ** 02 Sep 2003) of the Data Format Working Group (DFWG),        **
+      ** chartered by the NIfTI (Neuroimaging Informatics Technology  **
+      ** Initiative) at the National Institutes of Health (NIH).      **
+      **--------------------------------------------------------------**
+      ** Neither the National Institutes of Health (NIH), the DFWG,   **
+      ** nor any of the members or employees of these institutions    **
+      ** imply any warranty of usefulness of this material for any    **
+      ** purpose, and do not assume any liability for damages,        **
+      ** incidental or otherwise, caused by any use of this document. **
+      ** If these conditions are not acceptable, do not use this!     **
+      **--------------------------------------------------------------**
+      ** Author:   Robert W Cox (NIMH, Bethesda)                      **
+      ** Advisors: John Ashburner (FIL, London),                      **
+      **           Stephen Smith (FMRIB, Oxford),                     **
+      **           Mark Jenkinson (FMRIB, Oxford)                     **
+******************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Note that the ANALYZE 7.5 file header (dbh.h) is
+         (c) Copyright 1986-1995
+         Biomedical Imaging Resource
+         Mayo Foundation
+   Incorporation of components of dbh.h are by permission of the
+   Mayo Foundation.
+
+   Changes from the ANALYZE 7.5 file header in this file are released to the
+   public domain, including the functional comments and any amusing asides.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/*! INTRODUCTION TO NIFTI-1:
+   ------------------------
+   The twin (and somewhat conflicting) goals of this modified ANALYZE 7.5
+   format are:
+    (a) To add information to the header that will be useful for functional
+        neuroimaging data analysis and display.  These additions include:
+        - More basic data types.
+        - Two affine transformations to specify voxel coordinates.
+        - "Intent" codes and parameters to describe the meaning of the data.
+        - Affine scaling of the stored data values to their "true" values.
+        - Optional storage of the header and image data in one file (.nii).
+    (b) To maintain compatibility with non-NIFTI-aware ANALYZE 7.5 compatible
+        software (i.e., such a program should be able to do something useful
+        with a NIFTI-1 dataset -- at least, with one stored in a traditional
+        .img/.hdr file pair).
+
+   Most of the unused fields in the ANALYZE 7.5 header have been taken,
+   and some of the lesser-used fields have been co-opted for other purposes.
+   Notably, most of the data_history substructure has been co-opted for
+   other purposes, since the ANALYZE 7.5 format describes this substructure
+   as "not required".
+
+   NIFTI-1 FLAG (MAGIC STRINGS):
+   ----------------------------
+   To flag such a struct as being conformant to the NIFTI-1 spec, the last 4
+   bytes of the header must be either the C String "ni1" or "n+1";
+   in hexadecimal, the 4 bytes
+     6E 69 31 00   or   6E 2B 31 00
+   (in any future version of this format, the '1' will be upgraded to '2',
+   etc.).  Normally, such a "magic number" or flag goes at the start of the
+   file, but trying to avoid clobbering widely-used ANALYZE 7.5 fields led to
+   putting this marker last.  However, recall that "the last shall be first"
+   (Matthew 20:16).
+
+   If a NIFTI-aware program reads a header file that is NOT marked with a
+   NIFTI magic string, then it should treat the header as an ANALYZE 7.5
+   structure.
+
+   NIFTI-1 FILE STORAGE:
+   --------------------
+   "ni1" means that the image data is stored in the ".img" file corresponding
+   to the header file (starting at file offset 0).
+
+   "n+1" means that the image data is stored in the same file as the header
+   information.  We recommend that the combined header+data filename suffix
+   be ".nii".  When the dataset is stored in one file, the first byte of image
+   data is stored at byte location (int)vox_offset in this combined file.
+   The minimum allowed value of vox_offset is 352; for compatibility with
+   some software, vox_offset should be an integral multiple of 16.
+
+   GRACE UNDER FIRE:
+   ----------------
+   Most NIFTI-aware programs will only be able to handle a subset of the full
+   range of datasets possible with this format.  All NIFTI-aware programs
+   should take care to check if an input dataset conforms to the program's
+   needs and expectations (e.g., check datatype, intent_code, etc.).  If the
+   input dataset can't be handled by the program, the program should fail
+   gracefully (e.g., print a useful warning; not crash).
+
+   SAMPLE CODES:
+   ------------
+   The associated files nifti1_io.h and nifti1_io.c provide a sample
+   implementation in C of a set of functions to read, write, and manipulate
+   NIFTI-1 files.  The file nifti1_test.c is a sample program that uses
+   the nifti1_io.c functions.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* HEADER STRUCT DECLARATION:
+   -------------------------
+   In the comments below for each field, only NIFTI-1 specific requirements
+   or changes from the ANALYZE 7.5 format are described.  For convenience,
+   the 348 byte header is described as a single struct, rather than as the
+   ANALYZE 7.5 group of 3 substructs.
+
+   Further comments about the interpretation of various elements of this
+   header are after the data type definition itself.  Fields that are
+   marked as ++UNUSED++ have no particular interpretation in this standard.
+   (Also see the UNUSED FIELDS comment section, far below.)
+
+   The presumption below is that the various C types have particular sizes:
+     sizeof(int) = sizeof(float) = 4 ;  sizeof(short) = 2
+-----------------------------------------------------------------------------*/
+
+/*=================*/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*=================*/
+
+/*! \struct nifti_1_header
+    \brief Data structure defining the fields in the nifti1 header.
+           This binary header should be found at the beginning of a valid
+           NIFTI-1 header file.
+ */
+                        /*************************/  /************************/
+struct nifti_1_header { /* NIFTI-1 usage         */  /* ANALYZE 7.5 field(s) */
+                        /*************************/  /************************/
+
+                                           /*--- was header_key substruct ---*/
+ int   sizeof_hdr;    /*!< MUST be 348           */  /* int sizeof_hdr;      */
+ char  data_type[10]; /*!< ++UNUSED++            */  /* char data_type[10];  */
+ char  db_name[18];   /*!< ++UNUSED++            */  /* char db_name[18];    */
+ int   extents;       /*!< ++UNUSED++            */  /* int extents;         */
+ short session_error; /*!< ++UNUSED++            */  /* short session_error; */
+ char  regular;       /*!< ++UNUSED++            */  /* char regular;        */
+ char  dim_info;      /*!< MRI slice ordering.   */  /* char hkey_un0;       */
+
+                                      /*--- was image_dimension substruct ---*/
+ short dim[8];        /*!< Data array dimensions.*/  /* short dim[8];        */
+ float intent_p1 ;    /*!< 1st intent parameter. */  /* short unused8;       */
+                                                     /* short unused9;       */
+ float intent_p2 ;    /*!< 2nd intent parameter. */  /* short unused10;      */
+                                                     /* short unused11;      */
+ float intent_p3 ;    /*!< 3rd intent parameter. */  /* short unused12;      */
+                                                     /* short unused13;      */
+ short intent_code ;  /*!< NIFTI_INTENT_* code.  */  /* short unused14;      */
+ short datatype;      /*!< Defines data type!    */  /* short datatype;      */
+ short bitpix;        /*!< Number bits/voxel.    */  /* short bitpix;        */
+ short slice_start;   /*!< First slice index.    */  /* short dim_un0;       */
+ float pixdim[8];     /*!< Grid spacings.        */  /* float pixdim[8];     */
+ float vox_offset;    /*!< Offset into .nii file */  /* float vox_offset;    */
+ float scl_slope ;    /*!< Data scaling: slope.  */  /* float funused1;      */
+ float scl_inter ;    /*!< Data scaling: offset. */  /* float funused2;      */
+ short slice_end;     /*!< Last slice index.     */  /* float funused3;      */
+ char  slice_code ;   /*!< Slice timing order.   */
+ char  xyzt_units ;   /*!< Units of pixdim[1..4] */
+ float cal_max;       /*!< Max display intensity */  /* float cal_max;       */
+ float cal_min;       /*!< Min display intensity */  /* float cal_min;       */
+ float slice_duration;/*!< Time for 1 slice.     */  /* float compressed;    */
+ float toffset;       /*!< Time axis shift.      */  /* float verified;      */
+ int   glmax;         /*!< ++UNUSED++            */  /* int glmax;           */
+ int   glmin;         /*!< ++UNUSED++            */  /* int glmin;           */
+
+                                         /*--- was data_history substruct ---*/
+ char  descrip[80];   /*!< any text you like.    */  /* char descrip[80];    */
+ char  aux_file[24];  /*!< auxiliary filename.   */  /* char aux_file[24];   */
+
+ short qform_code ;   /*!< NIFTI_XFORM_* code.   */  /*-- all ANALYZE 7.5 ---*/
+ short sform_code ;   /*!< NIFTI_XFORM_* code.   */  /*   fields below here  */
+                                                     /*   are replaced       */
+ float quatern_b ;    /*!< Quaternion b param.   */
+ float quatern_c ;    /*!< Quaternion c param.   */
+ float quatern_d ;    /*!< Quaternion d param.   */
+ float qoffset_x ;    /*!< Quaternion x shift.   */
+ float qoffset_y ;    /*!< Quaternion y shift.   */
+ float qoffset_z ;    /*!< Quaternion z shift.   */
+
+ float srow_x[4] ;    /*!< 1st row affine transform.   */
+ float srow_y[4] ;    /*!< 2nd row affine transform.   */
+ float srow_z[4] ;    /*!< 3rd row affine transform.   */
+
+ char intent_name[16];/*!< 'name' or meaning of data.  */
+
+ char magic[4] ;      /*!< MUST be "ni1\0" or "n+1\0". */
+
+} ;                   /**** 348 bytes total ****/
+
+typedef struct nifti_1_header nifti_1_header ;
+
+/*---------------------------------------------------------------------------*/
+/* HEADER EXTENSIONS:
+   -----------------
+   After the end of the 348 byte header (e.g., after the magic field),
+   the next 4 bytes are a char array field named "extension". By default,
+   all 4 bytes of this array should be set to zero. In a .nii file, these
+   4 bytes will always be present, since the earliest start point for
+   the image data is byte #352. In a separate .hdr file, these bytes may
+   or may not be present. If not present (i.e., if the length of the .hdr
+   file is 348 bytes), then a NIfTI-1 compliant program should use the
+   default value of extension={0,0,0,0}. The first byte (extension[0])
+   is the only value of this array that is specified at present. The other
+   3 bytes are reserved for future use.
+
+   If extension[0] is nonzero, it indicates that extended header information
+   is present in the bytes following the extension array. In a .nii file,
+   this extended header data is before the image data (and vox_offset
+   must be set correctly to allow for this). In a .hdr file, this extended
+   data follows extension and proceeds (potentially) to the end of the file.
+
+   The format of extended header data is weakly specified. Each extension
+   must be an integer multiple of 16 bytes long. The first 8 bytes of each
+   extension comprise 2 integers:
+      int esize , ecode ;
+   These values may need to be byte-swapped, as indicated by dim[0] for
+   the rest of the header.
+     * esize is the number of bytes that form the extended header data
+       + esize must be a positive integral multiple of 16
+       + this length includes the 8 bytes of esize and ecode themselves
+     * ecode is a non-negative integer that indicates the format of the
+       extended header data that follows
+       + different ecode values are assigned to different developer groups
+       + at present, the "registered" values for code are
+         = 0 = unknown private format (not recommended!)
+         = 2 = DICOM format (i.e., attribute tags and values)
+         = 4 = AFNI group (i.e., ASCII XML-ish elements)
+   In the interests of interoperability (a primary rationale for NIfTI),
+   groups developing software that uses this extension mechanism are
+   encouraged to document and publicize the format of their extensions.
+   To this end, the NIfTI DFWG will assign even numbered codes upon request
+   to groups submitting at least rudimentary documentation for the format
+   of their extension; at present, the contact is mailto:rwcox at nih.gov.
+   The assigned codes and documentation will be posted on the NIfTI
+   website. All odd values of ecode (and 0) will remain unassigned;
+   at least, until the even ones are used up, when we get to 2,147,483,646.
+
+   Note that the other contents of the extended header data section are
+   totally unspecified by the NIfTI-1 standard. In particular, if binary
+   data is stored in such a section, its byte order is not necessarily
+   the same as that given by examining dim[0]; it is incumbent on the
+   programs dealing with such data to determine the byte order of binary
+   extended header data.
+
+   Multiple extended header sections are allowed, each starting with an
+   esize,ecode value pair. The first esize value, as described above,
+   is at bytes #352-355 in the .hdr or .nii file (files start at byte #0).
+   If this value is positive, then the second (esize2) will be found
+   starting at byte #352+esize1 , the third (esize3) at byte #352+esize1+esize2,
+   et cetera.  Of course, in a .nii file, the value of vox_offset must
+   be compatible with these extensions. If a malformed file indicates
+   that an extended header data section would run past vox_offset, then
+   the entire extended header section should be ignored. In a .hdr file,
+   if an extended header data section would run past the end-of-file,
+   that extended header data should also be ignored.
+
+   With the above scheme, a program can successively examine the esize
+   and ecode values, and skip over each extended header section if the
+   program doesn't know how to interpret the data within. Of course, any
+   program can simply ignore all extended header sections simply by jumping
+   straight to the image data using vox_offset.
+-----------------------------------------------------------------------------*/
+   
+/*! \struct nifti1_extender
+    \brief This structure represents a 4-byte string that should follow the
+           binary nifti_1_header data in a NIFTI-1 header file.  If the char
+           values are {1,0,0,0}, the file is expected to contain extensions,
+           values of {0,0,0,0} imply the file does not contain extensions.
+           Other sequences of values are not currently defined.
+ */
+struct nifti1_extender { char extension[4] ; } ;
+typedef struct nifti1_extender nifti1_extender ;
+
+/*! \struct nifti1_extension
+    \brief Data structure defining the fields of a header extension.
+ */
+struct nifti1_extension {
+   int    esize ; /*!< size of extension, in bytes (must be multiple of 16) */
+   int    ecode ; /*!< extension code, one of the NIFTI_ECODE_ values       */
+   char * edata ; /*!< raw data, with no byte swapping (length is esize-8)  */
+} ;
+typedef struct nifti1_extension nifti1_extension ;
+
+/*---------------------------------------------------------------------------*/
+/* DATA DIMENSIONALITY (as in ANALYZE 7.5):
+   ---------------------------------------
+     dim[0] = number of dimensions;
+              - if dim[0] is outside range 1..7, then the header information
+                needs to be byte swapped appropriately
+              - ANALYZE supports dim[0] up to 7, but NIFTI-1 reserves
+                dimensions 1,2,3 for space (x,y,z), 4 for time (t), and
+                5,6,7 for anything else needed.
+
+     dim[i] = length of dimension #i, for i=1..dim[0]  (must be positive)
+              - also see the discussion of intent_code, far below
+
+     pixdim[i] = voxel width along dimension #i, i=1..dim[0] (positive)
+                 - cf. ORIENTATION section below for use of pixdim[0]
+                 - the units of pixdim can be specified with the xyzt_units
+                   field (also described far below).
+
+   Number of bits per voxel value is in bitpix, which MUST correspond with
+   the datatype field.  The total number of bytes in the image data is
+     dim[1] * ... * dim[dim[0]] * bitpix / 8
+
+   In NIFTI-1 files, dimensions 1,2,3 are for space, dimension 4 is for time,
+   and dimension 5 is for storing multiple values at each spatiotemporal
+   voxel.  Some examples:
+     - A typical whole-brain FMRI experiment's time series:
+        - dim[0] = 4
+        - dim[1] = 64   pixdim[1] = 3.75 xyzt_units =  NIFTI_UNITS_MM
+        - dim[2] = 64   pixdim[2] = 3.75             | NIFTI_UNITS_SEC
+        - dim[3] = 20   pixdim[3] = 5.0
+        - dim[4] = 120  pixdim[4] = 2.0
+     - A typical T1-weighted anatomical volume:
+        - dim[0] = 3
+        - dim[1] = 256  pixdim[1] = 1.0  xyzt_units = NIFTI_UNITS_MM
+        - dim[2] = 256  pixdim[2] = 1.0
+        - dim[3] = 128  pixdim[3] = 1.1
+     - A single slice EPI time series:
+        - dim[0] = 4
+        - dim[1] = 64   pixdim[1] = 3.75 xyzt_units =  NIFTI_UNITS_MM
+        - dim[2] = 64   pixdim[2] = 3.75             | NIFTI_UNITS_SEC
+        - dim[3] = 1    pixdim[3] = 5.0
+        - dim[4] = 1200 pixdim[4] = 0.2
+     - A 3-vector stored at each point in a 3D volume:
+        - dim[0] = 5
+        - dim[1] = 256  pixdim[1] = 1.0  xyzt_units = NIFTI_UNITS_MM
+        - dim[2] = 256  pixdim[2] = 1.0
+        - dim[3] = 128  pixdim[3] = 1.1
+        - dim[4] = 1    pixdim[4] = 0.0
+        - dim[5] = 3                     intent_code = NIFTI_INTENT_VECTOR
+     - A single time series with a 3x3 matrix at each point:
+        - dim[0] = 5
+        - dim[1] = 1                     xyzt_units = NIFTI_UNITS_SEC
+        - dim[2] = 1
+        - dim[3] = 1
+        - dim[4] = 1200 pixdim[4] = 0.2
+        - dim[5] = 9                     intent_code = NIFTI_INTENT_GENMATRIX
+        - intent_p1 = intent_p2 = 3.0    (indicates matrix dimensions)
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA STORAGE:
+   ------------
+   If the magic field is "n+1", then the voxel data is stored in the
+   same file as the header.  In this case, the voxel data starts at offset
+   (int)vox_offset into the header file.  Thus, vox_offset=352.0 means that
+   the data starts immediately after the NIFTI-1 header.  If vox_offset is
+   greater than 352, the NIFTI-1 format does not say much about the
+   contents of the dataset file between the end of the header and the
+   start of the data.
+
+   FILES:
+   -----
+   If the magic field is "ni1", then the voxel data is stored in the
+   associated ".img" file, starting at offset 0 (i.e., vox_offset is not
+   used in this case, and should be set to 0.0).
+
+   When storing NIFTI-1 datasets in pairs of files, it is customary to name
+   the files in the pattern "name.hdr" and "name.img", as in ANALYZE 7.5.
+   When storing in a single file ("n+1"), the file name should be in
+   the form "name.nii" (the ".nft" and ".nif" suffixes are already taken;
+   cf. http://www.icdatamaster.com/n.html ).
+
+   BYTE ORDERING:
+   -------------
+   The byte order of the data arrays is presumed to be the same as the byte
+   order of the header (which is determined by examining dim[0]).
+
+   Floating point types are presumed to be stored in IEEE-754 format.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DETAILS ABOUT vox_offset:
+   ------------------------
+   In a .nii file, the vox_offset field value is interpreted as the start
+   location of the image data bytes in that file. In a .hdr/.img file pair,
+   the vox_offset field value is the start location of the image data
+   bytes in the .img file.
+    * If vox_offset is less than 352 in a .nii file, it is equivalent
+      to 352 (i.e., image data never starts before byte #352 in a .nii file).
+    * The default value for vox_offset in a .nii file is 352.
+    * In a .hdr file, the default value for vox_offset is 0.
+    * vox_offset should be an integer multiple of 16; otherwise, some
+      programs may not work properly (e.g., SPM). This is to allow
+      memory-mapped input to be properly byte-aligned.
+   Note that since vox_offset is an IEEE-754 32 bit float (for compatibility
+   with the ANALYZE-7.5 format), it effectively has a 24 bit mantissa. All
+   integers from 0 to 2^24 can be represented exactly in this format, but not
+   all larger integers are exactly storable as IEEE-754 32 bit floats. However,
+   unless you plan to have vox_offset be potentially larger than 16 MB, this
+   should not be an issue. (Actually, any integral multiple of 16 up to 2^27
+   can be represented exactly in this format, which allows for up to 128 MB
+   of random information before the image data.  If that isn't enough, then
+   perhaps this format isn't right for you.)
+
+   In a .img file (i.e., image data stored separately from the NIfTI-1
+   header), data bytes between #0 and #vox_offset-1 (inclusive) are completely
+   undefined and unregulated by the NIfTI-1 standard. One potential use of
+   having vox_offset > 0 in the .hdr/.img file pair storage method is to make
+   the .img file be a copy of (or link to) a pre-existing image file in some
+   other format, such as DICOM; then vox_offset would be set to the offset of
+   the image data in this file. (It may not be possible to follow the
+   "multiple-of-16 rule" with an arbitrary external file; using the NIfTI-1
+   format in such a case may lead to a file that is incompatible with software
+   that relies on vox_offset being a multiple of 16.)
+
+   In a .nii file, data bytes between #348 and #vox_offset-1 (inclusive) may
+   be used to store user-defined extra information; similarly, in a .hdr file,
+   any data bytes after byte #347 are available for user-defined extra
+   information. The (very weak) regulation of this extra header data is
+   described elsewhere.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA SCALING:
+   ------------
+   If the scl_slope field is nonzero, then each voxel value in the dataset
+   should be scaled as
+      y = scl_slope * x + scl_inter
+   where x = voxel value stored
+         y = "true" voxel value
+   Normally, we would expect this scaling to be used to store "true" floating
+   values in a smaller integer datatype, but that is not required.  That is,
+   it is legal to use scaling even if the datatype is a float type (crazy,
+   perhaps, but legal).
+    - However, the scaling is to be ignored if datatype is DT_RGB24.
+    - If datatype is a complex type, then the scaling is to be
+      applied to both the real and imaginary parts.
+
+   The cal_min and cal_max fields (if nonzero) are used for mapping (possibly
+   scaled) dataset values to display colors:
+    - Minimum display intensity (black) corresponds to dataset value cal_min.
+    - Maximum display intensity (white) corresponds to dataset value cal_max.
+    - Dataset values below cal_min should display as black also, and values
+      above cal_max as white.
+    - Colors "black" and "white", of course, may refer to any scalar display
+      scheme (e.g., a color lookup table specified via aux_file).
+    - cal_min and cal_max only make sense when applied to scalar-valued
+      datasets (i.e., dim[0] < 5 or dim[5] = 1).
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* TYPE OF DATA (acceptable values for datatype field):
+   ---------------------------------------------------
+   Values of datatype smaller than 256 are ANALYZE 7.5 compatible.
+   Larger values are NIFTI-1 additions.  These are all multiples of 256, so
+   that no bits below position 8 are set in datatype.  But there is no need
+   to use only powers-of-2, as the original ANALYZE 7.5 datatype codes do.
+
+   The additional codes are intended to include a complete list of basic
+   scalar types, including signed and unsigned integers from 8 to 64 bits,
+   floats from 32 to 128 bits, and complex (float pairs) from 64 to 256 bits.
+
+   Note that most programs will support only a few of these datatypes!
+   A NIFTI-1 program should fail gracefully (e.g., print a warning message)
+   when it encounters a dataset with a type it doesn't like.
+-----------------------------------------------------------------------------*/
+
+#undef DT_UNKNOWN  /* defined in dirent.h on some Unix systems */
+
+/*! \defgroup NIFTI1_DATATYPES
+    \brief nifti1 datatype codes
+    @{
+ */
+                            /*--- the original ANALYZE 7.5 type codes ---*/
+#define DT_NONE                    0
+#define DT_UNKNOWN                 0     /* what it says, dude           */
+#define DT_BINARY                  1     /* binary (1 bit/voxel)         */
+#define DT_UNSIGNED_CHAR           2     /* unsigned char (8 bits/voxel) */
+#define DT_SIGNED_SHORT            4     /* signed short (16 bits/voxel) */
+#define DT_SIGNED_INT              8     /* signed int (32 bits/voxel)   */
+#define DT_FLOAT                  16     /* float (32 bits/voxel)        */
+#define DT_COMPLEX                32     /* complex (64 bits/voxel)      */
+#define DT_DOUBLE                 64     /* double (64 bits/voxel)       */
+#define DT_RGB                   128     /* RGB triple (24 bits/voxel)   */
+#define DT_ALL                   255     /* not very useful (?)          */
+
+                            /*----- another set of names for the same ---*/
+#define DT_UINT8                   2
+#define DT_INT16                   4
+#define DT_INT32                   8
+#define DT_FLOAT32                16
+#define DT_COMPLEX64              32
+#define DT_FLOAT64                64
+#define DT_RGB24                 128
+
+                            /*------------------- new codes for NIFTI ---*/
+#define DT_INT8                  256     /* signed char (8 bits)         */
+#define DT_UINT16                512     /* unsigned short (16 bits)     */
+#define DT_UINT32                768     /* unsigned int (32 bits)       */
+#define DT_INT64                1024     /* long long (64 bits)          */
+#define DT_UINT64               1280     /* unsigned long long (64 bits) */
+#define DT_FLOAT128             1536     /* long double (128 bits)       */
+#define DT_COMPLEX128           1792     /* double pair (128 bits)       */
+#define DT_COMPLEX256           2048     /* long double pair (256 bits)  */
+#define DT_RGBA32               2304     /* 4 byte RGBA (32 bits/voxel)  */
+/* @} */
+
+
+                            /*------- aliases for all the above codes ---*/
+
+/*! \defgroup NIFTI1_DATATYPE_ALIASES
+    \brief aliases for the nifti1 datatype codes
+    @{
+ */
+                                       /*! unsigned char. */
+#define NIFTI_TYPE_UINT8           2
+                                       /*! signed short. */
+#define NIFTI_TYPE_INT16           4
+                                       /*! signed int. */
+#define NIFTI_TYPE_INT32           8
+                                       /*! 32 bit float. */
+#define NIFTI_TYPE_FLOAT32        16
+                                       /*! 64 bit complex = 2 32 bit floats. */
+#define NIFTI_TYPE_COMPLEX64      32
+                                       /*! 64 bit float = double. */
+#define NIFTI_TYPE_FLOAT64        64
+                                       /*! 3 8 bit bytes. */
+#define NIFTI_TYPE_RGB24         128
+                                       /*! signed char. */
+#define NIFTI_TYPE_INT8          256
+                                       /*! unsigned short. */
+#define NIFTI_TYPE_UINT16        512
+                                       /*! unsigned int. */
+#define NIFTI_TYPE_UINT32        768
+                                       /*! signed long long. */
+#define NIFTI_TYPE_INT64        1024
+                                       /*! unsigned long long. */
+#define NIFTI_TYPE_UINT64       1280
+                                       /*! 128 bit float = long double. */
+#define NIFTI_TYPE_FLOAT128     1536
+                                       /*! 128 bit complex = 2 64 bit floats. */
+#define NIFTI_TYPE_COMPLEX128   1792
+                                       /*! 256 bit complex = 2 128 bit floats */
+#define NIFTI_TYPE_COMPLEX256   2048
+                                       /*! 4 8 bit bytes. */
+#define NIFTI_TYPE_RGBA32       2304
+/* @} */
+
+                     /*-------- sample typedefs for complicated types ---*/
+#if 0
+typedef struct { float       r,i;     } complex_float ;
+typedef struct { double      r,i;     } complex_double ;
+typedef struct { long double r,i;     } complex_longdouble ;
+typedef struct { unsigned char r,g,b; } rgb_byte ;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* INTERPRETATION OF VOXEL DATA:
+   ----------------------------
+   The intent_code field can be used to indicate that the voxel data has
+   some particular meaning.  In particular, a large number of codes is
+   given to indicate that the the voxel data should be interpreted as
+   being drawn from a given probability distribution.
+
+   VECTOR-VALUED DATASETS:
+   ----------------------
+   The 5th dimension of the dataset, if present (i.e., dim[0]=5 and
+   dim[5] > 1), contains multiple values (e.g., a vector) to be stored
+   at each spatiotemporal location.  For example, the header values
+    - dim[0] = 5
+    - dim[1] = 64
+    - dim[2] = 64
+    - dim[3] = 20
+    - dim[4] = 1     (indicates no time axis)
+    - dim[5] = 3
+    - datatype = DT_FLOAT
+    - intent_code = NIFTI_INTENT_VECTOR
+   mean that this dataset should be interpreted as a 3D volume (64x64x20),
+   with a 3-vector of floats defined at each point in the 3D grid.
+
+   A program reading a dataset with a 5th dimension may want to reformat
+   the image data to store each voxels' set of values together in a struct
+   or array.  This programming detail, however, is beyond the scope of the
+   NIFTI-1 file specification!  Uses of dimensions 6 and 7 are also not
+   specified here.
+
+   STATISTICAL PARAMETRIC DATASETS (i.e., SPMs):
+   --------------------------------------------
+   Values of intent_code from NIFTI_FIRST_STATCODE to NIFTI_LAST_STATCODE
+   (inclusive) indicate that the numbers in the dataset should be interpreted
+   as being drawn from a given distribution.  Most such distributions have
+   auxiliary parameters (e.g., NIFTI_INTENT_TTEST has 1 DOF parameter).
+
+   If the dataset DOES NOT have a 5th dimension, then the auxiliary parameters
+   are the same for each voxel, and are given in header fields intent_p1,
+   intent_p2, and intent_p3.
+
+   If the dataset DOES have a 5th dimension, then the auxiliary parameters
+   are different for each voxel.  For example, the header values
+    - dim[0] = 5
+    - dim[1] = 128
+    - dim[2] = 128
+    - dim[3] = 1      (indicates a single slice)
+    - dim[4] = 1      (indicates no time axis)
+    - dim[5] = 2
+    - datatype = DT_FLOAT
+    - intent_code = NIFTI_INTENT_TTEST
+   mean that this is a 2D dataset (128x128) of t-statistics, with the
+   t-statistic being in the first "plane" of data and the degrees-of-freedom
+   parameter being in the second "plane" of data.
+
+   If the dataset 5th dimension is used to store the voxel-wise statistical
+   parameters, then dim[5] must be 1 plus the number of parameters required
+   by that distribution (e.g., intent_code=NIFTI_INTENT_TTEST implies dim[5]
+   must be 2, as in the example just above).
+
+   Note: intent_code values 2..10 are compatible with AFNI 1.5x (which is
+   why there is no code with value=1, which is obsolescent in AFNI).
+
+   OTHER INTENTIONS:
+   ----------------
+   The purpose of the intent_* fields is to help interpret the values
+   stored in the dataset.  Some non-statistical values for intent_code
+   and conventions are provided for storing other complex data types.
+
+   The intent_name field provides space for a 15 character (plus 0 byte)
+   'name' string for the type of data stored. Examples:
+    - intent_code = NIFTI_INTENT_ESTIMATE; intent_name = "T1";
+       could be used to signify that the voxel values are estimates of the
+       NMR parameter T1.
+    - intent_code = NIFTI_INTENT_TTEST; intent_name = "House";
+       could be used to signify that the voxel values are t-statistics
+       for the significance of 'activation' response to a House stimulus.
+    - intent_code = NIFTI_INTENT_DISPVECT; intent_name = "ToMNI152";
+       could be used to signify that the voxel values are a displacement
+       vector that transforms each voxel (x,y,z) location to the
+       corresponding location in the MNI152 standard brain.
+    - intent_code = NIFTI_INTENT_SYMMATRIX; intent_name = "DTI";
+       could be used to signify that the voxel values comprise a diffusion
+       tensor image.
+
+   If no data name is implied or needed, intent_name[0] should be set to 0.
+-----------------------------------------------------------------------------*/
+
+ /*! default: no intention is indicated in the header. */
+
+#define NIFTI_INTENT_NONE        0
+
+    /*-------- These codes are for probability distributions ---------------*/
+    /* Most distributions have a number of parameters,
+       below denoted by p1, p2, and p3, and stored in
+        - intent_p1, intent_p2, intent_p3 if dataset doesn't have 5th dimension
+        - image data array                if dataset does have 5th dimension
+
+       Functions to compute with many of the distributions below can be found
+       in the CDF library from U Texas.
+
+       Formulas for and discussions of these distributions can be found in the
+       following books:
+
+        [U] Univariate Discrete Distributions,
+            NL Johnson, S Kotz, AW Kemp.
+
+        [C1] Continuous Univariate Distributions, vol. 1,
+             NL Johnson, S Kotz, N Balakrishnan.
+
+        [C2] Continuous Univariate Distributions, vol. 2,
+             NL Johnson, S Kotz, N Balakrishnan.                            */
+    /*----------------------------------------------------------------------*/
+
+  /*! [C2, chap 32] Correlation coefficient R (1 param):
+       p1 = degrees of freedom
+       R/sqrt(1-R*R) is t-distributed with p1 DOF. */
+
+/*! \defgroup NIFTI1_INTENT_CODES
+    \brief nifti1 intent codes, to describe intended meaning of dataset contents
+    @{
+ */
+#define NIFTI_INTENT_CORREL      2
+
+  /*! [C2, chap 28] Student t statistic (1 param): p1 = DOF. */
+
+#define NIFTI_INTENT_TTEST       3
+
+  /*! [C2, chap 27] Fisher F statistic (2 params):
+       p1 = numerator DOF, p2 = denominator DOF. */
+
+#define NIFTI_INTENT_FTEST       4
+
+  /*! [C1, chap 13] Standard normal (0 params): Density = N(0,1). */
+
+#define NIFTI_INTENT_ZSCORE      5
+
+  /*! [C1, chap 18] Chi-squared (1 param): p1 = DOF.
+      Density(x) proportional to exp(-x/2) * x^(p1/2-1). */
+
+#define NIFTI_INTENT_CHISQ       6
+
+  /*! [C2, chap 25] Beta distribution (2 params): p1=a, p2=b.
+      Density(x) proportional to x^(a-1) * (1-x)^(b-1). */
+
+#define NIFTI_INTENT_BETA        7
+
+  /*! [U, chap 3] Binomial distribution (2 params):
+       p1 = number of trials, p2 = probability per trial.
+      Prob(x) = (p1 choose x) * p2^x * (1-p2)^(p1-x), for x=0,1,...,p1. */
+
+#define NIFTI_INTENT_BINOM       8
+
+  /*! [C1, chap 17] Gamma distribution (2 params):
+       p1 = shape, p2 = scale.
+      Density(x) proportional to x^(p1-1) * exp(-p2*x). */
+
+#define NIFTI_INTENT_GAMMA       9
+
+  /*! [U, chap 4] Poisson distribution (1 param): p1 = mean.
+      Prob(x) = exp(-p1) * p1^x / x! , for x=0,1,2,.... */
+
+#define NIFTI_INTENT_POISSON    10
+
+  /*! [C1, chap 13] Normal distribution (2 params):
+       p1 = mean, p2 = standard deviation. */
+
+#define NIFTI_INTENT_NORMAL     11
+
+  /*! [C2, chap 30] Noncentral F statistic (3 params):
+       p1 = numerator DOF, p2 = denominator DOF,
+       p3 = numerator noncentrality parameter.  */
+
+#define NIFTI_INTENT_FTEST_NONC 12
+
+  /*! [C2, chap 29] Noncentral chi-squared statistic (2 params):
+       p1 = DOF, p2 = noncentrality parameter.     */
+
+#define NIFTI_INTENT_CHISQ_NONC 13
+
+  /*! [C2, chap 23] Logistic distribution (2 params):
+       p1 = location, p2 = scale.
+      Density(x) proportional to sech^2((x-p1)/(2*p2)). */
+
+#define NIFTI_INTENT_LOGISTIC   14
+
+  /*! [C2, chap 24] Laplace distribution (2 params):
+       p1 = location, p2 = scale.
+      Density(x) proportional to exp(-abs(x-p1)/p2). */
+
+#define NIFTI_INTENT_LAPLACE    15
+
+  /*! [C2, chap 26] Uniform distribution: p1 = lower end, p2 = upper end. */
+
+#define NIFTI_INTENT_UNIFORM    16
+
+  /*! [C2, chap 31] Noncentral t statistic (2 params):
+       p1 = DOF, p2 = noncentrality parameter. */
+
+#define NIFTI_INTENT_TTEST_NONC 17
+
+  /*! [C1, chap 21] Weibull distribution (3 params):
+       p1 = location, p2 = scale, p3 = power.
+      Density(x) proportional to
+       ((x-p1)/p2)^(p3-1) * exp(-((x-p1)/p2)^p3) for x > p1. */
+
+#define NIFTI_INTENT_WEIBULL    18
+
+  /*! [C1, chap 18] Chi distribution (1 param): p1 = DOF.
+      Density(x) proportional to x^(p1-1) * exp(-x^2/2) for x > 0.
+       p1 = 1 = 'half normal' distribution
+       p1 = 2 = Rayleigh distribution
+       p1 = 3 = Maxwell-Boltzmann distribution.                  */
+
+#define NIFTI_INTENT_CHI        19
+
+  /*! [C1, chap 15] Inverse Gaussian (2 params):
+       p1 = mu, p2 = lambda
+      Density(x) proportional to
+       exp(-p2*(x-p1)^2/(2*p1^2*x)) / x^3  for x > 0. */
+
+#define NIFTI_INTENT_INVGAUSS   20
+
+  /*! [C2, chap 22] Extreme value type I (2 params):
+       p1 = location, p2 = scale
+      cdf(x) = exp(-exp(-(x-p1)/p2)). */
+
+#define NIFTI_INTENT_EXTVAL     21
+
+  /*! Data is a 'p-value' (no params). */
+
+#define NIFTI_INTENT_PVAL       22
+
+  /*! Data is ln(p-value) (no params).
+      To be safe, a program should compute p = exp(-abs(this_value)).
+      The nifti_stats.c library returns this_value
+      as positive, so that this_value = -log(p). */
+
+
+#define NIFTI_INTENT_LOGPVAL    23
+
+  /*! Data is log10(p-value) (no params).
+      To be safe, a program should compute p = pow(10.,-abs(this_value)).
+      The nifti_stats.c library returns this_value
+      as positive, so that this_value = -log10(p). */
+
+#define NIFTI_INTENT_LOG10PVAL  24
+
+  /*! Smallest intent_code that indicates a statistic. */
+
+#define NIFTI_FIRST_STATCODE     2
+
+  /*! Largest intent_code that indicates a statistic. */
+
+#define NIFTI_LAST_STATCODE     24
+
+ /*---------- these values for intent_code aren't for statistics ----------*/
+
+ /*! To signify that the value at each voxel is an estimate
+     of some parameter, set intent_code = NIFTI_INTENT_ESTIMATE.
+     The name of the parameter may be stored in intent_name.     */
+
+#define NIFTI_INTENT_ESTIMATE  1001
+
+ /*! To signify that the value at each voxel is an index into
+     some set of labels, set intent_code = NIFTI_INTENT_LABEL.
+     The filename with the labels may stored in aux_file.        */
+
+#define NIFTI_INTENT_LABEL     1002
+
+ /*! To signify that the value at each voxel is an index into the
+     NeuroNames labels set, set intent_code = NIFTI_INTENT_NEURONAME. */
+
+#define NIFTI_INTENT_NEURONAME 1003
+
+ /*! To store an M x N matrix at each voxel:
+       - dataset must have a 5th dimension (dim[0]=5 and dim[5]>1)
+       - intent_code must be NIFTI_INTENT_GENMATRIX
+       - dim[5] must be M*N
+       - intent_p1 must be M (in float format)
+       - intent_p2 must be N (ditto)
+       - the matrix values A[i][[j] are stored in row-order:
+         - A[0][0] A[0][1] ... A[0][N-1]
+         - A[1][0] A[1][1] ... A[1][N-1]
+         - etc., until
+         - A[M-1][0] A[M-1][1] ... A[M-1][N-1]        */
+
+#define NIFTI_INTENT_GENMATRIX 1004
+
+ /*! To store an NxN symmetric matrix at each voxel:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_SYMMATRIX
+       - dim[5] must be N*(N+1)/2
+       - intent_p1 must be N (in float format)
+       - the matrix values A[i][[j] are stored in row-order:
+         - A[0][0]
+         - A[1][0] A[1][1]
+         - A[2][0] A[2][1] A[2][2]
+         - etc.: row-by-row                           */
+
+#define NIFTI_INTENT_SYMMATRIX 1005
+
+ /*! To signify that the vector value at each voxel is to be taken
+     as a displacement field or vector:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_DISPVECT
+       - dim[5] must be the dimensionality of the displacment
+         vector (e.g., 3 for spatial displacement, 2 for in-plane) */
+
+#define NIFTI_INTENT_DISPVECT  1006   /* specifically for displacements */
+#define NIFTI_INTENT_VECTOR    1007   /* for any other type of vector */
+
+ /*! To signify that the vector value at each voxel is really a
+     spatial coordinate (e.g., the vertices or nodes of a surface mesh):
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_POINTSET
+       - dim[0] = 5
+       - dim[1] = number of points
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] must be the dimensionality of space (e.g., 3 => 3D space).
+       - intent_name may describe the object these points come from
+         (e.g., "pial", "gray/white" , "EEG", "MEG").                   */
+
+#define NIFTI_INTENT_POINTSET  1008
+
+ /*! To signify that the vector value at each voxel is really a triple
+     of indexes (e.g., forming a triangle) from a pointset dataset:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_TRIANGLE
+       - dim[0] = 5
+       - dim[1] = number of triangles
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] = 3
+       - datatype should be an integer type (preferably DT_INT32)
+       - the data values are indexes (0,1,...) into a pointset dataset. */
+
+#define NIFTI_INTENT_TRIANGLE  1009
+
+ /*! To signify that the vector value at each voxel is a quaternion:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_QUATERNION
+       - dim[0] = 5
+       - dim[5] = 4
+       - datatype should be a floating point type     */
+
+#define NIFTI_INTENT_QUATERNION 1010
+
+ /*! Dimensionless value - no params - although, as in _ESTIMATE 
+     the name of the parameter may be stored in intent_name.     */
+
+#define NIFTI_INTENT_DIMLESS    1011
+
+ /*---------- these values apply to GIFTI datasets ----------*/
+
+ /*! To signify that the value at each location is from a time series. */
+
+#define NIFTI_INTENT_TIME_SERIES  2001
+
+ /*! To signify that the value at each location is a node index, from
+     a complete surface dataset.                                       */
+
+#define NIFTI_INTENT_NODE_INDEX   2002
+
+ /*! To signify that the vector value at each location is an RGB triplet,
+     of whatever type.
+       - dataset must have a 5th dimension
+       - dim[0] = 5
+       - dim[1] = number of nodes
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] = 3
+    */
+
+#define NIFTI_INTENT_RGB_VECTOR   2003
+
+ /*! To signify that the vector value at each location is a 4 valued RGBA
+     vector, of whatever type.
+       - dataset must have a 5th dimension
+       - dim[0] = 5
+       - dim[1] = number of nodes
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] = 4
+    */
+
+#define NIFTI_INTENT_RGBA_VECTOR  2004
+
+ /*! To signify that the value at each location is a shape value, such
+     as the curvature.  */
+
+#define NIFTI_INTENT_SHAPE        2005
+
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* 3D IMAGE (VOLUME) ORIENTATION AND LOCATION IN SPACE:
+   ---------------------------------------------------
+   There are 3 different methods by which continuous coordinates can
+   attached to voxels.  The discussion below emphasizes 3D volumes, and
+   the continuous coordinates are referred to as (x,y,z).  The voxel
+   index coordinates (i.e., the array indexes) are referred to as (i,j,k),
+   with valid ranges:
+     i = 0 .. dim[1]-1
+     j = 0 .. dim[2]-1  (if dim[0] >= 2)
+     k = 0 .. dim[3]-1  (if dim[0] >= 3)
+   The (x,y,z) coordinates refer to the CENTER of a voxel.  In methods
+   2 and 3, the (x,y,z) axes refer to a subject-based coordinate system,
+   with
+     +x = Right  +y = Anterior  +z = Superior.
+   This is a right-handed coordinate system.  However, the exact direction
+   these axes point with respect to the subject depends on qform_code
+   (Method 2) and sform_code (Method 3).
+
+   N.B.: The i index varies most rapidly, j index next, k index slowest.
+    Thus, voxel (i,j,k) is stored starting at location
+      (i + j*dim[1] + k*dim[1]*dim[2]) * (bitpix/8)
+    into the dataset array.
+
+   N.B.: The ANALYZE 7.5 coordinate system is
+      +x = Left  +y = Anterior  +z = Superior
+    which is a left-handed coordinate system.  This backwardness is
+    too difficult to tolerate, so this NIFTI-1 standard specifies the
+    coordinate order which is most common in functional neuroimaging.
+
+   N.B.: The 3 methods below all give the locations of the voxel centers
+    in the (x,y,z) coordinate system.  In many cases, programs will wish
+    to display image data on some other grid.  In such a case, the program
+    will need to convert its desired (x,y,z) values into (i,j,k) values
+    in order to extract (or interpolate) the image data.  This operation
+    would be done with the inverse transformation to those described below.
+
+   N.B.: Method 2 uses a factor 'qfac' which is either -1 or 1; qfac is
+    stored in the otherwise unused pixdim[0].  If pixdim[0]=0.0 (which
+    should not occur), we take qfac=1.  Of course, pixdim[0] is only used
+    when reading a NIFTI-1 header, not when reading an ANALYZE 7.5 header.
+
+   N.B.: The units of (x,y,z) can be specified using the xyzt_units field.
+
+   METHOD 1 (the "old" way, used only when qform_code = 0):
+   -------------------------------------------------------
+   The coordinate mapping from (i,j,k) to (x,y,z) is the ANALYZE
+   7.5 way.  This is a simple scaling relationship:
+
+     x = pixdim[1] * i
+     y = pixdim[2] * j
+     z = pixdim[3] * k
+
+   No particular spatial orientation is attached to these (x,y,z)
+   coordinates.  (NIFTI-1 does not have the ANALYZE 7.5 orient field,
+   which is not general and is often not set properly.)  This method
+   is not recommended, and is present mainly for compatibility with
+   ANALYZE 7.5 files.
+
+   METHOD 2 (used when qform_code > 0, which should be the "normal" case):
+   ---------------------------------------------------------------------
+   The (x,y,z) coordinates are given by the pixdim[] scales, a rotation
+   matrix, and a shift.  This method is intended to represent
+   "scanner-anatomical" coordinates, which are often embedded in the
+   image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030),
+   and (0018,0050)), and represent the nominal orientation and location of
+   the data.  This method can also be used to represent "aligned"
+   coordinates, which would typically result from some post-acquisition
+   alignment of the volume to a standard orientation (e.g., the same
+   subject on another day, or a rigid rotation to true anatomical
+   orientation from the tilted position of the subject in the scanner).
+   The formula for (x,y,z) in terms of header parameters and (i,j,k) is:
+
+     [ x ]   [ R11 R12 R13 ] [        pixdim[1] * i ]   [ qoffset_x ]
+     [ y ] = [ R21 R22 R23 ] [        pixdim[2] * j ] + [ qoffset_y ]
+     [ z ]   [ R31 R32 R33 ] [ qfac * pixdim[3] * k ]   [ qoffset_z ]
+
+   The qoffset_* shifts are in the NIFTI-1 header.  Note that the center
+   of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is
+   just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z).
+
+   The rotation matrix R is calculated from the quatern_* parameters.
+   This calculation is described below.
+
+   The scaling factor qfac is either 1 or -1.  The rotation matrix R
+   defined by the quaternion parameters is "proper" (has determinant 1).
+   This may not fit the needs of the data; for example, if the image
+   grid is
+     i increases from Left-to-Right
+     j increases from Anterior-to-Posterior
+     k increases from Inferior-to-Superior
+   Then (i,j,k) is a left-handed triple.  In this example, if qfac=1,
+   the R matrix would have to be
+
+     [  1   0   0 ]
+     [  0  -1   0 ]  which is "improper" (determinant = -1).
+     [  0   0   1 ]
+
+   If we set qfac=-1, then the R matrix would be
+
+     [  1   0   0 ]
+     [  0  -1   0 ]  which is proper.
+     [  0   0  -1 ]
+
+   This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0]
+   (which encodes a 180 degree rotation about the x-axis).
+
+   METHOD 3 (used when sform_code > 0):
+   -----------------------------------
+   The (x,y,z) coordinates are given by a general affine transformation
+   of the (i,j,k) indexes:
+
+     x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3]
+     y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3]
+     z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3]
+
+   The srow_* vectors are in the NIFTI_1 header.  Note that no use is
+   made of pixdim[] in this method.
+
+   WHY 3 METHODS?
+   --------------
+   Method 1 is provided only for backwards compatibility.  The intention
+   is that Method 2 (qform_code > 0) represents the nominal voxel locations
+   as reported by the scanner, or as rotated to some fiducial orientation and
+   location.  Method 3, if present (sform_code > 0), is to be used to give
+   the location of the voxels in some standard space.  The sform_code
+   indicates which standard space is present.  Both methods 2 and 3 can be
+   present, and be useful in different contexts (method 2 for displaying the
+   data on its original grid; method 3 for displaying it on a standard grid).
+
+   In this scheme, a dataset would originally be set up so that the
+   Method 2 coordinates represent what the scanner reported.  Later,
+   a registration to some standard space can be computed and inserted
+   in the header.  Image display software can use either transform,
+   depending on its purposes and needs.
+
+   In Method 2, the origin of coordinates would generally be whatever
+   the scanner origin is; for example, in MRI, (0,0,0) is the center
+   of the gradient coil.
+
+   In Method 3, the origin of coordinates would depend on the value
+   of sform_code; for example, for the Talairach coordinate system,
+   (0,0,0) corresponds to the Anterior Commissure.
+
+   QUATERNION REPRESENTATION OF ROTATION MATRIX (METHOD 2)
+   -------------------------------------------------------
+   The orientation of the (x,y,z) axes relative to the (i,j,k) axes
+   in 3D space is specified using a unit quaternion [a,b,c,d], where
+   a*a+b*b+c*c+d*d=1.  The (b,c,d) values are all that is needed, since
+   we require that a = sqrt(1.0-(b*b+c*c+d*d)) be nonnegative.  The (b,c,d)
+   values are stored in the (quatern_b,quatern_c,quatern_d) fields.
+
+   The quaternion representation is chosen for its compactness in
+   representing rotations. The (proper) 3x3 rotation matrix that
+   corresponds to [a,b,c,d] is
+
+         [ a*a+b*b-c*c-d*d   2*b*c-2*a*d       2*b*d+2*a*c     ]
+     R = [ 2*b*c+2*a*d       a*a+c*c-b*b-d*d   2*c*d-2*a*b     ]
+         [ 2*b*d-2*a*c       2*c*d+2*a*b       a*a+d*d-c*c-b*b ]
+
+         [ R11               R12               R13             ]
+       = [ R21               R22               R23             ]
+         [ R31               R32               R33             ]
+
+   If (p,q,r) is a unit 3-vector, then rotation of angle h about that
+   direction is represented by the quaternion
+
+     [a,b,c,d] = [cos(h/2), p*sin(h/2), q*sin(h/2), r*sin(h/2)].
+
+   Requiring a >= 0 is equivalent to requiring -Pi <= h <= Pi.  (Note that
+   [-a,-b,-c,-d] represents the same rotation as [a,b,c,d]; there are 2
+   quaternions that can be used to represent a given rotation matrix R.)
+   To rotate a 3-vector (x,y,z) using quaternions, we compute the
+   quaternion product
+
+     [0,x',y',z'] = [a,b,c,d] * [0,x,y,z] * [a,-b,-c,-d]
+
+   which is equivalent to the matrix-vector multiply
+
+     [ x' ]     [ x ]
+     [ y' ] = R [ y ]   (equivalence depends on a*a+b*b+c*c+d*d=1)
+     [ z' ]     [ z ]
+
+   Multiplication of 2 quaternions is defined by the following:
+
+     [a,b,c,d] = a*1 + b*I + c*J + d*K
+     where
+       I*I = J*J = K*K = -1 (I,J,K are square roots of -1)
+       I*J =  K    J*K =  I    K*I =  J
+       J*I = -K    K*J = -I    I*K = -J  (not commutative!)
+     For example
+       [a,b,0,0] * [0,0,0,1] = [0,0,-b,a]
+     since this expands to
+       (a+b*I)*(K) = (a*K+b*I*K) = (a*K-b*J).
+
+   The above formula shows how to go from quaternion (b,c,d) to
+   rotation matrix and direction cosines.  Conversely, given R,
+   we can compute the fields for the NIFTI-1 header by
+
+     a = 0.5  * sqrt(1+R11+R22+R33)    (not stored)
+     b = 0.25 * (R32-R23) / a       => quatern_b
+     c = 0.25 * (R13-R31) / a       => quatern_c
+     d = 0.25 * (R21-R12) / a       => quatern_d
+
+   If a=0 (a 180 degree rotation), alternative formulas are needed.
+   See the nifti1_io.c function mat44_to_quatern() for an implementation
+   of the various cases in converting R to [a,b,c,d].
+
+   Note that R-transpose (= R-inverse) would lead to the quaternion
+   [a,-b,-c,-d].
+
+   The choice to specify the qoffset_x (etc.) values in the final
+   coordinate system is partly to make it easy to convert DICOM images to
+   this format.  The DICOM attribute "Image Position (Patient)" (0020,0032)
+   stores the (Xd,Yd,Zd) coordinates of the center of the first voxel.
+   Here, (Xd,Yd,Zd) refer to DICOM coordinates, and Xd=-x, Yd=-y, Zd=z,
+   where (x,y,z) refers to the NIFTI coordinate system discussed above.
+   (i.e., DICOM +Xd is Left, +Yd is Posterior, +Zd is Superior,
+        whereas +x is Right, +y is Anterior  , +z is Superior. )
+   Thus, if the (0020,0032) DICOM attribute is extracted into (px,py,pz), then
+     qoffset_x = -px   qoffset_y = -py   qoffset_z = pz
+   is a reasonable setting when qform_code=NIFTI_XFORM_SCANNER_ANAT.
+
+   That is, DICOM's coordinate system is 180 degrees rotated about the z-axis
+   from the neuroscience/NIFTI coordinate system.  To transform between DICOM
+   and NIFTI, you just have to negate the x- and y-coordinates.
+
+   The DICOM attribute (0020,0037) "Image Orientation (Patient)" gives the
+   orientation of the x- and y-axes of the image data in terms of 2 3-vectors.
+   The first vector is a unit vector along the x-axis, and the second is
+   along the y-axis.  If the (0020,0037) attribute is extracted into the
+   value (xa,xb,xc,ya,yb,yc), then the first two columns of the R matrix
+   would be
+              [ -xa  -ya ]
+              [ -xb  -yb ]
+              [  xc   yc ]
+   The negations are because DICOM's x- and y-axes are reversed relative
+   to NIFTI's.  The third column of the R matrix gives the direction of
+   displacement (relative to the subject) along the slice-wise direction.
+   This orientation is not encoded in the DICOM standard in a simple way;
+   DICOM is mostly concerned with 2D images.  The third column of R will be
+   either the cross-product of the first 2 columns or its negative.  It is
+   possible to infer the sign of the 3rd column by examining the coordinates
+   in DICOM attribute (0020,0032) "Image Position (Patient)" for successive
+   slices.  However, this method occasionally fails for reasons that I
+   (RW Cox) do not understand.
+-----------------------------------------------------------------------------*/
+
+   /* [qs]form_code value:  */      /* x,y,z coordinate system refers to:    */
+   /*-----------------------*/      /*---------------------------------------*/
+
+/*! \defgroup NIFTI1_XFORM_CODES
+    \brief nifti1 xform codes to describe the "standard" coordinate system
+    @{
+ */
+                                    /*! Arbitrary coordinates (Method 1). */
+
+#define NIFTI_XFORM_UNKNOWN      0
+
+                                    /*! Scanner-based anatomical coordinates */
+
+#define NIFTI_XFORM_SCANNER_ANAT 1
+
+                                    /*! Coordinates aligned to another file's,
+                                        or to anatomical "truth".            */
+
+#define NIFTI_XFORM_ALIGNED_ANAT 2
+
+                                    /*! Coordinates aligned to Talairach-
+                                        Tournoux Atlas; (0,0,0)=AC, etc. */
+
+#define NIFTI_XFORM_TALAIRACH    3
+
+                                    /*! MNI 152 normalized coordinates. */
+
+#define NIFTI_XFORM_MNI_152      4
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* UNITS OF SPATIAL AND TEMPORAL DIMENSIONS:
+   ----------------------------------------
+   The codes below can be used in xyzt_units to indicate the units of pixdim.
+   As noted earlier, dimensions 1,2,3 are for x,y,z; dimension 4 is for
+   time (t).
+    - If dim[4]=1 or dim[0] < 4, there is no time axis.
+    - A single time series (no space) would be specified with
+      - dim[0] = 4 (for scalar data) or dim[0] = 5 (for vector data)
+      - dim[1] = dim[2] = dim[3] = 1
+      - dim[4] = number of time points
+      - pixdim[4] = time step
+      - xyzt_units indicates units of pixdim[4]
+      - dim[5] = number of values stored at each time point
+
+   Bits 0..2 of xyzt_units specify the units of pixdim[1..3]
+    (e.g., spatial units are values 1..7).
+   Bits 3..5 of xyzt_units specify the units of pixdim[4]
+    (e.g., temporal units are multiples of 8).
+
+   This compression of 2 distinct concepts into 1 byte is due to the
+   limited space available in the 348 byte ANALYZE 7.5 header.  The
+   macros XYZT_TO_SPACE and XYZT_TO_TIME can be used to mask off the
+   undesired bits from the xyzt_units fields, leaving "pure" space
+   and time codes.  Inversely, the macro SPACE_TIME_TO_XYZT can be
+   used to assemble a space code (0,1,2,...,7) with a time code
+   (0,8,16,32,...,56) into the combined value for xyzt_units.
+
+   Note that codes are provided to indicate the "time" axis units are
+   actually frequency in Hertz (_HZ), in part-per-million (_PPM)
+   or in radians-per-second (_RADS).
+
+   The toffset field can be used to indicate a nonzero start point for
+   the time axis.  That is, time point #m is at t=toffset+m*pixdim[4]
+   for m=0..dim[4]-1.
+-----------------------------------------------------------------------------*/
+
+/*! \defgroup NIFTI1_UNITS
+    \brief nifti1 units codes to describe the unit of measurement for
+           each dimension of the dataset
+    @{
+ */
+                               /*! NIFTI code for unspecified units. */
+#define NIFTI_UNITS_UNKNOWN 0
+
+                               /** Space codes are multiples of 1. **/
+                               /*! NIFTI code for meters. */
+#define NIFTI_UNITS_METER   1
+                               /*! NIFTI code for millimeters. */
+#define NIFTI_UNITS_MM      2
+                               /*! NIFTI code for micrometers. */
+#define NIFTI_UNITS_MICRON  3
+
+                               /** Time codes are multiples of 8. **/
+                               /*! NIFTI code for seconds. */
+#define NIFTI_UNITS_SEC     8
+                               /*! NIFTI code for milliseconds. */
+#define NIFTI_UNITS_MSEC   16
+                               /*! NIFTI code for microseconds. */
+#define NIFTI_UNITS_USEC   24
+
+                               /*** These units are for spectral data: ***/
+                               /*! NIFTI code for Hertz. */
+#define NIFTI_UNITS_HZ     32
+                               /*! NIFTI code for ppm. */
+#define NIFTI_UNITS_PPM    40
+                               /*! NIFTI code for radians per second. */
+#define NIFTI_UNITS_RADS   48
+/* @} */
+
+#undef  XYZT_TO_SPACE
+#undef  XYZT_TO_TIME
+#define XYZT_TO_SPACE(xyzt)       ( (xyzt) & 0x07 )
+#define XYZT_TO_TIME(xyzt)        ( (xyzt) & 0x38 )
+
+#undef  SPACE_TIME_TO_XYZT
+#define SPACE_TIME_TO_XYZT(ss,tt) (  (((char)(ss)) & 0x07)   \
+                                   | (((char)(tt)) & 0x38) )
+
+/*---------------------------------------------------------------------------*/
+/* MRI-SPECIFIC SPATIAL AND TEMPORAL INFORMATION:
+   ---------------------------------------------
+   A few fields are provided to store some extra information
+   that is sometimes important when storing the image data
+   from an FMRI time series experiment.  (After processing such
+   data into statistical images, these fields are not likely
+   to be useful.)
+
+  { freq_dim  } = These fields encode which spatial dimension (1,2, or 3)
+  { phase_dim } = corresponds to which acquisition dimension for MRI data.
+  { slice_dim } =
+    Examples:
+      Rectangular scan multi-slice EPI:
+        freq_dim = 1  phase_dim = 2  slice_dim = 3  (or some permutation)
+      Spiral scan multi-slice EPI:
+        freq_dim = phase_dim = 0  slice_dim = 3
+        since the concepts of frequency- and phase-encoding directions
+        don't apply to spiral scan
+
+    slice_duration = If this is positive, AND if slice_dim is nonzero,
+                     indicates the amount of time used to acquire 1 slice.
+                     slice_duration*dim[slice_dim] can be less than pixdim[4]
+                     with a clustered acquisition method, for example.
+
+    slice_code = If this is nonzero, AND if slice_dim is nonzero, AND
+                 if slice_duration is positive, indicates the timing
+                 pattern of the slice acquisition.  The following codes
+                 are defined:
+                   NIFTI_SLICE_SEQ_INC  == sequential increasing
+                   NIFTI_SLICE_SEQ_DEC  == sequential decreasing
+                   NIFTI_SLICE_ALT_INC  == alternating increasing
+                   NIFTI_SLICE_ALT_DEC  == alternating decreasing
+                   NIFTI_SLICE_ALT_INC2 == alternating increasing #2
+                   NIFTI_SLICE_ALT_DEC2 == alternating decreasing #2
+  { slice_start } = Indicates the start and end of the slice acquisition
+  { slice_end   } = pattern, when slice_code is nonzero.  These values
+                    are present to allow for the possible addition of
+                    "padded" slices at either end of the volume, which
+                    don't fit into the slice timing pattern.  If there
+                    are no padding slices, then slice_start=0 and
+                    slice_end=dim[slice_dim]-1 are the correct values.
+                    For these values to be meaningful, slice_start must
+                    be non-negative and slice_end must be greater than
+                    slice_start.  Otherwise, they should be ignored.
+
+  The following table indicates the slice timing pattern, relative to
+  time=0 for the first slice acquired, for some sample cases.  Here,
+  dim[slice_dim]=7 (there are 7 slices, labeled 0..6), slice_duration=0.1,
+  and slice_start=1, slice_end=5 (1 padded slice on each end).
+
+  slice
+  index  SEQ_INC SEQ_DEC ALT_INC ALT_DEC ALT_INC2 ALT_DEC2
+    6  :   n/a     n/a     n/a     n/a    n/a      n/a    n/a = not applicable
+    5  :   0.4     0.0     0.2     0.0    0.4      0.2    (slice time offset
+    4  :   0.3     0.1     0.4     0.3    0.1      0.0     doesn't apply to
+    3  :   0.2     0.2     0.1     0.1    0.3      0.3     slices outside
+    2  :   0.1     0.3     0.3     0.4    0.0      0.1     the range
+    1  :   0.0     0.4     0.0     0.2    0.2      0.4     slice_start ..
+    0  :   n/a     n/a     n/a     n/a    n/a      n/a     slice_end)
+
+  The SEQ slice_codes are sequential ordering (uncommon but not unknown),
+  either increasing in slice number or decreasing (INC or DEC), as
+  illustrated above.
+
+  The ALT slice codes are alternating ordering.  The 'standard' way for
+  these to operate (without the '2' on the end) is for the slice timing
+  to start at the edge of the slice_start .. slice_end group (at slice_start
+  for INC and at slice_end for DEC).  For the 'ALT_*2' slice_codes, the
+  slice timing instead starts at the first slice in from the edge (at
+  slice_start+1 for INC2 and at slice_end-1 for DEC2).  This latter
+  acquisition scheme is found on some Siemens scanners.
+
+  The fields freq_dim, phase_dim, slice_dim are all squished into the single
+  byte field dim_info (2 bits each, since the values for each field are
+  limited to the range 0..3).  This unpleasantness is due to lack of space
+  in the 348 byte allowance.
+
+  The macros DIM_INFO_TO_FREQ_DIM, DIM_INFO_TO_PHASE_DIM, and
+  DIM_INFO_TO_SLICE_DIM can be used to extract these values from the
+  dim_info byte.
+
+  The macro FPS_INTO_DIM_INFO can be used to put these 3 values
+  into the dim_info byte.
+-----------------------------------------------------------------------------*/
+
+#undef  DIM_INFO_TO_FREQ_DIM
+#undef  DIM_INFO_TO_PHASE_DIM
+#undef  DIM_INFO_TO_SLICE_DIM
+
+#define DIM_INFO_TO_FREQ_DIM(di)   ( ((di)     ) & 0x03 )
+#define DIM_INFO_TO_PHASE_DIM(di)  ( ((di) >> 2) & 0x03 )
+#define DIM_INFO_TO_SLICE_DIM(di)  ( ((di) >> 4) & 0x03 )
+
+#undef  FPS_INTO_DIM_INFO
+#define FPS_INTO_DIM_INFO(fd,pd,sd) ( ( ( ((char)(fd)) & 0x03)      ) |  \
+                                      ( ( ((char)(pd)) & 0x03) << 2 ) |  \
+                                      ( ( ((char)(sd)) & 0x03) << 4 )  )
+
+/*! \defgroup NIFTI1_SLICE_ORDER
+    \brief nifti1 slice order codes, describing the acquisition order
+           of the slices
+    @{
+ */
+#define NIFTI_SLICE_UNKNOWN   0
+#define NIFTI_SLICE_SEQ_INC   1
+#define NIFTI_SLICE_SEQ_DEC   2
+#define NIFTI_SLICE_ALT_INC   3
+#define NIFTI_SLICE_ALT_DEC   4
+#define NIFTI_SLICE_ALT_INC2  5  /* 05 May 2005: RWCox */
+#define NIFTI_SLICE_ALT_DEC2  6  /* 05 May 2005: RWCox */
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* UNUSED FIELDS:
+   -------------
+   Some of the ANALYZE 7.5 fields marked as ++UNUSED++ may need to be set
+   to particular values for compatibility with other programs.  The issue
+   of interoperability of ANALYZE 7.5 files is a murky one -- not all
+   programs require exactly the same set of fields.  (Unobscuring this
+   murkiness is a principal motivation behind NIFTI-1.)
+
+   Some of the fields that may need to be set for other (non-NIFTI aware)
+   software to be happy are:
+
+     extents    dbh.h says this should be 16384
+     regular    dbh.h says this should be the character 'r'
+     glmin,   } dbh.h says these values should be the min and max voxel
+      glmax   }  values for the entire dataset
+
+   It is best to initialize ALL fields in the NIFTI-1 header to 0
+   (e.g., with calloc()), then fill in what is needed.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* MISCELLANEOUS C MACROS
+-----------------------------------------------------------------------------*/
+
+/*.................*/
+/*! Given a nifti_1_header struct, check if it has a good magic number.
+    Returns NIFTI version number (1..9) if magic is good, 0 if it is not. */
+
+#define NIFTI_VERSION(h)                               \
+ ( ( (h).magic[0]=='n' && (h).magic[3]=='\0'    &&     \
+     ( (h).magic[1]=='i' || (h).magic[1]=='+' ) &&     \
+     ( (h).magic[2]>='1' && (h).magic[2]<='9' )   )    \
+ ? (h).magic[2]-'0' : 0 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct says if the data is stored in the
+    same file or in a separate file.  Returns 1 if the data is in the same
+    file as the header, 0 if it is not.                                   */
+
+#define NIFTI_ONEFILE(h) ( (h).magic[1] == '+' )
+
+/*.................*/
+/*! Check if a nifti_1_header struct needs to be byte swapped.
+    Returns 1 if it needs to be swapped, 0 if it does not.     */
+
+#define NIFTI_NEEDS_SWAP(h) ( (h).dim[0] < 0 || (h).dim[0] > 7 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct contains a 5th (vector) dimension.
+    Returns size of 5th dimension if > 1, returns 0 otherwise.         */
+
+#define NIFTI_5TH_DIM(h) ( ((h).dim[0]>4 && (h).dim[5]>1) ? (h).dim[5] : 0 )
+
+/*****************************************************************************/
+
+/*=================*/
+#ifdef  __cplusplus
+}
+#endif
+/*=================*/
+
+#endif /* _NIFTI_HEADER_ */
diff --git a/src/nifti1_io.c b/src/nifti1_io.c
new file mode 100644
index 0000000..17a3eb6
--- /dev/null
+++ b/src/nifti1_io.c
@@ -0,0 +1,7569 @@
+#define _NIFTI1_IO_C_
+
+#include "nifti1_io.h"   /* typedefs, prototypes, macros, etc. */
+#include <R.h>
+/*****===================================================================*****/
+/*****     Sample functions to deal with NIFTI-1 and ANALYZE files       *****/
+/*****...................................................................*****/
+/*****            This code is released to the public domain.            *****/
+/*****...................................................................*****/
+/*****  Author: Robert W Cox, SSCC/DIRP/NIMH/NIH/DHHS/USA/EARTH          *****/
+/*****  Date:   August 2003                                              *****/
+/*****...................................................................*****/
+/*****  Neither the National Institutes of Health (NIH), nor any of its  *****/
+/*****  employees imply any warranty of usefulness of this software for  *****/
+/*****  any purpose, and do not assume any liability for damages,        *****/
+/*****  incidental or otherwise, caused by any use of this document.     *****/
+/*****===================================================================*****/
+
+/** \file nifti1_io.c
+    \brief main collection of nifti1 i/o routines
+           - written by Bob Cox, SSCC NIMH
+           - revised by Mark Jenkinson, FMRIB
+           - revised by Rick Reynolds, SSCC, NIMH
+           - revised by Kate Fissell, University of Pittsburgh
+
+        The library history can be viewed via "nifti_tool -nifti_hist".
+    <br>The library version can be viewed via "nifti_tool -nifti_ver".
+ */
+
+/* changes by Oliver Granert:
+- change HAVE_ZLIB to HAVE_LIBZ to fit autoconf tests
+*/
+
+/*! global history and version strings, for printing */
+static char * gni_history[] = 
+{
+  "----------------------------------------------------------------------\n"
+  "history (of nifti library changes):\n"
+  "\n",
+  "0.0  August, 2003 [rwcox]\n"
+  "     (Robert W Cox of the National Institutes of Health, SSCC/DIRP/NIMH)\n"
+  "   - initial version\n"
+  "\n",
+  "0.1  July/August, 2004 [Mark Jenkinson]\n"
+  "     (FMRIB Centre, University of Oxford, UK)\n"
+  "   - Mainly adding low-level IO and changing things to allow gzipped\n"
+  "     files to be read and written\n"
+  "   - Full backwards compatability should have been maintained\n"
+  "\n",
+  "0.2  16 Nov 2004 [rickr]\n"
+  "     (Rick Reynolds of the National Institutes of Health, SSCC/DIRP/NIMH)\n"
+  "   - included Mark's changes in the AFNI distribution (including znzlib/)\n"
+  "     (HAVE_LIBZ is commented out for the standard distribution)\n"
+  "   - modified nifti_validfilename() and nifti_makebasename()\n"
+  "   - added nifti_find_file_extension()\n"
+  "\n",
+  "0.3  3 Dec 2004 [rickr]\n"
+  "   - note: header extensions are not yet checked for\n"
+  "   - added formatted history as global string, for printing\n"
+  "   - added nifti_disp_lib_hist(), to display the nifti library history\n"
+  "   - added nifti_disp_lib_version(), to display the nifti library history\n",
+  "   - re-wrote nifti_findhdrname()\n"
+  "       o used nifti_find_file_extension()\n"
+  "       o changed order of file tests (default is .nii, depends on input)\n"
+  "       o free hdrname on failure\n"
+  "   - made similar changes to nifti_findimgname()\n"
+  "   - check for NULL return from nifti_findhdrname() calls\n",
+  "   - removed most of ERREX() macros\n"
+  "   - modified nifti_image_read()\n"
+  "       o added debug info and error checking (on gni_debug > 0, only)\n"
+  "       o fail if workingname is NULL\n"
+  "       o check for failure to open header file\n"
+  "       o free workingname on failure\n"
+  "       o check for failure of nifti_image_load()\n"
+  "       o check for failure of nifti_convert_nhdr2nim()\n",
+  "   - changed nifti_image_load() to int, and check nifti_read_buffer return\n"
+  "   - changed nifti_read_buffer() to fail on short read, and to count float\n"
+  "     fixes (to print on debug)\n"
+  "   - changed nifti_image_infodump to print to stderr\n"
+  "   - updated function header comments, or moved comments above header\n"
+  "   - removed const keyword\n"
+  "   - added LNI_FERR() macro for error reporting on input files\n"
+  "\n",
+  "0.4  10 Dec 2004 [rickr]  - added header extensions\n"
+  "   - in nifti1_io.h:\n"
+  "       o added num_ext and ext_list to the definition of nifti_image\n"
+  "       o made many functions static (more to follow)\n"
+  "       o added LNI_MAX_NIA_EXT_LEN, for max nifti_type 3 extension length\n",
+  "   - added __DATE__ to version output in nifti_disp_lib_version()\n"
+  "   - added nifti_disp_matrix_orient() to print orientation information\n"
+  "   - added '.nia' as a valid file extension in nifti_find_file_extension()\n"
+  "   - added much more debug output\n"
+  "   - in nifti_image_read(), in the case of an ASCII header, check for\n"
+  "     extensions after the end of the header\n",
+  "   - added nifti_read_extensions() function\n"
+  "   - added nifti_read_next_extension() function\n"
+  "   - added nifti_add_exten_to_list() function\n"
+  "   - added nifti_check_extension() function\n"
+  "   - added nifti_write_extensions() function\n"
+  "   - added nifti_extension_size() function\n"
+  "   - in nifti_set_iname_offest():\n"
+  "       o adjust offset by the extension size and the extender size\n",
+  "       o fixed the 'ceiling modulo 16' computation\n"
+  "   - in nifti_image_write_hdr_img2(): \n"
+  "       o added extension writing\n"
+  "       o check for NULL return from nifti_findimgname()\n"
+  "   - include number of extensions in nifti_image_to_ascii() output\n"
+  "   - in nifti_image_from_ascii():\n"
+  "       o return bytes_read as a parameter, computed from the final spos\n"
+  "       o extract num_ext from ASCII header\n"
+  "\n",
+  "0.5  14 Dec 2004 [rickr]  - added sub-brick reading functions\n"
+  "   - added nifti_brick_list type to nifti1_io.h, along with new prototypes\n"
+  "   - added main nifti_image_read_bricks() function, with description\n"
+  "   - added nifti_image_load_bricks() - library function (requires nim)\n"
+  "   - added valid_nifti_brick_list() - library function\n"
+  "   - added free_NBL() - library function\n",
+  "   - added update_nifti_image_for_brick_list() for dimension update\n"
+  "   - added nifti_load_NBL_bricks(), nifti_alloc_NBL_mem(),\n"
+  "           nifti_copynsort() and force_positive() (static functions)\n"
+  "   - in nifti_image_read(), check for failed load only if read_data is set\n"
+  "   - broke most of nifti_image_load() into nifti_image_load_prep()\n"
+  "\n",
+  "0.6  15 Dec 2004 [rickr]  - added sub-brick writing functionality\n"
+  "   - in nifti1_io.h, removed znzlib directory from include - all nifti\n"
+  "       library files are now under the nifti directory\n"
+  "   - nifti_read_extensions(): print no offset warning for nifti_type 3\n"
+  "   - nifti_write_all_data():\n"
+  "       o pass nifti_brick_list * NBL, for optional writing\n"
+  "       o if NBL, write each sub-brick, sequentially\n",
+  "   - nifti_set_iname_offset(): case 1 must have sizeof() cast to int\n"
+  "   - pass NBL to nifti_image_write_hdr_img2(), and allow NBL or data\n"
+  "   - added nifti_image_write_bricks() wrapper for ...write_hdr_img2()\n"
+  "   - included compression abilities\n"
+  "\n",
+  "0.7  16 Dec 2004 [rickr] - minor changes to extension reading\n"
+  "\n",
+  "0.8  21 Dec 2004 [rickr] - restrict extension reading, and minor changes\n"
+  "   - in nifti_image_read(), compute bytes for extensions (see remaining)\n"
+  "   - in nifti_read_extensions(), pass 'remain' as space for extensions,\n"
+  "        pass it to nifti_read_next_ext(), and update for each one read \n"
+  "   - in nifti_check_extension(), require (size <= remain)\n",
+  "   - in update_nifti_image_brick_list(), update nvox\n"
+  "   - in nifti_image_load_bricks(), make explicit check for nbricks <= 0\n"
+  "   - in int_force_positive(), check for (!list)\n"
+  "   - in swap_nifti_header(), swap sizeof_hdr, and reorder to struct order\n"
+  "   - change get_filesize functions to signed ( < 0 is no file or error )\n",
+  "   - in nifti_validfilename(), lose redundant (len < 0) check\n"
+  "   - make print_hex_vals() static\n"
+  "   - in disp_nifti_1_header, restrict string field widths\n"
+  "\n",
+  "0.9  23 Dec 2004 [rickr] - minor changes\n"
+  "   - broke ASCII header reading out of nifti_image_read(), into new\n"
+  "        functions has_ascii_header() and read_ascii_image()\n",
+  "   - check image_read failure and znzseek failure\n"
+  "   - altered some debug output\n"
+  "   - nifti_write_all_data() now returns an int\n"
+  "\n",
+  "0.10 29 Dec 2004 [rickr]\n"
+  "   - renamed nifti_valid_extension() to nifti_check_extension()\n"
+  "   - added functions nifti_makehdrname() and nifti_makeimgname()\n"
+  "   - added function valid_nifti_extensions()\n"
+  "   - in nifti_write_extensions(), check for validity before writing\n",
+  "   - rewrote nifti_image_write_hdr_img2():\n"
+  "       o set write_data and leave_open flags from write_opts\n"
+  "       o add debug print statements\n"
+  "       o use nifti_write_ascii_image() for the ascii case\n"
+  "       o rewrote the logic of all cases to be easier to follow\n",
+  "   - broke out code as nifti_write_ascii_image() function\n"
+  "   - added debug to top-level write functions, and free the znzFile\n"
+  "   - removed unused internal function nifti_image_open()\n"
+  "\n",
+  "0.11 30 Dec 2004 [rickr] - small mods\n"
+  "   - moved static function prototypes from header to C file\n"
+  "   - free extensions in nifti_image_free()\n"
+  "\n",
+  "1.0  07 Jan 2005 [rickr] - INITIAL RELEASE VERSION\n"
+  "   - added function nifti_set_filenames()\n"
+  "   - added function nifti_read_header()\n"
+  "   - added static function nhdr_looks_good()\n"
+  "   - added static function need_nhdr_swap()\n"
+  "   - exported nifti_add_exten_to_list symbol\n",
+  "   - fixed #bytes written in nifti_write_extensions()\n"
+  "   - only modify offset if it is too small (nifti_set_iname_offset)\n"
+  "   - added nifti_type 3 to nifti_makehdrname and nifti_makeimgname\n"
+  "   - added function nifti_set_filenames()\n"
+  "\n",
+  "1.1  07 Jan 2005 [rickr]\n"
+  "   - in nifti_read_header(), swap if needed\n"
+  "\n",
+  "1.2  07 Feb 2005 [kate fissell c/o rickr] \n"
+  "   - nifti1.h: added doxygen comments for main struct and #define groups\n"
+  "   - nifti1_io.h: added doxygen comments for file and nifti_image struct\n"
+  "   - nifti1_io.h: added doxygen comments for file and some functions\n"
+  "   - nifti1_io.c: changed nifti_copy_nim_info to use memcpy\n"
+  "\n",
+  "1.3  09 Feb 2005 [rickr]\n"
+  "   - nifti1.h: added doxygen comments for extension structs\n"
+  "   - nifti1_io.h: put most #defines in #ifdef _NIFTI1_IO_C_ block\n"
+  "   - added a doxygen-style description to every exported function\n"
+  "   - added doxygen-style comments within some functions\n"
+  "   - re-exported many znzFile functions that I had made static\n"
+  "   - re-added nifti_image_open (sorry, Mark)\n"
+  "   - every exported function now has 'nifti' in the name (19 functions)\n",
+  "   - made sure every alloc() has a failure test\n"
+  "   - added nifti_copy_extensions function, for use in nifti_copy_nim_info\n"
+  "   - nifti_is_gzfile: added initial strlen test\n"
+  "   - nifti_set_filenames: added set_byte_order parameter option\n"
+  "     (it seems appropriate to set the BO when new files are associated)\n"
+  "   - disp_nifti_1_header: prints to stdout (a.o.t. stderr), with fflush\n"
+  "\n",
+  "1.4  23 Feb 2005 [rickr] - sourceforge merge\n"
+  "   - merged into the nifti_io CVS directory structure at sourceforge.net\n"
+  "   - merged in 4 changes by Mark, and re-added his const keywords\n"
+  "   - cast some pointers to (void *) for -pedantic compile option\n"
+  "   - added nifti_free_extensions()\n"
+  "\n",
+  "1.5  02 Mar 2005 [rickr] - started nifti global options\n"
+  "   - gni_debug is now g_opts.debug\n"
+  "   - added validity check parameter to nifti_read_header\n"
+  "   - need_nhdr_swap no longer does test swaps on the stack\n"
+  "\n",
+  "1.6  05 April 2005 [rickr] - validation and collapsed_image_read\n"
+  "   - added nifti_read_collapsed_image(), an interface for reading partial\n"
+  "     datasets, specifying a subset of array indices\n"
+  "   - for read_collapsed_image, added static functions: rci_read_data(),\n"
+  "     rci_alloc_mem(), and make_pivot_list()\n",
+  "   - added nifti_nim_is_valid() to check for consistency (more to do)\n"
+  "   - added nifti_nim_has_valid_dims() to do many dimensions tests\n"
+  "\n",
+  "1.7  08 April 2005 [rickr]\n"
+  "   - added nifti_update_dims_from_array() - to update dimensions\n"
+  "   - modified nifti_makehdrname() and nifti_makeimgname():\n"
+  "       if prefix has a valid extension, use it (else make one up)\n"
+  "   - added nifti_get_intlist - for making an array of ints\n"
+  "   - fixed init of NBL->bsize in nifti_alloc_NBL_mem()  {thanks, Bob}\n"
+  "\n",
+  "1.8  14 April 2005 [rickr]\n"
+  "   - added nifti_set_type_from_names(), for nifti_set_filenames()\n"
+  "     (only updates type if number of files does not match it)\n"
+  "   - added is_valid_nifti_type(), just to be sure\n"
+  "   - updated description of nifti_read_collapsed_image() for *data change\n"
+  "     (if *data is already set, assume memory exists for results)\n"
+  "   - modified rci_alloc_mem() to allocate only if *data is NULL\n"
+  "\n",
+  "1.9  19 April 2005 [rickr]\n"
+  "   - added extension codes NIFTI_ECODE_COMMENT and NIFTI_ECODE_XCEDE\n"
+  "   - added nifti_type codes NIFTI_MAX_ECODE and NIFTI_MAX_FTYPE\n"
+  "   - added nifti_add_extension() {exported}\n"
+  "   - added nifti_fill_extension() as a static function\n"
+  "   - added nifti_is_valid_ecode() {exported}\n",
+  "   - nifti_type values are now NIFTI_FTYPE_* file codes\n"
+  "   - in nifti_read_extensions(), decrement 'remain' by extender size, 4\n"
+  "   - in nifti_set_iname_offset(), case 1, update if offset differs\n"
+  "   - only output '-d writing nifti file' if debug > 1\n"
+  "\n",
+  "1.10 10 May 2005 [rickr]\n"
+  "   - files are read using ZLIB only if they end in '.gz'\n"
+  "\n",
+  "1.11 12 August 2005 [kate fissell]\n"
+  "   - Kate's 0.2 release packaging, for sourceforge\n"
+  "\n",
+  "1.12 17 August 2005 [rickr] - comment (doxygen) updates\n"
+  "   - updated comments for most functions (2 updates from Cinly Ooi)\n"
+  "   - added nifti_type_and_names_match()\n"
+  "\n",
+  "1.12a 24 August 2005 [rickr] - remove all tabs from Clibs/*/*.[ch]\n",
+  "1.12b 25 August 2005 [rickr] - changes by Hans Johnson\n",
+  "1.13  25 August 2005 [rickr]\n",
+  "   - finished changes by Hans for Insight\n"
+  "   - added const in all appropraite parameter locations (30-40)\n"
+  "     (any pointer referencing data that will not change)\n"
+  "   - shortened all string constants below 509 character limit\n"
+  "1.14  28 October 2005 [HJohnson]\n",
+  "   - use nifti_set_filenames() in nifti_convert_nhdr2nim()\n"
+  "1.15  02 November 2005 [rickr]\n",
+  "   - added skip_blank_ext to nifti_global_options\n"
+  "   - added nifti_set_skip_blank_ext(), to set option\n"
+  "   - if skip_blank_ext and no extensions, do not read/write extender\n"
+  "1.16 18 November 2005 [rickr]\n",
+  "   - removed any test or access of dim[i], i>dim[0]\n"
+  "   - do not set pixdim for collapsed dims to 1.0, leave them as they are\n"
+  "   - added magic and dim[i] tests in nifti_hdr_looks_good()\n"
+  "   - added 2 size_t casts\n"
+  "1.17 22 November 2005 [rickr]\n",
+  "   - in hdr->nim, for i > dim[0], pass 0 or 1, else set to 1\n"
+  "1.18 02 March 2006 [rickr]\n",
+  "   - in nifti_alloc_NBL_mem(), fixed nt=0 case from 1.17 change\n"
+  "1.19 23 May 2006 [HJohnson,rickr]\n",
+  "   - nifti_write_ascii_image(): free(hstr)\n"
+  "   - nifti_copy_extensions(): clear num_ext and ext_list\n"
+  "1.20 27 Jun 2006 [rickr]\n",
+  "   - nifti_findhdrname(): fixed assign of efirst to match stated logic\n"
+  "     (problem found by Atle Bjørnerud)\n"
+  "1.21 05 Sep 2006 [rickr] update for nifticlib-0.4 release\n",
+  "   - was reminded to actually add nifti_set_skip_blank_ext()\n"
+  "   - init g_opts.skip_blank_ext to 0\n"
+  "1.22 01 Jun 2007 nifticlib-0.5 release\n",
+  "1.23 05 Jun 2007 nifti_add_exten_to_list: revert on failure, free old list\n"
+  "1.24 07 Jun 2007 nifti_copy_extensions: use esize-8 for data size\n"
+  "1.25 12 Jun 2007 [rickr] EMPTY_IMAGE creation\n",
+  "   - added nifti_make_new_header() - to create from dims/dtype\n"
+  "   - added nifti_make_new_nim() - to create from dims/dtype/fill\n"
+  "   - added nifti_is_valid_datatype(), and more debug info\n",
+  "1.26 27 Jul 2007 [rickr] handle single volumes > 2^31 bytes (but < 2^32)\n",
+  "1.27 28 Jul 2007 [rickr] nim->nvox, NBL-bsize are now type size_t\n"
+  "1.28 30 Jul 2007 [rickr] size_t updates\n",
+  "1.29 08 Aug 2007 [rickr] for list, valid_nifti_brick_list requires 3 dims\n"
+  "1.30 08 Nov 2007 [Yaroslav/rickr]\n"
+  "   - fix ARM struct alignment problem in byte-swapping routines\n",
+  "1.31 29 Nov 2007 [rickr] for nifticlib-1.0.0\n"
+  "   - added nifti_datatype_to/from_string routines\n"
+  "   - added DT_RGBA32/NIFTI_TYPE_RGBA32 datatype macros (2304)\n"
+  "   - added NIFTI_ECODE_FREESURFER (14)\n",
+  "1.32 08 Dec 2007 [rickr]\n"
+  "   - nifti_hdr_looks_good() allows ANALYZE headers (req. by V. Luccio)\n"
+  "   - added nifti_datatype_is_valid()\n",
+  "1.33 05 Feb 2008 [hansj,rickr] - block nia.gz use\n"
+  "1.34 13 Jun 2008 [rickr] - added nifti_compiled_with_zlib()\n"
+  "1.35 03 Aug 2008 [rickr]\n",
+  "   - deal with swapping, so that CPU type does not affect output\n"
+  "     (motivated by C Burns)\n"
+  "   - added nifti_analyze75 structure and nifti_swap_as_analyze()\n"
+  "   - previous swap_nifti_header is saved as old_swap_nifti_header\n"
+  "   - also swap UNUSED fields in nifti_1_header struct\n",
+  "1.36 07 Oct 2008 [rickr]\n",
+  "   - added nifti_NBL_matches_nim() check for write_bricks()\n"
+  "1.37 10 Mar 2009 [rickr]\n",
+  "   - H Johnson cast updates (06 Feb)\n"
+  "   - added NIFTI_ECODE_PYPICKLE for PyNIfTI (06 Feb)\n"
+  "   - added NIFTI_ECODEs 18-28 for the LONI MiND group\n"
+  "1.38 28 Apr 2009 [rickr]\n",
+  "   - uppercase extensions are now valid (requested by M. Coursolle)\n"
+  "   - nifti_set_allow_upper_fext controls this option (req by C. Ooi)\n"
+  "1.39 23 Jun 2009 [rickr]: added 4 checks of alloc() returns\n",
+  "1.40 16 Mar 2010 [rickr]: added NIFTI_ECODE_VOXBO for D. Kimberg\n",
+  "1.41 28 Apr 2010 [rickr]: added NIFTI_ECODE_CARET for J. Harwell\n",
+  "1.42 06 Jul 2010 [rickr]: trouble with large (gz) files\n",
+  "   - noted/investigated by M Hanke and Y Halchenko\n"
+  "   - fixed znzread/write, noting example by M Adler\n"
+  "   - changed nifti_swap_* routines/calls to take size_t (6)\n"
+  "1.43 07 Jul 2010 [rickr]: fixed znzR/W to again return nmembers\n",
+  "1.43r 09 Jan 2013 [oliverg]: replace outputs to stdout and stderr by \n",
+  "      Rprintf and REprintf\n",
+  "----------------------------------------------------------------------\n"
+};
+static char gni_version[] = "nifti library version 1.43r (9 Jan, 2013)";
+
+/*! global nifti options structure - init with defaults */
+static nifti_global_options g_opts = { 
+        1, /* debug level                                         */
+        0, /* skip_blank_ext    - skip extender if no extensions  */
+        1  /* allow_upper_fext  - allow uppercase file extensions */
+};
+
+/*! global nifti types structure list (per type, ordered oldest to newest) */
+static nifti_type_ele nifti_type_list[] = {
+    /* type  nbyper  swapsize   name  */
+    {    0,     0,       0,   "DT_UNKNOWN"              }, 
+    {    0,     0,       0,   "DT_NONE"                 }, 
+    {    1,     0,       0,   "DT_BINARY"               },  /* not usable */
+    {    2,     1,       0,   "DT_UNSIGNED_CHAR"        },
+    {    2,     1,       0,   "DT_UINT8"                },
+    {    2,     1,       0,   "NIFTI_TYPE_UINT8"        },
+    {    4,     2,       2,   "DT_SIGNED_SHORT"         },
+    {    4,     2,       2,   "DT_INT16"                },
+    {    4,     2,       2,   "NIFTI_TYPE_INT16"        },
+    {    8,     4,       4,   "DT_SIGNED_INT"           },
+    {    8,     4,       4,   "DT_INT32"                },
+    {    8,     4,       4,   "NIFTI_TYPE_INT32"        },
+    {   16,     4,       4,   "DT_FLOAT"                },
+    {   16,     4,       4,   "DT_FLOAT32"              },
+    {   16,     4,       4,   "NIFTI_TYPE_FLOAT32"      },
+    {   32,     8,       4,   "DT_COMPLEX"              },
+    {   32,     8,       4,   "DT_COMPLEX64"            },
+    {   32,     8,       4,   "NIFTI_TYPE_COMPLEX64"    },
+    {   64,     8,       8,   "DT_DOUBLE"               },
+    {   64,     8,       8,   "DT_FLOAT64"              },
+    {   64,     8,       8,   "NIFTI_TYPE_FLOAT64"      },
+    {  128,     3,       0,   "DT_RGB"                  },
+    {  128,     3,       0,   "DT_RGB24"                },
+    {  128,     3,       0,   "NIFTI_TYPE_RGB24"        },
+    {  255,     0,       0,   "DT_ALL"                  },
+    {  256,     1,       0,   "DT_INT8"                 },
+    {  256,     1,       0,   "NIFTI_TYPE_INT8"         },
+    {  512,     2,       2,   "DT_UINT16"               },
+    {  512,     2,       2,   "NIFTI_TYPE_UINT16"       },
+    {  768,     4,       4,   "DT_UINT32"               },
+    {  768,     4,       4,   "NIFTI_TYPE_UINT32"       },
+    { 1024,     8,       8,   "DT_INT64"                },
+    { 1024,     8,       8,   "NIFTI_TYPE_INT64"        },
+    { 1280,     8,       8,   "DT_UINT64"               },
+    { 1280,     8,       8,   "NIFTI_TYPE_UINT64"       },
+    { 1536,    16,      16,   "DT_FLOAT128"             },
+    { 1536,    16,      16,   "NIFTI_TYPE_FLOAT128"     },
+    { 1792,    16,       8,   "DT_COMPLEX128"           },
+    { 1792,    16,       8,   "NIFTI_TYPE_COMPLEX128"   },
+    { 2048,    32,      16,   "DT_COMPLEX256"           },
+    { 2048,    32,      16,   "NIFTI_TYPE_COMPLEX256"   },
+    { 2304,     4,       0,   "DT_RGBA32"               },
+    { 2304,     4,       0,   "NIFTI_TYPE_RGBA32"       },
+};
+
+/*---------------------------------------------------------------------------*/
+/* prototypes for internal functions - not part of exported library          */
+
+/* extension routines */
+static int  nifti_read_extensions( nifti_image *nim, znzFile fp, int remain );
+static int  nifti_read_next_extension( nifti1_extension * nex, nifti_image *nim,                                       int remain, znzFile fp );
+static int  nifti_check_extension(nifti_image *nim, int size,int code, int rem);
+static void update_nifti_image_for_brick_list(nifti_image * nim , int nbricks);
+static int  nifti_add_exten_to_list(nifti1_extension *  new_ext,
+                                    nifti1_extension ** list, int new_length);
+static int  nifti_fill_extension(nifti1_extension * ext, const char * data,
+                                 int len, int ecode);
+
+/* NBL routines */
+static int  nifti_load_NBL_bricks(nifti_image * nim , int * slist, int * sindex,                                  nifti_brick_list * NBL, znzFile fp );
+static int  nifti_alloc_NBL_mem(  nifti_image * nim, int nbricks,
+                                  nifti_brick_list * nbl);
+static int  nifti_copynsort(int nbricks, const int *blist, int **slist,
+                            int **sindex);
+static int  nifti_NBL_matches_nim(const nifti_image *nim,
+                                  const nifti_brick_list *NBL);
+
+/* for nifti_read_collapsed_image: */
+static int  rci_read_data(nifti_image *nim, int *pivots, int *prods, int nprods,
+                  const int dims[], char *data, znzFile fp, size_t base_offset);
+static int  rci_alloc_mem(void ** data, int prods[8], int nprods, int nbyper );
+static int  make_pivot_list(nifti_image * nim, const int dims[], int pivots[],
+                            int prods[], int * nprods );
+
+/* misc */
+static int   compare_strlist   (const char * str, char ** strlist, int len);
+static int   fileext_compare   (const char * test_ext, const char * known_ext);
+static int   fileext_n_compare (const char * test_ext,
+                                const char * known_ext, int maxlen);
+static int   is_mixedcase      (const char * str);
+static int   is_uppercase      (const char * str);
+static int   make_lowercase    (char * str);
+static int   make_uppercase    (char * str);
+static int   need_nhdr_swap    (short dim0, int hdrsize);
+static int   print_hex_vals    (const char * data, int nbytes/*, FILE * fp*/);
+static int   unescape_string   (char *str);  /* string utility functions */
+static char *escapize_string   (const char *str);
+
+/* internal I/O routines */
+static znzFile nifti_image_load_prep( nifti_image *nim );
+static int     has_ascii_header(znzFile fp);
+/*---------------------------------------------------------------------------*/
+
+
+/* for calling from some main program */
+
+/*----------------------------------------------------------------------*/
+/*! display the nifti library module history (via stdout)
+*//*--------------------------------------------------------------------*/
+void nifti_disp_lib_hist( void )
+{
+   int c, len = sizeof(gni_history)/sizeof(char *);
+   for( c = 0; c < len; c++ )
+       Rprintf(gni_history[c]);
+}
+
+/*----------------------------------------------------------------------*/
+/*! display the nifti library version (via stdout)
+*//*--------------------------------------------------------------------*/
+/* replaced for use in R by function "const char *nifti_lib_version( void )"
+void nifti_disp_lib_version( void )
+{
+   printf("%s, compiled %s\n", gni_version, __DATE__);
+}*/
+
+/*----------------------------------------------------------------------*/
+/*! return the nifti library version (via constant string)
+*//*--------------------------------------------------------------------*/
+const char *nifti_lib_version( void )
+{
+  return gni_version;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_image_read_bricks        - read nifti data as array of bricks
+ *
+ *                                   13 Dec 2004 [rickr]
+ * 
+ *  \param  hname    - filename of dataset to read (must be valid)
+ *  \param  nbricks  - number of sub-bricks to read
+ *                     (if blist is valid, nbricks must be > 0)
+ *  \param  blist    - list of sub-bricks to read
+ *                     (can be NULL; if NULL, read complete dataset)
+ *  \param  NBL      - pointer to empty nifti_brick_list struct
+ *                     (must be a valid pointer)
+ *
+ *  \return
+ *     <br> nim      - same as nifti_image_read, but
+ *                          nim->nt       = NBL->nbricks (or nt*nu*nv*nw)
+ *                          nim->nu,nv,nw = 1
+ *                          nim->data     = NULL
+ *     <br> NBL      - filled with data volumes
+ *
+ * By default, this function will read the nifti dataset and break the data
+ * into a list of nt*nu*nv*nw sub-bricks, each having size nx*ny*nz elements.
+ * That is to say, instead of reading the entire dataset as a single array,
+ * break it up into sub-bricks (volumes), each of size nx*ny*nz elements.
+ *
+ * Note: in the returned nifti_image, nu, nv and nw will always be 1.  The
+ *       intention of this function is to collapse the dataset into a single
+ *       array of volumes (of length nbricks or nt*nu*nv*nw).
+ *
+ * If 'blist' is valid, it is taken to be a list of sub-bricks, of length
+ * 'nbricks'.  The data will still be separated into sub-bricks of size
+ * nx*ny*nz elements, but now 'nbricks' sub-bricks will be returned, of the
+ * caller's choosing via 'blist'.
+ *
+ * E.g. consider a dataset with 12 sub-bricks (numbered 0..11), and the
+ * following code:
+ *
+ * <pre>
+ * { nifti_brick_list   NB_orig, NB_select;
+ *   nifti_image      * nim_orig, * nim_select;
+ *   int                blist[5] = { 7, 0, 5, 5, 9 };
+ *
+ *   nim_orig   = nifti_image_read_bricks("myfile.nii", 0, NULL,  &NB_orig);
+ *   nim_select = nifti_image_read_bricks("myfile.nii", 5, blist, &NB_select);
+ * }
+ * </pre>
+ *
+ * Here, nim_orig gets the entire dataset, where NB_orig.nbricks = 12.  But
+ * nim_select has NB_select.nbricks = 5.
+ *
+ * Note that the first case is not quite the same as just calling the
+ * nifti_image_read function, as here the data is separated into sub-bricks.
+ *
+ * Note that valid blist elements are in [0..nt*nu*nv*nw-1],
+ * or written [ 0 .. (dim[4]*dim[5]*dim[6]*dim[7] - 1) ].
+ *
+ * Note that, as is the case with all of the reading functions, the
+ * data will be allocated, read in, and properly byte-swapped, if
+ * necessary.
+ *
+ * \sa nifti_image_load_bricks, nifti_free_NBL, valid_nifti_brick_list,
+       nifti_image_read
+*//*----------------------------------------------------------------------*/
+nifti_image *nifti_image_read_bricks(const char * hname, int nbricks,
+                                     const int * blist, nifti_brick_list * NBL)
+{
+   nifti_image * nim;
+
+   if( !hname || !NBL ){
+      REprintf("** nifti_image_read_bricks: bad params (%p,%p)\n",
+              hname, (void *)NBL);
+      return NULL;
+   }
+
+   if( blist && nbricks <= 0 ){
+      REprintf("** nifti_image_read_bricks: bad nbricks, %d\n", nbricks);
+      return NULL;
+   }
+
+   nim = nifti_image_read(hname, 0);  /* read header, but not data */
+
+   if( !nim ) return NULL;   /* errors were already printed */
+
+   /* if we fail, free image and return */
+   if( nifti_image_load_bricks(nim, nbricks, blist, NBL) <= 0 ){
+      nifti_image_free(nim);
+      return NULL;
+   }
+
+   if( blist ) update_nifti_image_for_brick_list(nim, nbricks);
+
+   return nim;
+}
+
+
+/*----------------------------------------------------------------------
+ * update_nifti_image_for_brick_list  - update nifti_image
+ *
+ * When loading a specific brick list, the distinction between
+ * nt, nu, nv and nw is lost.  So put everything in t, and set
+ * dim[0] = 4.
+ *----------------------------------------------------------------------*/
+static void update_nifti_image_for_brick_list( nifti_image * nim , int nbricks )
+{
+   int ndim;
+
+   if( g_opts.debug > 2 ){
+      REprintf("+d updating image dimensions for %d bricks in list\n",
+              nbricks);
+      REprintf("   ndim = %d\n",nim->ndim);
+      REprintf("   nx,ny,nz,nt,nu,nv,nw: (%d,%d,%d,%d,%d,%d,%d)\n",
+              nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
+   }
+
+   nim->nt = nbricks;
+   nim->nu = nim->nv = nim->nw = 1;
+   nim->dim[4] = nbricks;
+   nim->dim[5] = nim->dim[6] = nim->dim[7] = 1;
+
+   /* compute nvox                                                       */
+   /* do not rely on dimensions above dim[0]         16 Nov 2005 [rickr] */
+   for( nim->nvox = 1, ndim = 1; ndim <= nim->dim[0]; ndim++ )
+      nim->nvox *= nim->dim[ndim];
+
+   /* update the dimensions to 4 or lower */
+   for( ndim = 4; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- )
+       ;
+
+   if( g_opts.debug > 2 ){
+      REprintf("+d ndim = %d -> %d\n",nim->ndim, ndim);
+      REprintf(" --> (%d,%d,%d,%d,%d,%d,%d)\n",
+              nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
+   }
+
+   nim->dim[0] = nim->ndim = ndim;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_update_dims_from_array  - update nx, ny, ... from nim->dim[]
+
+    Fix all the dimension information, based on a new nim->dim[].
+
+    Note: we assume that dim[0] will not increase.
+
+    Check for updates to pixdim[], dx,...,  nx,..., nvox, ndim, dim[0].
+*//*--------------------------------------------------------------------*/
+int nifti_update_dims_from_array( nifti_image * nim )
+{
+   int c, ndim;
+
+   if( !nim ){
+      REprintf("** update_dims: missing nim\n");
+      return 1;
+   }
+
+   if( g_opts.debug > 2 ){
+      REprintf("+d updating image dimensions given nim->dim:");
+      for( c = 0; c < 8; c++ ) REprintf(" %d", nim->dim[c]);
+      REprintf("\n");/*fputc('\n',stderr);*/
+   }
+
+   /* verify dim[0] first */
+   if(nim->dim[0] < 1 || nim->dim[0] > 7){
+      REprintf("** invalid dim[0], dim[] = ");
+      for( c = 0; c < 8; c++ ) REprintf(" %d", nim->dim[c]);
+      REprintf("\n");/*fputc('\n',stderr);*/
+      return 1;
+   }
+
+   /* set nx, ny ..., dx, dy, ..., one by one */
+
+   /* less than 1, set to 1, else copy */
+   if(nim->dim[1] < 1) nim->nx = nim->dim[1] = 1;
+   else                nim->nx = nim->dim[1];
+   nim->dx = nim->pixdim[1];
+
+   /* if undefined, or less than 1, set to 1 */
+   if(nim->dim[0] < 2 || (nim->dim[0] >= 2 && nim->dim[2] < 1))
+      nim->ny = nim->dim[2] = 1;
+   else
+      nim->ny = nim->dim[2];
+   /* copy delta values, in any case */
+   nim->dy = nim->pixdim[2];
+
+   if(nim->dim[0] < 3 || (nim->dim[0] >= 3 && nim->dim[3] < 1))
+      nim->nz = nim->dim[3] = 1;
+   else /* just copy vals from arrays */
+      nim->nz = nim->dim[3];
+   nim->dz = nim->pixdim[3];
+
+   if(nim->dim[0] < 4 || (nim->dim[0] >= 4 && nim->dim[4] < 1))
+      nim->nt = nim->dim[4] = 1;
+   else /* just copy vals from arrays */
+      nim->nt = nim->dim[4];
+   nim->dt = nim->pixdim[4];
+
+   if(nim->dim[0] < 5 || (nim->dim[0] >= 5 && nim->dim[5] < 1))
+      nim->nu = nim->dim[5] = 1;
+   else /* just copy vals from arrays */
+      nim->nu = nim->dim[5];
+   nim->du = nim->pixdim[5];
+
+   if(nim->dim[0] < 6 || (nim->dim[0] >= 6 && nim->dim[6] < 1))
+      nim->nv = nim->dim[6] = 1;
+   else /* just copy vals from arrays */
+      nim->nv = nim->dim[6];
+   nim->dv = nim->pixdim[6];
+
+   if(nim->dim[0] < 7 || (nim->dim[0] >= 7 && nim->dim[7] < 1))
+      nim->nw = nim->dim[7] = 1;
+   else /* just copy vals from arrays */
+      nim->nw = nim->dim[7];
+   nim->dw = nim->pixdim[7];
+
+   for( c = 1, nim->nvox = 1; c <= nim->dim[0]; c++ )
+      nim->nvox *= nim->dim[c];
+
+   /* compute ndim, assuming it can be no larger than the old one */
+   for( ndim = nim->dim[0]; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- )
+       ;
+
+   if( g_opts.debug > 2 ){
+      REprintf("+d ndim = %d -> %d\n",nim->ndim, ndim);
+      REprintf(" --> (%d,%d,%d,%d,%d,%d,%d)\n",
+              nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
+   }
+
+   nim->dim[0] = nim->ndim = ndim;
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! Load the image data from disk into an already-prepared image struct.
+ *
+ * \param    nim      - initialized nifti_image, without data
+ * \param    nbricks  - the length of blist (must be 0 if blist is NULL)
+ * \param    blist    - an array of xyz volume indices to read (can be NULL)
+ * \param    NBL      - pointer to struct where resulting data will be stored
+ *
+ * If blist is NULL, read all sub-bricks.
+ * 
+ * \return the number of loaded bricks (NBL->nbricks),
+ *    0 on failure, < 0 on error
+ *
+ * NOTE: it is likely that another function will copy the data pointers
+ *       out of NBL, in which case the only pointer the calling function
+ *       will want to free is NBL->bricks (not each NBL->bricks[i]).
+*//*--------------------------------------------------------------------*/
+int nifti_image_load_bricks( nifti_image * nim , int nbricks,
+                             const int * blist, nifti_brick_list * NBL )
+{
+   int     * slist = NULL, * sindex = NULL, rv;
+   znzFile   fp;
+
+   /* we can have blist == NULL */
+   if( !nim || !NBL ){
+      REprintf("** nifti_image_load_bricks, bad params (%p,%p)\n",
+              (void *)nim, (void *)NBL);
+      return -1;
+   }
+
+   if( blist && nbricks <= 0 ){
+      if( g_opts.debug > 1 )
+         REprintf("-d load_bricks: received blist with nbricks = %d,"
+                        "ignoring blist\n", nbricks);
+      blist = NULL; /* pretend nothing was passed */
+   }
+
+   if( blist && ! valid_nifti_brick_list(nim, nbricks, blist, g_opts.debug>0) )
+      return -1;
+
+   /* for efficiency, let's read the file in order */
+   if( blist && nifti_copynsort( nbricks, blist, &slist, &sindex ) != 0 )
+      return -1;
+
+   /* open the file and position the FILE pointer */
+   fp = nifti_image_load_prep( nim );
+   if( !fp ){
+      if( g_opts.debug > 0 )
+         REprintf("** nifti_image_load_bricks, failed load_prep\n");
+      if( blist ){ free(slist); free(sindex); }
+      return -1;
+   }
+
+   /* this will flag to allocate defaults */
+   if( !blist ) nbricks = 0;
+   if( nifti_alloc_NBL_mem( nim, nbricks, NBL ) != 0 ){
+      if( blist ){ free(slist); free(sindex); }
+      znzclose(fp);
+      return -1;
+   }
+
+   rv = nifti_load_NBL_bricks(nim, slist, sindex, NBL, fp);
+
+   if( rv != 0 ){
+      nifti_free_NBL( NBL );  /* failure! */
+      NBL->nbricks = 0; /* repetative, but clear */
+   }
+
+   if( slist ){ free(slist); free(sindex); }
+
+   znzclose(fp);
+
+   return NBL->nbricks;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_free_NBL      - free all pointers and clear structure
+ *
+ * note: this does not presume to free the structure pointer
+*//*--------------------------------------------------------------------*/
+void nifti_free_NBL( nifti_brick_list * NBL )
+{
+   int c;
+
+   if( NBL->bricks ){
+      for( c = 0; c < NBL->nbricks; c++ )
+         if( NBL->bricks[c] ) free(NBL->bricks[c]);
+      free(NBL->bricks);
+      NBL->bricks = NULL;
+   }
+
+   NBL->bsize = NBL->nbricks = 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_load_NBL_bricks      - read the file data into the NBL struct
+ *
+ * return 0 on success, -1 on failure
+ *----------------------------------------------------------------------*/
+static int nifti_load_NBL_bricks( nifti_image * nim , int * slist, int * sindex,
+                                  nifti_brick_list * NBL, znzFile fp )
+{
+   size_t oposn, fposn;      /* orig and current file positions */
+   size_t rv;
+   long   test;
+   int    c;
+   int    prev, isrc, idest; /* previous and current sub-brick, and new index */
+
+   test = znztell(fp);  /* store current file position */
+   if( test < 0 ){
+      REprintf("** load bricks: ztell failed??\n");
+      return -1;
+   }
+   fposn = oposn = test;
+
+   /* first, handle the default case, no passed blist */
+   if( !slist ){
+      for( c = 0; c < NBL->nbricks; c++ ) {
+         rv = nifti_read_buffer(fp, NBL->bricks[c], NBL->bsize, nim);
+         if( rv != NBL->bsize ){
+            REprintf("** load bricks: cannot read brick %d from '%s'\n",
+                    c, nim->iname ? nim->iname : nim->fname);
+            return -1;
+         }
+      }
+      if( g_opts.debug > 1 )
+         REprintf("+d read %d default %u-byte bricks from file %s\n",
+                 NBL->nbricks, (unsigned int)NBL->bsize,
+                 nim->iname ? nim->iname:nim->fname );
+      return 0;
+   }
+
+   if( !sindex ){
+      REprintf("** load_NBL_bricks: missing index list\n");
+      return -1;
+   }
+
+   prev = -1;   /* use prev for previous sub-brick */
+   for( c = 0; c < NBL->nbricks; c++ ){
+       isrc = slist[c];   /* this is original brick index (c is new one) */
+       idest = sindex[c]; /* this is the destination index for this data */
+
+       /* if this sub-brick is not the previous, we must read from disk */
+       if( isrc != prev ){
+
+          /* if we are not looking at the correct sub-brick, scan forward */
+          if( fposn != (oposn + isrc*NBL->bsize) ){
+             fposn = oposn + isrc*NBL->bsize;
+             if( znzseek(fp, (long)fposn, SEEK_SET) < 0 ){
+                REprintf("** failed to locate brick %d in file '%s'\n",
+                        isrc, nim->iname ? nim->iname : nim->fname);
+                return -1;
+             }
+          }
+
+          /* only 10,000 lines later and we're actually reading something! */
+          rv = nifti_read_buffer(fp, NBL->bricks[idest], NBL->bsize, nim);
+          if( rv != NBL->bsize ){
+             REprintf("** failed to read brick %d from file '%s'\n",
+                     isrc, nim->iname ? nim->iname : nim->fname);
+             if( g_opts.debug > 1 )
+                REprintf("   (read %u of %u bytes)\n",
+                        (unsigned int)rv, (unsigned int)NBL->bsize);
+             return -1;
+          }
+          fposn += NBL->bsize;
+       } else {
+          /* we have already read this sub-brick, just copy the previous one */
+          /* note that this works because they are sorted */
+          memcpy(NBL->bricks[idest], NBL->bricks[sindex[c-1]], NBL->bsize);
+       }
+
+       prev = isrc;  /* in any case, note the now previous sub-brick */
+   }
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_alloc_NBL_mem      - allocate memory for bricks
+ *
+ * return 0 on success, -1 on failure
+ *----------------------------------------------------------------------*/
+static int nifti_alloc_NBL_mem(nifti_image * nim, int nbricks,
+                               nifti_brick_list * nbl)
+{
+   int c;
+
+   /* if nbricks is not specified, use the default */
+   if( nbricks > 0 ) nbl->nbricks = nbricks;
+   else {  /* I missed this one with the 1.17 change    02 Mar 2006 [rickr] */
+      nbl->nbricks = 1;
+      for( c = 4; c <= nim->ndim; c++ )
+          nbl->nbricks *= nim->dim[c];
+   }
+
+   nbl->bsize   = (size_t)nim->nx * nim->ny * nim->nz * nim->nbyper;/* bytes */
+   nbl->bricks  = (void **)malloc(nbl->nbricks * sizeof(void *));
+
+   if( ! nbl->bricks ){
+      REprintf("** NANM: failed to alloc %d void ptrs\n",nbricks);
+      return -1;
+   }
+
+   for( c = 0; c < nbl->nbricks; c++ ){
+      nbl->bricks[c] = (void *)malloc(nbl->bsize);
+      if( ! nbl->bricks[c] ){
+         REprintf("** NANM: failed to alloc %u bytes for brick %d\n",
+                 (unsigned int)nbl->bsize, c);
+         /* so free and clear everything before returning */
+         while( c > 0 ){
+            c--;
+            free(nbl->bricks[c]);
+         }
+         free(nbl->bricks);
+         nbl->bricks = NULL;
+         nbl->bsize = nbl->nbricks = 0;
+         return -1;
+      }
+   }
+
+   if( g_opts.debug > 2 )
+      REprintf("+d NANM: alloc'd %d bricks of %u bytes for NBL\n",
+              nbl->nbricks, (unsigned int)nbl->bsize);
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_copynsort      - copy int list, and sort with indices
+ *
+ * 1. duplicate the incoming list
+ * 2. create an sindex list, and init with 0..nbricks-1
+ * 3. do a slow insertion sort on the small slist, along with sindex list
+ * 4. check results, just to be positive
+ * 
+ * So slist is sorted, and sindex hold original positions.
+ *
+ * return 0 on success, -1 on failure
+ *----------------------------------------------------------------------*/
+static int nifti_copynsort(int nbricks, const int * blist, int ** slist,
+                           int ** sindex)
+{
+   int * stmp, * itmp;   /* for ease of typing/reading */
+   int   c1, c2, spos, tmp;
+
+   *slist  = (int *)malloc(nbricks * sizeof(int));
+   *sindex = (int *)malloc(nbricks * sizeof(int));
+
+   if( !*slist || !*sindex ){
+      REprintf("** NCS: failed to alloc %d ints for sorting\n",nbricks);
+      if(*slist)  free(*slist);   /* maybe one succeeded */
+      if(*sindex) free(*sindex);
+      return -1;
+   }
+
+   /* init the lists */
+   memcpy(*slist, blist, nbricks*sizeof(int));
+   for( c1 = 0; c1 < nbricks; c1++ ) (*sindex)[c1] = c1;
+
+   /* now actually sort slist */
+   stmp = *slist;
+   itmp = *sindex;
+   for( c1 = 0; c1 < nbricks-1; c1++ ) {
+      /* find smallest value, init to current */
+      spos = c1;
+      for( c2 = c1+1; c2 < nbricks; c2++ )
+         if( stmp[c2] < stmp[spos] ) spos = c2;
+      if( spos != c1 ) /* swap: fine, don't maintain sub-order, see if I care */
+      {
+         tmp        = stmp[c1];      /* first swap the sorting values */
+         stmp[c1]   = stmp[spos];
+         stmp[spos] = tmp;
+
+         tmp        = itmp[c1];      /* then swap the index values */
+         itmp[c1]   = itmp[spos];
+         itmp[spos] = tmp;
+      }
+   }
+
+   if( g_opts.debug > 2 ){
+      REprintf(  "+d sorted indexing list:\n");
+      REprintf(  "  orig   : ");
+      for( c1 = 0; c1 < nbricks; c1++ ) REprintf( "  %d",blist[c1]);
+      REprintf("\n  new    : ");
+      for( c1 = 0; c1 < nbricks; c1++ ) REprintf( "  %d",stmp[c1]);
+      REprintf("\n  indices: ");
+      for( c1 = 0; c1 < nbricks; c1++ ) REprintf( "  %d",itmp[c1]);
+      REprintf("\n"); /*fputc('\n', stderr);*/
+   }
+
+   /* check the sort (why not?  I've got time...) */
+   for( c1 = 0; c1 < nbricks-1; c1++ ){
+       if( (stmp[c1] > stmp[c1+1]) || (blist[itmp[c1]] != stmp[c1]) ){
+          REprintf("** sorting screw-up, way to go, rick!\n");
+          free(stmp); free(itmp); *slist = NULL; *sindex = NULL;
+          return -1;
+       }
+   }
+
+   if( g_opts.debug > 2 ) REprintf("-d sorting is okay\n");
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! valid_nifti_brick_list      - check sub-brick list for image
+ *
+ * This function verifies that nbricks and blist are appropriate
+ * for use with this nim, based on the dimensions.
+ *
+ * \param nim        nifti_image to check against
+ * \param nbricks    number of brick indices in blist
+ * \param blist      list of brick indices to check in nim
+ * \param disp_error if this flag is set, report errors to user
+ *
+ * \return 1 if valid, 0 if not
+*//*--------------------------------------------------------------------*/
+int valid_nifti_brick_list(nifti_image * nim , int nbricks,
+                           const int * blist, int disp_error)
+{
+   int c, nsubs;
+
+   if( !nim ){
+      if( disp_error || g_opts.debug > 0 )
+         REprintf("** valid_nifti_brick_list: missing nifti image\n");
+      return 0;
+   }
+
+   if( nbricks <= 0 || !blist ){
+      if( disp_error || g_opts.debug > 1 )
+         REprintf("** valid_nifti_brick_list: no brick list to check\n");
+      return 0;
+   }
+
+   if( nim->dim[0] < 3 ){
+      if( disp_error || g_opts.debug > 1 )
+         REprintf("** cannot read explict brick list from %d-D dataset\n",
+                 nim->dim[0]);
+      return 0;
+   }
+
+   /* nsubs sub-brick is nt*nu*nv*nw */
+   for( c = 4, nsubs = 1; c <= nim->dim[0]; c++ )
+      nsubs *= nim->dim[c];
+
+   if( nsubs <= 0 ){
+      REprintf("** VNBL warning: bad dim list (%d,%d,%d,%d)\n",
+                     nim->dim[4], nim->dim[5], nim->dim[6], nim->dim[7]);
+      return 0;
+   }
+
+   for( c = 0; c < nbricks; c++ )
+      if( (blist[c] < 0) || (blist[c] >= nsubs) ){
+         if( disp_error || g_opts.debug > 1 )
+            REprintf("** volume index %d (#%d) is out of range [0,%d]\n",
+               blist[c], c, nsubs-1);
+         return 0;
+      }
+
+   return 1;  /* all is well */
+}
+
+/*----------------------------------------------------------------------*/
+/* verify that NBL struct is a valid data source for the image
+ *
+ * return 1 if so, 0 otherwise
+*//*--------------------------------------------------------------------*/
+static int nifti_NBL_matches_nim(const nifti_image *nim,
+                                 const nifti_brick_list *NBL)
+{
+   size_t volbytes = 0;     /* bytes per volume */
+   int    ind, errs = 0, nvols = 0;
+
+
+   if( !nim || !NBL ) {
+      if( g_opts.debug > 0 )
+         REprintf("** nifti_NBL_matches_nim: NULL pointer(s)\n");
+      return 0;
+   }
+
+   /* for nim, compute volbytes and nvols */
+   if( nim->ndim > 0 ) {
+      /* first 3 indices are over a single volume */
+      volbytes = (size_t)nim->nbyper;
+      for( ind = 1; ind <= nim->ndim && ind < 4; ind++ )
+         volbytes *= (size_t)nim->dim[ind];
+
+      for( ind = 4, nvols = 1; ind <= nim->ndim; ind++ )
+         nvols *= nim->dim[ind];
+   }
+
+   if( volbytes != NBL->bsize ) {
+      if( g_opts.debug > 1 )
+         REprintf("** NBL/nim mismatch, volbytes = %u, %u\n",
+                 (unsigned)NBL->bsize, (unsigned)volbytes);
+      errs++;
+   }
+
+   if( nvols != NBL->nbricks ) {
+      if( g_opts.debug > 1 )
+         REprintf("** NBL/nim mismatch, nvols = %d, %d\n",
+                 NBL->nbricks, nvols);
+      errs++;
+   }
+
+   if( errs ) return 0;
+   else if ( g_opts.debug > 2 )
+      REprintf("-- nim/NBL agree: nvols = %d, nbytes = %u\n",
+              nvols, (unsigned)volbytes);
+
+   return 1;
+}
+
+/* end of new nifti_image_read_bricks() functionality */
+
+/*----------------------------------------------------------------------*/
+/*! display the orientation from the quaternian fields
+ *
+ * \param mesg if non-NULL, display this message first
+ * \param mat  the matrix to convert to "nearest" orientation
+ *
+ * \return -1 if results cannot be determined, 0 if okay
+*//*--------------------------------------------------------------------*/
+int nifti_disp_matrix_orient( const char * mesg, mat44 mat )
+{
+   int i, j, k;
+
+   if ( mesg ) Rprintf(mesg);  /* use stdout? */
+
+   nifti_mat44_to_orientation( mat, &i,&j,&k );
+   if ( i <= 0 || j <= 0 || k <= 0 ) return -1;
+
+   /* so we have good codes */
+   Rprintf("  i orientation = '%s'\n"
+           "  j orientation = '%s'\n"
+           "  k orientation = '%s'\n",
+           nifti_orientation_string(i),
+           nifti_orientation_string(j),
+           nifti_orientation_string(k) );
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! duplicate the given string (alloc length+1)
+ *
+ * \return allocated pointer (or NULL on failure)
+*//*--------------------------------------------------------------------*/
+char *nifti_strdup(const char *str)
+{
+  char *dup;
+
+  if( !str ) return NULL;       /* allow calls passing NULL */
+
+  dup = (char *)malloc(strlen(str) + 1);
+
+  /* check for failure */
+  if( dup ) strcpy(dup, str);
+  else      REprintf("** nifti_strdup: failed to alloc %u bytes\n", 
+                    (unsigned int)strlen(str)+1);
+
+  return dup;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI datatype.
+
+    \param dt NIfTI-1 datatype
+
+    \return pointer to static string holding the datatype name
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa NIFTI1_DATATYPES group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_datatype_string( int dt )
+{
+   switch( dt ){
+     case DT_UNKNOWN:    return "UNKNOWN"    ;
+     case DT_BINARY:     return "BINARY"     ;
+     case DT_INT8:       return "INT8"       ;
+     case DT_UINT8:      return "UINT8"      ;
+     case DT_INT16:      return "INT16"      ;
+     case DT_UINT16:     return "UINT16"     ;
+     case DT_INT32:      return "INT32"      ;
+     case DT_UINT32:     return "UINT32"     ;
+     case DT_INT64:      return "INT64"      ;
+     case DT_UINT64:     return "UINT64"     ;
+     case DT_FLOAT32:    return "FLOAT32"    ;
+     case DT_FLOAT64:    return "FLOAT64"    ;
+     case DT_FLOAT128:   return "FLOAT128"   ;
+     case DT_COMPLEX64:  return "COMPLEX64"  ;
+     case DT_COMPLEX128: return "COMPLEX128" ;
+     case DT_COMPLEX256: return "COMPLEX256" ;
+     case DT_RGB24:      return "RGB24"      ;
+     case DT_RGBA32:     return "RGBA32"     ;
+   }
+   return "**ILLEGAL**" ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! Determine if the datatype code dt is an integer type (1=YES, 0=NO).
+
+    \return whether the given NIfTI-1 datatype code is valid
+
+    \sa     NIFTI1_DATATYPES group in nifti1.h
+*//*--------------------------------------------------------------------*/
+int nifti_is_inttype( int dt )
+{
+   switch( dt ){
+     case DT_UNKNOWN:    return 0 ;
+     case DT_BINARY:     return 0 ;
+     case DT_INT8:       return 1 ;
+     case DT_UINT8:      return 1 ;
+     case DT_INT16:      return 1 ;
+     case DT_UINT16:     return 1 ;
+     case DT_INT32:      return 1 ;
+     case DT_UINT32:     return 1 ;
+     case DT_INT64:      return 1 ;
+     case DT_UINT64:     return 1 ;
+     case DT_FLOAT32:    return 0 ;
+     case DT_FLOAT64:    return 0 ;
+     case DT_FLOAT128:   return 0 ;
+     case DT_COMPLEX64:  return 0 ;
+     case DT_COMPLEX128: return 0 ;
+     case DT_COMPLEX256: return 0 ;
+     case DT_RGB24:      return 1 ;
+     case DT_RGBA32:     return 1 ;
+   }
+   return 0 ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI units type.
+
+    \param  uu NIfTI-1 unit code
+
+    \return pointer to static string for the given unit type
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_UNITS group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_units_string( int uu )
+{
+   switch( uu ){
+     case NIFTI_UNITS_METER:  return "m" ;
+     case NIFTI_UNITS_MM:     return "mm" ;
+     case NIFTI_UNITS_MICRON: return "um" ;
+     case NIFTI_UNITS_SEC:    return "s" ;
+     case NIFTI_UNITS_MSEC:   return "ms" ;
+     case NIFTI_UNITS_USEC:   return "us" ;
+     case NIFTI_UNITS_HZ:     return "Hz" ;
+     case NIFTI_UNITS_PPM:    return "ppm" ;
+     case NIFTI_UNITS_RADS:   return "rad/s" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI transform type.
+
+    \param  xx NIfTI-1 xform code
+
+    \return pointer to static string describing xform code
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_XFORM_CODES group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_xform_string( int xx )
+{
+   switch( xx ){
+     case NIFTI_XFORM_SCANNER_ANAT:  return "Scanner Anat" ;
+     case NIFTI_XFORM_ALIGNED_ANAT:  return "Aligned Anat" ;
+     case NIFTI_XFORM_TALAIRACH:     return "Talairach" ;
+     case NIFTI_XFORM_MNI_152:       return "MNI_152" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI intent type.
+
+    \param  ii NIfTI-1 intent code
+
+    \return pointer to static string describing code
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_INTENT_CODES group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_intent_string( int ii )
+{
+   switch( ii ){
+     case NIFTI_INTENT_CORREL:     return "Correlation statistic" ;
+     case NIFTI_INTENT_TTEST:      return "T-statistic" ;
+     case NIFTI_INTENT_FTEST:      return "F-statistic" ;
+     case NIFTI_INTENT_ZSCORE:     return "Z-score"     ;
+     case NIFTI_INTENT_CHISQ:      return "Chi-squared distribution" ;
+     case NIFTI_INTENT_BETA:       return "Beta distribution" ;
+     case NIFTI_INTENT_BINOM:      return "Binomial distribution" ;
+     case NIFTI_INTENT_GAMMA:      return "Gamma distribution" ;
+     case NIFTI_INTENT_POISSON:    return "Poisson distribution" ;
+     case NIFTI_INTENT_NORMAL:     return "Normal distribution" ;
+     case NIFTI_INTENT_FTEST_NONC: return "F-statistic noncentral" ;
+     case NIFTI_INTENT_CHISQ_NONC: return "Chi-squared noncentral" ;
+     case NIFTI_INTENT_LOGISTIC:   return "Logistic distribution" ;
+     case NIFTI_INTENT_LAPLACE:    return "Laplace distribution" ;
+     case NIFTI_INTENT_UNIFORM:    return "Uniform distribition" ;
+     case NIFTI_INTENT_TTEST_NONC: return "T-statistic noncentral" ;
+     case NIFTI_INTENT_WEIBULL:    return "Weibull distribution" ;
+     case NIFTI_INTENT_CHI:        return "Chi distribution" ;
+     case NIFTI_INTENT_INVGAUSS:   return "Inverse Gaussian distribution" ;
+     case NIFTI_INTENT_EXTVAL:     return "Extreme Value distribution" ;
+     case NIFTI_INTENT_PVAL:       return "P-value" ;
+
+     case NIFTI_INTENT_LOGPVAL:    return "Log P-value" ;
+     case NIFTI_INTENT_LOG10PVAL:  return "Log10 P-value" ;
+
+     case NIFTI_INTENT_ESTIMATE:   return "Estimate" ;
+     case NIFTI_INTENT_LABEL:      return "Label index" ;
+     case NIFTI_INTENT_NEURONAME:  return "NeuroNames index" ;
+     case NIFTI_INTENT_GENMATRIX:  return "General matrix" ;
+     case NIFTI_INTENT_SYMMATRIX:  return "Symmetric matrix" ;
+     case NIFTI_INTENT_DISPVECT:   return "Displacement vector" ;
+     case NIFTI_INTENT_VECTOR:     return "Vector" ;
+     case NIFTI_INTENT_POINTSET:   return "Pointset" ;
+     case NIFTI_INTENT_TRIANGLE:   return "Triangle" ;
+     case NIFTI_INTENT_QUATERNION: return "Quaternion" ;
+
+     case NIFTI_INTENT_DIMLESS:    return "Dimensionless number" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI slice_code.
+
+    \param  ss NIfTI-1 slice order code
+
+    \return pointer to static string describing code
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_SLICE_ORDER group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_slice_string( int ss )
+{
+   switch( ss ){
+     case NIFTI_SLICE_SEQ_INC:  return "sequential_increasing"    ;
+     case NIFTI_SLICE_SEQ_DEC:  return "sequential_decreasing"    ;
+     case NIFTI_SLICE_ALT_INC:  return "alternating_increasing"   ;
+     case NIFTI_SLICE_ALT_DEC:  return "alternating_decreasing"   ;
+     case NIFTI_SLICE_ALT_INC2: return "alternating_increasing_2" ;
+     case NIFTI_SLICE_ALT_DEC2: return "alternating_decreasing_2" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI orientation.
+
+    \param ii orientation code
+
+    \return pointer to static string holding the orientation information
+
+    \warning Do not free() or modify the return string!
+             It points to static storage.
+
+    \sa  NIFTI_L2R in nifti1_io.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_orientation_string( int ii )
+{
+   switch( ii ){
+     case NIFTI_L2R: return "Left-to-Right" ;
+     case NIFTI_R2L: return "Right-to-Left" ;
+     case NIFTI_P2A: return "Posterior-to-Anterior" ;
+     case NIFTI_A2P: return "Anterior-to-Posterior" ;
+     case NIFTI_I2S: return "Inferior-to-Superior" ;
+     case NIFTI_S2I: return "Superior-to-Inferior" ;
+   }
+   return "Unknown" ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a datatype code, set number of bytes per voxel and the swapsize.
+
+    \param datatype nifti1 datatype code
+    \param nbyper   pointer to return value: number of bytes per voxel
+    \param swapsize pointer to return value: size of swap blocks
+
+    \return appropriate values at nbyper and swapsize
+
+    The swapsize is set to 0 if this datatype doesn't ever need swapping.
+
+    \sa NIFTI1_DATATYPES in nifti1.h
+*//*------------------------------------------------------------------------*/
+void nifti_datatype_sizes( int datatype , int *nbyper, int *swapsize )
+{
+   int nb=0, ss=0 ;
+   switch( datatype ){
+     case DT_INT8:
+     case DT_UINT8:       nb =  1 ; ss =  0 ; break ;
+
+     case DT_INT16:
+     case DT_UINT16:      nb =  2 ; ss =  2 ; break ;
+
+     case DT_RGB24:       nb =  3 ; ss =  0 ; break ;
+     case DT_RGBA32:      nb =  4 ; ss =  0 ; break ;
+
+     case DT_INT32:
+     case DT_UINT32:
+     case DT_FLOAT32:     nb =  4 ; ss =  4 ; break ;
+
+     case DT_COMPLEX64:   nb =  8 ; ss =  4 ; break ;
+
+     case DT_FLOAT64:
+     case DT_INT64:
+     case DT_UINT64:      nb =  8 ; ss =  8 ; break ;
+
+     case DT_FLOAT128:    nb = 16 ; ss = 16 ; break ;
+
+     case DT_COMPLEX128:  nb = 16 ; ss =  8 ; break ;
+
+     case DT_COMPLEX256:  nb = 32 ; ss = 16 ; break ;
+   }
+
+   ASSIF(nbyper,nb) ; ASSIF(swapsize,ss) ; return ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Given the quaternion parameters (etc.), compute a transformation matrix.
+
+   See comments in nifti1.h for details.
+     - qb,qc,qd = quaternion parameters
+     - qx,qy,qz = offset parameters
+     - dx,dy,dz = grid stepsizes (non-negative inputs are set to 1.0)
+     - qfac     = sign of dz step (< 0 is negative; >= 0 is positive)
+
+   <pre>
+   If qx=qy=qz=0, dx=dy=dz=1, then the output is a rotation matrix.
+   For qfac >= 0, the rotation is proper.
+   For qfac <  0, the rotation is improper.
+   </pre>
+
+   \see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h
+   \see nifti_mat44_to_quatern, nifti_make_orthog_mat44,
+       nifti_mat44_to_orientation
+
+*//*-------------------------------------------------------------------------*/
+mat44 nifti_quatern_to_mat44( float qb, float qc, float qd,
+                              float qx, float qy, float qz,
+                              float dx, float dy, float dz, float qfac )
+{
+   mat44 R ;
+   double a,b=qb,c=qc,d=qd , xd,yd,zd ;
+
+   /* last row is always [ 0 0 0 1 ] */
+
+   R.m[3][0]=R.m[3][1]=R.m[3][2] = 0.0 ; R.m[3][3]= 1.0 ;
+
+   /* compute a parameter from b,c,d */
+
+   a = 1.0l - (b*b + c*c + d*d) ;
+   if( a < 1.e-7l ){                   /* special case */
+     a = 1.0l / sqrt(b*b+c*c+d*d) ;
+     b *= a ; c *= a ; d *= a ;        /* normalize (b,c,d) vector */
+     a = 0.0l ;                        /* a = 0 ==> 180 degree rotation */
+   } else{
+     a = sqrt(a) ;                     /* angle = 2*arccos(a) */
+   }
+
+   /* load rotation matrix, including scaling factors for voxel sizes */
+
+   xd = (dx > 0.0) ? dx : 1.0l ;       /* make sure are positive */
+   yd = (dy > 0.0) ? dy : 1.0l ;
+   zd = (dz > 0.0) ? dz : 1.0l ;
+
+   if( qfac < 0.0 ) zd = -zd ;         /* left handedness? */
+
+   R.m[0][0] =        (a*a+b*b-c*c-d*d) * xd ;
+   R.m[0][1] = 2.0l * (b*c-a*d        ) * yd ;
+   R.m[0][2] = 2.0l * (b*d+a*c        ) * zd ;
+   R.m[1][0] = 2.0l * (b*c+a*d        ) * xd ;
+   R.m[1][1] =        (a*a+c*c-b*b-d*d) * yd ;
+   R.m[1][2] = 2.0l * (c*d-a*b        ) * zd ;
+   R.m[2][0] = 2.0l * (b*d-a*c        ) * xd ;
+   R.m[2][1] = 2.0l * (c*d+a*b        ) * yd ;
+   R.m[2][2] =        (a*a+d*d-c*c-b*b) * zd ;
+
+   /* load offsets */
+
+   R.m[0][3] = qx ; R.m[1][3] = qy ; R.m[2][3] = qz ;
+
+   return R ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Given the 3x4 upper corner of the matrix R, compute the quaternion
+   parameters that fit it.
+
+     - Any NULL pointer on input won't get assigned (e.g., if you don't want
+       dx,dy,dz, just pass NULL in for those pointers).
+     - If the 3 input matrix columns are NOT orthogonal, they will be
+       orthogonalized prior to calculating the parameters, using
+       the polar decomposition to find the orthogonal matrix closest
+       to the column-normalized input matrix.
+     - However, if the 3 input matrix columns are NOT orthogonal, then
+       the matrix produced by nifti_quatern_to_mat44 WILL have orthogonal
+       columns, so it won't be the same as the matrix input here.
+       This "feature" is because the NIFTI 'qform' transform is
+       deliberately not fully general -- it is intended to model a volume
+       with perpendicular axes.
+     - If the 3 input matrix columns are not even linearly independent,
+       you'll just have to take your luck, won't you?
+
+   \see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h
+
+   \see nifti_quatern_to_mat44, nifti_make_orthog_mat44,
+       nifti_mat44_to_orientation
+*//*-------------------------------------------------------------------------*/
+void nifti_mat44_to_quatern( mat44 R ,
+                             float *qb, float *qc, float *qd,
+                             float *qx, float *qy, float *qz,
+                             float *dx, float *dy, float *dz, float *qfac )
+{
+   double r11,r12,r13 , r21,r22,r23 , r31,r32,r33 ;
+   double xd,yd,zd , a,b,c,d ;
+   mat33 P,Q ;
+
+   /* offset outputs are read write out of input matrix  */
+
+   ASSIF(qx,R.m[0][3]) ; ASSIF(qy,R.m[1][3]) ; ASSIF(qz,R.m[2][3]) ;
+
+   /* load 3x3 matrix into local variables */
+
+   r11 = R.m[0][0] ; r12 = R.m[0][1] ; r13 = R.m[0][2] ;
+   r21 = R.m[1][0] ; r22 = R.m[1][1] ; r23 = R.m[1][2] ;
+   r31 = R.m[2][0] ; r32 = R.m[2][1] ; r33 = R.m[2][2] ;
+
+   /* compute lengths of each column; these determine grid spacings  */
+
+   xd = sqrt( r11*r11 + r21*r21 + r31*r31 ) ;
+   yd = sqrt( r12*r12 + r22*r22 + r32*r32 ) ;
+   zd = sqrt( r13*r13 + r23*r23 + r33*r33 ) ;
+
+   /* if a column length is zero, patch the trouble */
+
+   if( xd == 0.0l ){ r11 = 1.0l ; r21 = r31 = 0.0l ; xd = 1.0l ; }
+   if( yd == 0.0l ){ r22 = 1.0l ; r12 = r32 = 0.0l ; yd = 1.0l ; }
+   if( zd == 0.0l ){ r33 = 1.0l ; r13 = r23 = 0.0l ; zd = 1.0l ; }
+
+   /* assign the output lengths */
+
+   ASSIF(dx,xd) ; ASSIF(dy,yd) ; ASSIF(dz,zd) ;
+
+   /* normalize the columns */
+
+   r11 /= xd ; r21 /= xd ; r31 /= xd ;
+   r12 /= yd ; r22 /= yd ; r32 /= yd ;
+   r13 /= zd ; r23 /= zd ; r33 /= zd ;
+
+   /* At this point, the matrix has normal columns, but we have to allow
+      for the fact that the hideous user may not have given us a matrix
+      with orthogonal columns.
+
+      So, now find the orthogonal matrix closest to the current matrix.
+
+      One reason for using the polar decomposition to get this
+      orthogonal matrix, rather than just directly orthogonalizing
+      the columns, is so that inputting the inverse matrix to R
+      will result in the inverse orthogonal matrix at this point.
+      If we just orthogonalized the columns, this wouldn't necessarily hold. */
+
+   Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */
+   Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ;
+   Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ;
+
+   P = nifti_mat33_polar(Q) ;  /* P is orthog matrix closest to Q */
+
+   r11 = P.m[0][0] ; r12 = P.m[0][1] ; r13 = P.m[0][2] ; /* unload */
+   r21 = P.m[1][0] ; r22 = P.m[1][1] ; r23 = P.m[1][2] ;
+   r31 = P.m[2][0] ; r32 = P.m[2][1] ; r33 = P.m[2][2] ;
+
+   /*                            [ r11 r12 r13 ]               */
+   /* at this point, the matrix  [ r21 r22 r23 ] is orthogonal */
+   /*                            [ r31 r32 r33 ]               */
+
+   /* compute the determinant to determine if it is proper */
+
+   zd = r11*r22*r33-r11*r32*r23-r21*r12*r33
+       +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;  /* should be -1 or 1 */
+
+   if( zd > 0 ){             /* proper */
+     ASSIF(qfac,1.0) ;
+   } else {                  /* improper ==> flip 3rd column */
+     ASSIF(qfac,-1.0) ;
+     r13 = -r13 ; r23 = -r23 ; r33 = -r33 ;
+   }
+
+   /* now, compute quaternion parameters */
+
+   a = r11 + r22 + r33 + 1.0l ;
+
+   if( a > 0.5l ){                /* simplest case */
+     a = 0.5l * sqrt(a) ;
+     b = 0.25l * (r32-r23) / a ;
+     c = 0.25l * (r13-r31) / a ;
+     d = 0.25l * (r21-r12) / a ;
+   } else {                       /* trickier case */
+     xd = 1.0 + r11 - (r22+r33) ;  /* 4*b*b */
+     yd = 1.0 + r22 - (r11+r33) ;  /* 4*c*c */
+     zd = 1.0 + r33 - (r11+r22) ;  /* 4*d*d */
+     if( xd > 1.0 ){
+       b = 0.5l * sqrt(xd) ;
+       c = 0.25l* (r12+r21) / b ;
+       d = 0.25l* (r13+r31) / b ;
+       a = 0.25l* (r32-r23) / b ;
+     } else if( yd > 1.0 ){
+       c = 0.5l * sqrt(yd) ;
+       b = 0.25l* (r12+r21) / c ;
+       d = 0.25l* (r23+r32) / c ;
+       a = 0.25l* (r13-r31) / c ;
+     } else {
+       d = 0.5l * sqrt(zd) ;
+       b = 0.25l* (r13+r31) / d ;
+       c = 0.25l* (r23+r32) / d ;
+       a = 0.25l* (r21-r12) / d ;
+     }
+     if( a < 0.0l ){ b=-b ; c=-c ; d=-d; a=-a; }
+   }
+
+   ASSIF(qb,b) ; ASSIF(qc,c) ; ASSIF(qd,d) ;
+   return ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Compute the inverse of a bordered 4x4 matrix.
+
+     <pre>
+   - Some numerical code fragments were generated by Maple 8.
+   - If a singular matrix is input, the output matrix will be all zero.
+   - You can check for this by examining the [3][3] element, which will
+     be 1.0 for the normal case and 0.0 for the bad case.
+
+     The input matrix should have the form:
+        [ r11 r12 r13 v1 ]
+        [ r21 r22 r23 v2 ]
+        [ r31 r32 r33 v3 ]
+        [  0   0   0   1 ]
+     </pre>
+*//*-------------------------------------------------------------------------*/
+mat44 nifti_mat44_inverse( mat44 R )
+{
+   double r11,r12,r13,r21,r22,r23,r31,r32,r33,v1,v2,v3 , deti ;
+   mat44 Q ;
+                                                       /*  INPUT MATRIX IS:  */
+   r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2];  /* [ r11 r12 r13 v1 ] */
+   r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2];  /* [ r21 r22 r23 v2 ] */
+   r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2];  /* [ r31 r32 r33 v3 ] */
+   v1  = R.m[0][3]; v2  = R.m[1][3]; v3  = R.m[2][3];  /* [  0   0   0   1 ] */
+
+   deti = r11*r22*r33-r11*r32*r23-r21*r12*r33
+         +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;
+
+   if( deti != 0.0l ) deti = 1.0l / deti ;
+
+   Q.m[0][0] = deti*( r22*r33-r32*r23) ;
+   Q.m[0][1] = deti*(-r12*r33+r32*r13) ;
+   Q.m[0][2] = deti*( r12*r23-r22*r13) ;
+   Q.m[0][3] = deti*(-r12*r23*v3+r12*v2*r33+r22*r13*v3
+                     -r22*v1*r33-r32*r13*v2+r32*v1*r23) ;
+
+   Q.m[1][0] = deti*(-r21*r33+r31*r23) ;
+   Q.m[1][1] = deti*( r11*r33-r31*r13) ;
+   Q.m[1][2] = deti*(-r11*r23+r21*r13) ;
+   Q.m[1][3] = deti*( r11*r23*v3-r11*v2*r33-r21*r13*v3
+                     +r21*v1*r33+r31*r13*v2-r31*v1*r23) ;
+
+   Q.m[2][0] = deti*( r21*r32-r31*r22) ;
+   Q.m[2][1] = deti*(-r11*r32+r31*r12) ;
+   Q.m[2][2] = deti*( r11*r22-r21*r12) ;
+   Q.m[2][3] = deti*(-r11*r22*v3+r11*r32*v2+r21*r12*v3
+                     -r21*r32*v1-r31*r12*v2+r31*r22*v1) ;
+
+   Q.m[3][0] = Q.m[3][1] = Q.m[3][2] = 0.0l ;
+   Q.m[3][3] = (deti == 0.0l) ? 0.0l : 1.0l ; /* failure flag if deti == 0 */
+
+   return Q ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Input 9 floats and make an orthgonal mat44 out of them.
+
+   Each row is normalized, then nifti_mat33_polar() is used to orthogonalize
+   them.  If row #3 (r31,r32,r33) is input as zero, then it will be taken to
+   be the cross product of rows #1 and #2.
+
+   This function can be used to create a rotation matrix for transforming
+   an oblique volume to anatomical coordinates.  For this application:
+    - row #1 (r11,r12,r13) is the direction vector along the image i-axis
+    - row #2 (r21,r22,r23) is the direction vector along the image j-axis
+    - row #3 (r31,r32,r33) is the direction vector along the slice direction
+      (if available; otherwise enter it as 0's)
+
+   The first 2 rows can be taken from the DICOM attribute (0020,0037)
+   "Image Orientation (Patient)".
+
+   After forming the rotation matrix, the complete affine transformation from
+   (i,j,k) grid indexes to (x,y,z) spatial coordinates can be computed by
+   multiplying each column by the appropriate grid spacing:
+    - column #1 (R.m[0][0],R.m[1][0],R.m[2][0]) by delta-x
+    - column #2 (R.m[0][1],R.m[1][1],R.m[2][1]) by delta-y
+    - column #3 (R.m[0][2],R.m[1][2],R.m[2][2]) by delta-z
+
+   and by then placing the center (x,y,z) coordinates of voxel (0,0,0) into
+   the column #4 (R.m[0][3],R.m[1][3],R.m[2][3]).
+
+   \sa nifti_quatern_to_mat44, nifti_mat44_to_quatern,
+       nifti_mat44_to_orientation
+*//*-------------------------------------------------------------------------*/
+mat44 nifti_make_orthog_mat44( float r11, float r12, float r13 ,
+                               float r21, float r22, float r23 ,
+                               float r31, float r32, float r33  )
+{
+   mat44 R ;
+   mat33 Q , P ;
+   double val ;
+
+   R.m[3][0] = R.m[3][1] = R.m[3][2] = 0.0l ; R.m[3][3] = 1.0l ;
+
+   Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */
+   Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ;
+   Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ;
+
+   /* normalize row 1 */
+
+   val = Q.m[0][0]*Q.m[0][0] + Q.m[0][1]*Q.m[0][1] + Q.m[0][2]*Q.m[0][2] ;
+   if( val > 0.0l ){
+     val = 1.0l / sqrt(val) ;
+     Q.m[0][0] *= val ; Q.m[0][1] *= val ; Q.m[0][2] *= val ;
+   } else {
+     Q.m[0][0] = 1.0l ; Q.m[0][1] = 0.0l ; Q.m[0][2] = 0.0l ;
+   }
+
+   /* normalize row 2 */
+
+   val = Q.m[1][0]*Q.m[1][0] + Q.m[1][1]*Q.m[1][1] + Q.m[1][2]*Q.m[1][2] ;
+   if( val > 0.0l ){
+     val = 1.0l / sqrt(val) ;
+     Q.m[1][0] *= val ; Q.m[1][1] *= val ; Q.m[1][2] *= val ;
+   } else {
+     Q.m[1][0] = 0.0l ; Q.m[1][1] = 1.0l ; Q.m[1][2] = 0.0l ;
+   }
+
+   /* normalize row 3 */
+
+   val = Q.m[2][0]*Q.m[2][0] + Q.m[2][1]*Q.m[2][1] + Q.m[2][2]*Q.m[2][2] ;
+   if( val > 0.0l ){
+     val = 1.0l / sqrt(val) ;
+     Q.m[2][0] *= val ; Q.m[2][1] *= val ; Q.m[2][2] *= val ;
+   } else {
+     Q.m[2][0] = Q.m[0][1]*Q.m[1][2] - Q.m[0][2]*Q.m[1][1] ;  /* cross */
+     Q.m[2][1] = Q.m[0][2]*Q.m[1][0] - Q.m[0][0]*Q.m[1][2] ;  /* product */
+     Q.m[2][2] = Q.m[0][0]*Q.m[1][1] - Q.m[0][1]*Q.m[1][0] ;
+   }
+
+   P = nifti_mat33_polar(Q) ;  /* P is orthog matrix closest to Q */
+
+   R.m[0][0] = P.m[0][0] ; R.m[0][1] = P.m[0][1] ; R.m[0][2] = P.m[0][2] ;
+   R.m[1][0] = P.m[1][0] ; R.m[1][1] = P.m[1][1] ; R.m[1][2] = P.m[1][2] ;
+   R.m[2][0] = P.m[2][0] ; R.m[2][1] = P.m[2][1] ; R.m[2][2] = P.m[2][2] ;
+
+   R.m[0][3] = R.m[1][3] = R.m[2][3] = 0.0 ; return R ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the inverse of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+mat33 nifti_mat33_inverse( mat33 R )   /* inverse of 3x3 matrix */
+{
+   double r11,r12,r13,r21,r22,r23,r31,r32,r33 , deti ;
+   mat33 Q ;
+                                                       /*  INPUT MATRIX:  */
+   r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2];  /* [ r11 r12 r13 ] */
+   r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2];  /* [ r21 r22 r23 ] */
+   r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2];  /* [ r31 r32 r33 ] */
+
+   deti = r11*r22*r33-r11*r32*r23-r21*r12*r33
+         +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;
+
+   if( deti != 0.0l ) deti = 1.0l / deti ;
+
+   Q.m[0][0] = deti*( r22*r33-r32*r23) ;
+   Q.m[0][1] = deti*(-r12*r33+r32*r13) ;
+   Q.m[0][2] = deti*( r12*r23-r22*r13) ;
+
+   Q.m[1][0] = deti*(-r21*r33+r31*r23) ;
+   Q.m[1][1] = deti*( r11*r33-r31*r13) ;
+   Q.m[1][2] = deti*(-r11*r23+r21*r13) ;
+
+   Q.m[2][0] = deti*( r21*r32-r31*r22) ;
+   Q.m[2][1] = deti*(-r11*r32+r31*r12) ;
+   Q.m[2][2] = deti*( r11*r22-r21*r12) ;
+
+   return Q ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the determinant of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+float nifti_mat33_determ( mat33 R )   /* determinant of 3x3 matrix */
+{
+   double r11,r12,r13,r21,r22,r23,r31,r32,r33 ;
+                                                       /*  INPUT MATRIX:  */
+   r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2];  /* [ r11 r12 r13 ] */
+   r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2];  /* [ r21 r22 r23 ] */
+   r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2];  /* [ r31 r32 r33 ] */
+
+   return r11*r22*r33-r11*r32*r23-r21*r12*r33
+         +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the max row norm of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+float nifti_mat33_rownorm( mat33 A )  /* max row norm of 3x3 matrix */
+{
+   float r1,r2,r3 ;
+
+   r1 = fabs(A.m[0][0])+fabs(A.m[0][1])+fabs(A.m[0][2]) ;
+   r2 = fabs(A.m[1][0])+fabs(A.m[1][1])+fabs(A.m[1][2]) ;
+   r3 = fabs(A.m[2][0])+fabs(A.m[2][1])+fabs(A.m[2][2]) ;
+   if( r1 < r2 ) r1 = r2 ;
+   if( r1 < r3 ) r1 = r3 ;
+   return r1 ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the max column norm of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+float nifti_mat33_colnorm( mat33 A )  /* max column norm of 3x3 matrix */
+{
+   float r1,r2,r3 ;
+
+   r1 = fabs(A.m[0][0])+fabs(A.m[1][0])+fabs(A.m[2][0]) ;
+   r2 = fabs(A.m[0][1])+fabs(A.m[1][1])+fabs(A.m[2][1]) ;
+   r3 = fabs(A.m[0][2])+fabs(A.m[1][2])+fabs(A.m[2][2]) ;
+   if( r1 < r2 ) r1 = r2 ;
+   if( r1 < r3 ) r1 = r3 ;
+   return r1 ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! multiply 2 3x3 matrices
+*//*--------------------------------------------------------------------*/
+mat33 nifti_mat33_mul( mat33 A , mat33 B )  /* multiply 2 3x3 matrices */
+{
+   mat33 C ; int i,j ;
+   for( i=0 ; i < 3 ; i++ )
+    for( j=0 ; j < 3 ; j++ )
+      C.m[i][j] =  A.m[i][0] * B.m[0][j]
+                 + A.m[i][1] * B.m[1][j]
+                 + A.m[i][2] * B.m[2][j] ;
+   return C ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! polar decomposition of a 3x3 matrix
+
+   This finds the closest orthogonal matrix to input A
+   (in both the Frobenius and L2 norms).
+
+   Algorithm is that from NJ Higham, SIAM J Sci Stat Comput, 7:1160-1174.
+*//*-------------------------------------------------------------------------*/
+mat33 nifti_mat33_polar( mat33 A )
+{
+   mat33 X , Y , Z ;
+   float alp,bet,gam,gmi , dif=1.0 ;
+   int k=0 ;
+
+   X = A ;
+
+   /* force matrix to be nonsingular */
+
+   gam = nifti_mat33_determ(X) ;
+   while( gam == 0.0 ){        /* perturb matrix */
+     gam = 0.00001 * ( 0.001 + nifti_mat33_rownorm(X) ) ;
+     X.m[0][0] += gam ; X.m[1][1] += gam ; X.m[2][2] += gam ;
+     gam = nifti_mat33_determ(X) ;
+   }
+
+   while(1){
+     Y = nifti_mat33_inverse(X) ;
+     if( dif > 0.3 ){     /* far from convergence */
+       alp = sqrt( nifti_mat33_rownorm(X) * nifti_mat33_colnorm(X) ) ;
+       bet = sqrt( nifti_mat33_rownorm(Y) * nifti_mat33_colnorm(Y) ) ;
+       gam = sqrt( bet / alp ) ;
+       gmi = 1.0 / gam ;
+     } else {
+       gam = gmi = 1.0 ;  /* close to convergence */
+     }
+     Z.m[0][0] = 0.5 * ( gam*X.m[0][0] + gmi*Y.m[0][0] ) ;
+     Z.m[0][1] = 0.5 * ( gam*X.m[0][1] + gmi*Y.m[1][0] ) ;
+     Z.m[0][2] = 0.5 * ( gam*X.m[0][2] + gmi*Y.m[2][0] ) ;
+     Z.m[1][0] = 0.5 * ( gam*X.m[1][0] + gmi*Y.m[0][1] ) ;
+     Z.m[1][1] = 0.5 * ( gam*X.m[1][1] + gmi*Y.m[1][1] ) ;
+     Z.m[1][2] = 0.5 * ( gam*X.m[1][2] + gmi*Y.m[2][1] ) ;
+     Z.m[2][0] = 0.5 * ( gam*X.m[2][0] + gmi*Y.m[0][2] ) ;
+     Z.m[2][1] = 0.5 * ( gam*X.m[2][1] + gmi*Y.m[1][2] ) ;
+     Z.m[2][2] = 0.5 * ( gam*X.m[2][2] + gmi*Y.m[2][2] ) ;
+
+     dif = fabs(Z.m[0][0]-X.m[0][0])+fabs(Z.m[0][1]-X.m[0][1])
+          +fabs(Z.m[0][2]-X.m[0][2])+fabs(Z.m[1][0]-X.m[1][0])
+          +fabs(Z.m[1][1]-X.m[1][1])+fabs(Z.m[1][2]-X.m[1][2])
+          +fabs(Z.m[2][0]-X.m[2][0])+fabs(Z.m[2][1]-X.m[2][1])
+          +fabs(Z.m[2][2]-X.m[2][2])                          ;
+
+     k = k+1 ;
+     if( k > 100 || dif < 3.e-6 ) break ;  /* convergence or exhaustion */
+     X = Z ;
+   }
+
+   return Z ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! compute the (closest) orientation from a 4x4 ijk->xyz tranformation matrix
+
+   <pre>
+   Input:  4x4 matrix that transforms (i,j,k) indexes to (x,y,z) coordinates,
+           where +x=Right, +y=Anterior, +z=Superior.
+           (Only the upper-left 3x3 corner of R is used herein.)
+   Output: 3 orientation codes that correspond to the closest "standard"
+           anatomical orientation of the (i,j,k) axes.
+   Method: Find which permutation of (x,y,z) has the smallest angle to the
+           (i,j,k) axes directions, which are the columns of the R matrix.
+   Errors: The codes returned will be zero.
+
+   For example, an axial volume might get return values of
+     *icod = NIFTI_R2L   (i axis is mostly Right to Left)
+     *jcod = NIFTI_P2A   (j axis is mostly Posterior to Anterior)
+     *kcod = NIFTI_I2S   (k axis is mostly Inferior to Superior)
+   </pre>
+
+   \see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h
+
+   \see nifti_quatern_to_mat44, nifti_mat44_to_quatern,
+        nifti_make_orthog_mat44
+*//*-------------------------------------------------------------------------*/
+void nifti_mat44_to_orientation( mat44 R , int *icod, int *jcod, int *kcod )
+{
+   float xi,xj,xk , yi,yj,yk , zi,zj,zk , val,detQ,detP ;
+   mat33 P , Q , M ;
+   int i,j,k=0,p,q,r , ibest,jbest,kbest,pbest,qbest,rbest ;
+   float vbest ;
+
+   if( icod == NULL || jcod == NULL || kcod == NULL ) return ; /* bad */
+
+   *icod = *jcod = *kcod = 0 ; /* error returns, if sh*t happens */
+
+   /* load column vectors for each (i,j,k) direction from matrix */
+
+   /*-- i axis --*/ /*-- j axis --*/ /*-- k axis --*/
+
+   xi = R.m[0][0] ; xj = R.m[0][1] ; xk = R.m[0][2] ;
+   yi = R.m[1][0] ; yj = R.m[1][1] ; yk = R.m[1][2] ;
+   zi = R.m[2][0] ; zj = R.m[2][1] ; zk = R.m[2][2] ;
+
+   /* normalize column vectors to get unit vectors along each ijk-axis */
+
+   /* normalize i axis */
+
+   val = sqrt( xi*xi + yi*yi + zi*zi ) ;
+   if( val == 0.0 ) return ;                 /* stupid input */
+   xi /= val ; yi /= val ; zi /= val ;
+
+   /* normalize j axis */
+
+   val = sqrt( xj*xj + yj*yj + zj*zj ) ;
+   if( val == 0.0 ) return ;                 /* stupid input */
+   xj /= val ; yj /= val ; zj /= val ;
+
+   /* orthogonalize j axis to i axis, if needed */
+
+   val = xi*xj + yi*yj + zi*zj ;    /* dot product between i and j */
+   if( fabs(val) > 1.e-4 ){
+     xj -= val*xi ; yj -= val*yi ; zj -= val*zi ;
+     val = sqrt( xj*xj + yj*yj + zj*zj ) ;  /* must renormalize */
+     if( val == 0.0 ) return ;              /* j was parallel to i? */
+     xj /= val ; yj /= val ; zj /= val ;
+   }
+
+   /* normalize k axis; if it is zero, make it the cross product i x j */
+
+   val = sqrt( xk*xk + yk*yk + zk*zk ) ;
+   if( val == 0.0 ){ xk = yi*zj-zi*yj; yk = zi*xj-zj*xi ; zk=xi*yj-yi*xj ; }
+   else            { xk /= val ; yk /= val ; zk /= val ; }
+
+   /* orthogonalize k to i */
+
+   val = xi*xk + yi*yk + zi*zk ;    /* dot product between i and k */
+   if( fabs(val) > 1.e-4 ){
+     xk -= val*xi ; yk -= val*yi ; zk -= val*zi ;
+     val = sqrt( xk*xk + yk*yk + zk*zk ) ;
+     if( val == 0.0 ) return ;      /* bad */
+     xk /= val ; yk /= val ; zk /= val ;
+   }
+
+   /* orthogonalize k to j */
+
+   val = xj*xk + yj*yk + zj*zk ;    /* dot product between j and k */
+   if( fabs(val) > 1.e-4 ){
+     xk -= val*xj ; yk -= val*yj ; zk -= val*zj ;
+     val = sqrt( xk*xk + yk*yk + zk*zk ) ;
+     if( val == 0.0 ) return ;      /* bad */
+     xk /= val ; yk /= val ; zk /= val ;
+   }
+
+   Q.m[0][0] = xi ; Q.m[0][1] = xj ; Q.m[0][2] = xk ;
+   Q.m[1][0] = yi ; Q.m[1][1] = yj ; Q.m[1][2] = yk ;
+   Q.m[2][0] = zi ; Q.m[2][1] = zj ; Q.m[2][2] = zk ;
+
+   /* at this point, Q is the rotation matrix from the (i,j,k) to (x,y,z) axes */
+
+   detQ = nifti_mat33_determ( Q ) ;
+   if( detQ == 0.0 ) return ; /* shouldn't happen unless user is a DUFIS */
+
+   /* Build and test all possible +1/-1 coordinate permutation matrices P;
+      then find the P such that the rotation matrix M=PQ is closest to the
+      identity, in the sense of M having the smallest total rotation angle. */
+
+   /* Despite the formidable looking 6 nested loops, there are
+      only 3*3*3*2*2*2 = 216 passes, which will run very quickly. */
+
+   vbest = -666.0 ; ibest=pbest=qbest=rbest=1 ; jbest=2 ; kbest=3 ;
+   for( i=1 ; i <= 3 ; i++ ){     /* i = column number to use for row #1 */
+    for( j=1 ; j <= 3 ; j++ ){    /* j = column number to use for row #2 */
+     if( i == j ) continue ;
+      for( k=1 ; k <= 3 ; k++ ){  /* k = column number to use for row #3 */
+       if( i == k || j == k ) continue ;
+       P.m[0][0] = P.m[0][1] = P.m[0][2] =
+        P.m[1][0] = P.m[1][1] = P.m[1][2] =
+         P.m[2][0] = P.m[2][1] = P.m[2][2] = 0.0 ;
+       for( p=-1 ; p <= 1 ; p+=2 ){    /* p,q,r are -1 or +1      */
+        for( q=-1 ; q <= 1 ; q+=2 ){   /* and go into rows #1,2,3 */
+         for( r=-1 ; r <= 1 ; r+=2 ){
+           P.m[0][i-1] = p ; P.m[1][j-1] = q ; P.m[2][k-1] = r ;
+           detP = nifti_mat33_determ(P) ;           /* sign of permutation */
+           if( detP * detQ <= 0.0 ) continue ;  /* doesn't match sign of Q */
+           M = nifti_mat33_mul(P,Q) ;
+
+           /* angle of M rotation = 2.0*acos(0.5*sqrt(1.0+trace(M)))       */
+           /* we want largest trace(M) == smallest angle == M nearest to I */
+
+           val = M.m[0][0] + M.m[1][1] + M.m[2][2] ; /* trace */
+           if( val > vbest ){
+             vbest = val ;
+             ibest = i ; jbest = j ; kbest = k ;
+             pbest = p ; qbest = q ; rbest = r ;
+           }
+   }}}}}}
+
+   /* At this point ibest is 1 or 2 or 3; pbest is -1 or +1; etc.
+
+      The matrix P that corresponds is the best permutation approximation
+      to Q-inverse; that is, P (approximately) takes (x,y,z) coordinates
+      to the (i,j,k) axes.
+
+      For example, the first row of P (which contains pbest in column ibest)
+      determines the way the i axis points relative to the anatomical
+      (x,y,z) axes.  If ibest is 2, then the i axis is along the y axis,
+      which is direction P2A (if pbest > 0) or A2P (if pbest < 0).
+
+      So, using ibest and pbest, we can assign the output code for
+      the i axis.  Mutatis mutandis for the j and k axes, of course. */
+
+   switch( ibest*pbest ){
+     case  1: i = NIFTI_L2R ; break ;
+     case -1: i = NIFTI_R2L ; break ;
+     case  2: i = NIFTI_P2A ; break ;
+     case -2: i = NIFTI_A2P ; break ;
+     case  3: i = NIFTI_I2S ; break ;
+     case -3: i = NIFTI_S2I ; break ;
+   }
+
+   switch( jbest*qbest ){
+     case  1: j = NIFTI_L2R ; break ;
+     case -1: j = NIFTI_R2L ; break ;
+     case  2: j = NIFTI_P2A ; break ;
+     case -2: j = NIFTI_A2P ; break ;
+     case  3: j = NIFTI_I2S ; break ;
+     case -3: j = NIFTI_S2I ; break ;
+   }
+
+   switch( kbest*rbest ){
+     case  1: k = NIFTI_L2R ; break ;
+     case -1: k = NIFTI_R2L ; break ;
+     case  2: k = NIFTI_P2A ; break ;
+     case -2: k = NIFTI_A2P ; break ;
+     case  3: k = NIFTI_I2S ; break ;
+     case -3: k = NIFTI_S2I ; break ;
+   }
+
+   *icod = i ; *jcod = j ; *kcod = k ; return ;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Routines to swap byte arrays in various ways:
+    -  2 at a time:  ab               -> ba               [short]
+    -  4 at a time:  abcd             -> dcba             [int, float]
+    -  8 at a time:  abcdDCBA         -> ABCDdcba         [long long, double]
+    - 16 at a time:  abcdefghHGFEDCBA -> ABCDEFGHhgfedcba [long double]
+-----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/*! swap each byte pair from the given list of n pairs
+ * 
+ *  Due to alignment of structures at some architectures (e.g. on ARM),
+ *  stick to char varaibles.
+ *  Fixes http://bugs.debian.org/446893   Yaroslav <debian at onerussian.com>
+ *
+*//*--------------------------------------------------------------------*/
+void nifti_swap_2bytes( size_t n , void *ar )    /* 2 bytes at a time */
+{
+   register size_t ii ;
+   unsigned char * cp1 = (unsigned char *)ar, * cp2 ;
+   unsigned char   tval;
+
+   for( ii=0 ; ii < n ; ii++ ){
+       cp2 = cp1 + 1;
+       tval = *cp1;  *cp1 = *cp2;  *cp2 = tval;
+       cp1 += 2;
+   }
+   return ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! swap 4 bytes at a time from the given list of n sets of 4 bytes
+*//*--------------------------------------------------------------------*/
+void nifti_swap_4bytes( size_t n , void *ar )    /* 4 bytes at a time */
+{
+   register size_t ii ;
+   unsigned char * cp0 = (unsigned char *)ar, * cp1, * cp2 ;
+   register unsigned char tval ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+       cp1 = cp0; cp2 = cp0+3;
+       tval = *cp1;  *cp1 = *cp2;  *cp2 = tval;
+       cp1++;  cp2--;
+       tval = *cp1;  *cp1 = *cp2;  *cp2 = tval;
+       cp0 += 4;
+   }
+   return ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! swap 8 bytes at a time from the given list of n sets of 8 bytes
+ *
+ *  perhaps use this style for the general Nbytes, as Yaroslav suggests
+*//*--------------------------------------------------------------------*/
+void nifti_swap_8bytes( size_t n , void *ar )    /* 8 bytes at a time */
+{
+   register size_t ii ;
+   unsigned char * cp0 = (unsigned char *)ar, * cp1, * cp2 ;
+   register unsigned char tval ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+       cp1 = cp0;  cp2 = cp0+7;
+       while ( cp2 > cp1 )      /* unroll? */
+       {
+           tval = *cp1 ; *cp1 = *cp2 ; *cp2 = tval ;
+           cp1++; cp2--;
+       }
+       cp0 += 8;
+   }
+   return ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! swap 16 bytes at a time from the given list of n sets of 16 bytes
+*//*--------------------------------------------------------------------*/
+void nifti_swap_16bytes( size_t n , void *ar )    /* 16 bytes at a time */
+{
+   register size_t ii ;
+   unsigned char * cp0 = (unsigned char *)ar, * cp1, * cp2 ;
+   register unsigned char tval ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+       cp1 = cp0;  cp2 = cp0+15;
+       while ( cp2 > cp1 )
+       {
+           tval = *cp1 ; *cp1 = *cp2 ; *cp2 = tval ;
+           cp1++; cp2--;
+       }
+       cp0 += 16;
+   }
+   return ;
+}
+
+#if 0  /* not important: save for version update     6 Jul 2010 [rickr] */
+
+/*----------------------------------------------------------------------*/
+/*! generic: swap siz bytes at a time from the given list of n sets
+*//*--------------------------------------------------------------------*/
+void nifti_swap_bytes( size_t n , int siz , void *ar )
+{
+   register size_t ii ;
+   unsigned char * cp0 = (unsigned char *)ar, * cp1, * cp2 ;
+   register unsigned char tval ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+       cp1 = cp0;  cp2 = cp0+(siz-1);
+       while ( cp2 > cp1 )
+       {
+           tval = *cp1 ; *cp1 = *cp2 ; *cp2 = tval ;
+           cp1++; cp2--;
+       }
+       cp0 += siz;
+   }
+   return ;
+}
+#endif
+
+/*---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/*! based on siz, call the appropriate nifti_swap_Nbytes() function
+*//*--------------------------------------------------------------------*/
+void nifti_swap_Nbytes( size_t n , int size , void *ar )  /* subsuming case */
+{
+   switch( size ){
+     case 2:  nifti_swap_2bytes ( n , ar ) ; break ;
+     case 4:  nifti_swap_4bytes ( n , ar ) ; break ;
+     case 8:  nifti_swap_8bytes ( n , ar ) ; break ;
+     case 16: nifti_swap_16bytes( n , ar ) ; break ;
+     default:    /* nifti_swap_bytes  ( n , size, ar ) ; */
+        REprintf("** nifti_swap_Nbytes: cannot swap in %d byte blocks\n", size);
+        break ;
+   }
+   return ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/*! Byte swap NIFTI-1 file header in various places and ways.
+
+    If is_nifti, swap all (even UNUSED) fields of NIfTI header.
+    Else, swap as a nifti_analyze75 struct.
+*//*---------------------------------------------------------------------- */
+void swap_nifti_header( struct nifti_1_header *h , int is_nifti )
+{
+
+   /* if ANALYZE, swap as such and return */
+   if( ! is_nifti ) {
+      nifti_swap_as_analyze((nifti_analyze75 *)h);
+      return;
+   }
+
+   /* otherwise, swap all NIFTI fields */
+
+   nifti_swap_4bytes(1, &h->sizeof_hdr);
+   nifti_swap_4bytes(1, &h->extents);
+   nifti_swap_2bytes(1, &h->session_error);
+
+   nifti_swap_2bytes(8, h->dim);
+   nifti_swap_4bytes(1, &h->intent_p1);
+   nifti_swap_4bytes(1, &h->intent_p2);
+   nifti_swap_4bytes(1, &h->intent_p3);
+
+   nifti_swap_2bytes(1, &h->intent_code);
+   nifti_swap_2bytes(1, &h->datatype);
+   nifti_swap_2bytes(1, &h->bitpix);
+   nifti_swap_2bytes(1, &h->slice_start);
+
+   nifti_swap_4bytes(8, h->pixdim);
+
+   nifti_swap_4bytes(1, &h->vox_offset);
+   nifti_swap_4bytes(1, &h->scl_slope);
+   nifti_swap_4bytes(1, &h->scl_inter);
+   nifti_swap_2bytes(1, &h->slice_end);
+
+   nifti_swap_4bytes(1, &h->cal_max);
+   nifti_swap_4bytes(1, &h->cal_min);
+   nifti_swap_4bytes(1, &h->slice_duration);
+   nifti_swap_4bytes(1, &h->toffset);
+   nifti_swap_4bytes(1, &h->glmax);
+   nifti_swap_4bytes(1, &h->glmin);
+
+   nifti_swap_2bytes(1, &h->qform_code);
+   nifti_swap_2bytes(1, &h->sform_code);
+
+   nifti_swap_4bytes(1, &h->quatern_b);
+   nifti_swap_4bytes(1, &h->quatern_c);
+   nifti_swap_4bytes(1, &h->quatern_d);
+   nifti_swap_4bytes(1, &h->qoffset_x);
+   nifti_swap_4bytes(1, &h->qoffset_y);
+   nifti_swap_4bytes(1, &h->qoffset_z);
+
+   nifti_swap_4bytes(4, h->srow_x);
+   nifti_swap_4bytes(4, h->srow_y);
+   nifti_swap_4bytes(4, h->srow_z);
+
+   return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/*! Byte swap as an ANALYZE 7.5 header
+ *
+ *  return non-zero on failure
+*//*---------------------------------------------------------------------- */
+int nifti_swap_as_analyze( nifti_analyze75 * h )
+{
+   if( !h ) return 1;
+
+   nifti_swap_4bytes(1, &h->sizeof_hdr);
+   nifti_swap_4bytes(1, &h->extents);
+   nifti_swap_2bytes(1, &h->session_error);
+
+   nifti_swap_2bytes(8, h->dim);
+   nifti_swap_2bytes(1, &h->unused8);
+   nifti_swap_2bytes(1, &h->unused9);
+   nifti_swap_2bytes(1, &h->unused10);
+   nifti_swap_2bytes(1, &h->unused11);
+   nifti_swap_2bytes(1, &h->unused12);
+   nifti_swap_2bytes(1, &h->unused13);
+   nifti_swap_2bytes(1, &h->unused14);
+
+   nifti_swap_2bytes(1, &h->datatype);
+   nifti_swap_2bytes(1, &h->bitpix);
+   nifti_swap_2bytes(1, &h->dim_un0);
+
+   nifti_swap_4bytes(8, h->pixdim);
+
+   nifti_swap_4bytes(1, &h->vox_offset);
+   nifti_swap_4bytes(1, &h->funused1);
+   nifti_swap_4bytes(1, &h->funused2);
+   nifti_swap_4bytes(1, &h->funused3);
+
+   nifti_swap_4bytes(1, &h->cal_max);
+   nifti_swap_4bytes(1, &h->cal_min);
+   nifti_swap_4bytes(1, &h->compressed);
+   nifti_swap_4bytes(1, &h->verified);
+
+   nifti_swap_4bytes(1, &h->glmax);
+   nifti_swap_4bytes(1, &h->glmin);
+
+   nifti_swap_4bytes(1, &h->views);
+   nifti_swap_4bytes(1, &h->vols_added);
+   nifti_swap_4bytes(1, &h->start_field);
+   nifti_swap_4bytes(1, &h->field_skip);
+
+   nifti_swap_4bytes(1, &h->omax);
+   nifti_swap_4bytes(1, &h->omin);
+   nifti_swap_4bytes(1, &h->smax);
+   nifti_swap_4bytes(1, &h->smin);
+
+   return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+/*! OLD VERSION of swap_nifti_header (left for undo/compare operations)
+  
+    Byte swap NIFTI-1 file header in various places and ways.
+
+    If is_nifti is nonzero, will also swap the NIFTI-specific
+    components of the header; otherwise, only the components
+    common to NIFTI and ANALYZE will be swapped.
+*//*---------------------------------------------------------------------- */
+void old_swap_nifti_header( struct nifti_1_header *h , int is_nifti )
+{
+   /* this stuff is always present, for ANALYZE and NIFTI */
+
+   swap_4(h->sizeof_hdr) ;
+   nifti_swap_2bytes( 8 , h->dim ) ;
+   nifti_swap_4bytes( 8 , h->pixdim ) ;
+
+   swap_2(h->datatype) ;
+   swap_2(h->bitpix) ;
+
+   swap_4(h->vox_offset); swap_4(h->cal_max); swap_4(h->cal_min);
+
+   /* this stuff is NIFTI specific */
+
+   if( is_nifti ){
+     swap_4(h->intent_p1); swap_4(h->intent_p2); swap_4(h->intent_p3);
+     swap_2(h->intent_code);
+
+     swap_2(h->slice_start);    swap_2(h->slice_end);
+     swap_4(h->scl_slope);      swap_4(h->scl_inter);
+     swap_4(h->slice_duration); swap_4(h->toffset);
+
+     swap_2(h->qform_code); swap_2(h->sform_code);
+     swap_4(h->quatern_b); swap_4(h->quatern_c); swap_4(h->quatern_d);
+     swap_4(h->qoffset_x); swap_4(h->qoffset_y); swap_4(h->qoffset_z);
+     nifti_swap_4bytes(4,h->srow_x);
+     nifti_swap_4bytes(4,h->srow_y);
+     nifti_swap_4bytes(4,h->srow_z);
+   }
+   return ;
+}
+
+
+#define USE_STAT
+#ifdef  USE_STAT
+/*---------------------------------------------------------------------------*/
+/* Return the file length (0 if file not found or has no contents).
+   This is a Unix-specific function, since it uses stat().
+-----------------------------------------------------------------------------*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/*---------------------------------------------------------------------------*/
+/*! return the size of a file, in bytes
+
+    \return size of file on success, -1 on error or no file
+
+    changed to return int, -1 means no file or error      20 Dec 2004 [rickr]
+*//*-------------------------------------------------------------------------*/
+int nifti_get_filesize( const char *pathname )
+{
+   struct stat buf ; int ii ;
+
+   if( pathname == NULL || *pathname == '\0' ) return -1 ;
+   ii = stat( pathname , &buf ); if( ii != 0 ) return -1 ;
+   return (unsigned int)buf.st_size ;
+}
+
+#else  /*---------- non-Unix version of the above, less efficient -----------*/
+
+int nifti_get_filesize( const char *pathname )
+{
+   znzFile fp ; int len ;
+
+   if( pathname == NULL || *pathname == '\0' ) return -1 ;
+   fp = znzopen(pathname,"rb",0); if( znz_isnull(fp) ) return -1 ;
+   znzseek(fp,0L,SEEK_END) ; len = znztell(fp) ;
+   znzclose(fp) ; return len ;
+}
+
+#endif /* USE_STAT */
+
+
+/*----------------------------------------------------------------------*/
+/*! return the total volume size, in bytes
+
+    This is computed as nvox * nbyper.
+*//*--------------------------------------------------------------------*/
+size_t nifti_get_volsize(const nifti_image *nim)
+{
+   return nim->nbyper * nim->nvox ; /* total bytes */
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* Support functions for filenames in read and write
+   - allows for gzipped files
+*/
+
+
+/*----------------------------------------------------------------------*/
+/*! simple check for file existence
+
+    \return 1 on existence, 0 otherwise
+*//*--------------------------------------------------------------------*/
+int nifti_fileexists(const char* fname)
+{
+   znzFile fp;
+   fp = znzopen( fname , "rb" , 1 ) ;
+   if( !znz_isnull(fp) )  { znzclose(fp);  return 1; }
+   return 0; /* fp is NULL */
+}
+
+/*----------------------------------------------------------------------*/
+/*! return whether the filename is valid
+ 
+    Note: uppercase extensions are now valid.    27 Apr 2009 [rickr]
+
+    The name is considered valid if the file basename has length greater than
+    zero, AND one of the valid nifti extensions is provided.
+    fname input          | return |
+    ===============================
+    "myimage"            |  0     |
+    "myimage.tif"        |  0     |
+    "myimage.tif.gz"     |  0     |
+    "myimage.nii"        |  1     |
+    ".nii"               |  0     |
+    ".myhiddenimage"     |  0     |
+    ".myhiddenimage.nii" |  1     |
+*//*--------------------------------------------------------------------*/
+int nifti_is_complete_filename(const char* fname)
+{
+   char * ext;
+
+   /* check input file(s) for sanity */
+   if( fname == NULL || *fname == '\0' ){
+      if ( g_opts.debug > 1 )
+         REprintf("-- empty filename in nifti_validfilename()\n");
+      return 0;
+   }
+
+   ext = nifti_find_file_extension(fname);
+   if ( ext == NULL ) { /*Invalid extension given */
+      if ( g_opts.debug > 0 )
+         REprintf("-- no nifti valid extension for filename '%s'\n", fname);
+       return 0;
+   }
+
+   if ( ext && ext == fname ) {   /* then no filename prefix */
+      if ( g_opts.debug > 0 )
+         REprintf("-- no prefix for filename '%s'\n", fname);
+      return 0;
+   }
+   return 1;
+}
+
+/*----------------------------------------------------------------------*/
+/*! return whether the filename is valid
+ 
+    Allow uppercase extensions as valid.        27 Apr 2009 [rickr]
+    Any .gz extension case must match the base extension case.
+
+    The name is considered valid if its length is positive, excluding
+    any nifti filename extension.
+    fname input         |  return | result of nifti_makebasename
+    ====================================================================
+    "myimage"           |  1      | "myimage"
+    "myimage.tif"       |  1      | "myimage.tif"
+    "myimage.tif.gz"    |  1      | "myimage.tif"
+    "myimage.nii"       |  1      | "myimage"
+    ".nii"              |  0      | <ERROR - basename has zero length>
+    ".myhiddenimage"    |  1      | ".myhiddenimage"
+    ".myhiddenimage.nii |  1      | ".myhiddenimage"
+*//*--------------------------------------------------------------------*/
+int nifti_validfilename(const char* fname)
+{
+   char * ext;
+
+   /* check input file(s) for sanity */
+   if( fname == NULL || *fname == '\0' ){
+      if ( g_opts.debug > 1 )
+         REprintf("-- empty filename in nifti_validfilename()\n");
+      return 0;
+   }
+
+   ext = nifti_find_file_extension(fname);
+
+   if ( ext && ext == fname ) {   /* then no filename prefix */
+      if ( g_opts.debug > 0 )
+         REprintf("-- no prefix for filename '%s'\n", fname);
+      return 0;
+   }
+
+   return 1;
+}
+
+/*----------------------------------------------------------------------*/
+/*! check the end of the filename for a valid nifti extension
+
+    Valid extensions are currently .nii, .hdr, .img, .nia,
+    or any of them followed by .gz.  Note that '.' is part of
+    the extension.
+
+    Uppercase extensions are also valid, but not mixed case.
+
+    \return a pointer to the extension (within the filename), or NULL
+*//*--------------------------------------------------------------------*/
+char * nifti_find_file_extension( const char * name )
+{
+   char * ext, extcopy[8];
+   int    len;
+   char   extnii[8] = ".nii";   /* modifiable, for possible uppercase */
+   char   exthdr[8] = ".hdr";   /* (leave space for .gz) */
+   char   extimg[8] = ".img";
+   char   extnia[8] = ".nia";
+   char   extgz[4]  = ".gz";
+   char * elist[4]  = { NULL, NULL, NULL, NULL};
+
+   /* stupid compiler... */
+   elist[0] = extnii; elist[1] = exthdr; elist[2] = extimg; elist[3] = extnia;
+
+   if ( ! name ) return NULL;
+
+   len = (int)strlen(name);
+   if ( len < 4 ) return NULL;
+
+   ext = (char *)name + len - 4;
+
+   /* make manipulation copy, and possibly convert to lowercase */
+   strcpy(extcopy, ext);
+   if( g_opts.allow_upper_fext ) make_lowercase(extcopy);
+
+   /* if it look like a basic extension, fail or return it */
+   if( compare_strlist(extcopy, elist, 4) >= 0 ) {
+      if( is_mixedcase(ext) ) {
+         REprintf("** mixed case extension '%s' is not valid\n", ext);
+         return NULL;
+      }
+      else return ext;
+   }
+
+#ifdef HAVE_LIBZ
+   if ( len < 7 ) return NULL;
+
+   ext = (char *)name + len - 7;
+
+   /* make manipulation copy, and possibly convert to lowercase */
+   strcpy(extcopy, ext);
+   if( g_opts.allow_upper_fext ) make_lowercase(extcopy);
+
+   /* go after .gz extensions using the modifiable strings */
+   strcat(elist[0], extgz); strcat(elist[1], extgz); strcat(elist[2], extgz);
+
+   if( compare_strlist(extcopy, elist, 3) >= 0 ) {
+      if( is_mixedcase(ext) ) {
+         REprintf("** mixed case extension '%s' is not valid\n", ext);
+         return NULL;
+      }
+      else return ext;
+   }
+
+#endif
+
+   if( g_opts.debug > 1 )
+      REprintf("** find_file_ext: failed for name '%s'\n", name);
+
+   return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/*! return whether the filename ends in ".gz"
+*//*--------------------------------------------------------------------*/
+int nifti_is_gzfile(const char* fname)
+{
+  /* return true if the filename ends with .gz */
+  if (fname == NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  { /* just so len doesn't generate compile warning */
+     int len;
+     len = (int)strlen(fname);
+     if (len < 3) return 0;  /* so we don't search before the name */
+     if (fileext_compare(fname + strlen(fname) - 3,".gz")==0) { return 1; }
+  }
+#endif
+  return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/*! return whether the given library was compiled with HAVE_LIBZ set
+*//*--------------------------------------------------------------------*/
+int nifti_compiled_with_zlib(void)
+{
+#ifdef HAVE_LIBZ
+    return 1;
+#else
+    return 0;
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/*! duplicate the filename, while clearing any extension
+
+    This allocates memory for basename which should eventually be freed.
+*//*--------------------------------------------------------------------*/
+char * nifti_makebasename(const char* fname)
+{
+   char *basename, *ext;
+
+   basename=nifti_strdup(fname);
+
+   ext = nifti_find_file_extension(basename);
+   if ( ext ) *ext = '\0';  /* clear out extension */
+   
+   return basename;  /* in either case */
+}
+
+/*----------------------------------------------------------------------*/
+/*! set nifti's global debug level, for status reporting
+
+    - 0    : quiet, nothing is printed to the terminal, but errors
+    - 1    : normal execution (the default)
+    - 2, 3 : more details
+*//*--------------------------------------------------------------------*/
+void nifti_set_debug_level( int level )
+{
+    g_opts.debug = level;
+}
+
+/*----------------------------------------------------------------------*/
+/*! set nifti's global skip_blank_ext flag            5 Sep 2006 [rickr]
+
+    explicitly set to 0 or 1
+*//*--------------------------------------------------------------------*/
+void nifti_set_skip_blank_ext( int skip )
+{
+    g_opts.skip_blank_ext = skip ? 1 : 0;
+}
+
+/*----------------------------------------------------------------------*/
+/*! set nifti's global allow_upper_fext flag         28 Apr 2009 [rickr]
+
+    explicitly set to 0 or 1
+*//*--------------------------------------------------------------------*/
+void nifti_set_allow_upper_fext( int allow )
+{
+    g_opts.allow_upper_fext = allow ? 1 : 0;
+}
+
+/*----------------------------------------------------------------------*/
+/*! check current directory for existing header file
+
+    \return filename of header on success and NULL if no appropriate file
+            could be found 
+
+    If fname has an uppercase extension, check for uppercase files.
+
+    NB: it allocates memory for hdrname which should be freed
+        when no longer required
+*//*-------------------------------------------------------------------*/
+char * nifti_findhdrname(const char* fname)
+{
+   char *basename, *hdrname, *ext;
+   char  elist[2][5] = { ".hdr", ".nii" };
+   char  extzip[4]   = ".gz";
+   int   efirst = 1;    /* init to .nii extension */
+   int   eisupper = 0;  /* init to lowercase extensions */
+
+   /**- check input file(s) for sanity */
+   if( !nifti_validfilename(fname) ) return NULL;
+
+   basename = nifti_makebasename(fname);
+   if( !basename ) return NULL;   /* only on string alloc failure */
+
+   /**- return filename if it has a valid extension and exists
+         (except if it is an .img file (and maybe .gz)) */
+   ext = nifti_find_file_extension(fname);
+
+   if( ext ) eisupper = is_uppercase(ext);  /* do we look for uppercase? */
+   
+   /* if the file exists and is a valid header name (not .img), return it */
+   if ( ext && nifti_fileexists(fname) ) { 
+     /* allow for uppercase extension */
+     if ( fileext_n_compare(ext,".img",4) != 0 ){
+        hdrname = nifti_strdup(fname); 
+        free(basename);
+        return hdrname; 
+     } else
+        efirst = 0;     /* note for below */
+   }
+
+   /* So the requested name is a basename, contains .img, or does not exist. */
+   /* In any case, use basename. */
+
+   /**- if .img, look for .hdr, .hdr.gz, .nii, .nii.gz, in that order */
+   /**- else,    look for .nii, .nii.gz, .hdr, .hdr.gz, in that order */
+
+   /* if we get more extension choices, this could be a loop */
+
+   /* note: efirst is 0 in the case of ".img" */
+
+   /* if the user passed an uppercase entension (.IMG), search for uppercase */
+   if( eisupper ) {
+      make_uppercase(elist[0]);
+      make_uppercase(elist[1]);
+      make_uppercase(extzip);
+   }
+
+   hdrname = (char *)calloc(sizeof(char),strlen(basename)+8);
+   if( !hdrname ){
+      REprintf("** nifti_findhdrname: failed to alloc hdrname\n");
+      free(basename);
+      return NULL;
+   }
+
+   strcpy(hdrname,basename);
+   strcat(hdrname,elist[efirst]);
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#ifdef HAVE_LIBZ
+   strcat(hdrname,extzip); 
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#endif
+
+   /* okay, try the other possibility */
+
+   efirst = 1 - efirst;
+
+   strcpy(hdrname,basename);
+   strcat(hdrname,elist[efirst]);
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#ifdef HAVE_LIBZ
+   strcat(hdrname,extzip); 
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#endif
+
+   /**- if nothing has been found, return NULL */
+   free(basename); 
+   free(hdrname); 
+   return NULL;
+}
+
+
+/*------------------------------------------------------------------------*/
+/*! check current directory for existing image file
+
+    \param fname filename to check for
+    \nifti_type  nifti_type for dataset - this determines whether to
+                 first check for ".nii" or ".img" (since both may exist)
+
+    \return filename of data/img file on success and NULL if no appropriate
+            file could be found
+
+    If fname has a valid, uppercase extension, apply all extensions as
+    uppercase.
+
+    NB: it allocates memory for the image filename, which should be freed
+        when no longer required
+*//*---------------------------------------------------------------------*/
+char * nifti_findimgname(const char* fname , int nifti_type)
+{
+   /* store all extensions as strings, in case we need to go uppercase */
+   char *basename, *imgname, elist[2][5] = { ".nii", ".img" };
+   char  extzip[4] = ".gz";
+   char  extnia[5] = ".nia";
+   char *ext;
+   int   first;  /* first extension to use */
+
+   /* check input file(s) for sanity */
+   if( !nifti_validfilename(fname) ) return NULL;
+
+   basename =  nifti_makebasename(fname);
+   imgname = (char *)calloc(sizeof(char),strlen(basename)+8);
+   if( !imgname ){
+      REprintf("** nifti_findimgname: failed to alloc imgname\n");
+      free(basename);
+      return NULL;
+   }
+
+   /* if we are looking for uppercase, apply the fact now */
+   ext = nifti_find_file_extension(fname);
+   if( ext && is_uppercase(ext) ) {
+      make_uppercase(elist[0]);
+      make_uppercase(elist[1]);
+      make_uppercase(extzip);
+      make_uppercase(extnia);
+   }
+
+   /* only valid extension for ASCII type is .nia, handle first */
+   if( nifti_type == NIFTI_FTYPE_ASCII ){
+      strcpy(imgname,basename);
+      strcat(imgname,extnia);
+      if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+
+   } else {
+
+      /**- test for .nii and .img (don't assume input type from image type) */
+      /**- if nifti_type = 1, check for .nii first, else .img first         */
+
+      /* if we get 3 or more extensions, can make a loop here... */
+
+      if (nifti_type == NIFTI_FTYPE_NIFTI1_1) first = 0; /* should match .nii */
+      else                                    first = 1; /* should match .img */
+
+      strcpy(imgname,basename);
+      strcat(imgname,elist[first]);
+      if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#ifdef HAVE_LIBZ  /* then also check for .gz */
+      strcat(imgname,extzip);
+      if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#endif
+
+      /* failed to find image file with expected extension, try the other */
+
+      strcpy(imgname,basename);
+      strcat(imgname,elist[1-first]);  /* can do this with only 2 choices */
+      if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#ifdef HAVE_LIBZ  /* then also check for .gz */
+      strcat(imgname,extzip);
+      if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#endif
+   }
+
+   /**- if nothing has been found, return NULL */
+   free(basename);
+   free(imgname);
+   return NULL;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! creates a filename for storing the header, based on nifti_type
+
+   \param   prefix      - this will be copied before the suffix is added
+   \param   nifti_type  - determines the extension, unless one is in prefix
+   \param   check       - check for existence (fail condition)
+   \param   comp        - add .gz for compressed name
+
+   Note that if prefix provides a file suffix, nifti_type is not used.
+  
+   NB: this allocates memory which should be freed
+
+   \sa nifti_set_filenames
+*//*-------------------------------------------------------------------*/
+char * nifti_makehdrname(const char * prefix, int nifti_type, int check,
+                         int comp)
+{
+   char * iname, * ext;
+   char   extnii[5] = ".nii";   /* modifiable, for possible uppercase */
+   char   exthdr[5] = ".hdr";
+   char   extimg[5] = ".img";
+   char   extnia[5] = ".nia";
+   char   extgz[5]  = ".gz";
+
+   if( !nifti_validfilename(prefix) ) return NULL;
+
+   /* add space for extension, optional ".gz", and null char */
+   iname = (char *)calloc(sizeof(char),strlen(prefix)+8);
+   if( !iname ){ REprintf("** small malloc failure!\n"); return NULL; }
+   strcpy(iname, prefix);
+
+   /* use any valid extension */
+   if( (ext = nifti_find_file_extension(iname)) != NULL ){
+      /* if uppercase, convert all extensions */
+      if( is_uppercase(ext) ) {
+         make_uppercase(extnii);
+         make_uppercase(exthdr);
+         make_uppercase(extimg);
+         make_uppercase(extnia);
+         make_uppercase(extgz);
+      }
+
+      if( strncmp(ext,extimg,4) == 0 )
+         memcpy(ext,exthdr,4);   /* then convert img name to hdr */
+   }
+   /* otherwise, make one up */
+   else if( nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcat(iname, extnii);
+   else if( nifti_type == NIFTI_FTYPE_ASCII )    strcat(iname, extnia);
+   else                                          strcat(iname, exthdr);
+
+#ifdef HAVE_LIBZ  /* if compression is requested, make sure of suffix */
+   if( comp && (!ext || !strstr(iname,extgz)) ) strcat(iname,extgz);
+#endif
+
+   /* check for existence failure */
+   if( check && nifti_fileexists(iname) ){
+      REprintf("** failure: header file '%s' already exists\n",iname);
+      free(iname);
+      return NULL;
+   }
+
+   if(g_opts.debug > 2) REprintf("+d made header filename '%s'\n", iname);
+
+   return iname;
+}
+   
+
+/*----------------------------------------------------------------------*/
+/*! creates a filename for storing the image, based on nifti_type
+
+   \param   prefix      - this will be copied before the suffix is added
+   \param   nifti_type  - determines the extension, unless provided by prefix
+   \param   check       - check for existence (fail condition)
+   \param   comp        - add .gz for compressed name
+  
+   Note that if prefix provides a file suffix, nifti_type is not used.
+  
+   NB: it allocates memory which should be freed
+
+   \sa nifti_set_filenames
+*//*-------------------------------------------------------------------*/
+char * nifti_makeimgname(const char * prefix, int nifti_type, int check,
+                         int comp)
+{
+   char * iname, * ext;
+   char   extnii[5] = ".nii";   /* modifiable, for possible uppercase */
+   char   exthdr[5] = ".hdr";
+   char   extimg[5] = ".img";
+   char   extnia[5] = ".nia";
+   char   extgz[5]  = ".gz";
+
+   if( !nifti_validfilename(prefix) ) return NULL;
+
+   /* add space for extension, optional ".gz", and null char */
+   iname = (char *)calloc(sizeof(char),strlen(prefix)+8);
+   if( !iname ){ REprintf("** small malloc failure!\n"); return NULL; }
+   strcpy(iname, prefix);
+
+   /* use any valid extension */
+   if( (ext = nifti_find_file_extension(iname)) != NULL ){
+      /* if uppercase, convert all extensions */
+      if( is_uppercase(ext) ) {
+         make_uppercase(extnii);
+         make_uppercase(exthdr);
+         make_uppercase(extimg);
+         make_uppercase(extnia);
+         make_uppercase(extgz);
+      }
+
+      if( strncmp(ext,exthdr,4) == 0 )
+         memcpy(ext,extimg,4);   /* then convert hdr name to img */
+   }
+   /* otherwise, make one up */
+   else if( nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcat(iname, extnii);
+   else if( nifti_type == NIFTI_FTYPE_ASCII )    strcat(iname, extnia);
+   else                                          strcat(iname, extimg);
+
+#ifdef HAVE_LIBZ  /* if compression is requested, make sure of suffix */
+   if( comp && (!ext || !strstr(iname,extgz)) ) strcat(iname,extgz);
+#endif
+
+   /* check for existence failure */
+   if( check && nifti_fileexists(iname) ){
+      REprintf("** failure: image file '%s' already exists\n",iname);
+      free(iname);
+      return NULL;
+   }
+
+   if( g_opts.debug > 2 ) REprintf("+d made image filename '%s'\n",iname);
+
+   return iname;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! create and set new filenames, based on prefix and image type
+
+   \param nim            pointer to nifti_image in which to set filenames
+   \param prefix         (required) prefix for output filenames
+   \param check          check for previous existence of filename
+                         (existence is an error condition)
+   \param set_byte_order flag to set nim->byteorder here
+                         (this is probably a logical place to do so)
+
+   \return 0 on successful update
+ 
+   \warning this will free() any existing names and create new ones
+
+   \sa nifti_makeimgname, nifti_makehdrname, nifti_type_and_names_match
+*//*--------------------------------------------------------------------*/
+int nifti_set_filenames( nifti_image * nim, const char * prefix, int check,
+                         int set_byte_order )
+{
+   int comp = nifti_is_gzfile(prefix);
+
+   if( !nim || !prefix ){
+      REprintf("** nifti_set_filenames, bad params %p, %p\n",
+              (void *)nim,prefix);
+      return -1;
+   }
+
+   if( g_opts.debug > 1 )
+      REprintf("+d modifying output filenames using prefix %s\n", prefix);
+
+   if( nim->fname ) free(nim->fname);
+   if( nim->iname ) free(nim->iname);
+   nim->fname = nifti_makehdrname(prefix, nim->nifti_type, check, comp);
+   nim->iname = nifti_makeimgname(prefix, nim->nifti_type, check, comp);
+   if( !nim->fname || !nim->iname ){
+      REprintf("nifti_set_filenames: failed to set prefix for %s.\n",prefix);
+      return -1;
+   }
+
+   if( set_byte_order ) nim->byteorder = nifti_short_order() ;
+
+   if( nifti_set_type_from_names(nim) < 0 )
+      return -1;
+
+   if( g_opts.debug > 2 )
+      REprintf("+d have new filenames %s and %s\n",nim->fname,nim->iname);
+
+   return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! check whether nifti_type matches fname and iname for the nifti_image
+
+    - if type 0 or 2, expect .hdr/.img pair
+    - if type 1, expect .nii (and names must match)
+
+    \param nim       given nifti_image
+    \param show_warn if set, print a warning message for any mis-match
+
+    \return
+        -   1 if the values seem to match
+        -   0 if there is a mis-match
+        -  -1 if there is not sufficient information to create file(s)
+
+    \sa NIFTI_FTYPE_* codes in nifti1_io.h
+    \sa nifti_set_type_from_names, is_valid_nifti_type
+*//*------------------------------------------------------------------------*/
+int nifti_type_and_names_match( nifti_image * nim, int show_warn )
+{
+   char func[] = "nifti_type_and_names_match";
+   char * ext_h, * ext_i;  /* header and image filename extensions */
+   int  errs = 0;          /* error counter */
+
+   /* sanity checks */
+   if( !nim ){
+      if( show_warn ) REprintf("** %s: missing nifti_image\n", func);
+      return -1;
+   }
+   if( !nim->fname ){
+      if( show_warn ) REprintf("** %s: missing header filename\n", func);
+      errs++;
+   }
+   if( !nim->iname ){
+      if( show_warn ) REprintf("** %s: missing image filename\n", func);
+      errs++;
+   }
+   if( !is_valid_nifti_type(nim->nifti_type) ){
+      if( show_warn )
+         REprintf("** %s: bad nifti_type %d\n", func, nim->nifti_type);
+      errs++;
+   }
+
+   if( errs ) return -1;   /* then do not proceed */
+
+   /* get pointers to extensions */
+   ext_h = nifti_find_file_extension( nim->fname );
+   ext_i = nifti_find_file_extension( nim->iname );
+
+   /* check for filename extensions */
+   if( !ext_h ){
+      if( show_warn )
+         REprintf("-d missing NIFTI extension in header filename, %s\n",
+                 nim->fname);
+      errs++;
+   }
+   if( !ext_i ){
+      if( show_warn )
+         REprintf("-d missing NIFTI extension in image filename, %s\n",
+                 nim->iname);
+      errs++;
+   }
+
+   if( errs ) return 0;   /* do not proceed, but this is just a mis-match */
+
+   /* general tests */
+   if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ){  /* .nii */
+      if( fileext_n_compare(ext_h,".nii",4) ) {
+         if( show_warn )
+            REprintf(
+            "-d NIFTI_FTYPE 1, but no .nii extension in header filename, %s\n",
+            nim->fname);
+         errs++;
+      }
+      if( fileext_n_compare(ext_i,".nii",4) ) {
+         if( show_warn )
+            REprintf(
+            "-d NIFTI_FTYPE 1, but no .nii extension in image filename, %s\n",
+            nim->iname);
+         errs++;
+      }
+      if( strcmp(nim->fname, nim->iname) != 0 ){
+         if( show_warn )
+            REprintf(
+            "-d NIFTI_FTYPE 1, but header and image filenames differ: %s, %s\n",
+            nim->fname, nim->iname);
+         errs++;
+      }
+   }
+   else if( (nim->nifti_type == NIFTI_FTYPE_NIFTI1_2) || /* .hdr/.img */
+            (nim->nifti_type == NIFTI_FTYPE_ANALYZE) )
+   {
+      if( fileext_n_compare(ext_h,".hdr",4) != 0 ){
+         if( show_warn )
+            REprintf("-d no '.hdr' extension, but NIFTI type is %d, %s\n",
+                    nim->nifti_type, nim->fname);
+         errs++;
+      }
+      if( fileext_n_compare(ext_i,".img",4) != 0 ){
+         if( show_warn )
+            REprintf("-d no '.img' extension, but NIFTI type is %d, %s\n",
+                    nim->nifti_type, nim->iname);
+         errs++;
+      }
+   }
+   /* ignore any other nifti_type */
+
+   return 1;
+}
+
+/* like strcmp, but also check against capitalization of known_ext
+ * (test as local string, with max length 7) */
+static int fileext_compare(const char * test_ext, const char * known_ext)
+{
+   char caps[8] = "";
+   int  c, cmp, len;
+
+   /* if equal, don't need to check case (store to avoid multiple calls) */
+   cmp = strcmp(test_ext, known_ext);
+   if( cmp == 0 ) return cmp;
+
+   /* if anything odd, use default */
+   if( !test_ext || !known_ext ) return cmp;
+
+   len = strlen(known_ext);
+   if( len > 7 ) return cmp;
+
+   /* if here, strings are different but need to check upper-case */
+
+   for(c = 0; c < len; c++ ) caps[c] = toupper(known_ext[c]);
+   caps[c] = '\0';
+
+   return strcmp(test_ext, caps);
+}
+
+/* like strncmp, but also check against capitalization of known_ext
+ * (test as local string, with max length 7) */
+static int fileext_n_compare(const char * test_ext,
+                             const char * known_ext, int maxlen)
+{
+   char caps[8] = "";
+   int  c, cmp, len;
+
+   /* if equal, don't need to check case (store to avoid multiple calls) */
+   cmp = strncmp(test_ext, known_ext, maxlen);
+   if( cmp == 0 ) return cmp;
+
+   /* if anything odd, use default */
+   if( !test_ext || !known_ext ) return cmp;
+
+   len = strlen(known_ext);
+   if( len > maxlen ) len = maxlen;     /* ignore anything past maxlen */
+   if( len > 7 ) return cmp;
+
+   /* if here, strings are different but need to check upper-case */
+
+   for(c = 0; c < len; c++ ) caps[c] = toupper(known_ext[c]);
+   caps[c] = '\0';
+
+   return strncmp(test_ext, caps, maxlen);
+}
+
+/* return 1 if there are uppercase but no lowercase */
+static int is_uppercase(const char * str)
+{
+   int c, hasupper = 0;
+
+   if( !str || !*str ) return 0;
+
+   for(c = 0; c < strlen(str); c++ ) {
+      if( islower(str[c]) ) return 0;
+      if( !hasupper && isupper(str[c]) ) hasupper = 1;
+   }
+
+   return hasupper;
+}
+
+/* return 1 if there are both uppercase and lowercase characters */
+static int is_mixedcase(const char * str)
+{
+   int c, hasupper = 0, haslower = 0;
+
+   if( !str || !*str ) return 0;
+
+   for(c = 0; c < strlen(str); c++ ) {
+      if( !haslower && islower(str[c]) ) haslower = 1;
+      if( !hasupper && isupper(str[c]) ) hasupper = 1;
+
+      if( haslower && hasupper ) return 1;
+   }
+
+   return 0;
+}
+
+/* convert any lowercase chars to uppercase */
+static int make_uppercase(char * str)
+{
+   int c;
+
+   if( !str || !*str ) return 0;
+
+   for(c = 0; c < strlen(str); c++ )
+      if( islower(str[c]) ) str[c] = toupper(str[c]);
+
+   return 0;
+}
+
+/* convert any uppercase chars to lowercase */
+static int make_lowercase(char * str)
+{
+   int c;
+
+   if( !str || !*str ) return 0;
+
+   for(c = 0; c < strlen(str); c++ )
+      if( isupper(str[c]) ) str[c] = tolower(str[c]);
+
+   return 0;
+}
+
+/* run strcmp against of list of strings
+ * return index of equality, if found
+ * else return -1 */
+static int compare_strlist(const char * str, char ** strlist, int len)
+{
+   int c;
+   if( len <= 0 || !str || !strlist ) return -1;
+   for( c = 0; c < len; c++ )
+      if( strlist[c] && !strcmp(str, strlist[c]) ) return c;
+   return -1;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! check whether the given type is on the "approved" list
+
+    The code is valid if it is non-negative, and does not exceed
+    NIFTI_MAX_FTYPE.
+
+    \return 1 if nifti_type is valid, 0 otherwise
+    \sa NIFTI_FTYPE_* codes in nifti1_io.h
+*//*------------------------------------------------------------------------*/
+int is_valid_nifti_type( int nifti_type )
+{
+   if( nifti_type >= NIFTI_FTYPE_ANALYZE &&   /* smallest type, 0 */
+       nifti_type <= NIFTI_MAX_FTYPE )
+      return 1;
+   return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! check whether the given type is on the "approved" list
+
+    The type is explicitly checked against the NIFTI_TYPE_* list
+    in nifti1.h.
+
+    \return 1 if dtype is valid, 0 otherwise
+    \sa NIFTI_TYPE_* codes in nifti1.h
+*//*------------------------------------------------------------------------*/
+int nifti_is_valid_datatype( int dtype )
+{
+   if( dtype == NIFTI_TYPE_UINT8        ||
+       dtype == NIFTI_TYPE_INT16        ||
+       dtype == NIFTI_TYPE_INT32        ||
+       dtype == NIFTI_TYPE_FLOAT32      ||
+       dtype == NIFTI_TYPE_COMPLEX64    ||
+       dtype == NIFTI_TYPE_FLOAT64      ||
+       dtype == NIFTI_TYPE_RGB24        ||
+       dtype == NIFTI_TYPE_RGBA32       ||
+       dtype == NIFTI_TYPE_INT8         ||
+       dtype == NIFTI_TYPE_UINT16       ||
+       dtype == NIFTI_TYPE_UINT32       ||
+       dtype == NIFTI_TYPE_INT64        ||
+       dtype == NIFTI_TYPE_UINT64       ||
+       dtype == NIFTI_TYPE_FLOAT128     ||
+       dtype == NIFTI_TYPE_COMPLEX128   ||
+       dtype == NIFTI_TYPE_COMPLEX256 ) return 1;
+   return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! set the nifti_type field based on fname and iname
+
+    Note that nifti_type is changed only when it does not match
+    the filenames.
+
+    \return 0 on success, -1 on error
+
+    \sa is_valid_nifti_type, nifti_type_and_names_match
+*//*------------------------------------------------------------------------*/
+int nifti_set_type_from_names( nifti_image * nim )
+{
+   /* error checking first */
+   if( !nim ){ REprintf("** NSTFN: no nifti_image\n");  return -1; }
+
+   if( !nim->fname || !nim->iname ){
+      REprintf("** NSTFN: missing filename(s) fname @ %p, iname @ %p\n",
+              nim->fname, nim->iname);
+      return -1;
+   }
+
+   if( ! nifti_validfilename      ( nim->fname ) ||
+       ! nifti_validfilename      ( nim->iname ) ||
+       ! nifti_find_file_extension( nim->fname ) ||
+       ! nifti_find_file_extension( nim->iname )
+     ) {
+      REprintf("** NSTFN: invalid filename(s) fname='%s', iname='%s'\n",
+              nim->fname, nim->iname);
+      return -1;
+   }
+
+   if( g_opts.debug > 2 )
+      REprintf("-d verify nifti_type from filenames: %d",nim->nifti_type);
+
+   /* type should be NIFTI_FTYPE_ASCII if extension is .nia */
+   if( (fileext_compare(nifti_find_file_extension(nim->fname),".nia")==0)){
+      nim->nifti_type = NIFTI_FTYPE_ASCII;
+   } else {
+      /* not too picky here, do what must be done, and then verify */
+      if( strcmp(nim->fname, nim->iname) == 0 )          /* one file, type 1 */
+         nim->nifti_type = NIFTI_FTYPE_NIFTI1_1;
+      else if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ) /* cannot be type 1 */
+         nim->nifti_type = NIFTI_FTYPE_NIFTI1_2;
+   }
+
+   if( g_opts.debug > 2 ) REprintf(" -> %d\n",nim->nifti_type);
+
+   if( g_opts.debug > 1 )  /* warn user about anything strange */
+      nifti_type_and_names_match(nim, 1);
+
+   if( is_valid_nifti_type(nim->nifti_type) ) return 0;  /* success! */
+
+   REprintf("** NSTFN: bad nifti_type %d, for '%s' and '%s'\n",
+           nim->nifti_type, nim->fname, nim->iname);
+
+   return -1;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! Determine if this is a NIFTI-formatted file.
+
+   <pre>
+   \return  0 if file looks like ANALYZE 7.5 [checks sizeof_hdr field == 348]
+            1 if file marked as NIFTI (header+data in 1 file)
+            2 if file marked as NIFTI (header+data in 2 files)
+           -1 if it can't tell, file doesn't exist, etc.
+   </pre>
+*//*------------------------------------------------------------------------*/
+int is_nifti_file( const char *hname )
+{
+   struct nifti_1_header nhdr ;
+   znzFile fp ;
+   int ii ;
+   char *tmpname;
+
+   /* bad input name? */
+
+   if( !nifti_validfilename(hname) ) return -1 ;
+
+   /* open file */
+
+   tmpname = nifti_findhdrname(hname);
+   if( tmpname == NULL ){
+      if( g_opts.debug > 0 )
+         REprintf("** no header file found for '%s'\n",hname);
+      return -1;
+   }
+   fp = znzopen( tmpname , "rb" , nifti_is_gzfile(tmpname) ) ;
+   free(tmpname);
+   if (znz_isnull(fp))                      return -1 ;  /* bad open? */
+
+   /* read header, close file */
+
+   ii = (int)znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ;
+   znzclose( fp ) ;
+   if( ii < (int) sizeof(nhdr) )               return -1 ;  /* bad read? */
+
+   /* check for NIFTI-ness */
+
+   if( NIFTI_VERSION(nhdr) != 0 ){
+     return ( NIFTI_ONEFILE(nhdr) ) ? 1 : 2 ;
+   }
+
+   /* check for ANALYZE-ness (sizeof_hdr field == 348) */
+
+   ii = nhdr.sizeof_hdr ;
+   if( ii == (int)sizeof(nhdr) ) return 0 ;  /* matches */
+
+   /* try byte-swapping header */
+
+   swap_4(ii) ;
+   if( ii == (int)sizeof(nhdr) ) return 0 ;  /* matches */
+
+   return -1 ;                          /* not good */
+}
+
+static int print_hex_vals( const char * data, int nbytes)
+{
+   int c;
+
+   if ( !data || nbytes < 1 ) return -1;
+
+   Rprintf("0x");
+   for ( c = 0; c < nbytes; c++ )
+      Rprintf(" %x", data[c]);
+
+   return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/*! display the contents of the nifti_1_header (send to stdout)
+
+   \param info if non-NULL, print this character string
+   \param hp   pointer to nifti_1_header
+*//*--------------------------------------------------------------------*/
+int disp_nifti_1_header( const char * info, const nifti_1_header * hp )
+{
+   int c;
+
+   Rprintf( "-------------------------------------------------------\n");
+   if ( info )  Rprintf( info );
+   if ( !hp  ){ Rprintf(" ** no nifti_1_header to display!\n"); return 1; }
+
+   Rprintf(" nifti_1_header :\n"
+           "    sizeof_hdr     = %d\n"
+           "    data_type[10]  = ", hp->sizeof_hdr);
+   print_hex_vals(hp->data_type, 10);
+   Rprintf( "\n"
+           "    db_name[18]    = ");
+   print_hex_vals(hp->db_name, 18);
+   Rprintf( "\n"
+           "    extents        = %d\n"
+           "    session_error  = %d\n"
+           "    regular        = 0x%x\n"
+           "    dim_info       = 0x%x\n",
+      hp->extents, hp->session_error, hp->regular, hp->dim_info );
+   Rprintf( "    dim[8]         =");
+   for ( c = 0; c < 8; c++ ) Rprintf(" %d", hp->dim[c]);
+   Rprintf( "\n"
+           "    intent_p1      = %f\n"
+           "    intent_p2      = %f\n"
+           "    intent_p3      = %f\n"
+           "    intent_code    = %d\n"
+           "    datatype       = %d\n"
+           "    bitpix         = %d\n"
+           "    slice_start    = %d\n"
+           "    pixdim[8]      =",
+           hp->intent_p1, hp->intent_p2, hp->intent_p3, hp->intent_code,
+           hp->datatype, hp->bitpix, hp->slice_start);
+   /* break pixdim over 2 lines */
+   for ( c = 0; c < 4; c++ ) Rprintf(" %f", hp->pixdim[c]);
+   Rprintf( "\n                    ");
+   for ( c = 4; c < 8; c++ ) Rprintf(" %f", hp->pixdim[c]);
+   Rprintf( "\n"
+           "    vox_offset     = %f\n"
+           "    scl_slope      = %f\n"
+           "    scl_inter      = %f\n"
+           "    slice_end      = %d\n"
+           "    slice_code     = %d\n"
+           "    xyzt_units     = 0x%x\n"
+           "    cal_max        = %f\n"
+           "    cal_min        = %f\n"
+           "    slice_duration = %f\n"
+           "    toffset        = %f\n"
+           "    glmax          = %d\n"
+           "    glmin          = %d\n",
+           hp->vox_offset, hp->scl_slope, hp->scl_inter, hp->slice_end,
+           hp->slice_code, hp->xyzt_units, hp->cal_max, hp->cal_min,
+           hp->slice_duration, hp->toffset, hp->glmax, hp->glmin);
+   Rprintf(
+           "    descrip        = '%.80s'\n"
+           "    aux_file       = '%.24s'\n"
+           "    qform_code     = %d\n"
+           "    sform_code     = %d\n"
+           "    quatern_b      = %f\n"
+           "    quatern_c      = %f\n"
+           "    quatern_d      = %f\n"
+           "    qoffset_x      = %f\n"
+           "    qoffset_y      = %f\n"
+           "    qoffset_z      = %f\n"
+           "    srow_x[4]      = %f, %f, %f, %f\n"
+           "    srow_y[4]      = %f, %f, %f, %f\n"
+           "    srow_z[4]      = %f, %f, %f, %f\n"
+           "    intent_name    = '%-.16s'\n"
+           "    magic          = '%-.4s'\n",
+           hp->descrip, hp->aux_file, hp->qform_code, hp->sform_code,
+           hp->quatern_b, hp->quatern_c, hp->quatern_d,
+           hp->qoffset_x, hp->qoffset_y, hp->qoffset_z,
+           hp->srow_x[0], hp->srow_x[1], hp->srow_x[2], hp->srow_x[3],
+           hp->srow_y[0], hp->srow_y[1], hp->srow_y[2], hp->srow_y[3],
+           hp->srow_z[0], hp->srow_z[1], hp->srow_z[2], hp->srow_z[3],
+           hp->intent_name, hp->magic);
+   Rprintf( "-------------------------------------------------------\n");
+   /*fflush(stdout);*/
+
+   return 0;
+}
+
+
+#undef  ERREX
+#define ERREX(msg)                                           \
+ do{ REprintf("** ERROR: nifti_convert_nhdr2nim: %s\n", (msg) ) ;  \
+     return NULL ; } while(0)
+
+/*----------------------------------------------------------------------*/
+/*! convert a nifti_1_header into a nift1_image
+  
+   \return an allocated nifti_image, or NULL on failure
+*//*--------------------------------------------------------------------*/
+nifti_image* nifti_convert_nhdr2nim(struct nifti_1_header nhdr,
+                                    const char * fname)
+{
+   int   ii , doswap , ioff ;
+   int   is_nifti , is_onefile ;
+   nifti_image *nim;
+
+   nim = (nifti_image *)calloc( 1 , sizeof(nifti_image) ) ;
+   if( !nim ) ERREX("failed to allocate nifti image");
+
+   /* be explicit with pointers */
+   nim->fname = NULL;
+   nim->iname = NULL;
+   nim->data = NULL;
+
+   /**- check if we must swap bytes */
+  
+   doswap = need_nhdr_swap(nhdr.dim[0], nhdr.sizeof_hdr); /* swap data flag */
+
+   if( doswap < 0 ){
+      if( doswap == -1 ) ERREX("bad dim[0]") ;
+      ERREX("bad sizeof_hdr") ;  /* else */
+   }
+
+   /**- determine if this is a NIFTI-1 compliant header */
+
+   is_nifti = NIFTI_VERSION(nhdr) ;
+   /*
+    * before swapping header, record the Analyze75 orient code
+    */
+   if(!is_nifti)
+     {
+     /**- in analyze75, the orient code is at the same address as
+      *   qform_code, but it's just one byte
+      *   the qform_code will be zero, at which point you can check
+      *   analyze75_orient if you care to.
+      */
+     unsigned char c = *((char *)(&nhdr.qform_code));
+     nim->analyze75_orient = (analyze_75_orient_code)c;
+     }
+   if( doswap ) {
+      if ( g_opts.debug > 3 ) disp_nifti_1_header("-d ni1 pre-swap: ", &nhdr);
+      swap_nifti_header( &nhdr , is_nifti ) ;
+   }
+
+   if ( g_opts.debug > 2 ) disp_nifti_1_header("-d nhdr2nim : ", &nhdr);
+
+   if( nhdr.datatype == DT_BINARY ||
+       nhdr.datatype == DT_UNKNOWN  )    ERREX("bad datatype") ;
+
+   if( nhdr.dim[1] <= 0 )                ERREX("bad dim[1]") ;
+
+   /* fix bad dim[] values in the defined dimension range */
+   for( ii=2 ; ii <= nhdr.dim[0] ; ii++ )
+     if( nhdr.dim[ii] <= 0 ) nhdr.dim[ii] = 1 ;
+
+   /* fix any remaining bad dim[] values, so garbage does not propagate */
+   /* (only values 0 or 1 seem rational, otherwise set to arbirary 1)   */
+   for( ii=nhdr.dim[0]+1 ; ii <= 7 ; ii++ )
+     if( nhdr.dim[ii] != 1 && nhdr.dim[ii] != 0) nhdr.dim[ii] = 1 ;
+
+#if 0  /* rely on dim[0], do not attempt to modify it   16 Nov 2005 [rickr] */
+
+   /**- get number of dimensions (ignoring dim[0] now) */
+   for( ii=7 ; ii >= 2 ; ii-- )            /* loop backwards until we  */
+     if( nhdr.dim[ii] > 1 ) break ;        /* find a dim bigger than 1 */
+   ndim = ii ;
+#endif
+
+   /**- set bad grid spacings to 1.0 */
+
+   for( ii=1 ; ii <= nhdr.dim[0] ; ii++ ){
+     if( nhdr.pixdim[ii] == 0.0         ||
+         !IS_GOOD_FLOAT(nhdr.pixdim[ii])  ) nhdr.pixdim[ii] = 1.0 ;
+   }
+
+  is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ;
+
+  if( is_nifti ) nim->nifti_type = (is_onefile) ? NIFTI_FTYPE_NIFTI1_1
+                                                : NIFTI_FTYPE_NIFTI1_2 ;
+  else           nim->nifti_type = NIFTI_FTYPE_ANALYZE ;
+  
+  ii = nifti_short_order() ;
+  if( doswap )   nim->byteorder = REVERSE_ORDER(ii) ;
+  else           nim->byteorder = ii ;
+  
+
+  /**- set dimensions of data array */
+  
+  nim->ndim = nim->dim[0] = nhdr.dim[0];
+  nim->nx   = nim->dim[1] = nhdr.dim[1];
+  nim->ny   = nim->dim[2] = nhdr.dim[2];
+  nim->nz   = nim->dim[3] = nhdr.dim[3];
+  nim->nt   = nim->dim[4] = nhdr.dim[4];
+  nim->nu   = nim->dim[5] = nhdr.dim[5];
+  nim->nv   = nim->dim[6] = nhdr.dim[6];
+  nim->nw   = nim->dim[7] = nhdr.dim[7];
+
+  for( ii=1, nim->nvox=1; ii <= nhdr.dim[0]; ii++ )
+     nim->nvox *= nhdr.dim[ii];
+  
+  /**- set the type of data in voxels and how many bytes per voxel */
+  
+  nim->datatype = nhdr.datatype ;
+  
+  nifti_datatype_sizes( nim->datatype , &(nim->nbyper) , &(nim->swapsize) ) ;
+  if( nim->nbyper == 0 ){ free(nim); ERREX("bad datatype"); }
+  
+  /**- set the grid spacings */
+  
+  nim->dx = nim->pixdim[1] = nhdr.pixdim[1] ;
+  nim->dy = nim->pixdim[2] = nhdr.pixdim[2] ;
+  nim->dz = nim->pixdim[3] = nhdr.pixdim[3] ;
+  nim->dt = nim->pixdim[4] = nhdr.pixdim[4] ;
+  nim->du = nim->pixdim[5] = nhdr.pixdim[5] ;
+  nim->dv = nim->pixdim[6] = nhdr.pixdim[6] ;
+  nim->dw = nim->pixdim[7] = nhdr.pixdim[7] ;
+  
+  /**- compute qto_xyz transformation from pixel indexes (i,j,k) to (x,y,z) */
+  
+  if( !is_nifti || nhdr.qform_code <= 0 ){
+    /**- if not nifti or qform_code <= 0, use grid spacing for qto_xyz */
+    
+    nim->qto_xyz.m[0][0] = nim->dx ;  /* grid spacings */
+    nim->qto_xyz.m[1][1] = nim->dy ;  /* along diagonal */
+    nim->qto_xyz.m[2][2] = nim->dz ;
+    
+    /* off diagonal is zero */
+    
+    nim->qto_xyz.m[0][1]=nim->qto_xyz.m[0][2]=nim->qto_xyz.m[0][3] = 0.0;
+    nim->qto_xyz.m[1][0]=nim->qto_xyz.m[1][2]=nim->qto_xyz.m[1][3] = 0.0;
+    nim->qto_xyz.m[2][0]=nim->qto_xyz.m[2][1]=nim->qto_xyz.m[2][3] = 0.0;
+    
+    /* last row is always [ 0 0 0 1 ] */
+    
+    nim->qto_xyz.m[3][0]=nim->qto_xyz.m[3][1]=nim->qto_xyz.m[3][2] = 0.0;
+    nim->qto_xyz.m[3][3]= 1.0 ;
+    
+    nim->qform_code = NIFTI_XFORM_UNKNOWN ;
+    
+    if( g_opts.debug > 1 ) REprintf("-d no qform provided\n");
+  } else {
+    /**- else NIFTI: use the quaternion-specified transformation */
+    
+    nim->quatern_b = FIXED_FLOAT( nhdr.quatern_b ) ;
+    nim->quatern_c = FIXED_FLOAT( nhdr.quatern_c ) ;
+    nim->quatern_d = FIXED_FLOAT( nhdr.quatern_d ) ;
+    
+    nim->qoffset_x = FIXED_FLOAT(nhdr.qoffset_x) ;
+    nim->qoffset_y = FIXED_FLOAT(nhdr.qoffset_y) ;
+    nim->qoffset_z = FIXED_FLOAT(nhdr.qoffset_z) ;
+    
+    nim->qfac = (nhdr.pixdim[0] < 0.0) ? -1.0 : 1.0 ;  /* left-handedness? */
+    
+    nim->qto_xyz = nifti_quatern_to_mat44(
+                      nim->quatern_b, nim->quatern_c, nim->quatern_d,
+                      nim->qoffset_x, nim->qoffset_y, nim->qoffset_z,
+                      nim->dx       , nim->dy       , nim->dz       ,
+                      nim->qfac                                      ) ;
+
+    nim->qform_code = nhdr.qform_code ;
+
+    if( g_opts.debug > 1 )
+       nifti_disp_matrix_orient("-d qform orientations:\n", nim->qto_xyz);
+  }
+  
+  /**- load inverse transformation (x,y,z) -> (i,j,k) */
+  
+  nim->qto_ijk = nifti_mat44_inverse( nim->qto_xyz ) ;
+  
+  /**- load sto_xyz affine transformation, if present */
+  
+  if( !is_nifti || nhdr.sform_code <= 0 ){
+    /**- if not nifti or sform_code <= 0, then no sto transformation */
+    
+    nim->sform_code = NIFTI_XFORM_UNKNOWN ;
+
+    if( g_opts.debug > 1 ) REprintf("-d no sform provided\n");
+    
+  } else {
+    /**- else set the sto transformation from srow_*[] */
+    
+    nim->sto_xyz.m[0][0] = nhdr.srow_x[0] ;
+    nim->sto_xyz.m[0][1] = nhdr.srow_x[1] ;
+    nim->sto_xyz.m[0][2] = nhdr.srow_x[2] ;
+    nim->sto_xyz.m[0][3] = nhdr.srow_x[3] ;
+    
+    nim->sto_xyz.m[1][0] = nhdr.srow_y[0] ;
+    nim->sto_xyz.m[1][1] = nhdr.srow_y[1] ;
+    nim->sto_xyz.m[1][2] = nhdr.srow_y[2] ;
+    nim->sto_xyz.m[1][3] = nhdr.srow_y[3] ;
+    
+    nim->sto_xyz.m[2][0] = nhdr.srow_z[0] ;
+    nim->sto_xyz.m[2][1] = nhdr.srow_z[1] ;
+    nim->sto_xyz.m[2][2] = nhdr.srow_z[2] ;
+    nim->sto_xyz.m[2][3] = nhdr.srow_z[3] ;
+    
+    /* last row is always [ 0 0 0 1 ] */
+    
+    nim->sto_xyz.m[3][0]=nim->sto_xyz.m[3][1]=nim->sto_xyz.m[3][2] = 0.0;
+    nim->sto_xyz.m[3][3]= 1.0 ;
+    
+    nim->sto_ijk = nifti_mat44_inverse( nim->sto_xyz ) ;
+    
+    nim->sform_code = nhdr.sform_code ;
+
+    if( g_opts.debug > 1 )
+       nifti_disp_matrix_orient("-d sform orientations:\n", nim->sto_xyz);
+  }
+  
+  /**- set miscellaneous NIFTI stuff */
+  
+  if( is_nifti ){
+    nim->scl_slope   = FIXED_FLOAT( nhdr.scl_slope ) ;
+    nim->scl_inter   = FIXED_FLOAT( nhdr.scl_inter ) ;
+    
+    nim->intent_code = nhdr.intent_code ;
+    
+    nim->intent_p1 = FIXED_FLOAT( nhdr.intent_p1 ) ;
+    nim->intent_p2 = FIXED_FLOAT( nhdr.intent_p2 ) ;
+    nim->intent_p3 = FIXED_FLOAT( nhdr.intent_p3 ) ;
+    
+    nim->toffset   = FIXED_FLOAT( nhdr.toffset ) ;
+    
+    memcpy(nim->intent_name,nhdr.intent_name,15); nim->intent_name[15] = '\0';
+    
+    nim->xyz_units  = XYZT_TO_SPACE(nhdr.xyzt_units) ;
+    nim->time_units = XYZT_TO_TIME (nhdr.xyzt_units) ;
+    
+    nim->freq_dim  = DIM_INFO_TO_FREQ_DIM ( nhdr.dim_info ) ;
+    nim->phase_dim = DIM_INFO_TO_PHASE_DIM( nhdr.dim_info ) ;
+    nim->slice_dim = DIM_INFO_TO_SLICE_DIM( nhdr.dim_info ) ;
+    
+    nim->slice_code     = nhdr.slice_code  ;
+    nim->slice_start    = nhdr.slice_start ;
+    nim->slice_end      = nhdr.slice_end   ;
+    nim->slice_duration = FIXED_FLOAT(nhdr.slice_duration) ;
+  }
+  
+  /**- set Miscellaneous ANALYZE stuff */
+  
+  nim->cal_min = FIXED_FLOAT(nhdr.cal_min) ;
+  nim->cal_max = FIXED_FLOAT(nhdr.cal_max) ;
+  
+  memcpy(nim->descrip ,nhdr.descrip ,79) ; nim->descrip [79] = '\0' ;
+  memcpy(nim->aux_file,nhdr.aux_file,23) ; nim->aux_file[23] = '\0' ;
+  
+   /**- set ioff from vox_offset (but at least sizeof(header)) */
+
+   is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ;
+
+   if( is_onefile ){
+     ioff = (int)nhdr.vox_offset ;
+     if( ioff < (int) sizeof(nhdr) ) ioff = (int) sizeof(nhdr) ;
+   } else {
+     ioff = (int)nhdr.vox_offset ;
+   }
+   nim->iname_offset = ioff ;
+
+
+   /**- deal with file names if set */
+   if (fname!=NULL) {
+       nifti_set_filenames(nim,fname,0,0);
+       if (nim->iname==NULL)  { ERREX("bad filename"); }
+   } else { 
+     nim->fname = NULL;  
+     nim->iname = NULL; 
+   }
+
+   /* clear extension fields */
+   nim->num_ext = 0;
+   nim->ext_list = NULL;
+
+   return nim;
+}
+
+#undef  ERREX
+#define ERREX(msg)                                           \
+ do{ REprintf("** ERROR: nifti_image_open(%s): %s\n",  \
+             (hname != NULL) ? hname : "(null)" , (msg) ) ;  \
+     return fptr ; } while(0)
+
+/***************************************************************
+ * nifti_image_open
+ ***************************************************************/
+/*! znzFile nifti_image_open( char *hname, char *opts , nifti_image **nim)
+    \brief Read in NIFTI-1 or ANALYZE-7.5 file (pair) header information into a nifti_image struct.
+
+    - The image data is not read from disk (it may be read later using
+        nifti_image_load(), for example).
+    - The image data will be stored in whatever data format the
+        input data is; no scaling will be applied.
+    - DT_BINARY data is not supported.
+    - nifti_image_free() can be used to delete the returned struct,
+        when you are done with it.
+
+    \param hname filename of dataset .hdr or .nii file
+    \param opts  options string for opening the header file
+    \param nim   pointer to pointer to nifti_image struct
+                 (this routine allocates the nifti_image struct)
+    \return file pointer (gzippable) to the file with the image data,
+                 ready for reading.
+        <br>NULL if something fails badly.
+    \sa nifti_image_load, nifti_image_free
+ */
+znzFile nifti_image_open(const char * hname, char * opts, nifti_image ** nim)
+{
+  znzFile fptr=NULL;
+  /* open the hdr and reading it in, but do not load the data  */
+  *nim = nifti_image_read(hname,0);
+  /* open the image file, ready for reading (compressed works for all reads) */
+  if( ((*nim) == NULL)      || ((*nim)->iname == NULL) ||
+      ((*nim)->nbyper <= 0) || ((*nim)->nvox <= 0)       )
+     ERREX("bad header info") ;
+                                                                                
+  /* open image data file */
+  fptr = znzopen( (*nim)->iname, opts, nifti_is_gzfile((*nim)->iname) );
+  if( znz_isnull(fptr) ) ERREX("Can't open data file") ;
+                                                                                
+  return fptr;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! return an allocated and filled nifti_1_header struct
+
+    Read the binary header from disk, and swap bytes if necessary.
+
+    \return an allocated nifti_1_header struct, or NULL on failure
+
+    \param hname   name of file containing header
+    \param swapped if not NULL, return whether header bytes were swapped
+    \param check   flag to check for invalid nifti_1_header
+
+    \warning ASCII header type is not supported
+
+    \sa nifti_image_read, nifti_image_free, nifti_image_read_bricks
+*//*--------------------------------------------------------------------*/
+nifti_1_header * nifti_read_header(const char * hname, int * swapped, int check)
+{
+   nifti_1_header   nhdr, * hptr;
+   znzFile          fp;
+   int              bytes, lswap;
+   char           * hfile;
+   char             fname[] = { "nifti_read_header" };
+   
+   /* determine file name to use for header */
+   hfile = nifti_findhdrname(hname);
+   if( hfile == NULL ){
+      if( g_opts.debug > 0 )
+         LNI_FERR(fname,"failed to find header file for", hname);
+      return NULL;
+   } else if( g_opts.debug > 1 )
+      REprintf("-d %s: found header filename '%s'\n",fname,hfile);
+
+   fp = znzopen( hfile, "rb", nifti_is_gzfile(hfile) );
+   if( znz_isnull(fp) ){
+      if( g_opts.debug > 0 ) LNI_FERR(fname,"failed to open header file",hfile);
+      free(hfile);
+      return NULL;
+   }
+
+   free(hfile);  /* done with filename */
+
+   if( has_ascii_header(fp) == 1 ){
+      znzclose( fp );
+      if( g_opts.debug > 0 )
+         LNI_FERR(fname,"ASCII header type not supported",hname);
+      return NULL;
+   }
+
+   /* read the binary header */ 
+   bytes = (int)znzread( &nhdr, 1, sizeof(nhdr), fp );
+   znzclose( fp );                      /* we are done with the file now */
+
+   if( bytes < (int)sizeof(nhdr) ){
+      if( g_opts.debug > 0 ){
+         LNI_FERR(fname,"bad binary header read for file", hname);
+         REprintf("  - read %d of %d bytes\n",bytes, (int)sizeof(nhdr));
+      }
+      return NULL;
+   }
+
+   /* now just decide on byte swapping */
+   lswap = need_nhdr_swap(nhdr.dim[0], nhdr.sizeof_hdr); /* swap data flag */
+   if( check && lswap < 0 ){
+      LNI_FERR(fname,"bad nifti_1_header for file", hname);
+      return NULL;
+   } else if ( lswap < 0 ) {
+      lswap = 0;  /* if swapping does not help, don't do it */
+      if(g_opts.debug > 1) REprintf("-- swap failure, none applied\n");
+   }
+
+   if( lswap ) {
+      if ( g_opts.debug > 3 ) disp_nifti_1_header("-d nhdr pre-swap: ", &nhdr);
+      swap_nifti_header( &nhdr , NIFTI_VERSION(nhdr) ) ;
+   }
+
+   if ( g_opts.debug > 2 ) disp_nifti_1_header("-d nhdr post-swap: ", &nhdr);
+
+   if ( check && ! nifti_hdr_looks_good(&nhdr) ){
+      LNI_FERR(fname,"nifti_1_header looks bad for file", hname);
+      return NULL;
+   }
+
+   /* all looks good, so allocate memory for and return the header */
+   hptr = (nifti_1_header *)malloc(sizeof(nifti_1_header));
+   if( ! hptr ){
+      REprintf("** nifti_read_hdr: failed to alloc nifti_1_header\n");
+      return NULL;
+   }
+
+   if( swapped ) *swapped = lswap;  /* only if they care <sniff!> */
+
+   memcpy(hptr, &nhdr, sizeof(nifti_1_header));
+
+   return hptr;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! decide if this nifti_1_header structure looks reasonable
+
+   Check dim[0], dim[1], sizeof_hdr, and datatype.
+   Check magic string for "n+1".
+   Maybe more tests will follow.
+
+   \return 1 if the header seems valid, 0 otherwise
+
+   \sa nifti_nim_is_valid, valid_nifti_extensions
+*//*--------------------------------------------------------------------*/
+int nifti_hdr_looks_good(const nifti_1_header * hdr)
+{
+   int is_nifti, c, errs = 0;
+
+   /* check dim[0] and sizeof_hdr */
+   if( need_nhdr_swap(hdr->dim[0], hdr->sizeof_hdr) < 0 ){
+      if( g_opts.debug > 0 )
+         REprintf("** bad nhdr fields: dim0, sizeof_hdr = %d, %d\n",
+                 hdr->dim[0], hdr->sizeof_hdr);
+      errs++;
+   }
+
+   /* check the valid dimension sizes (maybe dim[0] is bad) */
+   for( c = 1; c <= hdr->dim[0] && c <= 7; c++ )
+      if( hdr->dim[c] <= 0 ){
+         if( g_opts.debug > 0 )
+            REprintf("** bad nhdr field: dim[%d] = %d\n",c,hdr->dim[c]);
+         errs++;
+      }
+
+   is_nifti = NIFTI_VERSION(*hdr);      /* determine header type */
+
+   if( is_nifti ){      /* NIFTI */
+
+      if( ! nifti_datatype_is_valid(hdr->datatype, 1) ){
+         if( g_opts.debug > 0 )
+            REprintf("** bad NIFTI datatype in hdr, %d\n",hdr->datatype);
+         errs++;
+      }
+
+   } else {             /* ANALYZE 7.5 */
+
+      if( g_opts.debug > 1 )  /* maybe tell user it's an ANALYZE hdr */
+         REprintf(
+            "-- nhdr magic field implies ANALYZE: magic = '%.4s'\n",hdr->magic);
+
+      if( ! nifti_datatype_is_valid(hdr->datatype, 0) ){
+         if( g_opts.debug > 0 )
+           REprintf("** bad ANALYZE datatype in hdr, %d\n",hdr->datatype);
+         errs++;
+      }
+   }
+
+   if( errs ) return 0;  /* problems */
+
+   if( g_opts.debug > 2 ) REprintf("-d nifti header looks good\n");
+
+   return 1;   /* looks good */
+}
+
+
+/*----------------------------------------------------------------------
+ * check whether byte swapping is needed
+ * 
+ * dim[0] should be in [0,7], and sizeof_hdr should be accurate
+ *
+ * \returns  > 0 : needs swap
+ *             0 : does not need swap
+ *           < 0 : error condition
+ *----------------------------------------------------------------------*/
+static int need_nhdr_swap( short dim0, int hdrsize )
+{
+   short d0    = dim0;     /* so we won't have to swap them on the stack */
+   int   hsize = hdrsize;
+
+   if( d0 != 0 ){     /* then use it for the check */
+      if( d0 > 0 && d0 <= 7 ) return 0;
+
+      nifti_swap_2bytes(1, &d0);        /* swap? */
+      if( d0 > 0 && d0 <= 7 ) return 1;
+
+      if( g_opts.debug > 1 ){
+         REprintf("** NIFTI: bad swapped d0 = %d, unswapped = ", d0);
+         nifti_swap_2bytes(1, &d0);        /* swap? */
+         REprintf("%d\n", d0);
+      }
+
+      return -1;        /* bad, naughty d0 */
+   } 
+
+   /* dim[0] == 0 should not happen, but could, so try hdrsize */
+   if( hsize == sizeof(nifti_1_header) ) return 0;
+
+   nifti_swap_4bytes(1, &hsize);     /* swap? */
+   if( hsize == sizeof(nifti_1_header) ) return 1;
+
+   if( g_opts.debug > 1 ){
+      REprintf("** NIFTI: bad swapped hsize = %d, unswapped = ", hsize);
+      nifti_swap_4bytes(1, &hsize);        /* swap? */
+      REprintf("%d\n", hsize);
+   }
+
+   return -2;     /* bad, naughty hsize */
+}
+
+
+/* use macro LNI_FILE_ERROR instead of ERREX()
+#undef  ERREX
+#define ERREX(msg)                                           \
+ do{ fprintf(stderr,"** ERROR: nifti_image_read(%s): %s\n",  \
+             (hname != NULL) ? hname : "(null)" , (msg) ) ;  \
+     return NULL ; } while(0)
+*/
+
+
+/***************************************************************
+ * nifti_image_read
+ ***************************************************************/
+/*! \brief Read a nifti header and optionally the data, creating a nifti_image.
+
+        - The data buffer will be byteswapped if necessary.
+        - The data buffer will not be scaled.
+        - The data buffer is allocated with calloc().
+
+    \param hname filename of the nifti dataset
+    \param read_data Flag, true=read data blob, false=don't read blob.
+    \return A pointer to the nifti_image data structure.
+
+    \sa nifti_image_free, nifti_free_extensions, nifti_image_read_bricks
+*/
+nifti_image *nifti_image_read_NaN( const char *hname , int read_data , int rmNaN)
+{
+   struct nifti_1_header  nhdr ;
+   nifti_image           *nim ;
+   znzFile                fp ;
+   int                    rv, ii , filesize, remaining;
+   char                   fname[] = { "nifti_image_read_NaN" };
+   char                  *hfile=NULL;
+
+   if( g_opts.debug > 1 ){
+      REprintf("-d image_read from '%s', read_data = %d",hname,read_data);
+#ifdef HAVE_LIBZ
+      REprintf(", HAVE_LIBZ = 1\n");
+#else
+      REprintf(", HAVE_LIBZ = 0\n");
+#endif
+   }
+
+   /**- determine filename to use for header */
+   hfile = nifti_findhdrname(hname);
+   if( hfile == NULL ){
+      if(g_opts.debug > 0)
+         LNI_FERR(fname,"failed to find header file for", hname);
+      return NULL;  /* check return */
+   } else if( g_opts.debug > 1 )
+      REprintf("-d %s: found header filename '%s'\n",fname,hfile);
+
+   if( nifti_is_gzfile(hfile) ) filesize = -1;  /* unknown */
+   else                         filesize = nifti_get_filesize(hfile);
+
+   fp = znzopen(hfile, "rb", nifti_is_gzfile(hfile));
+   if( znz_isnull(fp) ){
+      if( g_opts.debug > 0 ) LNI_FERR(fname,"failed to open header file",hfile);
+      free(hfile);
+      return NULL;
+   }
+
+   rv = has_ascii_header( fp );
+   if( rv < 0 ){
+      if( g_opts.debug > 0 ) LNI_FERR(fname,"short header read",hfile);
+      znzclose( fp );
+      free(hfile);
+      return NULL;
+   }
+   else if ( rv == 1 )  /* process special file type */
+      return nifti_read_ascii_image( fp, hfile, filesize, read_data );
+
+   /* else, just process normally */
+
+   /**- read binary header */
+
+   ii = (int)znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ;       /* read the thing */
+
+   /* keep file open so we can check for exts. after nifti_convert_nhdr2nim() */
+
+   if( ii < (int) sizeof(nhdr) ){
+      if( g_opts.debug > 0 ){
+         LNI_FERR(fname,"bad binary header read for file", hfile);
+         REprintf("  - read %d of %d bytes\n",ii, (int)sizeof(nhdr));
+      }
+      znzclose(fp) ;
+      free(hfile);
+      return NULL;
+   }
+
+   /* create output image struct and set it up */
+
+   /**- convert all nhdr fields to nifti_image fields */
+   nim = nifti_convert_nhdr2nim(nhdr,hfile);
+
+   if( nim == NULL ){
+      znzclose( fp ) ;                                   /* close the file */
+      if( g_opts.debug > 0 )
+         LNI_FERR(fname,"cannot create nifti image from header",hfile);
+      free(hfile); /* had to save this for debug message */
+      return NULL;
+   }
+
+   if( g_opts.debug > 3 ){
+      REprintf("+d nifti_image_read(), have nifti image:\n");
+      if( g_opts.debug > 2 ) nifti_image_infodump(nim);
+   }
+
+   /**- check for extensions (any errors here means no extensions) */
+   if( NIFTI_ONEFILE(nhdr) ) remaining = nim->iname_offset - sizeof(nhdr);
+   else                      remaining = filesize - sizeof(nhdr);
+
+   (void)nifti_read_extensions(nim, fp, remaining);
+
+   znzclose( fp ) ;                                      /* close the file */
+   free(hfile);
+
+   /**- read the data if desired, then bug out */
+   if( read_data ){
+      if( nifti_image_load_NaN( nim , rmNaN) < 0 ){
+         nifti_image_free(nim);          /* take ball, go home. */
+         return NULL;
+      }
+   }
+   else nim->data = NULL ;
+
+   return nim ;
+}
+
+/***************************************************************
+ * nifti_image_read
+ ***************************************************************/
+/*! \brief Read a nifti header and optionally the data, creating a nifti_image.
+
+        - The data buffer will be byteswapped if necessary.
+        - The data buffer will not be scaled.
+        - The data buffer is allocated with calloc().
+
+    \param hname filename of the nifti dataset
+    \param read_data Flag, true=read data blob, false=don't read blob.
+    \return A pointer to the nifti_image data structure.
+
+    \sa nifti_image_free, nifti_free_extensions, nifti_image_read_bricks
+*/
+nifti_image *nifti_image_read( const char *hname , int read_data)
+{
+  return nifti_image_read_NaN( hname , read_data, 1);
+}
+
+/*----------------------------------------------------------------------
+ * has_ascii_header  - see if the NIFTI header is an ASCII format
+ *
+ * If the file starts with the ASCII string "<nifti_image", then
+ * process the dataset as a type-3 .nia file.
+ *
+ * return:  -1 on error, 1 if true, or 0 if false
+ *
+ * NOTE: this is NOT part of the NIFTI-1 standard
+ *----------------------------------------------------------------------*/
+static int has_ascii_header( znzFile fp )
+{
+   char  buf[16];
+   int   nread;
+
+   if( znz_isnull(fp) ) return 0;
+
+   nread = (int)znzread( buf, 1, 12, fp );
+   buf[12] = '\0';
+
+   if( nread < 12 ) return -1;
+
+   znzrewind(fp);  /* move back to the beginning, and check */
+
+   if( strcmp(buf, "<nifti_image") == 0 ) return 1;
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_read_ascii_image  - process as a type-3 .nia image file
+
+   return NULL on failure
+  
+   NOTE: this is NOT part of the NIFTI-1 standard
+*//*--------------------------------------------------------------------*/
+nifti_image * nifti_read_ascii_image(znzFile fp, char *fname, int flen,
+                                     int read_data)
+{
+   nifti_image * nim;
+   int           slen, txt_size, remain, rv = 0;
+   char        * sbuf, lfunc[25] = { "nifti_read_ascii_image" };
+
+   if( nifti_is_gzfile(fname) ){
+     LNI_FERR(lfunc,"compression not supported for file type NIFTI_FTYPE_ASCII",
+              fname);
+     free(fname);  znzclose(fp);  return NULL;
+   }
+   slen = flen;  /* slen will be our buffer length */
+
+   if( g_opts.debug > 1 )
+      REprintf("-d %s: have ASCII NIFTI file of size %d\n",fname,slen);
+
+   if( slen > 65530 ) slen = 65530 ;
+   sbuf = (char *)calloc(sizeof(char),slen+1) ;
+   if( !sbuf ){
+      REprintf("** %s: failed to alloc %d bytes for sbuf",lfunc,65530);
+      free(fname);  znzclose(fp);  return NULL;
+   }
+   znzread( sbuf , 1 , slen , fp ) ;
+   nim = nifti_image_from_ascii( sbuf, &txt_size ) ; free( sbuf ) ;
+   if( nim == NULL ){
+      LNI_FERR(lfunc,"failed nifti_image_from_ascii()",fname);
+      free(fname);  znzclose(fp);  return NULL;
+   }
+   nim->nifti_type = NIFTI_FTYPE_ASCII ;
+
+   /* compute remaining space for extensions */
+   remain = flen - txt_size - (int)nifti_get_volsize(nim);
+   if( remain > 4 ){
+      /* read extensions (reposition file pointer, first) */
+      znzseek(fp, txt_size, SEEK_SET);
+      (void) nifti_read_extensions(nim, fp, remain);
+   }
+
+   free(fname);
+   znzclose( fp ) ;
+
+   nim->iname_offset = -1 ;  /* check from the end of the file */
+
+   if( read_data ) rv = nifti_image_load( nim ) ;
+   else            nim->data = NULL ;
+
+   /* check for nifti_image_load() failure, maybe bail out */
+   if( read_data && rv != 0 ){
+      if( g_opts.debug > 1 )
+         REprintf("-d failed image_load, free nifti image struct\n");
+      free(nim);
+      return NULL;
+   }
+
+   return nim ;
+}
+
+
+/*----------------------------------------------------------------------
+ * Read the extensions into the nifti_image struct   08 Dec 2004 [rickr]
+ *
+ * This function is called just after the header struct is read in, and
+ * it is assumed the file pointer has not moved.  The value in remain
+ * is assumed to be accurate, reflecting the bytes of space for potential
+ * extensions.
+ *
+ * return the number of extensions read in, or < 0 on error
+ *----------------------------------------------------------------------*/
+static int nifti_read_extensions( nifti_image *nim, znzFile fp, int remain )
+{
+   nifti1_extender    extdr;      /* defines extension existence  */
+   nifti1_extension   extn;       /* single extension to process  */
+   nifti1_extension * Elist;      /* list of processed extensions */
+   int                posn, count;
+
+   if( !nim || znz_isnull(fp) ) {
+      if( g_opts.debug > 0 )
+         REprintf("** nifti_read_extensions: bad inputs (%p,%p)\n",
+                 (void *)nim, (void *)fp);
+      return -1;
+   }
+
+   posn = znztell(fp);
+ 
+   if( (posn != sizeof(nifti_1_header)) &&
+       (nim->nifti_type != NIFTI_FTYPE_ASCII) )
+      REprintf("** WARNING: posn not header size (%d, %d)\n",
+              posn, (int)sizeof(nifti_1_header));
+
+   if( g_opts.debug > 2 )
+      REprintf("-d nre: posn = %d, offset = %d, type = %d, remain = %d\n",
+              posn, nim->iname_offset, nim->nifti_type, remain);
+
+   if( remain < 16 ){
+      if( g_opts.debug > 2 ){
+         if( g_opts.skip_blank_ext )
+            REprintf("-d no extender in '%s' is okay, as "
+                           "skip_blank_ext is set\n",nim->fname);
+         else
+            REprintf("-d remain=%d, no space for extensions\n",remain);
+      }
+      return 0;
+   }
+
+   count = (int)znzread( extdr.extension, 1, 4, fp ); /* get extender */
+
+   if( count < 4 ){
+      if( g_opts.debug > 1 )
+         REprintf("-d file '%s' is too short for an extender\n",
+                 nim->fname);
+      return 0;
+   }
+
+   if( extdr.extension[0] != 1 ){
+      if( g_opts.debug > 2 )
+         REprintf("-d extender[0] (%d) shows no extensions for '%s'\n",
+                 extdr.extension[0], nim->fname);
+      return 0;
+   }
+
+   remain -= 4;
+   if( g_opts.debug > 2 )
+      REprintf("-d found valid 4-byte extender, remain = %d\n", remain);
+
+   /* so we expect extensions, but have no idea of how many there may be */
+
+   count = 0;
+   Elist = NULL;
+   while (nifti_read_next_extension(&extn, nim, remain, fp) > 0)
+   {
+      if( nifti_add_exten_to_list(&extn, &Elist, count+1) < 0 ){
+         if( g_opts.debug > 0 )
+            REprintf("** failed adding ext %d to list\n", count);
+         return -1;
+      }
+
+      /* we have a new extension */
+      if( g_opts.debug > 1 ){
+         REprintf("+d found extension #%d, code = 0x%x, size = %d\n",
+                 count, extn.ecode, extn.esize);
+         if( extn.ecode == NIFTI_ECODE_AFNI && g_opts.debug > 2 ) /* ~XML */
+            REprintf("   AFNI extension: %.*s\n",
+                    extn.esize-8,extn.edata);
+         else if( extn.ecode == NIFTI_ECODE_COMMENT && g_opts.debug > 2 )
+            REprintf("   COMMENT extension: %.*s\n",        /* TEXT */
+                    extn.esize-8,extn.edata);
+      }
+      remain -= extn.esize;
+      count++;
+   }
+
+   if( g_opts.debug > 2 ) REprintf("+d found %d extension(s)\n", count);
+
+   nim->num_ext = count;
+   nim->ext_list = Elist;
+
+   return count;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_add_extension - add an extension, with a copy of the data
+
+   Add an extension to the nim->ext_list array.
+   Fill this extension with a copy of the data, noting the
+       length and extension code.
+
+   \param nim    - nifti_image to add extension to
+   \param data   - raw extension data
+   \param length - length of raw extension data
+   \param ecode  - extension code
+
+   \sa extension codes NIFTI_ECODE_* in nifti1_io.h
+   \sa nifti_free_extensions, valid_nifti_extensions, nifti_copy_extensions
+
+   \return 0 on success, -1 on error (and free the entire list)
+*//*--------------------------------------------------------------------*/
+int nifti_add_extension(nifti_image *nim, const char * data, int len, int ecode)
+{
+   nifti1_extension ext;
+
+   /* error are printed in functions */
+   if( nifti_fill_extension(&ext, data, len, ecode) )                 return -1;
+   if( nifti_add_exten_to_list(&ext, &nim->ext_list, nim->num_ext+1)) return -1;
+
+   nim->num_ext++;  /* success, so increment */
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* nifti_add_exten_to_list     - add a new nifti1_extension to the list
+
+   We will append via "malloc, copy and free", because on an error,
+   the list will revert to the previous one (sorry realloc(), only
+   quality dolphins get to become part of St at rk!st brand tunafish).
+
+   return 0 on success, -1 on error (and free the entire list)
+*//*--------------------------------------------------------------------*/
+static int nifti_add_exten_to_list( nifti1_extension *  new_ext,
+                                    nifti1_extension ** list, int new_length )
+{
+   nifti1_extension * tmplist;
+  
+   tmplist = *list;
+   *list = (nifti1_extension *)malloc(new_length * sizeof(nifti1_extension));
+
+   /* check for failure first */
+   if( ! *list ){
+      REprintf("** failed to alloc %d extension structs (%d bytes)\n",
+              new_length, new_length*(int)sizeof(nifti1_extension));
+      if( !tmplist ) return -1;  /* no old list to lose */
+
+      *list = tmplist;  /* reset list to old one */
+      return -1;
+   }
+
+   /* if an old list exists, copy the pointers and free the list */
+   if( tmplist ){
+      memcpy(*list, tmplist, (new_length-1)*sizeof(nifti1_extension));
+      free(tmplist);
+   }
+
+   /* for some reason, I just don't like struct copy... */
+   (*list)[new_length-1].esize = new_ext->esize;
+   (*list)[new_length-1].ecode = new_ext->ecode;
+   (*list)[new_length-1].edata = new_ext->edata;
+
+   if( g_opts.debug > 2 )
+      REprintf("+d allocated and appended extension #%d to list\n",
+              new_length);
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* nifti_fill_extension  - given data and length, fill an extension struct
+
+   Allocate memory for data, copy data, set the size and code.
+
+   return 0 on success, -1 on error (and free the entire list)
+*//*--------------------------------------------------------------------*/
+static int nifti_fill_extension( nifti1_extension *ext, const char * data,
+                                int len, int ecode)
+{
+   int esize;
+
+   if( !ext || !data || len < 0 ){
+      REprintf("** fill_ext: bad params (%p,%p,%d)\n",
+              (void *)ext, data, len);
+      return -1;
+   } else if( ! nifti_is_valid_ecode(ecode) ){
+      REprintf("** fill_ext: invalid ecode %d\n", ecode);
+      return -1;
+   }
+
+   /* compute esize, first : len+8, and take ceiling up to a mult of 16 */
+   esize = len+8;
+   if( esize & 0xf ) esize = (esize + 0xf) & ~0xf;
+   ext->esize = esize;
+
+   /* allocate esize-8 (maybe more than len), using calloc for fill */
+   ext->edata = (char *)calloc(esize-8, sizeof(char));
+   if( !ext->edata ){
+      REprintf("** NFE: failed to alloc %d bytes for extension\n",len);
+      return -1;
+   }
+
+   memcpy(ext->edata, data, len);  /* copy the data, using len */
+   ext->ecode = ecode;             /* set the ecode */
+
+   if( g_opts.debug > 2 )
+      REprintf("+d alloc %d bytes for ext len %d, ecode %d, esize %d\n",
+              esize-8, len, ecode, esize);
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_read_next_extension  - read a single extension from the file
+ *
+ * return (>= 0 is okay):
+ *
+ *     success      : esize
+ *     no extension : 0
+ *     error        : -1
+ *----------------------------------------------------------------------*/
+static int nifti_read_next_extension( nifti1_extension * nex, nifti_image *nim,
+                                      int remain, znzFile fp )
+{
+   int swap = nim->byteorder != nifti_short_order();
+   int count, size, code;
+
+   /* first clear nex */
+   nex->esize = nex->ecode = 0;
+   nex->edata = NULL;
+
+   if( remain < 16 ){
+      if( g_opts.debug > 2 )
+         REprintf("-d only %d bytes remain, so no extension\n", remain);
+      return 0;
+   }
+
+   /* must start with 4-byte size and code */
+   count = (int)znzread( &size, 4, 1, fp );
+   if( count == 1 ) count += (int)znzread( &code, 4, 1, fp );
+
+   if( count != 2 ){
+      if( g_opts.debug > 2 )
+         REprintf("-d current extension read failed\n");
+      znzseek(fp, -4*count, SEEK_CUR); /* back up past any read */
+      return 0;                        /* no extension, no error condition */
+   }
+
+   if( swap ){
+      if( g_opts.debug > 2 )
+         REprintf("-d pre-swap exts: code %d, size %d\n", code, size);
+
+      nifti_swap_4bytes(1, &size);
+      nifti_swap_4bytes(1, &code);
+   }
+
+   if( g_opts.debug > 2 )
+      REprintf("-d potential extension: code %d, size %d\n", code, size);
+
+   if( !nifti_check_extension(nim, size, code, remain) ){
+      if( znzseek(fp, -8, SEEK_CUR) < 0 ){      /* back up past any read */
+         REprintf("** failure to back out of extension read!\n");
+         return -1;
+      }
+      return 0;
+   }
+
+   /* now get the actual data */
+   nex->esize = size;
+   nex->ecode = code;
+
+   size -= 8;  /* subtract space for size and code in extension */
+   nex->edata = (char *)malloc(size * sizeof(char));
+   if( !nex->edata ){
+      REprintf("** failed to allocate %d bytes for extension\n",size);
+      return -1;
+   }
+
+   count = (int)znzread(nex->edata, 1, size, fp);
+   if( count < size ){
+      if( g_opts.debug > 0 )
+         REprintf("-d read only %d (of %d) bytes for extension\n",
+                 count, size);
+      free(nex->edata);
+      nex->edata = NULL;
+      return -1;
+   }
+
+   /* success! */
+   if( g_opts.debug > 2 )
+      REprintf("+d successfully read extension, code %d, size %d\n",
+              nex->ecode, nex->esize);
+
+   return nex->esize;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! for each extension, check code, size and data pointer
+*//*--------------------------------------------------------------------*/
+int valid_nifti_extensions(const nifti_image * nim)
+{
+   nifti1_extension * ext;
+   int                c, errs;
+
+   if( nim->num_ext <= 0 || nim->ext_list == NULL ){
+      if( g_opts.debug > 2 ) REprintf("-d empty extension list\n");
+      return 0;
+   }
+
+   /* for each extension, check code, size and data pointer */
+   ext = nim->ext_list;
+   errs = 0;
+   for ( c = 0; c < nim->num_ext; c++ ){
+      if( ! nifti_is_valid_ecode(ext->ecode) ) {
+         if( g_opts.debug > 1 )
+            REprintf("-d ext %d, invalid code %d\n", c, ext->ecode);
+         errs++;
+      }
+
+      if( ext->esize <= 0 ){
+         if( g_opts.debug > 1 )
+            REprintf("-d ext %d, bad size = %d\n", c, ext->esize);
+         errs++;
+      } else if( ext->esize & 0xf ){
+         if( g_opts.debug > 1 )
+            REprintf("-d ext %d, size %d not multiple of 16\n",
+                    c, ext->esize);
+         errs++;
+      }
+
+      if( ext->edata == NULL ){
+         if( g_opts.debug > 1 ) REprintf("-d ext %d, missing data\n", c);
+         errs++;
+      }
+
+      ext++;
+   }
+
+   if( errs > 0 ){
+      if( g_opts.debug > 0 )
+         REprintf("-d had %d extension errors, none will be written\n",
+                 errs);
+      return 0;
+   }
+
+   /* if we're here, we're good */
+   return 1;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! check whether the extension code is valid
+
+    \return 1 if valid, 0 otherwise
+*//*--------------------------------------------------------------------*/
+int nifti_is_valid_ecode( int ecode )
+{
+   if( ecode < NIFTI_ECODE_IGNORE  ||   /* minimum code number (0) */
+       ecode > NIFTI_MAX_ECODE     ||   /* maximum code number     */
+       ecode & 1 )                      /* cannot be odd           */
+      return 0;
+
+   return 1;
+}
+
+
+/*----------------------------------------------------------------------
+ * check for valid size and code, as well as can be done
+ *----------------------------------------------------------------------*/
+static int nifti_check_extension(nifti_image *nim, int size, int code, int rem)
+{
+   /* check for bad code before bad size */
+   if( ! nifti_is_valid_ecode(code) ) {
+      if( g_opts.debug > 2 )
+         REprintf("-d invalid extension code %d\n",code);
+      return 0;
+   }
+
+   if( size < 16 ){
+      if( g_opts.debug > 2 )
+         REprintf("-d ext size %d, no extension\n",size);
+      return 0;
+   }
+
+   if( size > rem ){
+      if( g_opts.debug > 2 )
+         REprintf("-d ext size %d, space %d, no extension\n", size, rem);
+      return 0;
+   }
+
+   if( size & 0xf ){
+      if( g_opts.debug > 2 )
+         REprintf("-d nifti extension size %d not multiple of 16\n",size);
+      return 0;
+   }
+
+   if( nim->nifti_type == NIFTI_FTYPE_ASCII && size > LNI_MAX_NIA_EXT_LEN ){
+      if( g_opts.debug > 2 )
+         REprintf("-d NVE, bad nifti_type 3 size %d\n", size);
+      return 0;
+   }
+
+   return 1;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_image_load_prep  - prepare to read data
+ *
+ * Check nifti_image fields, open the file and seek to the appropriate
+ * offset for reading.
+ *
+ * return NULL on failure
+ *----------------------------------------------------------------------*/
+static znzFile nifti_image_load_prep( nifti_image *nim )
+{
+   /* set up data space, open data file and seek, then call nifti_read_buffer */
+   size_t  ntot , ii , ioff;
+   znzFile fp;
+   char   *tmpimgname;
+   char    fname[] = { "nifti_image_load_prep" };
+
+   /**- perform sanity checks */
+   if( nim == NULL      || nim->iname == NULL ||
+       nim->nbyper <= 0 || nim->nvox <= 0       )
+   {
+      if ( g_opts.debug > 0 ){
+         if( !nim ) REprintf("** ERROR: N_image_load: no nifti image\n");
+         else REprintf("** ERROR: N_image_load: bad params (%p,%d,%u)\n",
+                      nim->iname, nim->nbyper, (unsigned)nim->nvox);
+      }
+      return NULL;
+   }
+
+   ntot = nifti_get_volsize(nim) ; /* total bytes to read */
+
+   /**- open image data file */
+
+   tmpimgname = nifti_findimgname(nim->iname , nim->nifti_type);
+   if( tmpimgname == NULL ){
+      if( g_opts.debug > 0 )
+         REprintf("** no image file found for '%s'\n",nim->iname);
+      return NULL;
+   }
+
+   fp = znzopen(tmpimgname, "rb", nifti_is_gzfile(tmpimgname));
+   if (znz_isnull(fp)){
+       if(g_opts.debug > 0) LNI_FERR(fname,"cannot open data file",tmpimgname);
+       free(tmpimgname);
+       return NULL;  /* bad open? */
+   }
+   free(tmpimgname);
+
+   /**- get image offset: a negative offset means to figure from end of file */
+   if( nim->iname_offset < 0 ){
+     if( nifti_is_gzfile(nim->iname) ){
+        if( g_opts.debug > 0 )
+           LNI_FERR(fname,"negative offset for compressed file",nim->iname);
+        znzclose(fp);
+        return NULL;
+     }
+     ii = nifti_get_filesize( nim->iname ) ;
+     if( ii <= 0 ){
+        if( g_opts.debug > 0 ) LNI_FERR(fname,"empty data file",nim->iname);
+        znzclose(fp);
+        return NULL;
+     }
+     ioff = (ii > ntot) ? ii-ntot : 0 ;
+   } else {                              /* non-negative offset   */
+     ioff = nim->iname_offset ;          /* means use it directly */
+   }
+
+   /**- seek to the appropriate read position */
+   if( znzseek(fp , (long)ioff , SEEK_SET) < 0 ){
+      REprintf("** could not seek to offset %u in file '%s'\n",
+              (unsigned)ioff, nim->iname);
+      znzclose(fp);
+      return NULL;
+   }
+
+   /**- and return the File pointer */
+   return fp;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_image_load
+ *----------------------------------------------------------------------*/
+/*! \fn int nifti_image_load( nifti_image *nim )
+    \brief Load the image blob into a previously initialized nifti_image.
+
+        - If not yet set, the data buffer is allocated with calloc().
+        - The data buffer will be byteswapped if necessary.
+        - The data buffer will not be scaled.
+
+    This function is used to read the image from disk.  It should be used
+    after a function such as nifti_image_read(), so that the nifti_image
+    structure is already initialized.
+
+    \param  nim pointer to a nifti_image (previously initialized)
+    \return 0 on success, -1 on failure
+    \sa     nifti_image_read, nifti_image_free, nifti_image_unload
+*/
+int nifti_image_load_NaN( nifti_image *nim , int rmNaN)
+{
+   /* set up data space, open data file and seek, then call nifti_read_buffer */
+   size_t ntot , ii ;
+   znzFile fp ;
+
+   /**- open the file and position the FILE pointer */
+   fp = nifti_image_load_prep( nim );
+
+   if( fp == NULL ){
+      if( g_opts.debug > 0 )
+         REprintf("** nifti_image_load, failed load_prep\n");
+      return -1;
+   }
+
+   ntot = nifti_get_volsize(nim);
+
+   /**- if the data pointer is not yet set, get memory space for the image */
+
+   if( nim->data == NULL )
+   {
+     nim->data = (void *)calloc(1,ntot) ;  /* create image memory */
+     if( nim->data == NULL ){
+        if( g_opts.debug > 0 )
+           REprintf("** failed to alloc %d bytes for image data\n",
+                   (int)ntot);
+        znzclose(fp);
+        return -1;
+     }
+   }
+
+   /**- now that everything is set up, do the reading */
+   ii = nifti_read_buffer_NaN(fp,nim->data,ntot,nim, rmNaN);
+   if( ii < ntot ){
+      znzclose(fp) ;
+      free(nim->data) ;
+      nim->data = NULL ;
+      return -1 ;  /* errors were printed in nifti_read_buffer() */
+   }
+
+   /**- close the file */
+   znzclose( fp ) ;
+
+   return 0 ;
+}
+
+/*----------------------------------------------------------------------
+ * nifti_image_load
+ *----------------------------------------------------------------------*/
+/*! \fn int nifti_image_load( nifti_image *nim )
+    \brief Load the image blob into a previously initialized nifti_image.
+
+        - If not yet set, the data buffer is allocated with calloc().
+        - The data buffer will be byteswapped if necessary.
+        - The data buffer will not be scaled.
+
+    This function is used to read the image from disk.  It should be used
+    after a function such as nifti_image_read(), so that the nifti_image
+    structure is already initialized.
+
+    \param  nim pointer to a nifti_image (previously initialized)
+    \return 0 on success, -1 on failure
+    \sa     nifti_image_read, nifti_image_free, nifti_image_unload
+*/
+int nifti_image_load( nifti_image *nim)
+{
+  return nifti_image_load_NaN( nim , 1);
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! read ntot bytes of data from an open file and byte swaps if necessary
+
+   note that nifti_image is required for information on datatype, bsize
+   (for any needed byte swapping), etc.
+
+   This function does not allocate memory, so dataptr must be valid.
+*//*--------------------------------------------------------------------*/
+size_t nifti_read_buffer_NaN(znzFile fp, void* dataptr, size_t ntot, 
+                                nifti_image *nim, int rmNaN)
+{
+  size_t ii;
+
+  if( dataptr == NULL ){
+     if( g_opts.debug > 0 )
+        REprintf("** ERROR: nifti_read_buffer: NULL dataptr\n");
+     return -1;
+  }
+
+  ii = znzread( dataptr , 1 , ntot , fp ) ;             /* data input */
+
+  /* if read was short, fail */
+  if( ii < ntot ){ 
+    if( g_opts.debug > 0 )
+       REprintf("++ WARNING: nifti_read_buffer(%s):\n"
+               "   data bytes needed = %u\n"
+               "   data bytes input  = %u\n"
+               "   number missing    = %u (set to 0)\n",
+               nim->iname , (unsigned int)ntot ,
+               (unsigned int)ii , (unsigned int)(ntot-ii) ) ;
+    /* memset( (char *)(dataptr)+ii , 0 , ntot-ii ) ;  now failure [rickr] */
+    return -1 ;
+  }
+
+  if( g_opts.debug > 2 )
+    REprintf("+d nifti_read_buffer: read %u bytes\n", (unsigned)ii);
+  
+  /* byte swap array if needed */
+  
+  /* ntot/swapsize might not fit as int, use size_t    6 Jul 2010 [rickr] */
+  if( nim->swapsize > 1 && nim->byteorder != nifti_short_order() ) {
+    if( g_opts.debug > 1 )
+       REprintf("+d nifti_read_buffer: swapping data bytes...\n");
+    nifti_swap_Nbytes( ntot / nim->swapsize, nim->swapsize , dataptr ) ;
+  }
+
+#ifdef isfinite
+if(rmNaN)
+{
+  /* check input float arrays for goodness, and fix bad floats */
+  int fix_count = 0 ;
+  
+  switch( nim->datatype ){
+    
+    case NIFTI_TYPE_FLOAT32:
+    case NIFTI_TYPE_COMPLEX64:{
+        register float *far = (float *)dataptr ; register size_t jj,nj ;
+        nj = ntot / sizeof(float) ;
+        for( jj=0 ; jj < nj ; jj++ )   /* count fixes 30 Nov 2004 [rickr] */
+           if( !IS_GOOD_FLOAT(far[jj]) ){
+              far[jj] = 0 ;
+              fix_count++ ;
+           }
+      }
+      break ;
+    
+    case NIFTI_TYPE_FLOAT64:
+    case NIFTI_TYPE_COMPLEX128:{
+        register double *far = (double *)dataptr ; register size_t jj,nj ;
+        nj = ntot / sizeof(double) ;
+        for( jj=0 ; jj < nj ; jj++ )   /* count fixes 30 Nov 2004 [rickr] */
+           if( !IS_GOOD_FLOAT(far[jj]) ){
+              far[jj] = 0 ;
+              fix_count++ ;
+           }
+      }
+      break ;
+    
+  }
+
+  if( g_opts.debug > 1 )
+     REprintf("+d in image, %d bad floats were set to 0\n", fix_count);
+}
+  
+#endif
+  
+  return ii;
+}
+
+size_t nifti_read_buffer(znzFile fp, void* dataptr, size_t ntot, 
+                                nifti_image *nim)
+{
+  return nifti_read_buffer_NaN(fp, dataptr, ntot, nim, 1); // call new function with NaN flag support!
+}
+
+
+
+
+/*--------------------------------------------------------------------------*/
+/*! Unload the data in a nifti_image struct, but keep the metadata.
+*//*------------------------------------------------------------------------*/
+void nifti_image_unload( nifti_image *nim )
+{
+   if( nim != NULL && nim->data != NULL ){
+     free(nim->data) ; nim->data = NULL ;
+   }
+   return ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! free 'everything' about a nifti_image struct (including the passed struct)
+
+    free (only fields which are not NULL):
+      - fname and iname
+      - data
+      - any ext_list[i].edata
+      - ext_list
+      - nim
+*//*------------------------------------------------------------------------*/
+void nifti_image_free( nifti_image *nim )
+{
+   if( nim == NULL ) return ;
+   if( nim->fname != NULL ) free(nim->fname) ;
+   if( nim->iname != NULL ) free(nim->iname) ;
+   if( nim->data  != NULL ) free(nim->data ) ;
+   (void)nifti_free_extensions( nim ) ;
+   free(nim) ; return ;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! free the nifti extensions
+
+    - If any edata pointer is set in the extension list, free() it.
+    - Free ext_list, if it is set.
+    - Clear num_ext and ext_list from nim.
+
+    \return 0 on success, -1 on error
+
+    \sa nifti_add_extension, nifti_copy_extensions
+*//*------------------------------------------------------------------------*/
+int nifti_free_extensions( nifti_image *nim )
+{
+   int c ;
+   if( nim == NULL ) return -1;
+   if( nim->num_ext > 0 && nim->ext_list ){
+      for( c = 0; c < nim->num_ext; c++ )
+         if ( nim->ext_list[c].edata ) free(nim->ext_list[c].edata);
+      free(nim->ext_list);
+   }
+   /* or if it is inconsistent, warn the user (if we are not in quiet mode) */
+   else if ( (nim->num_ext > 0 || nim->ext_list != NULL) && (g_opts.debug > 0) )
+      REprintf("** warning: nifti extension num/ptr mismatch (%d,%p)\n",
+              nim->num_ext, (void *)nim->ext_list);
+
+   if( g_opts.debug > 2 )
+      REprintf("+d free'd %d extension(s)\n", nim->num_ext);
+
+   nim->num_ext = 0;
+   nim->ext_list = NULL;
+
+   return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! Print to stdout some info about a nifti_image struct.
+*//*------------------------------------------------------------------------*/
+void nifti_image_infodump( const nifti_image *nim )
+{
+   char *str = nifti_image_to_ascii( nim ) ;
+   /* stdout -> stderr   2 Dec 2004 [rickr] */
+   if( str != NULL ){ REprintf(str); /*fputs(str,stderr)*/ ; free(str) ; }
+   return ;
+}
+
+
+/*--------------------------------------------------------------------------
+ * nifti_write_buffer just check for a null znzFile and call znzwrite
+ *--------------------------------------------------------------------------*/
+/*! \fn size_t nifti_write_buffer(znzFile fp, void *buffer, size_t numbytes)
+    \brief write numbytes of buffer to file, fp
+
+    \param fp           File pointer (from znzopen) to gzippable nifti datafile
+    \param buffer       data buffer to be written
+    \param numbytes     number of bytes in buffer to write
+    \return number of bytes successfully written
+*/
+size_t nifti_write_buffer(znzFile fp, const void *buffer, size_t numbytes)
+{
+   /* Write all the image data at once (no swapping here) */
+   size_t ss;
+   if (znz_isnull(fp)){
+      REprintf("** ERROR: nifti_write_buffer: null file pointer\n");
+      return 0;
+   }
+   ss = znzwrite( (void*)buffer , 1 , numbytes , fp ) ;
+   return ss;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! write the nifti_image data to file (from nim->data or from NBL)
+
+   If NBL is not NULL, write the data from that structure.  Otherwise,
+   write it out from nim->data.  No swapping is done here.
+
+   \param  fp  : File pointer
+   \param  nim : nifti_image corresponding to the data
+   \param  NBL : optional source of write data (if NULL use nim->data)
+  
+   \return 0 on success, -1 on failure
+
+   Note: the nifti_image byte_order is set as that of the current CPU.
+         This is because such a conversion was made to the data upon
+         reading, while byte_order was not set (so the programs would
+         know what format the data was on disk).  Effectively, since
+         byte_order should match what is on disk, it should bet set to
+         that of the current CPU whenever new filenames are assigned.
+*//*--------------------------------------------------------------------*/
+int nifti_write_all_data(znzFile fp, nifti_image * nim,
+                         const nifti_brick_list * NBL)
+{
+   size_t ss;
+   int    bnum;
+
+   if( !NBL ){ /* just write one buffer and get out of here */
+      if( nim->data == NULL ){
+         REprintf("** NWAD: no image data to write\n");
+         return -1;
+      }
+
+      ss = nifti_write_buffer(fp,nim->data,nim->nbyper * nim->nvox);
+      if (ss < nim->nbyper * nim->nvox){
+         REprintf(
+            "** ERROR: NWAD: wrote only %u of %u bytes to file\n",
+            (unsigned)ss, (unsigned)(nim->nbyper * nim->nvox));
+         return -1;
+      }
+
+      if( g_opts.debug > 1 )
+         REprintf("+d wrote single image of %u bytes\n", (unsigned)ss);
+   } else {
+      if( ! NBL->bricks || NBL->nbricks <= 0 || NBL->bsize <= 0 ){
+         REprintf("** NWAD: no brick data to write (%p,%d,%u)\n",
+                 (void *)NBL->bricks, NBL->nbricks, (unsigned)NBL->bsize);
+         return -1;
+      }
+
+      for( bnum = 0; bnum < NBL->nbricks; bnum++ ){
+         ss = nifti_write_buffer(fp, NBL->bricks[bnum], NBL->bsize);
+         if( ss < NBL->bsize ){
+            REprintf(
+              "** NWAD ERROR: wrote %u of %u bytes of brick %d of %d to file",
+               (unsigned)ss, (unsigned)NBL->bsize, bnum+1, NBL->nbricks);
+            return -1;
+         }
+      }
+      if( g_opts.debug > 1 )
+         REprintf("+d wrote image of %d brick(s), each of %u bytes\n",
+                 NBL->nbricks, (unsigned int)NBL->bsize);
+   }
+
+   /* mark as being in this CPU byte order */
+   nim->byteorder = nifti_short_order() ;
+
+   return 0;
+}
+
+/* return number of extensions written, or -1 on error */
+static int nifti_write_extensions(znzFile fp, nifti_image *nim)
+{
+   nifti1_extension * list;
+   char               extdr[4] = { 0, 0, 0, 0 };
+   int                c, size, ok = 1;
+
+   if( znz_isnull(fp) || !nim || nim->num_ext < 0 ){
+      if( g_opts.debug > 0 )
+         REprintf("** nifti_write_extensions, bad params\n");
+      return -1;
+   }
+
+   /* if no extensions and user requests it, skip extender */
+   if( g_opts.skip_blank_ext && (nim->num_ext == 0 || ! nim->ext_list ) ){
+      if( g_opts.debug > 1 )
+         REprintf("-d no exts and skip_blank_ext set, "
+                        "so skipping 4-byte extender\n");
+      return 0;
+   }
+
+   /* if invalid extension list, clear num_ext */
+   if( ! valid_nifti_extensions(nim) ) nim->num_ext = 0;
+
+   /* write out extender block */
+   if( nim->num_ext > 0 ) extdr[0] = 1;
+   if( nifti_write_buffer(fp, extdr, 4) != 4 ){
+      REprintf("** failed to write extender\n");
+      return -1;
+   }
+
+   list = nim->ext_list;
+   for ( c = 0; c < nim->num_ext; c++ ){
+      size = (int)nifti_write_buffer(fp, &list->esize, sizeof(int));
+      ok = (size == (int)sizeof(int));
+      if( ok ){
+         size = (int)nifti_write_buffer(fp, &list->ecode, sizeof(int));
+         ok = (size == (int)sizeof(int));
+      }
+      if( ok ){
+         size = (int)nifti_write_buffer(fp, list->edata, list->esize - 8);
+         ok = (size == list->esize - 8);
+      }
+
+      if( !ok ){
+         REprintf("** failed while writing extension #%d\n",c);
+         return -1;
+      } else if ( g_opts.debug > 2 )
+         REprintf("+d wrote extension %d of %d bytes\n", c, size);
+
+      list++;
+   }
+
+   if( g_opts.debug > 1 )
+      REprintf("+d wrote out %d extension(s)\n", nim->num_ext);
+
+   return nim->num_ext;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! basic initialization of a nifti_image struct (to a 1x1x1 image)
+*//*--------------------------------------------------------------------*/
+nifti_image* nifti_simple_init_nim(void)
+{
+  nifti_image *nim;
+  struct nifti_1_header nhdr;
+  int nbyper, swapsize;
+  
+   memset(&nhdr,0,sizeof(nhdr)) ;  /* zero out header, to be safe */
+  
+   nhdr.sizeof_hdr = sizeof(nhdr) ;
+   nhdr.regular    = 'r' ;           /* for some stupid reason */
+
+   nhdr.dim[0] = 3 ;
+   nhdr.dim[1] = 1 ; nhdr.dim[2] = 1 ; nhdr.dim[3] = 1 ;
+   nhdr.dim[4] = 0 ;
+
+   nhdr.pixdim[0] = 0.0 ;
+   nhdr.pixdim[1] = 1.0 ; nhdr.pixdim[2] = 1.0 ;
+   nhdr.pixdim[3] = 1.0 ;
+
+   nhdr.datatype = DT_FLOAT32 ;
+   nifti_datatype_sizes( nhdr.datatype , &nbyper, &swapsize );
+   nhdr.bitpix   = 8 * nbyper ;
+
+   strcpy(nhdr.magic, "n+1");  /* init to single file */
+
+   nim = nifti_convert_nhdr2nim(nhdr,NULL);
+   nim->fname = NULL;
+   nim->iname = NULL;
+   return nim;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! basic initialization of a nifti_1_header struct (with given dimensions)
+
+   Return an allocated nifti_1_header struct, based on the given
+   dimensions and datatype.
+ 
+   \param arg_dims  : optional dim[8] array (default {3,1,1,1,0,0,0,0})
+   \param arg_dtype : optional datatype (default DT_FLOAT32)
+
+   \return pointer to allocated nifti_1_header struct
+*//*--------------------------------------------------------------------*/
+nifti_1_header * nifti_make_new_header(const int arg_dims[], int arg_dtype)
+{
+   nifti_1_header * nhdr;
+   const int        default_dims[8] = { 3, 1, 1, 1, 0, 0, 0, 0 };
+   const int      * dim;  /* either passed or default dims  */
+   int              dtype; /* either passed or default dtype */
+   int              c, nbyper, swapsize;
+  
+   /* if arg_dims is passed, apply it */
+   if( arg_dims ) dim = arg_dims;
+   else           dim = default_dims;
+
+   /* validate dim: if there is any problem, apply default_dims */
+   if( dim[0] < 1 || dim[0] > 7 ) {
+      REprintf("** nifti_simple_hdr_with_dims: bad dim[0]=%d\n",dim[0]);
+      dim = default_dims;
+   } else {
+      for( c = 1; c <= dim[0]; c++ )
+         if( dim[c] < 1 )
+         {
+            REprintf(
+                "** nifti_simple_hdr_with_dims: bad dim[%d]=%d\n",c,dim[c]);
+            dim = default_dims;
+            break;
+         }
+   }
+
+   /* validate dtype, too */
+   dtype = arg_dtype;
+   if( ! nifti_is_valid_datatype(dtype) ) {
+      REprintf("** nifti_simple_hdr_with_dims: bad dtype %d\n",dtype);
+      dtype = DT_FLOAT32;
+   }
+
+   /* now populate the header struct */
+
+   if( g_opts.debug > 1 )
+      REprintf("+d nifti_make_new_header, dim[0] = %d, datatype = %d\n",
+              dim[0], dtype);
+
+   nhdr = (nifti_1_header *)calloc(1,sizeof(nifti_1_header));
+   if( !nhdr ){
+      REprintf("** nifti_make_new_header: failed to alloc hdr\n");
+      return NULL;
+   }
+  
+   nhdr->sizeof_hdr = sizeof(nifti_1_header) ;
+   nhdr->regular    = 'r' ;           /* for some stupid reason */
+
+   /* init dim and pixdim */
+   nhdr->dim[0] = dim[0] ;
+   nhdr->pixdim[0] = 0.0;
+   for( c = 1; c <= dim[0]; c++ ) {
+      nhdr->dim[c] = dim[c];
+      nhdr->pixdim[c] = 1.0;
+   }
+
+   nhdr->datatype = dtype ;
+   nifti_datatype_sizes( nhdr->datatype , &nbyper, &swapsize );
+   nhdr->bitpix   = 8 * nbyper ;
+
+   strcpy(nhdr->magic, "n+1");  /* init to single file */
+
+   return nhdr;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! basic creation of a nifti_image struct
+
+   Create a nifti_image from the given dimensions and data type.
+   Optinally, allocate zero-filled data.
+  
+   \param dims      : optional dim[8]   (default {3,1,1,1,0,0,0,0})
+   \param datatype  : optional datatype (default DT_FLOAT32)
+   \param data_fill : if flag is set, allocate zero-filled data for image
+
+   \return pointer to allocated nifti_image struct
+*//*--------------------------------------------------------------------*/
+nifti_image * nifti_make_new_nim(const int dims[], int datatype, int data_fill)
+{
+   nifti_image    * nim;
+   nifti_1_header * nhdr;
+
+   nhdr = nifti_make_new_header(dims, datatype);
+   if( !nhdr ) return NULL;  /* error already printed */
+
+   nim = nifti_convert_nhdr2nim(*nhdr,NULL);
+   free(nhdr);               /* in any case, we are done with this */
+   if( !nim ){
+      REprintf("** NMNN: nifti_convert_nhdr2nim failure\n");
+      return NULL;
+   }
+
+   if( g_opts.debug > 1 )
+      REprintf("+d nifti_make_new_nim, data_fill = %d\n",data_fill);
+
+   if( data_fill ) {
+      nim->data = calloc(nim->nvox, nim->nbyper);
+
+      /* if we cannot allocate data, take ball and go home */
+      if( !nim->data ) {
+         REprintf("** NMNN: failed to alloc %u bytes for data\n",
+                 (unsigned)(nim->nvox*nim->nbyper));
+         nifti_image_free(nim);
+         nim = NULL;
+      }
+   }
+
+   return nim;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! convert a nifti_image structure to a nifti_1_header struct
+
+    No allocation is done, this should be used via structure copy.
+    As in:
+    <pre>
+    nifti_1_header my_header;
+    my_header = nifti_convert_nim2nhdr(my_nim_pointer);
+    </pre>
+*//*--------------------------------------------------------------------*/
+struct nifti_1_header nifti_convert_nim2nhdr(const nifti_image * nim)
+{
+   struct nifti_1_header nhdr;
+
+   memset(&nhdr,0,sizeof(nhdr)) ;  /* zero out header, to be safe */
+
+
+   /**- load the ANALYZE-7.5 generic parts of the header struct */
+
+   nhdr.sizeof_hdr = sizeof(nhdr) ;
+   nhdr.regular    = 'r' ;             /* for some stupid reason */
+
+   nhdr.dim[0] = nim->ndim ;
+   nhdr.dim[1] = nim->nx ; nhdr.dim[2] = nim->ny ; nhdr.dim[3] = nim->nz ;
+   nhdr.dim[4] = nim->nt ; nhdr.dim[5] = nim->nu ; nhdr.dim[6] = nim->nv ;
+   nhdr.dim[7] = nim->nw ;
+
+   nhdr.pixdim[0] = 0.0 ;
+   nhdr.pixdim[1] = nim->dx ; nhdr.pixdim[2] = nim->dy ;
+   nhdr.pixdim[3] = nim->dz ; nhdr.pixdim[4] = nim->dt ;
+   nhdr.pixdim[5] = nim->du ; nhdr.pixdim[6] = nim->dv ;
+   nhdr.pixdim[7] = nim->dw ;
+
+   nhdr.datatype = nim->datatype ;
+   nhdr.bitpix   = 8 * nim->nbyper ;
+
+   if( nim->cal_max > nim->cal_min ){
+     nhdr.cal_max = nim->cal_max ;
+     nhdr.cal_min = nim->cal_min ;
+   }
+
+   if( nim->scl_slope != 0.0 ){
+     nhdr.scl_slope = nim->scl_slope ;
+     nhdr.scl_inter = nim->scl_inter ;
+   }
+
+   if( nim->descrip[0] != '\0' ){
+     memcpy(nhdr.descrip ,nim->descrip ,79) ; nhdr.descrip[79] = '\0' ;
+   }
+   if( nim->aux_file[0] != '\0' ){
+     memcpy(nhdr.aux_file ,nim->aux_file ,23) ; nhdr.aux_file[23] = '\0' ;
+   }
+
+   /**- Load NIFTI specific stuff into the header */
+
+   if( nim->nifti_type > NIFTI_FTYPE_ANALYZE ){ /* then not ANALYZE */
+
+     if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcpy(nhdr.magic,"n+1") ;
+     else                                          strcpy(nhdr.magic,"ni1") ;
+
+     nhdr.pixdim[1] = fabs(nhdr.pixdim[1]) ; nhdr.pixdim[2] = fabs(nhdr.pixdim[2]) ;
+     nhdr.pixdim[3] = fabs(nhdr.pixdim[3]) ; nhdr.pixdim[4] = fabs(nhdr.pixdim[4]) ;
+     nhdr.pixdim[5] = fabs(nhdr.pixdim[5]) ; nhdr.pixdim[6] = fabs(nhdr.pixdim[6]) ;
+     nhdr.pixdim[7] = fabs(nhdr.pixdim[7]) ;
+
+     nhdr.intent_code = nim->intent_code ;
+     nhdr.intent_p1   = nim->intent_p1 ;
+     nhdr.intent_p2   = nim->intent_p2 ;
+     nhdr.intent_p3   = nim->intent_p3 ;
+     if( nim->intent_name[0] != '\0' ){
+       memcpy(nhdr.intent_name,nim->intent_name,15) ;
+       nhdr.intent_name[15] = '\0' ;
+     }
+
+     nhdr.vox_offset  = (float) nim->iname_offset ;
+     nhdr.xyzt_units  = SPACE_TIME_TO_XYZT( nim->xyz_units, nim->time_units ) ;
+     nhdr.toffset     = nim->toffset ;
+
+     if( nim->qform_code > 0 ){
+       nhdr.qform_code = nim->qform_code ;
+       nhdr.quatern_b  = nim->quatern_b ;
+       nhdr.quatern_c  = nim->quatern_c ;
+       nhdr.quatern_d  = nim->quatern_d ;
+       nhdr.qoffset_x  = nim->qoffset_x ;
+       nhdr.qoffset_y  = nim->qoffset_y ;
+       nhdr.qoffset_z  = nim->qoffset_z ;
+       nhdr.pixdim[0]  = (nim->qfac >= 0.0) ? 1.0 : -1.0 ;
+     }
+
+     if( nim->sform_code > 0 ){
+       nhdr.sform_code = nim->sform_code ;
+       nhdr.srow_x[0]  = nim->sto_xyz.m[0][0] ;
+       nhdr.srow_x[1]  = nim->sto_xyz.m[0][1] ;
+       nhdr.srow_x[2]  = nim->sto_xyz.m[0][2] ;
+       nhdr.srow_x[3]  = nim->sto_xyz.m[0][3] ;
+       nhdr.srow_y[0]  = nim->sto_xyz.m[1][0] ;
+       nhdr.srow_y[1]  = nim->sto_xyz.m[1][1] ;
+       nhdr.srow_y[2]  = nim->sto_xyz.m[1][2] ;
+       nhdr.srow_y[3]  = nim->sto_xyz.m[1][3] ;
+       nhdr.srow_z[0]  = nim->sto_xyz.m[2][0] ;
+       nhdr.srow_z[1]  = nim->sto_xyz.m[2][1] ;
+       nhdr.srow_z[2]  = nim->sto_xyz.m[2][2] ;
+       nhdr.srow_z[3]  = nim->sto_xyz.m[2][3] ;
+     }
+
+     nhdr.dim_info = FPS_INTO_DIM_INFO( nim->freq_dim ,
+                                        nim->phase_dim , nim->slice_dim ) ;
+     nhdr.slice_code     = nim->slice_code ;
+     nhdr.slice_start    = nim->slice_start ;
+     nhdr.slice_end      = nim->slice_end ;
+     nhdr.slice_duration = nim->slice_duration ;
+   }
+
+   return nhdr;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! \fn int nifti_copy_extensions(nifti_image * nim_dest, nifti_image * nim_src)
+    \brief copy the nifti1_extension list from src to dest
+
+    Duplicate the list of nifti1_extensions.  The dest structure must
+    be clear of extensions.
+    \return 0 on success, -1 on failure
+
+    \sa nifti_add_extension, nifti_free_extensions
+*/
+int nifti_copy_extensions(nifti_image * nim_dest, const nifti_image * nim_src)
+{
+   char   * data;
+   size_t   bytes;
+   int      c, size, old_size;
+
+   if( nim_dest->num_ext > 0 || nim_dest->ext_list != NULL ){
+      REprintf("** will not copy extensions over existing ones\n");
+      return -1;
+   }
+
+   if( g_opts.debug > 1 )
+      REprintf("+d duplicating %d extension(s)\n", nim_src->num_ext);
+
+   if( nim_src->num_ext <= 0 ) return 0;
+
+   bytes = nim_src->num_ext * sizeof(nifti1_extension);  /* I'm lazy */
+   nim_dest->ext_list = (nifti1_extension *)malloc(bytes);
+   if( !nim_dest->ext_list ){
+      REprintf("** failed to allocate %d nifti1_extension structs\n",
+              nim_src->num_ext);
+      return -1;
+   }
+
+   /* copy the extension data */
+   nim_dest->num_ext = 0;
+   for( c = 0; c < nim_src->num_ext; c++ ){
+      size = old_size = nim_src->ext_list[c].esize;
+      if( size & 0xf ) size = (size + 0xf) & ~0xf; /* make multiple of 16 */
+      if( g_opts.debug > 2 )
+         REprintf("+d dup'ing ext #%d of size %d (from size %d)\n",
+                 c, size, old_size);
+      /* data length is size-8, as esize includes space for esize and ecode */
+      data = (char *)calloc(size-8,sizeof(char));      /* maybe size > old */
+      if( !data ){
+         REprintf("** failed to alloc %d bytes for extention\n", size);
+         if( c == 0 ) { free(nim_dest->ext_list); nim_dest->ext_list = NULL; }
+         /* otherwise, keep what we have (a.o.t. deleting them all) */
+         return -1;
+      }
+      /* finally, fill the new structure */
+      nim_dest->ext_list[c].esize = size;
+      nim_dest->ext_list[c].ecode = nim_src->ext_list[c].ecode;
+      nim_dest->ext_list[c].edata = data;
+      memcpy(data, nim_src->ext_list[c].edata, old_size-8);
+
+      nim_dest->num_ext++;
+   }
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! compute the total size of all extensions
+
+    \return the total of all esize fields
+
+    Note that each esize includes 4 bytes for ecode, 4 bytes for esize,
+    and the bytes used for the data.  Each esize also needs to be a
+    multiple of 16, so it may be greater than the sum of its 3 parts.
+*//*--------------------------------------------------------------------*/
+int nifti_extension_size(nifti_image *nim)
+{
+   int c, size = 0;
+
+   if( !nim || nim->num_ext <= 0 ) return 0;
+
+   if( g_opts.debug > 2 ) REprintf("-d ext sizes:");
+
+   for ( c = 0; c < nim->num_ext; c++ ){
+      size += nim->ext_list[c].esize;
+      if( g_opts.debug > 2 ) REprintf("  %d",nim->ext_list[c].esize);
+   }
+
+   if( g_opts.debug > 2 ) REprintf(" (total = %d)\n",size);
+
+   return size;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! set the nifti_image iname_offset field, based on nifti_type
+
+    - if writing to 2 files, set offset to 0
+    - if writing to a single NIFTI-1 file, set the offset to
+         352 + total extension size, then align to 16-byte boundary
+    - if writing an ASCII header, set offset to -1
+*//*--------------------------------------------------------------------*/
+void nifti_set_iname_offset(nifti_image *nim)
+{
+   int offset;
+
+   switch( nim->nifti_type ){
+
+     default:  /* writing into 2 files */
+       /* we only write files with 0 offset in the 2 file format */
+       nim->iname_offset = 0 ;
+     break ;
+
+     /* NIFTI-1 single binary file - always update */
+     case NIFTI_FTYPE_NIFTI1_1:
+       offset = nifti_extension_size(nim)+sizeof(struct nifti_1_header)+4;
+       /* be sure offset is aligned to a 16 byte boundary */
+       if ( ( offset % 16 ) != 0 )  offset = ((offset + 0xf) & ~0xf);
+       if( nim->iname_offset != offset ){
+          if( g_opts.debug > 1 )
+             REprintf("+d changing offset from %d to %d\n",
+                  nim->iname_offset, offset);
+          nim->iname_offset = offset;
+       }
+     break ;
+
+     /* non-standard case: NIFTI-1 ASCII header + binary data (single file) */
+     case NIFTI_FTYPE_ASCII:
+       nim->iname_offset = -1 ;             /* compute offset from filesize */
+     break ;
+   }
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! write the nifti_image dataset to disk, optionally including data
+
+   This is just a front-end for nifti_image_write_hdr_img2.
+
+   \param nim        nifti_image to write to disk
+   \param write_data write options (see nifti_image_write_hdr_img2)
+   \param opts       file open options ("wb" from nifti_image_write)
+
+   \sa nifti_image_write, nifti_image_write_hdr_img2, nifti_image_free,
+       nifti_set_filenames
+*//*--------------------------------------------------------------------*/
+znzFile nifti_image_write_hdr_img( nifti_image *nim , int write_data , 
+                                          const char* opts )
+{
+  return nifti_image_write_hdr_img2(nim,write_data,opts,NULL,NULL);
+}
+
+
+#undef  ERREX
+#define ERREX(msg)                                                \
+ do{ REprintf("** ERROR: nifti_image_write_hdr_img: %s\n",(msg)) ;  \
+     return fp ; } while(0)
+
+
+/* ----------------------------------------------------------------------*/
+/*! This writes the header (and optionally the image data) to file
+ *
+ * If the image data file is left open it returns a valid znzFile handle.
+ * It also uses imgfile as the open image file is not null, and modifies
+ * it inside.
+ * 
+ * \param nim        nifti_image to write to disk
+ * \param write_opts flags whether to write data and/or close file (see below)
+ * \param opts       file-open options, probably "wb" from nifti_image_write()
+ * \param imgfile    optional open znzFile struct, for writing image data
+                     (may be NULL)
+ * \param NBL        optional nifti_brick_list, containing the image data
+                     (may be NULL)
+ * 
+ * Values for write_opts mode are based on two binary flags
+ * ( 0/1 for no-write/write data, and 0/2 for close/leave-open files ) :
+ *    -   0 = do not write data and close (do not open data file)
+ *    -   1 = write data        and close
+ *    -   2 = do not write data and leave data file open 
+ *    -   3 = write data        and leave data file open 
+ *
+ * \sa nifti_image_write, nifti_image_write_hdr_img, nifti_image_free,
+ *     nifti_set_filenames
+*//*---------------------------------------------------------------------*/
+znzFile nifti_image_write_hdr_img2(nifti_image *nim, int write_opts, 
+               const char * opts, znzFile imgfile, const nifti_brick_list * NBL)
+{
+   struct nifti_1_header nhdr ;
+   znzFile               fp=NULL;
+   size_t                ss ;
+   int                   write_data, leave_open;
+   char                  func[] = { "nifti_image_write_hdr_img2" };
+
+   write_data = write_opts & 1;  /* just separate the bits now */
+   leave_open = write_opts & 2;
+
+   if( ! nim                              ) ERREX("NULL input") ;
+   if( ! nifti_validfilename(nim->fname)  ) ERREX("bad fname input") ;
+   if( write_data && ! nim->data && ! NBL ) ERREX("no image data") ;
+
+   if( write_data && NBL && ! nifti_NBL_matches_nim(nim, NBL) )
+      ERREX("NBL does not match nim");
+
+   nifti_set_iname_offset(nim);
+
+   if( g_opts.debug > 1 ){
+      REprintf("-d writing nifti file '%s'...\n", nim->fname);
+      if( g_opts.debug > 2 )
+         REprintf("-d nifti type %d, offset %d\n",
+                 nim->nifti_type, nim->iname_offset);
+   }
+
+   if( nim->nifti_type == NIFTI_FTYPE_ASCII )   /* non-standard case */
+      return nifti_write_ascii_image(nim,NBL,opts,write_data,leave_open);
+
+   nhdr = nifti_convert_nim2nhdr(nim);    /* create the nifti1_header struct */
+
+   /* if writing to 2 files, make sure iname is set and different from fname */
+   if( nim->nifti_type != NIFTI_FTYPE_NIFTI1_1 ){
+       if( nim->iname && strcmp(nim->iname,nim->fname) == 0 ){
+         free(nim->iname) ; nim->iname = NULL ;
+       }
+       if( nim->iname == NULL ){ /* then make a new one */
+         nim->iname = nifti_makeimgname(nim->fname,nim->nifti_type,0,0);
+         if( nim->iname == NULL ) return NULL;  
+       }
+   }
+
+   /* if we have an imgfile and will write the header there, use it */
+   if( ! znz_isnull(imgfile) && nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ){
+      if( g_opts.debug > 2 ) REprintf("+d using passed file for hdr\n");
+      fp = imgfile;
+   }
+   else {
+      if( g_opts.debug > 2 )
+         REprintf("+d opening output file %s [%s]\n",nim->fname,opts);
+      fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ;
+      if( znz_isnull(fp) ){
+         LNI_FERR(func,"cannot open output file",nim->fname);
+         return fp;
+      }
+   }
+
+   /* write the header and extensions */
+
+   ss = znzwrite(&nhdr , 1 , sizeof(nhdr) , fp); /* write header */
+   if( ss < sizeof(nhdr) ){
+      LNI_FERR(func,"bad header write to output file",nim->fname);
+      znzclose(fp); return fp;
+   }
+
+   /* partial file exists, and errors have been printed, so ignore return */
+   if( nim->nifti_type != NIFTI_FTYPE_ANALYZE )
+      (void)nifti_write_extensions(fp,nim);
+
+   /* if the header is all we want, we are done */
+   if( ! write_data && ! leave_open ){
+      if( g_opts.debug > 2 ) REprintf("-d header is all we want: done\n");
+      znzclose(fp); return(fp);
+   }
+
+   if( nim->nifti_type != NIFTI_FTYPE_NIFTI1_1 ){ /* get a new file pointer */
+      znzclose(fp);         /* first, close header file */
+      if( ! znz_isnull(imgfile) ){
+         if(g_opts.debug > 2) REprintf("+d using passed file for img\n");
+         fp = imgfile;
+      }
+      else {
+         if( g_opts.debug > 2 )
+            REprintf("+d opening img file '%s'\n", nim->iname);
+         fp = znzopen( nim->iname , opts , nifti_is_gzfile(nim->iname) ) ;
+         if( znz_isnull(fp) ) ERREX("cannot open image file") ;
+      }
+   }
+
+   znzseek(fp, nim->iname_offset, SEEK_SET);  /* in any case, seek to offset */
+
+   if( write_data ) nifti_write_all_data(fp,nim,NBL);
+   if( ! leave_open ) znzclose(fp);
+
+   return fp;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! write a nifti_image to disk in ASCII format
+*//*--------------------------------------------------------------------*/
+znzFile nifti_write_ascii_image(nifti_image *nim, const nifti_brick_list * NBL,
+                              const char *opts, int write_data, int leave_open)
+{
+   znzFile   fp;
+   char    * hstr;
+                                                                                
+   hstr = nifti_image_to_ascii( nim ) ;  /* get header in ASCII form */
+   if( ! hstr ){ REprintf("** failed image_to_ascii()\n"); return NULL; }
+                                                                                
+   fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ;
+   if( znz_isnull(fp) ){
+      free(hstr);
+      REprintf("** failed to open '%s' for ascii write\n",nim->fname);
+      return fp;
+   }
+                                                                                
+   znzputs(hstr,fp);                                               /* header */
+   nifti_write_extensions(fp,nim);                             /* extensions */
+                                                                                
+   if ( write_data   ) { nifti_write_all_data(fp,nim,NBL); }         /* data */
+   if ( ! leave_open ) { znzclose(fp); }
+   free(hstr);
+   return fp;  /* returned but may be closed */
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! Write a nifti_image to disk.
+
+   Since data is properly byte-swapped upon reading, it is assumed
+   to be in the byte-order of the current CPU at write time.  Thus,
+   nim->byte_order should match that of the current CPU.  Note that
+   the nifti_set_filenames() function takes the flag, set_byte_order.
+
+   The following fields of nim affect how the output appears:
+    - nifti_type = 0 ==> ANALYZE-7.5 format file pair will be written
+    - nifti_type = 1 ==> NIFTI-1 format single file will be written
+                         (data offset will be 352+extensions)
+    - nifti_type = 2 ==> NIFTI_1 format file pair will be written
+    - nifti_type = 3 ==> NIFTI_1 ASCII single file will be written
+    - fname is the name of the output file (header or header+data)
+    - if a file pair is being written, iname is the name of the data file
+    - existing files WILL be overwritten with extreme prejudice
+    - if qform_code > 0, the quatern_*, qoffset_*, and qfac fields determine
+      the qform output, NOT the qto_xyz matrix; if you want to compute these
+      fields from the qto_xyz matrix, you can use the utility function
+      nifti_mat44_to_quatern()
+
+   \sa nifti_image_write_bricks, nifti_image_free, nifti_set_filenames,
+       nifti_image_write_hdr_img
+*//*------------------------------------------------------------------------*/
+void nifti_image_write( nifti_image *nim )
+{
+   znzFile fp = nifti_image_write_hdr_img(nim,1,"wb");
+   if( fp ){
+      if( g_opts.debug > 2 ) REprintf("-d niw: done with znzFile\n");
+      free(fp);
+   }
+   if( g_opts.debug > 1 ) REprintf("-d nifti_image_write: done\n");
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! similar to nifti_image_write, but data is in NBL struct, not nim->data
+
+   \sa nifti_image_write, nifti_image_free, nifti_set_filenames, nifti_free_NBL
+*//*--------------------------------------------------------------------*/
+void nifti_image_write_bricks( nifti_image *nim, const nifti_brick_list * NBL )
+{
+   znzFile fp = nifti_image_write_hdr_img2(nim,1,"wb",NULL,NBL);
+   if( fp ){
+      if( g_opts.debug > 2 ) REprintf("-d niwb: done with znzFile\n");
+      free(fp);
+   }
+   if( g_opts.debug > 1 ) REprintf("-d niwb: done writing bricks\n");
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! copy the nifti_image structure, without data
+
+    Duplicate the structure, including fname, iname and extensions.
+    Leave the data pointer as NULL.
+*//*--------------------------------------------------------------------*/
+nifti_image * nifti_copy_nim_info(const nifti_image * src)
+{
+  nifti_image *dest;
+  dest = (nifti_image *)calloc(1,sizeof(nifti_image));
+  if( !dest ){
+     REprintf("** NCNI: failed to alloc nifti_image\n");
+     return NULL;
+  }
+  memcpy(dest, src, sizeof(nifti_image));
+  if( src->fname ) dest->fname = nifti_strdup(src->fname);
+  if( src->iname ) dest->iname = nifti_strdup(src->iname);
+  dest->num_ext = 0;
+  dest->ext_list = NULL;
+  /* errors will be printed in NCE(), continue in either case */
+  (void)nifti_copy_extensions(dest, src);
+
+  dest->data = NULL;
+
+  return dest;
+}
+
+
+/*------------------------------------------------------------------------*/
+/* Un-escape a C string in place -- that is, convert XML escape sequences
+   back into their characters.  (This can be done in place since the
+   replacement is always smaller than the input.)  Escapes recognized are:
+     -  <   ->  <
+     -  >   ->  >
+     -  " ->  "
+     -  ' ->  '
+     -  &  ->  &
+   Also replace CR LF pair (Microsoft), or CR alone (Macintosh) with
+   LF (Unix), per the XML standard.
+   Return value is number of replacements made (if you care).
+--------------------------------------------------------------------------*/
+
+#undef  CR
+#undef  LF
+#define CR 0x0D
+#define LF 0x0A
+
+static int unescape_string( char *str )
+{
+   int ii,jj , nn,ll ;
+
+   if( str == NULL ) return 0 ;                /* no string? */
+   ll = (int)strlen(str) ; if( ll == 0 ) return 0 ;
+
+   /* scan for escapes: &something; */
+
+   for( ii=jj=nn=0 ; ii<ll ; ii++,jj++ ){ /* scan at ii; results go in at jj */
+
+     if( str[ii] == '&' ){  /* start of escape? */
+
+             if( ii+3 < ll        &&   /* < */
+                 str[ii+1] == 'l' &&
+                 str[ii+2] == 't' &&
+                 str[ii+3] == ';'   ){ str[jj] = '<' ; ii += 3 ; nn++ ; }
+
+        else if( ii+3 < ll        &&   /* > */
+                 str[ii+1] == 'g' &&
+                 str[ii+2] == 't' &&
+                 str[ii+3] == ';'   ){ str[jj] = '>' ; ii += 3 ; nn++ ; }
+
+        else if( ii+5 < ll        &&   /* " */
+                 str[ii+1] == 'q' &&
+                 str[ii+2] == 'u' &&
+                 str[ii+3] == 'o' &&
+                 str[ii+4] == 't' &&
+                 str[ii+5] == ';'   ){ str[jj] = '"' ; ii += 5 ; nn++ ; }
+
+        else if( ii+5 < ll        &&   /* ' */
+                 str[ii+1] == 'a' &&
+                 str[ii+2] == 'p' &&
+                 str[ii+3] == 'o' &&
+                 str[ii+4] == 's' &&
+                 str[ii+5] == ';'   ){ str[jj] = '\'' ; ii += 5 ; nn++ ; }
+
+        else if( ii+4 < ll        &&  /* & */
+                 str[ii+1] == 'a' &&
+                 str[ii+2] == 'm' &&
+                 str[ii+3] == 'p' &&
+                 str[ii+4] == ';'   ){ str[jj] = '&' ; ii += 4 ; nn++ ; }
+
+        /* although the comments above don't mention it,
+           we also look for XML style numeric escapes
+           of the forms   (decimal) and &#xfd; (hex) */
+
+        else if( ii+3 < ll        &&
+                 str[ii+1] == '#' &&
+                 isdigit(str[ii+2]) ){   /* &#dec; */
+
+           unsigned int val='?' ; int kk=ii+3 ;
+           while( kk < ll && kk != ';' ) kk++ ;
+           sscanf( str+ii+2 , "%u" , &val ) ;
+           str[jj] = (char) val ; ii = kk ; nn++ ;
+        }
+
+        else if( ii+4 < ll        &&
+                 str[ii+1] == '#' &&
+                 str[ii+2] == 'x' &&
+                 isxdigit(str[ii+3]) ){   /* &#hex; */
+
+           unsigned int val='?' ; int kk=ii+4 ;
+           while( kk < ll && kk != ';' ) kk++ ;
+           sscanf( str+ii+3 , "%x" , &val ) ;
+           str[jj] = (char) val ; ii = kk ; nn++ ;
+        }
+
+        /* didn't start a recognized escape, so just copy as normal */
+
+        else if( jj < ii ){ str[jj] = str[ii] ; }
+
+     } else if( str[ii] == CR ) {  /* is a carriage return */
+
+        if( str[ii+1] == LF ){ str[jj] = LF ; ii++ ; nn++ ; }  /* CR LF */
+        else                 { str[jj] = LF ;      ; nn++ ; }  /* CR only */
+
+     } else { /* is a normal character, just copy to output */
+
+             if( jj < ii ){ str[jj] = str[ii] ; }
+     }
+
+     /* at this point, ii=index of last character used up in scan
+                       jj=index of last character written to (jj <= ii) */
+   }
+
+   if( jj < ll ) str[jj] = '\0' ; /* end string properly */
+
+   return nn ;
+}
+
+/*------------------------------------------------------------------------*/
+/* Quotize (and escapize) one string, returning a new string.
+   Approximately speaking, this is the inverse of unescape_string().
+   The result should be free()-ed when you are done with it.
+--------------------------------------------------------------------------*/
+
+static char *escapize_string( const char * str )
+{
+   int ii,jj , lstr,lout ;
+   char *out ;
+
+   if( str == NULL || (lstr=(int)strlen(str)) == 0 ){      /* 0 length */
+     out = nifti_strdup("''") ; return out ;                /* string?? */
+   }
+
+   lout = 4 ;                      /* initialize length of output */
+   for( ii=0 ; ii < lstr ; ii++ ){ /* count characters for output */
+     switch( str[ii] ){
+       case '&':  lout += 5 ; break ;  /* replace '&' with "&" */
+
+       case '<':
+       case '>':  lout += 4 ; break ;  /* replace '<' with "<" */
+
+       case '"' :
+       case '\'': lout += 6 ; break ;  /* replace '"' with """ */
+
+       case CR:
+       case LF:   lout += 6 ; break ;  /* replace CR with "&#x0d;"
+                                                  LF with "&#x0a;" */
+
+       default: lout++ ; break ;      /* copy all other chars */
+     }
+   }
+   out = (char *)calloc(1,lout) ;     /* allocate output string */
+   if( !out ){
+      REprintf("** escapize_string: failed to alloc %d bytes\n",lout);
+      return NULL;
+   }
+   out[0] = '\'' ;                    /* opening quote mark */
+   for( ii=0,jj=1 ; ii < lstr ; ii++ ){
+      switch( str[ii] ){
+         default: out[jj++] = str[ii] ; break ;  /* normal characters */
+
+         case '&':  memcpy(out+jj,"&",5)  ; jj+=5 ; break ;
+
+         case '<':  memcpy(out+jj,"<",4)   ; jj+=4 ; break ;
+         case '>':  memcpy(out+jj,">",4)   ; jj+=4 ; break ;
+
+         case '"' : memcpy(out+jj,""",6) ; jj+=6 ; break ;
+
+         case '\'': memcpy(out+jj,"'",6) ; jj+=6 ; break ;
+
+         case CR:   memcpy(out+jj,"&#x0d;",6) ; jj+=6 ; break ;
+         case LF:   memcpy(out+jj,"&#x0a;",6) ; jj+=6 ; break ;
+      }
+   }
+   out[jj++] = '\''  ;  /* closing quote mark */
+   out[jj]   = '\0' ;  /* terminate the string */
+   return out ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Dump the information in a NIFTI image header to an XML-ish ASCII string
+   that can later be converted back into a NIFTI header in
+   nifti_image_from_ascii().
+
+   The resulting string can be free()-ed when you are done with it.
+*//*-------------------------------------------------------------------------*/
+char *nifti_image_to_ascii( const nifti_image *nim )
+{
+   char *buf , *ebuf ; int nbuf ;
+
+   if( nim == NULL ) return NULL ;   /* stupid caller */
+
+   buf = (char *)calloc(1,65534); nbuf = 0; /* longer than needed, to be safe */
+   if( !buf ){
+      REprintf("** NITA: failed to alloc %d bytes\n",65534);
+      return NULL;
+   }
+
+   sprintf( buf , "<nifti_image\n" ) ;   /* XML-ish opener */
+
+   sprintf( buf+strlen(buf) , "  nifti_type = '%s'\n" ,
+              (nim->nifti_type == NIFTI_FTYPE_NIFTI1_1) ? "NIFTI-1+"
+             :(nim->nifti_type == NIFTI_FTYPE_NIFTI1_2) ? "NIFTI-1"
+             :(nim->nifti_type == NIFTI_FTYPE_ASCII   ) ? "NIFTI-1A"
+             :                         "ANALYZE-7.5" ) ;
+
+   /** Strings that we don't control (filenames, etc.) that might
+       contain "weird" characters (like quotes) are "escaped":
+       - A few special characters are replaced by XML-style escapes, using
+         the function escapize_string().
+       - On input, function unescape_string() reverses this process.
+       - The result is that the NIFTI ASCII-format header is XML-compliant. */
+
+   ebuf = escapize_string(nim->fname) ;
+   sprintf( buf+strlen(buf) , "  header_filename = %s\n",ebuf); free(ebuf);
+
+   ebuf = escapize_string(nim->iname) ;
+   sprintf( buf+strlen(buf) , "  image_filename = %s\n", ebuf); free(ebuf);
+
+   sprintf( buf+strlen(buf) , "  image_offset = '%d'\n" , nim->iname_offset );
+
+                       sprintf( buf+strlen(buf), "  ndim = '%d'\n", nim->ndim);
+                       sprintf( buf+strlen(buf), "  nx = '%d'\n",   nim->nx  );
+   if( nim->ndim > 1 ) sprintf( buf+strlen(buf), "  ny = '%d'\n",   nim->ny  );
+   if( nim->ndim > 2 ) sprintf( buf+strlen(buf), "  nz = '%d'\n",   nim->nz  );
+   if( nim->ndim > 3 ) sprintf( buf+strlen(buf), "  nt = '%d'\n",   nim->nt  );
+   if( nim->ndim > 4 ) sprintf( buf+strlen(buf), "  nu = '%d'\n",   nim->nu  );
+   if( nim->ndim > 5 ) sprintf( buf+strlen(buf), "  nv = '%d'\n",   nim->nv  );
+   if( nim->ndim > 6 ) sprintf( buf+strlen(buf), "  nw = '%d'\n",   nim->nw  );
+                       sprintf( buf+strlen(buf), "  dx = '%g'\n",   nim->dx  );
+   if( nim->ndim > 1 ) sprintf( buf+strlen(buf), "  dy = '%g'\n",   nim->dy  );
+   if( nim->ndim > 2 ) sprintf( buf+strlen(buf), "  dz = '%g'\n",   nim->dz  );
+   if( nim->ndim > 3 ) sprintf( buf+strlen(buf), "  dt = '%g'\n",   nim->dt  );
+   if( nim->ndim > 4 ) sprintf( buf+strlen(buf), "  du = '%g'\n",   nim->du  );
+   if( nim->ndim > 5 ) sprintf( buf+strlen(buf), "  dv = '%g'\n",   nim->dv  );
+   if( nim->ndim > 6 ) sprintf( buf+strlen(buf), "  dw = '%g'\n",   nim->dw  );
+
+   sprintf( buf+strlen(buf) , "  datatype = '%d'\n" , nim->datatype ) ;
+   sprintf( buf+strlen(buf) , "  datatype_name = '%s'\n" ,
+                              nifti_datatype_string(nim->datatype) ) ;
+
+   sprintf( buf+strlen(buf) , "  nvox = '%u'\n" , (unsigned)nim->nvox ) ;
+   sprintf( buf+strlen(buf) , "  nbyper = '%d'\n" , nim->nbyper ) ;
+
+   sprintf( buf+strlen(buf) , "  byteorder = '%s'\n" ,
+            (nim->byteorder==MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" ) ;
+
+   if( nim->cal_min < nim->cal_max ){
+     sprintf( buf+strlen(buf) , "  cal_min = '%g'\n", nim->cal_min ) ;
+     sprintf( buf+strlen(buf) , "  cal_max = '%g'\n", nim->cal_max ) ;
+   }
+
+   if( nim->scl_slope != 0.0 ){
+     sprintf( buf+strlen(buf) , "  scl_slope = '%g'\n" , nim->scl_slope ) ;
+     sprintf( buf+strlen(buf) , "  scl_inter = '%g'\n" , nim->scl_inter ) ;
+   }
+
+   if( nim->intent_code > 0 ){
+     sprintf( buf+strlen(buf) , "  intent_code = '%d'\n", nim->intent_code ) ;
+     sprintf( buf+strlen(buf) , "  intent_code_name = '%s'\n" ,
+                                nifti_intent_string(nim->intent_code) ) ;
+     sprintf( buf+strlen(buf) , "  intent_p1 = '%g'\n" , nim->intent_p1 ) ;
+     sprintf( buf+strlen(buf) , "  intent_p2 = '%g'\n" , nim->intent_p2 ) ;
+     sprintf( buf+strlen(buf) , "  intent_p3 = '%g'\n" , nim->intent_p3 ) ;
+
+     if( nim->intent_name[0] != '\0' ){
+       ebuf = escapize_string(nim->intent_name) ;
+       sprintf( buf+strlen(buf) , "  intent_name = %s\n",ebuf) ;
+       free(ebuf) ;
+     }
+   }
+
+   if( nim->toffset != 0.0 )
+     sprintf( buf+strlen(buf) , "  toffset = '%g'\n",nim->toffset ) ;
+
+   if( nim->xyz_units > 0 )
+     sprintf( buf+strlen(buf) ,
+              "  xyz_units = '%d'\n"
+              "  xyz_units_name = '%s'\n" ,
+              nim->xyz_units , nifti_units_string(nim->xyz_units) ) ;
+
+   if( nim->time_units > 0 )
+     sprintf( buf+strlen(buf) ,
+              "  time_units = '%d'\n"
+              "  time_units_name = '%s'\n" ,
+              nim->time_units , nifti_units_string(nim->time_units) ) ;
+
+   if( nim->freq_dim > 0 )
+     sprintf( buf+strlen(buf) , "  freq_dim = '%d'\n",nim->freq_dim ) ;
+   if( nim->phase_dim > 0 )
+     sprintf( buf+strlen(buf) , "  phase_dim = '%d'\n",nim->phase_dim ) ;
+   if( nim->slice_dim > 0 )
+     sprintf( buf+strlen(buf) , "  slice_dim = '%d'\n",nim->slice_dim ) ;
+   if( nim->slice_code > 0 )
+     sprintf( buf+strlen(buf) ,
+              "  slice_code = '%d'\n"
+              "  slice_code_name = '%s'\n" ,
+              nim->slice_code , nifti_slice_string(nim->slice_code) ) ;
+   if( nim->slice_start >= 0 && nim->slice_end > nim->slice_start )
+     sprintf( buf+strlen(buf) ,
+              "  slice_start = '%d'\n"
+              "  slice_end = '%d'\n"  , nim->slice_start , nim->slice_end ) ;
+   if( nim->slice_duration != 0.0 )
+     sprintf( buf+strlen(buf) , "  slice_duration = '%g'\n",
+              nim->slice_duration ) ;
+
+   if( nim->descrip[0] != '\0' ){
+     ebuf = escapize_string(nim->descrip) ;
+     sprintf( buf+strlen(buf) , "  descrip = %s\n",ebuf) ;
+     free(ebuf) ;
+   }
+
+   if( nim->aux_file[0] != '\0' ){
+     ebuf = escapize_string(nim->aux_file) ;
+     sprintf( buf+strlen(buf) , "  aux_file = %s\n",ebuf) ;
+     free(ebuf) ;
+   }
+
+   if( nim->qform_code > 0 ){
+     int i,j,k ;
+
+     sprintf( buf+strlen(buf) ,
+              "  qform_code = '%d'\n"
+              "  qform_code_name = '%s'\n"
+     "  qto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->qform_code      , nifti_xform_string(nim->qform_code) ,
+         nim->qto_xyz.m[0][0] , nim->qto_xyz.m[0][1] ,
+         nim->qto_xyz.m[0][2] , nim->qto_xyz.m[0][3] ,
+         nim->qto_xyz.m[1][0] , nim->qto_xyz.m[1][1] ,
+         nim->qto_xyz.m[1][2] , nim->qto_xyz.m[1][3] ,
+         nim->qto_xyz.m[2][0] , nim->qto_xyz.m[2][1] ,
+         nim->qto_xyz.m[2][2] , nim->qto_xyz.m[2][3] ,
+         nim->qto_xyz.m[3][0] , nim->qto_xyz.m[3][1] ,
+         nim->qto_xyz.m[3][2] , nim->qto_xyz.m[3][3]  ) ;
+
+     sprintf( buf+strlen(buf) ,
+     "  qto_ijk_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->qto_ijk.m[0][0] , nim->qto_ijk.m[0][1] ,
+         nim->qto_ijk.m[0][2] , nim->qto_ijk.m[0][3] ,
+         nim->qto_ijk.m[1][0] , nim->qto_ijk.m[1][1] ,
+         nim->qto_ijk.m[1][2] , nim->qto_ijk.m[1][3] ,
+         nim->qto_ijk.m[2][0] , nim->qto_ijk.m[2][1] ,
+         nim->qto_ijk.m[2][2] , nim->qto_ijk.m[2][3] ,
+         nim->qto_ijk.m[3][0] , nim->qto_ijk.m[3][1] ,
+         nim->qto_ijk.m[3][2] , nim->qto_ijk.m[3][3]  ) ;
+
+     sprintf( buf+strlen(buf) ,
+              "  quatern_b = '%g'\n"
+              "  quatern_c = '%g'\n"
+              "  quatern_d = '%g'\n"
+              "  qoffset_x = '%g'\n"
+              "  qoffset_y = '%g'\n"
+              "  qoffset_z = '%g'\n"
+              "  qfac = '%g'\n" ,
+         nim->quatern_b , nim->quatern_c , nim->quatern_d ,
+         nim->qoffset_x , nim->qoffset_y , nim->qoffset_z , nim->qfac ) ;
+
+     nifti_mat44_to_orientation( nim->qto_xyz , &i,&j,&k ) ;
+     if( i > 0 && j > 0 && k > 0 )
+       sprintf( buf+strlen(buf) ,
+                "  qform_i_orientation = '%s'\n"
+                "  qform_j_orientation = '%s'\n"
+                "  qform_k_orientation = '%s'\n" ,
+                nifti_orientation_string(i) ,
+                nifti_orientation_string(j) ,
+                nifti_orientation_string(k)  ) ;
+   }
+
+   if( nim->sform_code > 0 ){
+     int i,j,k ;
+
+     sprintf( buf+strlen(buf) ,
+              "  sform_code = '%d'\n"
+              "  sform_code_name = '%s'\n"
+     "  sto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->sform_code      , nifti_xform_string(nim->sform_code) ,
+         nim->sto_xyz.m[0][0] , nim->sto_xyz.m[0][1] ,
+         nim->sto_xyz.m[0][2] , nim->sto_xyz.m[0][3] ,
+         nim->sto_xyz.m[1][0] , nim->sto_xyz.m[1][1] ,
+         nim->sto_xyz.m[1][2] , nim->sto_xyz.m[1][3] ,
+         nim->sto_xyz.m[2][0] , nim->sto_xyz.m[2][1] ,
+         nim->sto_xyz.m[2][2] , nim->sto_xyz.m[2][3] ,
+         nim->sto_xyz.m[3][0] , nim->sto_xyz.m[3][1] ,
+         nim->sto_xyz.m[3][2] , nim->sto_xyz.m[3][3]  ) ;
+
+     sprintf( buf+strlen(buf) ,
+     "  sto_ijk matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->sto_ijk.m[0][0] , nim->sto_ijk.m[0][1] ,
+         nim->sto_ijk.m[0][2] , nim->sto_ijk.m[0][3] ,
+         nim->sto_ijk.m[1][0] , nim->sto_ijk.m[1][1] ,
+         nim->sto_ijk.m[1][2] , nim->sto_ijk.m[1][3] ,
+         nim->sto_ijk.m[2][0] , nim->sto_ijk.m[2][1] ,
+         nim->sto_ijk.m[2][2] , nim->sto_ijk.m[2][3] ,
+         nim->sto_ijk.m[3][0] , nim->sto_ijk.m[3][1] ,
+         nim->sto_ijk.m[3][2] , nim->sto_ijk.m[3][3]  ) ;
+
+     nifti_mat44_to_orientation( nim->sto_xyz , &i,&j,&k ) ;
+     if( i > 0 && j > 0 && k > 0 )
+       sprintf( buf+strlen(buf) ,
+                "  sform_i_orientation = '%s'\n"
+                "  sform_j_orientation = '%s'\n"
+                "  sform_k_orientation = '%s'\n" ,
+                nifti_orientation_string(i) ,
+                nifti_orientation_string(j) ,
+                nifti_orientation_string(k)  ) ;
+   }
+
+   sprintf( buf+strlen(buf) , "  num_ext = '%d'\n", nim->num_ext ) ;
+
+   sprintf( buf+strlen(buf) , "/>\n" ) ;   /* XML-ish closer */
+
+   nbuf = (int)strlen(buf) ;
+   buf  = (char *)realloc((void *)buf, nbuf+1); /* cut back to proper length */
+   if( !buf ) REprintf("** NITA: failed to realloc %d bytes\n",nbuf+1);
+   return buf ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/*! get the byte order for this CPU
+
+    - LSB_FIRST means least significant byte, first (little endian)
+    - MSB_FIRST means most significant byte, first (big endian)
+*//*--------------------------------------------------------------------*/
+int nifti_short_order(void)   /* determine this CPU's byte order */
+{
+   union { unsigned char bb[2] ;
+           short         ss    ; } fred ;
+
+   fred.bb[0] = 1 ; fred.bb[1] = 0 ;
+
+   return (fred.ss == 1) ? LSB_FIRST : MSB_FIRST ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#undef  QQNUM
+#undef  QNUM
+#undef  QSTR
+
+/* macro to check lhs string against "n1"; if it matches,
+   interpret rhs string as a number, and put it into nim->"n2" */
+
+#define QQNUM(n1,n2) if( strcmp(lhs,#n1)==0 ) nim->n2=strtod(rhs,NULL)
+
+/* same, but where "n1" == "n2" */
+
+#define QNUM(nam)    QQNUM(nam,nam)
+
+/* macro to check lhs string against "nam"; if it matches,
+   put rhs string into nim->"nam" string, with max length = "ml" */
+
+#define QSTR(nam,ml) if( strcmp(lhs,#nam) == 0 )                           \
+                       strncpy(nim->nam,rhs,ml), nim->nam[ml]='\0'
+
+/*---------------------------------------------------------------------------*/
+/*! Take an XML-ish ASCII string and create a NIFTI image header to match.
+
+    NULL is returned if enough information isn't present in the input string.
+    - The image data can later be loaded with nifti_image_load().
+    - The struct returned here can be liberated with nifti_image_free().
+    - Not a lot of error checking is done here to make sure that the
+      input values are reasonable!
+*//*-------------------------------------------------------------------------*/
+nifti_image *nifti_image_from_ascii( const char *str, int * bytes_read )
+{
+   char lhs[1024] , rhs[1024] ;
+   int ii , spos, nn , slen ;
+   nifti_image *nim ;              /* will be output */
+
+   if( str == NULL || *str == '\0' ) return NULL ;  /* bad input!? */
+
+   /* scan for opening string */
+
+   spos = 0 ; slen = (int)strlen(str) ;
+   ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ;
+   if( ii == 0 || strcmp(lhs,"<nifti_image") != 0 ) return NULL ;
+
+   /* create empty image struct */
+
+   nim = (nifti_image *)calloc( 1 , sizeof(nifti_image) ) ;
+   if( !nim ){
+      REprintf("** NIFA: failed to alloc nifti_image\n");
+      return NULL;
+   }
+
+   nim->nx = nim->ny = nim->nz = nim->nt
+           = nim->nu = nim->nv = nim->nw = 1 ;
+   nim->dx = nim->dy = nim->dz = nim->dt
+           = nim->du = nim->dv = nim->dw = 0 ;
+   nim->qfac = 1.0 ;
+
+   nim->byteorder = nifti_short_order() ;
+
+   /* starting at str[spos], scan for "equations" of the form
+         lhs = 'rhs'
+      and assign rhs values into the struct component named by lhs */
+
+   while(1){
+
+     while( isspace((int) str[spos]) ) spos++ ;  /* skip whitespace */
+     if( str[spos] == '\0' ) break ;       /* end of string? */
+
+     /* get lhs string */
+
+     ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ;
+     if( ii == 0 || strcmp(lhs,"/>") == 0 ) break ;  /* end of input? */
+
+     /* skip whitespace and the '=' marker */
+
+     while( isspace((int) str[spos]) || str[spos] == '=' ) spos++ ;
+     if( str[spos] == '\0' ) break ;       /* end of string? */
+
+     /* if next character is a quote ', copy everything up to next '
+        otherwise, copy everything up to next nonblank              */
+
+     if( str[spos] == '\'' ){
+        ii = spos+1 ;
+        while( str[ii] != '\0' && str[ii] != '\'' ) ii++ ;
+        nn = ii-spos-1 ; if( nn > 1023 ) nn = 1023 ;
+        memcpy(rhs,str+spos+1,nn) ; rhs[nn] = '\0' ;
+        spos = (str[ii] == '\'') ? ii+1 : ii ;
+     } else {
+        ii = sscanf( str+spos , "%1023s%n" , rhs , &nn ) ; spos += nn ;
+        if( ii == 0 ) break ;  /* nothing found? */
+     }
+     unescape_string(rhs) ;  /* remove any XML escape sequences */
+
+     /* Now can do the assignment, based on lhs string.
+        Start with special cases that don't fit the QNUM/QSTR macros. */
+
+     if( strcmp(lhs,"nifti_type") == 0 ){
+            if( strcmp(rhs,"ANALYZE-7.5") == 0 )
+               nim->nifti_type = NIFTI_FTYPE_ANALYZE ;
+       else if( strcmp(rhs,"NIFTI-1+")    == 0 )
+               nim->nifti_type = NIFTI_FTYPE_NIFTI1_1 ;
+       else if( strcmp(rhs,"NIFTI-1")     == 0 )
+               nim->nifti_type = NIFTI_FTYPE_NIFTI1_2 ;
+       else if( strcmp(rhs,"NIFTI-1A")    == 0 )
+               nim->nifti_type = NIFTI_FTYPE_ASCII ;
+     }
+     else if( strcmp(lhs,"header_filename") == 0 ){
+       nim->fname = nifti_strdup(rhs) ;
+     }
+     else if( strcmp(lhs,"image_filename") == 0 ){
+       nim->iname = nifti_strdup(rhs) ;
+     }
+     else if( strcmp(lhs,"sto_xyz_matrix") == 0 ){
+       sscanf( rhs , "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f" ,
+               &(nim->sto_xyz.m[0][0]) , &(nim->sto_xyz.m[0][1]) ,
+               &(nim->sto_xyz.m[0][2]) , &(nim->sto_xyz.m[0][3]) ,
+               &(nim->sto_xyz.m[1][0]) , &(nim->sto_xyz.m[1][1]) ,
+               &(nim->sto_xyz.m[1][2]) , &(nim->sto_xyz.m[1][3]) ,
+               &(nim->sto_xyz.m[2][0]) , &(nim->sto_xyz.m[2][1]) ,
+               &(nim->sto_xyz.m[2][2]) , &(nim->sto_xyz.m[2][3]) ,
+               &(nim->sto_xyz.m[3][0]) , &(nim->sto_xyz.m[3][1]) ,
+               &(nim->sto_xyz.m[3][2]) , &(nim->sto_xyz.m[3][3])  ) ;
+     }
+     else if( strcmp(lhs,"byteorder") == 0 ){
+       if( strcmp(rhs,"MSB_FIRST") == 0 ) nim->byteorder = MSB_FIRST ;
+       if( strcmp(rhs,"LSB_FIRST") == 0 ) nim->byteorder = LSB_FIRST ;
+     }
+     else QQNUM(image_offset,iname_offset) ;
+     else QNUM(datatype) ;
+     else QNUM(ndim) ;
+     else QNUM(nx) ;
+     else QNUM(ny) ;
+     else QNUM(nz) ;
+     else QNUM(nt) ;
+     else QNUM(nu) ;
+     else QNUM(nv) ;
+     else QNUM(nw) ;
+     else QNUM(dx) ;
+     else QNUM(dy) ;
+     else QNUM(dz) ;
+     else QNUM(dt) ;
+     else QNUM(du) ;
+     else QNUM(dv) ;
+     else QNUM(dw) ;
+     else QNUM(cal_min) ;
+     else QNUM(cal_max) ;
+     else QNUM(scl_slope) ;
+     else QNUM(scl_inter) ;
+     else QNUM(intent_code) ;
+     else QNUM(intent_p1) ;
+     else QNUM(intent_p2) ;
+     else QNUM(intent_p3) ;
+     else QSTR(intent_name,15) ;
+     else QNUM(toffset) ;
+     else QNUM(xyz_units) ;
+     else QNUM(time_units) ;
+     else QSTR(descrip,79) ;
+     else QSTR(aux_file,23) ;
+     else QNUM(qform_code) ;
+     else QNUM(quatern_b) ;
+     else QNUM(quatern_c) ;
+     else QNUM(quatern_d) ;
+     else QNUM(qoffset_x) ;
+     else QNUM(qoffset_y) ;
+     else QNUM(qoffset_z) ;
+     else QNUM(qfac) ;
+     else QNUM(sform_code) ;
+     else QNUM(freq_dim) ;
+     else QNUM(phase_dim) ;
+     else QNUM(slice_dim) ;
+     else QNUM(slice_code) ;
+     else QNUM(slice_start) ;
+     else QNUM(slice_end) ;
+     else QNUM(slice_duration) ;
+     else QNUM(num_ext) ;
+
+   } /* end of while loop */
+
+   if( bytes_read ) *bytes_read = spos+1;         /* "process" last '\n' */
+
+   /* do miscellaneous checking and cleanup */
+
+   if( nim->ndim <= 0 ){ nifti_image_free(nim); return NULL; } /* bad! */
+
+   nifti_datatype_sizes( nim->datatype, &(nim->nbyper), &(nim->swapsize) );
+   if( nim->nbyper == 0 ){ nifti_image_free(nim); return NULL; } /* bad! */
+
+   nim->dim[0] = nim->ndim ;
+   nim->dim[1] = nim->nx ; nim->pixdim[1] = nim->dx ;
+   nim->dim[2] = nim->ny ; nim->pixdim[2] = nim->dy ;
+   nim->dim[3] = nim->nz ; nim->pixdim[3] = nim->dz ;
+   nim->dim[4] = nim->nt ; nim->pixdim[4] = nim->dt ;
+   nim->dim[5] = nim->nu ; nim->pixdim[5] = nim->du ;
+   nim->dim[6] = nim->nv ; nim->pixdim[6] = nim->dv ;
+   nim->dim[7] = nim->nw ; nim->pixdim[7] = nim->dw ;
+
+   nim->nvox = (size_t)nim->nx * nim->ny * nim->nz
+                     * nim->nt * nim->nu * nim->nv * nim->nw ;
+
+   if( nim->qform_code > 0 )
+     nim->qto_xyz = nifti_quatern_to_mat44(
+                      nim->quatern_b, nim->quatern_c, nim->quatern_d,
+                      nim->qoffset_x, nim->qoffset_y, nim->qoffset_z,
+                      nim->dx       , nim->dy       , nim->dz       ,
+                      nim->qfac                                      ) ;
+   else
+     nim->qto_xyz = nifti_quatern_to_mat44(
+                      0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ,
+                      nim->dx , nim->dy , nim->dz , 0.0 ) ;
+
+
+   nim->qto_ijk = nifti_mat44_inverse( nim->qto_xyz ) ;
+
+   if( nim->sform_code > 0 )
+     nim->sto_ijk = nifti_mat44_inverse( nim->sto_xyz ) ;
+
+   return nim ;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/*! validate the nifti_image
+
+    \return 1 if the structure seems valid, otherwise 0
+
+    \sa nifti_nim_has_valid_dims, nifti_hdr_looks_good
+*//*-------------------------------------------------------------------------*/
+int nifti_nim_is_valid(nifti_image * nim, int complain)
+{
+   int errs = 0;
+
+   if( !nim ){
+      REprintf("** is_valid_nim: nim is NULL\n");
+      return 0;
+   }
+
+   if( g_opts.debug > 2 ) REprintf("-d nim_is_valid check...\n");
+
+   /**- check that dim[] matches the individual values ndim, nx, ny, ... */
+   if( ! nifti_nim_has_valid_dims(nim,complain) ){
+      if( !complain ) return 0;
+      errs++;
+   }
+
+   /* might check nbyper, pixdim, q/sforms, swapsize, nifti_type, ... */
+
+   /**- be explicit in return of 0 or 1 */
+   if( errs > 0 ) return 0;
+   else           return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! validate nifti dimensions
+
+    \return 1 if valid, 0 if not
+
+    \sa nifti_nim_is_valid, nifti_hdr_looks_good
+
+    rely on dim[] as the master
+*//*-------------------------------------------------------------------------*/
+int nifti_nim_has_valid_dims(nifti_image * nim, int complain)
+{
+   size_t prod;
+   int    c, errs = 0;
+
+   /**- start with dim[0]: failure here is considered terminal */
+   if( nim->dim[0] <= 0 || nim->dim[0] > 7 ){
+      errs++;
+      if( complain )
+         REprintf("** NVd: dim[0] (%d) out of range [1,7]\n",nim->dim[0]);
+      return 0;
+   }
+
+   /**- check whether ndim equals dim[0] */
+   if( nim->ndim != nim->dim[0] ){
+      errs++;
+      if( ! complain ) return 0;
+      REprintf("** NVd: ndim != dim[0] (%d,%d)\n",nim->ndim,nim->dim[0]);
+   }
+
+   /**- compare each dim[i] to the proper nx, ny, ... */
+   if( ( (nim->dim[0] >= 1) && (nim->dim[1] != nim->nx) ) ||
+       ( (nim->dim[0] >= 2) && (nim->dim[2] != nim->ny) ) ||
+       ( (nim->dim[0] >= 3) && (nim->dim[3] != nim->nz) ) ||
+       ( (nim->dim[0] >= 4) && (nim->dim[4] != nim->nt) ) ||
+       ( (nim->dim[0] >= 5) && (nim->dim[5] != nim->nu) ) ||
+       ( (nim->dim[0] >= 6) && (nim->dim[6] != nim->nv) ) ||
+       ( (nim->dim[0] >= 7) && (nim->dim[7] != nim->nw) )   ){
+      errs++;
+      if( !complain ) return 0;
+      REprintf("** NVd mismatch: dims    = %d,%d,%d,%d,%d,%d,%d\n"
+                     "                 nxyz... = %d,%d,%d,%d,%d,%d,%d\n",
+                     nim->dim[1], nim->dim[2], nim->dim[3],
+                     nim->dim[4], nim->dim[5], nim->dim[6], nim->dim[7],
+                     nim->nx, nim->ny, nim->nz,
+                     nim->nt, nim->nu, nim->nv, nim->nw );
+   }
+
+   if( g_opts.debug > 2 ){
+      REprintf("-d check dim[%d] =", nim->dim[0]);
+      for( c = 0; c < 7; c++ ) REprintf(" %d", nim->dim[c]);
+      REprintf("\n"); /*fputc('\n', stderr);*/
+   }
+
+   /**- check the dimensions, and that their product matches nvox */
+   prod = 1;
+   for( c = 1; c <= nim->dim[0]; c++ ){
+      if( nim->dim[c] > 0)
+         prod *= nim->dim[c];
+      else if( nim->dim[c] <= 0 ){
+         if( !complain ) return 0;
+         REprintf("** NVd: dim[%d] (=%d) <= 0\n",c, nim->dim[c]);
+         errs++;
+      }
+   }
+   if( prod != nim->nvox ){
+      if( ! complain ) return 0;
+      REprintf("** NVd: nvox does not match %d-dim product (%u, %u)\n",
+              nim->dim[0], (unsigned)nim->nvox, (unsigned)prod);
+      errs++;
+   }
+
+   /**- if debug, warn about any remaining dim that is neither 0, nor 1 */
+   /*   (values in dims above dim[0] are undefined, as reminded by Cinly
+         Ooi and Alle Meije Wink)                   16 Nov 2005 [rickr] */
+   if( g_opts.debug > 1 )
+      for( c = nim->dim[0]+1; c <= 7; c++ )
+         if( nim->dim[c] != 0 && nim->dim[c] != 1 )
+            REprintf("** NVd warning: dim[%d] = %d, but ndim = %d\n",
+                    c, nim->dim[c], nim->dim[0]);
+
+   if( g_opts.debug > 2 )
+      REprintf("-d nim_has_valid_dims check, errs = %d\n", errs);
+
+   /**- return invalid or valid */
+   if( errs > 0 ) return 0;
+   else           return 1;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/*! read a nifti image, collapsed across dimensions according to dims[8]  <pre>
+
+    This function may be used to read parts of a nifti dataset, such as
+    the time series for a single voxel, or perhaps a slice.  It is similar
+    to nifti_image_load(), though the passed 'data' parameter is used for
+    returning the image, not nim->data.
+
+    \param nim  given nifti_image struct, corresponding to the data file
+    \param dims given list of dimensions (see below)
+    \param data pointer to data pointer (if *data is NULL, data will be
+                allocated, otherwise not)
+
+    Here, dims is an array of 8 ints, similar to nim->dim[8].  While dims[0]
+    is unused at this point, the other indices specify which dimensions to
+    collapse (and at which index), and which not to collapse.  If dims[i] is
+    set to -1, then that entire dimension will be read in, from index 0 to
+    index (nim->dim[i] - 1).  If dims[i] >= 0, then only that index will be
+    read in (so dims[i] must also be < nim->dim[i]).
+
+    Example: given  nim->dim[8] = { 4, 64, 64, 21, 80, 1, 1, 1 } (4-D dataset)
+
+      if dims[8] = { 0,  5,  4, 17, -1, -1, -1, -1 }
+         -> read time series for voxel i,j,k = 5,4,17
+
+      if dims[8] = { 0, -1, -1, -1, 17, -1, -1, -1 }
+         -> read single volume at time point 17
+
+    Example: given  nim->dim[8] = { 6, 64, 64, 21, 80, 4, 3, 1 } (6-D dataset)
+
+      if dims[8] = { 0, 5, 4, 17, -1, 2, 1, 0 }
+         -> read time series for the voxel i,j,k = 5,4,17, and dim 5,6 = 2,1
+
+      if dims[8] = { 0, 5, 4, -1, -1, 0, 0, 0 }
+         -> read time series for slice at i,j = 5,4, and dim 5,6,7 = 0,0,0
+            (note that dims[7] is not relevant, but must be 0 or -1)
+
+    If *data is NULL, then *data will be set as a pointer to new memory,
+    allocated here for the resulting collapsed image data.
+
+      e.g. { int    dims[8] = { 0,  5,  4, 17, -1, -1, -1, -1 };
+             void * data    = NULL;
+             ret_val = nifti_read_collapsed_image(nim, dims, &data);
+             if( ret_val > 0 ){
+                process_time_series(data);
+                if( data != NULL ) free(data);
+             }
+           }
+
+    NOTE: If *data is not NULL, then it will be assumed that it points to
+          valid memory, sufficient to hold the results.  This is done for
+          speed and possibly repeated calls to this function.
+
+      e.g. { int    dims[8] = { 0,  -1, -1, -1, -1, -1, -1, -1 };
+             void * data    = NULL;
+             for( zslice = 0; zslice < nzslices; zslice++ ){
+                dims[3] = zslice;
+                ret_val = nifti_read_collapsed_image(nim, dims, &data);
+                if( ret_val > 0 ) process_slice(zslice, data);
+             }
+             if( data != NULL ) free(data);
+           }
+
+    \return
+        -  the total number of bytes read, or < 0 on failure
+        -  the read and byte-swapped data, in 'data'            </pre>
+
+    \sa nifti_image_read, nifti_image_free, nifti_image_read_bricks
+        nifti_image_load
+*//*-------------------------------------------------------------------------*/
+int nifti_read_collapsed_image( nifti_image * nim, const int dims [8],
+                                void ** data )
+{
+   znzFile fp;
+   int     pivots[8], prods[8], nprods; /* sizes are bounded by dims[], so 8 */
+   int     c, bytes;
+
+   /** - check pointers for sanity */
+   if( !nim || !dims || !data ){
+      REprintf("** nifti_RCI: bad params %p, %p, %p\n",
+              (void *)nim, (void *)dims, (void *)data);
+      return -1;
+   }
+
+   if( g_opts.debug > 2 ){
+      REprintf("-d read_collapsed_image:\n        dims =");
+      for(c = 0; c < 8; c++) REprintf(" %3d", dims[c]);
+      REprintf("\n   nim->dims =");
+      for(c = 0; c < 8; c++) REprintf(" %3d", nim->dim[c]);
+      REprintf("\n"); /*fputc('\n', stderr);*/
+   }
+
+   /** - verify that dim[] makes sense */
+   if( ! nifti_nim_is_valid(nim, g_opts.debug > 0) ){
+      REprintf("** invalid nim (file is '%s')\n", nim->fname );
+      return -1;
+   }
+
+   /** - verify that dims[] makes sense for this dataset */
+   for( c = 1; c <= nim->dim[0]; c++ ){
+      if( dims[c] >= nim->dim[c] ){
+         REprintf("** nifti_RCI: dims[%d] >= nim->dim[%d] (%d,%d)\n",
+                 c, c, dims[c], nim->dim[c]);
+         return -1;
+      }
+   }
+
+   /** - prepare pivot list - pivots are fixed indices */
+   if( make_pivot_list(nim, dims, pivots, prods, &nprods) < 0 ) return -1;
+
+   bytes = rci_alloc_mem(data, prods, nprods, nim->nbyper);
+   if( bytes < 0 ) return -1;
+
+   /** - open the image file for reading at the appropriate offset */
+   fp = nifti_image_load_prep( nim );
+   if( ! fp ){ free(*data);  *data = NULL;  return -1; }     /* failure */
+
+   /** - call the recursive reading function, passing nim, the pivot info,
+         location to store memory, and file pointer and position */
+   c = rci_read_data(nim, pivots,prods,nprods,dims,
+                     (char *)*data, fp, znztell(fp));
+   znzclose(fp);   /* in any case, close the file */
+   if( c < 0 ){ free(*data);  *data = NULL;  return -1; }    /* failure */
+
+   if( g_opts.debug > 1 )
+      REprintf("+d read %d bytes of collapsed image from %s\n",
+              bytes, nim->fname);
+
+   return bytes;
+}
+
+
+/* local function to find strides per dimension. assumes 7D size and
+** stride array.
+*/
+static void
+compute_strides(int *strides,const int *size,int nbyper)
+{
+  int i;
+  strides[0] = nbyper;
+  for(i = 1; i < 7; i++)
+    {
+    strides[i] = size[i-1] * strides[i-1];
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+/*! read an arbitrary subregion from a nifti image
+
+    This function may be used to read a single arbitary subregion of any
+    rectangular size from a nifti dataset, such as a small 5x5x5 subregion
+    around the center of a 3D image.
+
+    \param nim  given nifti_image struct, corresponding to the data file
+    \param start_index the index location of the first voxel that will be returned
+    \param region_size the size of the subregion to be returned
+    \param data pointer to data pointer (if *data is NULL, data will be
+                allocated, otherwise not)
+
+    Example: given  nim->dim[8] = {3, 64, 64, 64, 1, 1, 1, 1 } (3-D dataset)
+
+      if start_index[7] = { 29,  29, 29, 0, 0, 0, 0 } and
+         region_size[7] = {  5,   5,  5, 1, 1, 1, 1 }
+         -> read 5x5x5 region starting with the first voxel location at (29,29,29)
+
+    NOTE: If *data is not NULL, then it will be assumed that it points to
+          valid memory, sufficient to hold the results.  This is done for
+          speed and possibly repeated calls to this function.
+    \return
+        -  the total number of bytes read, or < 0 on failure
+        -  the read and byte-swapped data, in 'data'            </pre>
+
+    \sa nifti_image_read, nifti_image_free, nifti_image_read_bricks
+        nifti_image_load, nifti_read_collapsed_image
+*//*-------------------------------------------------------------------------*/
+int nifti_read_subregion_image( nifti_image * nim,
+                                int *start_index,
+                                int *region_size,
+                                void ** data )
+{
+  znzFile fp;                   /* file to read */
+  int i,j,k,l,m,n;              /* indices for dims */
+  long int bytes = 0;           /* total # bytes read */
+  int total_alloc_size;         /* size of buffer allocation */
+  char *readptr;                /* where in *data to read next */
+  int strides[7];               /* strides between dimensions */
+  int collapsed_dims[8];        /* for read_collapsed_image */
+  int *image_size;              /* pointer to dimensions in header */
+  long int initial_offset;
+  long int offset;              /* seek offset for reading current row */
+
+  /* probably ignored, but set to ndim for consistency*/
+  collapsed_dims[0] = nim->ndim;
+
+  /* build a dims array for collapsed image read */
+  for(i = 0; i < nim->ndim; i++)
+    {
+    /* if you take the whole extent in this dimension */
+    if(start_index[i] == 0 &&
+       region_size[i] == nim->dim[i+1])
+      {
+      collapsed_dims[i+1] = -1;
+      }
+    /* if you specify a single element in this dimension */
+    else if(region_size[i] == 1)
+      {
+      collapsed_dims[i+1] = start_index[i];
+      }
+    else
+      {
+      collapsed_dims[i+1] = -2; /* sentinel value */
+      }
+    }
+  /* fill out end of collapsed_dims */
+  for(i = nim->ndim ; i < 7; i++)
+    {
+    collapsed_dims[i+1] = -1;
+    }
+
+  /* check to see whether collapsed read is possible */
+  for(i = 1; i <= nim->ndim; i++)
+    {
+    if(collapsed_dims[i] == -2)
+      {
+      break;
+      }
+    }
+
+  /* if you get through all the dimensions without hitting 
+  ** a subrange of size > 1, a collapsed read is possible
+  */
+  if(i > nim->ndim)
+    {
+    return nifti_read_collapsed_image(nim, collapsed_dims, data);
+    }
+
+  /* point past first element of dim, which holds nim->ndim */
+  image_size = &(nim->dim[1]);
+
+  /* check region sizes for sanity */
+  for(i = 0; i < nim->ndim; i++)
+    {
+    if(start_index[i]  + region_size[i] > image_size[i])
+      {
+      if(g_opts.debug > 1)
+        {
+        REprintf("region doesn't fit within image size\n");
+        }
+      return -1;
+      }
+    }
+
+  /* get the file open */
+  fp = nifti_image_load_prep( nim );
+  /* the current offset is just past the nifti header, save
+   * location so that SEEK_SET can be used below
+   */
+  initial_offset = znztell(fp);  
+  /* get strides*/
+  compute_strides(strides,image_size,nim->nbyper);
+
+  total_alloc_size = nim->nbyper; /* size of pixel */
+
+  /* find alloc size */
+  for(i = 0; i < nim->ndim; i++)
+    {
+    total_alloc_size *= region_size[i];
+    }
+  /* allocate buffer, if necessary */
+  if(*data == 0)
+    {
+    *data = (void *)malloc(total_alloc_size);
+    }
+
+  if(*data == 0)
+    {
+    if(g_opts.debug > 1)
+      {
+      REprintf("allocation of %d bytes failed\n",total_alloc_size);
+      return -1;
+      }
+    }
+
+  /* point to start of data buffer as char * */
+  readptr = *((char **)data);
+  {
+  /* can't assume that start_index and region_size have any more than
+  ** nim->ndim elements so make local copies, filled out to seven elements
+  */
+  int si[7], rs[7];
+  for(i = 0; i < nim->ndim; i++)
+    {
+    si[i] = start_index[i];
+    rs[i] = region_size[i];
+    }
+  for(i = nim->ndim; i < 7; i++)
+    {
+    si[i] = 0;
+    rs[i] = 1;
+    }
+  /* loop through subregion and read a row at a time */
+  for(i = si[6]; i < (si[6] + rs[6]); i++)
+    {
+    for(j = si[5]; j < (si[5] + rs[5]); j++)
+      {
+      for(k = si[4]; k < (si[4] + rs[4]); k++)
+        {
+        for(l = si[3]; l < (si[3] + rs[3]); l++)
+          {
+          for(m = si[2]; m < (si[2] + rs[2]); m++)
+            {
+            for(n = si[1]; n < (si[1] + rs[1]); n++)
+              {
+              int nread,read_amount;
+              offset = initial_offset +
+                (i * strides[6]) +
+                (j * strides[5]) +
+                (k * strides[4]) +
+                (l * strides[3]) +
+                (m * strides[2]) +
+                (n * strides[1]) +
+                (si[0] * strides[0]);
+              znzseek(fp, offset, SEEK_SET); /* seek to current row */
+              read_amount = rs[0] * nim->nbyper; /* read a row of the subregion*/
+              nread = (int)nifti_read_buffer(fp, readptr, read_amount, nim);
+              if(nread != read_amount)
+                {
+                if(g_opts.debug > 1)
+                  {
+                  REprintf("read of %d bytes failed\n",read_amount);
+                  return -1;
+                  }
+                }
+              bytes += nread;
+              readptr += read_amount;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  return bytes;
+}
+
+
+/* read the data from the file pointed to by fp
+
+   - this a recursive function, so start with the base case
+   - data is now (char *) for easy incrementing
+
+   return 0 on success, < 0 on failure
+*/
+static int rci_read_data(nifti_image * nim, int * pivots, int * prods,
+      int nprods, const int dims[], char * data, znzFile fp, size_t base_offset)
+{
+   size_t sublen, offset, read_size;
+   int    c;
+
+   /* bad check first - base_offset may not have been checked */
+   if( nprods <= 0 ){
+      REprintf("** rci_read_data, bad prods, %d\n", nprods);
+      return -1;
+   }
+
+   /* base case: actually read the data */
+   if( nprods == 1 ){
+      size_t nread, bytes;
+
+      /* make sure things look good here */
+      if( *pivots != 0 ){
+         REprintf("** rciRD: final pivot == %d!\n", *pivots);
+         return -1;
+      }
+
+      /* so just seek and read (prods[0] * nbyper) bytes from the file */
+      znzseek(fp, (long)base_offset, SEEK_SET);
+      bytes = (size_t)prods[0] * nim->nbyper;
+      nread = nifti_read_buffer(fp, data, bytes, nim);
+      if( nread != bytes ){
+         REprintf("** rciRD: read only %u of %u bytes from '%s'\n",
+                 (unsigned)nread, (unsigned)bytes, nim->fname);
+         return -1;
+      } else if( g_opts.debug > 3 )
+         REprintf("+d successful read of %u bytes at offset %u\n",
+                 (unsigned)bytes, (unsigned)base_offset);
+
+      return 0;  /* done with base case - return success */
+   }
+
+   /* not the base case, so do a set of reduced reads */
+
+   /* compute size of sub-brick: all dimensions below pivot */
+   for( c = 1, sublen = 1; c < *pivots; c++ ) sublen *= nim->dim[c];
+
+   /* compute number of values to read, i.e. remaining prods */
+   for( c = 1, read_size = 1; c < nprods; c++ ) read_size *= prods[c];
+   read_size *= nim->nbyper;  /* and multiply by bytes per voxel */
+
+   /* now repeatedly compute offsets, and recursively read */
+   for( c = 0; c < prods[0]; c++ ){
+      /* offset is (c * sub-block size (including pivot dim))   */
+      /*         + (dims[] index into pivot sub-block)          */
+      /* the unneeded multiplication is to make this more clear */
+      offset = (size_t)c * sublen * nim->dim[*pivots] +
+               (size_t)sublen * dims[*pivots];
+      offset *= nim->nbyper;
+
+      if( g_opts.debug > 3 )
+         REprintf("-d reading %u bytes, foff %u + %u, doff %u\n",
+                 (unsigned)read_size, (unsigned)base_offset, (unsigned)offset,
+                 (unsigned)(c*read_size));
+
+      /* now read the next level down, adding this offset */
+      if( rci_read_data(nim, pivots+1, prods+1, nprods-1, dims,
+                    data + c * read_size, fp, base_offset + offset) < 0 )
+         return -1;
+   }
+
+   return 0;
+}
+
+
+/* allocate memory for all collapsed image data
+
+   If *data is already set, do not allocate, but still calculate
+   size for debug report.
+
+   return total size on success, and < 0 on failure
+*/
+static int rci_alloc_mem(void ** data, int prods[8], int nprods, int nbyper )
+{
+   int size, index;
+
+   if( nbyper < 0 || nprods < 1 || nprods > 8 ){
+      REprintf("** rci_am: bad params, %d, %d\n", nbyper, nprods);
+      return -1;
+   }
+
+   for( index = 0, size = 1; index < nprods; index++ )
+       size *= prods[index];
+
+   size *= nbyper;
+
+   if( ! *data ){   /* then allocate what is needed */
+      if( g_opts.debug > 1 )
+         REprintf("+d alloc %d (= %d x %d) bytes for collapsed image\n",
+                 size, size/nbyper, nbyper);
+
+      *data = malloc(size);   /* actually allocate the memory */
+      if( ! *data ){
+         REprintf("** rci_am: failed to alloc %d bytes for data\n", size);
+         return -1;
+      }
+   } else if( g_opts.debug > 1 )
+      REprintf("-d rci_am: *data already set, need %d (%d x %d) bytes\n",
+              size, size/nbyper, nbyper);
+
+   return size;
+}
+
+
+/* prepare a pivot list for reading
+
+   The pivot points are the indices into dims where the calling function
+   wants to collapse a dimension.  The last pivot should always be zero
+   (note that we have space for that in the lists).
+*/
+static int make_pivot_list(nifti_image * nim, const int dims[], int pivots[],
+                                              int prods[], int * nprods )
+{
+   int len, index;
+
+   len = 0;
+   index = nim->dim[0];
+   while( index > 0 ){
+      prods[len] = 1;
+      while( index > 0 && (nim->dim[index] == 1 || dims[index] == -1) ){
+         prods[len] *= nim->dim[index];
+         index--;
+      }
+      pivots[len] = index;
+      len++;
+      index--;  /* fine, let it drop out at -1 */
+   }
+
+   /* make sure to include 0 as a pivot (instead of just 1, if it is) */
+   if( pivots[len-1] != 0 ){
+      pivots[len] = 0;
+      prods[len] = 1;
+      len++;
+   }
+
+   *nprods = len;
+
+   if( g_opts.debug > 2 ){
+      REprintf("+d pivot list created, pivots :");
+      for(index = 0; index < len; index++) REprintf(" %d", pivots[index]);
+      REprintf(", prods :");
+      for(index = 0; index < len; index++) REprintf(" %d", prods[index]);
+      REprintf("\n"); /*fputc('\n',stderr);*/
+   }
+
+   return 0;
+}
+
+
+#undef ISEND
+#define ISEND(c) ( (c)==']' || (c)=='}' || (c)=='\0' )
+
+/*---------------------------------------------------------------------*/
+/*! Get an integer list in the range 0..(nvals-1), from the
+   character string str.  If we call the output pointer fred,
+   then fred[0] = number of integers in the list (> 0), and
+        fred[i] = i-th integer in the list for i=1..fred[0].
+   If on return, fred == NULL or fred[0] == 0, then something is
+   wrong, and the caller must deal with that.
+
+   Syntax of input string:
+     - initial '{' or '[' is skipped, if present
+     - ends when '}' or ']' or end of string is found
+     - contains entries separated by commas
+     - entries have one of these forms:
+       - a single number
+       - a dollar sign '$', which means nvals-1
+       - a sequence of consecutive numbers in the form "a..b" or
+         "a-b", where "a" and "b" are single numbers (or '$')
+       - a sequence of evenly spaced numbers in the form
+         "a..b(c)" or "a-b(c)", where "c" encodes the step
+     - Example:  "[2,7..4,3..9(2)]" decodes to the list
+         2 7 6 5 4 3 5 7 9
+     - entries should be in the range 0..nvals-1
+
+   (borrowed, with permission, from thd_intlist.c)
+*//*-------------------------------------------------------------------*/
+int * nifti_get_intlist( int nvals , const char * str )
+{
+   int *subv = NULL ;
+   int ii , ipos , nout , slen ;
+   int ibot,itop,istep , nused ;
+   char *cpt ;
+
+   /* Meaningless input? */
+   if( nvals < 1 ) return NULL ;
+
+   /* No selection list? */
+   if( str == NULL || str[0] == '\0' ) return NULL ;
+
+   /* skip initial '[' or '{' */
+   subv = (int *)malloc( sizeof(int) * 2 ) ;
+   if( !subv ) {
+      REprintf("** nifti_get_intlist: failed alloc of 2 ints\n");
+      return NULL;
+   }
+   subv[0] = nout = 0 ;
+
+   ipos = 0 ;
+   if( str[ipos] == '[' || str[ipos] == '{' ) ipos++ ;
+
+   if( g_opts.debug > 1 )
+      REprintf("-d making int_list (vals = %d) from '%s'\n", nvals, str);
+
+   /**- for each sub-selector until end of input... */
+
+   slen = (int)strlen(str) ;
+   while( ipos < slen && !ISEND(str[ipos]) ){
+
+     while( isspace((int) str[ipos]) ) ipos++ ;   /* skip blanks */
+      if( ISEND(str[ipos]) ) break ;         /* done */
+
+      /**- get starting value */
+
+      if( str[ipos] == '$' ){  /* special case */
+         ibot = nvals-1 ; ipos++ ;
+      } else {                 /* decode an integer */
+         ibot = strtol( str+ipos , &cpt , 10 ) ;
+         if( ibot < 0 ){
+           REprintf("** ERROR: list index %d is out of range 0..%d\n",
+                   ibot,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         if( ibot >= nvals ){
+           REprintf("** ERROR: list index %d is out of range 0..%d\n",
+                   ibot,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         nused = (cpt-(str+ipos)) ;
+         if( ibot == 0 && nused == 0 ){
+           REprintf("** ERROR: list syntax error '%s'\n",str+ipos) ;
+           free(subv) ; return NULL ;
+         }
+         ipos += nused ;
+      }
+
+      while( isspace((int) str[ipos]) ) ipos++ ;   /* skip blanks */
+
+      /**- if that's it for this sub-selector, add one value to list */
+
+      if( str[ipos] == ',' || ISEND(str[ipos]) ){
+         nout++ ;
+         subv = (int *)realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
+         if( !subv ) {
+            REprintf("** nifti_get_intlist: failed realloc of %d ints\n",
+                    nout+1);
+            return NULL;
+         }
+         subv[0]    = nout ;
+         subv[nout] = ibot ;
+         if( ISEND(str[ipos]) ) break ; /* done */
+         ipos++ ; continue ;            /* re-start loop at next sub-selector */
+      }
+
+      /**- otherwise, must have '..' or '-' as next inputs */
+
+      if( str[ipos] == '-' ){
+         ipos++ ;
+      } else if( str[ipos] == '.' && str[ipos+1] == '.' ){
+         ipos++ ; ipos++ ;
+      } else {
+         REprintf("** ERROR: index list syntax is bad: '%s'\n",
+                 str+ipos) ;
+         free(subv) ; return NULL ;
+      }
+
+      /**- get ending value for loop now */
+
+      if( str[ipos] == '$' ){  /* special case */
+         itop = nvals-1 ; ipos++ ;
+      } else {                 /* decode an integer */
+         itop = strtol( str+ipos , &cpt , 10 ) ;
+         if( itop < 0 ){
+           REprintf("** ERROR: index %d is out of range 0..%d\n",
+                   itop,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         if( itop >= nvals ){
+           REprintf("** ERROR: index %d is out of range 0..%d\n",
+                   itop,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         nused = (cpt-(str+ipos)) ;
+         if( itop == 0 && nused == 0 ){
+           REprintf("** ERROR: index list syntax error '%s'\n",str+ipos) ;
+           free(subv) ; return NULL ;
+         }
+         ipos += nused ;
+      }
+
+      /**- set default loop step */
+
+      istep = (ibot <= itop) ? 1 : -1 ;
+
+      while( isspace((int) str[ipos]) ) ipos++ ;            /* skip blanks */
+
+      /**- check if we have a non-default loop step */
+
+      if( str[ipos] == '(' ){  /* decode an integer */
+         ipos++ ;
+         istep = strtol( str+ipos , &cpt , 10 ) ;
+         if( istep == 0 ){
+           REprintf("** ERROR: index loop step is 0!\n") ;
+           free(subv) ; return NULL ;
+         }
+         nused = (cpt-(str+ipos)) ;
+         ipos += nused ;
+         if( str[ipos] == ')' ) ipos++ ;
+         if( (ibot-itop)*istep > 0 ){
+           REprintf("** WARNING: index list '%d..%d(%d)' means nothing\n",
+                   ibot,itop,istep ) ;
+         }
+      }
+
+      /**- add values to output */
+
+      for( ii=ibot ; (ii-itop)*istep <= 0 ; ii += istep ){
+         nout++ ;
+         subv = (int *)realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
+         if( !subv ) {
+            REprintf("** nifti_get_intlist: failed realloc of %d ints\n",
+                    nout+1);
+            return NULL;
+         }
+         subv[0]    = nout ;
+         subv[nout] = ii ;
+      }
+
+      /**- check if we have a comma to skip over */
+
+      while( isspace((int) str[ipos]) ) ipos++ ;            /* skip blanks */
+      if( str[ipos] == ',' ) ipos++ ;                       /* skip commas */
+
+   }  /* end of loop through selector string */
+
+   if( g_opts.debug > 1 ) {
+      REprintf("+d int_list (vals = %d): ", subv[0]);
+      for( ii = 1; ii <= subv[0]; ii++ ) REprintf("%d ", subv[ii]);
+      REprintf("\n"); /*fputc('\n',stderr);*/
+   }
+
+   if( subv[0] == 0 ){ free(subv); subv = NULL; }
+   return subv ;
+}
+
+/*---------------------------------------------------------------------*/
+/*! Given a NIFTI_TYPE string, such as "NIFTI_TYPE_INT16", return the
+ *  corresponding integral type code.  The type code is the macro
+ *  value defined in nifti1.h.
+*//*-------------------------------------------------------------------*/
+int nifti_datatype_from_string( const char * name )
+{
+    int tablen = sizeof(nifti_type_list)/sizeof(nifti_type_ele);
+    int c;
+
+    if( !name ) return DT_UNKNOWN;
+
+    for( c = tablen-1; c > 0; c-- )
+        if( !strcmp(name, nifti_type_list[c].name) )
+            break;
+
+    return nifti_type_list[c].type;
+}
+
+
+/*---------------------------------------------------------------------*/
+/*! Given a NIFTI_TYPE value, such as NIFTI_TYPE_INT16, return the
+ *  corresponding macro label as a string.  The dtype code is the
+ *  macro value defined in nifti1.h.
+*//*-------------------------------------------------------------------*/
+const char * nifti_datatype_to_string( int dtype )
+{
+    int tablen = sizeof(nifti_type_list)/sizeof(nifti_type_ele);
+    int c;
+
+    for( c = tablen-1; c > 0; c-- )
+        if( nifti_type_list[c].type == dtype )
+            break;
+
+    return nifti_type_list[c].name;
+}
+
+
+/*---------------------------------------------------------------------*/
+/*! Determine whether dtype is a valid NIFTI_TYPE.
+ *
+ *  DT_UNKNOWN is considered invalid
+ *
+ *  The only difference 'for_nifti' makes is that DT_BINARY
+ *  should be invalid for a NIfTI dataset.
+*//*-------------------------------------------------------------------*/
+int nifti_datatype_is_valid( int dtype, int for_nifti )
+{
+    int tablen = sizeof(nifti_type_list)/sizeof(nifti_type_ele);
+    int c;
+
+    /* special case */
+    if( for_nifti && dtype == DT_BINARY ) return 0;
+
+    for( c = tablen-1; c > 0; c-- )
+        if( nifti_type_list[c].type == dtype )
+            return 1;
+
+    return 0;
+}
+
+
+/*---------------------------------------------------------------------*/
+/*! Only as a test, verify that the new nifti_type_list table matches
+ *  the the usage of nifti_datatype_sizes (which could be changed to
+ *  use the table, if there were interest).
+ *
+ *  return the number of errors (so 0 is success, as usual)
+*//*-------------------------------------------------------------------*/
+int nifti_test_datatype_sizes(int verb)
+{
+    int tablen = sizeof(nifti_type_list)/sizeof(nifti_type_ele);
+    int nbyper, ssize;
+    int c, errs = 0;
+
+    for( c = 0; c < tablen; c++ )
+    {
+        nbyper = ssize = -1;
+        nifti_datatype_sizes(nifti_type_list[c].type, &nbyper, &ssize);
+        if( nbyper < 0 || ssize < 0 ||
+                nbyper != nifti_type_list[c].nbyper ||
+                ssize != nifti_type_list[c].swapsize )
+        {
+            if( verb || g_opts.debug > 2 )
+                REprintf( "** type mismatch: %s, %d, %d, %d : %d, %d\n",
+                    nifti_type_list[c].name, nifti_type_list[c].type,
+                    nifti_type_list[c].nbyper, nifti_type_list[c].swapsize,
+                    nbyper, ssize);
+            errs++;
+        }
+    }
+
+    if( errs )
+        REprintf("** nifti_test_datatype_sizes: found %d errors\n",errs);
+    else if( verb || g_opts.debug > 1 )
+        REprintf("-- nifti_test_datatype_sizes: all OK\n");
+
+    return errs;
+}
+
+
+/*---------------------------------------------------------------------*/
+/*! Display the nifti_type_list table.
+ *
+ *  if which == 1  : display DT_*
+ *  if which == 2  : display NIFTI_TYPE*
+ *  else           : display all
+*//*-------------------------------------------------------------------*/
+int nifti_disp_type_list( int which )
+{
+    char * style;
+    int    tablen = sizeof(nifti_type_list)/sizeof(nifti_type_ele);
+    int    lwhich, c;
+
+    if     ( which == 1 ){ lwhich = 1; style = "DT_"; }
+    else if( which == 2 ){ lwhich = 2; style = "NIFTI_TYPE_"; }
+    else                 { lwhich = 3; style = "ALL"; }
+
+    Rprintf("nifti_type_list entries (%s) :\n"
+           "  name                    type    nbyper    swapsize\n"
+           "  ---------------------   ----    ------    --------\n", style);
+
+    for( c = 0; c < tablen; c++ )
+        if( (lwhich & 1 && nifti_type_list[c].name[0] == 'D')  ||
+            (lwhich & 2 && nifti_type_list[c].name[0] == 'N')     )
+            Rprintf("  %-22s %5d     %3d      %5d\n",
+                   nifti_type_list[c].name,
+                   nifti_type_list[c].type,
+                   nifti_type_list[c].nbyper,
+                   nifti_type_list[c].swapsize);
+
+    return 0;
+}
+
+
diff --git a/src/nifti1_io.h b/src/nifti1_io.h
new file mode 100644
index 0000000..6c1ec59
--- /dev/null
+++ b/src/nifti1_io.h
@@ -0,0 +1,555 @@
+/** \file nifti1_io.h
+    \brief Data structures for using nifti1_io API.
+           - Written by Bob Cox, SSCC NIMH
+           - Revisions by Rick Reynolds, SSCC NIMH
+ */
+#ifndef _NIFTI_IO_HEADER_
+#define _NIFTI_IO_HEADER_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+
+#ifndef DONT_INCLUDE_ANALYZE_STRUCT
+#define DONT_INCLUDE_ANALYZE_STRUCT  /*** not needed herein ***/
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#include "nifti1.h"                  /*** NIFTI-1 header specification ***/
+
+#include "znzlib.h"
+
+/*=================*/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*=================*/
+
+/*****===================================================================*****/
+/*****         File nifti1_io.h == Declarations for nifti1_io.c          *****/
+/*****...................................................................*****/
+/*****            This code is released to the public domain.            *****/
+/*****...................................................................*****/
+/*****  Author: Robert W Cox, SSCC/DIRP/NIMH/NIH/DHHS/USA/EARTH          *****/
+/*****  Date:   August 2003                                              *****/
+/*****...................................................................*****/
+/*****  Neither the National Institutes of Health (NIH), nor any of its  *****/
+/*****  employees imply any warranty of usefulness of this software for  *****/
+/*****  any purpose, and do not assume any liability for damages,        *****/
+/*****  incidental or otherwise, caused by any use of this document.     *****/
+/*****===================================================================*****/
+
+/* 
+   Modified by: Mark Jenkinson (FMRIB Centre, University of Oxford, UK)
+   Date: July/August 2004 
+
+      Mainly adding low-level IO and changing things to allow gzipped files
+      to be read and written
+      Full backwards compatability should have been maintained
+
+   Modified by: Rick Reynolds (SSCC/DIRP/NIMH, National Institutes of Health)
+   Date: December 2004
+
+      Modified and added many routines for I/O.
+*/
+
+/********************** Some sample data structures **************************/
+
+typedef struct {                   /** 4x4 matrix struct **/
+  float m[4][4] ;
+} mat44 ;
+
+typedef struct {                   /** 3x3 matrix struct **/
+  float m[3][3] ;
+} mat33 ;
+
+/*...........................................................................*/
+
+/*! \enum analyze_75_orient_code
+ *  \brief Old-style analyze75 orientation
+ *         codes.
+ */
+typedef enum _analyze75_orient_code {
+  a75_transverse_unflipped = 0,
+  a75_coronal_unflipped = 1,
+  a75_sagittal_unflipped = 2,
+  a75_transverse_flipped = 3,
+  a75_coronal_flipped = 4,
+  a75_sagittal_flipped = 5,
+  a75_orient_unknown = 6
+} analyze_75_orient_code;
+
+/*! \struct nifti_image
+    \brief High level data structure for open nifti datasets in the
+           nifti1_io API.  Note that this structure is not part of the
+           nifti1 format definition; it is used to implement one API
+           for reading/writing formats in the nifti1 format.
+ */
+typedef struct {                /*!< Image storage struct **/
+
+  int ndim ;                    /*!< last dimension greater than 1 (1..7) */
+  int nx ;                      /*!< dimensions of grid array             */
+  int ny ;                      /*!< dimensions of grid array             */
+  int nz ;                      /*!< dimensions of grid array             */
+  int nt ;                      /*!< dimensions of grid array             */
+  int nu ;                      /*!< dimensions of grid array             */
+  int nv ;                      /*!< dimensions of grid array             */
+  int nw ;                      /*!< dimensions of grid array             */
+  int dim[8] ;                  /*!< dim[0]=ndim, dim[1]=nx, etc.         */
+  size_t nvox ;                    /*!< number of voxels = nx*ny*nz*...*nw   */
+  int nbyper ;                  /*!< bytes per voxel, matches datatype    */
+  int datatype ;                /*!< type of data in voxels: DT_* code    */
+
+  float dx ;                    /*!< grid spacings      */
+  float dy ;                    /*!< grid spacings      */
+  float dz ;                    /*!< grid spacings      */
+  float dt ;                    /*!< grid spacings      */
+  float du ;                    /*!< grid spacings      */
+  float dv ;                    /*!< grid spacings      */
+  float dw ;                    /*!< grid spacings      */
+  float pixdim[8] ;             /*!< pixdim[1]=dx, etc. */
+
+  float scl_slope ;             /*!< scaling parameter - slope        */
+  float scl_inter ;             /*!< scaling parameter - intercept    */
+
+  float cal_min ;               /*!< calibration parameter, minimum   */
+  float cal_max ;               /*!< calibration parameter, maximum   */
+
+  int qform_code ;              /*!< codes for (x,y,z) space meaning  */
+  int sform_code ;              /*!< codes for (x,y,z) space meaning  */
+
+  int freq_dim  ;               /*!< indexes (1,2,3, or 0) for MRI    */
+  int phase_dim ;               /*!< directions in dim[]/pixdim[]     */
+  int slice_dim ;               /*!< directions in dim[]/pixdim[]     */
+
+  int   slice_code  ;           /*!< code for slice timing pattern    */
+  int   slice_start ;           /*!< index for start of slices        */
+  int   slice_end   ;           /*!< index for end of slices          */
+  float slice_duration ;        /*!< time between individual slices   */
+
+  /*! quaternion transform parameters
+    [when writing a dataset, these are used for qform, NOT qto_xyz]   */
+  float quatern_b , quatern_c , quatern_d ,
+        qoffset_x , qoffset_y , qoffset_z ,
+        qfac      ;
+
+  mat44 qto_xyz ;               /*!< qform: transform (i,j,k) to (x,y,z) */
+  mat44 qto_ijk ;               /*!< qform: transform (x,y,z) to (i,j,k) */
+
+  mat44 sto_xyz ;               /*!< sform: transform (i,j,k) to (x,y,z) */
+  mat44 sto_ijk ;               /*!< sform: transform (x,y,z) to (i,j,k) */
+
+  float toffset ;               /*!< time coordinate offset */
+
+  int xyz_units  ;              /*!< dx,dy,dz units: NIFTI_UNITS_* code  */
+  int time_units ;              /*!< dt       units: NIFTI_UNITS_* code  */
+
+  int nifti_type ;              /*!< 0==ANALYZE, 1==NIFTI-1 (1 file),
+                                                 2==NIFTI-1 (2 files),
+                                                 3==NIFTI-ASCII (1 file) */
+  int   intent_code ;           /*!< statistic type (or something)       */
+  float intent_p1 ;             /*!< intent parameters                   */
+  float intent_p2 ;             /*!< intent parameters                   */
+  float intent_p3 ;             /*!< intent parameters                   */
+  char  intent_name[16] ;       /*!< optional description of intent data */
+
+  char descrip[80]  ;           /*!< optional text to describe dataset   */
+  char aux_file[24] ;           /*!< auxiliary filename                  */
+
+  char *fname ;                 /*!< header filename (.hdr or .nii)         */
+  char *iname ;                 /*!< image filename  (.img or .nii)         */
+  int   iname_offset ;          /*!< offset into iname where data starts    */
+  int   swapsize ;              /*!< swap unit in image data (might be 0)   */
+  int   byteorder ;             /*!< byte order on disk (MSB_ or LSB_FIRST) */
+  void *data ;                  /*!< pointer to data: nbyper*nvox bytes     */
+
+  int                num_ext ;  /*!< number of extensions in ext_list       */
+  nifti1_extension * ext_list ; /*!< array of extension structs (with data) */
+  analyze_75_orient_code analyze75_orient; /*!< for old analyze files, orient */
+
+} nifti_image ;
+
+
+
+/* struct for return from nifti_image_read_bricks() */
+typedef struct {
+  int       nbricks;    /* the number of allocated pointers in 'bricks' */
+  size_t    bsize;      /* the length of each data block, in bytes      */
+  void   ** bricks;     /* array of pointers to data blocks             */
+} nifti_brick_list;
+
+
+/*****************************************************************************/
+/*------------------ NIfTI version of ANALYZE 7.5 structure -----------------*/
+
+/* (based on fsliolib/dbh.h, but updated for version 7.5) */
+
+typedef struct {
+       /* header info fields - describes the header    overlap with NIfTI */
+       /*                                              ------------------ */
+       int sizeof_hdr;                  /* 0 + 4        same              */
+       char data_type[10];              /* 4 + 10       same              */
+       char db_name[18];                /* 14 + 18      same              */
+       int extents;                     /* 32 + 4       same              */
+       short int session_error;         /* 36 + 2       same              */
+       char regular;                    /* 38 + 1       same              */
+       char hkey_un0;                   /* 39 + 1                40 bytes */
+
+       /* image dimension fields - describes image sizes */
+       short int dim[8];                /* 0 + 16       same              */
+       short int unused8;               /* 16 + 2       intent_p1...      */
+       short int unused9;               /* 18 + 2         ...             */
+       short int unused10;              /* 20 + 2       intent_p2...      */
+       short int unused11;              /* 22 + 2         ...             */
+       short int unused12;              /* 24 + 2       intent_p3...      */
+       short int unused13;              /* 26 + 2         ...             */
+       short int unused14;              /* 28 + 2       intent_code       */
+       short int datatype;              /* 30 + 2       same              */
+       short int bitpix;                /* 32 + 2       same              */
+       short int dim_un0;               /* 34 + 2       slice_start       */
+       float pixdim[8];                 /* 36 + 32      same              */
+
+       float vox_offset;                /* 68 + 4       same              */
+       float funused1;                  /* 72 + 4       scl_slope         */
+       float funused2;                  /* 76 + 4       scl_inter         */
+       float funused3;                  /* 80 + 4       slice_end,        */
+                                                     /* slice_code,       */
+                                                     /* xyzt_units        */
+       float cal_max;                   /* 84 + 4       same              */
+       float cal_min;                   /* 88 + 4       same              */
+       float compressed;                /* 92 + 4       slice_duration    */
+       float verified;                  /* 96 + 4       toffset           */
+       int glmax,glmin;                 /* 100 + 8              108 bytes */
+
+       /* data history fields - optional */
+       char descrip[80];                /* 0 + 80       same              */
+       char aux_file[24];               /* 80 + 24      same              */
+       char orient;                     /* 104 + 1      NO GOOD OVERLAP   */
+       char originator[10];             /* 105 + 10     FROM HERE DOWN... */
+       char generated[10];              /* 115 + 10                       */
+       char scannum[10];                /* 125 + 10                       */
+       char patient_id[10];             /* 135 + 10                       */
+       char exp_date[10];               /* 145 + 10                       */
+       char exp_time[10];               /* 155 + 10                       */
+       char hist_un0[3];                /* 165 + 3                        */
+       int views;                       /* 168 + 4                        */
+       int vols_added;                  /* 172 + 4                        */
+       int start_field;                 /* 176 + 4                        */
+       int field_skip;                  /* 180 + 4                        */
+       int omax, omin;                  /* 184 + 8                        */
+       int smax, smin;                  /* 192 + 8              200 bytes */
+} nifti_analyze75;                                   /* total:  348 bytes */
+
+
+/*****************************************************************************/
+/*--------------- Prototypes of functions defined in this file --------------*/
+
+char *nifti_datatype_string   ( int dt ) ;
+char *nifti_units_string      ( int uu ) ;
+char *nifti_intent_string     ( int ii ) ;
+char *nifti_xform_string      ( int xx ) ;
+char *nifti_slice_string      ( int ss ) ;
+char *nifti_orientation_string( int ii ) ;
+
+int   nifti_is_inttype( int dt ) ;
+
+mat44 nifti_mat44_inverse( mat44 R ) ;
+
+mat33 nifti_mat33_inverse( mat33 R ) ;
+mat33 nifti_mat33_polar  ( mat33 A ) ;
+float nifti_mat33_rownorm( mat33 A ) ;
+float nifti_mat33_colnorm( mat33 A ) ;
+float nifti_mat33_determ ( mat33 R ) ;
+mat33 nifti_mat33_mul    ( mat33 A , mat33 B ) ;
+
+void  nifti_swap_2bytes ( size_t n , void *ar ) ;
+void  nifti_swap_4bytes ( size_t n , void *ar ) ;
+void  nifti_swap_8bytes ( size_t n , void *ar ) ;
+void  nifti_swap_16bytes( size_t n , void *ar ) ;
+void  nifti_swap_Nbytes ( size_t n , int siz , void *ar ) ;
+
+int    nifti_datatype_is_valid   (int dtype, int for_nifti);
+int    nifti_datatype_from_string(const char * name);
+const char * nifti_datatype_to_string  (int dtype);
+
+int   nifti_get_filesize( const char *pathname ) ;
+void  swap_nifti_header ( struct nifti_1_header *h , int is_nifti ) ;
+void  old_swap_nifti_header( struct nifti_1_header *h , int is_nifti );
+int   nifti_swap_as_analyze( nifti_analyze75 *h );
+
+
+/* main read/write routines */
+
+nifti_image *nifti_image_read_bricks(const char *hname , int nbricks,
+                                     const int *blist, nifti_brick_list * NBL);
+int          nifti_image_load_bricks(nifti_image *nim , int nbricks,
+                                     const int *blist, nifti_brick_list * NBL);
+void         nifti_free_NBL( nifti_brick_list * NBL );
+
+nifti_image *nifti_image_read    ( const char *hname , int read_data );
+nifti_image *nifti_image_read_NaN    ( const char *hname , int read_data , int rmNaN);
+
+int          nifti_image_load    ( nifti_image *nim ) ;
+int          nifti_image_load_NaN    ( nifti_image *nim , int rmNaN) ;
+
+void         nifti_image_unload  ( nifti_image *nim ) ;
+void         nifti_image_free    ( nifti_image *nim ) ;
+
+int          nifti_read_collapsed_image( nifti_image * nim, const int dims [8],
+                                         void ** data );
+
+int          nifti_read_subregion_image( nifti_image * nim, 
+                                         int *start_index, int *region_size,
+                                         void ** data );
+
+void         nifti_image_write   ( nifti_image * nim ) ;
+void         nifti_image_write_bricks(nifti_image * nim, 
+                                      const nifti_brick_list * NBL);
+void         nifti_image_infodump( const nifti_image * nim ) ;
+
+void         nifti_disp_lib_hist( void ) ;     /* to display library history */
+void         nifti_disp_lib_version( void ) ;  /* to display library version */
+const char  *nifti_lib_version( void );
+int          nifti_disp_matrix_orient( const char * mesg, mat44 mat );
+int          nifti_disp_type_list( int which );
+
+
+char *       nifti_image_to_ascii  ( const nifti_image * nim ) ;
+nifti_image *nifti_image_from_ascii( const char * str, int * bytes_read ) ;
+
+size_t       nifti_get_volsize(const nifti_image *nim) ;
+
+/* basic file operations */
+int    nifti_set_filenames(nifti_image * nim, const char * prefix, int check,
+                           int set_byte_order);
+char * nifti_makehdrname  (const char * prefix, int nifti_type, int check,
+                           int comp);
+char * nifti_makeimgname  (const char * prefix, int nifti_type, int check,
+                           int comp);
+int    is_nifti_file      (const char *hname);
+char * nifti_find_file_extension(const char * name);
+int    nifti_is_complete_filename(const char* fname);
+int    nifti_validfilename(const char* fname);
+
+int    disp_nifti_1_header(const char * info, const nifti_1_header * hp ) ;
+void   nifti_set_debug_level( int level ) ;
+void   nifti_set_skip_blank_ext( int skip ) ;
+void   nifti_set_allow_upper_fext( int allow ) ;
+
+int    valid_nifti_brick_list(nifti_image * nim , int nbricks,
+                              const int * blist, int disp_error);
+
+/* znzFile operations */
+znzFile nifti_image_open(const char * hname, char * opts, nifti_image ** nim);
+znzFile nifti_image_write_hdr_img(nifti_image *nim, int write_data,
+                                  const char* opts);
+znzFile nifti_image_write_hdr_img2( nifti_image *nim , int write_opts ,
+               const char* opts, znzFile imgfile, const nifti_brick_list * NBL);
+size_t  nifti_read_buffer_NaN(znzFile fp, void* datatptr, size_t ntot,
+                         nifti_image *nim, int rmNaN);
+size_t  nifti_read_buffer(znzFile fp, void* datatptr, size_t ntot,
+                         nifti_image *nim);
+int     nifti_write_all_data(znzFile fp, nifti_image * nim,
+                             const nifti_brick_list * NBL);
+size_t  nifti_write_buffer(znzFile fp, const void * buffer, size_t numbytes);
+nifti_image *nifti_read_ascii_image(znzFile fp, char *fname, int flen,
+                         int read_data);
+znzFile nifti_write_ascii_image(nifti_image *nim, const nifti_brick_list * NBL,
+                         const char * opts, int write_data, int leave_open);
+
+
+void nifti_datatype_sizes( int datatype , int *nbyper, int *swapsize ) ;
+
+void nifti_mat44_to_quatern( mat44 R ,
+                             float *qb, float *qc, float *qd,
+                             float *qx, float *qy, float *qz,
+                             float *dx, float *dy, float *dz, float *qfac ) ;
+
+mat44 nifti_quatern_to_mat44( float qb, float qc, float qd,
+                              float qx, float qy, float qz,
+                              float dx, float dy, float dz, float qfac );
+
+mat44 nifti_make_orthog_mat44( float r11, float r12, float r13 ,
+                               float r21, float r22, float r23 ,
+                               float r31, float r32, float r33  ) ;
+
+int nifti_short_order(void) ;              /* CPU byte order */
+
+
+/* Orientation codes that might be returned from nifti_mat44_to_orientation().*/
+
+#define NIFTI_L2R  1    /* Left to Right         */
+#define NIFTI_R2L  2    /* Right to Left         */
+#define NIFTI_P2A  3    /* Posterior to Anterior */
+#define NIFTI_A2P  4    /* Anterior to Posterior */
+#define NIFTI_I2S  5    /* Inferior to Superior  */
+#define NIFTI_S2I  6    /* Superior to Inferior  */
+
+void nifti_mat44_to_orientation( mat44 R , int *icod, int *jcod, int *kcod ) ;
+
+/*--------------------- Low level IO routines ------------------------------*/
+
+char * nifti_findhdrname (const char* fname);
+char * nifti_findimgname (const char* fname , int nifti_type);
+int    nifti_is_gzfile   (const char* fname);
+
+char * nifti_makebasename(const char* fname);
+
+
+/* other routines */
+struct nifti_1_header   nifti_convert_nim2nhdr(const nifti_image* nim);
+nifti_1_header * nifti_make_new_header(const int arg_dims[], int arg_dtype);
+nifti_1_header * nifti_read_header(const char *hname, int *swapped, int check);
+nifti_image    * nifti_copy_nim_info(const nifti_image * src);
+nifti_image    * nifti_make_new_nim(const int dims[], int datatype,
+                                                      int data_fill);
+nifti_image    * nifti_simple_init_nim(void);
+nifti_image    * nifti_convert_nhdr2nim(struct nifti_1_header nhdr,
+                                        const char * fname);
+
+int    nifti_hdr_looks_good        (const nifti_1_header * hdr);
+int    nifti_is_valid_datatype     (int dtype);
+int    nifti_is_valid_ecode        (int ecode);
+int    nifti_nim_is_valid          (nifti_image * nim, int complain);
+int    nifti_nim_has_valid_dims    (nifti_image * nim, int complain);
+int    is_valid_nifti_type         (int nifti_type);
+int    nifti_test_datatype_sizes   (int verb);
+int    nifti_type_and_names_match  (nifti_image * nim, int show_warn);
+int    nifti_update_dims_from_array(nifti_image * nim);
+void   nifti_set_iname_offset      (nifti_image *nim);
+int    nifti_set_type_from_names   (nifti_image * nim);
+int    nifti_add_extension(nifti_image * nim, const char * data, int len,
+                           int ecode );
+int    nifti_compiled_with_zlib    (void);
+int    nifti_copy_extensions (nifti_image *nim_dest,const nifti_image *nim_src);
+int    nifti_free_extensions (nifti_image *nim);
+int  * nifti_get_intlist     (int nvals , const char *str);
+char * nifti_strdup          (const char *str);
+int    valid_nifti_extensions(const nifti_image *nim);
+
+
+/*-------------------- Some C convenience macros ----------------------------*/
+
+/* NIfTI-1.1 extension codes:
+   see http://nifti.nimh.nih.gov/nifti-1/documentation/faq#Q21 */
+
+#define NIFTI_ECODE_IGNORE           0  /* changed from UNKNOWN, 29 June 2005 */
+
+#define NIFTI_ECODE_DICOM            2  /* intended for raw DICOM attributes  */
+
+#define NIFTI_ECODE_AFNI             4  /* Robert W Cox: rwcox at nih.gov
+                                           http://afni.nimh.nih.gov/afni      */
+
+#define NIFTI_ECODE_COMMENT          6  /* plain ASCII text only              */
+
+#define NIFTI_ECODE_XCEDE            8  /* David B Keator: dbkeator at uci.edu 
+                                           http://www.nbirn.net/Resources
+                                                /Users/Applications/
+                                                /xcede/index.htm              */
+
+#define NIFTI_ECODE_JIMDIMINFO      10  /* Mark A Horsfield:
+                                           mah5 at leicester.ac.uk
+                                           http://someplace/something         */
+
+#define NIFTI_ECODE_WORKFLOW_FWDS   12  /* Kate Fissell: fissell at pitt.edu
+                                           http://kraepelin.wpic.pitt.edu
+                                            /~fissell/NIFTI_ECODE_WORKFLOW_FWDS
+                                            /NIFTI_ECODE_WORKFLOW_FWDS.html   */
+
+#define NIFTI_ECODE_FREESURFER      14  /* http://surfer.nmr.mgh.harvard.edu  */
+
+#define NIFTI_ECODE_PYPICKLE        16  /* embedded Python objects
+                                           http://niftilib.sourceforge.net
+                                                 /pynifti                     */
+
+        /* LONI MiND codes: http://www.loni.ucla.edu/twiki/bin/view/Main/MiND */
+#define NIFTI_ECODE_MIND_IDENT      18  /* Vishal Patel: vishal.patel at ucla.edu*/
+#define NIFTI_ECODE_B_VALUE         20
+#define NIFTI_ECODE_SPHERICAL_DIRECTION 22
+#define NIFTI_ECODE_DT_COMPONENT    24
+#define NIFTI_ECODE_SHC_DEGREEORDER 26  /* end LONI MiND codes                */
+
+#define NIFTI_ECODE_VOXBO           28  /* Dan Kimberg: www.voxbo.org         */
+
+#define NIFTI_ECODE_CARET           30  /* John Harwell: john at brainvis.wustl.edu
+                                           http://brainvis.wustl.edu/wiki
+                                             /index.php/Caret:Documentation
+                                             :CaretNiftiExtension             */
+
+#define NIFTI_MAX_ECODE             30  /******* maximum extension code *******/
+
+/* nifti_type file codes */
+#define NIFTI_FTYPE_ANALYZE   0
+#define NIFTI_FTYPE_NIFTI1_1  1
+#define NIFTI_FTYPE_NIFTI1_2  2
+#define NIFTI_FTYPE_ASCII     3
+#define NIFTI_MAX_FTYPE       3    /* this should match the maximum code */
+
+/*------------------------------------------------------------------------*/
+/*-- the rest of these apply only to nifti1_io.c, check for _NIFTI1_IO_C_ */
+/*                                                    Feb 9, 2005 [rickr] */
+#ifdef _NIFTI1_IO_C_
+
+typedef struct {
+    int debug;               /*!< debug level for status reports  */
+    int skip_blank_ext;      /*!< skip extender if no extensions  */
+    int allow_upper_fext;    /*!< allow uppercase file extensions */
+} nifti_global_options;
+
+typedef struct {
+    int    type;           /* should match the NIFTI_TYPE_ #define */
+    int    nbyper;         /* bytes per value, matches nifti_image */
+    int    swapsize;       /* bytes per swap piece, matches nifti_image */
+    char * name;           /* text string to match #define */
+} nifti_type_ele;
+
+#undef  LNI_FERR /* local nifti file error, to be compact and repetative */
+#define LNI_FERR(func,msg,file)                                      \
+            REprintf("** ERROR (%s): %s '%s'\n",func,msg,file)
+
+#undef  swap_2
+#undef  swap_4
+#define swap_2(s) nifti_swap_2bytes(1,&(s)) /* s: 2-byte short; swap in place */
+#define swap_4(v) nifti_swap_4bytes(1,&(v)) /* v: 4-byte value; swap in place */
+
+                        /***** isfinite() is a C99 macro, which is
+                               present in many C implementations already *****/
+
+#undef IS_GOOD_FLOAT
+#undef FIXED_FLOAT
+
+#ifdef isfinite       /* use isfinite() to check floats/doubles for goodness */
+#  define IS_GOOD_FLOAT(x) isfinite(x)       /* check if x is a "good" float */
+#  define FIXED_FLOAT(x)   (isfinite(x) ? (x) : 0)           /* fixed if bad */
+#else
+#  define IS_GOOD_FLOAT(x) 1                               /* don't check it */
+#  define FIXED_FLOAT(x)   (x)                               /* don't fix it */
+#endif
+
+#undef  ASSIF                                 /* assign v to *p, if possible */
+#define ASSIF(p,v) if( (p)!=NULL ) *(p) = (v)
+
+#undef  MSB_FIRST
+#undef  LSB_FIRST
+#undef  REVERSE_ORDER
+#define LSB_FIRST 1
+#define MSB_FIRST 2
+#define REVERSE_ORDER(x) (3-(x))    /* convert MSB_FIRST <--> LSB_FIRST */
+
+#define LNI_MAX_NIA_EXT_LEN 100000  /* consider a longer extension invalid */
+
+#endif  /* _NIFTI1_IO_C_ section */
+/*------------------------------------------------------------------------*/
+
+/*=================*/
+#ifdef  __cplusplus
+}
+#endif
+/*=================*/
+
+#endif /* _NIFTI_IO_HEADER_ */
diff --git a/src/znzlib.c b/src/znzlib.c
new file mode 100644
index 0000000..4f7c2c4
--- /dev/null
+++ b/src/znzlib.c
@@ -0,0 +1,327 @@
+/** \file znzlib.c
+    \brief Low level i/o interface to compressed and noncompressed files.
+        Written by Mark Jenkinson, FMRIB
+
+This library provides an interface to both compressed (gzip/zlib) and
+uncompressed (normal) file IO.  The functions are written to have the
+same interface as the standard file IO functions.
+
+To use this library instead of normal file IO, the following changes
+are required:
+ - replace all instances of FILE* with znzFile
+ - change the name of all function calls, replacing the initial character
+   f with the znz  (e.g. fseek becomes znzseek)
+   one exception is rewind() -> znzrewind()
+ - add a third parameter to all calls to znzopen (previously fopen)
+   that specifies whether to use compression (1) or not (0)
+ - use znz_isnull rather than any (pointer == NULL) comparisons in the code
+   for znzfile types (normally done after a return from znzopen)
+ 
+NB: seeks for writable files with compression are quite restricted
+
+ */
+/* changes by Oliver Granert:
+- change HAVE_ZLIB to HAVE_LIBZ to fit autoconf tests
+*/
+#include "znzlib.h"
+#include <R.h>
+
+/*
+znzlib.c  (zipped or non-zipped library)
+
+*****            This code is released to the public domain.            *****
+
+*****  Author: Mark Jenkinson, FMRIB Centre, University of Oxford       *****
+*****  Date:   September 2004                                           *****
+
+*****  Neither the FMRIB Centre, the University of Oxford, nor any of   *****
+*****  its employees imply any warranty of usefulness of this software  *****
+*****  for any purpose, and do not assume any liability for damages,    *****
+*****  incidental or otherwise, caused by any use of this document.     *****
+
+*/
+
+
+/* Note extra argument (use_compression) where 
+   use_compression==0 is no compression
+   use_compression!=0 uses zlib (gzip) compression
+*/
+
+znzFile znzopen(const char *path, const char *mode, int use_compression)
+{
+  znzFile file;
+  file = (znzFile) calloc(1,sizeof(struct znzptr));
+  if( file == NULL ){
+     REprintf(/*fprintf(stderr,*/"** ERROR: znzopen failed to alloc znzptr\n");
+     return NULL;
+  }
+
+  file->nzfptr = NULL;
+
+#ifdef HAVE_LIBZ
+  file->zfptr = NULL;
+
+  if (use_compression) {
+    file->withz = 1;
+    if((file->zfptr = gzopen(path,mode)) == NULL) {
+        free(file);
+        file = NULL;
+    }
+  } else {
+#endif
+
+    file->withz = 0;
+    if((file->nzfptr = fopen(path,mode)) == NULL) {
+      free(file);
+      file = NULL;
+    }
+
+#ifdef HAVE_LIBZ
+  }
+#endif
+
+  return file;
+}
+
+
+znzFile znzdopen(int fd, const char *mode, int use_compression)
+{
+  znzFile file;
+  file = (znzFile) calloc(1,sizeof(struct znzptr));
+  if( file == NULL ){
+     REprintf(/*fprintf(stderr,*/"** ERROR: znzdopen failed to alloc znzptr\n");
+     return NULL;
+  }
+#ifdef HAVE_LIBZ
+  if (use_compression) {
+    file->withz = 1;
+    file->zfptr = gzdopen(fd,mode);
+    file->nzfptr = NULL;
+  } else {
+#endif
+    file->withz = 0;
+#ifdef HAVE_FDOPEN
+    file->nzfptr = fdopen(fd,mode);
+#endif
+#ifdef HAVE_LIBZ
+    file->zfptr = NULL;
+  };
+#endif
+  return file;
+}
+
+
+int Xznzclose(znzFile * file)
+{
+  int retval = 0;
+  if (*file!=NULL) {
+#ifdef HAVE_LIBZ
+    if ((*file)->zfptr!=NULL)  { retval = gzclose((*file)->zfptr); }
+#endif
+    if ((*file)->nzfptr!=NULL) { retval = fclose((*file)->nzfptr); }
+                                                                                
+    free(*file);
+    *file = NULL;
+  }
+  return retval;
+}
+
+
+/* we already assume ints are 4 bytes */
+#undef ZNZ_MAX_BLOCK_SIZE
+#define ZNZ_MAX_BLOCK_SIZE (1<<30)
+
+size_t znzread(void* buf, size_t size, size_t nmemb, znzFile file)
+{
+#ifdef HAVE_LIBZ
+  size_t     remain = size*nmemb;
+  char     * cbuf = (char *)buf;
+  unsigned   n2read;
+  int        nread;
+#endif
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) {
+    /* gzread/write take unsigned int length, so maybe read in int pieces
+       (noted by M Hanke, example given by M Adler)   6 July 2010 [rickr] */
+    while( remain > 0 ) {
+       n2read = (remain < ZNZ_MAX_BLOCK_SIZE) ? remain : ZNZ_MAX_BLOCK_SIZE;
+       nread = gzread(file->zfptr, (void *)cbuf, n2read);
+       if( nread < 0 ) return nread; /* returns -1 on error */
+
+       remain -= nread;
+       cbuf += nread;
+
+       /* require reading n2read bytes, so we don't get stuck */
+       if( nread < (int)n2read ) break;  /* return will be short */
+    }
+
+    /* warn of a short read that will seem complete */
+    if( remain > 0 && remain < size )
+       REprintf(/*fprintf(stderr,*/"** znzread: read short by %u bytes\n",(unsigned)remain);
+
+    return nmemb - remain/size;   /* return number of members processed */
+  }
+#endif
+  return fread(buf,size,nmemb,file->nzfptr);
+}
+
+size_t znzwrite(const void* buf, size_t size, size_t nmemb, znzFile file)
+{
+#ifdef HAVE_LIBZ
+  size_t     remain = size*nmemb;
+  char     * cbuf = (char *)buf;
+  unsigned   n2write;
+  int        nwritten;
+#endif
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) {
+    while( remain > 0 ) {
+       n2write = (remain < ZNZ_MAX_BLOCK_SIZE) ? remain : ZNZ_MAX_BLOCK_SIZE;
+       nwritten = gzwrite(file->zfptr, (void *)cbuf, n2write);
+
+       /* gzread returns 0 on error, but in case that ever changes... */
+       if( nwritten < 0 ) return nwritten;
+
+       remain -= nwritten;
+       cbuf += nwritten;
+
+       /* require writing n2write bytes, so we don't get stuck */
+       if( nwritten < (int)n2write ) break;
+    }
+
+    /* warn of a short write that will seem complete */
+    if( remain > 0 && remain < size )
+      REprintf(/*fprintf(stderr,*/"** znzwrite: write short by %u bytes\n",(unsigned)remain);
+
+    return nmemb - remain/size;   /* return number of members processed */
+  }
+#endif
+  return fwrite(buf,size,nmemb,file->nzfptr);
+}
+
+long znzseek(znzFile file, long offset, int whence)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return (long) gzseek(file->zfptr,offset,whence);
+#endif
+  return fseek(file->nzfptr,offset,whence);
+}
+
+int znzrewind(znzFile stream)
+{
+  if (stream==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  /* On some systems, gzrewind() fails for uncompressed files.
+     Use gzseek(), instead.               10, May 2005 [rickr]
+
+     if (stream->zfptr!=NULL) return gzrewind(stream->zfptr);
+  */
+
+  if (stream->zfptr!=NULL) return (int)gzseek(stream->zfptr, 0L, SEEK_SET);
+#endif
+  rewind(stream->nzfptr);
+  return 0;
+}
+
+long znztell(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return (long) gztell(file->zfptr);
+#endif
+  return ftell(file->nzfptr);
+}
+
+int znzputs(const char * str, znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return gzputs(file->zfptr,str);
+#endif
+  return fputs(str,file->nzfptr);
+}
+
+
+char * znzgets(char* str, int size, znzFile file)
+{
+  if (file==NULL) { return NULL; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return gzgets(file->zfptr,str,size);
+#endif
+  return fgets(str,size,file->nzfptr);
+}
+
+
+int znzflush(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return gzflush(file->zfptr,Z_SYNC_FLUSH);
+#endif
+  return fflush(file->nzfptr);
+}
+
+
+int znzeof(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return gzeof(file->zfptr);
+#endif
+  return feof(file->nzfptr);
+}
+
+
+int znzputc(int c, znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return gzputc(file->zfptr,c);
+#endif
+  return fputc(c,file->nzfptr);
+}
+
+
+int znzgetc(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_LIBZ
+  if (file->zfptr!=NULL) return gzgetc(file->zfptr);
+#endif
+  return fgetc(file->nzfptr);
+}
+
+#if !defined (WIN32)
+int znzprintf(znzFile stream, const char *format, ...)
+{
+  int retval=0;
+  char *tmpstr;
+  va_list va;
+  if (stream==NULL) { return 0; }
+  va_start(va, format);
+#ifdef HAVE_LIBZ
+  if (stream->zfptr!=NULL) {
+    int size;  /* local to HAVE_LIBZ block */
+    size = strlen(format) + 1000000;  /* overkill I hope */
+    tmpstr = (char *)calloc(1, size);
+    if( tmpstr == NULL ){
+       REprintf(/*fprintf(stderr,*/"** ERROR: znzprintf failed to alloc %d bytes\n", size);
+       return retval;
+    }
+    vsprintf(tmpstr,format,va);
+    retval=gzprintf(stream->zfptr,"%s",tmpstr);
+    free(tmpstr);
+  } else 
+#endif
+  {
+   retval=vfprintf(stream->nzfptr,format,va);
+  }
+  va_end(va);
+  return retval;
+}
+
+#endif
+
diff --git a/src/znzlib.h b/src/znzlib.h
new file mode 100644
index 0000000..06cbf12
--- /dev/null
+++ b/src/znzlib.h
@@ -0,0 +1,129 @@
+#ifndef _ZNZLIB_H_
+#define _ZNZLIB_H_
+
+/*
+znzlib.h  (zipped or non-zipped library)
+
+*****            This code is released to the public domain.            *****
+
+*****  Author: Mark Jenkinson, FMRIB Centre, University of Oxford       *****
+*****  Date:   September 2004                                           *****
+
+*****  Neither the FMRIB Centre, the University of Oxford, nor any of   *****
+*****  its employees imply any warranty of usefulness of this software  *****
+*****  for any purpose, and do not assume any liability for damages,    *****
+*****  incidental or otherwise, caused by any use of this document.     *****
+
+*/
+
+/*
+
+This library provides an interface to both compressed (gzip/zlib) and
+uncompressed (normal) file IO.  The functions are written to have the
+same interface as the standard file IO functions.  
+
+To use this library instead of normal file IO, the following changes
+are required:
+ - replace all instances of FILE* with znzFile
+ - change the name of all function calls, replacing the initial character
+   f with the znz  (e.g. fseek becomes znzseek)
+ - add a third parameter to all calls to znzopen (previously fopen)
+   that specifies whether to use compression (1) or not (0)
+ - use znz_isnull rather than any (pointer == NULL) comparisons in the code
+ 
+NB: seeks for writable files with compression are quite restricted
+
+*/
+/* changes by Oliver Granert:
+- change HAVE_ZLIB to HAVE_LIBZ to fit autoconf tests
+*/
+
+/*=================*/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*=================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* include optional check for HAVE_FDOPEN here, from deleted config.h:
+
+   uncomment the following line if fdopen() exists for your compiler and
+   compiler options
+*/
+/* #define HAVE_FDOPEN */
+
+
+#ifdef HAVE_LIBZ
+#if defined(ITKZLIB)
+#include "itk_zlib.h"
+#else
+#include "zlib.h"
+#endif
+#endif
+
+
+struct znzptr {
+  int withz;
+  FILE* nzfptr;
+#ifdef HAVE_LIBZ
+  gzFile zfptr;
+#endif
+} ;
+
+/* the type for all file pointers */
+typedef struct znzptr * znzFile;
+
+
+/* int znz_isnull(znzFile f); */
+/* int znzclose(znzFile f); */
+#define znz_isnull(f) ((f) == NULL)
+#define znzclose(f)   Xznzclose(&(f))
+
+/* Note extra argument (use_compression) where 
+   use_compression==0 is no compression
+   use_compression!=0 uses zlib (gzip) compression
+*/
+
+znzFile znzopen(const char *path, const char *mode, int use_compression);
+
+znzFile znzdopen(int fd, const char *mode, int use_compression);
+
+int Xznzclose(znzFile * file);
+
+size_t znzread(void* buf, size_t size, size_t nmemb, znzFile file);
+
+size_t znzwrite(const void* buf, size_t size, size_t nmemb, znzFile file);
+
+long znzseek(znzFile file, long offset, int whence);
+
+int znzrewind(znzFile stream);
+
+long znztell(znzFile file);
+
+int znzputs(const char *str, znzFile file);
+
+char * znzgets(char* str, int size, znzFile file);
+
+int znzputc(int c, znzFile file);
+
+int znzgetc(znzFile file);
+
+#if !defined(WIN32)
+int znzprintf(znzFile stream, const char *format, ...);
+#endif
+
+/*=================*/
+#ifdef  __cplusplus
+}
+#endif
+/*=================*/
+
+#endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-rniftilib.git



More information about the debian-med-commit mailing list