Index: /branches/SDM_SciDAC/macros.make
===================================================================
--- /branches/SDM_SciDAC/macros.make (revision 2)
+++ /branches/SDM_SciDAC/macros.make (revision 2)
@@ -0,0 +1,88 @@
+# $Id$
+
+# The purpose of this file is to contain common make(1) macros.
+# It should be processed by every execution of that utility.
+
+
+# POSIX shell.  Shouldn't be necessary -- but is under IRIX 5.3.
+SHELL		= /bin/sh
+
+
+# Installation Directories:
+prefix		= /opt/netcdf
+exec_prefix	= $(prefix)
+INCDIR		= $(exec_prefix)/include
+LIBDIR		= $(exec_prefix)/lib
+BINDIR		= $(exec_prefix)/bin
+MANDIR		= $(prefix)/man
+
+
+# Preprocessing:
+M4		= m4
+M4FLAGS		= -B10000
+CPP		= c89 -E
+CPPFLAGS	= $(INCLUDES) $(DEFINES) @CPPFLAGS@
+FPP		= 
+FPPFLAGS	= $(CPPFLAGS)
+CXXCPPFLAGS	= $(CPPFLAGS)
+
+
+# Compilation:
+CC		= c89
+CXX		= CC
+FC		= f77
+CFLAGS		= -g
+CXXFLAGS	= $(CFLAGS) @CXXFLAGS@
+FFLAGS		= -g
+CC_MAKEDEPEND	= :
+COMPILE.c	= $(CC) -c $(CFLAGS) $(CPPFLAGS)
+COMPILE.cxx	= $(CXX) -c $(CXXFLAGS) $(CXXCPPFLAGS)
+COMPILE.f	= $(FC) -c $(FFLAGS)
+# The following command isn't available on some systems; therefore, the
+# `.F.o' rule is relatively complicated.
+COMPILE.F	= $(COMPILE.f)
+
+
+# Linking:
+MATHLIB		=
+FLIBS		=
+LIBS		=
+LINK.c		= $(CC) -o $@ $(CFLAGS) $(LDFLAGS)
+LINK.cxx	= $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS)
+LINK.F		= $(FC) -o $@ $(FFLAGS) $(FLDFLAGS)
+LINK.f		= $(FC) -o $@ $(FFLAGS) $(FLDFLAGS)
+
+
+# NetCDF files:
+NCDUMP		= ncdump
+NCGEN		= ncgen
+
+
+# Manual pages:
+WHATIS		=
+# The following macro should be empty on systems that don't
+# allow users to create their own manual-page indexes.
+MAKEWHATIS_CMD	=
+
+
+# Misc. Utilities:
+AR		= ar
+ARFLAGS		= cru	# NB: SunOS 4 doesn't like `-' option prefix
+RANLIB		=
+TARFLAGS	= -chf
+
+
+# Dummy macros: used only as placeholders to silence GNU make.  They are
+# redefined, as necessary, in subdirectory makefiles.
+HEADER		= dummy_header
+HEADER1		= dummy_header1
+HEADER2		= dummy_header2
+LIBRARY		= dummy_library.a
+MANUAL		= dummy_manual
+PROGRAM		= dummy_program
+
+
+# Distribution macros:
+FTPDIR		= /home/ftp/pub/$(PACKAGE)
+FTPBINDIR	= 
+VERSION		= dummy_version
Index: /branches/SDM_SciDAC/configure
===================================================================
--- /branches/SDM_SciDAC/configure (revision 2)
+++ /branches/SDM_SciDAC/configure (revision 2)
@@ -0,0 +1,4117 @@
+#! /bin/sh
+
+# From configure.in Id: configure.in
+CPPFLAGS=${CPPFLAGS--DNDEBUG}
+CFLAGS=${CFLAGS--O}
+FPPFLAGS=${FPPFLAGS-}
+FFLAGS=${FFLAGS-}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13 
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_default_prefix=`(cd ..; pwd)`
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+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=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -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 ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build="$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" ;;
+
+  -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+  | --da=*)
+    datadir="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$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)
+    # 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 << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [same as prefix]
+  --bindir=DIR            user executables in DIR [EPREFIX/bin]
+  --sbindir=DIR           system admin executables in DIR [EPREFIX/sbin]
+  --libexecdir=DIR        program executables in DIR [EPREFIX/libexec]
+  --datadir=DIR           read-only architecture-independent data in DIR
+                          [PREFIX/share]
+  --sysconfdir=DIR        read-only single-machine data in DIR [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data in DIR
+                          [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data in DIR [PREFIX/var]
+  --libdir=DIR            object code libraries in DIR [EPREFIX/lib]
+  --includedir=DIR        C header files in DIR [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc in DIR [/usr/include]
+  --infodir=DIR           info documentation in DIR [PREFIX/info]
+  --mandir=DIR            man documentation in DIR [PREFIX/man]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM
+                          run sed PROGRAM on installed program names
+EOF
+    cat << EOF
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+EOF
+    if test -n "$ac_help"; then
+      echo "--enable and --with options recognized:$ac_help"
+    fi
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$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" ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst \
+  | --locals | --local | --loca | --loc | --lo)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+  | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+    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)
+    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" ;;
+
+  -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 ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.13"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=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" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *)
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set.  These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}"    = set; then LC_CTYPE=C;    export LC_CTYPE;    fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=src/lib/ncconfig.in
+
+# 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 its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  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
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='	'
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+    echo "checking for top-level source-directory" 1>&6
+echo "configure:605: checking for top-level source-directory" >&5
+    SRCDIR=`(cd $srcdir && pwd)`
+    echo "$ac_t""$SRCDIR" 1>&6
+    
+
+
+
+
+    echo "checking for m4 preprocessor" 1>&6
+echo "configure:614: checking for m4 preprocessor" >&5
+    case "${M4-unset}" in
+	unset) for ac_prog in m4 gm4
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:621: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_M4'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$M4"; then
+  ac_cv_prog_M4="$M4" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_M4="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+M4="$ac_cv_prog_M4"
+if test -n "$M4"; then
+  echo "$ac_t""$M4" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$M4" && break
+done
+test -n "$M4" || M4="m4"
+ ;;
+	*) for ac_prog in $M4 m4 gm4
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:656: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_M4'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$M4"; then
+  ac_cv_prog_M4="$M4" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_M4="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+M4="$ac_cv_prog_M4"
+if test -n "$M4"; then
+  echo "$ac_t""$M4" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$M4" && break
+done
+test -n "$M4" || M4="m4"
+ ;;
+    esac
+    echo $ac_n "checking m4 flags""... $ac_c" 1>&6
+echo "configure:688: checking m4 flags" >&5
+    case "${M4FLAGS-unset}" in
+	unset) M4FLAGS=-B10000 ;;
+    esac
+    echo "$ac_t""$M4FLAGS" 1>&6
+    
+
+
+    # Because we must have a C compiler, we treat an unset CC
+    # the same as an empty CC.
+    case "${CC}" in
+	'')
+	    case `uname` in
+		ULTRIX)
+		    # The native ULTRIX C compiler isn't standard.
+		    ccs='gcc cc'
+		    ;;
+		*)
+		    # xlc is before c89 because AIX's sizeof(long long)
+		    # differs between the two.
+		    #
+		    ccs='xlc c89 acc cc gcc'
+		    ;;
+	    esac
+	    for cc in $ccs; do
+		# Extract the first word of "$cc", so it can be a program name with args.
+set dummy $cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:716: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="$cc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+		case "$CC" in
+		    '') ;;
+		    *)  break
+			;;
+		esac
+	    done
+	    case "${CC}" in
+		'')
+		    { echo "configure: error: "Could not find C compiler"" 1>&2; exit 1; }
+		    ;;
+	    esac
+	    ;;
+    esac
+    #
+    # On some systems, a discovered compiler nevertheless won't
+    # work (due to licensing, for example); thus, we check the
+    # compiler with a test program.
+    # 
+    echo $ac_n "checking C compiler \"$CC\"""... $ac_c" 1>&6
+echo "configure:761: checking C compiler \"$CC\"" >&5
+    cat > conftest.$ac_ext <<EOF
+#line 763 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:770: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  echo "$ac_t""works" 1>&6
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  echo "$ac_t""failed to compile test program" 1>&6
+fi
+rm -f conftest*
+    
+    case "$CC" in
+	*gcc*)
+	    GCC=yes		# Expected by autoconf(1) macros
+	    ;;
+    esac
+    case `uname -sr` in
+	'HP-UX A.09'*)
+	    cat >> confdefs.h <<\EOF
+#define _HPUX_SOURCE 1
+EOF
+
+	    ;;
+    esac
+
+
+    echo $ac_n "checking how to make dependencies""... $ac_c" 1>&6
+echo "configure:797: checking how to make dependencies" >&5
+    case `uname -s` in
+	IRIX*|OSF1)
+	    CC_MAKEDEPEND='cc -M'
+	    ;;
+	SunOS)
+	    case `uname -r` in
+		4*)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		5*|*)
+		    CC_MAKEDEPEND='cc -xM'
+		    ;;
+	    esac
+	    ;;
+	ULTRIX)
+	    case `uname -m` in
+		RISC)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		VAX)	# Can't handle prototypes in netcdf.h
+		    ;;
+	    esac
+	    ;;
+	AIX)	# Writes to .u files rather than standard out
+	    ;;
+	HP-UX)	# Writes escaped newlines to standard error
+	    ;;
+    esac
+    case "${CC_MAKEDEPEND}" in
+	'')
+	    CC_MAKEDEPEND=false
+	    ;;
+    esac
+    echo "$ac_t""$CC_MAKEDEPEND" 1>&6
+    
+
+
+    case "${CXX-unset}" in
+	unset)
+	    case `uname` in
+		AIX)
+		    preferred_cxx='xlC'
+		    ;;
+	    esac
+	    possible_cxxs="${preferred_cxx} CC cxx c++ g++ gcc"
+	    ;;
+	'') echo "configure: warning: "Empty CXX variable"" 1>&2
+	    possible_cxxs=
+	    ;;
+	*)  possible_cxxs=$CXX
+	    ;;
+    esac
+    case "${possible_cxxs}" in
+	'') CXX=
+	    ;;
+	*)  
+	    ac_ext=C
+# CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='${CXX-g++} -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cxx_cross
+
+	    for cxx in $possible_cxxs; do
+		# Extract the first word of "$cxx", so it can be a program name with args.
+set dummy $cxx; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:865: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CXX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CXX="$cxx"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+CXX="$ac_cv_prog_CXX"
+if test -n "$CXX"; then
+  echo "$ac_t""$CXX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+		case "$CXX" in
+		    '') ;;
+		    *)  # On some systems, a discovered compiler nevertheless
+			# won't work (because it's a script to a non-existant
+			# executable, for example); thus, we check the
+			# compiler with a test program.  We also test
+			# for <iostream.h> and the standard C++ library
+			# because we need these to work.
+			# 
+			echo $ac_n "checking C++ compiler \"$CXX\"""... $ac_c" 1>&6
+echo "configure:901: checking C++ compiler \"$CXX\"" >&5
+			if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 906 "configure"
+#include "confdefs.h"
+
+				#include <iostream.h>
+				int main() {
+				    cout << "";
+				    return 0;
+				}
+			    
+EOF
+if { (eval echo configure:916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  
+				echo "$ac_t""works" 1>&6
+				break
+			    
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  
+				echo "configure: warning: $CXX failed on test program" 1>&2
+				CXX=
+				unset ac_cv_prog_CXX
+			    
+fi
+rm -fr conftest*
+fi
+
+			;;
+		esac
+	    done
+	    ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+	    case "${CXX}" in
+		'') echo "configure: warning: "Could not find working C++ compiler"" 1>&2
+		    echo "configure: warning: Setting CXX to the empty string" 1>&2
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${CXX}" in
+	'') echo "configure: warning: The C++ interface will not be built" 1>&2
+	    ;;
+    esac
+    
+    case `uname` in
+	'HP-UX A.09'*)
+	    cat >> confdefs.h <<\EOF
+#define _HPUX_SOURCE 1
+EOF
+
+	    ;;
+    esac
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:967: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 982 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:988: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 999 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1005: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -nologo -E"
+  cat > conftest.$ac_ext <<EOF
+#line 1016 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1022: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+
+    
+    case "${FC+set}" in
+	set)
+	    case "$FC" in
+		'')
+		    echo "configure: warning: Fortran-77 compiler is explicitly null" 1>&2
+		    ;;
+		*)
+		    echo $ac_n "checking user-defined Fortran-77 compiler \"$FC\"""... $ac_c" 1>&6
+echo "configure:1056: checking user-defined Fortran-77 compiler \"$FC\"" >&5
+		    cat <<EOF >conftest.f
+                        CALL FOO
+                        END
+EOF
+		    doit='$FC -c ${FFLAGS} conftest.f'
+		    if { (eval echo configure:1062: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+			echo "$ac_t""works" 1>&6
+		    else
+			echo "$ac_t""failed to compile test program" 1>&6
+			FC=
+		    fi
+		    rm -f conftest.*
+		    ;;
+	    esac
+	    ;;
+	*)
+	    case "${F90+set}" in
+		set)
+		    FC=$F90
+		    FFLAGS="${FFLAGS-${F90FLAGS--O}}"
+		    FLIBS="${FLIBS-${F90LIBS-}}"
+		    echo $ac_n "checking \"$FC\" as Fortran-77 compiler""... $ac_c" 1>&6
+echo "configure:1079: checking \"$FC\" as Fortran-77 compiler" >&5
+		    cat <<EOF >conftest.f
+                        CALL FOO
+                        END
+EOF
+		    doit='$FC -c ${FFLAGS} conftest.f'
+		    if { (eval echo configure:1085: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+			echo "$ac_t""works" 1>&6
+		    else
+			echo "$ac_t""failed to compile test program" 1>&6
+			unset FC
+		    fi
+		    rm -f conftest.*
+		    ;;
+	    esac
+	    case "${FC-unset}" in
+		unset)
+		    case `uname -sr` in
+			AIX*)
+			    # xlf90(1) thinks fortran/ftest.F has bad syntax.
+			    forts="xlf f77"
+			    ;;
+			BSD/OS*|FreeBSD*)
+			    forts="f77 fort77 g77"
+			    ;;
+			HP-UX*)
+			    # f77(1) doesn't have the -L option.
+			    forts=fort77
+			    FLIBS=-lU77
+			    ;;
+			IRIX*)
+			    # f90(1) can't link with c89(1)-compiled objects
+			    forts=f77
+			    ;;
+			IRIX64*)
+			    forts='f77 g77 fort77'
+			    ;;
+			Linux*)
+			    forts="f77 fort77 g77"
+			    ;;
+			OSF1*)
+			    # The use of f90(1) results in the following for
+			    # an unknown reason (`make' works in the fortran/
+			    # directory):
+			    # f90 -c -I../libsrc ftest.F 
+			    # Last chance handler: pc = 0xa971b8, 
+			    # sp = 0x3fece0, ra = 0xa971b8
+			    # Last chance handler: internal exception: unwinding
+			    forts="f77"
+			    ;;
+			'SunOS 4'*)
+			    forts='f77 g77 fort77'
+			    ;;
+			'SunOS 5'*)
+			    # SunOS's f90(1) has problems passing a C `char'
+			    # as a Fortran `integer*1' => use f77(1)
+			    forts="f77"
+			    ;;
+			sn*|UNICOS*|unicos*)
+			    forts="fort77 cf77 f77 g77 f90"
+			    ;;
+			*)
+			    forts="xlf fort77 ghf77 f77 cf77 g77 xlf90 f90"
+			    ;;
+		    esac
+		    for fc in $forts; do
+			# Extract the first word of "$fc", so it can be a program name with args.
+set dummy $fc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1148: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_FC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$FC"; then
+  ac_cv_prog_FC="$FC" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_FC="$fc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+FC="$ac_cv_prog_FC"
+if test -n "$FC"; then
+  echo "$ac_t""$FC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+			case "${FC}" in
+			    '')
+				;;
+			    *)
+				#
+				# On some systems, a discovered compiler
+				# nevertheless won't work (due to licensing,
+				# for example); thus, we check the compiler
+				# with a test program.
+				# 
+				cat <<EOF >conftest.f
+				    CALL FOO
+				    END
+EOF
+				doit='$FC -c ${FFLAGS} conftest.f'
+				if { (eval echo configure:1189: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+				    break
+				else
+				    echo "$ac_t""failed to compile test program" 1>&6
+				    unset FC
+				    unset ac_cv_prog_FC
+				fi
+				;;
+			esac
+		    done
+		    rm -f conftest.*
+		    case "${FC}" in
+			'') echo "configure: warning: "Could not find working Fortran-77 compiler"" 1>&2
+			    ;;
+		    esac
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${FC}" in
+	'') echo "configure: warning: "The Fortran-77 interface will not be built"" 1>&2
+	    ;;
+    esac
+    
+    
+    
+    #
+    # Set the make(1) macro for compiling a .F file.
+    #
+    case "${FPP-}" in
+    '')
+	echo $ac_n "checking for Fortran .F compiler""... $ac_c" 1>&6
+echo "configure:1221: checking for Fortran .F compiler" >&5
+	echo "$ac_t""$COMPILE_F" 1>&6
+	case "${COMPILE_F-unset}" in
+	unset)
+	    case "${FC}" in
+	    '')
+		COMPILE_F=
+		;;
+	    *)
+		echo $ac_n "checking if Fortran-77 compiler handles *.F files""... $ac_c" 1>&6
+echo "configure:1231: checking if Fortran-77 compiler handles *.F files" >&5
+		cat >conftest.h <<\EOF
+#define J 1
+EOF
+		cat >conftest.F <<\EOF
+#include "conftest.h"
+#define N 5
+		  real r(J,N)
+		  end
+EOF
+		doit='$FC -o conftest ${FFLAGS} conftest.F ${FLIBS}'
+		if { (eval echo configure:1242: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    COMPILE_F='$(COMPILE.f) $(FPPFLAGS)'
+		    echo "$ac_t""yes" 1>&6
+		else
+		    COMPILE_F=
+		    echo "$ac_t""no" 1>&6
+		fi
+		rm -f conftest*
+		;;
+	    esac
+	    ;;
+	esac
+	;;
+    *)
+	unset COMPILE_F
+	;;
+    esac
+    case "${COMPILE_F-}" in
+	'') 
+    echo $ac_n "checking for Fortran preprocessor""... $ac_c" 1>&6
+echo "configure:1262: checking for Fortran preprocessor" >&5
+    case "$FPP" in
+    '')
+	
+	FPP="$CPP"
+	;;
+    esac
+    echo "$ac_t""$FPP" 1>&6
+    
+;;
+    esac
+    
+    FPPFLAGS=${FPPFLAGS-}
+    
+
+
+    case "${F90+set}" in
+	set)
+	    echo $ac_n "checking user-defined Fortran-90 compiler \"$F90\"""... $ac_c" 1>&6
+echo "configure:1281: checking user-defined Fortran-90 compiler \"$F90\"" >&5
+	    cat <<EOF >conftest.f90
+		subroutine foo(bar)
+		integer, intent(in) :: bar
+		end subroutine foo
+EOF
+	    doit='$F90 -c ${F90FLAGS} conftest.f90'
+	    if { (eval echo configure:1288: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		echo "$ac_t""works" 1>&6
+	    else
+		echo "$ac_t""failed to compile test program" 1>&6
+		unset F90
+	    fi
+	    rm -f conftest.*
+	    ;;
+	*)
+	    case "${FC+set}" in
+		set)
+		    F90=$FC
+		    F90FLAGS="${F90FLAGS-${FFLAGS--O}}"
+		    F90LIBS="${F90LIBS-${FLIBS}}"
+		    cat <<EOF >conftest.f90
+			program foo
+			call bar(1)
+			end program foo
+			subroutine bar(bof)
+			integer, intent(in) :: bof
+			end subroutine bar
+EOF
+		    echo $ac_n "checking \"$F90\" as Fortran-90 compiler""... $ac_c" 1>&6
+echo "configure:1311: checking \"$F90\" as Fortran-90 compiler" >&5
+		    doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}'
+		    if { (eval echo configure:1313: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+			doit=./conftest
+			if { (eval echo configure:1315: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+			    echo "$ac_t""works" 1>&6
+			else
+			    echo "$ac_t""failed to build executable program" 1>&6
+			    unset F90
+			fi
+		    else
+			echo "$ac_t""failed to build test program" 1>&6
+			unset F90
+		    fi
+		    rm -f conftest*
+		    ;;
+	    esac
+	    case "${F90-unset}" in
+		unset)
+		    cat <<EOF >conftest.f90
+			program foo
+			call bar(1)
+			end program foo
+			subroutine bar(bof)
+			integer, intent(in) :: bof
+			end subroutine bar
+EOF
+		    for f90 in xlf90 f90; do
+			# Extract the first word of "$f90", so it can be a program name with args.
+set dummy $f90; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1342: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_F90'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$F90"; then
+  ac_cv_prog_F90="$F90" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_F90="$f90"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+F90="$ac_cv_prog_F90"
+if test -n "$F90"; then
+  echo "$ac_t""$F90" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+			case "${F90}" in
+			    '')
+				;;
+			    *)
+				echo $ac_n "checking Fortran-90 compiler \"$F90\"""... $ac_c" 1>&6
+echo "configure:1373: checking Fortran-90 compiler \"$F90\"" >&5
+				doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}'
+				if { (eval echo configure:1375: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+				    doit=./conftest
+				    if { (eval echo configure:1377: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+					echo "$ac_t""works" 1>&6
+					break;
+				    else
+					echo "$ac_t""failed to build executable program" 1>&6
+					unset F90
+					unset ac_cv_prog_F90
+				    fi
+				else
+				    echo "$ac_t""failed to build test program" 1>&6
+				    unset F90
+				    unset ac_cv_prog_F90
+				fi
+				;;
+			esac
+		    done
+		    rm -f conftest*
+		    case "${F90}" in
+			'') echo "configure: warning: "Could not find working Fortran-90 compiler"" 1>&2
+			    ;;
+		    esac
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${F90}" in
+	'')
+	    echo "configure: warning: "The Fortran-90 interface will not be built"" 1>&2
+	    ;;
+	*f90*)
+	    case `uname -s` in
+		IRIX*)
+		    NETCDF_MOD=NETCDF.mod
+		    ;;
+		*)
+		    NETCDF_MOD=netcdf.mod
+		    ;;
+	    esac
+	    
+	    ;;
+    esac
+    
+    
+    
+
+
+    echo "checking for nm utility" 1>&6
+echo "configure:1424: checking for nm utility" >&5
+    case "${NM-unset}" in
+	unset) for ac_prog in nm
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1431: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_NM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_NM="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+NM="$ac_cv_prog_NM"
+if test -n "$NM"; then
+  echo "$ac_t""$NM" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$NM" && break
+done
+test -n "$NM" || NM="nm"
+ ;;
+	*) for ac_prog in $NM nm
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:1466: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_NM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_NM="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+NM="$ac_cv_prog_NM"
+if test -n "$NM"; then
+  echo "$ac_t""$NM" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$NM" && break
+done
+test -n "$NM" || NM="nm"
+ ;;
+    esac
+    echo $ac_n "checking nm flags""... $ac_c" 1>&6
+echo "configure:1498: checking nm flags" >&5
+    case "${NMFLAGS-unset}" in
+	unset) NMFLAGS= ;;
+    esac
+    echo "$ac_t""$NMFLAGS" 1>&6
+    
+
+
+    
+    case "$FC" in
+	'') ;;
+	*)
+	    
+	    
+	    
+	    echo $ac_n "checking for C-equivalent to Fortran routine \"SUB\"""... $ac_c" 1>&6
+echo "configure:1514: checking for C-equivalent to Fortran routine \"SUB\"" >&5
+	    cat >conftest.f <<\EOF
+              call sub()
+              end
+EOF
+	    doit='$FC -c ${FFLAGS} conftest.f'
+	    if { (eval echo configure:1520: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		FCALLSCSUB=`$NM $NMFLAGS conftest.o | awk '
+		    /SUB_/{print "SUB_";exit}
+		    /SUB/ {print "SUB"; exit}
+		    /sub_/{print "sub_";exit}
+		    /sub/ {print "sub"; exit}'`
+		case "$FCALLSCSUB" in
+		    '') { echo "configure: error: not found" 1>&2; exit 1; }
+			;;
+		    *)  echo "$ac_t""$FCALLSCSUB" 1>&6
+			;;
+		esac
+	    else
+		{ echo "configure: error: Could not compile conftest.f" 1>&2; exit 1; }
+	    fi
+	    rm -f conftest*
+	    ;;
+    esac
+
+
+    
+    case "$FC" in
+    '')
+	;;
+    *)
+	
+	
+    for ftype in byte integer*1 "integer(kind(1))"; do
+	echo $ac_n "checking for Fortran \"$ftype\"""... $ac_c" 1>&6
+echo "configure:1549: checking for Fortran \"$ftype\"" >&5
+	cat >conftest.f <<EOF
+      subroutine sub(value)
+      $ftype value
+      end
+EOF
+	doit='$FC -c ${FFLAGS} conftest.f'
+	if { (eval echo configure:1556: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    echo "$ac_t""yes" 1>&6
+	    NF_INT1_T=$ftype
+	    cat >> confdefs.h <<EOF
+#define NF_INT1_T $ftype
+EOF
+
+	    break
+	else
+	    echo "$ac_t""no" 1>&6
+	fi
+    done
+    rm -f conftest*
+
+	
+    for ftype in integer*2 "integer(kind(2))"; do
+	echo $ac_n "checking for Fortran \"$ftype\"""... $ac_c" 1>&6
+echo "configure:1573: checking for Fortran \"$ftype\"" >&5
+	cat >conftest.f <<EOF
+      subroutine sub(value)
+      $ftype value
+      end
+EOF
+	doit='$FC -c ${FFLAGS} conftest.f'
+	if { (eval echo configure:1580: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    echo "$ac_t""yes" 1>&6
+	    NF_INT2_T=$ftype
+	    cat >> confdefs.h <<EOF
+#define NF_INT2_T $ftype
+EOF
+
+	    break
+	else
+	    echo "$ac_t""no" 1>&6
+	fi
+    done
+    rm -f conftest*
+
+
+	case "${NF_INT1_T}" in
+	    '') ;;
+	    *)  
+    cat >conftestf.f <<EOF
+           $NF_INT1_T values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in "signed char"; do
+	echo $ac_n "checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1606: checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1615: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1617: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1619: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1621: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT1_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+		
+    cat >conftestf.f <<EOF
+           $NF_INT1_T values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in "short"; do
+	echo $ac_n "checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1654: checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1663: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1665: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1667: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1669: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT1_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+		
+    cat >conftestf.f <<EOF
+           $NF_INT1_T values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in "int"; do
+	echo $ac_n "checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1702: checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1711: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1713: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1715: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1717: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT1_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+		
+    cat >conftestf.f <<EOF
+           $NF_INT1_T values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in "long"; do
+	echo $ac_n "checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1750: checking if Fortran \"$NF_INT1_T\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1759: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1761: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1763: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1765: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT1_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+		;;
+	esac
+	case "${NF_INT2_T}" in
+	    '') ;;
+	    *)  
+    cat >conftestf.f <<EOF
+           $NF_INT2_T values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in short; do
+	echo $ac_n "checking if Fortran \"$NF_INT2_T\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1802: checking if Fortran \"$NF_INT2_T\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1811: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1813: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1815: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1817: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT2_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+		
+    cat >conftestf.f <<EOF
+           $NF_INT2_T values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in int; do
+	echo $ac_n "checking if Fortran \"$NF_INT2_T\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1850: checking if Fortran \"$NF_INT2_T\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1859: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1861: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1863: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1865: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT2_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+		
+    cat >conftestf.f <<EOF
+           $NF_INT2_T values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in long; do
+	echo $ac_n "checking if Fortran \"$NF_INT2_T\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1898: checking if Fortran \"$NF_INT2_T\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1907: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1909: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1911: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1913: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT2_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+		;;
+	esac
+	
+    cat >conftestf.f <<EOF
+           integer values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in int long; do
+	echo $ac_n "checking if Fortran \"integer\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1948: checking if Fortran \"integer\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:1957: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:1959: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:1961: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:1963: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_INT_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+	
+    cat >conftestf.f <<EOF
+           real values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in float double; do
+	echo $ac_n "checking if Fortran \"real\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:1996: checking if Fortran \"real\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:2005: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:2007: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:2009: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:2011: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_REAL_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+	
+    cat >conftestf.f <<EOF
+           doubleprecision values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in double float; do
+	echo $ac_n "checking if Fortran \"doubleprecision\" is C \"$ctype\"""... $ac_c" 1>&6
+echo "configure:2044: checking if Fortran \"doubleprecision\" is C \"$ctype\"" >&5
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[4];
+	    {
+		exit(values[1] != -2 || values[2] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if { (eval echo configure:2053: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if { (eval echo configure:2055: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if { (eval echo configure:2057: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		    doit=./conftest
+		    if { (eval echo configure:2059: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+		        echo "$ac_t""yes" 1>&6
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        cat >> confdefs.h <<EOF
+#define NF_DOUBLEPRECISION_IS_C_$cname 1
+EOF
+
+		        break
+		    else
+		        echo "$ac_t""no" 1>&6
+		    fi
+	        else
+		    { echo "configure: error: Could not link conftestf.o and conftest.o" 1>&2; exit 1; }
+	        fi
+	    else
+		{ echo "configure: error: Could not compile conftestf.f" 1>&2; exit 1; }
+	    fi
+	else
+	    { echo "configure: error: Could not compile conftest.c" 1>&2; exit 1; }
+	fi
+    done
+    rm -f conftest*
+
+
+	
+    echo $ac_n "checking for Fortran-equivalent to netCDF \"byte\"""... $ac_c" 1>&6
+echo "configure:2086: checking for Fortran-equivalent to netCDF \"byte\"" >&5
+    for type in byte integer*1 integer; do
+	cat >conftest.f <<EOF
+               $type foo
+               end
+EOF
+	doit='$FC -c ${FFLAGS} conftest.f'
+	if { (eval echo configure:2093: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    break;
+	fi
+    done
+    rm -f conftest.f conftest.o
+    cat >> confdefs.h <<EOF
+#define NCBYTE_T $type
+EOF
+
+    echo "$ac_t""$type" 1>&6
+    NCBYTE_T=$type
+
+
+	
+    echo $ac_n "checking for Fortran-equivalent to netCDF \"short\"""... $ac_c" 1>&6
+echo "configure:2108: checking for Fortran-equivalent to netCDF \"short\"" >&5
+    for type in integer*2 integer; do
+	cat >conftest.f <<EOF
+               $type foo
+               end
+EOF
+	doit='$FC -c ${FFLAGS} conftest.f'
+	if { (eval echo configure:2115: \"$doit\") 1>&5; (eval $doit) 2>&5; }; then
+	    break;
+	fi
+    done
+    rm -f conftest.f conftest.o
+    cat >> confdefs.h <<EOF
+#define NCSHORT_T $type
+EOF
+
+    echo "$ac_t""$type" 1>&6
+    NCSHORT_T=$type
+
+
+
+
+	;;
+    esac
+
+
+    echo "checking for math library" 1>&6
+echo "configure:2135: checking for math library" >&5
+    case "${MATHLIB}" in
+	'')
+	    echo $ac_n "checking for tanh in -lc""... $ac_c" 1>&6
+echo "configure:2139: checking for tanh in -lc" >&5
+ac_lib_var=`echo c'_'tanh | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lc  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2147 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char tanh();
+
+int main() {
+tanh()
+; return 0; }
+EOF
+if { (eval echo configure:2158: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  MATHLIB=
+else
+  echo "$ac_t""no" 1>&6
+echo $ac_n "checking for tanh in -lm""... $ac_c" 1>&6
+echo "configure:2177: checking for tanh in -lm" >&5
+ac_lib_var=`echo m'_'tanh | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lm  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2185 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char tanh();
+
+int main() {
+tanh()
+; return 0; }
+EOF
+if { (eval echo configure:2196: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  MATHLIB=-lm
+else
+  echo "$ac_t""no" 1>&6
+MATHLIB=
+fi
+
+fi
+
+	    ;;
+	*)
+	    echo "$ac_t""$MATHLIB (user defined)" 1>&6
+	    ;;
+    esac
+    
+
+
+    echo "checking for ar utility" 1>&6
+echo "configure:2228: checking for ar utility" >&5
+    case "${AR-unset}" in
+	unset) for ac_prog in ar
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2235: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AR="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+  echo "$ac_t""$AR" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AR" && break
+done
+test -n "$AR" || AR="ar"
+ ;;
+	*) for ac_prog in $AR ar
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2270: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$AR"; then
+  ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_AR="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+  echo "$ac_t""$AR" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AR" && break
+done
+test -n "$AR" || AR="ar"
+ ;;
+    esac
+    echo $ac_n "checking ar flags""... $ac_c" 1>&6
+echo "configure:2302: checking ar flags" >&5
+    case "${ARFLAGS-unset}" in
+	unset) ARFLAGS=cru ;;
+    esac
+    echo "$ac_t""$ARFLAGS" 1>&6
+    
+
+
+    echo "checking for nm utility" 1>&6
+echo "configure:2311: checking for nm utility" >&5
+    case "${NM-unset}" in
+	unset) for ac_prog in nm
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2318: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_NM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_NM="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+NM="$ac_cv_prog_NM"
+if test -n "$NM"; then
+  echo "$ac_t""$NM" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$NM" && break
+done
+test -n "$NM" || NM="nm"
+ ;;
+	*) for ac_prog in $NM nm
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2353: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_NM'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$NM"; then
+  ac_cv_prog_NM="$NM" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_NM="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+NM="$ac_cv_prog_NM"
+if test -n "$NM"; then
+  echo "$ac_t""$NM" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$NM" && break
+done
+test -n "$NM" || NM="nm"
+ ;;
+    esac
+    echo $ac_n "checking nm flags""... $ac_c" 1>&6
+echo "configure:2385: checking nm flags" >&5
+    case "${NMFLAGS-unset}" in
+	unset) NMFLAGS= ;;
+    esac
+    echo "$ac_t""$NMFLAGS" 1>&6
+    
+
+# Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:2395: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$RANLIB"; then
+  ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_RANLIB="ranlib"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+  echo "$ac_t""$RANLIB" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+ac_safe=`echo "stdlib.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for stdlib.h""... $ac_c" 1>&6
+echo "configure:2424: checking for stdlib.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2429 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2434: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+cat >> confdefs.h <<\EOF
+#define NO_STDLIB_H 1
+EOF
+
+fi
+
+ac_safe=`echo "sys/types.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for sys/types.h""... $ac_c" 1>&6
+echo "configure:2461: checking for sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2466 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2471: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+cat >> confdefs.h <<\EOF
+#define NO_SYS_TYPES_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for strerror""... $ac_c" 1>&6
+echo "configure:2497: checking for strerror" >&5
+if eval "test \"`echo '$''{'ac_cv_func_strerror'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2502 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char strerror(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char strerror();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_strerror) || defined (__stub___strerror)
+choke me
+#else
+strerror();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2525: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_strerror=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_strerror=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'strerror`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+cat >> confdefs.h <<\EOF
+#define NO_STRERROR 1
+EOF
+
+fi
+
+
+    echo $ac_n "checking for working ftruncate()""... $ac_c" 1>&6
+echo "configure:2550: checking for working ftruncate()" >&5
+    if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2555 "configure"
+#include "confdefs.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+main()
+{
+    char*	path = tmpnam(NULL);
+    int		exitStatus = 1;
+
+    if (path != NULL)
+    {
+	int	fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
+
+	if (fd != -1)
+	{
+	    if (write(fd, "0", 1) == 1)
+	    {
+		off_t	pos = lseek(fd, 0, SEEK_CUR);
+
+		if (pos != (off_t)-1)
+		{
+		    if (ftruncate(fd, 512) != -1)
+		    {
+			if (pos == lseek(fd, 0, SEEK_CUR))
+			{
+			    if (lseek(fd, 0, SEEK_SET) == 0)
+			    {
+				char	buf[512];
+
+				if (read(fd, buf, 512) == 512)
+				    exitStatus = 0;
+			    }
+			}
+		    }
+		}
+	    }
+	    close(fd);
+	    unlink(path);
+	}
+    }
+
+    return exitStatus;
+}
+    
+EOF
+if { (eval echo configure:2603: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  echo "$ac_t""yes" 1>&6
+	cat >> confdefs.h <<\EOF
+#define HAVE_FTRUNCATE 1
+EOF
+
+    
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  echo "$ac_t""no" 1>&6
+    
+fi
+rm -fr conftest*
+fi
+
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
+echo "configure:2625: checking for working alloca.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2630 "configure"
+#include "confdefs.h"
+#include <alloca.h>
+int main() {
+char *p = alloca(2 * sizeof(int));
+; return 0; }
+EOF
+if { (eval echo configure:2637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_header_alloca_h=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_alloca_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
+if test $ac_cv_header_alloca_h = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA_H 1
+EOF
+
+fi
+
+echo $ac_n "checking for alloca""... $ac_c" 1>&6
+echo "configure:2658: checking for alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2663 "configure"
+#include "confdefs.h"
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  if HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int main() {
+char *p = (char *) alloca(1);
+; return 0; }
+EOF
+if { (eval echo configure:2691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  ac_cv_func_alloca_works=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_func_alloca_works=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
+if test $ac_cv_func_alloca_works = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ALLOCA 1
+EOF
+
+fi
+
+if test $ac_cv_func_alloca_works = no; then
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+  # that cause trouble.  Some versions do not even contain alloca or
+  # contain a buggy version.  If you still want to use their alloca,
+  # use ar to extract alloca.o from them instead of compiling alloca.c.
+  ALLOCA=alloca.${ac_objext}
+  cat >> confdefs.h <<\EOF
+#define C_ALLOCA 1
+EOF
+
+
+echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
+echo "configure:2723: checking whether alloca needs Cray hooks" >&5
+if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2728 "configure"
+#include "confdefs.h"
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "webecray" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_os_cray=yes
+else
+  rm -rf conftest*
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_os_cray" 1>&6
+if test $ac_cv_os_cray = yes; then
+for ac_func in _getb67 GETB67 getb67; do
+  echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2753: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2758 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2781: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  cat >> confdefs.h <<EOF
+#define CRAY_STACKSEG_END $ac_func
+EOF
+
+  break
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+done
+fi
+
+echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
+echo "configure:2808: checking stack direction for C alloca" >&5
+if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_c_stack_direction=0
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2816 "configure"
+#include "confdefs.h"
+find_stack_direction ()
+{
+  static char *addr = 0;
+  auto char dummy;
+  if (addr == 0)
+    {
+      addr = &dummy;
+      return find_stack_direction ();
+    }
+  else
+    return (&dummy > addr) ? 1 : -1;
+}
+main ()
+{
+  exit (find_stack_direction() < 0);
+}
+EOF
+if { (eval echo configure:2835: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_stack_direction=1
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_stack_direction=-1
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
+cat >> confdefs.h <<EOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+EOF
+
+fi
+
+echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
+echo "configure:2857: checking for st_blksize in struct stat" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2862 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+struct stat s; s.st_blksize;
+; return 0; }
+EOF
+if { (eval echo configure:2870: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_struct_st_blksize=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_struct_st_blksize=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
+if test $ac_cv_struct_st_blksize = yes; then
+  cat >> confdefs.h <<\EOF
+#define HAVE_ST_BLKSIZE 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for IEEE floating point format""... $ac_c" 1>&6
+echo "configure:2892: checking for IEEE floating point format" >&5
+if test "$cross_compiling" = yes; then
+  :
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2897 "configure"
+#include "confdefs.h"
+#ifndef NO_FLOAT_H
+#include <float.h>
+#endif
+
+#define EXIT_NOTIEEE	1
+#define EXIT_MAYBEIEEE	0
+
+int
+main()
+{
+#if	defined(FLT_RADIX)	&& FLT_RADIX != 2
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MAX_EXP)	&& DBL_MAX_EXP != 1024
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MANT_DIG)	&& DBL_MANT_DIG != 53
+		return EXIT_NOTIEEE;
+#elif 	defined(FLT_MAX_EXP)	&& !(FLT_MAX_EXP == 1024 || FLT_MAX_EXP == 128)
+		return EXIT_NOTIEEE;
+#elif	defined(FLT_MANT_DIG)	&& !(FLT_MANT_DIG == 53 || FLT_MANT_DIG == 24)
+		return EXIT_NOTIEEE;
+#else
+	/* (assuming eight bit char) */
+	if(sizeof(double) != 8)
+		return EXIT_NOTIEEE;
+	if(!(sizeof(float) == 4 || sizeof(float) == 8))
+		return EXIT_NOTIEEE;
+
+	return EXIT_MAYBEIEEE;
+#endif
+}
+EOF
+if { (eval echo configure:2930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_ieeefloat=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_ieeefloat=no
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_ieeefloat" 1>&6
+if test $ac_cv_c_ieeefloat = no; then
+  cat >> confdefs.h <<\EOF
+#define NO_IEEE_FLOAT 1
+EOF
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2951: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2956 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2964: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  ac_cv_header_stdc=yes
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2981 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  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 <<EOF
+#line 2999 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  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 <<EOF
+#line 3020 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#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)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:3031: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  :
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:3055: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3060 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_size_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+  cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:3088: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3093 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_off_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+  cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for ssize_t""... $ac_c" 1>&6
+echo "configure:3121: checking for ssize_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3126 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])ssize_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_ssize_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_ssize_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_ssize_t" 1>&6
+if test $ac_cv_type_ssize_t = no; then
+  cat >> confdefs.h <<\EOF
+#define ssize_t int
+EOF
+
+fi
+
+echo $ac_n "checking for ptrdiff_t""... $ac_c" 1>&6
+echo "configure:3154: checking for ptrdiff_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_ptrdiff_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3159 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])ptrdiff_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_ptrdiff_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_ptrdiff_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_ptrdiff_t" 1>&6
+if test $ac_cv_type_ptrdiff_t = no; then
+  cat >> confdefs.h <<\EOF
+#define ptrdiff_t int
+EOF
+
+fi
+
+echo $ac_n "checking for uchar""... $ac_c" 1>&6
+echo "configure:3187: checking for uchar" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uchar'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3192 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "(^|[^a-zA-Z_0-9])uchar[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_uchar=yes
+else
+  rm -rf conftest*
+  ac_cv_type_uchar=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_uchar" 1>&6
+if test $ac_cv_type_uchar = no; then
+  cat >> confdefs.h <<\EOF
+#define uchar unsigned char
+EOF
+
+fi
+
+echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
+echo "configure:3220: checking whether char is unsigned" >&5
+if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$GCC" = yes; then
+  # GCC predefines this symbol on systems where it applies.
+cat > conftest.$ac_ext <<EOF
+#line 3227 "configure"
+#include "confdefs.h"
+#ifdef __CHAR_UNSIGNED__
+  yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "yes" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_c_char_unsigned=yes
+else
+  rm -rf conftest*
+  ac_cv_c_char_unsigned=no
+fi
+rm -f conftest*
+
+else
+if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3249 "configure"
+#include "confdefs.h"
+/* volatile prevents gcc2 from optimizing the test away on sparcs.  */
+#if !defined(__STDC__) || __STDC__ != 1
+#define volatile
+#endif
+main() {
+  volatile char c = 255; exit(c < 0);
+}
+EOF
+if { (eval echo configure:3259: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_char_unsigned=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_char_unsigned=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_char_unsigned" 1>&6
+if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
+  cat >> confdefs.h <<\EOF
+#define __CHAR_UNSIGNED__ 1
+EOF
+
+fi
+
+echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+echo "configure:3283: checking whether byte ordering is bigendian" >&5
+if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+cat > conftest.$ac_ext <<EOF
+#line 3290 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:3301: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  # It does; now see whether it defined to BIG_ENDIAN or not.
+cat > conftest.$ac_ext <<EOF
+#line 3305 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:3316: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  ac_cv_c_bigendian=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_c_bigendian=no
+fi
+rm -f conftest*
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+if test $ac_cv_c_bigendian = unknown; then
+if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3336 "configure"
+#include "confdefs.h"
+main () {
+  /* Are we little or big endian?  From Harbison&Steele.  */
+  union
+  {
+    long l;
+    char c[sizeof (long)];
+  } u;
+  u.l = 1;
+  exit (u.c[sizeof (long) - 1] == 1);
+}
+EOF
+if { (eval echo configure:3349: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_c_bigendian=no
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_c_bigendian=yes
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_bigendian" 1>&6
+if test $ac_cv_c_bigendian = yes; then
+  cat >> confdefs.h <<\EOF
+#define WORDS_BIGENDIAN 1
+EOF
+
+fi
+
+echo $ac_n "checking size of short""... $ac_c" 1>&6
+echo "configure:3373: checking size of short" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3381 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(short));
+  return(0);
+}
+EOF
+if { (eval echo configure:3392: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_short=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_short=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_short" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+EOF
+
+
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:3412: checking size of int" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3420 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(int));
+  return(0);
+}
+EOF
+if { (eval echo configure:3431: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_int=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_int=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking size of long""... $ac_c" 1>&6
+echo "configure:3451: checking size of long" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3459 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(long));
+  return(0);
+}
+EOF
+if { (eval echo configure:3470: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_long=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_long=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_long" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+
+echo $ac_n "checking size of float""... $ac_c" 1>&6
+echo "configure:3490: checking size of float" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3498 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(float));
+  return(0);
+}
+EOF
+if { (eval echo configure:3509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_float=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_float=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_float" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_FLOAT $ac_cv_sizeof_float
+EOF
+
+
+echo $ac_n "checking size of double""... $ac_c" 1>&6
+echo "configure:3529: checking size of double" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+    { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3537 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) return(1);
+  fprintf(f, "%d\n", sizeof(double));
+  return(0);
+}
+EOF
+if { (eval echo configure:3548: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_double=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_double=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_double" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_DOUBLE $ac_cv_sizeof_double
+EOF
+
+
+echo $ac_n "checking size of off_t""... $ac_c" 1>&6
+echo "configure:3568: checking size of off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_off_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_sizeof_off_t=0
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3576 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) exit(1);
+  fprintf(f, "%d\n", sizeof(off_t));
+  exit(0);
+}
+EOF
+if { (eval echo configure:3591: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_off_t=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_off_t=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_off_t" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_OFF_T $ac_cv_sizeof_off_t
+EOF
+
+
+echo $ac_n "checking size of size_t""... $ac_c" 1>&6
+echo "configure:3611: checking size of size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_size_t'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test "$cross_compiling" = yes; then
+  ac_cv_sizeof_size_t=0
+else
+  cat > conftest.$ac_ext <<EOF
+#line 3619 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) exit(1);
+  fprintf(f, "%d\n", sizeof(size_t));
+  exit(0);
+}
+EOF
+if { (eval echo configure:3634: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+  ac_cv_sizeof_size_t=`cat conftestval`
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
+  ac_cv_sizeof_size_t=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_size_t" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t
+EOF
+
+
+
+    #
+    # NB: We always want to define WHATIS to prevent the
+    # $(MANDIR)/$(WHATIS) make(1) target from being just $(MANDIR)/ and
+    # conflicting with the (directory creation) target with the same name.
+    #
+    WHATIS=whatis
+    case `uname -sr` in
+	BSD/OS*|FreeBSD*)
+	    # Can't generate a user-database -- only /usr/share/man/whatis.db.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'IRIX64 6.5'|'IRIX 6.5')
+	    MAKEWHATIS_CMD='/usr/lib/makewhatis -M $(MANDIR) $(MANDIR)/whatis'
+	    ;;
+	'IRIX 6'*)
+	    # Can't generate a user-database.
+	    MAKEWHATIS_CMD=
+	    ;;
+	HP-UX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'Linux '*)
+	    # /usr/sbin/makewhatis doesn't work
+	    MAKEWHATIS_CMD=
+	    ;;
+	ULTRIX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	*)
+	    if test -r /usr/man/windex; then
+		WHATIS=windex
+	    fi
+	    for ac_prog in catman makewhatis /usr/lib/makewhatis
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3693: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_prog'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$prog"; then
+  ac_cv_prog_prog="$prog" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_prog="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+prog="$ac_cv_prog_prog"
+if test -n "$prog"; then
+  echo "$ac_t""$prog" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$prog" && break
+done
+
+	    case "$prog" in
+		*catman*)
+		    MAKEWHATIS_CMD=$prog' -w -M $(MANDIR)'
+		    ;;
+		*makewhatis*)
+		    MAKEWHATIS_CMD=$prog' $(MANDIR)'
+		    ;;
+	    esac
+	    ;;
+    esac
+    
+    
+    echo $ac_n "checking for manual-page index command""... $ac_c" 1>&6
+echo "configure:3735: checking for manual-page index command" >&5
+    echo "$ac_t""$MAKEWHATIS_CMD" 1>&6
+
+    echo $ac_n "checking binary distribution directory""... $ac_c" 1>&6
+echo "configure:3739: checking binary distribution directory" >&5
+    case ${FTPBINDIR-unset} in
+	unset)
+	    system=`(system) 2>/dev/null || echo dummy_system`
+	    FTPBINDIR=${FTPDIR-/home/ftp}/pub/binary/$system
+	    ;;
+    esac
+        echo "$ac_t""$FTPBINDIR" 1>&6
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# 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.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# 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.
+(set) 2>&1 |
+  case `(ac_space=' '; set | grep ac_space) 2>&1` in
+  *ac_space=\ *)
+    # `set' does not quote correctly, so add quotes (double-quote substitution
+    # turns \\\\ into \\, and sed turns \\ into \).
+    sed -n \
+      -e "s/'/'\\\\''/g" \
+      -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+    ;;
+  *)
+    # `set' quotes correctly as required by POSIX, so do not add quotes.
+    sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+    ;;
+  esac >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[ 	]*VPATH[ 	]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+    exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version 2.13"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "macros.make src/lib/ncconfig.h:src/lib/ncconfig.in
+" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@SRCDIR@%$SRCDIR%g
+s%@M4@%$M4%g
+s%@M4FLAGS@%$M4FLAGS%g
+s%@CC@%$CC%g
+s%@CC_MAKEDEPEND@%$CC_MAKEDEPEND%g
+s%@CXX@%$CXX%g
+s%@FC@%$FC%g
+s%@FLIBS@%$FLIBS%g
+s%@CPP@%$CPP%g
+s%@FPP@%$FPP%g
+s%@COMPILE_F@%$COMPILE_F%g
+s%@FPPFLAGS@%$FPPFLAGS%g
+s%@F90@%$F90%g
+s%@NETCDF_MOD@%$NETCDF_MOD%g
+s%@F90FLAGS@%$F90FLAGS%g
+s%@F90LIBS@%$F90LIBS%g
+s%@NM@%$NM%g
+s%@NMFLAGS@%$NMFLAGS%g
+s%@MATHLIB@%$MATHLIB%g
+s%@AR@%$AR%g
+s%@ARFLAGS@%$ARFLAGS%g
+s%@RANLIB@%$RANLIB%g
+s%@ALLOCA@%$ALLOCA%g
+s%@prog@%$prog%g
+s%@WHATIS@%$WHATIS%g
+s%@MAKEWHATIS_CMD@%$MAKEWHATIS_CMD%g
+s%@FTPBINDIR@%$FTPBINDIR%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"macros.make"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
+ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_uB='\([ 	]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="src/lib/ncconfig.h:src/lib/ncconfig.in
+"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+  cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #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.
+cat >> conftest.vals <<\EOF
+s%^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    # Remove last slash and all that follows it.  Not all systems have dirname.
+      ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+      if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+      # The file is in a subdirectory.
+      test ! -d "$ac_dir" && mkdir "$ac_dir"
+    fi
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
Index: /branches/SDM_SciDAC/doc/netcdf-api.bbl
===================================================================
--- /branches/SDM_SciDAC/doc/netcdf-api.bbl (revision 2)
+++ /branches/SDM_SciDAC/doc/netcdf-api.bbl (revision 2)
@@ -0,0 +1,10 @@
+\begin{thebibliography}{1}
+
+\bibitem{thakur:romio}
+Rajeev Thakur, William Gropp, and Ewing Lusk.
+\newblock Data sieving and collective {I/O} in {ROMIO}.
+\newblock In {\em Proceedings of the Seventh Symposium on the Frontiers of
+  Massively Parallel Computation}, pages 182--189. IEEE Computer Society Press,
+  February 1999.
+
+\end{thebibliography}
Index: /branches/SDM_SciDAC/doc/netcdf-api.tex
===================================================================
--- /branches/SDM_SciDAC/doc/netcdf-api.tex (revision 2)
+++ /branches/SDM_SciDAC/doc/netcdf-api.tex (revision 2)
@@ -0,0 +1,994 @@
+\documentclass[10pt]{article}
+\usepackage{utopia}
+
+\pagestyle{plain}
+
+\addtolength{\hoffset}{-2cm}
+\addtolength{\textwidth}{4cm}
+
+\addtolength{\voffset}{-1.5cm}
+\addtolength{\textheight}{3cm}
+
+\setlength{\parindent}{0pt}
+\setlength{\parskip}{11pt}
+
+\title{A Parallel API for Creating and Reading NetCDF Files}
+
+\begin{document}
+
+\maketitle
+
+\begin{abstract}
+Scientists recognize the importance of portable and efficient mechanisms for
+storing datasets created and used by their applications.  NetCDF is one such
+mechanism and is popular in a number of applicaiton domains because of its
+availability on a wide variety of platforms and its easy to use API.  However,
+this API was originally designed for use in serial codes, and so the semantics
+of the interface are not designed to allow for high performance parallel
+access.
+
+In this work we present a new API for creating and reading NetCDF datasets,
+the \emph{Parallel NetCDF API}.  This interface builds on the original NetCDF
+interface and defines semantics for parallel access to NetCDF datasets.  The
+interface is built on top of MPI-IO, allowing for further performance gains
+through the use of collective I/O optimizations that already exist in MPI-IO
+implementations.
+
+\end{abstract}
+
+\section{Introduction}
+
+NetCDF is a popular package for storing data files in scientific applications.
+NetCDF consists of both an API and a portable file format.  The API provides a
+consistent interface for access NetCDF files across multiple platforms, while
+the NetCDF file format guarantees data portability.
+
+The NetCDF API provides a convenient mechanism for a single process to define
+and access variables and attributes in a NetCDF file.  However, it does not
+define a parallel access mechanism.  In particular there is no mechanism for
+concurrently writing to a NetCDF data file.  Because of this, parallel
+applications operating on NetCDF files must serialize access.  This is
+typically accomplished by shipping all data to and from a single process that
+performs NetCDF operations.  This mode of access is both cumbersome to the
+application programmer and considerably slower than parallel access to the
+NetCDF file.  This mode can be particularly inconvenient when data set sizes
+exceed the size of available memory on a single node; in this case the data
+must be split into pieces to be shipped and written.
+
+In this document we propose an alternative API for accessing NetCDF format
+files in a parallel application.  This API allows all processes in a parallel
+application to access the NetCDF file simultaneously, which is considerably
+more convenient than the serial API and allows for significantly higher
+performance.
+
+\emph{Note subset of interface that we are implementing, including both what
+types we support and any functions that we might be leaving out.}
+
+\section{Preliminaries}
+
+In MPI, communicators are typically used to describe collections of processes
+to MPI calls (e.g. the collective MPI-1 calls).  In our parallel NetCDF API we
+will similarly use a communicator to denote a collection of MPI processes that
+will access a NetCDF file.  By describing this collection of processes, we
+provide the underlying implementation (of our parallel NetCDF API) with
+information that it can use to ensure that the file is kept in a consistent
+state.  
+
+Further, by using the collective operations provided in our parallel NetCDF
+API (ones in which all processes in this collection participate), application
+programmers provide the underlying implementation with an opportunity to
+further optimize access to the NetCDF file.  These optimizations are performed
+without further intervention by the application programmer and have been
+proven to provide huge performance wins in multidimensional dataset access \cite{thakur:romio},
+exactly the kinds of accesses used in NetCDF.
+
+All this said, the original NetCDF interface is made available with a minimum
+of changes so that users migrating from the original NetCDF interface will
+have little trouble moving to this new, parallel NetCDF interface.
+
+The decision to slightly modify the API was not made lightly.  It is
+relatively trivial to port NetCDF to use MPI-IO through the use of the MPI-IO
+independent access calls.  However, it was only though adding this concept of
+a collection of processes simultaneously accessing the file and adding
+collective access semantics that we could hope to eliminate the serialization
+step necessary in the original API or gain the performance advantages
+available from the use of collective optimizations.  Thus our performance
+requirements mandated these small adjustments.
+
+% Finally, some of the calls in our API utilize MPI datatypes.  These datatypes
+% allow one to describe noncontiguous regions of data (in this case memory
+% regions) as an endpoint of a data transfer.
+
+\section{Parallel NetCDF API}
+
+The NetCDF interface breaks access into two \emph{modes}, ``define'' mode and
+``data'' mode.  The define mode is used to describe the data set to be stored,
+while the data mode is used for storing and retrieving data values.
+
+We maintain these modes and (for the most part) maintain the operations when
+in define mode.  We will discuss the API for opening and closing a dataset and
+for moving between modes first, next cover inquiry functions, then cover the
+define mode, attribute functions, and finally discuss the API for data mode.
+
+%
+% PREFIX
+%
+We will prefix our C interface calls with ``ncmpi'' and our Fortran interface
+calls with ``nfmpi''.  This ensures no naming clashes with existing NetCDF
+libraries and does not conflict with the desire to reserve the ``MPI'' prefix
+for functions that are part of the MPI standard.
+
+All of our functions return integer NetCDF status values, just as the original
+NetCDF interface does.
+
+We will only discuss points where our interface deviates from the original
+interface in the following sections. A complete function listing is included
+in Appendix A.
+
+\subsection{Variable and Parameter Types}
+
+%
+% MPI_Offset
+%
+Rather than using \texttt{size\_t} types for size parameters passed in to our
+functions, we choose to use \texttt{MPI\_Offset} type instead.  For many
+systems \texttt{size\_t} is a 32-bit unsigned value, which limits the maximum
+range of values to 4~GBytes.  The \texttt{MPI\_Offset} is typically a 64-bit
+value, so it does not have this limitation.  This gives us room to extend the
+file size capabilities of NetCDF at a later date.
+
+\emph{Add mapping of MPI types to NetCDF types.}
+
+\emph{Is NetCDF already exactly in external32 format?}
+
+\subsection{Dataset Functions}
+
+As mentioned before, we will define a collection of processes that are
+operating on the file by passing in a MPI communicator.  This communicator is
+passed in the call to \texttt{ncmpi\_create} or \texttt{ncmpi\_open}.  These
+calls are collective across all processes in the communicator.  The second
+additional parameter is an \texttt{MPI\_Info}.  This is used to pass hints in
+to the implementation (e.g. expected access pattern, aggregation
+information).  The value \texttt{MPI\_INFO\_NULL} may be passed in if the user
+does not want to take advantage of this feature.
+
+\begin{verbatim}
+int ncmpi_create(MPI_Comm comm, 
+                 const char *path, 
+                 int cmode,
+                 MPI_Info info,
+                 int *ncidp)
+
+int ncmpi_open(MPI_Comm comm, 
+               const char *path, 
+               int omode,
+               MPI_Info info,
+               int *ncidp)
+\end{verbatim}
+
+\subsection{Define Mode Functions}
+
+\emph{All define mode functions are collective} (see Appendix B for
+rationale).
+
+All processes in the communicator must call them with the same values.  At the
+end of the define mode the values passed in by all processes are checked to
+verify that they match, and if they do not then an error is returned from the
+\texttt{ncmpi\_enddef}.
+
+
+\subsection{Inquiry Functions}
+
+\emph{These calls are all collective operations} (see Appendix B for
+rationale).
+
+As in the original NetCDF interface, they may be called from either define or
+data mode.  \emph{ They return information stored prior to the last open,
+enddef, or sync.}
+
+% In the original NetCDF interface the inquiry functions could be called from
+% either data or define mode.  To aid in the implementation of these functions
+% in a parallel library, \emph{inquiry functions may only be called in data mode
+% in the parallel NetCDF API}.  They return information stored prior to the last
+% open, enddef, or sync.  This ensures that the NetCDF metadata need only be
+% kept up-to-date on all nodes when in data mode.
+%
+
+\subsection{Attribute Functions}
+
+\emph{These calls are all collective operations} (see Appendix B for
+rationale).
+
+Attributes in NetCDF are intended for storing scalar or vector values that
+describe a variable in some way.  As such the expectation is that these
+attributes will be small enough to fit into memory.  
+
+In the original interface, attribute operations can be performed in either
+define or data mode; however, it is possible for attribute operations that
+modify attributes (e.g. copy or create attributes) to fail if in data mode.
+This is possible because such operations can cause the amount of space needed
+to grow.  In this case the cost of the operation can be on the order of a copy
+of the entire dataset.  We will maintain these semantics.
+
+\subsection{Data Mode Functions}
+
+The most important change from the original NetCDF interface with respect to
+data mode functions is the split of data mode into two distinct modes:
+\emph{collective data mode} and \emph{independent data mode}.  \emph{By default when
+a user calls \texttt{ncmpi\_enddef} or \texttt{ncmpi\_open}, the user will be
+in collective data mode.}  The expectation is that most users will be using the
+collective operations; these users will never need to switch to independent
+data mode.  In collective data mode, all processes must call the same function
+on the same ncid at the same point in the code.  Different parameters for
+values such as start, count, and stride, are acceptable.  Knowledge that all
+processes will be calling the function allows for additional optimization
+under the API.  In independent mode processes do not need to coordinate calls
+to the API; however, this limits the optimizations that can be applied to I/O operations.
+
+A pair of new dataset operations \texttt{ncmpi\_begin\_indep\_data} and
+\texttt{ncmpi\_end\_indep\_data} switch into and out of independent data mode.
+These calls are collective.  Calling \texttt{ncmpi\_close} or
+\texttt{ncmpi\_redef} also leaves independent data mode.
+
+\begin{verbatim}
+int ncmpi_begin_indep_data(int ncid)
+
+int ncmpi_end_indep_data(int ncid)
+\end{verbatim}
+
+The separation of the data mode into two distinct data modes is necessary to
+provide consistent views of file data when moving between MPI-IO collective
+and independent operations.
+
+We have chosen to implement two collections of data mode functions.  The first
+collection closely mimics the original NetCDF access functions and is intended
+to serve as an easy path of migration from the original NetCDF interface to
+the parallel NetCDF interface.  We call this subset of our parallel NetCDF
+interface the \emph{high level data mode} interface.
+
+The second collection uses more MPI functionality in order to provide better
+handling of internal data representations and to more fully expose the
+capabilities of MPI-IO to the application programmer.  All of the first
+collection will be implemented in terms of these calls.  We will denote this
+the \emph{flexible data mode} interface.
+
+In both collections, both independent and collective operations are provided.
+Collective function names end with \texttt{\_all}.  They are collective across
+the communicator associated with the ncid, so all those processes must call
+the function at the same time.
+
+Remember that in all cases the input data type is converted into the
+appropriate type for the variable stored in the NetCDF file.
+
+\subsubsection{High Level Data Mode Interface}
+
+The independent calls in this interface closely resemble the NetCDF data mode
+interface.  The only major change is the use of \texttt{MPI\_Offset} types in
+place of \texttt{size\_t} types, as described previously.
+
+The collective calls have the same arguments as their independent
+counterparts, but they must be called by all processes in the communicator
+associated with the ncid.
+
+Here are the example prototypes for accessing a strided subarray of a variable
+in a NetCDF file; the remainder of the functions are listed in Appendix A.
+
+In our initial implementation the following data function types will be
+implemented for independent access: single data value read and write (var1),
+entire variable read and write (var), array of values read and write (vara),
+and subsampled array of values read and write (vars).  Collective versions of
+these types will also be provided, with the exception of a collective entire
+variable write; semantically this doesn't make sense.
+
+We could use the same function names for both independent and collective
+operations (relying instead on the mode associated with the ncid); however, we
+feel that the interface is cleaner, and it will be easier to detect bugs, with
+separate calls for independent and collective access.
+
+% \textbf{Strided Subarray Access}
+%
+Independent calls for writing or reading a strided subarray of values to/from
+a NetCDF variable (values are contiguous in memory):
+\begin{verbatim}
+int ncmpi_put_vars_uchar(int ncid, 
+                      int varid, 
+                      const MPI_Offset start[],
+                      const MPI_Offset count[], 
+                      const MPI_Offset stride[],
+                      const unsigned char *up)
+
+int ncmpi_get_vars_uchar(int ncid, 
+                      int varid, 
+                      const MPI_Offset start[],
+                      const MPI_Offset count[], 
+                      const MPI_Offset stride[],
+                      unsigned char *up)
+\end{verbatim}
+
+Collective calls for writing or reading a strided subarray of values to/from a
+NetCDF variable (values are contiguous in memory).
+\begin{verbatim}
+int ncmpi_put_vars_uchar_all(int ncid, 
+                             int varid, 
+                             const MPI_Offset start[],
+                             const MPI_Offset count[], 
+                             const MPI_Offset stride[],
+                             unsigned char *up)
+
+int ncmpi_get_vars_uchar_all(int ncid, 
+                             int varid, 
+                             const MPI_Offset start[],
+                             const MPI_Offset count[],
+                             const MPI_Offset stride[],
+                             unsigned char *up)
+\end{verbatim}
+
+\emph{Note what calls are and aren't implemented at this time.}
+
+\subsubsection{Flexible Data Mode Interface}
+
+This smaller set of functions is all that is needed to implement the data mode
+functions.  These are also made available to the application programmer.
+
+The advantage of these functions is that they allow the programmer to use MPI
+datatypes to describe the in-memory organization of the values.  The only
+mechanism provides in the original NetCDF interface for such a description is
+the mapped array calls.  Mapped arrays are a suboptimal method of describing
+any regular pattern in memory.
+
+In all these functions the varid, start, count, and stride values refer to the
+data in the file (just as in a NetCDF vars-type call).  The buf, count, and
+datatype fields refer to data in memory.
+
+Here are examples for subarray access:
+\begin{verbatim}
+int ncmpi_put_vars(int ncid,
+                   int varid,
+                   MPI_Offset start[],
+                   MPI_Offset count[],
+                   MPI_Offset stride[],
+                   const void *buf,
+                   int count,
+                   MPI_Datatype datatype)
+
+int ncmpi_get_vars(int ncid,
+                   int varid,
+                   MPI_Offset start[],
+                   MPI_Offset count[],
+                   MPI_Offset stride[],
+                   void *buf,
+                   int count,
+                   MPI_Datatype datatype)
+
+int ncmpi_put_vars_all(int ncid,
+                       int varid,
+                       MPI_Offset start[],
+                       MPI_Offset count[],
+                       MPI_Offset stride[],
+                       void *buf,
+                       int count,
+                       MPI_Datatype datatype)
+
+int ncmpi_get_vars_all(int ncid,
+                       int varid,
+                       MPI_Offset start[],
+                       MPI_Offset count[],
+                       MPI_Offset stride[],
+                       void *buf,
+                       int count,
+                       MPI_Datatype datatype)
+\end{verbatim}
+
+
+\subsubsection{Mapping Between NetCDF and MPI Types}
+
+It is assumed here that the datatypes passed to the flexible NetCDF interface
+use only one basic datatype.  For example, the datatype can be arbitrarily
+complex, but it cannot consist of both \texttt{MPI\_FLOAT} and
+\texttt{MPI\_INT} values, but only one of these basic types.
+
+\emph{Describe status of type support.}
+
+
+\subsection{Missing}
+
+Calls that were in John M.'s list but that we haven't mentioned here yet.
+
+Attribute functions, strerror, text functions, get\_vara\_text (?).
+
+\section{Examples}
+
+This section will hopefully soon hold some examples, perhaps based on writing
+out the 1D and 2D Jacobi examples in the Using MPI book using our interface?
+
+\section{Implementation Notes}
+
+Here we will keep any particular implementation details.  As the
+implementation matures, this section should discuss implementation decisions.
+
+One trend that will be seen throughout here is the use of collective I/O
+routines when it would be possible to use independent operations.  There are
+two reasons for this.  First, for some operations (such as reading the
+header), there are important optimizations that can be made to more
+efficiently read data from the I/O system, especially as the number of NetCDF
+application processes increases.  Second, the use of collective routines
+allows for the use of aggregation routines in the MPI-IO implementation.  This
+allows us to redirect I/O to nodes that have access to I/O resources in
+systems where not all processes have access.  This isn't currently possible
+using the independent I/O calls.
+
+See the ROMIO User's Guide for more information on the aggregation hints, in
+particular the \texttt{cb\_config\_list} hint.
+
+\subsection{Questions for Users on Implementation}
+\begin{itemize}
+\item Is this emphasis on collective operations appropriate or problematic?
+\item Is C or Fortran the primary language for NetCDF programs?
+\end{itemize}
+
+\subsection{I/O routines}
+
+All I/O within our implementation will be performed through MPI-IO.
+
+No temporary files will be created at any time.
+
+%
+% HEADER I/O
+%
+\subsection{Header I/O}
+
+\emph{It is assumed that headers are too small to benefit from parallel I/O.}
+
+All header updates will be performed with collective I/O, but only rank 0 will
+provide any input data.  This is important because only through the collective
+calls can our \texttt{cb\_config\_list} hint be used to control what hosts
+actually do writing.  Otherwise we could pick some arbitrary process to do
+I/O, but we have no way of knowing if that was a process that the user
+intended to do I/O in the first place (thus that process might not even be
+able to write to the file!)
+
+Headers are written all at once at \texttt{ncmpi\_enddef}.
+
+Likewise collective I/O will be used when reading the header, which should
+simply be used to read the entire header to everyone on open.
+
+\emph{First cut might not do this.}
+
+\subsection{Code Reuse}
+We will not reuse any NetCDF code.  This will give us an opportunity to leave
+out any code pertaining to optimizations on specific machines (e.g. Cray) that
+we will not need and, more importantly, cannot test.
+
+\subsection{Providing Independent and Collective I/O}
+In order to make use of \texttt{MPI\_File\_set\_view} for both independent and
+collective NetCDF operations, we will need to open the NetCDF file separately
+for both, with the input communicator for collective I/O and with
+MPI\_COMM\_SELF for independent I/O.  However, we can defer opening the file
+for independent access until an independent access call is made if we like.
+This can be an important optimization as we scale.
+
+Synchronization when switching between collective and independent access is
+mandatory to ensure correctness under the MPI I/O model.
+
+\subsection{Outline of I/O}
+
+Outline of steps to I/O:
+\begin{itemize}
+\item MPI\_File is extracted from ncid
+\item variable type is extracted from varid
+\item file view is created from:
+  \begin{itemize}
+  \item metadata associated with ncid
+  \item variable index info, array size, limited/unlimited, type from varid
+  \item start/count/stride info
+  \end{itemize}
+\item datatype/count must match number of elements specified by
+  start/count/stride
+\item status returns normal mpi status information, which is mapped to a
+  NetCDF error code.
+\end{itemize}
+
+
+\section{Future Work}
+
+Since MPI-IO has the capability to perform nonblocking operations, it makes
+sense to provide a NetCDF interface that exposes this capability:
+
+\begin{verbatim}
+ncmpi_iput_vars(int ncid,
+                int varid,
+                MPI_Offset start[],
+                MPI_Offset count[],
+                MPI_Offset stride[],
+                void *buf,
+                int count,
+                MPI_Datatype datatype,
+                MPI_Request *request);
+
+ncmpi_iget_vars(int ncid,
+                int varid,
+                MPI_Offset start[],
+                MPI_Offset count[],
+                MPI_Offset stride[],
+                void *buf,
+                int count,
+                MPI_Datatype datatype,
+                MPI_Request *request);
+
+int ncmpi_wait(MPI_Request *request, 
+               MPI_Status *status);
+
+int ncmpi_test(MPI_Request *request,
+               int *flag,
+               MPI_Status *status);
+\end{verbatim}
+
+%
+% BIBLIOGRAPHY
+%
+\bibliography{./pario}
+\bibliographystyle{plain}
+
+%
+% APPENDIX A: FUNCTION LISTING
+%
+\section*{Appendix A: C API Listing}
+
+%
+% DATASET FUNCTIONS
+%
+\subsection*{A.1  Dataset Functions}
+
+\begin{verbatim}
+int ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp);
+
+int ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp);
+
+int ncmpi_enddef(int ncid);
+
+int ncmpi_redef(int ncid);
+
+int ncmpi_sync(int ncid);
+
+int ncmpi_abort(int ncid);
+
+int ncmpi_begin_indep_data(int ncid);
+
+int ncmpi_end_indep_data(int ncid);
+
+int ncmpi_close(int ncid);
+\end{verbatim}
+
+%
+% INQUIRY FUNCTIONS
+%
+\subsection*{A.2  Inquiry Functions}
+
+\begin{verbatim}
+int ncmpi_inq(int ncid, int *ndimsp, int *nvarsp, int *ngattsp, int *unlimdimidp); 
+
+int ncmpi_inq_ndims(int ncid, int *ndimsp);
+
+int ncmpi_inq_nvars(int ncid, int *nvarsp);
+
+int ncmpi_inq_natts(int ncid, int *ngattsp);
+
+int ncmpi_inq_unlimdim(int ncid, int *unlimdimidp);
+
+int ncmpi_inq_dimid(int ncid, const char *name, int *idp);
+
+int ncmpi_inq_dim(int ncid, int dimid, char *name, MPI_Offset *lenp);
+
+int ncmpi_inq_dimname(int ncid, int dimid, char *name);
+
+int ncmpi_inq_dimlen(int ncid, int dimid, MPI_Offset *lenp);
+
+int ncmpi_inq_var(int ncid, int varid, char *name, nc_type *xtypep, 
+                  int *ndimsp, int *dimidsp, int *nattsp);
+
+int ncmpi_inq_varid(int ncid, const char *name, int *varidp);
+
+int ncmpi_inq_varname(int ncid, int varid, char *name);
+
+int ncmpi_inq_vartype(int ncid, int varid, nc_type *xtypep);
+
+int ncmpi_inq_varndims(int ncid, int varid, int *ndimsp);
+
+int ncmpi_inq_vardimid(int ncid, int varid, int *dimidsp);
+
+int ncmpi_inq_varnatts(int ncid, int varid, int *nattsp);
+
+\end{verbatim}
+
+%
+% DEFINE FUNCTIONS
+%
+\subsection*{A.3  Define Mode Functions}
+
+\begin{verbatim}
+int ncmpi_def_dim(int ncid, const char *name, MPI_Offset len, int *idp);
+
+int ncmpi_def_var(int ncid, const char *name, nc_type xtype, int ndims, 
+                  const int *dimidsp, int *varidp);
+
+int ncmpi_rename_dim(int ncid, int dimid, const char *name);
+
+int ncmpi_rename_var(int ncid, int varid, const char *name);
+
+\end{verbatim}
+%
+% ATTRIBUTE FUNCTIONS
+%
+\subsection*{A.4  Attribute Functions}
+
+\begin{verbatim}
+int ncmpi_inq_att(int ncid, int varid, const char *name, nc_type *xtypep,
+                  MPI_Offset *lenp);
+
+int ncmpi_inq_attid(int ncid, int varid, const char *name, int *idp);
+
+int ncmpi_inq_atttype(int ncid, int varid, const char *name, nc_type *xtypep);
+
+int ncmpi_inq_attlen(int ncid, int varid, const char *name, MPI_Offset *lenp);
+
+int ncmpi_inq_attname(int ncid, int varid, int attnum, char *name);
+
+int ncmpi_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out,
+                   int varid_out);
+
+int ncmpi_rename_att(int ncid, int varid, const char *name, const char *newname);
+
+int ncmpi_del_att(int ncid, int varid, const char *name);
+
+int ncmpi_put_att_text(int ncid, int varid, const char *name, MPI_Offset len,
+                       const char *op);
+
+int ncmpi_get_att_text(int ncid, int varid, const char *name, char *ip);
+
+int ncmpi_put_att_uchar(int ncid, int varid, const char *name, nc_type xtype,
+                        MPI_Offset len, const unsigned char *op);
+
+int ncmpi_get_att_uchar(int ncid, int varid, const char *name, unsigned char *ip);
+
+int ncmpi_put_att_schar(int ncid, int varid, const char *name, nc_type xtype, 
+                        MPI_Offset len, const signed char *op);
+
+int ncmpi_get_att_schar(int ncid, int varid, const char *name, signed char *ip);
+
+int ncmpi_put_att_short(int ncid, int varid, const char *name, nc_type xtype,
+                        MPI_Offset len, const short *op);
+
+int ncmpi_get_att_short(int ncid, int varid, const char *name, short *ip);
+
+int ncmpi_put_att_int(int ncid, int varid, const char *name, nc_type xtype, 
+                      MPI_Offset len, const int *op);
+
+int ncmpi_get_att_int(int ncid, int varid, const char *name, int *ip);
+
+int ncmpi_put_att_long(int ncid, int varid, const char *name,
+                       nc_type xtype, MPI_Offset len, const long *op);
+
+int ncmpi_get_att_long(int ncid, int varid, const char *name, long *ip);
+
+int ncmpi_put_att_float(int ncid, int varid, const char *name,
+                        nc_type xtype, MPI_Offset len, const float *op);
+
+int ncmpi_get_att_float(int ncid, int varid, const char *name, float *ip);
+
+int ncmpi_put_att_double(int ncid, int varid, const char *name, nc_type xtype,
+                         MPI_Offset len, const double *op);
+
+
+int ncmpi_get_att_double(int ncid, int varid, const char *name, double *ip);
+\end{verbatim}
+%
+% DATA FUNCTIONS
+%
+\subsection*{A.5  Data Mode Functions}
+
+Recall that the data mode functions are split into the High Level data mode interface and the
+Flexible data mode interface.
+
+\subsubsection*{A.5.1  High Level Data Mode Interface}
+
+The High Level functions most closely mimic the original NetCDF data mode interface.
+
+\emph{What about the single variable and varm functions?  Are they important?}
+
+\begin{verbatim}
+int ncmpi_put_vara_short_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], const short *op);
+
+int ncmpi_put_vara_short(int ncid, int varid, const MPI_Offset start[], 
+                         const MPI_Offset count[], const short *op);
+
+int ncmpi_put_vara_int_all(int ncid, int varid, const MPI_Offset start[],
+                           const MPI_Offset count[], const int *op);
+
+int ncmpi_put_vara_int(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], const int *op);
+
+int ncmpi_put_vara_float_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], const float *op);
+
+int ncmpi_put_vara_float(int ncid, int varid, const MPI_Offset start[],
+                         const MPI_Offset count[], const float *op);
+
+int ncmpi_put_vara_double_all(int ncid, int varid, const MPI_Offset start[], 
+                              const MPI_Offset count[], const double *op);
+
+int ncmpi_put_vara_double(int ncid, int varid, const MPI_Offset start[],
+                          const MPI_Offset count[], const double *op);
+
+int ncmpi_get_vara_short_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], short *ip);
+
+int ncmpi_get_vara_short(int ncid, int varid, const MPI_Offset start[],
+                         const MPI_Offset count[], short *ip);
+
+int ncmpi_get_vara_int_all(int ncid, int varid, const MPI_Offset start[],
+                           const MPI_Offset count[], int *ip);
+
+int ncmpi_get_vara_int(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], int *ip);
+
+int ncmpi_get_vara_float_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], float *ip);
+
+int ncmpi_get_vara_float(int ncid, int varid, const MPI_Offset start[],
+                         const MPI_Offset count[], float *ip);
+
+int ncmpi_get_vara_double_all(int ncid, int varid, const MPI_Offset start[],
+                              const MPI_Offset count[], double *ip);
+
+int ncmpi_get_vara_double(int ncid, int varid,  const MPI_Offset start[],
+                          const MPI_Offset count[], double *ip);
+
+int ncmpi_put_vars_short_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], const MPI_Offset stride[],
+                             const short *op);
+
+int ncmpi_put_vars_short(int ncid, int varid, const MPI_Offset start[],
+                         const MPI_Offset count[], const MPI_Offset stride[],
+                         const short *op);
+
+int ncmpi_put_vars_int_all(int ncid, int varid, const MPI_Offset start[],
+                           const MPI_Offset count[], const MPI_Offset stride[],
+                           const int *op);
+
+int ncmpi_put_vars_int(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], const MPI_Offset stride[],
+                       const int *op);
+
+int ncmpi_put_vars_float_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], const MPI_Offset stride[],
+                             const float *op);
+
+int ncmpi_put_vars_float(int ncid, int varid, const MPI_Offset start[],
+                         const MPI_Offset count[], const MPI_Offset stride[],
+                         const float *op);
+
+int ncmpi_put_vars_double_all(int ncid, int varid, const MPI_Offset start[],
+                              const MPI_Offset count[], const MPI_Offset stride[],
+                              const double *op);
+
+int ncmpi_put_vars_double(int ncid, int varid, const MPI_Offset start[],
+                          const MPI_Offset count[], const MPI_Offset stride[],
+                          const double *op);
+
+int ncmpi_get_vars_short_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], const MPI_Offset stride[],
+                             short *ip);
+
+int ncmpi_get_vars_short(int ncid, int varid, const MPI_Offset start[],
+                         const MPI_Offset count[], const MPI_Offset stride[],
+                         short *ip);
+
+int ncmpi_get_vars_int_all(int ncid, int varid, const MPI_Offset start[],
+                           const MPI_Offset count[], const MPI_Offset stride[],
+                           int *ip);
+
+int ncmpi_get_vars_int(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], const MPI_Offset stride[], int *ip);
+
+int ncmpi_get_vars_float_all(int ncid, int varid, const MPI_Offset start[],
+                             const MPI_Offset count[], const MPI_Offset stride[],
+                             float *ip);
+
+int ncmpi_get_vars_float(int ncid, int varid, const MPI_Offset start[],
+                         const MPI_Offset count[], const MPI_Offset stride[], float *ip);
+
+int ncmpi_get_vars_double_all(int ncid, int varid, const MPI_Offset start[],
+                              const MPI_Offset count[], const MPI_Offset stride[],
+                              double *ip);
+
+int ncmpi_get_vars_double(int ncid, int varid, const MPI_Offset start[],
+                          const MPI_Offset count[], const MPI_Offset stride[],
+                          double *ip);
+\end{verbatim}
+
+\subsubsection*{A.5.2  Flexible Data Mode Interface}
+
+Note that there are considerably fewer functions in the flexible data mode
+inteface, because these functions can handle all different types with the same
+call.  All of the high level functions are written in terms of these
+functions.
+
+\begin{verbatim}
+int ncmpi_put_vara_all(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], const void *buf, int bufcount,
+                       MPI_Datatype datatype);
+
+int ncmpi_get_vara_all(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], void *buf, int bufcount,
+                       MPI_Datatype datatype);
+
+int ncmpi_put_vara(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const void *buf, int bufcount,
+                   MPI_Datatype datatype);
+
+int ncmpi_get_vara(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], void *buf, int bufcount,
+                   MPI_Datatype datatype);
+
+int ncmpi_put_vars_all(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], const MPI_Offset stride[],
+                       const void *buf, int bufcount, MPI_Datatype datatype);
+
+int ncmpi_get_vars_all(int ncid, int varid, const MPI_Offset start[],
+                       const MPI_Offset count[], const MPI_Offset stride[], void *buf,
+                       int bufcount, MPI_Datatype datatype);
+
+int ncmpi_put_vars(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[], const void *buf,
+                   int bufcount, MPI_Datatype datatype);
+
+int ncmpi_get_vars(int ncid, int varid, const MPI_Offset start[],
+                   const MPI_Offset count[], const MPI_Offset stride[], void *buf,
+                   int bufcount, MPI_Datatype datatype);
+\end{verbatim}
+%
+% APPENDIX B: RATIONALE
+%
+\section*{Appendix B: Rationale}
+
+This section covers the rationale behind our decisions on API specifics.
+
+%
+% define mode function semantics
+%
+\subsection*{B.1  Define Mode Function Semantics}
+
+There are two options to choose from here, either forcing a single process to
+make these calls (funnelled) or forcing all these calls to be collective with
+the same data.  Note that making them collective does \emph{not} imply any
+communication at the time the call is made.
+
+Both of these options allow for better error detection than what we
+previously described (functions independent, anyone could call, only node
+0's data was used).  Error detection could be performed at the end of the
+define mode to minimize costs.
+
+In fact, it is only fractionally more costly to implement collectives than
+funneled (including the error detection).  To do this one simply bcast's
+process 0's values out (which one would have to do anyway) and then
+allgathers a single char or int from everyone indicating if there was a
+problem.
+
+There has to be some synchronization at the end of the define mode in any
+case, so this extra error detection comes at an especially low cost.
+
+\subsection*{B.2  Attribute and Inquiry Function Semantics}
+
+There are similar options here to the ones for define mode functions.
+
+One option would be to make these functions independent.  This would be easy
+for read operations, but would be more difficult for write operations.  In
+particular we would need to gather up modifications at some point in order to
+distribute them out to all processes.  Ordering of modifications might also be
+an issue.  Finally, we would want to constrain use of these independent
+operations to the define mode so that we would have an obvious point at which
+to perform this collect and distribute operation (e.g. \texttt{ncmpi\_enddef}).
+
+Another option would be to make all of these functions collective.  This is an
+unnecessary constraint for the read operations, but it helps in implementing
+the write operations (we can distribute modifications right away) and allows
+us to maintain the use of these functions outside define mode if we wish.
+This is also more consistent with the SPMD model that (we think) our users are
+using.
+
+The final option would be to allow independent use of the read operations but
+force collective use of the write operations.  This would result in confusing
+semantics.
+
+For now we will implement the second option, all collective operation.  Based
+on feedback from users we will consider relaxing this constraint.
+
+\subsubsection*{Questions for Users Regarding Attribute and Inquiry Functions}
+\begin{itemize}
+\item Are attribute calls used in data mode?
+\item Is it inconvenient that the inquiry functions are collective?
+\end{itemize}
+
+\subsection*{B.3  Splitting Data Mode into Collective and Independent Data Modes}
+
+In both independent and collective MPI-IO operations, it is important to be
+able to set the file view to allow for noncontiguous file regions.  However,
+since the \texttt{MPI\_File\_set\_view} is a collective operation, it is
+impossible to use a single file handle to perform collective I/O and still be
+able to arbitrarily reset the file view before an independent operation
+(because all the processes would need to participate in the file set view).
+
+For this reason it is necessary to have two file handles in the case where
+both independent and collective I/O will be performed.  One file handle is
+opened with \texttt{MPI\_COMM\_SELF} and is used for independent operations,
+while the other is opened with the communicator containing all the processes
+for the collective operations.
+
+It is difficult if not impossible in the general case to ensure consistency of
+access when a collection of processes are using multiple MPI\_File handles to
+access the same file with mixed independent and collective operations.
+However, if explicit and collective synchronization points are introduced
+between phases where collective and independent I/O operations will be
+performed, then the correct set of operations to ensure a consistent view can
+be inserted at this point.
+
+\emph{Does this explanation make any sense?  I think we need to document this.}
+
+\subsection*{B.4  Even More MPI-Like Data Mode Functions}
+
+Recall that our flexible NetCDF interface has functions such as:
+\begin{verbatim}
+int ncmpi_put_vars(int ncid,
+                   int varid,
+                   MPI_Offset start[],
+                   MPI_Offset count[],
+                   MPI_Offset stride[],
+                   void *buf,
+                   int count,
+                   MPI_Datatype datatype)
+\end{verbatim}
+
+It is possible to move to an even more MPI-like interface by using an MPI
+datatype to describe the file region in addition to using datatypes for the
+memory region:
+\begin{verbatim}
+int ncmpi_put(int ncid,
+              int varid,
+              MPI_Datatype file_dtype,
+              void *buf,
+              int count,
+              MPI_Datatype mem_dtype)
+\end{verbatim}
+
+At first glance this looks rather elegant.  However, this isn't as clean as it
+seems.  The \texttt{file\_dtype} in this case has to describe the variable
+layout \emph{in terms of the variable array}, not in terms of the file,
+because the user doesn't know about the internal file layout.  So the
+underlying implementation would need to tear apart \texttt{file\_dtype} and
+rebuild a new datatype, on the fly, that corresponded to the data layout in
+the file as a whole.  This is complicated by the fact that
+\texttt{file\_dtype} could be arbitrarily complex.
+
+The flexible NetCDF interface parameters, \texttt{start}, \texttt{count}, and
+\texttt{stride} must also be used to build a file type, but the process is
+considerably simpler.
+
+\subsection*{B.5  MPI and NetCDF Types}
+
+\subsubsection*{Questions for Users Regarding MPI and NetCDF Types}
+
+\begin{itemize}
+\item How do users use text strings?
+\item What types are our users using?
+\end{itemize}
+
+\end{document}
+
+
+
+
+
+
+
+
Index: /branches/SDM_SciDAC/doc/Makefile
===================================================================
--- /branches/SDM_SciDAC/doc/Makefile (revision 2)
+++ /branches/SDM_SciDAC/doc/Makefile (revision 2)
@@ -0,0 +1,6 @@
+all: doc
+doc:
+	latex netcdf-api.tex
+	latex netcdf-api.tex
+clean:
+	rm  *.dvi *.log *.aux
Index: /branches/SDM_SciDAC/macros.make.in
===================================================================
--- /branches/SDM_SciDAC/macros.make.in (revision 2)
+++ /branches/SDM_SciDAC/macros.make.in (revision 2)
@@ -0,0 +1,92 @@
+# $Id$
+
+# The purpose of this file is to contain common make(1) macros.
+# It should be processed by every execution of that utility.
+
+
+# POSIX shell.  Shouldn't be necessary -- but is under IRIX 5.3.
+SHELL		= /bin/sh
+
+
+# Installation Directories:
+SRCDIR		= @SRCDIR@
+prefix		= @prefix@
+exec_prefix	= $(prefix)
+INCDIR		= $(exec_prefix)/include
+LIBDIR		= $(exec_prefix)/lib
+BINDIR		= $(exec_prefix)/bin
+MANDIR		= $(prefix)/man
+
+
+# Preprocessing:
+M4		= @M4@
+M4FLAGS		= @M4FLAGS@
+CPP		= @CPP@
+CPPFLAGS	= $(INCLUDES) $(DEFINES) @CPPFLAGS@
+FPP		= @FPP@
+FPPFLAGS	= @FPPFLAGS@
+CXXCPPFLAGS	= $(CPPFLAGS)
+
+
+# Compilation:
+CC		= @CC@
+CXX		= @CXX@
+FC		= @FC@
+F90		= @F90@
+CFLAGS		= @CFLAGS@
+CXXFLAGS	= @CXXFLAGS@
+FFLAGS		= @FFLAGS@
+F90FLAGS	= @F90FLAGS@
+NETCDF.MOD	= @NETCDF_MOD@
+CC_MAKEDEPEND	= @CC_MAKEDEPEND@
+COMPILE.c	= $(CC) -c $(CFLAGS) $(CPPFLAGS)
+COMPILE.cxx	= $(CXX) -c $(CXXFLAGS) $(CXXCPPFLAGS)
+COMPILE.f	= $(FC) -c $(FFLAGS)
+COMPILE.F90	= $(F90) -c $(F90FLAGS)
+# The following command isn't available on some systems; therefore, the
+# `.F.o' rule is relatively complicated.
+COMPILE.F	= @COMPILE_F@
+
+
+# Linking:
+MATHLIB		= @MATHLIB@
+FLIBS		= @FLIBS@
+F90LIBS		= @F90LIBS@
+LIBS		= @LIBS@
+F90LDFLAGS	= $(LDFLAGS)
+LINK.c		= $(CC) -o $@ $(CFLAGS) $(LDFLAGS)
+LINK.cxx	= $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS)
+LINK.F		= $(FC) -o $@ $(FFLAGS) $(FLDFLAGS)
+LINK.f		= $(FC) -o $@ $(FFLAGS) $(FLDFLAGS)
+LINK.F90	= $(F90) -o $@ $(F90FLAGS) $(F90LDFLAGS)
+
+
+# Manual pages:
+WHATIS		= @WHATIS@
+# The following macro should be empty on systems that don't
+# allow users to create their own manual-page indexes.
+MAKEWHATIS_CMD	= @MAKEWHATIS_CMD@
+
+
+# Misc. Utilities:
+AR		= @AR@
+ARFLAGS		= @ARFLAGS@
+RANLIB		= @RANLIB@
+TARFLAGS	= -chf
+
+
+# Dummy macros: used only as placeholders to silence GNU make.  They are
+# redefined, as necessary, in subdirectory makefiles.
+HEADER		= dummy_header
+HEADER1		= dummy_header1
+HEADER2		= dummy_header2
+HEADER3		= dummy_header3
+LIBRARY		= dummy_library.a
+MANUAL		= dummy_manual
+PROGRAM		= dummy_program
+
+
+# Distribution macros:
+FTPDIR		= /home/ftp/pub/$(PACKAGE)
+FTPBINDIR	= @FTPBINDIR@
+VERSION		= dummy_version
Index: /branches/SDM_SciDAC/configure.in
===================================================================
--- /branches/SDM_SciDAC/configure.in (revision 2)
+++ /branches/SDM_SciDAC/configure.in (revision 2)
@@ -0,0 +1,52 @@
+AC_REVISION($Id$)dnl
+dnl
+dnl Process this file with GNU autoconf(1) to produce a configure script.
+dnl
+
+dnl Defaults:
+CPPFLAGS=${CPPFLAGS--DNDEBUG}
+CFLAGS=${CFLAGS--O}
+FPPFLAGS=${FPPFLAGS-}
+FFLAGS=${FFLAGS-}
+
+AC_INIT(src/lib/ncconfig.in)
+UD_SRCDIR
+AC_PREFIX_DEFAULT(`(cd ..; pwd)`)
+AC_CONFIG_HEADER(
+    src/lib/ncconfig.h:src/lib/ncconfig.in
+)
+UD_PROG_M4
+UD_PROG_CC
+UD_PROG_CC_MAKEDEPEND
+UD_PROG_CXX
+UD_PROG_FC
+UD_PROG_F90
+UD_FORTRAN_TYPES
+UD_CHECK_LIB_MATH
+UD_PROG_AR()
+UD_PROG_NM()
+AC_PROG_RANLIB
+AC_CHECK_HEADER(stdlib.h, ,AC_DEFINE(NO_STDLIB_H))
+AC_CHECK_HEADER(sys/types.h, ,AC_DEFINE(NO_SYS_TYPES_H))
+AC_CHECK_FUNC(strerror, ,AC_DEFINE(NO_STRERROR))
+UD_CHECK_FTRUNCATE
+AC_FUNC_ALLOCA
+AC_STRUCT_ST_BLKSIZE
+UD_CHECK_IEEE
+AC_TYPE_SIZE_T
+AC_TYPE_OFF_T
+AC_CHECK_TYPE(ssize_t, int)
+AC_CHECK_TYPE(ptrdiff_t, int)
+AC_CHECK_TYPE(uchar, unsigned char)
+AC_C_CHAR_UNSIGNED
+AC_C_BIGENDIAN
+AC_CHECK_SIZEOF(short)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(float)
+AC_CHECK_SIZEOF(double)
+UD_CHECK_SIZEOF(off_t)
+UD_CHECK_SIZEOF(size_t)
+UD_MAKEWHATIS
+UD_FTPBINDIR
+UD_OUTPUT(macros.make)
Index: /branches/SDM_SciDAC/rules.make
===================================================================
--- /branches/SDM_SciDAC/rules.make (revision 2)
+++ /branches/SDM_SciDAC/rules.make (revision 2)
@@ -0,0 +1,221 @@
+# $Id$
+
+# The purpose of this file is to contain common make(1) rules.
+# It should be processed by every execution of the that utility.
+
+.SUFFIXES:
+.SUFFIXES:	.a .o .i .f .c .cpp .F .y .l .m4
+
+
+################################################################################
+# Compilation (including preprocessing):
+
+.c.o:
+	$(COMPILE.c) $<
+
+.c.i:
+	$(CPP) $(CPPFLAGS) $< >$@
+
+.cpp.o:
+	$(COMPILE.cxx) $<
+
+# Not all FORTRAN compilers support C-preprocessing of *.F files; ergo, a 
+# relatively complicated rule ensues.
+.F.o:
+	@case "$(COMPILE.F)" in	\
+	    '')	\
+		set -x;	\
+		$(FPP) $(FPPFLAGS) $*.F | grep -v '^#' >$*-tmp.f || 	\
+		    (rm $*-tmp.f ; exit 1);	\
+		$(COMPILE.f) -o $@ $*-tmp.f || (rm $*-tmp.f; exit 1);	\
+		rm $*-tmp.f;	\
+		;;	\
+	    *)	\
+		set -x;	\
+		$(COMPILE.F) $<;	\
+		;;	\
+	esac
+
+.f.o:
+	$(COMPILE.f) $<
+
+#.F.f:
+#	$(FPP) $(FPPFLAGS) $*.F | grep -v '^#' >$*.f || (rm $*.f; exit 1)
+
+.m4.c:
+	$(M4) $(M4FLAGS) $< >$@
+
+.m4.F:
+	$(M4) $(M4FLAGS) $< >$@
+
+
+################################################################################
+# Libraries:
+
+lib:		$(LIBRARY)
+
+$(LIBRARY):	$(LIB_OBJS) FORCE
+	$(AR) $(ARFLAGS) $@ $(LIB_OBJS)
+	$(RANLIB) $@
+
+#-------------------------------------------------------------------------------
+# Shared Libraries:
+#
+# Here only as a place holder and notebook.  Don't try to use this stuff
+# unless you really, really know what you're doing!  (And even then we
+# guarantee nothing!)
+#
+shared_library:
+	@case `uname -sr` in \
+	HP-UX*) \
+	    $(MAKE) hpux_shared_library;; \
+	IRIX*) \
+	    $(MAKE) irix_shared_library;; \
+	Linux*) \
+	    $(MAKE) linux_shared_library;; \
+	OSF1*) \
+	    $(MAKE) osf1_shared_library;; \
+	'SunOS 4'*) \
+	    $(MAKE) sunos4_shared_library;; \
+	'SunOS 5'*) \
+	    $(MAKE) sunos5_shared_library;; \
+	*) \
+	    echo 1>&2 "Don't know how to make a shared library" \
+		"on this system"; \
+	    exit 1;; \
+	esac
+
+hpux_shared_library:
+	nm libnetcdf.a | grep extern | grep entry | \
+	    awk '-F|' '{print $$1}' | sed 's/^/-u /' >symbols.log
+	ld -o $(LIBRARY:.a=.sl) -b -c symbols.log $(LIBRARY)
+	rm symbols.log
+irix_shared_library:
+	ld -o $(LIBRARY:.a=.so) -shared -no_archive \
+	    -all $(LIBRARY) -none -lc -lC $(LIBS)
+linux_shared_library:
+	ld -o $(LIBRARY:.a=.so) -shared --whole-archive $(LIBRARY)
+osf1_shared_library:
+	ld -o $(LIBRARY:.a=.so) -shared -all $(LIBRARY)
+sunos4_shared_library:
+	undefopts=`/bin/nm $(LIBRARY) | awk '$$2~/^T$$/{print $$3}' | \
+		   sed 's/^/-u /'` && \
+	    ld -o $(LIBRARY:.a=.so) $$undefopts $(LIBRARY)
+sunos5_shared_library:
+	undefopts=`/usr/ccs/bin/nm $(LIBRARY) | grep GLOB | grep FUNC | \
+		   awk '-F|' '{print $$8}' | sed 's/^/-u /'` && \
+	    ld -o $(LIBRARY:.a=.so) -G $$undefopts $(LIBRARY)
+
+
+################################################################################
+# Linking:
+
+
+################################################################################
+# Installation:
+
+$(INCDIR)/$(HEADER):	$(INCDIR) $(HEADER)
+	cp $(HEADER) $@
+$(INCDIR)/$(HEADER1):	$(INCDIR) $(HEADER1)
+	cp $(HEADER1) $@
+$(INCDIR)/$(HEADER2):	$(INCDIR) $(HEADER2)
+	cp $(HEADER2) $@
+$(INCDIR)/$(HEADER3):	$(INCDIR) $(HEADER3)
+	cp $(HEADER3) $@
+
+$(LIBDIR)/$(LIBRARY):	$(LIBDIR) $(LIBRARY)
+	cp $(LIBRARY) $@
+
+$(BINDIR)/$(PROGRAM):	$(BINDIR) $(PROGRAM)
+	cp $(PROGRAM) $@
+
+$(BINDIR) \
+$(INCDIR) \
+$(LIBDIR) \
+$(MANDIR) :
+	-test -d $@ || mkdir $@
+
+$(MANDIR)/man1 \
+$(MANDIR)/man3 \
+$(MANDIR)/man3f \
+$(MANDIR)/man3f90 :		$(MANDIR)
+	-test -d $@ || mkdir $@
+
+$(MANDIR)/man1/$(MANUAL):	$(MANDIR)/man1 $(MANUAL)
+	cp $(MANUAL) $@
+$(MANDIR)/man3/$(MANUAL):	$(MANDIR)/man3 $(MANUAL)
+	cp $(MANUAL) $@
+$(MANDIR)/man3f/$(MANUAL):	$(MANDIR)/man3 $(MANDIR)/man3/$(MANUAL) \
+				$(MANDIR)/man3f
+	rm -f $@
+	ln -s $(MANDIR)/man3/$(MANUAL) $@
+$(MANDIR)/man3f90/$(MANUAL):	$(MANDIR)/man3 $(MANDIR)/man3/$(MANUAL) \
+				$(MANDIR)/man3f90
+	rm -f $@
+	ln -s $(MANDIR)/man3/$(MANUAL) $@
+
+################################################################################
+# Cleanup:
+
+clean:		FORCE
+	rm -f *.o *.a *.so *.sl *.i *.Z core $(GARBAGE)
+
+distclean:	FORCE
+	rm -f *.o *.a *.so *.sl *.i *.Z core $(GARBAGE) \
+	    MANIFEST *.log $(DIST_GARBAGE)
+	rm -rf SunWS_cache
+
+################################################################################
+# Dependencies:
+
+# This target should only need to be made at the UPC.
+# NOTES:
+#   *  The target file might be a symbolic link.
+#   *  The name of the target doesn't match the name of the created file to
+#      prevent constant updating of the included file `depend' by make(1).
+#
+deps:		FORCE
+	$(CC_MAKEDEPEND) $(CPPFLAGS) *.c | grep -v '/usr/include' >>depend
+	sort -u -o depend depend
+
+
+################################################################################
+# Distribution:
+
+# The following rule echoes the contents of $(PACKING_LIST) in the
+# current directory and in all subdirectories.  All pathnames are made
+# relative to the current directory.
+#
+MANIFEST.echo:	FORCE
+	@echo $(PACKING_LIST) | fmt -1
+	@if [ -n "$(SUBDIRS)" ]; then \
+	    subdirs="$(SUBDIRS)"; \
+	    for subdir in $$subdirs; do \
+		(cd $$subdir && \
+		echo 1>&2 Creating $@ in `pwd` && \
+		$(MAKE) MANIFEST.echo | sed "s|^|$$subdir/|") || exit 1; \
+	    done; \
+	else \
+	   :; \
+	fi
+
+# The following rule ensures that all files in $(PACKING_LIST) exist in
+# the current directory and in all subdirectories.
+#
+ensure_manifest:	$(PACKING_LIST) FORCE
+	@if [ -n "$(SUBDIRS)" ]; then \
+	    subdirs="$(SUBDIRS)"; \
+	    for subdir in $$subdirs; do \
+		(cd $$subdir && \
+		echo 1>&2 Creating $@ in `pwd` && \
+		$(MAKE) ensure_manifest) || exit 1; \
+	    done; \
+	else \
+	   :; \
+	fi
+
+
+################################################################################
+# Misc:
+
+FORCE:
Index: /branches/SDM_SciDAC/src/lib/mpincio.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/mpincio.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/mpincio.c (revision 2)
@@ -0,0 +1,554 @@
+/***********************************************************************************
+ *
+ * This file is created by Northwestern University and Argonne National Laboratory
+ *
+ **********************************************************************************/
+
+#include "ncconfig.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifndef ENOERR
+#define ENOERR 0
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef _MSC_VER /* Microsoft Compilers */
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "ncio.h"
+#include "fbits.h"
+#include "rnd.h"
+
+/* #define INSTRUMENT 1 */
+#if INSTRUMENT /* debugging */
+#undef NDEBUG
+#include <stdio.h>
+#include "instr.h"
+#endif
+
+#undef MIN  /* system may define MIN somewhere and complain */
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+
+#if !defined(NDEBUG) && !defined(X_INT_MAX)
+#define  X_INT_MAX 2147483647
+#endif
+
+#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */
+#define  X_ALIGN 4
+#else
+#undef X_ALIGN
+#endif
+
+#ifdef USE_MPIO /* Following code add by Jianwei Li */
+
+#define MAX_NC_ID 1024
+
+static unsigned char IDalloc[MAX_NC_ID];
+
+#endif /* USE_MPIO */
+
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */ 
+
+void
+ncio_free(ncio *nciop) {
+  if (nciop != NULL)
+    free(nciop);
+}
+
+#else /* Following interface modified as above by Jianwei Li */
+
+static void
+ncio_free(ncio *nciop)
+{
+	if(nciop == NULL)
+		return;
+
+	if(nciop->free != NULL)
+		nciop->free(nciop->pvt);
+	
+	free(nciop);
+}
+
+#endif /* USE_MPIO */
+
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */  
+
+ncio *
+ncio_new(const char *path, int ioflags)
+{
+  size_t sz_ncio = M_RNDUP(sizeof(ncio));
+  size_t sz_path = M_RNDUP(strlen(path) +1); 
+  ncio *nciop; 
+
+  nciop = (ncio *) malloc(sz_ncio + sz_path);
+  if (nciop == NULL) 
+    return NULL;
+
+  nciop->ioflags = ioflags;
+
+  nciop->path = (char *) ((char *)nciop + sz_ncio);
+  (void) strcpy((char *)nciop->path, path); 
+
+  return nciop;
+}
+
+#else /* Following interface modified as above by Jianwei Li */
+
+static ncio *
+ncio_new(const char *path, int ioflags)
+{
+	size_t sz_ncio = M_RNDUP(sizeof(ncio));
+	size_t sz_path = M_RNDUP(strlen(path) +1);
+	size_t sz_ncio_pvt;
+	ncio *nciop;
+ 
+#if ALWAYS_NC_SHARE /* DEBUG */
+	fSet(ioflags, NC_SHARE);
+#endif
+
+	if(fIsSet(ioflags, NC_SHARE))
+		sz_ncio_pvt = sizeof(ncio_spx);
+	else
+		sz_ncio_pvt = sizeof(ncio_px);
+
+	nciop = (ncio *) malloc(sz_ncio + sz_path + sz_ncio_pvt);
+	if(nciop == NULL)
+		return NULL;
+	
+	nciop->ioflags = ioflags;
+	*((int *)&nciop->fd) = -1; /* cast away const */
+
+	nciop->path = (char *) ((char *)nciop + sz_ncio);
+	(void) strcpy((char *)nciop->path, path); /* cast away const */
+
+				/* cast away const */
+	*((void **)&nciop->pvt) = (void *)(nciop->path + sz_path);
+
+	if(fIsSet(ioflags, NC_SHARE))
+		ncio_spx_init(nciop);
+	else
+		ncio_px_init(nciop);
+
+	return nciop;
+}
+
+#endif /* USE_MPIO */
+
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */
+
+int
+ncio_create(MPI_Comm comm, const char *path, int ioflags, MPI_Info info, 
+            ncio **nciopp) {
+  ncio *nciop;
+  int i;
+  int mpiomode = (MPI_MODE_RDWR | MPI_MODE_CREATE);
+  int mpireturn, status; 
+
+
+  fSet(ioflags, NC_WRITE);
+
+  if(path == NULL || *path == 0)
+    return EINVAL;
+
+  nciop = ncio_new(path, ioflags);
+  if(nciop == NULL)
+    return ENOMEM;
+
+  nciop->mpiomode = MPI_MODE_RDWR;
+  nciop->mpioflags = 0;
+  nciop->comm = comm;
+  nciop->mpiinfo = info;
+
+  if (fIsSet(ioflags, NC_NOCLOBBER))
+    fSet(mpiomode, MPI_MODE_EXCL);
+  else
+    MPI_File_delete((char *)path, info);
+
+  mpireturn = MPI_File_open(comm, (char *)path, mpiomode, info, &nciop->collective_fh);
+  if (mpireturn != MPI_SUCCESS) {
+    ncio_free(nciop);
+    return NC_EOFILE;  
+  }
+
+  for (i = 0; i < MAX_NC_ID && IDalloc[i] != 0; i++);
+  if (i == MAX_NC_ID) {
+    ncio_free(nciop);
+    return NC_ENFILE;
+  }
+  *((int *)&nciop->fd) = i;
+  IDalloc[i] = 1;
+
+  set_NC_collectiveFh(nciop);
+
+  *nciopp = nciop;
+  return ENOERR;  
+}
+
+#else /* Following interface modified as above by Jianwei Li */
+
+int
+ncio_create(const char *path, int ioflags,
+	size_t initialsz,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp)
+{
+	ncio *nciop;
+	int oflags = (O_RDWR|O_CREAT);
+	int fd;
+	int status;
+
+	if(initialsz < (size_t)igeto + igetsz)
+		initialsz = (size_t)igeto + igetsz;
+
+	fSet(ioflags, NC_WRITE);
+
+	if(path == NULL || *path == 0)
+		return EINVAL;
+
+	nciop = ncio_new(path, ioflags);
+	if(nciop == NULL)
+		return ENOMEM;
+
+	if(fIsSet(ioflags, NC_NOCLOBBER))
+		fSet(oflags, O_EXCL);
+	else
+		fSet(oflags, O_TRUNC);
+#ifdef O_BINARY
+	fSet(oflags, O_BINARY);
+#endif
+#ifdef vms
+	fd = open(path, oflags, NC_DEFAULT_CREAT_MODE, "ctx=stm");
+#else
+	/* Should we mess with the mode based on NC_SHARE ?? */
+	fd = open(path, oflags, NC_DEFAULT_CREAT_MODE);
+#endif
+#if 0
+	(void) fprintf(stderr, "ncio_create(): path=\"%s\"\n", path);
+	(void) fprintf(stderr, "ncio_create(): oflags=0x%x\n", oflags);
+#endif
+	if(fd < 0)
+	{
+		status = errno;
+		goto unwind_new;
+	}
+	*((int *)&nciop->fd) = fd; /* cast away const */
+
+	if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE)
+	{
+		/* Use default */
+		*sizehintp = blksize(fd);
+	}
+	else
+	{
+		*sizehintp = M_RNDUP(*sizehintp);
+	}
+
+	if(fIsSet(nciop->ioflags, NC_SHARE))
+		status = ncio_spx_init2(nciop, sizehintp);
+	else
+		status = ncio_px_init2(nciop, sizehintp, 1);
+
+	if(status != ENOERR)
+		goto unwind_open;
+
+	if(initialsz != 0)
+	{
+		status = fgrow(fd, (off_t)initialsz);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	if(igetsz != 0)
+	{
+		status = nciop->get(nciop,
+				igeto, igetsz,
+                        	RGN_WRITE,
+                        	igetvpp);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	*nciopp = nciop;
+	return ENOERR;
+
+unwind_open:
+	(void) close(fd);
+	/* ?? unlink */
+	/*FALLTHRU*/
+unwind_new:
+	ncio_free(nciop);
+	return status;
+}
+
+#endif /* USE_MPIO */
+
+
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */
+
+int
+ncio_open(MPI_Comm comm, const char *path, int ioflags, MPI_Info info,
+          ncio **nciopp) {
+  ncio *nciop;
+  int i;
+  int mpiomode = fIsSet(ioflags, NC_WRITE) ? MPI_MODE_RDWR : MPI_MODE_RDONLY;
+  int mpireturn, status;
+ 
+  if(path == NULL || *path == 0)
+    return EINVAL;
+ 
+  nciop = ncio_new(path, ioflags);
+  if(nciop == NULL)
+    return ENOMEM;
+ 
+  nciop->mpiomode = mpiomode;
+  nciop->mpioflags = 0;
+  nciop->comm = comm;
+  nciop->mpiinfo = info;
+ 
+  mpireturn = MPI_File_open(comm, (char *)path, mpiomode, info, &nciop->collective_fh);
+  if (mpireturn != MPI_SUCCESS) {
+    ncio_free(nciop);
+    return NC_EOFILE;
+  }
+ 
+  for (i = 0; i < MAX_NC_ID && IDalloc[i] != 0; i++);
+  if (i == MAX_NC_ID) {
+    ncio_free(nciop);
+    return NC_ENFILE;
+  }
+  *((int *)&nciop->fd) = i;
+  IDalloc[i] = 1;
+ 
+  set_NC_collectiveFh(nciop);
+ 
+  *nciopp = nciop;
+  return ENOERR; 
+}
+
+#else /* Following interface modified as above by Jianwei Li */
+
+int
+ncio_open(const char *path,
+	int ioflags,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp)
+{
+	ncio *nciop;
+	int oflags = fIsSet(ioflags, NC_WRITE) ? O_RDWR : O_RDONLY;
+	int fd;
+	int status;
+
+	if(path == NULL || *path == 0)
+		return EINVAL;
+
+	nciop = ncio_new(path, ioflags);
+	if(nciop == NULL)
+		return ENOMEM;
+
+#ifdef O_BINARY
+	fSet(oflags, O_BINARY);
+#endif
+#ifdef vms
+	fd = open(path, oflags, 0, "ctx=stm");
+#else
+	fd = open(path, oflags, 0);
+#endif
+	if(fd < 0)
+	{
+		status = errno;
+		goto unwind_new;
+	}
+	*((int *)&nciop->fd) = fd; /* cast away const */
+
+	if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE)
+	{
+		/* Use default */
+		*sizehintp = blksize(fd);
+	}
+	else
+	{
+		*sizehintp = M_RNDUP(*sizehintp);
+	}
+
+	if(fIsSet(nciop->ioflags, NC_SHARE))
+		status = ncio_spx_init2(nciop, sizehintp);
+	else
+		status = ncio_px_init2(nciop, sizehintp, 0);
+
+	if(status != ENOERR)
+		goto unwind_open;
+
+	if(igetsz != 0)
+	{
+		status = nciop->get(nciop,
+				igeto, igetsz,
+                        	0,
+                        	igetvpp);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	*nciopp = nciop;
+	return ENOERR;
+
+unwind_open:
+	(void) close(fd);
+	/*FALLTHRU*/
+unwind_new:
+	ncio_free(nciop);
+	return status;
+}
+
+#endif /* USE_MPIO */
+
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */ 
+
+int
+ncio_sync(ncio *nciop) {
+  if(NC_independentFhOpened(nciop))
+    MPI_File_sync(nciop->independent_fh);
+ 
+  if(NC_collectiveFhOpened(nciop))
+    MPI_File_sync(nciop->collective_fh); 
+
+  MPI_Barrier(nciop->comm);
+
+  return ENOERR;
+}
+
+int
+ncio_close(ncio *nciop, int doUnlink) {
+  int status = ENOERR;
+
+  if (nciop == NULL)
+    return EINVAL;
+
+  if(NC_independentFhOpened(nciop))
+    MPI_File_close(&(nciop->independent_fh));
+ 
+  if(NC_collectiveFhOpened(nciop))
+    MPI_File_close(&(nciop->collective_fh));  
+ 
+  if (doUnlink)
+    MPI_File_delete((char *)nciop->path, nciop->mpiinfo);
+
+  ncio_free(nciop);
+
+  return status;
+}
+
+#else /* Following interface modified as above by Jianwei Li */
+
+int 
+ncio_close(ncio *nciop, int doUnlink)
+{
+	int status = ENOERR;
+
+	if(nciop == NULL)
+		return EINVAL;
+
+	status = nciop->sync(nciop);
+
+	(void) close(nciop->fd);
+	
+	if(doUnlink)
+		(void) unlink(nciop->path);
+
+	ncio_free(nciop);
+
+	return status;
+}
+
+#endif /* USE_MPIO */
+
+#ifdef USE_MPIO /* Following interface added by Jianwei Li */
+
+int
+ncio_move(ncio *const nciop, off_t to, off_t from, size_t nbytes) {
+  int mpireturn, mpierr = 0, errcheck;
+  const int bufsize = 4096;
+  size_t movesize, bufcount;
+  int rank, grpsize;
+  void *buf = malloc(bufsize);
+  MPI_Comm comm;
+  MPI_Status mpistatus;
+
+  comm = nciop->comm;
+  MPI_Comm_size(comm, &grpsize);
+  MPI_Comm_rank(comm, &rank);
+
+  movesize = nbytes;
+
+  while (movesize > 0) {
+    /* find a proper number of processors to participate I/O */
+    while (grpsize > 1 && movesize/grpsize < bufsize)
+      grpsize--;
+    if (grpsize > 1) {
+      bufcount = bufsize;
+      movesize -= bufsize*grpsize;
+    } 
+    else if (movesize < bufsize) {
+      bufcount = movesize;
+      movesize = 0;
+    } 
+    else {
+      bufcount = bufsize;
+      movesize -= bufsize;
+    }
+
+    /* reset the file view */
+    mpireturn = MPI_File_set_view(nciop->collective_fh, 0, MPI_BYTE,
+                                  MPI_BYTE, "native", nciop->mpiinfo);
+    if (mpireturn != MPI_SUCCESS) {
+      free(buf);
+      return NC_EREAD;
+    }
+    if (rank < grpsize) {
+      /* read the original data @ from+movesize+rank*bufsize */
+      mpireturn = MPI_File_read_at(nciop->collective_fh,
+                                   from+movesize+rank*bufsize,
+                                   buf, bufcount, MPI_BYTE, &mpistatus);
+      if (mpireturn != MPI_SUCCESS)
+        mpierr = 1;
+    }
+    MPI_Allreduce(&mpierr, &errcheck, 1, MPI_INT, MPI_LOR, comm);
+    if (errcheck) {
+      free(buf);
+      return NC_EREAD;
+    }
+
+    MPI_Barrier(comm); /* important, in case new region overlaps old region */
+
+    /* reset the file view */
+    mpireturn = MPI_File_set_view(nciop->collective_fh, 0, MPI_BYTE,
+                                  MPI_BYTE, "native", nciop->mpiinfo);
+    if (mpireturn != MPI_SUCCESS) {
+      free(buf);
+      return NC_EWRITE;
+    }
+    if (rank < grpsize) {
+      /* write to new location @ to+movesize+rank*bufsize */
+      mpireturn = MPI_File_write_at(nciop->collective_fh,
+                                    to+movesize+rank*bufsize,
+                                   buf, bufcount, MPI_BYTE, &mpistatus);
+      if (mpireturn != MPI_SUCCESS)
+        mpierr = 1;
+    }
+    MPI_Allreduce(&mpierr, &errcheck, 1, MPI_INT, MPI_LOR, comm);
+    if (errcheck) {
+      free(buf);
+      return NC_EWRITE;
+    }
+  }
+
+  free(buf);
+  return NC_NOERR;
+}
+
+#endif /* USE_MPIO */
Index: /branches/SDM_SciDAC/src/lib/nc.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/nc.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/nc.c (revision 2)
@@ -0,0 +1,1439 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "nc.h"
+#include "rnd.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ncx.h"
+#if defined(LOCKNUMREC) /* && _CRAYMPP */
+#  include <mpp/shmem.h>
+#  include <intrinsics.h>
+#endif
+
+/* list of open netcdf's */
+static NC *NClist = NULL;
+
+/* static */
+void
+add_to_NCList(NC *ncp)
+{
+	assert(ncp != NULL);
+
+	ncp->prev = NULL;
+	if(NClist != NULL)
+		NClist->prev = ncp;
+	ncp->next = NClist;
+	NClist = ncp;
+}
+
+/* static */
+void
+del_from_NCList(NC *ncp)
+{
+	assert(ncp != NULL);
+
+	if(NClist == ncp)
+	{
+		assert(ncp->prev == NULL);
+		NClist = ncp->next;
+	}
+	else
+	{
+		assert(ncp->prev != NULL);
+		ncp->prev->next = ncp->next;
+	}
+
+	if(ncp->next != NULL)
+		ncp->next->prev = ncp->prev;
+
+	ncp->next = NULL;
+	ncp->prev = NULL;
+}
+
+#ifdef USE_MPIO /* Following interface added by Jianwei Li */
+
+/*
+ * Check the data set definitions across all processes by
+ * comparing the header buffer streams of all processes.
+ */
+int
+NC_check_def(MPI_Comm comm, void *buf, size_t nn) {
+  int rank;
+  int errcheck, compare = 0;
+  void *cmpbuf;
+
+  MPI_Comm_rank(comm, &rank);
+
+  if (rank == 0) 
+    cmpbuf = buf;
+  else
+    cmpbuf = (void *)malloc(nn);
+
+  MPI_Bcast(cmpbuf, nn, MPI_BYTE, 0, comm);
+
+  if (rank != 0) {
+    compare = memcmp(buf, cmpbuf, nn);
+    free(cmpbuf);
+  }
+
+  MPI_Allreduce(&compare, &errcheck, 1, MPI_INT, MPI_LOR, comm);
+
+  if (errcheck)
+    return NC_EMULTIDEFINE;
+  else 
+    return NC_NOERR;
+}
+
+#endif /* USE_MPIO */
+
+int
+NC_check_id(int ncid, NC **ncpp)
+{
+	NC *ncp;
+
+	if(ncid >= 0)
+	{
+		for(ncp = NClist; ncp != NULL; ncp = ncp->next)
+		{
+			if(ncp->nciop->fd == ncid)
+			{
+				*ncpp = ncp;
+				return NC_NOERR; /* normal return */
+			}
+		}
+	}
+
+	/* else, not found */
+	return NC_EBADID;
+}
+
+
+/* static */
+void
+free_NC(NC *ncp)
+{
+	if(ncp == NULL)
+		return;
+	free_NC_dimarrayV(&ncp->dims);
+	free_NC_attrarrayV(&ncp->attrs);
+	free_NC_vararrayV(&ncp->vars);
+#if _CRAYMPP && defined(LOCKNUMREC)
+	shfree(ncp);
+#else
+	free(ncp);
+#endif /* _CRAYMPP && LOCKNUMREC */
+}
+
+
+/* static */
+NC *
+new_NC(const size_t *chunkp)
+{
+	NC *ncp;
+
+#if _CRAYMPP && defined(LOCKNUMREC)
+	ncp = (NC *) shmalloc(sizeof(NC));
+#else
+	ncp = (NC *) malloc(sizeof(NC));
+#endif /* _CRAYMPP && LOCKNUMREC */
+	if(ncp == NULL)
+		return NULL;
+	(void) memset(ncp, 0, sizeof(NC));
+
+	ncp->xsz = MIN_NC_XSZ;
+	assert(ncp->xsz == hdr_len_NC(ncp));
+	
+	ncp->chunk = chunkp != NULL ? *chunkp : NC_SIZEHINT_DEFAULT;
+
+	return ncp;
+}
+
+
+/* static */
+NC *
+dup_NC(const NC *ref)
+{
+	NC *ncp;
+
+#if _CRAYMPP && defined(LOCKNUMREC)
+	ncp = (NC *) shmalloc(sizeof(NC));
+#else
+	ncp = (NC *) malloc(sizeof(NC));
+#endif /* _CRAYMPP && LOCKNUMREC */
+	if(ncp == NULL)
+		return NULL;
+	(void) memset(ncp, 0, sizeof(NC));
+
+	if(dup_NC_dimarrayV(&ncp->dims, &ref->dims) != NC_NOERR)
+		goto err;
+	if(dup_NC_attrarrayV(&ncp->attrs, &ref->attrs) != NC_NOERR)
+		goto err;
+	if(dup_NC_vararrayV(&ncp->vars, &ref->vars) != NC_NOERR)
+		goto err;
+
+	ncp->xsz = ref->xsz;
+	ncp->begin_var = ref->begin_var;
+	ncp->begin_rec = ref->begin_rec;
+	ncp->recsize = ref->recsize;
+	NC_set_numrecs(ncp, NC_get_numrecs(ref));
+	return ncp;
+err:
+	free_NC(ncp);
+	return NULL;
+}
+
+
+/*
+ *  Verify that this is a user nc_type
+ * Formerly
+NCcktype()
+ * Sense of the return is changed.
+ */
+int
+nc_cktype(nc_type type)
+{
+	switch((int)type){
+	case NC_BYTE:
+	case NC_CHAR:
+	case NC_SHORT:
+	case NC_INT:
+	case NC_FLOAT:
+	case NC_DOUBLE:
+		return(NC_NOERR);
+	}
+	return(NC_EBADTYPE);
+}
+
+
+/*
+ * How many objects of 'type'
+ * will fit into xbufsize?
+ */
+size_t
+ncx_howmany(nc_type type, size_t xbufsize)
+{
+	switch(type){
+	case NC_BYTE:
+	case NC_CHAR:
+		return xbufsize;
+	case NC_SHORT:
+		return xbufsize/X_SIZEOF_SHORT;
+	case NC_INT:
+		return xbufsize/X_SIZEOF_INT;
+	case NC_FLOAT:
+		return xbufsize/X_SIZEOF_FLOAT;
+	case NC_DOUBLE:
+		return xbufsize/X_SIZEOF_DOUBLE;
+	}
+	assert("ncx_howmany: Bad type" == 0);
+	return(0);
+}
+
+#define	D_RNDUP(x, align) _RNDUP(x, (off_t)(align))
+
+/*
+ * Compute each variable's 'begin' offset,
+ * update 'begin_rec' as well.
+ */
+/* static */
+void
+NC_begins(NC *ncp,
+	size_t h_minfree, size_t v_align,
+	size_t v_minfree, size_t r_align)
+{
+	size_t ii;
+	off_t index = 0;
+	NC_var **vpp;
+	NC_var *last = NULL;
+
+	if(v_align == NC_ALIGN_CHUNK)
+		v_align = ncp->chunk;
+	if(r_align == NC_ALIGN_CHUNK)
+		r_align = ncp->chunk;
+
+	ncp->xsz = hdr_len_NC(ncp);
+
+	if(ncp->vars.nelems == 0) 
+		return;
+
+	/* only (re)calculate begin_var if there is not sufficient space in header
+	   or start of non-record variables is not aligned as requested by valign */
+	if (ncp->begin_var < ncp->xsz + h_minfree ||
+	    ncp->begin_var != D_RNDUP(ncp->begin_var, v_align) ) 
+	{
+	  index = (off_t) ncp->xsz;
+	  ncp->begin_var = D_RNDUP(index, v_align);
+	  if(ncp->begin_var < index + h_minfree)
+	  {
+	    ncp->begin_var = D_RNDUP(index + (off_t)h_minfree, v_align);
+	  }
+	}
+	index = ncp->begin_var;
+
+	/* loop thru vars, first pass is for the 'non-record' vars */
+	vpp = ncp->vars.value;
+	for(ii = 0; ii < ncp->vars.nelems ; ii++, vpp++)
+	{
+		if( IS_RECVAR(*vpp) )
+		{
+			/* skip record variables on this pass */
+			continue;
+		}
+#if 0
+fprintf(stderr, "    VAR %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index);
+#endif
+		(*vpp)->begin = index;
+		index += (*vpp)->len;
+	}
+
+	/* only (re)calculate begin_rec if there is not sufficient
+	   space at end of non-record variables or if start of record
+	   variables is not aligned as requested by r_align */
+	if (ncp->begin_rec < index + v_minfree ||
+	    ncp->begin_rec != D_RNDUP(ncp->begin_rec, r_align) )
+	{
+	  ncp->begin_rec = D_RNDUP(index, r_align);
+	  if(ncp->begin_rec < index + v_minfree)
+	  {
+	    ncp->begin_rec = D_RNDUP(index + (off_t)v_minfree, r_align);
+	  }
+	}
+	index = ncp->begin_rec;
+
+	ncp->recsize = 0;
+
+	/* loop thru vars, second pass is for the 'record' vars */
+	vpp = (NC_var **)ncp->vars.value;
+	for(ii = 0; ii < ncp->vars.nelems; ii++, vpp++)
+	{
+		if( !IS_RECVAR(*vpp) )
+		{
+			/* skip non-record variables on this pass */
+			continue;
+		}
+
+#if 0
+fprintf(stderr, "    REC %d %s: %ld\n", ii, (*vpp)->name->cp, (long)index);
+#endif
+		(*vpp)->begin = index;
+		index += (*vpp)->len;
+		ncp->recsize += (*vpp)->len;
+		last = (*vpp);
+	}
+
+	/*
+	 * for special case of exactly one record variable, pack value
+	 */
+	if(last != NULL && ncp->recsize == last->len)
+		ncp->recsize = *last->dsizes * last->xsz;
+
+	if(NC_IsNew(ncp))
+		NC_set_numrecs(ncp, 0);
+
+}
+
+#define NC_NUMRECS_OFFSET 4
+#define NC_NUMRECS_EXTENT 4
+
+/*
+ * Read just the numrecs member.
+ * (A relatively expensive way to do things.)
+ */
+
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */
+ 
+int
+read_numrecs(NC *ncp) {
+  int status = NC_NOERR, mpireturn;
+  size_t nrecs;
+  void *buf, *pos;
+  MPI_Status mpistatus;
+ 
+  assert(!NC_indef(ncp));
+ 
+  pos = buf = (void *)malloc(X_SIZEOF_SIZE_T);
+
+  /* reset the file view */
+  MPI_File_set_view(ncp->nciop->collective_fh, 0, MPI_BYTE,
+                    MPI_BYTE, "native", ncp->nciop->mpiinfo);
+ 
+  mpireturn = MPI_File_read_at(ncp->nciop->collective_fh, NC_NUMRECS_OFFSET,
+                               buf, X_SIZEOF_SIZE_T, MPI_BYTE, &mpistatus);
+ 
+  if (mpireturn != MPI_SUCCESS) {
+    status = NC_EWRITE;
+  } 
+
+  status = ncx_get_size_t((const void **)&pos, &nrecs);
+  ncp->numrecs = nrecs;
+ 
+  free(buf);
+ 
+  return status;
+}
+ 
+#else /* Following interface modified as above by Jianwei Li */
+
+int
+read_numrecs(NC *ncp)
+{
+	int status = NC_NOERR;
+	const void *xp;
+	size_t nrecs = NC_get_numrecs(ncp);
+
+	assert(!NC_indef(ncp));
+
+	status = ncp->nciop->get(ncp->nciop,
+		 NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, 0, (void **)&xp);
+					/* cast away const */
+	if(status != NC_NOERR)
+		return status;
+
+	status = ncx_get_size_t(&xp, &nrecs);
+
+	(void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, 0);
+
+	if(status == NC_NOERR)
+	{
+		NC_set_numrecs(ncp, nrecs);
+		fClr(ncp->flags, NC_NDIRTY);
+	}
+
+	return status;
+}
+
+#endif
+
+/*
+ * Write out just the numrecs member.
+ * (A relatively expensive way to do things.)
+ */
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */ 
+
+/*
+ * Collective operation implicit
+ */
+
+int
+write_numrecs(NC *ncp) {
+  int status = NC_NOERR, mpireturn;
+  size_t nrecs;
+  void *buf, *pos; 
+  MPI_Status mpistatus;
+  MPI_Comm comm;
+  int rank;
+  
+  assert(!NC_readonly(ncp));
+  assert(!NC_indef(ncp));
+
+  comm = ncp->nciop->comm;
+  MPI_Comm_rank(comm, &rank);
+
+  nrecs = ncp->numrecs;
+  pos = buf = (void *)malloc(X_SIZEOF_SIZE_T);
+  status = ncx_put_size_t(&pos, &nrecs);
+
+  if(NC_indep(ncp) && NC_independentFhOpened(ncp->nciop)) {
+    MPI_File_sync(ncp->nciop->independent_fh);
+    MPI_Barrier(comm);
+  }
+
+  /* reset the file view */
+  MPI_File_set_view(ncp->nciop->collective_fh, 0, MPI_BYTE, 
+		    MPI_BYTE, "native", ncp->nciop->mpiinfo);
+
+  if (rank == 0) {
+    mpireturn = MPI_File_write_at(ncp->nciop->collective_fh, NC_NUMRECS_OFFSET,
+				  buf, X_SIZEOF_SIZE_T, MPI_BYTE, &mpistatus); 
+  } 
+
+  MPI_Bcast(&mpireturn, 1, MPI_INT, 0, comm);
+
+  if (mpireturn != MPI_SUCCESS) {
+    status = NC_EWRITE;
+  } else {
+    MPI_File_sync(ncp->nciop->collective_fh); 
+    MPI_Barrier(comm);
+    fClr(ncp->flags, NC_NDIRTY);  
+  }
+
+  free(buf);
+
+  return status;
+}
+
+#else /* Following interface modified as above by Jianwei Li */ 
+
+int
+write_numrecs(NC *ncp)
+{
+	int status = NC_NOERR;
+	void *xp;
+
+	assert(!NC_readonly(ncp));
+	assert(!NC_indef(ncp));
+
+	status = ncp->nciop->get(ncp->nciop,
+		 NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, RGN_WRITE, &xp);
+	if(status != NC_NOERR)
+		return status;
+
+	{
+		const size_t nrecs = NC_get_numrecs(ncp);
+		status = ncx_put_size_t(&xp, &nrecs);
+	}
+
+	(void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, RGN_MODIFIED);
+
+	if(status == NC_NOERR)
+		fClr(ncp->flags, NC_NDIRTY);
+
+	return status;
+}
+
+#endif /* USE_MPIO */
+
+/*
+ * Read in the header
+ * It is expensive.
+ */
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */
+
+int
+read_NC(NC *ncp) {
+  int status = NC_NOERR;
+
+  free_NC_dimarrayV(&ncp->dims);
+  free_NC_attrarrayV(&ncp->attrs);
+  free_NC_vararrayV(&ncp->vars); 
+
+  status = hdr_get_NC(ncp);
+
+  if(status == NC_NOERR)
+    fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
+
+  return status;
+}
+
+#else /* Following interface modified as above by Jianwei Li */
+
+/* static */
+int
+read_NC(NC *ncp)
+{
+	int status = NC_NOERR;
+
+	free_NC_dimarrayV(&ncp->dims);
+	free_NC_attrarrayV(&ncp->attrs);
+	free_NC_vararrayV(&ncp->vars);
+
+	status = nc_get_NC(ncp);
+
+	if(status == NC_NOERR)
+		fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
+
+	return status;
+}
+
+#endif /* USE_MPIO */
+
+/*
+ * Write out the header
+ */
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */
+
+int
+write_NC(NC *ncp)
+{
+  int status = NC_NOERR, mpireturn;
+  void *buf;
+  MPI_Status mpistatus;
+  int rank;
+ 
+  assert(!NC_readonly(ncp));
+ 
+  MPI_Comm_rank(ncp->nciop->comm, &rank);
+
+  buf = (void *)malloc(ncp->xsz);
+  status = hdr_put_NC(ncp, buf);
+  if(status != NC_NOERR) {
+    free(buf);
+    return status;
+  }
+  status = NC_check_def(ncp->nciop->comm, buf, ncp->xsz);
+  if (status != NC_NOERR) {
+    free(buf);
+    return status;
+  }
+ 
+  /* reset the file view */
+  MPI_File_set_view(ncp->nciop->collective_fh, 0, MPI_BYTE,
+                    MPI_BYTE, "native", ncp->nciop->mpiinfo);
+
+  if (rank == 0) {
+    mpireturn = MPI_File_write_at(ncp->nciop->collective_fh, 0, buf, 
+			          ncp->xsz, MPI_BYTE, &mpistatus);
+  }
+
+  fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
+  free(buf);
+ 
+  return status;
+} 
+
+#else /* Following interface modified as above by Jianwei Li */
+
+static int
+write_NC(NC *ncp)
+{
+	int status = NC_NOERR;
+
+	assert(!NC_readonly(ncp));
+
+	status = ncx_put_NC(ncp, NULL, 0, 0);
+
+	if(status == NC_NOERR)
+		fClr(ncp->flags, NC_NDIRTY | NC_HDIRTY);
+
+	return status;
+}
+
+#endif /* USE_MPIO */
+
+/*
+ * Write the header or the numrecs if necessary.
+ */
+int
+NC_sync(NC *ncp)
+{
+  int mynumrecs, numrecs;
+
+  assert(!NC_readonly(ncp));
+
+  /* collect and set the max numrecs due to difference by independent write */
+
+  mynumrecs = ncp->numrecs;
+  MPI_Allreduce(&mynumrecs, &numrecs, 1, MPI_INT, MPI_MAX, ncp->nciop->comm);
+  if (numrecs > ncp->numrecs) {
+    ncp->numrecs = numrecs;
+    set_NC_ndirty(ncp);
+  }
+
+  if(NC_hdirty(ncp)) {
+    return write_NC(ncp);
+  }
+  /* else */
+
+  if(NC_ndirty(ncp)) {
+    return write_numrecs(ncp);
+  }
+  /* else */
+
+  return NC_NOERR;
+}
+
+
+#ifndef USE_MPIO /* out-of-date code removed by Jianwei Li */
+
+/*
+ * Initialize the 'non-record' variables.
+ */
+static int
+fillerup(NC *ncp)
+{
+	int status = NC_NOERR;
+	size_t ii;
+	NC_var **varpp;
+
+	assert(!NC_readonly(ncp));
+	assert(NC_dofill(ncp));
+
+	/* loop thru vars */
+	varpp = ncp->vars.value;
+	for(ii = 0; ii < ncp->vars.nelems; ii++, varpp++)
+	{
+		if(IS_RECVAR(*varpp))
+		{
+			/* skip record variables */
+			continue;
+		}
+
+		status = fill_NC_var(ncp, *varpp, 0);
+		if(status != NC_NOERR)
+			break;
+	}
+	return status;
+}
+
+/* Begin endef */
+
+/*
+ */
+static int
+fill_added_recs(NC *gnu, NC *old)
+{
+	NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
+
+	const int old_nrecs = (int) NC_get_numrecs(old);
+	int recno = 0;
+	for(; recno < old_nrecs; recno++)
+	{
+		int varid = (int)old->vars.nelems;
+		for(; varid < (int)gnu->vars.nelems; varid++)
+		{
+			const NC_var *const gnu_varp = *(gnu_varpp + varid);
+			if(!IS_RECVAR(gnu_varp))
+			{
+				/* skip non-record variables */
+				continue;
+			}
+			/* else */
+			{
+			const int status = fill_NC_var(gnu, gnu_varp, recno);
+			if(status != NC_NOERR)
+				return status;
+			}
+		}
+	}
+
+	return NC_NOERR;
+}
+
+/*
+ */
+static int
+fill_added(NC *gnu, NC *old)
+{
+	NC_var ** const gnu_varpp = (NC_var **)gnu->vars.value;
+	int varid = (int)old->vars.nelems;
+
+	for(; varid < (int)gnu->vars.nelems; varid++)
+	{
+		const NC_var *const gnu_varp = *(gnu_varpp + varid);
+		if(IS_RECVAR(gnu_varp))
+		{
+			/* skip record variables */
+			continue;
+		}
+		/* else */
+		{
+		const int status = fill_NC_var(gnu, gnu_varp, 0);
+		if(status != NC_NOERR)
+			return status;
+		}
+	}
+
+	return NC_NOERR;
+}
+
+#endif /* USE_MPIO */
+
+/*
+ * Move the records "out". 
+ * Fill as needed.
+ */
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */
+
+int
+move_data_r(NC *ncp, NC *old) {
+  /* no new variable inserted, move the whole contiguous data part */
+  ncp->numrecs = old->numrecs;
+  return ncio_move(ncp->nciop, ncp->begin_var, old->begin_var, 
+              old->begin_rec - old->begin_var + old->recsize * old->numrecs);
+}
+
+int
+move_recs_r(NC *ncp, NC *old) {
+  int status;
+  int recno;
+  const size_t old_nrecs = old->numrecs;
+  const size_t ncp_recsize = ncp->recsize;
+  const size_t old_recsize = old->recsize;
+  const off_t ncp_off = ncp->begin_rec;
+  const off_t old_off = old->begin_rec;
+
+  assert(ncp_recsize >= old_recsize);
+
+  if (ncp_recsize == old_recsize) {
+    
+    /* No new rec var inserted, move all rec vars as a whole */
+
+    status = ncio_move(ncp->nciop, ncp_off, old_off, 
+                       old_recsize * old_nrecs);
+    if(status != NC_NOERR)
+      return status;
+  } else {
+
+    /* else, new rec var inserted, to be moved one record at a time */
+
+    for (recno = (int)old_nrecs -1; recno >= 0; recno--) {
+      status = ncio_move(ncp->nciop, 
+                         ncp_off+recno*ncp_recsize, 
+                         old_off+recno*old_recsize, 
+                         old_recsize);
+      if(status != NC_NOERR)
+        return status;
+    } 
+  }
+
+  ncp->numrecs = old_nrecs;
+  
+  return NC_NOERR;
+}
+
+#else /* Following interface modified as above by Jianwei Li */
+
+/* static */
+int
+move_recs_r(NC *gnu, NC *old)
+{
+	int status;
+	int recno;
+	int varid;
+	NC_var **gnu_varpp = (NC_var **)gnu->vars.value;
+	NC_var **old_varpp = (NC_var **)old->vars.value;
+	NC_var *gnu_varp;
+	NC_var *old_varp;
+	off_t gnu_off;
+	off_t old_off;
+	const size_t old_nrecs = NC_get_numrecs(old);
+	
+	/* Don't parallelize this loop */
+	for(recno = (int)old_nrecs -1; recno >= 0; recno--)
+	{
+	/* Don't parallelize this loop */
+	for(varid = (int)old->vars.nelems -1; varid >= 0; varid--)
+	{
+		gnu_varp = *(gnu_varpp + varid);
+		if(!IS_RECVAR(gnu_varp))
+		{
+			/* skip non-record variables on this pass */
+			continue;
+		}
+		/* else */
+
+		/* else, a pre-existing variable */
+		old_varp = *(old_varpp + varid);
+		gnu_off = gnu_varp->begin + (off_t)(gnu->recsize * recno);
+		old_off = old_varp->begin + (off_t)(old->recsize * recno);
+
+		if(gnu_off == old_off)
+			continue; 	/* nothing to do */
+
+		assert(gnu_off > old_off);
+	
+		status = gnu->nciop->move(gnu->nciop, gnu_off, old_off,
+			 old_varp->len, 0);
+
+		if(status != NC_NOERR)
+			return status;
+		
+	}
+	}
+
+	NC_set_numrecs(gnu, old_nrecs);
+
+	return NC_NOERR;
+}
+
+#endif /* USE_MPIO */
+
+/*
+ * Move the "non record" variables "out". 
+ * Fill as needed.
+ */
+#ifdef USE_MPIO /* Following interface rewritten by Jianwei Li */
+
+int
+move_vars_r(NC *ncp, NC *old) {
+  return ncio_move(ncp->nciop, ncp->begin_var, old->begin_var, 
+                   old->begin_rec - old->begin_var); 
+}
+ 
+#else /* Following interface modified as above by Jianwei Li */   
+
+/* static */
+int
+move_vars_r(NC *gnu, NC *old)
+{
+	int status;
+	int varid;
+	NC_var **gnu_varpp = (NC_var **)gnu->vars.value;
+	NC_var **old_varpp = (NC_var **)old->vars.value;
+	NC_var *gnu_varp;
+	NC_var *old_varp;
+	off_t gnu_off;
+	off_t old_off;
+	
+	/* Don't parallelize this loop */
+	for(varid = (int)old->vars.nelems -1;
+		 varid >= 0; varid--)
+	{
+		gnu_varp = *(gnu_varpp + varid);
+		if(IS_RECVAR(gnu_varp))
+		{
+			/* skip record variables on this pass */
+			continue;
+		}
+		/* else */
+
+		old_varp = *(old_varpp + varid);
+		gnu_off = gnu_varp->begin;
+		old_off = old_varp->begin;
+	
+		if(gnu_off == old_off)
+			continue; 	/* nothing to do */
+
+		assert(gnu_off > old_off);
+
+		status = gnu->nciop->move(gnu->nciop, gnu_off, old_off,
+			 old_varp->len, 0);
+
+		if(status != NC_NOERR)
+			return status;
+		
+	}
+
+	return NC_NOERR;
+}
+
+#endif /* USE_MPIO */
+
+#ifdef USE_MPIO /* function below added by Jianwei Li */
+
+int 
+NC_enddef(NC *ncp) {
+  int status = NC_NOERR;
+  MPI_Comm comm;
+
+  assert(!NC_readonly(ncp));
+  assert(NC_indef(ncp)); 
+
+  comm = ncp->nciop->comm;
+
+  NC_begins(ncp, 0, 1, 0, 1);
+ 
+  /* To be updated */
+  if(ncp->old != NULL) {
+    /* a plain redef, not a create */
+    assert(!NC_IsNew(ncp));
+    assert(fIsSet(ncp->flags, NC_INDEF));
+    assert(ncp->begin_rec >= ncp->old->begin_rec);
+    assert(ncp->begin_var >= ncp->old->begin_var);
+    assert(ncp->vars.nelems >= ncp->old->vars.nelems);
+ 
+    MPI_File_sync(ncp->nciop->collective_fh);
+    /*
+     * Barrier needed switching between read and write 
+     * Important, MPI_File_sync doesn't ensure barrier 
+     */
+    MPI_Barrier(comm); 
+
+    if(ncp->vars.nelems != 0) {
+      if(ncp->begin_rec > ncp->old->begin_rec) {
+        if (ncp->vars.nelems == ncp->old->vars.nelems) {
+          status = move_data_r(ncp, ncp->old);
+          if(status != NC_NOERR)
+            return status;
+        } else {
+          status = move_recs_r(ncp, ncp->old);
+          if(status != NC_NOERR)
+            return status;
+          if(ncp->begin_var > ncp->old->begin_var) {
+            status = move_vars_r(ncp, ncp->old);
+            if(status != NC_NOERR)
+              return status;
+          }
+        }
+      } else {
+        /* Even if (ncp->begin_rec == ncp->old->begin_rec)
+         * and     (ncp->begin_var == ncp->old->begin_var)
+         * might still have added a new record variable
+         */
+        if(ncp->recsize > ncp->old->recsize) {
+          status = move_recs_r(ncp, ncp->old);
+          if(status != NC_NOERR)
+            return status;
+        }
+      }
+    }
+  }
+ 
+  status = write_NC(ncp);
+  if (status != NC_NOERR)
+    return status;
+ 
+  if(ncp->old != NULL) {
+    free_NC(ncp->old);
+    ncp->old = NULL;
+  }
+ 
+  fClr(ncp->flags, NC_CREAT | NC_INDEF);
+  MPI_File_sync(ncp->nciop->collective_fh);
+  MPI_Barrier(comm);
+
+  return NC_NOERR;
+}
+
+
+int 
+enddef(NC *ncp)
+{
+  assert(!NC_readonly(ncp));
+  if(!NC_indef(ncp))
+    return(NC_ENOTINDEFINE);
+
+  NC_begins(ncp, 0, 1, 0, 1);
+
+  if(ncp->old != NULL)
+  {
+    free_NC(ncp->old);
+    ncp->old = NULL;
+  }
+
+  fClr(ncp->flags, NC_CREAT | NC_INDEF);
+
+  return NC_NOERR;
+}
+
+#endif
+
+/*
+ *  End define mode.
+ *  Common code for ncendef, ncclose(endef)
+ *  Flushes I/O buffers.
+ */
+static int
+NC_endef(NC *ncp,
+	size_t h_minfree, size_t v_align,
+	size_t v_minfree, size_t r_align)
+{
+	int status = NC_NOERR;
+
+	assert(!NC_readonly(ncp));
+	assert(NC_indef(ncp));
+
+	NC_begins(ncp, h_minfree, v_align, v_minfree, r_align);
+
+	if(ncp->old != NULL)
+	{
+		/* a plain redef, not a create */
+		assert(!NC_IsNew(ncp));
+		assert(fIsSet(ncp->flags, NC_INDEF));
+		assert(ncp->begin_rec >= ncp->old->begin_rec);
+		assert(ncp->begin_var >= ncp->old->begin_var);
+
+		if(ncp->vars.nelems != 0)
+		{
+		if(ncp->begin_rec > ncp->old->begin_rec)
+		{
+			status = move_recs_r(ncp, ncp->old);
+			if(status != NC_NOERR)
+				return status;
+			if(ncp->begin_var > ncp->old->begin_var)
+			{
+				status = move_vars_r(ncp, ncp->old);
+				if(status != NC_NOERR)
+					return status;
+			} 
+			/* else if (ncp->begin_var == ncp->old->begin_var) { NOOP } */
+		}
+		else
+		{	/* Even if (ncp->begin_rec == ncp->old->begin_rec)
+			   and     (ncp->begin_var == ncp->old->begin_var)
+			   might still have added a new record variable */
+		        if(ncp->recsize > ncp->old->recsize)
+			{
+			        status = move_recs_r(ncp, ncp->old);
+				if(status != NC_NOERR)
+				      return status;
+			}
+		}
+		}
+	}
+
+	status = write_NC(ncp);
+	if(status != NC_NOERR)
+		return status;
+
+#ifndef USE_MPIO /* out-of-date code removed by Jianwei Li */
+
+	if(NC_dofill(ncp))
+	{
+		if(NC_IsNew(ncp))
+		{
+			status = fillerup(ncp);
+			if(status != NC_NOERR)
+				return status;
+			
+		}
+		else if(ncp->vars.nelems > ncp->old->vars.nelems)
+		{
+			status = fill_added(ncp, ncp->old);
+			if(status != NC_NOERR)
+				return status;
+			status = fill_added_recs(ncp, ncp->old);
+			if(status != NC_NOERR)
+				return status;
+		}
+	}
+
+#endif /* USE_MPIO */
+
+	if(ncp->old != NULL)
+	{
+		free_NC(ncp->old);
+		ncp->old = NULL;
+	}
+
+	fClr(ncp->flags, NC_CREAT | NC_INDEF);
+
+	return ncp->nciop->sync(ncp->nciop);
+}
+
+#ifdef LOCKNUMREC
+static int
+NC_init_pe(NC *ncp, int basepe) {
+	if (basepe < 0 || basepe >= _num_pes()) {
+		return NC_EINVAL; /* invalid base pe */
+	}
+	/* initialize common values */
+	ncp->lock[LOCKNUMREC_VALUE] = 0;
+	ncp->lock[LOCKNUMREC_LOCK] = 0;
+	ncp->lock[LOCKNUMREC_SERVING] = 0;
+	ncp->lock[LOCKNUMREC_BASEPE] =  basepe;
+	return NC_NOERR;
+}
+#endif
+
+/* Public */
+
+#ifdef USE_MPIO /* This section is added by Jianwei Li */
+
+int 
+NC_close(NC *ncp) {
+  int status = NC_NOERR;
+
+  if(NC_indef(ncp)) {
+    status = NC_enddef(ncp); /* TODO: defaults */
+    if(status != NC_NOERR ) {
+      /* To do: Abort new definition, if any */
+      if (ncp->old != NULL) {
+        free_NC(ncp->old);
+        ncp->old = NULL;
+        fClr(ncp->flags, NC_INDEF);
+      }
+    }
+  }
+  else if(!NC_readonly(ncp)) {
+    status = NC_sync(ncp);
+    if (status != NC_NOERR)
+      return status;
+  }
+ 
+  (void) ncio_close(ncp->nciop, 0);
+  ncp->nciop = NULL;
+ 
+  del_from_NCList(ncp);
+ 
+  free_NC(ncp);
+ 
+  return status;
+}
+
+#else
+
+int
+nc_close(int ncid)
+{
+	int status = NC_NOERR;
+	NC *ncp; 
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+	{
+		status = NC_endef(ncp, 0, 1, 0, 1); /* TODO: defaults */
+		if(status != NC_NOERR )
+		{
+			(void) nc_abort(ncid);
+			return status;
+		}
+	}
+	else if(!NC_readonly(ncp))
+	{
+		status = NC_sync(ncp);
+	}
+
+	(void) ncio_close(ncp->nciop, 0);
+	ncp->nciop = NULL;
+
+	del_from_NCList(ncp);
+
+	free_NC(ncp);
+
+	return status;
+}
+#endif /* #ifdef USE_MPI */
+
+int
+nc_inq(int ncid,
+	int *ndimsp,
+	int *nvarsp,
+	int *nattsp,
+	int *xtendimp)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(ndimsp != NULL)
+		*ndimsp = (int) ncp->dims.nelems;
+	if(nvarsp != NULL)
+		*nvarsp = (int) ncp->vars.nelems;
+	if(nattsp != NULL)
+		*nattsp = (int) ncp->attrs.nelems;
+	if(xtendimp != NULL)
+		*xtendimp = find_NC_Udim(&ncp->dims, NULL);
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_ndims(int ncid, int *ndimsp)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(ndimsp != NULL)
+		*ndimsp = (int) ncp->dims.nelems;
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_nvars(int ncid, int *nvarsp)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(nvarsp != NULL)
+		*nvarsp = (int) ncp->vars.nelems;
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_natts(int ncid, int *nattsp)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(nattsp != NULL)
+		*nattsp = (int) ncp->attrs.nelems;
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_unlimdim(int ncid, int *xtendimp)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(xtendimp != NULL)
+		*xtendimp = find_NC_Udim(&ncp->dims, NULL);
+
+	return NC_NOERR;
+}
+
+
+int
+nc_sync(int ncid)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	if(NC_readonly(ncp))
+	{
+		return read_NC(ncp);
+	}
+	/* else, read/write */
+
+	status = NC_sync(ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	return ncp->nciop->sync(ncp->nciop);
+}
+
+
+int
+nc_set_fill(int ncid,
+	int fillmode, int *old_mode_ptr)
+{
+	int status;
+	NC *ncp;
+	int oldmode;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	oldmode = fIsSet(ncp->flags, NC_NOFILL) ? NC_NOFILL : NC_FILL;
+
+	if(fillmode == NC_NOFILL)
+	{
+		fSet(ncp->flags, NC_NOFILL);
+	}
+	else if(fillmode == NC_FILL)
+	{
+		if(fIsSet(ncp->flags, NC_NOFILL))
+		{
+			/*
+			 * We are changing back to fill mode
+			 * so do a sync
+			 */
+			status = NC_sync(ncp);
+			if(status != NC_NOERR)
+				return status;
+		}
+		fClr(ncp->flags, NC_NOFILL);
+	}
+	else
+	{
+		return NC_EINVAL; /* Invalid fillmode */
+	}
+
+	if(old_mode_ptr != NULL)
+		*old_mode_ptr = oldmode;
+
+	return NC_NOERR;
+}
+
+#ifdef LOCKNUMREC
+
+/* create function versions of the NC_*_numrecs macros */
+size_t NC_get_numrecs(const NC *ncp) {
+	shmem_t numrec;
+	shmem_short_get(&numrec, (shmem_t *) ncp->lock + LOCKNUMREC_VALUE, 1,
+		ncp->lock[LOCKNUMREC_BASEPE]);
+	return (size_t) numrec;
+}
+
+void NC_set_numrecs(NC *ncp, size_t nrecs) {
+	shmem_t numrec = (shmem_t) nrecs;
+	/* update local value too */
+	ncp->lock[LOCKNUMREC_VALUE] = (ushmem_t) numrec;
+	shmem_short_put((shmem_t *) ncp->lock + LOCKNUMREC_VALUE, &numrec, 1,
+		ncp->lock[LOCKNUMREC_BASEPE]);
+}
+
+void NC_increase_numrecs(NC *ncp, size_t nrecs) {
+	/* this is only called in one place that's already protected
+	 * by a lock ... so don't worry about it */
+	if (nrecs > NC_get_numrecs(ncp))
+		NC_set_numrecs(ncp, nrecs);
+}
+
+#endif /* LOCKNUMREC */
+
+/* everyone in communicator group will be executing this */
+/*ARGSUSED*/
+int
+nc_set_base_pe(int ncid, int pe)
+{
+#if _CRAYMPP && defined(LOCKNUMREC)
+	int status;
+	NC *ncp;
+	shmem_t numrecs;
+
+	if ((status = NC_check_id(ncid, &ncp)) != NC_NOERR) {
+		return status;
+	}
+	if (pe < 0 || pe >= _num_pes()) {
+		return NC_EINVAL; /* invalid base pe */
+	}
+
+	numrecs = (shmem_t) NC_get_numrecs(ncp);
+
+	ncp->lock[LOCKNUMREC_VALUE] = (ushmem_t) numrecs;
+
+	/* update serving & lock values for a "smooth" transition */
+	/* note that the "real" server will being doing this as well */
+	/* as all the rest in the group */
+	/* must have syncronization before & after this step */
+	shmem_short_get(
+		(shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
+		(shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
+		1, ncp->lock[LOCKNUMREC_BASEPE]);
+
+	shmem_short_get(
+		(shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
+		(shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
+		1, ncp->lock[LOCKNUMREC_BASEPE]);
+
+	/* complete transition */
+	ncp->lock[LOCKNUMREC_BASEPE] = (ushmem_t) pe;
+
+#endif /* _CRAYMPP && LOCKNUMREC */
+	return NC_NOERR;
+}
+
+/*ARGSUSED*/
+int
+nc_inq_base_pe(int ncid, int *pe)
+{
+#if _CRAYMPP && defined(LOCKNUMREC)
+	int status;
+	NC *ncp;
+
+	if ((status = NC_check_id(ncid, &ncp)) != NC_NOERR) {
+		return status;
+	}
+
+	*pe = (int) ncp->lock[LOCKNUMREC_BASEPE];
+#else
+	/*
+	 * !_CRAYMPP, only pe 0 is valid
+	 */
+	*pe = 0;
+#endif /* _CRAYMPP && LOCKNUMREC */
+	return NC_NOERR;
+}
Index: /branches/SDM_SciDAC/src/lib/nc.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/nc.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/nc.h (revision 2)
@@ -0,0 +1,417 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+#ifndef _NC_H_
+#define _NC_H_
+
+/*
+ *	netcdf library 'private' data structures, objects and interfaces
+ */
+
+#include	"ncconfig.h"
+#include	<stddef.h>	/* size_t */
+#include	<sys/types.h>	/* off_t */
+#include	"netcdf.h"
+#include	"ncio.h"	/* ncio */
+#include	"fbits.h"
+
+
+#ifndef NC_ARRAY_GROWBY
+#define NC_ARRAY_GROWBY 4
+#endif
+
+/*
+ * The extern size of an empty
+ * netcdf version 1 file.
+ * The initial value of ncp->xsz.
+ */
+#define MIN_NC_XSZ 32
+
+typedef struct NC NC; /* forward reference */
+
+/*
+ *  The internal data types
+ */
+typedef enum {
+	NC_UNSPECIFIED = 0,
+/* future	NC_BITFIELD = 7, */
+/*	NC_STRING =	8,	*/
+	NC_DIMENSION =	10,
+	NC_VARIABLE =	11,
+	NC_ATTRIBUTE =	12
+} NCtype;
+
+
+/*
+ * Counted string for names and such
+ */
+typedef struct {
+	/* all xdr'd */
+	size_t nchars;
+	char *cp;
+} NC_string;
+
+extern NC *
+new_NC(const size_t *chunkp);
+
+extern NC *
+dup_NC(const NC *ref);
+
+/* Begin defined in string.c */
+extern void
+free_NC_string(NC_string *ncstrp);
+
+extern int
+NC_check_name(const char *name);
+
+extern NC_string *
+new_NC_string(size_t slen, const char *str);
+
+extern int
+set_NC_string(NC_string *ncstrp, const char *str);
+
+/* End defined in string.c */
+
+/*
+ * NC dimension stucture
+ */
+typedef struct {
+	/* all xdr'd */
+	NC_string *name;
+	size_t size;
+} NC_dim;
+
+typedef struct NC_dimarray {
+	size_t nalloc;		/* number allocated >= nelems */
+	/* below gets xdr'd */
+	/* NCtype type = NC_DIMENSION */
+	size_t nelems;		/* length of the array */
+	NC_dim **value;
+} NC_dimarray;
+
+/* Begin defined in dim.c */
+
+extern void
+free_NC_dim(NC_dim *dimp);
+
+extern NC_dim *
+new_x_NC_dim(NC_string *name);
+
+extern int
+find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp);
+
+/* dimarray */
+
+extern void
+free_NC_dimarrayV0(NC_dimarray *ncap);
+
+extern void
+free_NC_dimarrayV(NC_dimarray *ncap);
+
+extern int
+dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref);
+
+extern NC_dim *
+elem_NC_dimarray(const NC_dimarray *ncap, size_t elem);
+
+/* End defined in dim.c */
+
+/*
+ * NC attribute
+ */
+typedef struct {
+	size_t xsz;		/* amount of space at xvalue */
+	/* below gets xdr'd */
+	NC_string *name;
+	nc_type type;		/* the discriminant */
+	size_t nelems;		/* length of the array */
+	void *xvalue;		/* the actual data, in external representation */
+} NC_attr;
+
+typedef struct NC_attrarray {
+	size_t nalloc;		/* number allocated >= nelems */
+	/* below gets xdr'd */
+	/* NCtype type = NC_ATTRIBUTE */
+	size_t nelems;		/* length of the array */
+	NC_attr **value;
+} NC_attrarray;
+
+/* Begin defined in attr.c */
+
+extern void
+free_NC_attr(NC_attr *attrp);
+
+extern NC_attr *
+new_x_NC_attr(
+	NC_string *strp,
+	nc_type type,
+	size_t nelems);
+
+extern NC_attr **
+NC_findattr(const NC_attrarray *ncap, const char *name);
+
+/* attrarray */
+
+extern void
+free_NC_attrarrayV0(NC_attrarray *ncap);
+
+extern void
+free_NC_attrarrayV(NC_attrarray *ncap);
+
+extern int
+dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref);
+
+extern NC_attr *
+elem_NC_attrarray(const NC_attrarray *ncap, size_t elem);
+
+/* End defined in attr.c */
+
+
+/*
+ * NC variable: description and data
+ */
+typedef struct {
+	size_t xsz;		/* xszof 1 element */
+	size_t *shape; /* compiled info: dim->size of each dim */
+	size_t *dsizes; /* compiled info: the right to left product of shape */
+	/* below gets xdr'd */
+	NC_string *name;
+	/* next two: formerly NC_iarray *assoc */ /* user definition */
+	size_t ndims;	/* assoc->count */
+	int *dimids;	/* assoc->value */
+	NC_attrarray attrs;
+	nc_type type;		/* the discriminant */
+	size_t len;		/* the total length originally allocated */
+	off_t begin;
+} NC_var;
+
+typedef struct NC_vararray {
+	size_t nalloc;		/* number allocated >= nelems */
+	/* below gets xdr'd */
+	/* NCtype type = NC_VARIABLE */
+	size_t nelems;		/* length of the array */
+	NC_var **value;
+} NC_vararray;
+
+/* Begin defined in var.c */
+
+extern void
+free_NC_var(NC_var *varp);
+
+extern NC_var *
+new_x_NC_var(
+	NC_string *strp,
+	size_t ndims);
+
+/* vararray */
+
+extern void
+free_NC_vararrayV0(NC_vararray *ncap);
+
+extern void
+free_NC_vararrayV(NC_vararray *ncap);
+
+extern int
+dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref);
+
+extern int
+NC_var_shape(NC_var *varp, const NC_dimarray *dims);
+
+extern int
+NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp);
+
+extern NC_var *
+NC_lookupvar(NC *ncp, int varid);
+
+/* End defined in var.c */
+
+#define IS_RECVAR(vp) \
+	((vp)->shape != NULL ? (*(vp)->shape == NC_UNLIMITED) : 0 )
+
+#ifdef LOCKNUMREC
+/*
+ * typedef SHMEM type
+ * for whenever the SHMEM functions can handle other than shorts
+ */
+typedef unsigned short int	ushmem_t;
+typedef short int		 shmem_t;
+#endif
+
+struct NC {
+	/* links to make list of open netcdf's */
+	struct NC *next;
+	struct NC *prev;
+	/* contains the previous NC during redef. */
+	struct NC *old;
+	/* flags */
+#define NC_INDEP 1	/* in independent data mode, cleared by endindep */
+#define NC_CREAT 2	/* in create phase, cleared by ncendef */
+#define NC_INDEF 8	/* in define mode, cleared by ncendef */
+#define NC_NSYNC 0x10	/* synchronise numrecs on change */
+#define NC_HSYNC 0x20	/* synchronise whole header on change */
+#define NC_NDIRTY 0x40	/* numrecs has changed */
+#define NC_HDIRTY 0x80  /* header info has changed */
+/*	NC_NOFILL in netcdf.h, historical interface */
+	int flags;
+	ncio *nciop;
+	size_t chunk;	/* largest extent this layer will request from ncio->get() */
+	size_t xsz;	/* external size of this header, <= var[0].begin */
+	off_t begin_var; /* postion of the first (non-record) var */
+	off_t begin_rec; /* postion of the first 'record' */
+	size_t recsize; /* length of 'record' */
+	/* below gets xdr'd */
+	size_t numrecs; /* number of 'records' allocated */
+	NC_dimarray dims;
+	NC_attrarray attrs;
+	NC_vararray vars;
+};
+
+#define NC_readonly(ncp) \
+	(!fIsSet(ncp->nciop->ioflags, NC_WRITE))
+
+#define NC_IsNew(ncp) \
+	fIsSet((ncp)->flags, NC_CREAT)
+
+#define NC_indep(ncp) \
+	fIsSet((ncp)->flags, NC_INDEP)
+
+#define NC_indef(ncp) \
+	(NC_IsNew(ncp) || fIsSet((ncp)->flags, NC_INDEF)) 
+
+#define set_NC_ndirty(ncp) \
+	fSet((ncp)->flags, NC_NDIRTY)
+
+#define NC_ndirty(ncp) \
+	fIsSet((ncp)->flags, NC_NDIRTY)
+
+#define set_NC_hdirty(ncp) \
+	fSet((ncp)->flags, NC_HDIRTY)
+
+#define NC_hdirty(ncp) \
+	fIsSet((ncp)->flags, NC_HDIRTY)
+
+#define NC_dofill(ncp) \
+	(!fIsSet((ncp)->flags, NC_NOFILL))
+
+#define NC_doHsync(ncp) \
+	fIsSet((ncp)->flags, NC_HSYNC)
+
+#define NC_doNsync(ncp) \
+	fIsSet((ncp)->flags, NC_NSYNC)
+
+#ifndef LOCKNUMREC
+#  define NC_get_numrecs(ncp) \
+	((ncp)->numrecs)
+
+#  define NC_set_numrecs(ncp, nrecs) \
+	{((ncp)->numrecs = (nrecs));}
+
+#  define NC_increase_numrecs(ncp, nrecs) \
+	{if((nrecs) > (ncp)->numrecs) ((ncp)->numrecs = (nrecs));}
+#else
+	size_t NC_get_numrecs(const NC *ncp);
+	void   NC_set_numrecs(NC *ncp, size_t nrecs);
+	void   NC_increase_numrecs(NC *ncp, size_t nrecs);
+#endif
+
+/* Begin defined in nc.c */
+
+extern int
+NC_check_id(int ncid, NC **ncpp);
+
+extern int
+nc_cktype(nc_type datatype);
+
+extern size_t
+ncx_howmany(nc_type type, size_t xbufsize);
+
+extern int
+read_numrecs(NC *ncp);
+
+extern int
+write_numrecs(NC *ncp);
+
+extern int
+NC_sync(NC *ncp);
+
+/* End defined in nc.c */
+/* Begin defined in v1hpg.c */
+
+extern size_t
+ncx_len_NC(const NC *ncp);
+
+extern int
+ncx_put_NC(const NC *ncp, void **xpp, off_t offset, size_t extent);
+
+extern int
+nc_get_NC( NC *ncp);
+
+/* End defined in v1hpg.c */
+/* Begin defined in putget.c */
+
+extern int
+fill_NC_var(NC *ncp, const NC_var *varp, size_t recno);
+
+extern int
+nc_inq_rec(int ncid, size_t *nrecvars, int *recvarids, size_t *recsizes);
+
+extern int
+nc_get_rec(int ncid, size_t recnum, void **datap);
+
+extern int
+nc_put_rec(int ncid, size_t recnum, void *const *datap);
+
+/* End defined in putget.c */
+
+/*
+ * These functions are used to support
+ * interface version 2 backward compatiblity.
+ * N.B. these are tested in ../nc_test even though they are
+ * not public. So, be careful to change the declarations in
+ * ../nc_test/tests.h if you change these.
+ */
+
+extern int
+nc_put_att(int ncid, int varid, const char *name, nc_type datatype,
+	size_t len, const void *value);
+
+extern int
+nc_get_att(int ncid, int varid, const char *name, void *value);
+
+extern int
+nc_put_var1(int ncid, int varid, const size_t *index, const void *value);
+
+extern int
+nc_get_var1(int ncid, int varid, const size_t *index, void *value);
+
+extern int
+nc_put_vara(int ncid, int varid,
+	 const size_t *start, const size_t *count, const void *value);
+
+extern int
+nc_get_vara(int ncid, int varid,
+	 const size_t *start, const size_t *count, void *value);
+
+extern int
+nc_put_vars(int ncid, int varid,
+	 const size_t *start, const size_t *count, const ptrdiff_t *stride,
+	 const void * value);
+
+extern int
+nc_get_vars(int ncid, int varid,
+	 const size_t *start, const size_t *count, const ptrdiff_t *stride,
+	 void * value);
+
+extern int
+nc_put_varm(int ncid, int varid,
+	 const size_t *start, const size_t *count, const ptrdiff_t *stride,
+	 const ptrdiff_t * map, const void *value);
+
+extern int
+nc_get_varm(int ncid, int varid,
+	 const size_t *start, const size_t *count, const ptrdiff_t *stride,
+	 const ptrdiff_t * map, void *value);
+
+#endif /* _NC_H_ */
Index: /branches/SDM_SciDAC/src/lib/string.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/string.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/string.c (revision 2)
@@ -0,0 +1,120 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "nc.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include "ncx.h"
+#include "rnd.h"
+
+
+/*
+ * Free string, and, if needed, its values.
+ * Formerly
+NC_free_string()
+ */
+void
+free_NC_string(NC_string *ncstrp)
+{
+	if(ncstrp==NULL)
+		return;
+	free(ncstrp);
+}
+
+
+/*
+ * Verify that a name string is valid
+ * CDL syntax, eg, all the characters are
+ * alphanumeric, '-', '_', or '.'.
+ */
+int
+NC_check_name(const char *name)
+{
+	const char *cp = name;
+	assert(name != NULL);
+
+	if(*name == 0)
+		return NC_EBADNAME; /* empty names disallowed */
+
+	for(; *cp != 0; cp++)
+	{
+		int ch = *cp;
+		if(!isalnum(ch))
+		{
+			if(ch != '_' && ch != '-' && ch != '.')
+				return NC_EBADNAME;
+		}
+	}
+	if(cp - name > NC_MAX_NAME)
+		return NC_EMAXNAME;
+
+	return NC_NOERR;
+}
+
+
+/*
+ * Allocate a NC_string structure large enough
+ * to hold slen characters.
+ * Formerly
+NC_new_string(count, str)
+ */
+NC_string *
+new_NC_string(size_t slen, const char *str)
+{
+	NC_string *ncstrp;
+	size_t sz = M_RNDUP(sizeof(NC_string)) + slen + 1;
+
+#if 0
+	sz = _RNDUP(sz, X_ALIGN);
+#endif
+		
+	ncstrp = (NC_string *)malloc(sz);
+	if( ncstrp == NULL )
+		return NULL;
+	(void) memset(ncstrp, 0, sz);
+
+	ncstrp->nchars = sz - M_RNDUP(sizeof(NC_string)) - 1;
+	assert(ncstrp->nchars + 1 > slen);
+	ncstrp->cp = (char *)ncstrp + M_RNDUP(sizeof(NC_string));
+
+	if(str != NULL && *str != 0)
+	{
+		(void) strncpy(ncstrp->cp, str, ncstrp->nchars +1);
+		ncstrp->cp[ncstrp->nchars] = 0;
+	}
+	
+	return(ncstrp);
+}
+
+
+/*
+ * If possible, change the value of an NC_string to 'str'.
+ *
+ * Formerly
+NC_re_string()
+ */
+int
+set_NC_string(NC_string *ncstrp, const char *str)
+{
+	size_t slen;
+	size_t diff;
+
+	assert(str != NULL && *str != 0);
+
+	slen = strlen(str);
+
+	if(ncstrp->nchars < slen)
+		return NC_ENOTINDEFINE;
+
+	(void) memcpy(ncstrp->cp, str, slen);
+	diff = ncstrp->nchars - slen;
+	if(diff != 0)
+		(void) memset(ncstrp->cp + slen, 0, diff);
+
+	return NC_NOERR;
+}
Index: /branches/SDM_SciDAC/src/lib/onstack.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/onstack.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/onstack.h (revision 2)
@@ -0,0 +1,72 @@
+/*
+ *	Copyright 1997, University Corporation for Atmospheric Research
+ *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#ifndef _ONSTACK_H_
+#define _ONSTACK_H_
+/* include after ncconfig.h */
+/**
+ * This file provides definitions which allow us to
+ * "allocate" arrays on the stack where possible.
+ * (Where not possible, malloc and free are used.)
+ *
+ * The macro ALLOC_ONSTACK(name, type, nelems) is used to declare 
+ * an array of 'type' named 'name' which is 'nelems' long.
+ * FREE_ONSTACK(name) is placed at the end of the scope of 'name'
+ * to call 'free' if necessary.
+ * 
+ * The macro ALLOC_ONSTACK wraps a call to alloca() on most systems.
+ */
+
+#if HAVE_ALLOCA
+/*
+ * Implementation based on alloca()
+ */
+
+#if defined(__GNUC__)
+# if !defined(alloca)
+# define alloca __builtin_alloca
+# endif
+#else
+# if HAVE_ALLOCA_H
+#  include <alloca.h>
+# elif defined(_AIX)
+#  pragma alloca
+# endif /* HAVE_ALLOCA_H */
+#endif /* __GNUC__ */
+
+# if !defined(ALLOCA_ARG_T)
+# define ALLOCA_ARG_T int /* the usual type of the alloca argument */
+# endif
+
+# define ALLOC_ONSTACK(name, type, nelems) \
+	type *const name = (type *) alloca((ALLOCA_ARG_T)((nelems) * sizeof(type)))
+
+# define FREE_ONSTACK(name)
+
+#elif defined(_CRAYC) && !__cplusplus && __STDC__ > 1
+/*
+ * Cray C allows sizing of arrays with non-constant values.
+ */
+
+# define ALLOC_ONSTACK(name, type, nelems) \
+	type name[nelems]
+
+# define FREE_ONSTACK(name)
+
+#else
+/*
+ * Default implementation. When all else fails, use malloc/free.
+ */
+
+# define ALLOC_ONSTACK(name, type, nelems) \
+	type *const name = (type *) malloc((nelems) * sizeof(type))
+
+# define FREE_ONSTACK(name) \
+	free(name)
+
+#endif
+	
+#endif /* _ONSTACK_H_ */
Index: /branches/SDM_SciDAC/src/lib/netcdf.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/netcdf.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/netcdf.h (revision 2)
@@ -0,0 +1,1075 @@
+/*
+ * Copyright 1993-1996 University Corporation for Atmospheric Research/Unidata
+ * 
+ * Portions of this software were developed by the Unidata Program at the 
+ * University Corporation for Atmospheric Research.
+ * 
+ * Access and use of this software shall impose the following obligations
+ * and understandings on the user. The user is granted the right, without
+ * any fee or cost, to use, copy, modify, alter, enhance and distribute
+ * this software, and any derivative works thereof, and its supporting
+ * documentation for any purpose whatsoever, provided that this entire
+ * notice appears in all copies of the software, derivative works and
+ * supporting documentation.  Further, UCAR requests that the user credit
+ * UCAR/Unidata in any publications that result from the use of this
+ * software or in any product that includes this software. The names UCAR
+ * and/or Unidata, however, may not be used in any advertising or publicity
+ * to endorse or promote any products or commercial entity unless specific
+ * written permission is obtained from UCAR/Unidata. The user also
+ * understands that UCAR/Unidata is not obligated to provide the user with
+ * any support, consulting, training or assistance of any kind with regard
+ * to the use, operation and performance of this software nor to provide
+ * the user with any updates, revisions, new versions or "bug fixes."
+ * 
+ * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* "$Id$" */
+
+#ifndef _NETCDF_
+#define _NETCDF_
+
+#include <stddef.h> /* size_t, ptrdiff_t */
+#include <errno.h>  /* netcdf functions sometimes return system errors */
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ *  The netcdf external data types
+ */
+typedef enum {
+	NC_NAT =	0,	/* NAT = 'Not A Type' (c.f. NaN) */
+	NC_BYTE =	1,	/* signed 1 byte integer */
+	NC_CHAR =	2,	/* ISO/ASCII character */
+	NC_SHORT =	3,	/* signed 2 byte integer */
+	NC_INT =	4,	/* signed 4 byte integer */
+	NC_FLOAT =	5,	/* single precision floating point number */
+	NC_DOUBLE =	6	/* double precision floating point number */
+} nc_type;
+
+
+/*
+ * 	Default fill values, used unless _FillValue attribute is set.
+ * These values are stuffed into newly allocated space as appropriate.
+ * The hope is that one might use these to notice that a particular datum
+ * has not been set.
+ */
+#define NC_FILL_BYTE	((signed char)-127)
+#define NC_FILL_CHAR	((char)0)
+#define NC_FILL_SHORT	((short)-32767)
+#define NC_FILL_INT	(-2147483647L)
+#define NC_FILL_FLOAT	(9.9692099683868690e+36f) /* near 15 * 2^119 */
+#define NC_FILL_DOUBLE	(9.9692099683868690e+36)
+
+
+/*
+ * The above values are defaults.
+ * If you wish a variable to use a different value than the above
+ * defaults, create an attribute with the same type as the variable
+ * and the following reserved name. The value you give the attribute
+ * will be used as the fill value for that variable.
+ */
+#define _FillValue	"_FillValue"
+
+
+/*
+ * 'mode' flags for nccreate and ncopen
+ */
+#define NC_NOWRITE	0	/* default is read only */
+#define NC_WRITE    	0x1	/* read & write */
+#define NC_CLOBBER	0
+#define NC_NOCLOBBER	0x4	/* Don't destroy existing file on create */
+#define NC_FILL		0	/* argument to ncsetfill to clear NC_NOFILL */
+#define NC_NOFILL	0x100	/* Don't fill data section an records */
+#define NC_LOCK		0x0400	/* Use locking if available */
+#define NC_SHARE	0x0800	/* Share updates, limit cacheing */
+
+/*
+ * Let nc__create() or nc__open() figure out
+ * as suitable chunk size.
+ */
+#define NC_SIZEHINT_DEFAULT 0
+
+/*
+ * In nc__enddef(), align to the chunk size.
+ */
+#define NC_ALIGN_CHUNK ((size_t)(-1))
+
+/*
+ * 'size' argument to ncdimdef for an unlimited dimension
+ */
+#define NC_UNLIMITED 0L
+
+/*
+ * attribute id to put/get a global attribute
+ */
+#define NC_GLOBAL -1
+
+
+/*
+ * These maximums are enforced by the interface, to facilitate writing
+ * applications and utilities.  However, nothing is statically allocated to
+ * these sizes internally.
+ */
+#define NC_MAX_DIMS	100	 /* max dimensions per file */
+#define NC_MAX_ATTRS	2000	 /* max global or per variable attributes */
+#define NC_MAX_VARS	2000	 /* max variables per file */
+#define NC_MAX_NAME	128	 /* max length of a name */
+#define NC_MAX_VAR_DIMS	NC_MAX_DIMS /* max per variable dimensions */
+
+
+/*
+ * The netcdf version 3 functions all return integer error status.
+ * These are the possible values, in addition to certain
+ * values from the system errno.h.
+ */
+
+#define NC_ISSYSERR(err)	((err) > 0)
+
+#define	NC_NOERR	0	/* No Error */
+
+#define NC_ENOTINDEP	(-26)	/* Operation not allowed in collective data mode */
+#define NC_EINDEP	(-27)	/* Operation not allowed in independent data mode */
+#define NC_EREAD	(-29)	/* Unknown error in reading file */
+#define NC_EWRITE	(-30)	/* Unknown error in writting to file */
+#define NC_EMULTIDEFINE (-31)	/* NC definations on multiprocesses conflict */
+#define NC_EOFILE	(-32)	/* file open/creation failed */
+#define	NC_EBADID	(-33)	/* Not a netcdf id */
+#define	NC_ENFILE	(-34)	/* Too many netcdfs open */
+#define	NC_EEXIST	(-35)	/* netcdf file exists && NC_NOCLOBBER */
+#define	NC_EINVAL	(-36)	/* Invalid Argument */
+#define	NC_EPERM	(-37)	/* Write to read only */
+#define	NC_ENOTINDEFINE	(-38)	/* Operation not allowed in data mode */
+#define	NC_EINDEFINE	(-39)	/* Operation not allowed in define mode */
+#define	NC_EINVALCOORDS	(-40)	/* Index exceeds dimension bound */
+#define	NC_EMAXDIMS	(-41)	/* NC_MAX_DIMS exceeded */
+#define	NC_ENAMEINUSE	(-42)	/* String match to name in use */
+#define NC_ENOTATT	(-43)	/* Attribute not found */
+#define	NC_EMAXATTS	(-44)	/* NC_MAX_ATTRS exceeded */
+#define NC_EBADTYPE	(-45)	/* Not a netcdf data type */
+#define NC_EBADDIM	(-46)	/* Invalid dimension id or name */
+#define NC_EUNLIMPOS	(-47)	/* NC_UNLIMITED in the wrong index */
+#define	NC_EMAXVARS	(-48)	/* NC_MAX_VARS exceeded */
+#define NC_ENOTVAR	(-49)	/* Variable not found */
+#define NC_EGLOBAL	(-50)	/* Action prohibited on NC_GLOBAL varid */
+#define NC_ENOTNC	(-51)	/* Not a netcdf file */
+#define NC_ESTS        	(-52)	/* In Fortran, string too short */
+#define NC_EMAXNAME    	(-53)	/* NC_MAX_NAME exceeded */
+#define NC_EUNLIMIT    	(-54)	/* NC_UNLIMITED size already in use */
+#define NC_ENORECVARS  	(-55)	/* nc_rec op when there are no record vars */
+#define NC_ECHAR	(-56)	/* Attempt to convert between text & numbers */
+#define NC_EEDGE	(-57)	/* Edge+start exceeds dimension bound */
+#define NC_ESTRIDE	(-58)	/* Illegal stride */
+#define NC_EBADNAME	(-59)	/* Attribute or variable name
+                                         contains illegal characters */
+/* N.B. following must match value in ncx.h */
+#define NC_ERANGE	(-60)	/* Math result not representable */
+#define NC_ENOMEM	(-61)	/* Memory allocation (malloc) failure */
+
+/*
+ * The Interface
+ */
+
+/* Declaration modifiers for DLL support (MSC et al) */
+
+#if defined(DLL_NETCDF) /* define when library is a DLL */
+#  if defined(DLL_EXPORT) /* define when building the library */
+#   define MSC_EXTRA __declspec(dllexport)
+#  else
+#   define MSC_EXTRA __declspec(dllimport)
+#  endif
+#else
+#define MSC_EXTRA
+#endif	/* defined(DLL_NETCDF) */
+
+# define EXTERNL extern MSC_EXTRA
+
+#ifndef USE_MPIO /* interfaces below removed by Jianwei Li */
+
+/* Begin v2.4 backward compatiblity */
+/*
+ * defining NO_NETCDF_2 to the preprocessor
+ * turns off backward compatiblity declarations.
+ */
+#ifndef NO_NETCDF_2
+
+/*
+ * Backward compatible aliases
+ */
+#define FILL_BYTE	NC_FILL_BYTE
+#define FILL_CHAR	NC_FILL_CHAR
+#define FILL_SHORT	NC_FILL_SHORT
+#define FILL_LONG	NC_FILL_INT
+#define FILL_FLOAT	NC_FILL_FLOAT
+#define FILL_DOUBLE	NC_FILL_DOUBLE
+
+#define MAX_NC_DIMS	NC_MAX_DIMS
+#define MAX_NC_ATTRS	NC_MAX_ATTRS
+#define MAX_NC_VARS	NC_MAX_VARS
+#define MAX_NC_NAME	NC_MAX_NAME
+#define MAX_VAR_DIMS	NC_MAX_VAR_DIMS
+
+/*
+ * If and when 64 integer types become ubiquitous,
+ * we would like to use NC_LONG for that. 
+ * For now, define for backward compatibility.
+ */
+#define NC_LONG NC_INT
+
+/*
+ * Global error status
+ */
+EXTERNL int ncerr;
+
+#define NC_ENTOOL       NC_EMAXNAME   /* Backward compatibility */
+#define	NC_EXDR		(-32)	/* */
+#define	NC_SYSERR	(-31)
+
+/*
+ * Avoid use of this meaningless macro
+ * Use sysconf(_SC_OPEN_MAX).
+ */
+#ifndef MAX_NC_OPEN
+#define MAX_NC_OPEN 32
+#endif
+
+/*
+ * Global options variable.
+ * Used to determine behavior of error handler.
+ */
+#define	NC_FATAL	1
+#define	NC_VERBOSE	2
+
+EXTERNL int ncopts;	/* default is (NC_FATAL | NC_VERBOSE) */
+
+EXTERNL void
+nc_advise(const char *cdf_routine_name, int err, const char *fmt,...);
+
+/*
+ * C data type corresponding to a netCDF NC_LONG argument,
+ * a signed 32 bit object.
+ * 
+ * This is the only thing in this file which architecture dependent.
+ */
+typedef int nclong;
+
+EXTERNL int
+nctypelen(nc_type datatype);
+
+EXTERNL int
+nccreate(const char* path, int cmode);
+
+EXTERNL int
+ncopen(const char* path, int mode);
+
+EXTERNL int
+ncsetfill(int ncid, int fillmode);
+
+EXTERNL int
+ncredef(int ncid);
+
+EXTERNL int
+ncendef(int ncid);
+
+EXTERNL int
+ncsync(int ncid);
+
+EXTERNL int
+ncabort(int ncid);
+
+EXTERNL int
+ncclose(int ncid);
+
+EXTERNL int
+ncinquire(int ncid, int *ndimsp, int *nvarsp, int *nattsp, int *unlimdimp);
+
+EXTERNL int
+ncdimdef(int ncid, const char *name, long len);
+
+EXTERNL int
+ncdimid(int ncid, const char *name);
+
+EXTERNL int
+ncdiminq(int ncid, int dimid, char *name, long *lenp);
+
+EXTERNL int
+ncdimrename(int ncid, int dimid, const char *name);
+
+EXTERNL int
+ncattput(int ncid, int varid, const char *name, nc_type xtype,
+	int len, const void *op);
+
+EXTERNL int
+ncattinq(int ncid, int varid, const char *name, nc_type *xtypep, int *lenp);
+
+EXTERNL int
+ncattget(int ncid, int varid, const char *name, void *ip);
+
+EXTERNL int
+ncattcopy(int ncid_in, int varid_in, const char *name, int ncid_out,
+	int varid_out);
+
+EXTERNL int
+ncattname(int ncid, int varid, int attnum, char *name);
+
+EXTERNL int
+ncattrename(int ncid, int varid, const char *name, const char *newname);
+
+EXTERNL int
+ncattdel(int ncid, int varid, const char *name);
+
+EXTERNL int
+ncvardef(int ncid, const char *name, nc_type xtype,
+	int ndims, const int *dimidsp);
+
+EXTERNL int
+ncvarid(int ncid, const char *name);
+
+EXTERNL int
+ncvarinq(int ncid, int varid, char *name, nc_type *xtypep,
+	int *ndimsp, int *dimidsp, int *nattsp);
+
+EXTERNL int
+ncvarput1(int ncid, int varid, const long *indexp, const void *op);
+
+EXTERNL int
+ncvarget1(int ncid, int varid, const long *indexp, void *ip);
+
+EXTERNL int
+ncvarput(int ncid, int varid, const long *startp, const long *countp,
+	const void *op);
+
+EXTERNL int
+ncvarget(int ncid, int varid, const long *startp, const long *countp, 
+	void *ip);
+
+EXTERNL int
+ncvarputs(int ncid, int varid, const long *startp, const long *countp,
+	const long *stridep, const void *op);
+
+EXTERNL int
+ncvargets(int ncid, int varid, const long *startp, const long *countp,
+	const long *stridep, void *ip);
+
+EXTERNL int
+ncvarputg(int ncid, int varid, const long *startp, const long *countp,
+	const long *stridep, const long *imapp, const void *op);
+
+EXTERNL int
+ncvargetg(int ncid, int varid, const long *startp, const long *countp,
+	const long *stridep, const long *imapp, void *ip);
+
+EXTERNL int
+ncvarrename(int ncid, int varid, const char *name);
+
+EXTERNL int
+ncrecinq(int ncid, int *nrecvarsp, int *recvaridsp, long *recsizesp);
+
+EXTERNL int
+ncrecget(int ncid, long recnum, void **datap);
+
+EXTERNL int
+ncrecput(int ncid, long recnum, void *const *datap);
+
+/* End v2.4 backward compatiblity */
+#endif /*!NO_NETCDF_2*/
+
+#endif /* USE_MPIO */
+
+#if defined(__cplusplus)
+}
+#endif
+
+#ifdef USE_MPIO /* interface implemented by Jianwei Li */
+
+#include <mpi.h>
+
+EXTERNL
+const char *
+ncmpi_strerror(int err);
+
+/* Begin Dataset Functions */
+
+EXTERNL
+int
+ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp);
+
+EXTERNL
+int
+ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp);
+
+EXTERNL
+int
+ncmpi_enddef(int ncid);
+
+EXTERNL
+int
+ncmpi_redef(int ncid);
+
+EXTERNL
+int
+ncmpi_sync(int ncid);
+
+EXTERNL
+int
+ncmpi_abort(int ncid);
+
+EXTERNL
+int
+ncmpi_begin_indep_data(int ncid);
+
+EXTERNL
+int
+ncmpi_end_indep_data(int ncid);
+
+EXTERNL
+int
+ncmpi_close(int ncid);
+
+/* End Dataset Functions */
+
+/* Begin Define Mode Functions */
+
+EXTERNL
+int
+ncmpi_def_dim(int ncid, const char *name, size_t len, int *idp);
+
+EXTERNL
+int
+ncmpi_def_var(int ncid, const char *name, nc_type xtype, 
+              int ndims, const int *dimidsp, int *varidp);
+
+EXTERNL
+int
+ncmpi_rename_dim(int ncid, int dimid, const char *name);
+
+EXTERNL
+int
+ncmpi_rename_var(int ncid, int varid, const char *name);
+
+/* End Define Mode Functions */
+
+/* Begin Inquiry Functions */
+
+EXTERNL
+int
+ncmpi_inq(int ncid, int *ndimsp, int *nvarsp,
+          int *ngattsp, int *unlimdimidp); 
+
+EXTERNL
+int
+ncmpi_inq_ndims(int ncid, int *ndimsp);
+
+EXTERNL
+int
+ncmpi_inq_nvars(int ncid, int *nvarsp);
+
+EXTERNL
+int
+ncmpi_inq_natts(int ncid, int *ngattsp);
+
+EXTERNL
+int
+ncmpi_inq_unlimdim(int ncid, int *unlimdimidp);
+
+EXTERNL
+int
+ncmpi_inq_dimid(int ncid, const char *name, int *idp);
+
+EXTERNL
+int
+ncmpi_inq_dim(int ncid, int dimid, char *name, size_t *lenp);
+
+EXTERNL
+int
+ncmpi_inq_dimname(int ncid, int dimid, char *name);
+
+EXTERNL
+int
+ncmpi_inq_dimlen(int ncid, int dimid, size_t *lenp);
+
+EXTERNL
+int
+ncmpi_inq_var(int ncid, int varid, char *name,
+              nc_type *xtypep, int *ndimsp, int *dimidsp,
+              int *nattsp);
+
+EXTERNL
+int
+ncmpi_inq_varid(int ncid, const char *name, int *varidp);
+
+EXTERNL
+int
+ncmpi_inq_varname(int ncid, int varid, char *name);
+
+EXTERNL
+int
+ncmpi_inq_vartype(int ncid, int varid, nc_type *xtypep);
+
+EXTERNL
+int
+ncmpi_inq_varndims(int ncid, int varid, int *ndimsp);
+
+EXTERNL
+int
+ncmpi_inq_vardimid(int ncid, int varid, int *dimidsp);
+
+EXTERNL
+int
+ncmpi_inq_varnatts(int ncid, int varid, int *nattsp);
+
+/* End Inquiry Functions */
+
+/* Begin _att */
+
+EXTERNL
+int
+ncmpi_inq_att(int ncid, int varid, const char *name,
+              nc_type *xtypep, size_t *lenp);
+
+EXTERNL
+int
+ncmpi_inq_attid(int ncid, int varid, const char *name, int *idp);
+
+EXTERNL
+int
+ncmpi_inq_atttype(int ncid, int varid, const char *name,
+                  nc_type *xtypep);
+
+EXTERNL
+int
+ncmpi_inq_attlen(int ncid, int varid, const char *name,
+                 size_t *lenp);
+
+EXTERNL
+int
+ncmpi_inq_attname(int ncid, int varid, int attnum, char *name);
+
+EXTERNL
+int
+ncmpi_copy_att(int ncid_in, int varid_in, const char *name,
+               int ncid_out, int varid_out);
+
+EXTERNL
+int
+ncmpi_rename_att(int ncid, int varid, const char *name,
+                 const char *newname);
+
+EXTERNL
+int
+ncmpi_del_att(int ncid, int varid, const char *name);
+
+EXTERNL
+int
+ncmpi_put_att_text(int ncid, int varid, const char *name, size_t len,
+                   const char *op);
+
+EXTERNL
+int
+ncmpi_get_att_text(int ncid, int varid, const char *name, char *ip);
+
+EXTERNL
+int
+ncmpi_put_att_uchar(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const unsigned char *op);
+
+EXTERNL
+int
+ncmpi_get_att_uchar(int ncid, int varid, const char *name,
+                    unsigned char *ip);
+
+EXTERNL
+int
+ncmpi_put_att_schar(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const signed char *op);
+
+EXTERNL
+int
+ncmpi_get_att_schar(int ncid, int varid, const char *name,
+                    signed char *ip);
+
+EXTERNL
+int
+ncmpi_put_att_short(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const short *op);
+
+EXTERNL
+int
+ncmpi_get_att_short(int ncid, int varid, const char *name, short *ip);
+
+EXTERNL
+int
+ncmpi_put_att_int(int ncid, int varid, const char *name,
+                  nc_type xtype, size_t len, const int *op);
+
+EXTERNL
+int
+ncmpi_get_att_int(int ncid, int varid, const char *name, int *ip);
+
+EXTERNL
+int
+ncmpi_put_att_long(int ncid, int varid, const char *name,
+                   nc_type xtype, size_t len, const long *op);
+
+EXTERNL
+int
+ncmpi_get_att_long(int ncid, int varid, const char *name, long *ip);
+
+EXTERNL
+int
+ncmpi_put_att_float(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const float *op);
+
+EXTERNL
+int
+ncmpi_get_att_float(int ncid, int varid, const char *name, float *ip);
+
+EXTERNL
+int
+ncmpi_put_att_double(int ncid, int varid, const char *name,
+                     nc_type xtype, size_t len, const double *op);
+
+EXTERNL
+int
+ncmpi_get_att_double(int ncid, int varid, const char *name,
+                     double *ip);
+
+/* End _att */
+
+/* Begin {put,get}_var1 */
+
+EXTERNL
+int
+ncmpi_put_var1(int ncid, int varid,
+               const size_t index[],
+               const void *buf, int bufcount,
+               MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_get_var1(int ncid, int varid,
+               const size_t index[],
+               void *buf, int bufcount,
+               MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_put_var1_short(int ncid, int varid,
+                     const size_t index[],
+                     const short *op);
+
+EXTERNL
+int
+ncmpi_put_var1_int(int ncid, int varid,
+                   const size_t index[],
+                   const int *op);
+
+EXTERNL
+int
+ncmpi_put_var1_float(int ncid, int varid,
+                     const size_t index[],
+                     const float *op);
+
+EXTERNL
+int
+ncmpi_put_var1_double(int ncid, int varid,
+                      const size_t index[],
+                      const double *op);
+
+EXTERNL
+int
+ncmpi_get_var1_short(int ncid, int varid,
+                     const size_t index[],
+                     short *ip);
+
+EXTERNL
+int
+ncmpi_get_var1_int(int ncid, int varid,
+                   const size_t index[],
+                   int *ip);
+
+EXTERNL
+int
+ncmpi_get_var1_float(int ncid, int varid,
+                     const size_t index[],
+                     float *ip);
+
+EXTERNL
+int
+ncmpi_get_var1_double(int ncid, int varid,
+                      const size_t index[],
+                      double *ip);
+
+/* End {put,get}_var1 */
+
+/* Begin {put,get}_var */  
+
+EXTERNL
+int
+ncmpi_put_var(int ncid, int varid, const void *buf, int bufcount, MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_get_var(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_get_var_all(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_put_var_short(int ncid, int varid, const short *op);
+
+EXTERNL
+int
+ncmpi_put_var_int(int ncid, int varid, const int *op);
+
+EXTERNL
+int
+ncmpi_put_var_float(int ncid, int varid, const float *op);
+
+EXTERNL
+int
+ncmpi_put_var_double(int ncid, int varid, const double *op);
+
+EXTERNL
+int
+ncmpi_get_var_short(int ncid, int varid, short *ip);
+
+EXTERNL
+int
+ncmpi_get_var_int(int ncid, int varid, int *ip);
+
+EXTERNL
+int
+ncmpi_get_var_float(int ncid, int varid, float *ip);
+
+EXTERNL
+int
+ncmpi_get_var_double(int ncid, int varid, double *ip);
+
+EXTERNL
+int
+ncmpi_get_var_short_all(int ncid, int varid, short *ip);
+
+EXTERNL
+int
+ncmpi_get_var_int_all(int ncid, int varid, int *ip);
+
+EXTERNL
+int
+ncmpi_get_var_float_all(int ncid, int varid, float *ip);
+
+EXTERNL
+int
+ncmpi_get_var_double_all(int ncid, int varid, double *ip);
+
+/* End {put,get}_var */
+
+/* Begin {put,get}_vara */
+
+EXTERNL
+int
+ncmpi_put_vara_all(int ncid, int varid,
+                   const size_t start[], const size_t count[],
+                   const void *buf, int bufcount,
+                   MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_get_vara_all(int ncid, int varid,
+                   const size_t start[], const size_t count[],
+                   void *buf, int bufcount,
+                   MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_put_vara(int ncid, int varid,
+               const size_t start[], const size_t count[],
+               const void *buf, int bufcount,
+               MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_get_vara(int ncid, int varid,
+               const size_t start[], const size_t count[],
+               void *buf, int bufcount,
+               MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_put_vara_short_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const short *op);
+
+EXTERNL
+int
+ncmpi_put_vara_short(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const short *op);
+
+EXTERNL
+int
+ncmpi_put_vara_int_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const int *op);
+
+EXTERNL
+int
+ncmpi_put_vara_int(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const int *op);
+
+EXTERNL
+int
+ncmpi_put_vara_float_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const float *op);
+
+EXTERNL
+int
+ncmpi_put_vara_float(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const float *op);
+
+EXTERNL
+int
+ncmpi_put_vara_double_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const double *op);
+
+EXTERNL
+int
+ncmpi_put_vara_double(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const double *op);
+
+EXTERNL
+int
+ncmpi_get_vara_short_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    short *ip);
+
+EXTERNL
+int
+ncmpi_get_vara_short(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    short *ip);
+
+EXTERNL
+int
+ncmpi_get_vara_int_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    int *ip);
+
+EXTERNL
+int
+ncmpi_get_vara_int(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                int *ip);
+
+EXTERNL
+int
+ncmpi_get_vara_float_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    float *ip);
+
+EXTERNL
+int
+ncmpi_get_vara_float(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                float *ip);
+
+EXTERNL
+int
+ncmpi_get_vara_double_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    double *ip);
+
+EXTERNL
+int
+ncmpi_get_vara_double(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                double *ip);
+
+/* End {put,get}_vara */
+
+/* Begin {put,get}_vars */
+
+EXTERNL
+int
+ncmpi_put_vars_all(int ncid, int varid,
+                   const size_t start[],
+                   const size_t count[],
+                   const size_t stride[],
+                   const void *buf, int bufcount,
+                   MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_get_vars_all(int ncid, int varid,
+                   const size_t start[],
+                   const size_t count[],
+                   const size_t stride[],
+                   void *buf, int bufcount,
+                   MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_put_vars(int ncid, int varid,
+               const size_t start[],
+               const size_t count[],
+               const size_t stride[],
+               const void *buf, int bufcount,
+               MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_get_vars(int ncid, int varid,
+               const size_t start[],
+               const size_t count[],
+               const size_t stride[],
+               void *buf, int bufcount,
+               MPI_Datatype datatype);
+
+EXTERNL
+int
+ncmpi_put_vars_short_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         const short *op);
+
+EXTERNL
+int
+ncmpi_put_vars_short(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     const short *op);
+
+EXTERNL
+int
+ncmpi_put_vars_int_all(int ncid, int varid,
+                       const size_t start[],
+                       const size_t count[],
+                       const size_t stride[],
+                       const int *op);
+
+EXTERNL
+int
+ncmpi_put_vars_int(int ncid, int varid,
+                   const size_t start[],
+                   const size_t count[],
+                   const size_t stride[],
+                   const int *op);
+
+EXTERNL
+int
+ncmpi_put_vars_float_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         const float *op);
+
+EXTERNL
+int
+ncmpi_put_vars_float(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     const float *op);
+
+EXTERNL
+int
+ncmpi_put_vars_double_all(int ncid, int varid,
+                          const size_t start[],
+                          const size_t count[],
+                          const size_t stride[],
+                          const double *op);
+
+EXTERNL
+int
+ncmpi_put_vars_double(int ncid, int varid,
+                      const size_t start[],
+                      const size_t count[],
+                      const size_t stride[],
+                      const double *op);
+
+EXTERNL
+int
+ncmpi_get_vars_short_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         short *ip);
+
+EXTERNL
+int
+ncmpi_get_vars_short(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     short *ip);
+
+EXTERNL
+int
+ncmpi_get_vars_int_all(int ncid, int varid,
+                       const size_t start[],
+                       const size_t count[],
+                       const size_t stride[],
+                       int *ip);
+
+EXTERNL
+int
+ncmpi_get_vars_int(int ncid, int varid,
+                   const size_t start[],
+                   const size_t count[],
+                   const size_t stride[],
+                   int *ip);
+
+EXTERNL
+int
+ncmpi_get_vars_float_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         float *ip);
+
+EXTERNL
+int
+ncmpi_get_vars_float(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     float *ip);
+
+EXTERNL
+int
+ncmpi_get_vars_double_all(int ncid, int varid,
+                          const size_t start[],
+                          const size_t count[],
+                          const size_t stride[],
+                          double *ip);
+
+EXTERNL
+int
+ncmpi_get_vars_double(int ncid, int varid,
+                      const size_t start[],
+                      const size_t count[],
+                      const size_t stride[],
+                      double *ip);
+
+/* End {put,get}_vars */
+
+#endif /* USE_MPIO */
+
+#endif /* _NETCDF_ */
Index: /branches/SDM_SciDAC/src/lib/putget.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/putget.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/putget.c (revision 2)
@@ -0,0 +1,11789 @@
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "nc.h"
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "ncx.h"
+#include "fbits.h"
+#include "onstack.h"
+#ifdef LOCKNUMREC
+#  include <mpp/shmem.h>	/* for SGI/Cray SHMEM routines */
+#  ifdef LN_TEST
+#    include <stdio.h>
+#  endif
+#endif
+
+#undef MIN  /* system may define MIN somewhere and complain */
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+
+/* #define ODEBUG 1 */
+
+#if ODEBUG
+#include <stdio.h>
+/*
+ * Print the values of an array of size_t
+ */
+void
+arrayp(const char *label, size_t count, const size_t *array)
+{
+	(void) fprintf(stderr, "%s", label);
+	(void) fputc('\t',stderr);	
+	for(; count > 0; count--, array++)
+		(void) fprintf(stderr," %lu", (unsigned long)*array);
+	(void) fputc('\n',stderr);	
+}
+#endif /* ODEBUG */
+
+
+/* Begin fill */
+/*
+ * This is tunable parameter.
+ * It essentially controls the tradeoff between the number of times
+ * memcpy() gets called to copy the external data to fill 
+ * a large buffer vs the number of times its called to
+ * prepare the external data.
+ */
+#define NFILL 16
+
+
+
+/*
+ * Next 6 type specific functions
+ * Fill a some memory with the default special value.
+ * Formerly
+NC_arrayfill()
+ */
+static int
+NC_fill_schar(
+	void **xpp,
+	size_t nelems)	/* how many */
+{
+	schar fillp[NFILL * sizeof(double)/X_SIZEOF_CHAR];
+
+	assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
+
+	{
+		schar *vp = fillp;	/* lower bound of area to be filled */
+		const schar *const end = vp + nelems;
+		while(vp < end)
+		{
+			*vp++ = NC_FILL_BYTE;
+		}
+	}
+	return ncx_putn_schar_schar(xpp, nelems, fillp);
+}
+
+static int
+NC_fill_char(
+	void **xpp,
+	size_t nelems)	/* how many */
+{
+	char fillp[NFILL * sizeof(double)/X_SIZEOF_CHAR];
+
+	assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
+
+	{
+		char *vp = fillp;	/* lower bound of area to be filled */
+		const char *const end = vp + nelems;
+		while(vp < end)
+		{
+			*vp++ = NC_FILL_CHAR;
+		}
+	}
+	return ncx_putn_char_char(xpp, nelems, fillp);
+}
+
+static int
+NC_fill_short(
+	void **xpp,
+	size_t nelems)	/* how many */
+{
+	short fillp[NFILL * sizeof(double)/X_SIZEOF_SHORT];
+
+	assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
+
+	{
+		short *vp = fillp;	/* lower bound of area to be filled */
+		const short *const end = vp + nelems;
+		while(vp < end)
+		{
+			*vp++ = NC_FILL_SHORT;
+		}
+	}
+	return ncx_putn_short_short(xpp, nelems, fillp);
+}
+
+
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+static int
+NC_fill_int(
+	void **xpp,
+	size_t nelems)	/* how many */
+{
+	int fillp[NFILL * sizeof(double)/X_SIZEOF_INT];
+
+	assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
+
+	{
+		int *vp = fillp;	/* lower bound of area to be filled */
+		const int *const end = vp + nelems;
+		while(vp < end)
+		{
+			*vp++ = NC_FILL_INT;
+		}
+	}
+	return ncx_putn_int_int(xpp, nelems, fillp);
+}
+
+#elif SIZEOF_LONG == X_SIZEOF_INT
+static int
+NC_fill_int(
+	void **xpp,
+	size_t nelems)	/* how many */
+{
+	long fillp[NFILL * sizeof(double)/X_SIZEOF_INT];
+
+	assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
+
+	{
+		long *vp = fillp;	/* lower bound of area to be filled */
+		const long *const end = vp + nelems;
+		while(vp < end)
+		{
+			*vp++ = NC_FILL_INT;
+		}
+	}
+	return ncx_putn_int_long(xpp, nelems, fillp);
+}
+
+#else
+#error "NC_fill_int implementation"
+#endif
+
+static int
+NC_fill_float(
+	void **xpp,
+	size_t nelems)	/* how many */
+{
+	float fillp[NFILL * sizeof(double)/X_SIZEOF_FLOAT];
+
+	assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
+
+	{
+		float *vp = fillp;	/* lower bound of area to be filled */
+		const float *const end = vp + nelems;
+		while(vp < end)
+		{
+			*vp++ = NC_FILL_FLOAT;
+		}
+	}
+	return ncx_putn_float_float(xpp, nelems, fillp);
+}
+
+static int
+NC_fill_double(
+	void **xpp,
+	size_t nelems)	/* how many */
+{
+	double fillp[NFILL * sizeof(double)/X_SIZEOF_DOUBLE];
+
+	assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
+
+	{
+		double *vp = fillp;	/* lower bound of area to be filled */
+		const double *const end = vp + nelems;
+		while(vp < end)
+		{
+			*vp++ = NC_FILL_DOUBLE;
+		}
+	}
+	return ncx_putn_double_double(xpp, nelems, fillp);
+}
+
+
+
+/*
+ * Fill the external space for variable 'varp' values at 'recno'
+ * with the appropriate value. If 'varp' is not a record
+ * variable, fill the whole thing.
+ * Formerly
+xdr_NC_fill()
+ */
+int
+fill_NC_var(NC *ncp, const NC_var *varp, size_t recno)
+{
+	char xfillp[NFILL * X_SIZEOF_DOUBLE];
+	const size_t step = varp->xsz;
+	const size_t nelems = sizeof(xfillp)/step;
+	const size_t xsz = varp->xsz * nelems;
+	NC_attr **attrpp = NULL;
+	off_t offset;
+	size_t remaining = varp->len;
+
+	void *xp;
+	int status = NC_NOERR;
+
+	/*
+	 * Set up fill value
+	 */
+	attrpp = NC_findattr(&varp->attrs, _FillValue);
+	if( attrpp != NULL )
+	{
+		/* User defined fill value */
+		if( (*attrpp)->type != varp->type || (*attrpp)->nelems != 1 )
+		{
+			return NC_EBADTYPE;
+		}
+		else
+		{
+			/* Use the user defined value */
+			char *cp = xfillp;
+			const char *const end = &xfillp[sizeof(xfillp)];
+
+			assert(step <= (*attrpp)->xsz);
+
+			for( /*NADA*/; cp < end; cp += step)
+			{
+				(void) memcpy(cp, (*attrpp)->xvalue, step);
+			}
+		}
+	}
+	else
+	{
+		/* use the default */
+		
+		assert(xsz % X_ALIGN == 0);
+		assert(xsz <= sizeof(xfillp));
+	
+		xp = xfillp;
+	
+		switch(varp->type){
+		case NC_BYTE :
+			status = NC_fill_schar(&xp, nelems);
+			break;
+		case NC_CHAR :
+			status = NC_fill_char(&xp, nelems);
+			break;
+		case NC_SHORT :
+			status = NC_fill_short(&xp, nelems);
+			break;
+		case NC_INT :
+			status = NC_fill_int(&xp, nelems);
+			break;
+		case NC_FLOAT :
+			status = NC_fill_float(&xp, nelems);
+			break;
+		case NC_DOUBLE : 
+			status = NC_fill_double(&xp, nelems);
+			break;
+		default :
+			assert("fill_NC_var invalid type" == 0);
+			status = NC_EBADTYPE;
+			break;
+		}
+		if(status != NC_NOERR)
+			return status;
+	
+		assert(xp == xfillp + xsz);
+	}
+
+	/*
+	 * copyout:
+	 * xfillp now contains 'nelems' elements of the fill value
+	 * in external representation.
+	 */
+
+	/*
+	 * Copy it out.
+	 */
+
+	offset = varp->begin;
+	if(IS_RECVAR(varp))
+	{
+		offset += (off_t)ncp->recsize * recno;
+	}
+
+	assert(remaining > 0);
+	for(;;)
+	{
+		const size_t chunksz = MIN(remaining, ncp->chunk);
+		size_t ii;
+		assert(chunksz % X_ALIGN == 0);
+
+		status = ncp->nciop->get(ncp->nciop, offset, chunksz,
+				 RGN_WRITE, &xp);	
+		if(status != NC_NOERR)
+		{
+			return status;
+		}
+
+		/*
+		 * fill the chunksz buffer in units  of xsz
+		 */
+		for(ii = 0; ii < chunksz/xsz; ii++)
+		{
+			(void) memcpy(xp, xfillp, xsz);
+			xp = (char *)xp + xsz;
+		}
+		/*
+		 * Deal with any remainder
+		 */
+		{
+			const size_t rem = chunksz % xsz;
+			if(rem != 0)
+			{
+				(void) memcpy(xp, xfillp, rem);
+				/* xp = (char *)xp + xsz; */
+			}
+
+		}
+
+		status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED);
+
+		if(status != NC_NOERR)
+		{
+			break;
+		}
+
+		remaining -= chunksz;
+		if(remaining == 0)
+			break;	/* normal loop exit */
+		offset += chunksz;
+
+	}
+
+	return status;
+}
+/* End fill */
+
+
+/*
+ * Add a record containing the fill values.
+ */
+static int
+NCfillrecord(NC *ncp, const NC_var *const *varpp, size_t recno)
+{
+	size_t ii = 0;
+	for(; ii < ncp->vars.nelems; ii++, varpp++)
+	{
+		if( !IS_RECVAR(*varpp) )
+		{
+			continue;	/* skip non-record variables */
+		}
+		{
+		const int status = fill_NC_var(ncp, *varpp, recno);
+		if(status != NC_NOERR)
+			return status;
+		}
+	}
+	return NC_NOERR;
+}
+
+/*
+ * It is advantageous to
+ * #define TOUCH_LAST
+ * when using memory mapped io.
+ */
+#if TOUCH_LAST
+/*
+ * Grow the file to a size which can contain recno
+ */
+static int
+NCtouchlast(NC *ncp, const NC_var *const *varpp, size_t recno)
+{
+	int status = NC_NOERR;
+	const NC_var *varp = NULL;
+	
+	{
+	size_t ii = 0;
+	for(; ii < ncp->vars.nelems; ii++, varpp++)
+	{
+		if( !IS_RECVAR(*varpp) )
+		{
+			continue;	/* skip non-record variables */
+		}
+		varp = *varpp;
+	}
+	}
+	assert(varp != NULL);
+	assert( IS_RECVAR(varp) );
+	{
+		const off_t offset = varp->begin
+				+ (off_t)(recno-1) * (off_t)ncp->recsize
+				+ (off_t)(varp->len - varp->xsz);
+		void *xp;
+
+
+		status = ncp->nciop->get(ncp->nciop, offset, varp->xsz,
+				 RGN_WRITE, &xp);	
+		if(status != NC_NOERR)
+			return status;
+		(void)memset(xp, 0, varp->xsz);
+		status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED);
+	}
+	return status;
+}
+#endif /* TOUCH_LAST */
+
+
+/*
+ * Ensure that the netcdf file has 'numrecs' records,
+ * add records and fill as neccessary.
+ */
+static int
+NCvnrecs(NC *ncp, size_t numrecs)
+{
+	int status = NC_NOERR;
+#ifdef LOCKNUMREC
+	ushmem_t myticket = 0, nowserving = 0;
+	ushmem_t numpe = (ushmem_t) _num_pes();
+
+	/* get ticket and wait */
+	myticket = shmem_short_finc((shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
+		ncp->lock[LOCKNUMREC_BASEPE]);
+#ifdef LN_TEST
+		fprintf(stderr,"%d of %d : ticket = %hu\n",
+			_my_pe(), _num_pes(), myticket);
+#endif
+	do {
+		shmem_short_get((shmem_t *) &nowserving,
+			(shmem_t *) ncp->lock + LOCKNUMREC_SERVING, 1,
+			ncp->lock[LOCKNUMREC_BASEPE]);
+#ifdef LN_TEST
+		fprintf(stderr,"%d of %d : serving = %hu\n",
+			_my_pe(), _num_pes(), nowserving);
+#endif
+		/* work-around for non-unique tickets */
+		if (nowserving > myticket && nowserving < myticket + numpe ) {
+			/* get a new ticket ... you've been bypassed */ 
+			/* and handle the unlikely wrap-around effect */
+			myticket = shmem_short_finc(
+				(shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
+				ncp->lock[LOCKNUMREC_BASEPE]);
+#ifdef LN_TEST
+				fprintf(stderr,"%d of %d : new ticket = %hu\n",
+					_my_pe(), _num_pes(), myticket);
+#endif
+		}
+	} while(nowserving != myticket);
+	/* now our turn to check & update value */
+#endif
+
+	if(numrecs > NC_get_numrecs(ncp))
+	{
+
+
+#if TOUCH_LAST
+		status = NCtouchlast(ncp,
+			(const NC_var *const*)ncp->vars.value,
+			numrecs);
+		if(status != NC_NOERR)
+			goto common_return;
+#endif /* TOUCH_LAST */
+
+		set_NC_ndirty(ncp);
+
+		if(!NC_dofill(ncp))
+		{
+			/* Simply set the new numrecs value */
+			NC_set_numrecs(ncp, numrecs);
+		}
+		else
+		{
+			/* Fill each record out to numrecs */
+			size_t cur_nrecs;
+			while((cur_nrecs = NC_get_numrecs(ncp)) < numrecs)
+			{
+				status = NCfillrecord(ncp,
+					(const NC_var *const*)ncp->vars.value,
+					cur_nrecs);
+				if(status != NC_NOERR)
+				{
+					break;
+				}
+				NC_increase_numrecs(ncp, cur_nrecs +1);
+			}
+			if(status != NC_NOERR)
+				goto common_return;
+		}
+
+		if(NC_doNsync(ncp))
+		{
+			status = write_numrecs(ncp);
+		}
+
+	}
+common_return:
+#ifdef LOCKNUMREC
+	/* finished with our lock - increment serving number */
+	(void) shmem_short_finc((shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
+		ncp->lock[LOCKNUMREC_BASEPE]);
+#endif
+	return status;
+}
+
+
+/* 
+ * Check whether 'coord' values are valid for the variable.
+ */
+static int
+NCcoordck(NC *ncp, const NC_var *varp, const size_t *coord)
+{
+	const size_t *ip;
+	size_t *up;
+
+	if(varp->ndims == 0)
+		return NC_NOERR;	/* 'scalar' variable */
+
+	if(IS_RECVAR(varp))
+	{
+		if(*coord > X_INT_MAX)
+			return NC_EINVALCOORDS; /* sanity check */
+		if(NC_readonly(ncp) && *coord >= NC_get_numrecs(ncp))
+		{
+			if(!NC_doNsync(ncp))
+				return NC_EINVALCOORDS;
+			/* else */
+			{
+				/* Update from disk and check again */
+				const int status = read_numrecs(ncp);
+				if(status != NC_NOERR)
+					return status;
+				if(*coord >= NC_get_numrecs(ncp))
+					return NC_EINVALCOORDS;
+			}
+		}
+		ip = coord + 1;
+		up = varp->shape + 1;
+	}
+	else
+	{
+		ip = coord;
+		up = varp->shape;
+	}
+	
+#ifdef CDEBUG
+fprintf(stderr,"	NCcoordck: coord %ld, count %d, ip %ld\n",
+		coord, varp->ndims, ip );
+#endif /* CDEBUG */
+
+	for(; ip < coord + varp->ndims; ip++, up++)
+	{
+
+#ifdef CDEBUG
+fprintf(stderr,"	NCcoordck: ip %p, *ip %ld, up %p, *up %lu\n",
+			ip, *ip, up, *up );
+#endif /* CDEBUG */
+
+		/* cast needed for braindead systems with signed size_t */
+		if((unsigned long) *ip >= (unsigned long) *up )
+			return NC_EINVALCOORDS;
+	}
+
+	return NC_NOERR;
+}
+
+
+/* 
+ * Check whether 'edges' are valid for the variable and 'start'
+ */
+/*ARGSUSED*/
+static int
+NCedgeck(const NC *ncp, const NC_var *varp,
+	 const size_t *start, const size_t *edges)
+{
+	const size_t *const end = start + varp->ndims;
+	const size_t *shp = varp->shape;
+
+	if(varp->ndims == 0)
+		return NC_NOERR;	/* 'scalar' variable */
+
+	if(IS_RECVAR(varp))
+	{
+		start++;
+		edges++;
+		shp++;
+	}
+
+	for(; start < end; start++, edges++, shp++)
+	{
+		/* cast needed for braindead systems with signed size_t */
+		if((unsigned long) *edges > *shp ||
+			(unsigned long) *start + (unsigned long) *edges > *shp)
+		{
+			return(NC_EEDGE);
+		}
+	}
+	return NC_NOERR;
+}
+
+
+/* 
+ * Translate the (variable, coord) pair into a seek index
+ */
+static off_t
+NC_varoffset(const NC *ncp, const NC_var *varp, const size_t *coord)
+{
+	if(varp->ndims == 0) /* 'scalar' variable */
+		return varp->begin;
+
+	if(varp->ndims == 1)
+	{
+		if(IS_RECVAR(varp))
+			return varp->begin +
+				 (off_t)(*coord) * (off_t)ncp->recsize;
+		/* else */
+		return varp->begin + (off_t)(*coord) * (off_t)varp->xsz;
+	}
+	/* else */
+	{
+		off_t lcoord = (off_t)coord[varp->ndims -1];
+
+		size_t *up = varp->dsizes +1;
+		const size_t *ip = coord;
+		const size_t *const end = varp->dsizes + varp->ndims;
+		
+		if(IS_RECVAR(varp))
+			up++, ip++;
+
+		for(; up < end; up++, ip++)
+			lcoord += *up * *ip;
+
+		lcoord *= varp->xsz;
+		
+		if(IS_RECVAR(varp))
+			lcoord += (off_t)(*coord) * ncp->recsize;
+		
+		lcoord += varp->begin;
+		return lcoord;
+	}
+}
+
+
+
+static int
+putNCvx_char_char(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const char *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_char_char(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+
+static int
+putNCvx_schar_schar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_schar_schar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_schar_uchar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_schar_uchar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_schar_short(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_schar_short(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_schar_int(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_schar_int(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_schar_long(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_schar_long(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_schar_float(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_schar_float(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_schar_double(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_schar_double(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+
+static int
+putNCvx_short_schar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_short_schar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_short_uchar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_short_uchar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_short_short(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_short_short(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_short_int(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_short_int(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_short_long(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_short_long(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_short_float(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_short_float(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_short_double(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_short_double(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+
+static int
+putNCvx_int_schar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_int_schar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_int_uchar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_int_uchar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_int_short(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_int_short(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_int_int(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_int_int(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_int_long(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_int_long(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_int_float(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_int_float(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_int_double(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_int_double(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+
+static int
+putNCvx_float_schar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_float_schar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_float_uchar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_float_uchar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_float_short(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_float_short(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_float_int(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_float_int(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_float_long(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_float_long(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_float_float(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_float_float(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_float_double(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_float_double(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+
+static int
+putNCvx_double_schar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_double_schar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_double_uchar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_double_uchar(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_double_short(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_double_short(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_double_int(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_double_int(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_double_long(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_double_long(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_double_float(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_double_float(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+static int
+putNCvx_double_double(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nput = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 RGN_WRITE, &xp);	
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_putn_double_double(&xp, nput, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+		{
+			/* not fatal to the loop */
+			status = lstatus;
+		}
+
+		(void) ncp->nciop->rel(ncp->nciop, offset,
+				 RGN_MODIFIED);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nput;
+
+	}
+
+	return status;
+}
+
+
+
+
+static int
+putNCv_text(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const char *value)
+{
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+	return putNCvx_char_char(ncp, varp, start, nelems, value);
+}
+
+static int
+putNCv_schar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const schar *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return putNCvx_schar_schar(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return putNCvx_short_schar(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return putNCvx_int_schar(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return putNCvx_float_schar(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return putNCvx_double_schar(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+putNCv_uchar(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const uchar *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return putNCvx_schar_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return putNCvx_short_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return putNCvx_int_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return putNCvx_float_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return putNCvx_double_uchar(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+putNCv_short(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const short *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return putNCvx_schar_short(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return putNCvx_short_short(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return putNCvx_int_short(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return putNCvx_float_short(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return putNCvx_double_short(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+putNCv_int(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const int *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return putNCvx_schar_int(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return putNCvx_short_int(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return putNCvx_int_int(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return putNCvx_float_int(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return putNCvx_double_int(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+putNCv_long(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const long *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return putNCvx_schar_long(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return putNCvx_short_long(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return putNCvx_int_long(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return putNCvx_float_long(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return putNCvx_double_long(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+putNCv_float(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const float *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return putNCvx_schar_float(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return putNCvx_short_float(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return putNCvx_int_float(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return putNCvx_float_float(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return putNCvx_double_float(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+putNCv_double(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const double *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return putNCvx_schar_double(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return putNCvx_short_double(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return putNCvx_int_double(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return putNCvx_float_double(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return putNCvx_double_double(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+
+
+
+static int
+getNCvx_char_char(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, char *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_char_char(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+
+static int
+getNCvx_schar_schar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_schar_schar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_schar_uchar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_schar_uchar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_schar_short(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_schar_short(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_schar_int(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_schar_int(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_schar_long(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_schar_long(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_schar_float(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_schar_float(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_schar_double(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_schar_double(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+
+static int
+getNCvx_short_schar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_short_schar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_short_uchar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_short_uchar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_short_short(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_short_short(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_short_int(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_short_int(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_short_long(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_short_long(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_short_float(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_short_float(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_short_double(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_short_double(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+
+static int
+getNCvx_int_schar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_int_schar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_int_uchar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_int_uchar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_int_short(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_int_short(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_int_int(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_int_int(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_int_long(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_int_long(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_int_float(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_int_float(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_int_double(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_int_double(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+
+static int
+getNCvx_float_schar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_float_schar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_float_uchar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_float_uchar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_float_short(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_float_short(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_float_int(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_float_int(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_float_long(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_float_long(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_float_float(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_float_float(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_float_double(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_float_double(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+
+static int
+getNCvx_double_schar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, schar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_double_schar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_double_uchar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, uchar *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_double_uchar(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_double_short(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, short *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_double_short(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_double_int(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, int *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_double_int(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_double_long(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, long *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_double_long(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_double_float(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, float *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_double_float(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+static int
+getNCvx_double_double(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, double *value)
+{
+	off_t offset = NC_varoffset(ncp, varp, start);
+	size_t remaining = varp->xsz * nelems;
+	int status = NC_NOERR;
+	const void *xp;
+
+	if(nelems == 0)
+		return NC_NOERR;
+
+	assert(value != NULL);
+
+	for(;;)
+	{
+		size_t extent = MIN(remaining, ncp->chunk);
+		size_t nget = ncx_howmany(varp->type, extent);
+
+		int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
+				 0, (void **)&xp);	/* cast away const */
+		if(lstatus != NC_NOERR)
+			return lstatus;
+		
+		lstatus = ncx_getn_double_double(&xp, nget, value);
+		if(lstatus != NC_NOERR && status == NC_NOERR)
+			status = lstatus;
+
+		(void) ncp->nciop->rel(ncp->nciop, offset, 0);	
+
+		remaining -= extent;
+		if(remaining == 0)
+			break; /* normal loop exit */
+		offset += extent;
+		value += nget;
+	}
+
+	return status;
+}
+
+
+
+
+static int
+getNCv_schar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, schar *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return getNCvx_schar_schar(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return getNCvx_short_schar(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return getNCvx_int_schar(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return getNCvx_float_schar(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return getNCvx_double_schar(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+getNCv_uchar(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, uchar *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return getNCvx_schar_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return getNCvx_short_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return getNCvx_int_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return getNCvx_float_uchar(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return getNCvx_double_uchar(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+getNCv_short(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, short *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return getNCvx_schar_short(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return getNCvx_short_short(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return getNCvx_int_short(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return getNCvx_float_short(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return getNCvx_double_short(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+getNCv_int(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, int *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return getNCvx_schar_int(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return getNCvx_short_int(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return getNCvx_int_int(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return getNCvx_float_int(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return getNCvx_double_int(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+getNCv_long(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, long *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return getNCvx_schar_long(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return getNCvx_short_long(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return getNCvx_int_long(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return getNCvx_float_long(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return getNCvx_double_long(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+getNCv_float(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, float *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return getNCvx_schar_float(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return getNCvx_short_float(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return getNCvx_int_float(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return getNCvx_float_float(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return getNCvx_double_float(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+static int
+getNCv_double(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, double *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return getNCvx_schar_double(ncp, varp, start, nelems,
+			value);
+	case NC_SHORT:
+		return getNCvx_short_double(ncp, varp, start, nelems,
+			value);
+	case NC_INT:
+		return getNCvx_int_double(ncp, varp, start, nelems,
+			value);
+	case NC_FLOAT:
+		return getNCvx_float_double(ncp, varp, start, nelems,
+			value);
+	case NC_DOUBLE: 
+		return getNCvx_double_double(ncp, varp, start, nelems,
+			value);
+	}
+	return NC_EBADTYPE;
+}
+
+
+
+static int
+getNCv_text(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, char *value)
+{
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+	return getNCvx_char_char(ncp, varp, start, nelems, value);
+}
+
+
+/*
+ * Copy 'nbytes' contiguous external values
+ * from ('inncp', invp', inncoord')
+ * to   ('outncp', 'outvp', 'outcoord')
+ * 'inncp' shouldn't be the same as 'outncp'.
+ * Used only by ncvarcopy()
+ */
+static int
+NCxvarcpy(NC *inncp, NC_var *invp, size_t *incoord,
+	NC *outncp, NC_var *outvp, size_t *outcoord, size_t nbytes)
+{
+	int status;
+	off_t inoffset = NC_varoffset(inncp, invp, incoord);
+	off_t outoffset = NC_varoffset(outncp, outvp, outcoord);
+	void *inxp;
+	void *outxp;
+	const size_t chunk = MIN(inncp->chunk, outncp->chunk);
+
+	do {
+		const size_t extent = MIN(nbytes, chunk);
+
+		status = inncp->nciop->get(inncp->nciop, inoffset, extent,
+				 0, &inxp);	
+		if(status != NC_NOERR)
+			return status;
+
+		status = outncp->nciop->get(outncp->nciop, outoffset, extent,
+				 RGN_WRITE, &outxp);	
+		if(status != NC_NOERR)
+		{
+			(void) inncp->nciop->rel(inncp->nciop, inoffset, 0);	
+			break;
+		}
+
+		(void) memcpy(outxp, inxp, extent);
+
+		status = outncp->nciop->rel(outncp->nciop, outoffset,
+			 RGN_MODIFIED);
+		(void) inncp->nciop->rel(inncp->nciop, inoffset, 0);	
+
+		nbytes -= extent;
+		if(nbytes == 0)
+			break; /* normal loop exit */
+		inoffset += extent;
+		outoffset += extent;
+		
+	} while (status == NC_NOERR);
+
+	return status;
+}
+
+
+/*
+ *  For ncvar{put,get},
+ *  find the largest contiguous block from within 'edges'.
+ *  returns the index to the left of this (which may be -1).
+ *  Compute the number of contiguous elements and return
+ *  that in *iocountp.
+ *  The presence of "record" variables makes this routine
+ *  overly subtle.
+ */
+static int
+NCiocount(const NC *const ncp, const NC_var *const varp,
+	const size_t *const edges,
+	size_t *const iocountp)
+{
+	const size_t *edp0 = edges;
+	const size_t *edp = edges + varp->ndims;
+	const size_t *shp = varp->shape + varp->ndims;
+
+	if(IS_RECVAR(varp))
+	{
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only 'record' variable */
+			*iocountp = *edges;
+			return(0);
+		}
+		/* else */
+		edp0++;
+	}
+
+	assert(edges != NULL);
+
+	/* find max contiguous */
+	while(edp > edp0)
+	{
+		shp--; edp--;
+		if(*edp < *shp )
+		{
+			const size_t *zedp = edp;
+			while(zedp >= edp0)
+			{
+				if(*zedp == 0)
+				{
+					*iocountp = 0;
+					goto done;
+				}
+				/* Tip of the hat to segmented architectures */
+				if(zedp == edp0)
+					break;
+				zedp--;
+			}
+			break;
+		}
+		assert(*edp == *shp);
+	}
+
+	/*
+	 * edp, shp reference rightmost index s.t. *(edp +1) == *(shp +1)
+	 *
+	 * Or there is only one dimension.
+	 * If there is only one dimension and it is 'non record' dimension,
+	 * 	edp is &edges[0] and we will return -1.
+	 * If there is only one dimension and and it is a "record dimension",
+	 *	edp is &edges[1] (out of bounds) and we will return 0;
+	 */
+	assert(shp >= varp->shape + varp->ndims -1 
+		|| *(edp +1) == *(shp +1));
+
+	/* now accumulate max count for a single io operation */
+	for(*iocountp = 1, edp0 = edp;
+		 	edp0 < edges + varp->ndims;
+			edp0++)
+	{
+		*iocountp *= *edp0;
+	}
+
+done:
+	return((int)(edp - edges) - 1);
+}
+
+
+/*
+ * Set the elements of the array 'upp' to
+ * the sum of the corresponding elements of
+ * 'stp' and 'edp'. 'end' should be &stp[nelems].
+ */
+static void
+set_upper(size_t *upp, /* modified on return */
+	const size_t *stp,
+	const size_t *edp,
+	const size_t *const end)
+{
+	while(upp < end) {
+		*upp++ = *stp++ + *edp++;
+	}
+}
+
+
+/*
+ * The infamous and oft-discussed odometer code.
+ *
+ * 'start[]' is the starting coordinate.
+ * 'upper[]' is the upper bound s.t. start[ii] < upper[ii].
+ * 'coord[]' is the register, the current coordinate value.
+ * For some ii,
+ * upp == &upper[ii]
+ * cdp == &coord[ii]
+ * 
+ * Running this routine increments *cdp.
+ *
+ * If after the increment, *cdp is equal to *upp
+ * (and cdp is not the leftmost dimension),
+ * *cdp is "zeroed" to the starting value and
+ * we need to "carry", eg, increment one place to
+ * the left.
+ * 
+ * TODO: Some architectures hate recursion?
+ * 	Reimplement non-recursively.
+ */
+static void
+odo1(const size_t *const start, const size_t *const upper,
+	size_t *const coord, /* modified on return */
+	const size_t *upp,
+	size_t *cdp)
+{
+	assert(coord <= cdp && cdp <= coord + NC_MAX_DIMS);
+	assert(upper <= upp && upp <= upper + NC_MAX_DIMS);
+	assert(upp - upper == cdp - coord);
+	
+	assert(*cdp <= *upp);
+
+	(*cdp)++;
+	if(cdp != coord && *cdp >= *upp)
+	{
+		*cdp = start[cdp - coord];
+		odo1(start, upper, coord, upp -1, cdp -1);
+	}
+}
+#ifdef _CRAYC
+#pragma _CRI noinline odo1
+#endif
+
+
+
+
+/* Public */
+
+#ifdef USE_MPIO /* function added by Jianwei Li */
+
+/*
+ *  This is how much space is required by the user, as in
+ *
+ *   vals = malloc(nel * nctypelen(var.type));
+ *   ncvarget(cdfid, varid, cor, edg, vals);
+ */
+int
+nctypelen(nc_type type)
+{
+        switch(type){
+        case NC_BYTE :
+        case NC_CHAR :
+                return((int)sizeof(char));
+        case NC_SHORT :
+                return(int)(sizeof(short));
+        case NC_INT :
+                return((int)sizeof(int));
+        case NC_FLOAT :
+                return((int)sizeof(float));
+        case NC_DOUBLE :
+                return((int)sizeof(double));
+        }
+
+        return -1;
+}
+
+#else /* interface below removed by Jianwei Li */
+
+int
+nc_put_var1_text(int ncid, int varid, const size_t *coord,
+	const char *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_text(ncp, varp, coord, 1, value);
+}
+
+
+int
+nc_put_var1_uchar(int ncid, int varid, const size_t *coord,
+	const uchar *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_uchar(ncp, varp, coord, 1, value);
+}
+
+int
+nc_put_var1_schar(int ncid, int varid, const size_t *coord,
+	const schar *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_schar(ncp, varp, coord, 1, value);
+}
+
+int
+nc_put_var1_short(int ncid, int varid, const size_t *coord,
+	const short *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_short(ncp, varp, coord, 1, value);
+}
+
+int
+nc_put_var1_int(int ncid, int varid, const size_t *coord,
+	const int *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_int(ncp, varp, coord, 1, value);
+}
+
+int
+nc_put_var1_long(int ncid, int varid, const size_t *coord,
+	const long *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_long(ncp, varp, coord, 1, value);
+}
+
+int
+nc_put_var1_float(int ncid, int varid, const size_t *coord,
+	const float *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_float(ncp, varp, coord, 1, value);
+}
+
+int
+nc_put_var1_double(int ncid, int varid, const size_t *coord,
+	const double *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *coord +1);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return putNCv_double(ncp, varp, coord, 1, value);
+}
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_put_var1(int ncid, int varid, const size_t *coord, const void *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR;
+
+	switch(varp->type){
+	case NC_CHAR:
+		return nc_put_var1_text(ncid, varid, coord,
+			(const char *) value);
+	case NC_BYTE:
+		return nc_put_var1_schar(ncid, varid, coord,
+			(const schar *) value);
+	case NC_SHORT:
+		return nc_put_var1_short(ncid, varid, coord,
+			(const short *) value);
+	case NC_INT:
+		return nc_put_var1_int(ncid, varid, coord,
+			(const int *) value);
+	case NC_FLOAT:
+		return nc_put_var1_float(ncid, varid, coord,
+			(const float *) value);
+	case NC_DOUBLE: 
+		return nc_put_var1_double(ncid, varid, coord,
+			(const double *) value);
+	}
+	return NC_EBADTYPE;
+}
+
+int
+nc_get_var1_text(int ncid, int varid, const size_t *coord, char *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_text(ncp, varp, coord, 1, value);
+}
+
+
+int
+nc_get_var1_uchar(int ncid, int varid, const size_t *coord, uchar *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_uchar(ncp, varp, coord, 1, value);
+}
+
+int
+nc_get_var1_schar(int ncid, int varid, const size_t *coord, schar *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_schar(ncp, varp, coord, 1, value);
+}
+
+int
+nc_get_var1_short(int ncid, int varid, const size_t *coord, short *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_short(ncp, varp, coord, 1, value);
+}
+
+int
+nc_get_var1_int(int ncid, int varid, const size_t *coord, int *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_int(ncp, varp, coord, 1, value);
+}
+
+int
+nc_get_var1_long(int ncid, int varid, const size_t *coord, long *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_long(ncp, varp, coord, 1, value);
+}
+
+int
+nc_get_var1_float(int ncid, int varid, const size_t *coord, float *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_float(ncp, varp, coord, 1, value);
+}
+
+int
+nc_get_var1_double(int ncid, int varid, const size_t *coord, double *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, coord);
+	if(status != NC_NOERR)
+		return status;
+
+	return getNCv_double(ncp, varp, coord, 1, value);
+}
+
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_get_var1(int ncid, int varid, const size_t *coord, void *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR;
+
+	switch(varp->type){
+	case NC_CHAR:
+		return nc_get_var1_text(ncid, varid, coord,
+			(char *) value);
+	case NC_BYTE:
+		return nc_get_var1_schar(ncid, varid, coord,
+			(schar *) value);
+	case NC_SHORT:
+		return nc_get_var1_short(ncid, varid, coord,
+			(short *) value);
+	case NC_INT:
+		return nc_get_var1_int(ncid, varid, coord,
+			(int *) value);
+	case NC_FLOAT:
+		return nc_get_var1_float(ncid, varid, coord,
+			(float *) value);
+	case NC_DOUBLE: 
+		return nc_get_var1_double(ncid, varid, coord,
+			(double *) value);
+	}
+	return NC_EBADTYPE;
+}
+
+
+
+int
+nc_put_vara_text(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const char *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_text(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_text(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_text(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_text(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+
+int
+nc_put_vara_uchar(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const uchar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_uchar(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_uchar(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_uchar(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_uchar(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_put_vara_schar(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const schar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_schar(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_schar(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_schar(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_schar(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_put_vara_short(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const short *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_short(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_short(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_short(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_short(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_put_vara_int(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const int *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_int(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_int(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_int(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_int(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_put_vara_long(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const long *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_long(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_long(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_long(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_long(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_put_vara_float(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const float *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_float(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_float(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_float(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_float(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_put_vara_double(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const double *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( putNCv_double(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		status = NCvnrecs(ncp, *start + *edges);
+		if(status != NC_NOERR)
+			return status;
+
+		if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( putNCv_double(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( putNCv_double(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = putNCv_double(ncp, varp, coord, iocount,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_put_vara(int ncid, int varid,
+	 const size_t *start, const size_t *edges, const void *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	switch(varp->type){
+	case NC_CHAR:
+		return nc_put_vara_text(ncid, varid, start, edges,
+			(const char *) value);
+	case NC_BYTE:
+		return nc_put_vara_schar(ncid, varid, start, edges,
+			(const schar *) value);
+	case NC_SHORT:
+		return nc_put_vara_short(ncid, varid, start, edges,
+			(const short *) value);
+	case NC_INT:
+		return nc_put_vara_int(ncid, varid, start, edges,
+			(const int *) value);
+	case NC_FLOAT:
+		return nc_put_vara_float(ncid, varid, start, edges,
+			(const float *) value);
+	case NC_DOUBLE: 
+		return nc_put_vara_double(ncid, varid, start, edges,
+			(const double *) value);
+	}
+	return NC_EBADTYPE;
+}
+
+int
+nc_get_vara_text(int ncid, int varid,
+	 const size_t *start, const size_t *edges, char *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_text(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_text(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_text(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_text(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+
+int
+nc_get_vara_uchar(int ncid, int varid,
+	 const size_t *start, const size_t *edges, uchar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_uchar(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_uchar(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_uchar(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_uchar(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_get_vara_schar(int ncid, int varid,
+	 const size_t *start, const size_t *edges, schar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_schar(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_schar(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_schar(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_schar(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_get_vara_short(int ncid, int varid,
+	 const size_t *start, const size_t *edges, short *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_short(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_short(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_short(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_short(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_get_vara_int(int ncid, int varid,
+	 const size_t *start, const size_t *edges, int *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_int(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_int(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_int(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_int(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_get_vara_long(int ncid, int varid,
+	 const size_t *start, const size_t *edges, long *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_long(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_long(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_long(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_long(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_get_vara_float(int ncid, int varid,
+	 const size_t *start, const size_t *edges, float *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_float(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_float(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_float(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_float(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+int
+nc_get_vara_double(int ncid, int varid,
+	 const size_t *start, const size_t *edges, double *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+	int ii;
+	size_t iocount;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	status = NCcoordck(ncp, varp, start);
+	if(status != NC_NOERR)
+		return status;
+	status = NCedgeck(ncp, varp, start, edges);
+	if(status != NC_NOERR)
+		return status;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		return( getNCv_double(ncp, varp, start, 1, value) );
+	}
+
+	if(IS_RECVAR(varp))
+	{
+		if(*start + *edges > NC_get_numrecs(ncp))
+			return NC_EEDGE;
+		if(varp->ndims == 1 && ncp->recsize <= varp->len)
+		{
+			/* one dimensional && the only record variable  */
+			return( getNCv_double(ncp, varp, start, *edges, value) );
+		}
+	}
+
+	/*
+	 * find max contiguous
+	 *   and accumulate max count for a single io operation
+	 */
+	ii = NCiocount(ncp, varp, edges, &iocount);
+
+	if(ii == -1)
+	{
+		return( getNCv_double(ncp, varp, start, iocount, value) );
+	}
+
+	assert(ii >= 0);
+
+
+	{ /* inline */
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	ALLOC_ONSTACK(upper, size_t, varp->ndims);
+	const size_t index = ii;
+
+	/* copy in starting indices */
+	(void) memcpy(coord, start, varp->ndims * sizeof(size_t));
+
+	/* set up in maximum indices */
+	set_upper(upper, start, edges, &upper[varp->ndims]);
+
+	/* ripple counter */
+	while(*coord < *upper)
+	{
+		const int lstatus = getNCv_double(ncp, varp, coord, iocount,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += iocount;
+		odo1(start, upper, coord, &upper[index], &coord[index]);
+	}
+
+	FREE_ONSTACK(upper);
+	FREE_ONSTACK(coord);
+	} /* end inline */
+
+	return status;
+}
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_get_vara(int ncid, int varid,
+	 const size_t *start, const size_t *edges, void *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	switch(varp->type){
+	case NC_CHAR:
+		return nc_get_vara_text(ncid, varid, start, edges,
+			(char *) value);
+	case NC_BYTE:
+		return nc_get_vara_schar(ncid, varid, start, edges,
+			(schar *) value);
+	case NC_SHORT:
+		return nc_get_vara_short(ncid, varid, start, edges,
+			(short *) value);
+	case NC_INT:
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+		return nc_get_vara_int(ncid, varid, start, edges,
+			(int *) value);
+#elif SIZEOF_LONG == X_SIZEOF_INT
+		return nc_get_vara_long(ncid, varid, start, edges,
+			(long *) value);
+#else
+#error "nc_get_vara implementation"
+#endif
+	case NC_FLOAT:
+		return nc_get_vara_float(ncid, varid, start, edges,
+			(float *) value);
+	case NC_DOUBLE: 
+		return nc_get_vara_double(ncid, varid, start, edges,
+			(double *) value);
+	}
+	return NC_EBADTYPE;
+}
+
+#if defined(__cplusplus)
+/* C++ consts default to internal linkage and must be initialized */
+const size_t coord_zero[NC_MAX_VAR_DIMS] = {0};
+#else
+static const size_t coord_zero[NC_MAX_VAR_DIMS];
+#endif
+
+int
+nc_put_var_text(int ncid, int varid, const char *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_text(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_text(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_text(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_text(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+
+int
+nc_put_var_uchar(int ncid, int varid, const uchar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_uchar(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_uchar(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_uchar(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_uchar(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_put_var_schar(int ncid, int varid, const schar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_schar(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_schar(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_schar(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_schar(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_put_var_short(int ncid, int varid, const short *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_short(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_short(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_short(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_short(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_put_var_int(int ncid, int varid, const int *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_int(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_int(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_int(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_int(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_put_var_long(int ncid, int varid, const long *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_long(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_long(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_long(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_long(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_put_var_float(int ncid, int varid, const float *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_float(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_float(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_float(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_float(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_put_var_double(int ncid, int varid, const double *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( putNCv_double(ncp, varp, &zed, 1, value) );
+	}
+
+	if(!IS_RECVAR(varp))
+	{
+		return(putNCv_double(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(putNCv_double(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = putNCv_double(ncp, varp, coord, elemsPerRec,
+				 value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+
+
+
+int
+nc_get_var_text(int ncid, int varid, char *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_text(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_text(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_text(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_text(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+
+int
+nc_get_var_uchar(int ncid, int varid, uchar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_uchar(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_uchar(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_uchar(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_uchar(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_get_var_schar(int ncid, int varid, schar *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_schar(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_schar(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_schar(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_schar(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_get_var_short(int ncid, int varid, short *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_short(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_short(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_short(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_short(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_get_var_int(int ncid, int varid, int *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_int(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_int(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_int(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_int(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_get_var_long(int ncid, int varid, long *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_long(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_long(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_long(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_long(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_get_var_float(int ncid, int varid, float *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_float(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_float(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_float(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_float(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+int
+nc_get_var_double(int ncid, int varid, double *value)
+{
+	int status = NC_NOERR;
+	NC *ncp;
+	const NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+		return NC_EINDEFINE;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
+
+	if(varp->ndims == 0) /* scalar variable */
+	{
+		const size_t zed = 0;
+		return( getNCv_double(ncp, varp, &zed, 1, value) );
+	}
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+
+	if(!IS_RECVAR(varp))
+	{
+		return(getNCv_double(ncp, varp, coord_zero, *varp->dsizes, value));
+	}
+	/* else */
+
+	if(varp->ndims == 1
+			&& ncp->recsize <= varp->len)
+	{
+		/* one dimensional && the only record variable  */
+		return(getNCv_double(ncp, varp, coord_zero, NC_get_numrecs(ncp),
+			value));
+	}
+	/* else */
+
+	{
+	ALLOC_ONSTACK(coord, size_t, varp->ndims);
+	size_t elemsPerRec = 1;
+	const size_t nrecs = NC_get_numrecs(ncp);
+	(void) memset(coord, 0, varp->ndims * sizeof(size_t));
+	/* TODO: fix dsizes to avoid this nonsense */
+	if(varp->ndims > 1)
+		elemsPerRec = varp->dsizes[1];
+	while(*coord < nrecs)
+	{
+		const int lstatus = getNCv_double(ncp, varp, coord, elemsPerRec,
+				value);
+		if(lstatus != NC_NOERR)
+		{
+			if(lstatus != NC_ERANGE)
+			{
+				status = lstatus;
+				/* fatal for the loop */
+				break;
+			}
+			/* else NC_ERANGE, not fatal for the loop */
+			if(status == NC_NOERR)
+				status = lstatus;
+		}
+		value += elemsPerRec;
+		(*coord)++;
+	}
+	FREE_ONSTACK(coord);
+	} /* elemsPerRec */
+
+	return status;
+}
+
+
+
+/* Begin putgetg.c */
+
+
+
+int
+nc_get_vars_text (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	char *value)
+{
+	return nc_get_varm_text (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+
+int
+nc_get_vars_uchar (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	uchar *value)
+{
+	return nc_get_varm_uchar (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_get_vars_schar (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	schar *value)
+{
+	return nc_get_varm_schar (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_get_vars_short (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	short *value)
+{
+	return nc_get_varm_short (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_get_vars_int (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	int *value)
+{
+	return nc_get_varm_int (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_get_vars_long (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	long *value)
+{
+	return nc_get_varm_long (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_get_vars_float (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	float *value)
+{
+	return nc_get_varm_float (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_get_vars_double (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	double *value)
+{
+	return nc_get_varm_double (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+
+int
+nc_get_vars (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	void *value)
+{
+	return nc_get_varm (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+
+
+int
+nc_put_vars_text (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const char *value)
+{
+	return nc_put_varm_text (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+
+int
+nc_put_vars_uchar (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const uchar *value)
+{
+	return nc_put_varm_uchar (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_put_vars_schar (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const schar *value)
+{
+	return nc_put_varm_schar (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_put_vars_short (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const short *value)
+{
+	return nc_put_varm_short (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_put_vars_int (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const int *value)
+{
+	return nc_put_varm_int (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_put_vars_long (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const long *value)
+{
+	return nc_put_varm_long (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_put_vars_float (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const float *value)
+{
+	return nc_put_varm_float (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+int
+nc_put_vars_double (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const double *value)
+{
+	return nc_put_varm_double (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+
+int
+nc_put_vars (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const void *value)
+{
+	return nc_put_varm (ncid, varid, start, edges,
+			 stride, 0, value);
+}
+
+
+/*
+ * Generalized hyperslab input.
+ */
+
+int
+nc_get_varm_text(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	char *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_text (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_text()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_text (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+
+int
+nc_get_varm_uchar(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	uchar *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_uchar (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_uchar()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_uchar (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_get_varm_schar(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	schar *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_schar (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_schar()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_schar (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_get_varm_short(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	short *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_short (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_short()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_short (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_get_varm_int(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	int *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_int (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_int()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_int (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_get_varm_long(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	long *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_long (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_long()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_long (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_get_varm_float(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	float *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_float (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_float()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_float (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_get_varm_double(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride,
+	const ptrdiff_t *map,
+	double *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return getNCv_double (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			size_t dimlen = 
+				idim == 0 && IS_RECVAR (varp)
+					? NC_get_numrecs(ncp)
+					  : varp->shape[idim];
+			if (mystart[idim] >= dimlen)
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+
+			if (mystart[idim] + myedges[idim] > dimlen)
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_get_vara_double()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_get_vara_double (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_get_varm (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const ptrdiff_t * map,
+	void *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+	ptrdiff_t *cvtmap = NULL;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR;
+
+	if(map != NULL && varp->ndims != 0)
+	{
+		/*
+		 * convert map units from bytes to units of sizeof(type)
+		 */
+		size_t ii;
+		const ptrdiff_t szof = (ptrdiff_t) nctypelen(varp->type);
+		cvtmap = (ptrdiff_t *)calloc(varp->ndims, sizeof(ptrdiff_t));
+		if(cvtmap == NULL)
+			return NC_ENOMEM;
+		for(ii = 0; ii < varp->ndims; ii++)
+		{
+			if(map[ii] % szof != 0)	
+			{
+				free(cvtmap);
+				return NC_EINVAL;
+			}
+			cvtmap[ii] = map[ii] / szof;
+		}
+		map = cvtmap;
+	}
+
+	switch(varp->type){
+	case NC_CHAR:
+		status =  nc_get_varm_text(ncid, varid, start, edges,
+			stride, map,
+			(char *) value);
+		break;
+	case NC_BYTE:
+		status = nc_get_varm_schar(ncid, varid, start, edges,
+			stride, map,
+			(schar *) value);
+		break;
+	case NC_SHORT:
+		status = nc_get_varm_short(ncid, varid, start, edges,
+			stride, map,
+			(short *) value);
+		break;
+	case NC_INT:
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+		status = nc_get_varm_int(ncid, varid, start, edges,
+			stride, map,
+			(int *) value);
+#elif SIZEOF_LONG == X_SIZEOF_INT
+		status = nc_get_varm_long(ncid, varid, start, edges,
+			stride, map,
+			(long *) value);
+#else
+#error "nc_get_varm implementation"
+#endif
+		break;
+	case NC_FLOAT:
+		status = nc_get_varm_float(ncid, varid, start, edges,
+			stride, map,
+			(float *) value);
+		break;
+	case NC_DOUBLE: 
+		status = nc_get_varm_double(ncid, varid, start, edges,
+			stride, map,
+			(double *) value);
+		break;
+	default:
+		status = NC_EBADTYPE;
+		break;
+	}
+
+	if(cvtmap != NULL)
+	{
+		free(cvtmap);
+	}
+	return status;
+}
+
+/*
+ * Generalized hyperslab output.
+ */
+
+int
+nc_put_varm_text(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const char *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_text (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_text()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_text (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+
+int
+nc_put_varm_uchar(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const uchar *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_uchar (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_uchar()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_uchar (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_put_varm_schar(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const schar *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_schar (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_schar()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_schar (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_put_varm_short(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const short *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_short (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_short()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_short (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_put_varm_int(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const int *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_int (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_int()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_int (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_put_varm_long(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const long *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_long (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_long()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_long (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_put_varm_float(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const float *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_float (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_float()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_float (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+int
+nc_put_varm_double(int ncid, int varid,
+	const size_t *start, const size_t *edges,
+	const ptrdiff_t *stride, const ptrdiff_t *map,
+	const double *value)
+{
+	int status = ENOERR;
+	NC *ncp;
+	NC_var *varp;
+	int maxidim;	/* maximum dimensional index */
+
+	status = NC_check_id (ncid, &ncp);
+	if (status != NC_NOERR)
+		return status;
+
+	if (NC_indef (ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+		if (NC_readonly (ncp))
+			return NC_EPERM;
+	varp = NC_lookupvar (ncp, varid);
+	if (varp == NULL)
+		return NC_ENOTVAR;
+
+	if(varp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	maxidim = (int) varp->ndims - 1;
+
+	if (maxidim < 0)
+	{
+		/*
+		 * The variable is a scalar; consequently,
+		 * there s only one thing to get and only one place to put it.
+		 * (Why was I called?)
+		 */
+		return putNCv_double (ncp, varp, start, 1, value);
+	}
+	
+	/*
+	 * else
+	 * The variable is an array.
+	 */
+	{
+		int idim;
+		size_t *mystart = NULL;
+		size_t *myedges;
+		size_t *iocount;	/* count vector */
+		size_t *stop;	/* stop indexes */
+		size_t *length;	/* edge lengths in bytes */
+		ptrdiff_t *mystride;
+		ptrdiff_t *mymap;
+
+		/*
+		 * Verify stride argument.
+		 */
+		for (idim = 0; idim <= maxidim; ++idim)
+		{
+			if (stride != NULL
+				&& (stride[idim] == 0
+		/* cast needed for braindead systems with signed size_t */
+				|| (unsigned long) stride[idim] >= X_INT_MAX))
+			{
+				return NC_ESTRIDE;
+			}
+		}
+
+		/* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
+		mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
+		if(mystart == NULL)
+			return NC_ENOMEM;
+		myedges = mystart + varp->ndims;
+		iocount = myedges + varp->ndims;
+		stop = iocount + varp->ndims;
+		length = stop + varp->ndims;
+		mystride = (ptrdiff_t *)(length + varp->ndims);
+		mymap = mystride + varp->ndims;
+
+		/*
+		 * Initialize I/O parameters.
+		 */
+		for (idim = maxidim; idim >= 0; --idim)
+		{
+			mystart[idim] = start != NULL
+				? start[idim]
+				: 0;
+
+			if (edges[idim] == 0)
+			{
+				status = NC_NOERR;	/* read/write no data */
+				goto done;
+			}
+
+			myedges[idim] = edges != NULL
+				? edges[idim]
+				: idim == 0 && IS_RECVAR (varp)
+				? NC_get_numrecs(ncp) - mystart[idim]
+				: varp->shape[idim] - mystart[idim];
+			mystride[idim] = stride != NULL
+				? stride[idim]
+				: 1;
+			mymap[idim] = map != NULL
+				? map[idim]
+				: idim == maxidim
+				? 1
+				: mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
+
+			iocount[idim] = 1;
+			length[idim] = mymap[idim] * myedges[idim];
+			stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
+		}
+
+		/*
+		 * Check start, edges
+		 */
+		for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
+		{
+			if (mystart[idim] >= varp->shape[idim])
+			{
+				status = NC_EINVALCOORDS;
+				goto done;
+			}
+			if (mystart[idim] + myedges[idim] > varp->shape[idim])
+			{
+				status = NC_EEDGE;
+				goto done;
+			}
+		}
+		/*
+		 * As an optimization, adjust I/O parameters when the fastest 
+		 * dimension has unity stride both externally and internally.
+		 * In this case, the user could have called a simpler routine
+		 * (i.e. ncvarnc_put_vara_double()
+		 */
+		if (mystride[maxidim] == 1
+			&& mymap[maxidim] == 1)
+		{
+			iocount[maxidim] = myedges[maxidim];
+			mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
+			mymap[maxidim] = (ptrdiff_t) length[maxidim];
+		}
+
+		/*
+		 * Perform I/O.  Exit when done.
+		 */
+		for (;;)
+		{
+			/* TODO: */
+			int lstatus = nc_put_vara_double (ncid, varid, mystart, iocount,
+						value);
+			if (lstatus != NC_NOERR 
+				&& (status == NC_NOERR || lstatus != NC_ERANGE))
+				status = lstatus;
+
+			/*
+			 * The following code permutes through the variable s
+			 * external start-index space and it s internal address
+			 * space.  At the UPC, this algorithm is commonly
+			 * called "odometer code".
+			 */
+			idim = maxidim;
+		carry:
+			value += mymap[idim];
+			mystart[idim] += mystride[idim];
+			if (mystart[idim] == stop[idim])
+			{
+				mystart[idim] = start[idim];
+				value -= length[idim];
+				if (--idim < 0)
+					break; /* normal return */
+				goto carry;
+			}
+		} /* I/O loop */
+	done:
+		free(mystart);
+	} /* variable is array */
+	return status;
+
+}
+
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_put_varm (
+	int ncid,
+	int varid,
+	const size_t * start,
+	const size_t * edges,
+	const ptrdiff_t * stride,
+	const ptrdiff_t * map,
+	const void *value)
+{
+	int status;
+	NC *ncp;
+	const NC_var *varp;
+	ptrdiff_t *cvtmap = NULL;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+		return NC_ENOTVAR;
+
+	if(map != NULL && varp->ndims != 0)
+	{
+		/*
+		 * convert map units from bytes to units of sizeof(type)
+		 */
+		size_t ii;
+		const ptrdiff_t szof = (ptrdiff_t) nctypelen(varp->type);
+		cvtmap = (ptrdiff_t *)calloc(varp->ndims, sizeof(ptrdiff_t));
+		if(cvtmap == NULL)
+			return NC_ENOMEM;
+		for(ii = 0; ii < varp->ndims; ii++)
+		{
+			if(map[ii] % szof != 0)	
+			{
+				free(cvtmap);
+				return NC_EINVAL;
+			}
+			cvtmap[ii] = map[ii] / szof;
+		}
+		map = cvtmap;
+	}
+
+	switch(varp->type){
+	case NC_CHAR:
+		status =  nc_put_varm_text(ncid, varid, start, edges,
+			stride, map,
+			(const char *) value);
+		break;
+	case NC_BYTE:
+		status = nc_put_varm_schar(ncid, varid, start, edges,
+			stride, map,
+			(const schar *) value);
+		break;
+	case NC_SHORT:
+		status = nc_put_varm_short(ncid, varid, start, edges,
+			stride, map,
+			(const short *) value);
+		break;
+	case NC_INT:
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+		status = nc_put_varm_int(ncid, varid, start, edges,
+			stride, map,
+			(const int *) value);
+#elif SIZEOF_LONG == X_SIZEOF_INT
+		status = nc_put_varm_long(ncid, varid, start, edges,
+			stride, map,
+			(const long *) value);
+#else
+#error "nc_put_varm implementation"
+#endif
+		break;
+	case NC_FLOAT:
+		status = nc_put_varm_float(ncid, varid, start, edges,
+			stride, map,
+			(const float *) value);
+		break;
+	case NC_DOUBLE: 
+		status = nc_put_varm_double(ncid, varid, start, edges,
+			stride, map,
+			(const double *) value);
+		break;
+	default:
+		status = NC_EBADTYPE;
+		break;
+	}
+
+	if(cvtmap != NULL)
+	{
+		free(cvtmap);
+	}
+	return status;
+}
+
+#endif /* USE_MPIO */
+
+/* Begin recio, deprecated */
+
+/*
+ * input 'nelems' items of contiguous data of 'varp' at 'start'
+ * N.B. this function deprecated.
+ */
+static int
+getNCvdata(const NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, void *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return getNCvx_char_char(ncp, varp, start, nelems,
+			(char *) value);
+	case NC_BYTE:
+		return getNCvx_schar_schar(ncp, varp, start, nelems,
+			(schar *) value);
+	case NC_SHORT:
+		return getNCvx_short_short(ncp, varp, start, nelems,
+			(short *) value);
+	case NC_INT:
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+		return getNCvx_int_int(ncp, varp, start, nelems,
+			(int *) value);
+#elif SIZEOF_LONG == X_SIZEOF_INT
+		return getNCvx_int_long(ncp, varp, start, nelems,
+			(long *) value);
+#else
+#error "getNCvdata implementation"
+#endif
+	case NC_FLOAT:
+		return getNCvx_float_float(ncp, varp, start, nelems,
+			(float *) value);
+	case NC_DOUBLE: 
+		return getNCvx_double_double(ncp, varp, start, nelems,
+			(double *) value);
+	}
+	return NC_EBADTYPE;
+}
+
+
+/*
+ * output 'nelems' items of contiguous data of 'varp' at 'start'
+ * N.B. this function deprecated.
+ */
+static int
+putNCvdata(NC *ncp, const NC_var *varp,
+		 const size_t *start, size_t nelems, const void *value)
+{
+	switch(varp->type){
+	case NC_CHAR:
+		return putNCvx_char_char(ncp, varp, start, nelems,
+			(const char *) value);
+	case NC_BYTE:
+		return putNCvx_schar_schar(ncp, varp, start, nelems,
+			(const schar *) value);
+	case NC_SHORT:
+		return putNCvx_short_short(ncp, varp, start, nelems,
+			(const short *) value);
+	case NC_INT:
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+		return putNCvx_int_int(ncp, varp, start, nelems,
+			(const int *) value);
+#elif SIZEOF_LONG == X_SIZEOF_INT
+		return putNCvx_long_int(ncp, varp, start, nelems,
+			(const long *) value);
+#else
+#error "putNCvdata implementation"
+#endif
+	case NC_FLOAT:
+		return putNCvx_float_float(ncp, varp, start, nelems,
+			(const float *) value);
+	case NC_DOUBLE: 
+		return putNCvx_double_double(ncp, varp, start, nelems,
+			(const double *) value);
+	}
+	return NC_EBADTYPE;
+}
+
+
+static size_t
+NCelemsPerRec(
+	const NC_var *varp)
+{
+	size_t nelems = 1;
+	size_t jj;
+	for(jj = 1; jj < varp->ndims; jj++)	
+		nelems *= varp->shape[jj];
+	return nelems;
+}
+
+
+/*
+ * Retrieves the number of record variables, the record variable ids, and the
+ * record size of each record variable.  If any pointer to info to be returned
+ * is null, the associated information is not returned.  Returns -1 on error.
+ */
+int
+nc_inq_rec(
+	int ncid,
+	size_t *nrecvars,
+	int *recvarids,
+	size_t *recsizes)
+{
+	NC *ncp;
+
+   {
+	const int status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+   }
+
+   {
+	size_t nrvars = 0;
+	size_t ii = 0;
+	for(; ii < ncp->vars.nelems; ii++)
+	{
+		const NC_var *const varp = ncp->vars.value[ii];
+		if(!IS_RECVAR(varp))
+			continue;
+
+		if(recvarids != NULL)
+			recvarids[nrvars] = (int) ii;
+		if(recsizes != NULL)
+		{
+			*recsizes++ = nctypelen(varp->type)
+				 * NCelemsPerRec(varp);
+		}
+		nrvars++;
+	}
+
+	if(nrecvars != NULL)
+		*nrecvars = nrvars;
+    }
+
+	return NC_NOERR;
+}
+
+
+static int
+NCrecput(
+	NC *ncp,
+	size_t recnum,
+	void *const *datap)
+{
+	int status = NC_NOERR;
+	size_t nrvars = 0;
+	NC_var *varp;
+	size_t ii;
+	size_t iocount;
+	ALLOC_ONSTACK(coord, size_t, ncp->dims.nelems);
+
+	assert(ncp->dims.nelems != 0);
+
+	(void) memset(coord, 0, ncp->dims.nelems * sizeof(size_t));
+	coord[0] = recnum;
+	for(ii = 0; ii < ncp->vars.nelems; ii++)
+	{
+		varp = ncp->vars.value[ii];
+		if(!IS_RECVAR(varp))
+			continue;
+		/* else */
+		nrvars++;
+		if(*datap == NULL)
+		{
+			datap++;
+			continue;
+		}
+		/* else */
+		iocount = NCelemsPerRec(varp);
+		status = putNCvdata(ncp, varp, coord, iocount, *datap++);
+		if(status != NC_NOERR)
+			break;
+	}
+	if(nrvars == 0 && status == NC_NOERR)
+	{
+		status = NC_ENORECVARS;
+	}
+		
+	FREE_ONSTACK(coord);
+	return status;
+}
+
+
+static int
+NCrecget(
+	NC *ncp,
+	size_t recnum,
+	void **datap)
+{
+	int status = NC_NOERR;
+	size_t nrvars = 0;
+	NC_var *varp;
+	size_t ii;
+	size_t iocount;
+	ALLOC_ONSTACK(coord, size_t, ncp->dims.nelems);
+
+	assert(ncp->dims.nelems != 0);
+
+	(void) memset(coord, 0, ncp->dims.nelems * sizeof(size_t));
+	coord[0] = recnum;
+	for(ii = 0; ii < ncp->vars.nelems; ii++)
+	{
+		varp = ncp->vars.value[ii];
+		if(!IS_RECVAR(varp))
+			continue;
+		/* else */
+		nrvars++;
+		if(*datap == NULL)
+		{
+			datap++;
+			continue;
+		}
+		/* else */
+		iocount = NCelemsPerRec(varp);
+		status = getNCvdata(ncp, varp, coord, iocount, *datap++);
+		if(status != NC_NOERR)
+			break;
+	}
+	if(nrvars == 0 && status == NC_NOERR)
+	{
+		status = NC_ENORECVARS;
+	}
+
+	FREE_ONSTACK(coord);
+	return status;
+}
+
+
+/*
+ * Write one record's worth of data, except don't write to variables for which
+ * the address of the data to be written is null.  Return -1 on error.
+ */
+int
+nc_put_rec(
+	int ncid,
+	size_t recnum,
+	void * const *datap)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+	{
+		return NC_EPERM;
+	}
+
+	if(NC_indef(ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	status = NCvnrecs(ncp, recnum +1);
+	if(status != NC_NOERR)
+		return status;
+
+	return( NCrecput(ncp, recnum, datap) );
+}
+
+
+/*
+ * Read one record's worth of data, except don't read from variables for which
+ * the address of the data to be read is null.  Return -1 on error;
+ */
+int
+nc_get_rec(
+	int ncid,
+	size_t recnum,
+	void **datap)
+{
+	int status;
+	NC *ncp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_indef(ncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	if(recnum >= NC_get_numrecs(ncp))
+	{
+		return NC_EINVALCOORDS;
+	}
+
+	return( NCrecget(ncp, recnum, datap) );
+}
+
+
+/*
+ * Copy the values of a variable from an input netCDF to an output netCDF.
+ * Input and output var assummed to have the same shape.
+ * return -1 on error.
+ */
+int
+nc_copy_var(int ncid_in, int varid, int ncid_out)
+{
+	int status = NC_NOERR;
+	NC *inncp, *outncp;
+	NC_var *invp, *outvp;
+
+	status = NC_check_id(ncid_in, &inncp); 
+	if(status != NC_NOERR)
+		return status;
+
+
+	if(NC_indef(inncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	status = NC_check_id(ncid_out, &outncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(outncp))
+	{
+		/* output file isn't writable */
+		return NC_EPERM;
+	}
+
+	if(NC_indef(outncp))
+	{
+		return NC_EINDEFINE;
+	}
+
+	/* find the variable in the input cdf */
+	invp = NC_lookupvar(inncp, varid);
+	if(invp == NULL)
+	{
+		return NC_ENOTVAR;
+	}
+
+	/* find the variable in the output cdf */
+	if(NC_findvar(&outncp->vars, invp->name->cp, &outvp) == -1)
+	{
+		return NC_ENOTVAR;
+	}
+
+	/* can we even attempt to copy without conversion? */
+	if(outvp->type != invp->type)
+	{
+		return NC_EINVAL;
+	}
+
+	if(        (invp->ndims == 0 && outvp->ndims != 0)
+		|| (invp->ndims != 0 && outvp->ndims == 0)
+		|| (IS_RECVAR(invp) && !IS_RECVAR(outvp))
+		|| (!IS_RECVAR(invp) && IS_RECVAR(outvp))
+		|| (invp->len != outvp->len)
+	)
+	{
+		return NC_EINVAL;
+	}
+
+	/*
+	 * Check coordinates
+	 */
+	{
+	ALLOC_ONSTACK(coord, size_t, invp->ndims);
+	const size_t nrecs = NC_get_numrecs(inncp);
+	(void) memcpy(coord, invp->shape, invp->ndims * sizeof(size_t));
+	if(IS_RECVAR(invp))
+		*coord = nrecs;
+	
+	{
+	size_t ii = 0;
+	for(; ii < invp->ndims; ii++)
+		coord[ii] --;
+	}
+	/* at this point, coord is the largest valid coord of invp */
+
+	if(NCcoordck(outncp, outvp, coord) != NC_NOERR)
+	{
+		return NC_EINVAL;
+	}
+	/* else */
+
+	(void) memset(coord, 0, invp->ndims * sizeof(size_t));
+	
+	if(!IS_RECVAR(invp))
+	{
+		status = NCxvarcpy(inncp, invp, coord,
+				outncp, outvp, coord,
+				invp->len);
+		goto done;
+	}
+	/* else */
+
+	status = NCvnrecs(outncp, nrecs);
+	if(status != NC_NOERR)
+		goto done;
+
+	for( /*NADA*/; *coord < nrecs; (*coord)++)
+	{
+		status = NCxvarcpy(inncp, invp, coord,
+				outncp, outvp, coord,
+				invp->len);
+		if(status != NC_NOERR)
+			break;
+	}
+done:
+	FREE_ONSTACK(coord);
+	}
+	return status;
+}
Index: /branches/SDM_SciDAC/src/lib/mpinetcdf.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/mpinetcdf.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/mpinetcdf.c (revision 2)
@@ -0,0 +1,3963 @@
+/*********************************************************************************
+ * 
+ * This file is written by Northwestern University and Argonne National Laboratory
+ *
+ ********************************************************************************/
+
+#include <mpi.h>
+#include "nc.h"
+#include "ncx.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+
+const char *
+ncmpi_inq_libvers(void) {
+  return "version = 3.5.0 of Aug 30 2002 13:00:00 $";
+}
+
+/* to be updated */ 
+const char *
+ncmpi_strerror(int err) {
+  return nc_strerror(err);
+}
+
+/* Begin Of Dataset Functions */
+
+int 
+ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp) {
+  int status = NC_NOERR;
+  NC *ncp;
+
+  ncp = new_NC(NULL);
+  if(ncp == NULL) 
+    return NC_ENOMEM;
+
+  assert(ncp->xsz = ncx_len_NC(ncp));
+
+  fSet(ncp->flags, NC_NOFILL);
+
+  status = ncio_create(comm, path, cmode, info, &ncp->nciop);  
+  if(status != NC_NOERR) {
+    free_NC(ncp);
+    return status;
+  }
+
+  assert(ncp->flags == 0);
+  fSet(ncp->flags, NC_CREAT);
+
+  if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) {
+     /*
+      * NC_SHARE implies sync up the number of records as well.
+      * (File format version one.)
+      * Note that other header changes are not shared
+      * automatically.  Some sort of IPC (external to this package)
+      * would be used to trigger a call to ncmpi_sync().
+      */ 
+    fSet(ncp->flags, NC_NSYNC);
+  }
+
+  add_to_NCList(ncp);
+  *ncidp = ncp->nciop->fd;
+
+  return status;
+}
+
+int
+ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp) {
+  int status = NC_NOERR;
+  NC *ncp;
+  
+  ncp = new_NC(NULL);
+  if(ncp == NULL)
+    return NC_ENOMEM;
+
+  status = ncio_open(comm, path, omode, info, &ncp->nciop);
+  if(status != NC_NOERR) {
+    free_NC(ncp);
+    return status;
+  } 
+
+  assert(ncp->flags == 0); 
+
+  if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) {
+    /*
+     * NC_SHARE implies sync up the number of records as well.
+     * (File format version one.)
+     * Note that other header changes are not shared
+     * automatically.  Some sort of IPC (external to this package)
+     * would be used to trigger a call to ncmpi_sync().
+     */ 
+    fSet(ncp->flags, NC_NSYNC);
+  }
+
+  status = hdr_get_NC(ncp);
+  if (status != NC_NOERR) {
+    free_NC(ncp);
+    return status;
+  }
+
+  add_to_NCList(ncp);
+
+  *ncidp = ncp->nciop->fd;
+ 
+  return status;
+}
+
+int
+ncmpi_redef(int ncid) {
+  int status;
+  NC *ncp;
+  int mynumrecs, numrecs;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR) 
+    return status; 
+
+  if(NC_readonly(ncp)) 
+    return NC_EPERM;
+
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* ensure exiting define mode always entering collective data mode */
+  if(NC_indep(ncp))
+    ncmpi_end_indep_data(ncid);
+
+  if(fIsSet(ncp->nciop->ioflags, NC_SHARE)) {
+    /* read in from disk */
+    status = read_NC(ncp);
+    if(status != NC_NOERR)
+      return status;
+  } else {
+
+    /* collect and set the max numrecs */
+
+    mynumrecs = ncp->numrecs;
+    MPI_Allreduce(&mynumrecs, &numrecs, 1, MPI_INT, MPI_MAX, ncp->nciop->comm);
+    if (numrecs > ncp->numrecs) {
+      ncp->numrecs = numrecs;
+      set_NC_ndirty(ncp);
+    }
+  }
+
+  ncp->old = dup_NC(ncp);
+  if(ncp->old == NULL)
+    return NC_ENOMEM;
+
+  fSet(ncp->flags, NC_INDEF);
+
+  return NC_NOERR;
+}
+
+int
+ncmpi_begin_indep_data(int ncid) {
+  int status = NC_NOERR;
+  NC *ncp;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if (status != NC_NOERR)
+    return status;
+
+  if (NC_indep(ncp))
+    return NC_EINDEP;
+ 
+  if(!NC_readonly(ncp) && NC_collectiveFhOpened(ncp->nciop))
+    MPI_File_sync(ncp->nciop->collective_fh);   /* collective */
+
+  fSet(ncp->flags, NC_INDEP);
+
+  MPI_Barrier(ncp->nciop->comm);
+
+  return status;  
+}
+
+int 
+ncmpi_end_indep_data(int ncid) {
+  int status = NC_NOERR;
+  NC *ncp;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if (status != NC_NOERR)
+    return status; 
+
+  if (!NC_indep(ncp))
+    return NC_ENOTINDEP;
+
+  if(!NC_readonly(ncp) && NC_independentFhOpened(ncp->nciop))
+    MPI_File_sync(ncp->nciop->independent_fh); /* independent */
+
+  fClr(ncp->flags, NC_INDEP);
+ 
+  MPI_Barrier(ncp->nciop->comm);
+
+  return status;
+}
+
+int
+ncmpi_enddef(int ncid) {
+  int status = NC_NOERR;
+  NC *ncp;
+
+  status = NC_check_id(ncid, &ncp); 
+  if(status != NC_NOERR)
+    return status;
+
+  if(!NC_indef(ncp))
+    return(NC_ENOTINDEFINE);
+
+  return NC_enddef(ncp);
+}
+
+int
+ncmpi_sync(int ncid) {
+  int status = NC_NOERR;
+  NC *ncp;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  if(NC_indef(ncp)) 
+    return NC_EINDEFINE;
+
+  if(NC_readonly(ncp))
+    return read_NC(ncp);
+
+  /* else, read/write */
+
+  status = NC_sync(ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  return ncio_sync(ncp->nciop);
+}
+
+int
+ncmpi_abort(int ncid) {
+ /*
+  * In data mode, same as ncio_close.
+  * In define mode, descard new definition.
+  * In create, remove the file.
+  */
+  int status;
+  NC *ncp;
+  int doUnlink = 0;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  doUnlink = NC_IsNew(ncp);
+
+  if (ncp->old != NULL) {
+    /* a plain redef, not a create */
+    assert(!NC_IsNew(ncp));
+    assert(fIsSet(ncp->flags, NC_INDEF));
+    free_NC(ncp->old);
+    ncp->old = NULL;
+    fClr(ncp->flags, NC_INDEF);
+  } 
+  else if (!NC_readonly(ncp) && !NC_indef(ncp)) {
+    /* data mode, write */
+    status = NC_sync(ncp);
+    if (status != NC_NOERR)
+      return status;
+  }
+
+  (void) ncio_close(ncp->nciop, doUnlink);
+  ncp->nciop = NULL;
+
+  del_from_NCList(ncp);
+
+  free_NC(ncp);
+
+  return NC_NOERR;
+}
+
+int
+ncmpi_close(int ncid) {
+  int status = NC_NOERR;
+  NC *ncp;
+
+  NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  /* release NC object, close the file and write Dirty numrecs if necessary */
+
+  return NC_close(ncp);
+}
+
+/* End Of Dataset Functions */
+
+/* Begin Of Define Mode Functions */
+
+int
+ncmpi_def_dim(int ncid, const char *name, size_t len, int *idp) {
+  return nc_def_dim(ncid, name, len, idp);
+}
+
+int
+ncmpi_def_var(int ncid, const char *name, nc_type xtype, 
+              int ndims, const int *dimidsp, int *varidp) {
+  return nc_def_var(ncid, name, xtype, ndims, dimidsp, varidp);
+}
+
+int 
+ncmpi_rename_dim(int ncid, int dimid, const char *name) {
+  return nc_rename_dim(ncid, dimid, name);
+}
+
+int 
+ncmpi_rename_var(int ncid, int varid, const char *name) {
+  return nc_rename_var(ncid, varid, name);
+}
+
+/* End Of Define Mode Functions */
+
+/* Begin Of Inquiry Functions */
+
+int 
+ncmpi_inq(int ncid, int *ndimsp, int *nvarsp,
+          int *ngattsp, int *unlimdimidp) {
+  return nc_inq(ncid, ndimsp, nvarsp, ngattsp, unlimdimidp);
+}
+
+int 
+ncmpi_inq_ndims(int ncid, int *ndimsp) {
+  return nc_inq_ndims(ncid, ndimsp);
+}
+
+int
+ncmpi_inq_nvars(int ncid, int *nvarsp) {
+  return nc_inq_nvars(ncid, nvarsp); 
+}
+
+int 
+ncmpi_inq_natts(int ncid, int *ngattsp) {
+  return nc_inq_natts(ncid, ngattsp);
+} 
+
+int
+ncmpi_inq_unlimdim(int ncid, int *unlimdimidp) {
+  return nc_inq_unlimdim(ncid, unlimdimidp);
+} 
+
+int 
+ncmpi_inq_dimid(int ncid, const char *name, int *idp) {
+  return nc_inq_dimid(ncid, name, idp);
+} 
+
+int 
+ncmpi_inq_dim(int ncid, int dimid, char *name, size_t *lenp) {
+  return nc_inq_dim(ncid, dimid, name, lenp);
+} 
+
+int 
+ncmpi_inq_dimname(int ncid, int dimid, char *name) {
+  return nc_inq_dimname(ncid, dimid, name);
+} 
+
+int 
+ncmpi_inq_dimlen(int ncid, int dimid, size_t *lenp) {
+  return nc_inq_dimlen(ncid, dimid, lenp);
+} 
+
+int 
+ncmpi_inq_var(int ncid, int varid, char *name, 
+              nc_type *xtypep, int *ndimsp, int *dimidsp,
+              int *nattsp) {
+  return nc_inq_var(ncid, varid, name, xtypep, ndimsp, dimidsp, nattsp);
+} 
+
+int 
+ncmpi_inq_varid(int ncid, const char *name, int *varidp) {
+  return nc_inq_varid(ncid, name, varidp);
+} 
+
+int 
+ncmpi_inq_varname(int ncid, int varid, char *name) {
+  return nc_inq_varname(ncid, varid, name);
+} 
+
+int 
+ncmpi_inq_vartype(int ncid, int varid, nc_type *xtypep) {
+  return nc_inq_vartype(ncid, varid, xtypep);
+} 
+
+int 
+ncmpi_inq_varndims(int ncid, int varid, int *ndimsp) {
+  return nc_inq_varndims(ncid, varid, ndimsp);
+} 
+
+int 
+ncmpi_inq_vardimid(int ncid, int varid, int *dimidsp) {
+  return nc_inq_vardimid(ncid, varid, dimidsp);
+} 
+
+int
+ncmpi_inq_varnatts(int ncid, int varid, int *nattsp) {
+  return nc_inq_varnatts(ncid, varid, nattsp);
+} 
+
+/* End Of Inquiry Functions */
+
+/* Begin Of Attribute Functions */
+
+/*
+int 
+ncmpi_inq_att(int ncid, int varid, const char *name,
+              nc_type *xtypep, size_t *lenp) {
+  return nc_inq_att(ncid, varid, name, xtypep, lenp);
+}
+
+int 
+ncmpi_inq_attid(int ncid, int varid, const char *name, int *idp) {
+  return nc_inq_attid(ncid, varid, name, idp);
+}
+
+int 
+ncmpi_inq_atttype(int ncid, int varid, const char *name,
+                  nc_type *xtypep) {
+  return nc_inq_atttype(ncid, varid, name, xtypep);
+}
+
+int 
+ncmpi_inq_attlen(int ncid, int varid, const char *name,
+                 size_t *lenp) {
+  return nc_inq_attlen(ncid, varid, name, lenp);
+}
+
+int 
+ncmpi_inq_attname(int ncid, int varid, int attnum, char *name) {
+  return nc_inq_attname(ncid, varid, attnum, name);
+}
+
+int 
+ncmpi_copy_att(int ncid_in, int varid_in, const char *name,
+               int ncid_out, int varid_out) {
+  return nc_copy_att(ncid_in, varid_in, name, ncid_out, varid_out);
+}
+
+int 
+ncmpi_rename_att(int ncid, int varid, const char *name,
+                 const char *newname) {
+  return nc_rename_att(ncid, varid, name, newname);
+}
+
+int 
+ncmpi_del_att(int ncid, int varid, const char *name) {
+  return nc_del_att(ncid, varid, name);
+}
+
+int 
+ncmpi_put_att_text(int ncid, int varid, const char *name, size_t len,
+                   const char *op) {
+  return nc_put_att_text(ncid, varid, name, len, op);
+}
+
+int 
+ncmpi_get_att_text(int ncid, int varid, const char *name, char *ip) {
+  return nc_get_att_text(ncid, varid, name, ip);
+}
+
+int 
+ncmpi_put_att_uchar(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const unsigned char *op) {
+  return nc_put_att_uchar(ncid, varid, name, xtype, len, op);
+}
+
+int 
+ncmpi_get_att_uchar(int ncid, int varid, const char *name,
+                    unsigned char *ip) {
+  return nc_get_att_uchar(ncid, varid, name, ip);
+}
+
+int 
+ncmpi_put_att_schar(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const signed char *op) {
+  return nc_put_att_schar(ncid, varid, name, xtype, len, op);
+}
+
+int 
+ncmpi_get_att_schar(int ncid, int varid, const char *name,
+                    signed char *ip) {
+  return nc_get_att_schar(ncid, varid, name, ip);
+}
+
+int 
+ncmpi_put_att_short(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const short *op) {
+  return nc_put_att_short(ncid, varid, name, xtype, len, op);
+}
+
+int 
+ncmpi_get_att_short(int ncid, int varid, const char *name, short *ip) {
+  return nc_get_att_short(ncid, varid, name, ip);
+}
+
+int 
+ncmpi_put_att_int(int ncid, int varid, const char *name,
+                  nc_type xtype, size_t len, const int *op) {
+  return nc_put_att_int(ncid, varid, name, xtype, len, op);
+}
+
+int 
+ncmpi_get_att_int(int ncid, int varid, const char *name, int *ip) {
+  return nc_get_att_int(ncid, varid, name, ip);
+}
+
+int 
+ncmpi_put_att_long(int ncid, int varid, const char *name,
+                   nc_type xtype, size_t len, const long *op) {
+  return nc_put_att_long(ncid, varid, name, xtype, len, op);
+}
+
+int 
+ncmpi_get_att_long(int ncid, int varid, const char *name, long *ip) {
+  return nc_get_att_long(ncid, varid, name, ip);
+}
+
+int 
+ncmpi_put_att_float(int ncid, int varid, const char *name,
+                    nc_type xtype, size_t len, const float *op) {
+  return nc_put_att_float(ncid, varid, name, xtype, len, op);
+}
+
+int 
+ncmpi_get_att_float(int ncid, int varid, const char *name, float *ip) {
+  return nc_get_att_float(ncid, varid, name, ip);
+}
+
+int 
+ncmpi_put_att_double(int ncid, int varid, const char *name,
+                     nc_type xtype, size_t len, const double *op) {
+  return nc_put_att_double(ncid, varid, name, xtype, len, op);
+}
+
+int 
+ncmpi_get_att_double(int ncid, int varid, const char *name, 
+                     double *ip) {
+  return nc_get_att_double(ncid, varid, name, ip);
+}
+
+*/
+
+/* End Of Attribute Functions */
+
+/* Begin {put,get}_att */
+
+/* to be updated */
+int
+ncmpi_put_att_text(int ncid, int varid, const char *name,
+        size_t len, const char *op) {
+  int status = NC_NOERR;
+/*
+  int rank;
+  MPI_Comm_rank(comm, &rank);
+*/
+  status = nc_put_att_text(ncid, varid, name, len, op);
+
+  return status;
+}
+
+/* End {put,get}_att */
+
+/* Begin {put,get}_var */
+
+/*
+ *  MAPPING:  MPI DATATYPE   <--->   NETCDF DATATYPE
+ *		MPI_BYTE		NC_BYTE
+ *		MPI_CHAR		NC_CHAR
+ *		MPI_SHORT		NC_SHORT
+ *		MPI_INT			NC_INT
+ *		MPI_FLOAT		NC_FLOAT
+ *		MPI_DOUBLE		NC_DOUBLE
+ *
+ *
+ *  Assume: MPI_Datatype and nc_type are both enumerable types
+ */
+
+int
+length_of_mpitype(MPI_Datatype datatype) {
+  switch(datatype) {
+    case MPI_BYTE:
+    case MPI_CHAR:
+	return ((int)sizeof(char));
+    case MPI_SHORT:
+	return (int)(sizeof(short));
+    case MPI_INT:
+	return((int)sizeof(int)); 
+    case MPI_FLOAT:
+	return((int)sizeof(float));
+    case MPI_DOUBLE:
+	return((int)sizeof(double));
+  }
+
+  return -1;
+}
+
+static void
+swapn(void *dst, const void *src, size_t nn, int xsize)
+{
+  int i;
+  char *op = dst;
+  const char *ip = src;
+  while (nn-- != 0) {
+    for (i=0; i<xsize; i++)
+      op[i] = ip[xsize-1-i];
+    op += xsize;
+    ip += xsize;
+  }
+}
+
+void
+x_putn_short(void *xbuf, const void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+ 
+  xp = (char *) xbuf;
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);
+ 
+  switch (datatype) {
+    case MPI_SHORT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_put_short_short(xp, (const short *)data);
+        return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_put_short_int(xp, (const int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_put_short_float(xp, (const float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_put_short_double(xp, (const double *)data);
+        return;
+  }
+} 
+
+void
+x_putn_int(void *xbuf, const void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+ 
+  xp = (char *) xbuf;
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);
+ 
+  switch (datatype) {
+    case MPI_SHORT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_put_int_short(xp, (const short *)data);
+        return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_put_int_int(xp, (const int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_put_int_float(xp, (const float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_put_int_double(xp, (const double *)data);
+        return;
+  }
+} 
+
+void
+x_putn_float(void *xbuf, const void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+ 
+  xp = (char *) xbuf;
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);
+ 
+  switch (datatype) {
+    case MPI_SHORT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_put_float_short(xp, (const short *)data);
+        return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_put_float_int(xp, (const int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_put_float_float(xp, (const float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_put_float_double(xp, (const double *)data);
+        return;
+  }
+} 
+
+void
+x_putn_double(void *xbuf, const void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+ 
+  xp = (char *) xbuf; 
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);  
+
+  switch (datatype) {
+    case MPI_SHORT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc)
+          ncx_put_double_short(xp, (const short *)data);
+        return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc)
+          ncx_put_double_int(xp, (const int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc)
+          ncx_put_double_float(xp, (const float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc) 
+          ncx_put_double_double(xp, (const double *)data);
+        return;
+  }
+} 
+
+void
+x_getn_short(const void *xbuf, void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+
+  xp = (char *) xbuf;
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);
+ 
+  switch(datatype) {
+    case MPI_SHORT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_get_short_short(xp, (short *)data);
+        return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_get_short_int(xp, (int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_get_short_float(xp, (float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, data += datainc)
+          ncx_get_short_double(xp, (double *)data);
+        return;
+  }
+} 
+
+void 
+x_getn_int(const void *xbuf, void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+ 
+  xp = (char *) xbuf;
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);
+ 
+  switch(datatype) {
+    case MPI_SHORT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_get_int_short(xp, (short *)data);
+        return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_get_int_int(xp, (int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_get_int_float(xp, (float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, data += datainc)
+          ncx_get_int_double(xp, (double *)data);
+        return;
+  }
+} 
+
+void
+x_getn_float(const void *xbuf, void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+ 
+  xp = (char *) xbuf;
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);
+ 
+  switch(datatype) {
+    case MPI_SHORT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_get_float_short(xp, (short *)data);
+        return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_get_float_int(xp, (int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_get_float_float(xp, (float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, data += datainc)
+          ncx_get_float_double(xp, (double *)data);
+        return;
+  }
+}
+
+void
+x_getn_double(const void *xbuf, void *buf, int nelems, MPI_Datatype datatype) {
+  char *xp, *data;
+  int datainc;
+ 
+  xp = (char *) xbuf;
+  data = (char *) buf;
+  datainc = length_of_mpitype(datatype);
+                                                                                    
+  switch(datatype) {
+    case MPI_SHORT:
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc) 
+	  ncx_get_double_short(xp, (short *)data);
+	return;
+    case MPI_INT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc)
+          ncx_get_double_int(xp, (int *)data);
+        return;
+    case MPI_FLOAT:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc)
+          ncx_get_double_float(xp, (float *)data);
+        return;
+    case MPI_DOUBLE:
+        for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, data += datainc)
+          ncx_get_double_double(xp, (double *)data);
+        return;
+  }
+}
+
+int
+NC_check_mpifh(NC* ncp, MPI_File *mpifh, MPI_Comm comm, int collective) {
+
+  if (collective && NC_indep(ncp))
+    return NC_EINDEP;
+
+  if (!collective && !NC_indep(ncp))
+    return NC_ENOTINDEP;
+
+  if (collective && !NC_collectiveFhOpened(ncp->nciop) 
+    || !collective && !NC_independentFhOpened(ncp->nciop)) {
+  
+    int mpireturn;
+    mpireturn = MPI_File_open(comm, (char *)ncp->nciop->path, ncp->nciop->mpiomode,
+                              ncp->nciop->mpiinfo, mpifh);
+    if (mpireturn != MPI_SUCCESS) {
+      char errorString[512];
+      int  errorStringLen;
+      MPI_Error_string(mpireturn, errorString, &errorStringLen);
+      printf("NC_check_mpifh() calliing MPI_File_open error = %s\n", errorString);
+      return NC_ENFILE;
+      /* To be determined the return error code ???????????? */
+    }
+
+    if (collective)
+      set_NC_collectiveFh(ncp->nciop);
+    else
+      set_NC_independentFh(ncp->nciop);
+
+  }
+
+  return NC_NOERR;
+}
+
+/*
+ * Check whether 'coord' values (indices) are valid for the variable.
+ */
+int
+NCcoordck(NC *ncp, const NC_var *varp, const size_t *coord)
+{
+        const size_t *ip;
+        size_t *up;
+ 
+        if(varp->ndims == 0)
+                return NC_NOERR;        /* 'scalar' variable */
+ 
+        if(IS_RECVAR(varp))
+        {
+                if(*coord > X_INT_MAX)
+                        return NC_EINVALCOORDS; /* sanity check */
+                if(NC_readonly(ncp) && *coord >= ncp->numrecs)
+                {
+                        if(!NC_doNsync(ncp))
+                                return NC_EINVALCOORDS;
+                        /* else */
+                        {
+                                /* Update from disk and check again */
+                                const int status = read_numrecs(ncp);
+                                if(status != NC_NOERR)
+                                        return status;
+                                if(*coord >= ncp->numrecs)
+                                        return NC_EINVALCOORDS;
+                        }
+                }
+                ip = coord + 1;
+                up = varp->shape + 1;
+        }
+        else
+        {
+                ip = coord;
+                up = varp->shape;
+        }
+ 
+        for(; ip < coord + varp->ndims; ip++, up++)
+        {
+                /* cast needed for braindead systems with signed size_t */
+                if((unsigned long) *ip >= (unsigned long) *up )
+                        return NC_EINVALCOORDS;
+        }
+ 
+        return NC_NOERR;                                                              }
+
+int
+NC_set_var1_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, const size_t index[]) {
+  MPI_Offset offset;
+  int status;
+  int dim, ndims;
+
+  status = NCcoordck(ncp, varp, index);
+  if (status != NC_NOERR)
+    return status;
+
+  offset = varp->begin;
+ 
+  ndims = varp->ndims;
+
+  if (IS_RECVAR(varp))
+    offset += index[0] * ncp->recsize;
+  else 
+    offset += index[ndims-1] * varp->xsz;
+
+  if (ndims > 1) {
+    if (IS_RECVAR(varp))
+      offset += index[ndims - 1] * varp->xsz;
+    else
+      offset += index[0] * varp->dsizes[1] * varp->xsz;
+
+    for (dim = 1; dim < ndims - 1; dim++)
+      offset += index[dim] * varp->dsizes[dim+1] * varp->xsz;
+  }
+
+  MPI_File_set_view(*mpifh, offset, MPI_BYTE, MPI_BYTE, "native", ncp->nciop->mpiinfo);
+
+  return NC_NOERR;
+}
+
+int
+NC_set_var_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp) {
+  MPI_Offset offset;
+  int status;
+
+  offset = varp->begin;
+
+  if (!IS_RECVAR(varp)) { 
+    /* Contiguous file view */
+    MPI_File_set_view(*mpifh, offset, MPI_BYTE, MPI_BYTE, "native", ncp->nciop->mpiinfo);
+  } else {
+    /* Record variable, Strided file view */
+    int dim, ndims;
+    MPI_Datatype filetype;  
+    MPI_Aint stride;
+    int blocklen;
+
+    ndims = varp->ndims;
+    if (ndims > 1)
+      blocklen = varp->dsizes[1] * varp->xsz;
+    else
+      blocklen = varp->xsz;
+
+    stride = ncp->recsize;
+
+#if (MPI_VERSION < 2)
+    MPI_Type_hvector(ncp->numrecs, blocklen, stride, MPI_BYTE, &filetype);
+#else
+    MPI_Type_create_hvector(ncp->numrecs, blocklen, stride, MPI_BYTE, &filetype);
+#endif
+    MPI_Type_commit(&filetype);
+
+    MPI_File_set_view(*mpifh, offset, MPI_BYTE, filetype, "native", ncp->nciop->mpiinfo);
+
+    MPI_Type_free(&filetype); 
+  }
+
+  return NC_NOERR;
+}
+
+int
+NC_set_vara_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, const size_t start[], const size_t count[]) {
+
+  MPI_Offset offset;
+  int status;
+  int dim, ndims;
+  int *shape, *subcount, *substart; /* all in bytes */
+  size_t *end;
+  MPI_Datatype rectype;
+  MPI_Datatype filetype;
+
+  offset = varp->begin;
+  
+  ndims = varp->ndims;
+  end = (size_t *)malloc(sizeof(size_t) * ndims);
+  shape = (int *)malloc(sizeof(int) * ndims);
+  subcount = (int *)malloc(sizeof(int) * ndims);
+  substart = (int *)malloc(sizeof(int) * ndims);
+
+  for (dim = 0; dim < ndims; dim++)
+    end[dim] = start[dim] + count[dim] - 1;
+  status = NCcoordck(ncp, varp, end);
+  if (status != NC_NOERR)
+    return status;
+  
+  if (IS_RECVAR(varp)) {
+    subcount[0] = count[0];
+    substart[0] = 0;
+    shape[0] = subcount[0];
+
+    if (ncp->recsize <= varp->len) {
+
+      /* the only record variable */
+
+      if (varp->ndims == 1) {
+        shape[0] *= varp->xsz;
+	subcount[0] *= varp->xsz;
+      } else {
+	for (dim = 1; dim < ndims-1; dim++) {
+          shape[dim] = varp->shape[dim];
+          subcount[dim] = count[dim];
+          substart[dim] = start[dim];
+	}
+	shape[dim] = varp->xsz * varp->shape[dim];
+	subcount[dim] = varp->xsz * count[dim];
+	substart[dim] = varp->xsz * start[dim];
+      }
+      offset += start[0] * ncp->recsize;
+
+      MPI_Type_create_subarray(ndims, shape, subcount, substart, 
+				MPI_ORDER_C, MPI_BYTE, &filetype); 
+
+      MPI_Type_commit(&filetype);
+    } else {
+
+      /* more than one record variables */
+
+      offset += start[0] * ncp->recsize;
+      if (varp->ndims == 1) {
+#if (MPI_VERSION < 2)
+	MPI_Type_vector(subcount[0], varp->xsz, ncp->recsize,
+			MPI_BYTE, &filetype);
+#else
+	MPI_Type_create_vector(subcount[0], varp->xsz, ncp->recsize,
+				MPI_BYTE, &filetype);
+#endif
+	MPI_Type_commit(&filetype);
+
+      } else {
+        for (dim = 1; dim < ndims-1; dim++) {
+          shape[dim] = varp->shape[dim];
+          subcount[dim] = count[dim];
+          substart[dim] = start[dim];
+        }
+        shape[dim] = varp->xsz * varp->shape[dim];
+        subcount[dim] = varp->xsz * count[dim];
+        substart[dim] = varp->xsz * start[dim];
+
+	MPI_Type_create_subarray(ndims-1, shape+1, subcount+1, substart+1,
+				 MPI_ORDER_C, MPI_BYTE, &rectype);
+	MPI_Type_commit(&rectype);
+#if (MPI_VERSION < 2)
+	MPI_Type_hvector(subcount[0], 1, ncp->recsize, rectype, &filetype);
+#else
+	MPI_Type_create_hvector(subcount[0], 1, ncp->recsize, rectype, &filetype);
+#endif
+	MPI_Type_commit(&filetype);
+	MPI_Type_free(&rectype);
+      }
+    }
+
+  } else {
+
+    /* non record variable */
+
+    for (dim = 0; dim < ndims-1; dim++ ) {
+      shape[dim] = varp->shape[dim];
+      subcount[dim] = count[dim];
+      substart[dim] = start[dim];
+    }
+    shape[dim] = varp->xsz * varp->shape[dim];
+    subcount[dim] = varp->xsz * count[dim];
+    substart[dim] = varp->xsz * start[dim];
+
+    MPI_Type_create_subarray(ndims, shape, subcount, substart, 
+	 		   MPI_ORDER_C, MPI_BYTE, &filetype); 
+
+    MPI_Type_commit(&filetype);
+  }
+
+  MPI_File_set_view(*mpifh, offset, MPI_BYTE, 
+		    filetype, "native", ncp->nciop->mpiinfo);
+
+  MPI_Type_free(&filetype);
+
+  free(shape);
+  free(subcount);
+  free(substart);
+
+  return NC_NOERR;
+}
+
+int
+NC_set_vars_fileview(NC* ncp, MPI_File *mpifh, NC_var* varp, 
+		     const size_t start[], const size_t count[], 
+                     const size_t stride[]) {
+  MPI_Offset offset;
+  int status;
+  int dim, ndims;
+  MPI_Datatype *subtypes, *filetype;
+  size_t *blocklens, *blockstride, *blockcount, *end;
+
+  offset = varp->begin;
+  
+  ndims = varp->ndims;
+  subtypes = (MPI_Datatype *)malloc((ndims+1) * sizeof(MPI_Datatype));
+  filetype = subtypes;
+  subtypes[ndims] = MPI_BYTE;
+
+  end = (size_t *) malloc(ndims * sizeof(size_t));
+  for (dim = 0; dim < ndims; dim++)
+    end[dim] = start[dim] + (count[dim] - 1) * stride[dim];
+  status = NCcoordck(ncp, varp, end);
+  if (status != NC_NOERR)
+    return status; 
+
+  blocklens = (size_t *) malloc(ndims * sizeof(size_t));
+  blockstride = (size_t *) malloc(ndims * sizeof(size_t));
+  blockcount = (size_t *) malloc(ndims * sizeof(size_t));
+  blocklens[ndims - 1] = varp->xsz;
+  blockcount[ndims - 1] = count[ndims - 1];
+  if (ndims == 1 && IS_RECVAR(varp)) {
+    blockstride[ndims - 1] = stride[ndims - 1] * ncp->recsize;
+    offset += start[ndims - 1] * ncp->recsize;
+  } else {
+    blockstride[ndims - 1] = stride[ndims - 1] * varp->xsz;
+    offset += start[ndims - 1] * varp->xsz;
+  }
+
+  for (dim = ndims - 1; dim >= 0; dim--) {
+#if (MPI_VERSION < 2)
+    MPI_Type_hvector(blockcount[dim], blocklens[dim], blockstride[dim],
+                     subtypes[dim + 1], subtypes + dim);
+#else
+    MPI_Type_create_hvector(blockcount[dim], blocklens[dim], blockstride[dim],
+                            subtypes[dim + 1], subtypes + dim);
+#endif
+    MPI_Type_commit(subtypes + dim);
+    
+    if (dim - 1 >= 0) {
+      blocklens[dim - 1] = 1;
+      blockcount[dim - 1] = count[dim - 1];
+      if (dim - 1 == 0 && IS_RECVAR(varp)) {
+        blockstride[dim - 1] = stride[dim - 1] * ncp->recsize;
+	offset += start[dim-1] * ncp->recsize;
+      } else {
+        blockstride[dim - 1] = stride[dim - 1] * varp->dsizes[dim] * varp->xsz;
+        offset += start[dim-1] * varp->dsizes[dim] * varp->xsz;
+      }
+    }
+  } 
+
+  MPI_File_set_view(*mpifh, offset, MPI_BYTE, 
+                    *filetype, "native", ncp->nciop->mpiinfo);
+
+  for (dim= 0; dim < ndims; dim++ ) 
+    MPI_Type_free(subtypes + dim);
+
+  free(blocklens);
+  free(blockstride);
+  free(blockcount);
+
+  return NC_NOERR;
+}
+
+int
+ncmpi_put_var1(int ncid, int varid,
+               const size_t index[],
+               const void *buf, int bufcount,
+               MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int nbytes;
+  MPI_Status mpistatus;
+  int words_bigendian = 0;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_readonly(ncp))
+    return NC_EPERM;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_var1_fileview(ncp, &(ncp->nciop->independent_fh), varp, index);
+  if(status != NC_NOERR)
+    return status; 
+
+  nbytes = varp->xsz;
+
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = (void *)buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  /* automatic datatype conversion */
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_putn_short(xbuf, buf, 1, datatype);
+         break;
+      case NC_INT:
+         x_putn_int(xbuf, buf, 1, datatype);
+         break;
+      case NC_FLOAT:
+         x_putn_float(xbuf, buf, 1, datatype);
+         break;
+      case NC_DOUBLE:
+         x_putn_double(xbuf, buf, 1, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(xbuf,  buf, 1, ncx_len_nctype(varp->type));
+ 
+  }
+ 
+  MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  if (xbuf != buf)
+    free(xbuf);
+ 
+  if (IS_RECVAR(varp)) {
+    /* update the number of records in NC */
+ 
+    int newnumrecs;
+    newnumrecs = index[0] + 1;
+    if (ncp->numrecs < newnumrecs) {
+      ncp->numrecs = newnumrecs;
+      set_NC_ndirty(ncp);
+    }
+  }
+ 
+  return status;
+}
+
+int
+ncmpi_get_var1(int ncid, int varid,
+               const size_t index[],
+               void *buf, int bufcount,
+               MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int nbytes;
+  int words_bigendian = 0;
+  MPI_Status mpistatus;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  /* set the mpi file view */
+ 
+  status = NC_set_var1_fileview(ncp, &(ncp->nciop->independent_fh), varp, index);
+  if(status != NC_NOERR)
+    return status; 
+
+  nbytes = varp->xsz;
+
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  /* automatic datatype conversion */
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+ 
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_getn_short(xbuf, buf, 1, datatype);
+         break;
+      case NC_INT:
+         x_getn_int(xbuf, buf, 1, datatype);
+         break;
+      case NC_FLOAT:
+         x_getn_float(xbuf, buf, 1, datatype);
+         break;
+      case NC_DOUBLE:
+         x_getn_double(xbuf, buf, 1, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+    free(xbuf);
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(buf, xbuf, 1, ncx_len_nctype(varp->type));
+    free(xbuf);
+ 
+  }
+ 
+  return status;
+}
+
+int
+ncmpi_get_var_all(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  int words_bigendian = 0;
+  MPI_Status mpistatus;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->collective_fh), ncp->nciop->comm, 1);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = bufcount/length_of_mpitype(datatype);
+  nbytes = nelems * varp->xsz;
+
+  /* set the mpi file view */
+ 
+  status = NC_set_var_fileview(ncp, &(ncp->nciop->collective_fh), varp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  MPI_File_read_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  /* automatic datatype conversion */
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+ 
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_getn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_getn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_getn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_getn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+    free(xbuf);
+
+  } else if (!words_bigendian) {
+ 
+    swapn(buf, xbuf, nelems, ncx_len_nctype(varp->type));
+    free(xbuf);
+ 
+  }
+ 
+  return status;
+}
+
+int
+ncmpi_put_var(int ncid, int varid, const void *buf, int bufcount, MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  MPI_Status mpistatus;
+  int words_bigendian = 0;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_readonly(ncp))
+    return NC_EPERM;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR; 
+ 
+  nelems = bufcount/length_of_mpitype(datatype);
+  nbytes = nelems * varp->xsz;
+
+  /* set the mpi file view */
+ 
+  status = NC_set_var_fileview(ncp, &(ncp->nciop->independent_fh), varp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = (void *)buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  /* automatic datatype conversion */
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_putn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_putn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_putn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_putn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(xbuf,  buf, nelems, ncx_len_nctype(varp->type));
+ 
+  }
+ 
+  MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  if (xbuf != buf)
+    free(xbuf);
+ 
+  if (IS_RECVAR(varp)) {
+    /* update the number of records in NC */
+ 
+    int newnumrecs;
+    if (varp->ndims > 1)
+      newnumrecs = nelems / varp->dsizes[1];
+    else
+      newnumrecs = nelems;
+    if (ncp->numrecs < newnumrecs) {
+      ncp->numrecs = newnumrecs;
+      set_NC_ndirty(ncp);
+    }
+  }
+ 
+  return status;
+}
+
+int
+ncmpi_get_var(int ncid, int varid, void *buf, int bufcount, MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  int words_bigendian = 0;
+  MPI_Status mpistatus;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = bufcount/length_of_mpitype(datatype);
+  nbytes = nelems * varp->xsz;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_var_fileview(ncp, &(ncp->nciop->independent_fh), varp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  /* automatic datatype conversion */
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+ 
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_getn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_getn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_getn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_getn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+    free(xbuf);
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(buf, xbuf, nelems, ncx_len_nctype(varp->type));
+    free(xbuf);
+ 
+  }
+
+  return status; 
+} 
+
+int
+ncmpi_put_vara_all(int ncid, int varid,
+                   const size_t start[], const size_t count[],
+                   const void *buf, int bufcount, 
+                   MPI_Datatype datatype) {
+
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  MPI_Status mpistatus;
+  MPI_Comm comm;
+  int rank;
+  int words_bigendian = 0;
+
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  comm = ncp->nciop->comm;
+  MPI_Comm_rank(comm, &rank);
+ 
+  if(NC_readonly(ncp))
+    return NC_EPERM;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->collective_fh), comm, 1);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vara_fileview(ncp, &(ncp->nciop->collective_fh), varp, start, count);
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems;
+
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = (void *)buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+
+  /* automatic datatype conversion */
+
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_putn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_putn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_putn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_putn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+
+  } else if (!words_bigendian) { 
+
+    swapn(xbuf,  buf, nelems, ncx_len_nctype(varp->type));
+
+  }
+
+  MPI_File_write_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+
+  if (xbuf != buf)
+    free(xbuf);
+ 
+  if (IS_RECVAR(varp)) {
+ 
+    /* update the number of records in NC
+        and write it back to file header, if necessary
+    */
+    int newnumrecs, max_numrecs;
+    newnumrecs = start[0] + count[0];
+    if (ncp->numrecs < newnumrecs) {
+      ncp->numrecs = newnumrecs;
+      set_NC_ndirty(ncp);
+    }
+    if (NC_doNsync(ncp)) {
+      MPI_Allreduce( &newnumrecs, &max_numrecs, 1, MPI_INT, MPI_MAX, comm );
+ 
+      if (ncp->numrecs < max_numrecs) {
+        ncp->numrecs = max_numrecs;
+        if (rank == 0) {
+          status = write_numrecs(ncp); /* call subroutine from nc.c */
+          if(status != NC_NOERR)
+            return status;
+        }
+      }
+    }
+  }
+ 
+  return status;
+}
+
+
+int
+ncmpi_get_vara_all(int ncid, int varid,
+                   const size_t start[], const size_t count[],
+		   void *buf, int bufcount,
+                   MPI_Datatype datatype) {
+
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  int words_bigendian = 0;
+  MPI_Status mpistatus;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->collective_fh), ncp->nciop->comm, 1);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vara_fileview(ncp, &(ncp->nciop->collective_fh), varp, start, count);
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems; 
+
+  /* assign or allocate MPI read buffer */ 
+
+  if ( words_bigendian && 
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+
+  MPI_File_read_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+
+  /* automatic datatype conversion */
+
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_getn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_getn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_getn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_getn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+    free(xbuf);
+
+  } else if (!words_bigendian) {
+
+    swapn(buf, xbuf, nelems, ncx_len_nctype(varp->type));
+    free(xbuf);
+
+  }
+ 
+  return status;
+}
+
+int
+ncmpi_put_vara(int ncid, int varid,
+               const size_t start[], const size_t count[],
+               const void *buf, int bufcount,
+               MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  MPI_Status mpistatus;
+  int words_bigendian = 0;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_readonly(ncp))
+    return NC_EPERM;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vara_fileview(ncp, &(ncp->nciop->independent_fh), varp, start, count);
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems;
+ 
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = (void *)buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  /* automatic datatype conversion */ 
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_putn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_putn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_putn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_putn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(xbuf,  buf, nelems, ncx_len_nctype(varp->type));
+ 
+  }
+ 
+  MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  if (xbuf != buf)
+    free(xbuf);
+
+  if (IS_RECVAR(varp)) {
+    /* update the number of records in NC */
+ 
+    int newnumrecs;
+    newnumrecs = start[0] + count[0];
+    if (ncp->numrecs < newnumrecs) {
+      ncp->numrecs = newnumrecs;
+      set_NC_ndirty(ncp);
+    }
+  }
+ 
+  return status;
+} 
+
+int
+ncmpi_get_vara(int ncid, int varid,
+               const size_t start[], const size_t count[],
+               void *buf, int bufcount,
+               MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  int words_bigendian = 0;
+  MPI_Status mpistatus;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vara_fileview(ncp, &(ncp->nciop->independent_fh), varp, start, count);
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems;
+ 
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  /* automatic datatype conversion */
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+ 
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_getn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_getn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_getn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_getn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+    free(xbuf);
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(buf, xbuf, nelems, ncx_len_nctype(varp->type));
+    free(xbuf);
+ 
+  }
+ 
+  return status;
+} 
+
+int
+ncmpi_put_vars_all(int ncid, int varid,
+                   const size_t start[], 
+		   const size_t count[],
+		   const size_t stride[],
+                   const void *buf, int bufcount, 
+                   MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  MPI_Status mpistatus;
+  MPI_Comm comm;
+  int rank;
+  int words_bigendian = 0;
+
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  comm = ncp->nciop->comm;
+  MPI_Comm_rank(comm, &rank);
+ 
+  if(NC_readonly(ncp))
+    return NC_EPERM;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->collective_fh), comm, 1);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vars_fileview(ncp, &(ncp->nciop->collective_fh), 
+                                varp, start, count, stride);
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems;
+
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = (void *)buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  /* automatic datatype conversion */
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_putn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_putn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_putn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_putn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(xbuf,  buf, nelems, ncx_len_nctype(varp->type));
+ 
+  }
+ 
+  MPI_File_write_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  if (xbuf != buf)
+    free(xbuf);
+ 
+  if (IS_RECVAR(varp)) {
+ 
+    /* update the number of records in NC
+        and write it back to file header, if necessary
+    */
+    int newnumrecs, max_numrecs;
+    newnumrecs = start[0] + (count[0] - 1) * stride[0] + 1;
+    if (ncp->numrecs < newnumrecs) {
+      ncp->numrecs = newnumrecs;
+      set_NC_ndirty(ncp);
+    }
+    if (NC_doNsync(ncp)) {
+      MPI_Allreduce( &newnumrecs, &max_numrecs, 1, MPI_INT, MPI_MAX, comm );
+ 
+      if (ncp->numrecs < max_numrecs) {
+        ncp->numrecs = max_numrecs;
+        if (rank == 0) {
+          status = write_numrecs(ncp); /* call subroutine from nc.c */
+          if(status != NC_NOERR)
+            return status;
+        }
+      }
+    }
+  }
+ 
+  return status;
+}
+
+
+int
+ncmpi_get_vars_all(int ncid, int varid,
+                   const size_t start[], 
+		   const size_t count[],
+                   const size_t stride[],
+		   void *buf, int bufcount,
+                   MPI_Datatype datatype) {
+
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  int words_bigendian = 0;
+  MPI_Status mpistatus;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->collective_fh), ncp->nciop->comm, 1);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vars_fileview(ncp, &(ncp->nciop->collective_fh), 
+				varp, start, count, stride);
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems; 
+
+  /* assign or allocate MPI read buffer */ 
+
+  if ( words_bigendian && 
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+
+  MPI_File_read_all(ncp->nciop->collective_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+
+  /* automatic datatype conversion */
+
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_getn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_getn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_getn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_getn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+    free(xbuf);
+
+  } else if (!words_bigendian) {
+
+    swapn(buf, xbuf, nelems, ncx_len_nctype(varp->type));
+    free(xbuf);
+
+  }
+ 
+  return status;
+}
+
+int
+ncmpi_put_vars(int ncid, int varid,
+               const size_t start[], 
+	       const size_t count[],
+	       const size_t stride[],
+               const void *buf, int bufcount,
+               MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  MPI_Status mpistatus;
+  int words_bigendian = 0;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_readonly(ncp))
+    return NC_EPERM;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vars_fileview(ncp, &(ncp->nciop->independent_fh),
+			        varp, start, count, stride);
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems;
+ 
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = (void *)buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  /* automatic datatype conversion */ 
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_putn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_putn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_putn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_putn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(xbuf,  buf, nelems, ncx_len_nctype(varp->type));
+ 
+  }
+ 
+  MPI_File_write(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  if (xbuf != buf)
+    free(xbuf);
+
+  if (IS_RECVAR(varp)) {
+    /* update the number of records in NC */
+ 
+    int newnumrecs;
+    newnumrecs = start[0] + (count[0] - 1) * stride[0] + 1;
+    if (ncp->numrecs < newnumrecs) {
+      ncp->numrecs = newnumrecs;
+      set_NC_ndirty(ncp);
+    }
+  }
+
+  return status;
+} 
+
+int
+ncmpi_get_vars(int ncid, int varid,
+               const size_t start[], 
+	       const size_t count[],
+               const size_t stride[],
+               void *buf, int bufcount,
+               MPI_Datatype datatype) {
+  NC_var *varp;
+  NC *ncp;
+  void *xbuf;
+  int status;
+  int dim;
+  int nelems, nbytes;
+  int words_bigendian = 0;
+  MPI_Status mpistatus;
+ 
+#if WORDS_BIGENDIAN
+  words_bigendian = 1;
+#endif
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  if(NC_indef(ncp))
+    return NC_EINDEFINE;
+ 
+  /* check to see that the desired mpi file handle is opened */
+ 
+  status = NC_check_mpifh(ncp, &(ncp->nciop->independent_fh), MPI_COMM_SELF, 0);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  /* set the mpi file view */
+ 
+  status = NC_set_vars_fileview(ncp, &(ncp->nciop->independent_fh),
+				varp, start, count, stride); 
+  if(status != NC_NOERR)
+    return status;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = varp->xsz * nelems;
+ 
+  /* assign or allocate MPI read buffer */
+ 
+  if ( words_bigendian &&
+      ncx_len_nctype(varp->type) == length_of_mpitype(datatype) )
+    /* Just assign MPI read buffer */
+    xbuf = buf;
+  else
+    /* else, allocate new buffer */
+    xbuf = (void *)malloc(nbytes);
+ 
+  MPI_File_read(ncp->nciop->independent_fh, xbuf, nbytes, MPI_BYTE, &mpistatus);
+ 
+  /* automatic datatype conversion */
+ 
+  if ( ncx_len_nctype(varp->type) != length_of_mpitype(datatype) ) {
+ 
+    switch( varp->type ) {
+      case NC_SHORT:
+         x_getn_short(xbuf, buf, nelems, datatype);
+         break;
+      case NC_INT:
+         x_getn_int(xbuf, buf, nelems, datatype);
+         break;
+      case NC_FLOAT:
+         x_getn_float(xbuf, buf, nelems, datatype);
+         break;
+      case NC_DOUBLE:
+         x_getn_double(xbuf, buf, nelems, datatype);
+         break;
+      case NC_CHAR:
+         break;
+      default:
+         break;
+    }
+    free(xbuf);
+ 
+  } else if (!words_bigendian) {
+ 
+    swapn(buf, xbuf, nelems, ncx_len_nctype(varp->type));
+    free(xbuf);
+ 
+  }
+ 
+  return status;
+} 
+
+int
+ncmpi_put_var1_short(int ncid, int varid,
+                     const size_t index[],
+		     const short *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  return ncmpi_put_var1(ncid, varid, index, 
+                        (const void *)op, sizeof(short), MPI_SHORT); 
+}
+
+int
+ncmpi_put_var1_int(int ncid, int varid,
+                   const size_t index[],
+                   const int *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  return ncmpi_put_var1(ncid, varid, index,
+                        (const void *)op, sizeof(int), MPI_INT);
+}
+
+int
+ncmpi_put_var1_float(int ncid, int varid,
+                     const size_t index[],
+                     const float *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  return ncmpi_put_var1(ncid, varid, index,
+                        (const void *)op, sizeof(float), MPI_FLOAT); 
+}
+ 
+int
+ncmpi_put_var1_double(int ncid, int varid,
+                      const size_t index[],
+                      const double *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  return ncmpi_put_var1(ncid, varid, index,
+                        (const void *)op, sizeof(double), MPI_DOUBLE);
+}
+
+int
+ncmpi_get_var1_short(int ncid, int varid,
+                     const size_t index[],
+                     short *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR; 
+
+  return ncmpi_get_var1(ncid, varid, index,
+                        (void *)ip, sizeof(short), MPI_SHORT); 
+}
+ 
+int
+ncmpi_get_var1_int(int ncid, int varid,
+                   const size_t index[],
+                   int *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  return ncmpi_get_var1(ncid, varid, index,
+                        (void *)ip, sizeof(int), MPI_INT);  
+}
+ 
+int
+ncmpi_get_var1_float(int ncid, int varid,
+                     const size_t index[],
+                     float *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  return ncmpi_get_var1(ncid, varid, index,
+                        (void *)ip, sizeof(float), MPI_FLOAT);  
+}
+ 
+int
+ncmpi_get_var1_double(int ncid, int varid,
+                      const size_t index[],
+                      double *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  return ncmpi_get_var1(ncid, varid, index,
+                        (void *)ip, sizeof(double), MPI_DOUBLE);  
+} 
+
+int
+ncmpi_put_var_short(int ncid, int varid, const short *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR; 
+
+  ndims = varp->ndims;
+
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp)) 
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+
+  nbytes = nelems * sizeof(short);
+ 
+  return ncmpi_put_var(ncid, varid, (const void *)op, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_put_var_int(int ncid, int varid, const int *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(int);
+ 
+  return ncmpi_put_var(ncid, varid, (const void *)op, nbytes, MPI_INT);
+} 
+
+int
+ncmpi_put_var_float(int ncid, int varid, const float *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(float);
+ 
+  return ncmpi_put_var(ncid, varid, (const void *)op, nbytes, MPI_FLOAT);
+} 
+
+int
+ncmpi_put_var_double(int ncid, int varid, const double *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(double);
+ 
+  return ncmpi_put_var(ncid, varid, (const void *)op, nbytes, MPI_DOUBLE);
+} 
+
+int
+ncmpi_get_var_short(int ncid, int varid, short *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(short);
+ 
+  return ncmpi_get_var(ncid, varid, (void *)ip, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_get_var_int(int ncid, int varid, int *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(int);
+ 
+  return ncmpi_get_var(ncid, varid, (void *)ip, nbytes, MPI_INT);
+} 
+
+int
+ncmpi_get_var_float(int ncid, int varid, float *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(float);
+ 
+  return ncmpi_get_var(ncid, varid, (void *)ip, nbytes, MPI_FLOAT);
+} 
+
+int
+ncmpi_get_var_double(int ncid, int varid, double *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(double);
+ 
+  return ncmpi_get_var(ncid, varid, (void *)ip, nbytes, MPI_DOUBLE);
+} 
+
+int
+ncmpi_get_var_short_all(int ncid, int varid, short *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(short);
+ 
+  return ncmpi_get_var_all(ncid, varid, (void *)ip, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_get_var_int_all(int ncid, int varid, int *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(int);
+ 
+  return ncmpi_get_var_all(ncid, varid, (void *)ip, nbytes, MPI_INT);
+} 
+
+int
+ncmpi_get_var_float_all(int ncid, int varid, float *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(float);
+ 
+  return ncmpi_get_var_all(ncid, varid, (void *)ip, nbytes, MPI_FLOAT);
+} 
+
+int
+ncmpi_get_var_double_all(int ncid, int varid, double *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int ndims;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  ndims = varp->ndims;
+ 
+  if (ndims > 1)
+    nelems = varp->dsizes[1];
+  else
+    nelems = 1;
+  if (IS_RECVAR(varp))
+    nelems *= ncp->numrecs;
+  else
+    nelems *= varp->shape[0];
+ 
+  nbytes = nelems * sizeof(double);
+ 
+  return ncmpi_get_var_all(ncid, varid, (void *)ip, nbytes, MPI_DOUBLE);
+} 
+
+int
+ncmpi_put_vara_short_all(int ncid, int varid,
+                         const size_t start[], const size_t count[],
+                         const short *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(short) * nelems;
+ 
+  return ncmpi_put_vara_all(ncid, varid, start, count,
+                            (const void *)op, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_put_vara_short(int ncid, int varid,
+                     const size_t start[], const size_t count[],
+                     const short *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(short) * nelems;
+ 
+  return ncmpi_put_vara(ncid, varid, start, count,
+                        (const void *)op, nbytes, MPI_SHORT);
+} 
+
+int
+ncmpi_put_vara_int_all(int ncid, int varid, 
+                       const size_t start[], const size_t count[], 
+		       const int *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;                                                                  
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR; 
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+
+  return ncmpi_put_vara_all(ncid, varid, start, count, 
+			    (const void *)op, nbytes, MPI_INT);
+}
+
+int
+ncmpi_put_vara_int(int ncid, int varid, 
+		const size_t start[], const size_t count[], 
+		const int *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+ 
+  return ncmpi_put_vara(ncid, varid, start, count,
+                        (const void *)op, nbytes, MPI_INT);
+}
+
+int
+ncmpi_put_vara_float_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const float *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+
+  return ncmpi_put_vara_all(ncid, varid, start, count, 
+			    (const void *)op, nbytes, MPI_FLOAT);
+}
+
+int
+ncmpi_put_vara_float(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const float *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+ 
+  return ncmpi_put_vara(ncid, varid, start, count,
+                        (const void *)op, nbytes, MPI_FLOAT);
+}
+
+int
+ncmpi_put_vara_double_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const double *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+
+  return ncmpi_put_vara_all(ncid, varid, start, count, 
+                            (const void *)op, nbytes, MPI_DOUBLE);
+}
+
+int
+ncmpi_put_vara_double(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const double *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+ 
+  return ncmpi_put_vara(ncid, varid, start, count,
+                        (const void *)op, nbytes, MPI_DOUBLE);
+}
+
+int
+ncmpi_get_vara_short_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    short *ip) {
+ 
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+ 
+  return ncmpi_get_vara_all(ncid, varid, start, count,
+                            (void *)ip, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_get_vara_short(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    short *ip) {
+ 
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+ 
+  return ncmpi_get_vara(ncid, varid, start, count,
+                        (void *)ip, nbytes, MPI_SHORT);
+} 
+
+int
+ncmpi_get_vara_int_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    int *ip) {
+
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+  
+  return ncmpi_get_vara_all(ncid, varid, start, count, 
+                            (void *)ip, nbytes, MPI_INT);
+}
+
+int
+ncmpi_get_vara_int(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                int *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+ 
+  return ncmpi_get_vara(ncid, varid, start, count,
+                        (void *)ip, nbytes, MPI_INT);
+}
+
+int
+ncmpi_get_vara_float_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    float *ip) {
+
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+  
+  return ncmpi_get_vara_all(ncid, varid, start, count, 
+			    (void *)ip, nbytes, MPI_FLOAT); 
+}
+
+int
+ncmpi_get_vara_float(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                float *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+ 
+  return ncmpi_get_vara(ncid, varid, start, count,
+                        (void *)ip, nbytes, MPI_FLOAT);
+}
+
+int
+ncmpi_get_vara_double_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    double *ip) {
+
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+
+  return ncmpi_get_vara_all(ncid, varid, start, count, 
+			    (void *)ip, nbytes, MPI_DOUBLE); 
+}
+
+int
+ncmpi_get_vara_double(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                double *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+ 
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+ 
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+ 
+  return ncmpi_get_vara(ncid, varid, start, count,
+                        (void *)ip, nbytes, MPI_DOUBLE);
+}
+
+int
+ncmpi_put_vars_short_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         const short *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(short) * nelems;
+
+  return ncmpi_put_vars_all(ncid, varid, start, count, stride,
+                            (const void *)op, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_put_vars_short(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     const short *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(short) * nelems;
+
+  return ncmpi_put_vars(ncid, varid, start, count, stride,
+                        (const void *)op, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_put_vars_int_all(int ncid, int varid,
+                       const size_t start[],
+                       const size_t count[],
+                       const size_t stride[],
+                       const int *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+
+  return ncmpi_put_vars_all(ncid, varid, start, count, stride,
+                            (const void *)op, nbytes, MPI_INT);
+}
+
+int
+ncmpi_put_vars_int(int ncid, int varid,
+                   const size_t start[],
+                   const size_t count[],
+                   const size_t stride[],
+                   const int *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+  
+  nelems = 1; 
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+    
+  return ncmpi_put_vars(ncid, varid, start, count, stride,
+                        (const void *)op, nbytes, MPI_INT);
+} 
+
+int
+ncmpi_put_vars_float_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         const float *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+
+  return ncmpi_put_vars_all(ncid, varid, start, count, stride,
+                            (const void *)op, nbytes, MPI_FLOAT);
+}
+
+int
+ncmpi_put_vars_float(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     const float *op) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+
+  return ncmpi_put_vars(ncid, varid, start, count, stride,
+                        (const void *)op, nbytes, MPI_FLOAT);
+}
+
+int
+ncmpi_put_vars_double_all(int ncid, int varid,
+                          const size_t start[], 
+                          const size_t count[],
+                          const size_t stride[],
+                          const double *op) {
+
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+
+  return ncmpi_put_vars_all(ncid, varid, start, count, stride,
+                            (const void *)op, nbytes, MPI_DOUBLE);
+
+}
+
+int
+ncmpi_put_vars_double(int ncid, int varid,
+                      const size_t start[],
+                      const size_t count[],
+                      const size_t stride[],
+                      const double *op) {
+
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+
+  return ncmpi_put_vars(ncid, varid, start, count, stride,
+                        (const void *)op, nbytes, MPI_DOUBLE);
+
+}
+
+int
+ncmpi_get_vars_short_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         short *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(short) * nelems;
+
+  return ncmpi_get_vars_all(ncid, varid, start, count, stride,
+                            (void *)ip, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_get_vars_short(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     short *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(short) * nelems;
+
+  return ncmpi_get_vars(ncid, varid, start, count, stride,
+                        (void *)ip, nbytes, MPI_SHORT);
+}
+
+int
+ncmpi_get_vars_int_all(int ncid, int varid,
+                       const size_t start[],
+                       const size_t count[],
+                       const size_t stride[],
+                       int *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+
+  return ncmpi_get_vars_all(ncid, varid, start, count, stride,
+                            (void *)ip, nbytes, MPI_INT);
+}
+
+int
+ncmpi_get_vars_int(int ncid, int varid,
+                   const size_t start[],
+                   const size_t count[],
+                   const size_t stride[],
+                   int *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(int) * nelems;
+
+  return ncmpi_get_vars(ncid, varid, start, count, stride,
+                        (void *)ip, nbytes, MPI_INT);
+}
+
+int
+ncmpi_get_vars_float_all(int ncid, int varid,
+                         const size_t start[],
+                         const size_t count[],
+                         const size_t stride[],
+                         float *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+
+  return ncmpi_get_vars_all(ncid, varid, start, count, stride,
+                            (void *)ip, nbytes, MPI_FLOAT);
+}
+
+int
+ncmpi_get_vars_float(int ncid, int varid,
+                     const size_t start[],
+                     const size_t count[],
+                     const size_t stride[],
+                     float *ip) {
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(float) * nelems;
+
+  return ncmpi_get_vars(ncid, varid, start, count, stride,
+                        (void *)ip, nbytes, MPI_FLOAT);
+}
+
+int
+ncmpi_get_vars_double_all(int ncid, int varid,
+                          const size_t start[], 
+			  const size_t count[],
+			  const size_t stride[],
+                          double *ip) {
+
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+ 
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+
+  return ncmpi_get_vars_all(ncid, varid, start, count, stride,
+			    (void *)ip, nbytes, MPI_DOUBLE); 
+}
+
+int
+ncmpi_get_vars_double(int ncid, int varid,
+                      const size_t start[],
+                      const size_t count[],
+                      const size_t stride[],
+                      double *ip) {
+
+  NC_var *varp;
+  NC *ncp;
+  int status;
+  int dim;
+  int nelems, nbytes;
+
+  status = NC_check_id(ncid, &ncp);
+  if(status != NC_NOERR)
+    return status;
+
+  varp = NC_lookupvar(ncp, varid);
+  if(varp == NULL)
+    return NC_ENOTVAR;
+
+  nelems = 1;
+  for (dim = 0; dim < varp->ndims; dim++)
+    nelems *= count[dim];
+  nbytes = (int)sizeof(double) * nelems;
+
+  return ncmpi_get_vars(ncid, varid, start, count, stride,
+                        (void *)ip, nbytes, MPI_DOUBLE);
+}
+
+/* End {put,get}_var */
Index: /branches/SDM_SciDAC/src/lib/dim.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/dim.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/dim.c (revision 2)
@@ -0,0 +1,520 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "nc.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ncx.h"
+#include "fbits.h"
+
+/*
+ * Free dim
+ * Formerly
+NC_free_dim(dim)
+ */
+void
+free_NC_dim(NC_dim *dimp)
+{
+	if(dimp == NULL)
+		return;
+	free_NC_string(dimp->name);
+	free(dimp);
+}
+
+
+NC_dim *
+new_x_NC_dim(NC_string *name)
+{
+	NC_dim *dimp;
+
+	dimp = (NC_dim *) malloc(sizeof(NC_dim));
+	if(dimp == NULL)
+		return NULL;
+
+	dimp->name = name;
+	dimp->size = 0;
+
+	return(dimp);
+}
+
+
+/*
+ * Formerly
+NC_new_dim(const char *name, long size)
+ */
+static NC_dim *
+new_NC_dim(const char *name, size_t size)
+{
+	NC_string *strp;
+	NC_dim *dimp;
+
+	strp = new_NC_string(strlen(name), name);
+	if(strp == NULL)
+		return NULL;
+
+	dimp = new_x_NC_dim(strp);
+	if(dimp == NULL)
+	{
+		free_NC_string(strp);
+		return NULL;
+	}
+
+	dimp->size = size;
+
+	return(dimp);
+}
+
+
+static NC_dim *
+dup_NC_dim(const NC_dim *dimp)
+{
+	return new_NC_dim(dimp->name->cp, dimp->size);
+}
+
+/*
+ * Step thru NC_DIMENSION array, seeking the UNLIMITED dimension.
+ * Return dimid or -1 on not found.
+ * *dimpp is set to the appropriate NC_dim.
+ * The loop structure is odd. In order to parallelize,
+ * we moved a clearer 'break' inside the loop body to the loop test.
+ */
+int
+find_NC_Udim(const NC_dimarray *ncap, NC_dim **dimpp)
+{
+	assert(ncap != NULL);
+
+	if(ncap->nelems == 0)
+		return -1;
+
+	{
+	int dimid = 0;
+	NC_dim **loc = ncap->value;
+
+	for(; (size_t) dimid < ncap->nelems
+			 && (*loc)->size != NC_UNLIMITED; dimid++, loc++)
+	{
+		/*EMPTY*/
+	}
+	if(dimid >= ncap->nelems)
+		return(-1); /* not found */
+	/* else, normal return */
+	if(dimpp != NULL)
+		*dimpp = *loc;
+	return dimid;
+	}
+}
+
+
+/*
+ * Step thru NC_DIMENSION array, seeking match on name.
+ * Return dimid or -1 on not found.
+ * *dimpp is set to the appropriate NC_dim.
+ * The loop structure is odd. In order to parallelize,
+ * we moved a clearer 'break' inside the loop body to the loop test.
+ */
+static int
+NC_finddim(const NC_dimarray *ncap, const char *name, NC_dim **dimpp)
+{
+
+	assert(ncap != NULL);
+
+	if(ncap->nelems == 0)
+		return -1;
+
+	{
+	size_t slen = strlen(name);
+	int dimid = 0;
+	NC_dim **loc = (NC_dim **) ncap->value;
+
+	for(; (size_t) dimid < ncap->nelems
+			&& (strlen((*loc)->name->cp) != slen
+				|| strncmp((*loc)->name->cp, name, slen) != 0);
+		 dimid++, loc++)
+	{
+		/*EMPTY*/
+	}
+	if(dimid >= ncap->nelems)
+		return(-1); /* not found */
+	/* else, normal return */
+	if(dimpp != NULL)
+			*dimpp = *loc;
+	return(dimid);
+	}
+}
+
+
+/* dimarray */
+
+
+/*
+ * Free the stuff "in" (referred to by) an NC_dimarray.
+ * Leaves the array itself allocated.
+ */
+void
+free_NC_dimarrayV0(NC_dimarray *ncap)
+{
+	assert(ncap != NULL);
+
+	if(ncap->nelems == 0)
+		return;
+
+	assert(ncap->value != NULL);
+
+	{
+		NC_dim **dpp = ncap->value;
+		NC_dim *const *const end = &dpp[ncap->nelems];
+		for( /*NADA*/; dpp < end; dpp++)
+		{
+			free_NC_dim(*dpp);
+			*dpp = NULL;
+		}
+	}
+	ncap->nelems = 0;
+}
+
+
+/*
+ * Free NC_dimarray values.
+ * formerly
+NC_free_array()
+ */
+void
+free_NC_dimarrayV(NC_dimarray *ncap)
+{
+	assert(ncap != NULL);
+	
+	if(ncap->nalloc == 0)
+		return;
+
+	assert(ncap->value != NULL);
+
+	free_NC_dimarrayV0(ncap);
+
+	free(ncap->value);
+	ncap->value = NULL;
+	ncap->nalloc = 0;
+}
+
+
+int
+dup_NC_dimarrayV(NC_dimarray *ncap, const NC_dimarray *ref)
+{
+	int status = NC_NOERR;
+
+	assert(ref != NULL);
+	assert(ncap != NULL);
+
+	if(ref->nelems != 0)
+	{
+		const size_t sz = ref->nelems * sizeof(NC_dim *);
+		ncap->value = (NC_dim **) malloc(sz);
+		if(ncap->value == NULL)
+			return NC_ENOMEM;
+		(void) memset(ncap->value, 0, sz);
+		ncap->nalloc = ref->nelems;
+	}
+
+	ncap->nelems = 0;
+	{
+		NC_dim **dpp = ncap->value;
+		const NC_dim **drpp = (const NC_dim **)ref->value;
+		NC_dim *const *const end = &dpp[ref->nelems];
+		for( /*NADA*/; dpp < end; drpp++, dpp++, ncap->nelems++)
+		{
+			*dpp = dup_NC_dim(*drpp);
+			if(*dpp == NULL)
+			{
+				status = NC_ENOMEM;
+				break;
+			}
+		}
+	}
+
+	if(status != NC_NOERR)
+	{
+		free_NC_dimarrayV(ncap);
+		return status;
+	}
+
+	assert(ncap->nelems == ref->nelems);
+
+	return NC_NOERR;
+}
+
+
+/*
+ * Add a new handle on the end of an array of handles
+ * Formerly
+NC_incr_array(array, tail)
+ */
+static int
+incr_NC_dimarray(NC_dimarray *ncap, NC_dim *newelemp)
+{
+	NC_dim **vp;
+
+	assert(ncap != NULL);
+
+	if(ncap->nalloc == 0)
+	{
+		assert(ncap->nelems == 0);
+		vp = (NC_dim **) malloc(NC_ARRAY_GROWBY * sizeof(NC_dim *));
+		if(vp == NULL)
+			return NC_ENOMEM;
+		ncap->value = vp;
+		ncap->nalloc = NC_ARRAY_GROWBY;
+	}
+	else if(ncap->nelems +1 > ncap->nalloc)
+	{
+		vp = (NC_dim **) realloc(ncap->value,
+			(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_dim *));
+		if(vp == NULL)
+			return NC_ENOMEM;
+		ncap->value = vp;
+		ncap->nalloc += NC_ARRAY_GROWBY;
+	}
+
+	if(newelemp != NULL)
+	{
+		ncap->value[ncap->nelems] = newelemp;
+		ncap->nelems++;
+	}
+	return NC_NOERR;
+}
+
+
+NC_dim *
+elem_NC_dimarray(const NC_dimarray *ncap, size_t elem)
+{
+	assert(ncap != NULL);
+		/* cast needed for braindead systems with signed size_t */
+	if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
+		return NULL;
+
+	assert(ncap->value != NULL);
+
+	return ncap->value[elem];
+}
+
+
+/* Public */
+
+int
+nc_def_dim(int ncid, const char *name, size_t size, int *dimidp)
+{
+	int status;
+	NC *ncp;
+	int dimid;
+	NC_dim *dimp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(!NC_indef(ncp))
+		return NC_ENOTINDEFINE;
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) size > X_INT_MAX) /* Backward compat */
+		return NC_EINVAL;
+
+	if(size == NC_UNLIMITED)
+	{
+		dimid = find_NC_Udim(&ncp->dims, &dimp);
+		if(dimid != -1)
+		{
+			assert(dimid != -1);
+			return NC_EUNLIMIT;
+		}
+	}
+
+	if(ncp->dims.nelems >= NC_MAX_DIMS)
+		return NC_EMAXDIMS;
+
+	dimid = NC_finddim(&ncp->dims, name, &dimp);
+	if(dimid != -1)
+		return NC_ENAMEINUSE;
+	
+	dimp = new_NC_dim(name, size);
+	if(dimp == NULL)
+		return NC_ENOMEM;
+	status = incr_NC_dimarray(&ncp->dims, dimp);
+	if(status != NC_NOERR)
+	{
+		free_NC_dim(dimp);
+		return status;
+	}
+
+	if(dimidp != NULL)
+		*dimidp = (int)ncp->dims.nelems -1;
+	return NC_NOERR;
+}
+
+
+int
+nc_inq_dimid(int ncid, const char *name, int *dimid_ptr)
+{
+	int status;
+	NC *ncp;
+	int dimid;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	dimid = NC_finddim(&ncp->dims, name, NULL);
+
+	if(dimid == -1)
+		return NC_EBADDIM;
+
+	*dimid_ptr = dimid;
+	return NC_NOERR;
+}
+
+
+int
+nc_inq_dim(int ncid, int dimid, char *name, size_t *sizep)
+{
+	int status;
+	NC *ncp;
+	NC_dim *dimp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
+	if(dimp == NULL)
+		return NC_EBADDIM;
+
+	if(name != NULL)
+	{
+		(void)strncpy(name, dimp->name->cp, 
+			dimp->name->nchars);
+		name[dimp->name->nchars] = 0;
+	}
+	if(sizep != 0)
+	{
+		if(dimp->size == NC_UNLIMITED)
+			*sizep = NC_get_numrecs(ncp);
+		else
+			*sizep = dimp->size;	
+	}
+	return NC_NOERR;
+}
+
+
+int 
+nc_inq_dimname(int ncid, int dimid, char *name)
+{
+	int status;
+	NC *ncp;
+	NC_dim *dimp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
+	if(dimp == NULL)
+		return NC_EBADDIM;
+
+	if(name != NULL)
+	{
+		(void)strncpy(name, dimp->name->cp, 
+			dimp->name->nchars);
+		name[dimp->name->nchars] = 0;
+	}
+
+	return NC_NOERR;
+}
+
+
+int 
+nc_inq_dimlen(int ncid, int dimid, size_t *lenp)
+{
+	int status;
+	NC *ncp;
+	NC_dim *dimp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
+	if(dimp == NULL)
+		return NC_EBADDIM;
+
+	if(lenp != 0)
+	{
+		if(dimp->size == NC_UNLIMITED)
+			*lenp = NC_get_numrecs(ncp);
+		else
+			*lenp = dimp->size;	
+	}
+	return NC_NOERR;
+}
+
+
+int
+nc_rename_dim( int ncid, int dimid, const char *newname)
+{
+	int status;
+	NC *ncp;
+	int existid;
+	NC_dim *dimp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	status = NC_check_name(newname);
+	if(status != NC_NOERR)
+		return status;
+
+	existid = NC_finddim(&ncp->dims, newname, &dimp);
+	if(existid != -1)
+		return NC_ENAMEINUSE;
+
+	dimp = elem_NC_dimarray(&ncp->dims, (size_t)dimid);
+	if(dimp == NULL)
+		return NC_EBADDIM;
+
+	if(NC_indef(ncp))
+	{
+		NC_string *old = dimp->name;
+		NC_string *newStr = new_NC_string(strlen(newname), newname);
+		if(newStr == NULL)
+			return NC_ENOMEM;
+		dimp->name = newStr;
+		free_NC_string(old);
+		return NC_NOERR;
+	}
+
+	/* else, not in define mode */
+
+	status = set_NC_string(dimp->name, newname);
+	if(status != NC_NOERR)
+		return status;
+
+	set_NC_hdirty(ncp);
+
+	if(NC_doHsync(ncp))
+	{
+		status = NC_sync(ncp);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return NC_NOERR;
+}
Index: /branches/SDM_SciDAC/src/lib/ncconfig.in
===================================================================
--- /branches/SDM_SciDAC/src/lib/ncconfig.in (revision 2)
+++ /branches/SDM_SciDAC/src/lib/ncconfig.in (revision 2)
@@ -0,0 +1,81 @@
+/* libsrc/ncconfig.in.  Generated automatically from configure.in by autoheader.  */
+/* $Id$ */
+#ifndef _NCCONFIG_H_
+#define _NCCONFIG_H_
+
+/* Define if you're on an HP-UX system. */
+#undef _HPUX_SOURCE
+
+/* Define if type char is unsigned and you are not using gcc.  */
+#ifndef __CHAR_UNSIGNED__
+#undef __CHAR_UNSIGNED__
+#endif
+
+/* Define if your struct stat has st_blksize.  */
+#undef HAVE_ST_BLKSIZE
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+#undef off_t
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+#undef size_t
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+#undef WORDS_BIGENDIAN
+
+/* Define if you don't have the <stdlib.h>.  */
+#undef NO_STDLIB_H
+
+/* Define if you don't have the <sys/types.h>.  */
+#undef NO_SYS_TYPES_H
+
+/* Define if you have the ftruncate function  */
+#undef HAVE_FTRUNCATE
+
+/* Define if you have alloca, as a function or macro.  */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#undef HAVE_ALLOCA_H
+
+/* Define if you don't have the strerror function  */
+#undef NO_STRERROR
+
+/* The number of bytes in a size_t */
+#undef SIZEOF_SIZE_T
+
+/* The number of bytes in a off_t */
+#undef SIZEOF_OFF_T
+
+/* Define to `int' if system doesn't define.  */
+#undef ssize_t
+
+/* Define to `int' if system doesn't define.  */
+#undef ptrdiff_t
+
+/* Define to `unsigned char' if system doesn't define.  */
+#undef uchar
+
+/* Define if the system does not use IEEE floating point representation */
+#undef NO_IEEE_FLOAT
+
+/* The number of bytes in a double.  */
+#undef SIZEOF_DOUBLE
+
+/* The number of bytes in a float.  */
+#undef SIZEOF_FLOAT
+
+/* The number of bytes in a int.  */
+#undef SIZEOF_INT
+
+/* The number of bytes in a long.  */
+#undef SIZEOF_LONG
+
+/* The number of bytes in a short.  */
+#undef SIZEOF_SHORT
+
+#endif /* !_NCCONFIG_H_ */
Index: /branches/SDM_SciDAC/src/lib/attr.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/attr.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/attr.c (revision 2)
@@ -0,0 +1,2253 @@
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "nc.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ncx.h"
+#include "fbits.h"
+#include "rnd.h"
+
+
+/*
+ * Free attr
+ * Formerly
+NC_free_attr()
+ */
+void
+free_NC_attr(NC_attr *attrp)
+{
+
+	if(attrp == NULL)
+		return;
+	free_NC_string(attrp->name);
+	free(attrp);
+}
+
+
+/*
+ * How much space will 'nelems' of 'type' take in
+ *  external representation (as the values of an attribute)?
+ */
+static size_t
+ncx_len_NC_attrV(nc_type type, size_t nelems)
+{
+	switch(type) {
+	case NC_BYTE:
+	case NC_CHAR:
+		return ncx_len_char(nelems);
+	case NC_SHORT:
+		return ncx_len_short(nelems);
+	case NC_INT:
+		return ncx_len_int(nelems);
+	case NC_FLOAT:
+		return ncx_len_float(nelems);
+	case NC_DOUBLE:
+		return ncx_len_double(nelems);
+	}
+	/* default */
+	assert("ncx_len_NC_attr bad type" == 0);
+	return 0;
+}
+
+
+NC_attr *
+new_x_NC_attr(
+	NC_string *strp,
+	nc_type type,
+	size_t nelems)
+{
+	NC_attr *attrp;
+	const size_t xsz = ncx_len_NC_attrV(type, nelems);
+	size_t sz = M_RNDUP(sizeof(NC_attr));
+
+	assert(!(xsz == 0 && nelems != 0));
+
+	sz += xsz;
+
+	attrp = (NC_attr *) malloc(sz);
+	if(attrp == NULL )
+		return NULL;
+
+	attrp->xsz = xsz;
+
+	attrp->name = strp;
+	attrp->type = type;
+	attrp->nelems = nelems;
+	if(xsz != 0)
+		attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
+	else
+		attrp->xvalue = NULL;
+
+	return(attrp);
+}
+
+
+/*
+ * Formerly
+NC_new_attr(name,type,count,value)
+ */
+static NC_attr *
+new_NC_attr(
+	const char *name,
+	nc_type type,
+	size_t nelems)
+{
+	NC_string *strp;
+	NC_attr *attrp;
+
+	assert(name != NULL && *name != 0);
+
+	strp = new_NC_string(strlen(name), name);
+	if(strp == NULL)
+		return NULL;
+	
+	attrp = new_x_NC_attr(strp, type, nelems);
+	if(attrp == NULL)
+	{
+		free_NC_string(strp);
+		return NULL;
+	}
+
+	return(attrp);
+}
+
+
+static NC_attr *
+dup_NC_attr(const NC_attr *rattrp)
+{
+	NC_attr *attrp = new_NC_attr(rattrp->name->cp,
+		 rattrp->type, rattrp->nelems);
+	if(attrp == NULL)
+		return NULL;
+	(void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
+	return attrp;
+}
+
+/* attrarray */
+
+/*
+ * Free the stuff "in" (referred to by) an NC_attrarray.
+ * Leaves the array itself allocated.
+ */
+void
+free_NC_attrarrayV0(NC_attrarray *ncap)
+{
+	assert(ncap != NULL);
+
+	if(ncap->nelems == 0)
+		return;
+
+	assert(ncap->value != NULL);
+
+	{
+		NC_attr **app = ncap->value;
+		NC_attr *const *const end = &app[ncap->nelems];
+		for( /*NADA*/; app < end; app++)
+		{
+			free_NC_attr(*app);
+			*app = NULL;
+		}
+	}
+	ncap->nelems = 0;
+}
+
+
+/*
+ * Free NC_attrarray values.
+ * formerly
+NC_free_array()
+ */
+void
+free_NC_attrarrayV(NC_attrarray *ncap)
+{
+	assert(ncap != NULL);
+	
+	if(ncap->nalloc == 0)
+		return;
+
+	assert(ncap->value != NULL);
+
+	free_NC_attrarrayV0(ncap);
+
+	free(ncap->value);
+	ncap->value = NULL;
+	ncap->nalloc = 0;
+}
+
+
+int
+dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref)
+{
+	int status = NC_NOERR;
+
+	assert(ref != NULL);
+	assert(ncap != NULL);
+
+	if(ref->nelems != 0)
+	{
+		const size_t sz = ref->nelems * sizeof(NC_attr *);
+		ncap->value = (NC_attr **) malloc(sz);
+		if(ncap->value == NULL)
+			return NC_ENOMEM;
+
+		(void) memset(ncap->value, 0, sz);
+		ncap->nalloc = ref->nelems;
+	}
+
+	ncap->nelems = 0;
+	{
+		NC_attr **app = ncap->value;
+		const NC_attr **drpp = (const NC_attr **)ref->value;
+		NC_attr *const *const end = &app[ref->nelems];
+		for( /*NADA*/; app < end; drpp++, app++, ncap->nelems++)
+		{
+			*app = dup_NC_attr(*drpp);
+			if(*app == NULL)
+			{
+				status = NC_ENOMEM;
+				break;
+			}
+		}
+	}
+
+	if(status != NC_NOERR)
+	{
+		free_NC_attrarrayV(ncap);
+		return status;
+	}
+
+	assert(ncap->nelems == ref->nelems);
+
+	return NC_NOERR;
+}
+
+
+/*
+ * Add a new handle on the end of an array of handles
+ * Formerly
+NC_incr_array(array, tail)
+ */
+static int
+incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp)
+{
+	NC_attr **vp;
+
+	assert(ncap != NULL);
+
+	if(ncap->nalloc == 0)
+	{
+		assert(ncap->nelems == 0);
+		vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *));
+		if(vp == NULL)
+			return NC_ENOMEM;
+
+		ncap->value = vp;
+		ncap->nalloc = NC_ARRAY_GROWBY;
+	}
+	else if(ncap->nelems +1 > ncap->nalloc)
+	{
+		vp = (NC_attr **) realloc(ncap->value,
+			(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *));
+		if(vp == NULL)
+			return NC_ENOMEM;
+	
+		ncap->value = vp;
+		ncap->nalloc += NC_ARRAY_GROWBY;
+	}
+
+	if(newelemp != NULL)
+	{
+		ncap->value[ncap->nelems] = newelemp;
+		ncap->nelems++;
+	}
+	return NC_NOERR;
+}
+
+
+NC_attr *
+elem_NC_attrarray(const NC_attrarray *ncap, size_t elem)
+{
+	assert(ncap != NULL);
+		/* cast needed for braindead systems with signed size_t */
+	if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
+		return NULL;
+
+	assert(ncap->value != NULL);
+
+	return ncap->value[elem];
+}
+
+/* End attarray per se */
+
+/*
+ * Given ncp and varid, return ptr to array of attributes
+ *  else NULL on error
+ */
+static NC_attrarray *
+NC_attrarray0( NC *ncp, int varid)
+{
+	NC_attrarray *ap;
+
+	if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */
+	{
+		ap = &ncp->attrs;
+	}
+	else if(varid >= 0 && (size_t) varid < ncp->vars.nelems)
+	{
+		NC_var **vpp;
+		vpp = (NC_var **)ncp->vars.value;
+		vpp += varid;
+		ap = &(*vpp)->attrs;
+	} else {
+		ap = NULL;
+	}
+	return(ap);
+}
+
+
+/*
+ * Step thru NC_ATTRIBUTE array, seeking match on name.
+ *  return match or NULL if Not Found.
+ */
+NC_attr **
+NC_findattr(const NC_attrarray *ncap, const char *name)
+{
+	NC_attr **attrpp;
+	size_t attrid;
+	size_t slen;
+
+	assert(ncap != NULL);
+
+	if(ncap->nelems == 0)
+		return NULL;
+
+	attrpp = (NC_attr **) ncap->value;
+
+	slen = strlen(name);
+
+	for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++)
+	{
+		if(strlen((*attrpp)->name->cp) == slen &&
+			strncmp((*attrpp)->name->cp, name, slen) == 0)
+		{
+			return(attrpp); /* Normal return */
+		}
+	}
+	return(NULL);
+}
+
+
+/*
+ * Look up by ncid, varid and name, return NULL if not found
+ */
+static int 
+NC_lookupattr(int ncid,
+	int varid,
+	const char *name, /* attribute name */
+	NC_attr **attrpp) /* modified on return */
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **tmp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	tmp = NC_findattr(ncap, name);
+	if(tmp == NULL)
+		return NC_ENOTATT;
+
+	if(attrpp != NULL)
+		*attrpp = *tmp;
+
+	return ENOERR;
+}
+
+/* Public */
+
+int
+nc_inq_attname(int ncid, int varid, int attnum, char *name)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	attrp = elem_NC_attrarray(ncap, (size_t)attnum);
+	if(attrp == NULL)
+		return NC_ENOTATT;
+
+	(void) strncpy(name, attrp->name->cp, attrp->name->nchars);
+	name[attrp->name->nchars] = 0;
+
+	return NC_NOERR;
+}
+
+
+int 
+nc_inq_attid(int ncid, int varid, const char *name, int *attnump)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+	
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp == NULL)
+		return NC_ENOTATT;
+
+	if(attnump != NULL)
+		*attnump = (int)(attrpp - ncap->value);
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_atttype(int ncid, int varid, const char *name, nc_type *datatypep)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(datatypep != NULL)
+		*datatypep = attrp->type;
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_attlen(int ncid, int varid, const char *name, size_t *lenp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(lenp != NULL)
+		*lenp = attrp->nelems;
+
+	return NC_NOERR;
+}
+
+int
+nc_inq_att(int ncid,
+	int varid,
+	const char *name, /* input, attribute name */
+	nc_type *datatypep,
+	size_t *lenp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(datatypep != NULL)
+		*datatypep = attrp->type;
+	if(lenp != NULL)
+		*lenp = attrp->nelems;
+
+	return NC_NOERR;
+}
+
+
+int
+nc_rename_att( int ncid, int varid, const char *name, const char *newname)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **tmp;
+	NC_attr *attrp;
+	NC_string *newStr, *old;
+
+			/* sortof inline clone of NC_lookupattr() */
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+/* bugs found by Jianwei Li
+	status = NC_check_name(name);
+*/
+	status = NC_check_name(newname);
+	if(status != NC_NOERR)
+		return status;
+
+	tmp = NC_findattr(ncap, name);
+	if(tmp == NULL)
+		return NC_ENOTATT;
+	attrp = *tmp;
+			/* end inline clone NC_lookupattr() */
+
+	if(NC_findattr(ncap, newname) != NULL)
+	{
+		/* name in use */
+		return NC_ENAMEINUSE;
+	}
+
+	old = attrp->name;
+	if(NC_indef(ncp))
+	{
+		newStr = new_NC_string(strlen(newname), newname);
+		if( newStr == NULL)
+			return NC_ENOMEM;
+		attrp->name = newStr;
+		free_NC_string(old);
+		return NC_NOERR;
+	}
+	/* else */
+	status = set_NC_string(old, newname);
+	if( status != NC_NOERR)
+		return status;
+
+	set_NC_hdirty(ncp);
+
+	if(NC_doHsync(ncp))
+	{
+		status = NC_sync(ncp);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return NC_NOERR;
+}
+
+
+int
+nc_copy_att(int ncid_in, int varid_in, const char *name, int ncid_out, int ovarid)
+{
+	int status;
+	NC_attr *iattrp;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid_in, varid_in, name, &iattrp);
+	if(status != NC_NOERR)
+		return status;
+
+	status = NC_check_id(ncid_out, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, ovarid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			attrp = *attrpp; /* convenience */
+	
+			if(iattrp->xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = iattrp->xsz;
+			attrp->type = iattrp->type;
+			attrp->nelems = iattrp->nelems;
+
+			(void) memcpy(attrp->xvalue, iattrp->xvalue,
+				iattrp->xsz);
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				status = NC_sync(ncp);
+				if(status != NC_NOERR)
+					return status;
+			}
+
+			return NC_NOERR;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	attrp = new_NC_attr(name, iattrp->type, iattrp->nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	(void) memcpy(attrp->xvalue, iattrp->xvalue,
+		iattrp->xsz);
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		status = incr_NC_attrarray(ncap, attrp);
+		if(status != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return status;
+		}
+	}
+
+	return NC_NOERR;
+}
+
+
+int
+nc_del_att(int ncid, int varid, const char *name)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	int attrid;
+	size_t slen;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(!NC_indef(ncp))
+		return NC_ENOTINDEFINE;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+			/* sortof inline NC_findattr() */
+	slen = strlen(name);
+
+	attrpp = (NC_attr **) ncap->value;
+	for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++)
+	{
+		if( slen == (*attrpp)->name->nchars &&
+			strncmp(name, (*attrpp)->name->cp, slen) == 0)
+		{
+			old = *attrpp;
+			break;
+		}
+	}
+	if( (size_t) attrid == ncap->nelems )
+		return NC_ENOTATT;
+			/* end inline NC_findattr() */
+
+	/* shuffle down */
+	for(attrid++; (size_t) attrid < ncap->nelems; attrid++)
+	{
+		*attrpp = *(attrpp + 1);
+		attrpp++;
+	}
+	*attrpp = NULL;
+	/* decrement count */
+	ncap->nelems--;
+
+	free_NC_attr(old);
+
+	return NC_NOERR;
+}
+
+
+static int
+ncx_pad_putn_Iuchar(void **xpp, size_t nelems, const uchar *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_putn_schar_uchar(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_putn_short_uchar(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_putn_int_uchar(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_putn_float_uchar(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_putn_double_uchar(xpp, nelems, tp);
+	}
+	assert("ncx_pad_putn_Iuchar invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+static int
+ncx_pad_getn_Iuchar(const void **xpp, size_t nelems, uchar *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_getn_schar_uchar(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_getn_short_uchar(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_getn_int_uchar(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_getn_float_uchar(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_getn_double_uchar(xpp, nelems, tp);
+	}
+	assert("ncx_pad_getn_Iuchar invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+
+static int
+ncx_pad_putn_Ischar(void **xpp, size_t nelems, const schar *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_putn_schar_schar(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_putn_short_schar(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_putn_int_schar(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_putn_float_schar(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_putn_double_schar(xpp, nelems, tp);
+	}
+	assert("ncx_pad_putn_Ischar invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+static int
+ncx_pad_getn_Ischar(const void **xpp, size_t nelems, schar *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_getn_schar_schar(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_getn_short_schar(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_getn_int_schar(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_getn_float_schar(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_getn_double_schar(xpp, nelems, tp);
+	}
+	assert("ncx_pad_getn_Ischar invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+
+static int
+ncx_pad_putn_Ishort(void **xpp, size_t nelems, const short *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_putn_schar_short(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_putn_short_short(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_putn_int_short(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_putn_float_short(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_putn_double_short(xpp, nelems, tp);
+	}
+	assert("ncx_pad_putn_Ishort invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+static int
+ncx_pad_getn_Ishort(const void **xpp, size_t nelems, short *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_getn_schar_short(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_getn_short_short(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_getn_int_short(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_getn_float_short(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_getn_double_short(xpp, nelems, tp);
+	}
+	assert("ncx_pad_getn_Ishort invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+
+static int
+ncx_pad_putn_Iint(void **xpp, size_t nelems, const int *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_putn_schar_int(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_putn_short_int(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_putn_int_int(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_putn_float_int(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_putn_double_int(xpp, nelems, tp);
+	}
+	assert("ncx_pad_putn_Iint invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+static int
+ncx_pad_getn_Iint(const void **xpp, size_t nelems, int *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_getn_schar_int(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_getn_short_int(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_getn_int_int(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_getn_float_int(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_getn_double_int(xpp, nelems, tp);
+	}
+	assert("ncx_pad_getn_Iint invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+
+static int
+ncx_pad_putn_Ilong(void **xpp, size_t nelems, const long *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_putn_schar_long(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_putn_short_long(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_putn_int_long(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_putn_float_long(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_putn_double_long(xpp, nelems, tp);
+	}
+	assert("ncx_pad_putn_Ilong invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+static int
+ncx_pad_getn_Ilong(const void **xpp, size_t nelems, long *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_getn_schar_long(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_getn_short_long(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_getn_int_long(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_getn_float_long(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_getn_double_long(xpp, nelems, tp);
+	}
+	assert("ncx_pad_getn_Ilong invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+
+static int
+ncx_pad_putn_Ifloat(void **xpp, size_t nelems, const float *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_putn_schar_float(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_putn_short_float(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_putn_int_float(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_putn_float_float(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_putn_double_float(xpp, nelems, tp);
+	}
+	assert("ncx_pad_putn_Ifloat invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+static int
+ncx_pad_getn_Ifloat(const void **xpp, size_t nelems, float *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_getn_schar_float(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_getn_short_float(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_getn_int_float(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_getn_float_float(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_getn_double_float(xpp, nelems, tp);
+	}
+	assert("ncx_pad_getn_Ifloat invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+
+static int
+ncx_pad_putn_Idouble(void **xpp, size_t nelems, const double *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_putn_schar_double(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_putn_short_double(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_putn_int_double(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_putn_float_double(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_putn_double_double(xpp, nelems, tp);
+	}
+	assert("ncx_pad_putn_Idouble invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+static int
+ncx_pad_getn_Idouble(const void **xpp, size_t nelems, double *tp, nc_type type)
+{
+	switch(type) {
+	case NC_CHAR:
+		return NC_ECHAR;
+	case NC_BYTE:
+		return ncx_pad_getn_schar_double(xpp, nelems, tp);
+	case NC_SHORT:
+		return ncx_pad_getn_short_double(xpp, nelems, tp);
+	case NC_INT:
+		return ncx_getn_int_double(xpp, nelems, tp);
+	case NC_FLOAT:
+		return ncx_getn_float_double(xpp, nelems, tp);
+	case NC_DOUBLE:
+		return ncx_getn_double_double(xpp, nelems, tp);
+	}
+	assert("ncx_pad_getn_Idouble invalid type" == 0);
+	return NC_EBADTYPE;
+}
+
+
+
+int
+nc_put_att_text(int ncid, int varid, const char *name,
+	size_t nelems, const char *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(NC_CHAR, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = NC_CHAR;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_text(&xp, nelems, value);
+				if(status != NC_NOERR)
+					return status;
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				status = NC_sync(ncp);
+				if(status != NC_NOERR)
+					return status;
+			}
+
+			return NC_NOERR;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	attrp = new_NC_attr(name, NC_CHAR, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_text(&xp, nelems, value);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		status = incr_NC_attrarray(ncap, attrp);
+		if(status != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return status;
+		}
+	}
+
+	return NC_NOERR;
+}
+
+
+int
+nc_get_att_text(int ncid, int varid, const char *name, char *str)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type != NC_CHAR)
+		return NC_ECHAR;
+
+	/* else */
+	{
+		const void *xp = attrp->xvalue;
+		return ncx_pad_getn_text(&xp, attrp->nelems, str);
+	}
+}
+
+
+
+
+int
+nc_put_att_schar(int ncid, int varid, const char *name,
+	nc_type type, size_t nelems, const signed char *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+	if(type == NC_CHAR)
+		return NC_ECHAR;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(type, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = type;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_Ischar(&xp, nelems,
+					value, type);
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				const int lstatus = NC_sync(ncp);
+				/*
+				 * N.B.: potentially overrides NC_ERANGE
+				 * set by ncx_pad_putn_Ischar
+				 */
+				if(lstatus != ENOERR)
+					return lstatus;
+			}
+
+			return status;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	attrp = new_NC_attr(name, type, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_Ischar(&xp, nelems,
+			value, type);
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		const int lstatus = incr_NC_attrarray(ncap, attrp);
+		/*
+		 * N.B.: potentially overrides NC_ERANGE
+		 * set by ncx_pad_putn_Ischar
+		 */
+		if(lstatus != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return lstatus;
+		}
+	}
+
+	return status;
+}
+
+int
+nc_get_att_schar(int ncid, int varid, const char *name, signed char *tp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	{
+	const void *xp = attrp->xvalue;
+	return ncx_pad_getn_Ischar(&xp, attrp->nelems, tp, attrp->type);
+	}
+}
+
+
+int
+nc_put_att_uchar(int ncid, int varid, const char *name,
+	nc_type type, size_t nelems, const unsigned char *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+	if(type == NC_CHAR)
+		return NC_ECHAR;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(type, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = type;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_Iuchar(&xp, nelems,
+					value, type);
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				const int lstatus = NC_sync(ncp);
+				/*
+				 * N.B.: potentially overrides NC_ERANGE
+				 * set by ncx_pad_putn_Iuchar
+				 */
+				if(lstatus != ENOERR)
+					return lstatus;
+			}
+
+			return status;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	attrp = new_NC_attr(name, type, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_Iuchar(&xp, nelems,
+			value, type);
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		const int lstatus = incr_NC_attrarray(ncap, attrp);
+		/*
+		 * N.B.: potentially overrides NC_ERANGE
+		 * set by ncx_pad_putn_Iuchar
+		 */
+		if(lstatus != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return lstatus;
+		}
+	}
+
+	return status;
+}
+
+int
+nc_get_att_uchar(int ncid, int varid, const char *name, unsigned char *tp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	{
+	const void *xp = attrp->xvalue;
+	return ncx_pad_getn_Iuchar(&xp, attrp->nelems, tp, attrp->type);
+	}
+}
+
+
+int
+nc_put_att_short(int ncid, int varid, const char *name,
+	nc_type type, size_t nelems, const short *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+	if(type == NC_CHAR)
+		return NC_ECHAR;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(type, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = type;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_Ishort(&xp, nelems,
+					value, type);
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				const int lstatus = NC_sync(ncp);
+				/*
+				 * N.B.: potentially overrides NC_ERANGE
+				 * set by ncx_pad_putn_Ishort
+				 */
+				if(lstatus != ENOERR)
+					return lstatus;
+			}
+
+			return status;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	attrp = new_NC_attr(name, type, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_Ishort(&xp, nelems,
+			value, type);
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		const int lstatus = incr_NC_attrarray(ncap, attrp);
+		/*
+		 * N.B.: potentially overrides NC_ERANGE
+		 * set by ncx_pad_putn_Ishort
+		 */
+		if(lstatus != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return lstatus;
+		}
+	}
+
+	return status;
+}
+
+int
+nc_get_att_short(int ncid, int varid, const char *name, short *tp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	{
+	const void *xp = attrp->xvalue;
+	return ncx_pad_getn_Ishort(&xp, attrp->nelems, tp, attrp->type);
+	}
+}
+
+
+int
+nc_put_att_int(int ncid, int varid, const char *name,
+	nc_type type, size_t nelems, const int *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+	if(type == NC_CHAR)
+		return NC_ECHAR;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(type, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = type;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_Iint(&xp, nelems,
+					value, type);
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				const int lstatus = NC_sync(ncp);
+				/*
+				 * N.B.: potentially overrides NC_ERANGE
+				 * set by ncx_pad_putn_Iint
+				 */
+				if(lstatus != ENOERR)
+					return lstatus;
+			}
+
+			return status;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	attrp = new_NC_attr(name, type, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_Iint(&xp, nelems,
+			value, type);
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		const int lstatus = incr_NC_attrarray(ncap, attrp);
+		/*
+		 * N.B.: potentially overrides NC_ERANGE
+		 * set by ncx_pad_putn_Iint
+		 */
+		if(lstatus != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return lstatus;
+		}
+	}
+
+	return status;
+}
+
+int
+nc_get_att_int(int ncid, int varid, const char *name, int *tp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	{
+	const void *xp = attrp->xvalue;
+	return ncx_pad_getn_Iint(&xp, attrp->nelems, tp, attrp->type);
+	}
+}
+
+
+int
+nc_put_att_long(int ncid, int varid, const char *name,
+	nc_type type, size_t nelems, const long *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+	if(type == NC_CHAR)
+		return NC_ECHAR;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(type, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = type;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_Ilong(&xp, nelems,
+					value, type);
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				const int lstatus = NC_sync(ncp);
+				/*
+				 * N.B.: potentially overrides NC_ERANGE
+				 * set by ncx_pad_putn_Ilong
+				 */
+				if(lstatus != ENOERR)
+					return lstatus;
+			}
+
+			return status;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	attrp = new_NC_attr(name, type, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_Ilong(&xp, nelems,
+			value, type);
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		const int lstatus = incr_NC_attrarray(ncap, attrp);
+		/*
+		 * N.B.: potentially overrides NC_ERANGE
+		 * set by ncx_pad_putn_Ilong
+		 */
+		if(lstatus != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return lstatus;
+		}
+	}
+
+	return status;
+}
+
+int
+nc_get_att_long(int ncid, int varid, const char *name, long *tp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	{
+	const void *xp = attrp->xvalue;
+	return ncx_pad_getn_Ilong(&xp, attrp->nelems, tp, attrp->type);
+	}
+}
+
+
+int
+nc_put_att_float(int ncid, int varid, const char *name,
+	nc_type type, size_t nelems, const float *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+	if(type == NC_CHAR)
+		return NC_ECHAR;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(type, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = type;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_Ifloat(&xp, nelems,
+					value, type);
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				const int lstatus = NC_sync(ncp);
+				/*
+				 * N.B.: potentially overrides NC_ERANGE
+				 * set by ncx_pad_putn_Ifloat
+				 */
+				if(lstatus != ENOERR)
+					return lstatus;
+			}
+
+			return status;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	attrp = new_NC_attr(name, type, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_Ifloat(&xp, nelems,
+			value, type);
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		const int lstatus = incr_NC_attrarray(ncap, attrp);
+		/*
+		 * N.B.: potentially overrides NC_ERANGE
+		 * set by ncx_pad_putn_Ifloat
+		 */
+		if(lstatus != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return lstatus;
+		}
+	}
+
+	return status;
+}
+
+int
+nc_get_att_float(int ncid, int varid, const char *name, float *tp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	{
+	const void *xp = attrp->xvalue;
+	return ncx_pad_getn_Ifloat(&xp, attrp->nelems, tp, attrp->type);
+	}
+}
+
+
+int
+nc_put_att_double(int ncid, int varid, const char *name,
+	nc_type type, size_t nelems, const double *value)
+{
+	int status;
+	NC *ncp;
+	NC_attrarray *ncap;
+	NC_attr **attrpp;
+	NC_attr *old = NULL;
+	NC_attr *attrp;
+
+	status = NC_check_id(ncid, &ncp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+		return NC_EPERM;
+
+	ncap = NC_attrarray0(ncp, varid);
+	if(ncap == NULL)
+		return NC_ENOTVAR;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+	if(type == NC_CHAR)
+		return NC_ECHAR;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) nelems > X_INT_MAX) /* backward compat */
+		return NC_EINVAL; /* Invalid nelems */
+
+	if(nelems != 0 && value == NULL)
+		return NC_EINVAL; /* Null arg */
+
+	attrpp = NC_findattr(ncap, name);
+	if(attrpp != NULL) /* name in use */
+	{
+		if(!NC_indef(ncp) )
+		{
+			const size_t xsz = ncx_len_NC_attrV(type, nelems);
+			attrp = *attrpp; /* convenience */
+	
+			if(xsz > attrp->xsz)
+				return NC_ENOTINDEFINE;
+			/* else, we can reuse existing without redef */
+			
+			attrp->xsz = xsz;
+			attrp->type = type;
+			attrp->nelems = nelems;
+
+			if(nelems != 0)
+			{
+				void *xp = attrp->xvalue;
+				status = ncx_pad_putn_Idouble(&xp, nelems,
+					value, type);
+			}
+			
+			set_NC_hdirty(ncp);
+
+			if(NC_doHsync(ncp))
+			{
+				const int lstatus = NC_sync(ncp);
+				/*
+				 * N.B.: potentially overrides NC_ERANGE
+				 * set by ncx_pad_putn_Idouble
+				 */
+				if(lstatus != ENOERR)
+					return lstatus;
+			}
+
+			return status;
+		}
+		/* else, redefine using existing array slot */
+		old = *attrpp;
+	} 
+	else
+	{
+		if(!NC_indef(ncp))
+			return NC_ENOTINDEFINE;
+
+		if(ncap->nelems >= NC_MAX_ATTRS)
+			return NC_EMAXATTS;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	attrp = new_NC_attr(name, type, nelems);
+	if(attrp == NULL)
+		return NC_ENOMEM;
+
+	if(nelems != 0)
+	{
+		void *xp = attrp->xvalue;
+		status = ncx_pad_putn_Idouble(&xp, nelems,
+			value, type);
+	}
+
+	if(attrpp != NULL)
+	{
+		assert(old != NULL);
+		*attrpp = attrp;
+		free_NC_attr(old);
+	}
+	else
+	{
+		const int lstatus = incr_NC_attrarray(ncap, attrp);
+		/*
+		 * N.B.: potentially overrides NC_ERANGE
+		 * set by ncx_pad_putn_Idouble
+		 */
+		if(lstatus != NC_NOERR)
+		{
+			free_NC_attr(attrp);
+			return lstatus;
+		}
+	}
+
+	return status;
+}
+
+int
+nc_get_att_double(int ncid, int varid, const char *name, double *tp)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	if(attrp->nelems == 0)
+		return NC_NOERR;
+
+	if(attrp->type == NC_CHAR)
+		return NC_ECHAR;
+
+	{
+	const void *xp = attrp->xvalue;
+	return ncx_pad_getn_Idouble(&xp, attrp->nelems, tp, attrp->type);
+	}
+}
+
+
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_put_att(
+	int ncid,
+	int varid,
+	const char *name,
+	nc_type type,
+	size_t nelems,
+	const void *value)
+{
+	switch (type) {
+	case NC_BYTE:
+		return nc_put_att_schar(ncid, varid, name, type, nelems,
+			(schar *)value);
+	case NC_CHAR:
+		return nc_put_att_text(ncid, varid, name, nelems,
+			(char *)value);
+	case NC_SHORT:
+		return nc_put_att_short(ncid, varid, name, type, nelems,
+			(short *)value);
+	case NC_INT:
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+		return nc_put_att_int(ncid, varid, name, type, nelems,
+			(int *)value);
+#elif SIZEOF_LONG == X_SIZEOF_INT
+		return nc_put_att_long(ncid, varid, name, type, nelems,
+			(long *)value);
+#endif
+	case NC_FLOAT:
+		return nc_put_att_float(ncid, varid, name, type, nelems,
+			(float *)value);
+	case NC_DOUBLE:
+		return nc_put_att_double(ncid, varid, name, type, nelems,
+			(double *)value);
+	}
+	return NC_EBADTYPE;
+}
+
+
+/* deprecated, used to support the 2.x interface */
+int
+nc_get_att(int ncid, int varid, const char *name, void *value)
+{
+	int status;
+	NC_attr *attrp;
+
+	status = NC_lookupattr(ncid, varid, name, &attrp);
+	if(status != NC_NOERR)
+		return status;
+
+	switch (attrp->type) {
+	case NC_BYTE:
+		return nc_get_att_schar(ncid, varid, name,
+			(schar *)value);
+	case NC_CHAR:
+		return nc_get_att_text(ncid, varid, name,
+			(char *)value);
+	case NC_SHORT:
+		return nc_get_att_short(ncid, varid, name,
+			(short *)value);
+	case NC_INT:
+#if (SIZEOF_INT >= X_SIZEOF_INT)
+		return nc_get_att_int(ncid, varid, name,
+			(int *)value);
+#elif SIZEOF_LONG == X_SIZEOF_INT
+		return nc_get_att_long(ncid, varid, name,
+			(long *)value);
+#endif
+	case NC_FLOAT:
+		return nc_get_att_float(ncid, varid, name,
+			(float *)value);
+	case NC_DOUBLE:
+		return nc_get_att_double(ncid, varid, name,
+			(double *)value);
+	}
+	return NC_EBADTYPE;
+}
Index: /branches/SDM_SciDAC/src/lib/fbits.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/fbits.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/fbits.h (revision 2)
@@ -0,0 +1,26 @@
+/*
+ *   Copyright 1995, University Corporation for Atmospheric Research
+ *   See top level COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#ifndef _FBITS_H_
+#define _FBITS_H_
+
+/*
+ * Macros for dealing with flag bits.
+ */
+#define fSet(t, f)       ((t) |= (f))
+#define fClr(t, f)       ((t) &= ~(f))
+#define fIsSet(t, f)     ((t) & (f))
+#define fMask(t, f)     ((t) & ~(f))
+
+/*
+ * Propositions
+ */
+/* a implies b */
+#define pIf(a,b) (!(a) || (b))
+/* a if and only if b, use == when it makes sense */
+#define pIff(a,b) (((a) && (b)) || (!(a) && !(b)))
+
+#endif /*!FBITS_H_*/
Index: /branches/SDM_SciDAC/src/lib/mpinetcdf.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/mpinetcdf.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/mpinetcdf.h (revision 2)
@@ -0,0 +1,94 @@
+#include <mpi.h>
+#include "nc.h"
+
+int
+ncmpi_create(MPI_Comm comm, const char *path, int cmode, MPI_Info info, int *ncidp);
+
+int
+ncmpi_open(MPI_Comm comm, const char *path, int omode, MPI_Info info, int *ncidp);
+
+
+int
+ncmpi_enddef(int ncid);
+
+
+
+int
+ncmpi_close(int ncid);
+
+/* Begin _dim */
+
+
+/* End _dim */
+/* Begin {put,get}_att */
+
+
+/* End {put,get}_att */
+/* Begin _var */
+
+
+/* End _var */
+/* Begin {put,get}_vara */
+
+int
+ncmpi_put_vara_int_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const int *op);
+
+int
+ncmpi_put_vara_int(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const int *op);
+
+int
+ncmpi_put_vara_float_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const float *op);
+
+int
+ncmpi_put_vara_float(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const float *op);
+
+int
+ncmpi_put_vara_double_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    const double *op);
+
+int
+ncmpi_put_vara_double(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                const double *op);
+
+int
+ncmpi_get_vara_int_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    int *ip);
+
+int
+ncmpi_get_vara_int(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                int *ip);
+
+int
+ncmpi_get_vara_float_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    float *ip);
+
+int
+ncmpi_get_vara_float(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                float *ip);
+
+int
+ncmpi_get_vara_double_all(int ncid, int varid,
+                    const size_t start[], const size_t count[],
+                    double *ip);
+
+int
+ncmpi_get_vara_double(int ncid, int varid,
+                const size_t start[], const size_t count[],
+                double *ip);
+
+
+/* End {put,get}_vara */
Index: /branches/SDM_SciDAC/src/lib/depend
===================================================================
--- /branches/SDM_SciDAC/src/lib/depend (revision 2)
+++ /branches/SDM_SciDAC/src/lib/depend (revision 2)
@@ -0,0 +1,50 @@
+validator: validator.c
+header.o: header.c
+header.o: nc.h
+header.o: ncx.h
+mpincio.o: mpincio.c
+mpincio.o: ncio.h
+mpincio.o: ncconfig.h
+mpincio.o: fbits.h
+mpincio.o: rnd.h
+mpinetcdf.o: mpinetcdf.c
+mpinetcdf.o: nc.h
+mpinetcdf.o: ncx.h
+attr.o: attr.c
+attr.o: fbits.h
+attr.o: nc.h
+attr.o: ncconfig.h
+attr.o: ncio.h
+attr.o: ncx.h
+attr.o: netcdf.h
+attr.o: rnd.h
+dim.o: dim.c
+dim.o: fbits.h
+dim.o: nc.h
+dim.o: ncconfig.h
+dim.o: ncio.h
+dim.o: ncx.h
+dim.o: netcdf.h
+dim.o: rnd.h
+error.o: error.c
+error.o: netcdf.h
+nc.o: fbits.h
+nc.o: nc.c
+nc.o: nc.h
+nc.o: ncconfig.h
+nc.o: ncio.h
+nc.o: ncx.h
+nc.o: netcdf.h
+nc.o: rnd.h
+ncx.o: ncconfig.h
+ncx.o: ncx.c
+ncx.o: ncx.h
+ncx.o: rnd.h
+var.o: fbits.h
+var.o: nc.h
+var.o: ncconfig.h
+var.o: ncio.h
+var.o: ncx.h
+var.o: netcdf.h
+var.o: rnd.h
+var.o: var.c
Index: /branches/SDM_SciDAC/src/lib/ffio.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/ffio.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/ffio.c (revision 2)
@@ -0,0 +1,743 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+/* addition by O. Heudecker, AWI-Bremerhaven, 12.3.1998 */
+/* added correction by John Sheldon and Hans Vahlenkamp 15.4.1998*/
+
+#include "ncconfig.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>	/* DEBUG */
+#include <errno.h>
+#ifndef ENOERR
+#define ENOERR 0
+#endif
+#include <fcntl.h>
+#include <ffio.h>
+#include <unistd.h>
+#include <string.h>
+/* Insertion by O. R. Heudecker, AWI-Bremerhaven 12.3.98 (1 line)*/
+#include <fortran.h>
+
+#include "ncio.h"
+#include "fbits.h"
+#include "rnd.h"
+
+#if !defined(NDEBUG) && !defined(X_INT_MAX)
+#define  X_INT_MAX 2147483647
+#endif
+#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */
+#define  X_ALIGN 4
+#endif
+
+#define ALWAYS_NC_SHARE 0 /* DEBUG */
+
+/* Begin OS */
+
+/*
+ * What is the preferred I/O block size?
+ * (This becomes the default *sizehint == ncp->chunk in the higher layers.)
+ * TODO: What is the the best answer here?
+ */
+static size_t
+blksize(int fd)
+{
+	struct ffc_stat_s sb;
+	struct ffsw sw;
+	if (fffcntl(fd, FC_STAT, &sb, &sw) > -1)
+	{
+		if(sb.st_oblksize > 0)
+			return (size_t) sb.st_oblksize;
+	}
+	/* else, silent in the face of error */
+	return (size_t) 32768;
+}
+
+/*
+ * Sortof like ftruncate, except won't make the
+ * file shorter.
+ */
+static int
+fgrow(const int fd, const off_t len)
+{
+	struct ffc_stat_s sb;
+	struct ffsw sw;
+	if (fffcntl(fd, FC_STAT, &sb, &sw) < 0)
+		return errno;
+	if (len < sb.st_size)
+		return ENOERR;
+	{
+		const long dumb = 0;
+			/* cache current position */
+		const off_t pos = ffseek(fd, 0, SEEK_CUR);
+		if(pos < 0)
+			return errno;
+		if (ffseek(fd, len-sizeof(dumb), SEEK_SET) < 0)
+			return errno;
+		if(ffwrite(fd, (void *)&dumb, sizeof(dumb)) < 0)
+			return errno;
+		if (ffseek(fd, pos, SEEK_SET) < 0)
+			return errno;
+	}
+	/* else */
+	return ENOERR;
+}
+
+/* End OS */
+/* Begin ffio */
+
+static int
+ffio_pgout(ncio *const nciop, 
+	off_t const offset,  const size_t extent,
+	const void *const vp, off_t *posp)
+{
+#ifdef X_ALIGN
+	assert(offset % X_ALIGN == 0);
+	assert(extent % X_ALIGN == 0);
+#endif
+
+	if(*posp != offset)
+	{
+		if(ffseek(nciop->fd, offset, SEEK_SET) != offset)
+		{
+			return errno;
+		}
+		*posp = offset;
+	}
+	if(ffwrite(nciop->fd, vp, extent) != extent)
+	{
+		return errno;
+	}
+	*posp += extent;
+
+	return ENOERR;
+}
+
+
+static int
+ffio_pgin(ncio *const nciop,
+	off_t const offset, const size_t extent,
+	void *const vp, size_t *nreadp, off_t *posp)
+{
+	int status;
+	ssize_t nread;
+
+#ifdef X_ALIGN
+	assert(offset % X_ALIGN == 0);
+	assert(extent % X_ALIGN == 0);
+#endif
+
+	if(*posp != offset)
+	{
+		if(ffseek(nciop->fd, offset, SEEK_SET) != offset)
+		{
+			status = errno;
+			return status;
+		}
+		*posp = offset;
+	}
+
+	errno = 0;
+	nread = ffread(nciop->fd, vp, extent);
+	if(nread != extent)
+	{
+		status = errno;
+		if(nread == -1 || status != ENOERR)
+			return status;
+		/* else it's okay we read 0. */
+	}
+	*nreadp = nread;
+	*posp += nread;
+
+	return ENOERR;
+}
+
+/* */
+
+typedef struct ncio_ffio {
+	off_t pos;
+	/* buffer */
+	off_t	bf_offset; 
+	size_t	bf_extent;
+	size_t	bf_cnt;
+	void	*bf_base;
+} ncio_ffio;
+
+
+static int
+ncio_ffio_rel(ncio *const nciop, off_t offset, int rflags)
+{
+	ncio_ffio *ffp = (ncio_ffio *)nciop->pvt;
+	int status = ENOERR;
+
+	assert(ffp->bf_offset <= offset);
+	assert(ffp->bf_cnt != 0);
+	assert(ffp->bf_cnt <= ffp->bf_extent);
+#ifdef X_ALIGN
+	assert(offset < ffp->bf_offset + X_ALIGN);
+	assert(ffp->bf_cnt % X_ALIGN == 0 );
+#endif
+
+	if(fIsSet(rflags, RGN_MODIFIED))
+	{
+		if(!fIsSet(nciop->ioflags, NC_WRITE))
+			return EPERM; /* attempt to write readonly file */
+
+		status = ffio_pgout(nciop, ffp->bf_offset,
+			ffp->bf_cnt,
+			ffp->bf_base, &ffp->pos);
+		/* if error, invalidate buffer anyway */
+	}
+	ffp->bf_offset = OFF_NONE;
+	ffp->bf_cnt = 0;
+	return status;
+}
+
+
+static int
+ncio_ffio_get(ncio *const nciop,
+		off_t offset, size_t extent,
+		int rflags,
+		void **const vpp)
+{
+	ncio_ffio *ffp = (ncio_ffio *)nciop->pvt;
+	int status = ENOERR;
+#ifdef X_ALIGN
+	size_t rem;
+#endif
+	
+	if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))
+		return EPERM; /* attempt to write readonly file */
+
+	assert(extent != 0);
+	assert(extent < X_INT_MAX); /* sanity check */
+	assert(offset < X_INT_MAX); /* sanity check */
+
+	assert(ffp->bf_cnt == 0);
+
+#ifdef X_ALIGN
+	/* round to seekable boundaries */
+	rem = offset % X_ALIGN;
+	if(rem != 0)
+	{
+		offset -= rem;
+		extent += rem;
+	}
+
+	{
+		const size_t rndup = extent % X_ALIGN;
+		if(rndup != 0)
+			extent += X_ALIGN - rndup;
+	}
+
+	assert(offset % X_ALIGN == 0);
+	assert(extent % X_ALIGN == 0);
+#endif
+
+	if(ffp->bf_extent < extent)
+	{
+		if(ffp->bf_base != NULL)
+		{
+			free(ffp->bf_base);
+			ffp->bf_base = NULL;
+			ffp->bf_extent = 0;
+		}
+		assert(ffp->bf_extent == 0);
+		ffp->bf_base = malloc(extent);
+		if(ffp->bf_base == NULL)
+			return ENOMEM;
+		ffp->bf_extent = extent;
+	}
+
+	status = ffio_pgin(nciop, offset,
+		 extent,
+		 ffp->bf_base,
+		 &ffp->bf_cnt, &ffp->pos);
+	if(status != ENOERR)
+		return status;
+
+	ffp->bf_offset = offset;
+
+	if(ffp->bf_cnt < extent)
+	{
+		(void) memset((char *)ffp->bf_base + ffp->bf_cnt, 0,
+			extent - ffp->bf_cnt);
+		ffp->bf_cnt = extent;
+	}
+
+
+#ifdef X_ALIGN
+	*vpp = (char *)ffp->bf_base + rem;
+#else
+	*vpp = (char *)ffp->bf_base;
+#endif
+	return ENOERR;
+}
+
+
+static int
+ncio_ffio_move(ncio *const nciop, off_t to, off_t from,
+			size_t nbytes, int rflags)
+{
+	int status = ENOERR;
+	off_t lower = from;	
+	off_t upper = to;
+	char *base;
+	size_t diff = upper - lower;
+	size_t extent = diff + nbytes;
+
+	rflags &= RGN_NOLOCK; /* filter unwanted flags */
+
+	if(to == from)
+		return ENOERR; /* NOOP */
+	
+	if(to > from)
+	{
+		/* growing */
+		lower = from;	
+		upper = to;
+	}
+	else
+	{
+		/* shrinking */
+		lower = to;
+		upper = from;
+	}
+
+	diff = upper - lower;
+	extent = diff + nbytes;
+
+	status = ncio_ffio_get(nciop, lower, extent, RGN_WRITE|rflags,
+			(void **)&base);
+
+	if(status != ENOERR)
+		return status;
+
+	if(to > from)
+		(void) memmove(base + diff, base, nbytes); 
+	else
+		(void) memmove(base, base + diff, nbytes); 
+		
+	(void) ncio_ffio_rel(nciop, lower, RGN_MODIFIED);
+
+	return status;
+}
+
+#ifdef NOFFFLUSH
+/* ncio_ffio_sync_noffflush is only needed if the FFIO global layer is
+ * used, because it currently has a bug that causes the PEs to hang
+ * RKO 06/26/98
+ */
+static int
+ncio_ffio_sync_noffflush(ncio *const nciop)
+{
+	struct ffc_stat_s si;	/* for call to fffcntl() */
+	struct ffsw ffstatus;	/* to return ffsw.sw_error */
+	/* run some innocuous ffio routine to get if any errno */
+	if(fffcntl(nciop->fd, FC_STAT, &si, &ffstatus) < 0)
+		return ffstatus.sw_error;
+	return ENOERR;
+}
+/* this tests to see if the global FFIO layer is being called for
+ * returns ~0 if it is, else returns 0
+ */
+static int
+ncio_ffio_global_test(const char *ControlString)
+{
+	if (strstr(ControlString,"global") != (char *) NULL) {
+		return ~0;
+	} else {
+		return 0;
+	}
+}
+#endif
+
+static int
+ncio_ffio_sync(ncio *const nciop)
+{
+	if(ffflush(nciop->fd) < 0)
+		return errno;
+	return ENOERR;
+}
+
+static void
+ncio_ffio_free(void *const pvt)
+{
+	ncio_ffio *ffp = (ncio_ffio *)pvt;
+	if(ffp == NULL)
+		return;
+
+	if(ffp->bf_base != NULL)
+	{
+		free(ffp->bf_base);
+		ffp->bf_base = NULL;
+		ffp->bf_offset = OFF_NONE;
+		ffp->bf_extent = 0;
+		ffp->bf_cnt = 0;
+	}
+}
+
+
+static int
+ncio_ffio_init2(ncio *const nciop, size_t *sizehintp)
+{
+	ncio_ffio *ffp = (ncio_ffio *)nciop->pvt;
+
+	assert(nciop->fd >= 0);
+
+	ffp->bf_extent = *sizehintp;
+
+	assert(ffp->bf_base == NULL);
+
+	/* this is separate allocation because it may grow */
+	ffp->bf_base = malloc(ffp->bf_extent);
+	if(ffp->bf_base == NULL)
+	{
+		ffp->bf_extent = 0;
+		return ENOMEM;
+	}
+	/* else */
+	return ENOERR;
+}
+
+
+static void
+ncio_ffio_init(ncio *const nciop)
+{
+	ncio_ffio *ffp = (ncio_ffio *)nciop->pvt;
+
+	*((ncio_relfunc **)&nciop->rel) = ncio_ffio_rel; /* cast away const */
+	*((ncio_getfunc **)&nciop->get) = ncio_ffio_get; /* cast away const */
+	*((ncio_movefunc **)&nciop->move) = ncio_ffio_move; /* cast away const */
+	*((ncio_syncfunc **)&nciop->sync) = ncio_ffio_sync; /* cast away const */
+	*((ncio_freefunc **)&nciop->free) = ncio_ffio_free; /* cast away const */
+
+	ffp->pos = -1;
+	ffp->bf_offset = OFF_NONE;
+	ffp->bf_extent = 0;
+	ffp->bf_cnt = 0;
+	ffp->bf_base = NULL;
+}
+
+/* */
+
+static void
+ncio_free(ncio *nciop)
+{
+	if(nciop == NULL)
+		return;
+
+	if(nciop->free != NULL)
+		nciop->free(nciop->pvt);
+	
+	free(nciop);
+}
+
+
+static ncio *
+ncio_new(const char *path, int ioflags)
+{
+	size_t sz_ncio = M_RNDUP(sizeof(ncio));
+	size_t sz_path = M_RNDUP(strlen(path) +1);
+	size_t sz_ncio_pvt;
+	ncio *nciop;
+ 
+#if ALWAYS_NC_SHARE /* DEBUG */
+	fSet(ioflags, NC_SHARE);
+#endif
+
+	if(fIsSet(ioflags, NC_SHARE))
+		fprintf(stderr, "NC_SHARE not implemented for ffio\n");
+
+	sz_ncio_pvt = sizeof(ncio_ffio);
+
+	nciop = (ncio *) malloc(sz_ncio + sz_path + sz_ncio_pvt);
+	if(nciop == NULL)
+		return NULL;
+	
+	nciop->ioflags = ioflags;
+	*((int *)&nciop->fd) = -1; /* cast away const */
+
+	nciop->path = (char *) ((char *)nciop + sz_ncio);
+	(void) strcpy((char *)nciop->path, path); /* cast away const */
+
+				/* cast away const */
+	*((void **)&nciop->pvt) = (void *)(nciop->path + sz_path);
+
+	ncio_ffio_init(nciop);
+
+	return nciop;
+}
+
+/* put all the FFIO assign specific code here
+ * returns a pointer to an internal static char location
+ * which may change when the function is called again
+ * if the returned pointer is NULL this indicates that an error occured
+ * check errno for the netCDF error value
+ */
+/* prototype fortran subroutines */
+void ASNQFILE(_fcd filename, _fcd attribute, int *istat);
+void ASNFILE(_fcd filename, _fcd attribute, int *istat);
+
+#define BUFLEN 256
+static const char *
+ncio_ffio_assign(const char *filename) {
+	static char buffer[BUFLEN];
+	int istat;
+	_fcd fnp, fbp;
+	char *envstr;
+	char *xtra_assign;
+	char emptystr='\0';
+
+/* put things into known states */
+	memset(buffer,'\0',BUFLEN);
+	errno = ENOERR;
+
+/* set up Fortran character pointers */
+	fnp = _cptofcd((char *)filename, strlen(filename));
+	fbp = _cptofcd(buffer, BUFLEN);
+
+/* see if the user has "assigned" to this file */
+	ASNQFILE(fnp, fbp, &istat);
+	if (istat == 0) {	/* user has already specified an assign */
+		return buffer;
+	} else if (istat > 0 || istat < -1) {	/* error occured */
+		errno = NC_EINVAL;		/* as good as any */
+		return (const char *) NULL;
+	} /* istat = -1 -> no assign for file */
+	envstr = getenv("NETCDF_FFIOSPEC");
+	if(envstr == (char *) NULL) {
+		 envstr = "bufa:336:2";		/* this should be macroized */
+	}
+	
+	/* Insertion by Olaf Heudecker, AWI-Bremerhaven, 12.8.1998
+	   to allow more versatile FFIO-assigns */
+	/* this is unnecessary and could have been included
+	 * into the NETCDF_FFIOSPEC environment variable */
+	xtra_assign = getenv("NETCDF_XFFIOSPEC");
+	if(xtra_assign == (char *) NULL) {
+		xtra_assign=&emptystr;
+	}
+	if (strlen(envstr)+strlen(xtra_assign) + 4 > BUFLEN) {
+	/* Error: AssignCommand too long */
+		errno=E2BIG;
+		return (const char *) NULL;
+	}
+	(void) sprintf(buffer,"-F %s %s", envstr,xtra_assign);
+	fbp = _cptofcd(buffer, strlen(buffer));
+	ASNFILE(fnp, fbp, &istat);
+	if (istat == 0) {	/* success */
+		return buffer;
+	} else {		/* error */
+		errno = NC_EINVAL;
+		return (const char *) NULL;
+	}
+}
+
+/* Public below this point */
+
+/* TODO: Is this reasonable for this platform? */
+static const size_t NCIO_MINBLOCKSIZE = 256;
+static const size_t NCIO_MAXBLOCKSIZE = 268435456; /* sanity check, about X_SIZE_T_MAX/8 */
+
+int
+ncio_create(const char *path, int ioflags,
+	size_t initialsz,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp)
+{
+	ncio *nciop;
+	const char *ControlString;
+	int oflags = (O_RDWR|O_CREAT|O_TRUNC);
+	int fd;
+	int status;
+	struct ffsw stat;
+
+	if(initialsz < (size_t)igeto + igetsz)
+		initialsz = (size_t)igeto + igetsz;
+
+	fSet(ioflags, NC_WRITE);
+
+	if(path == NULL || *path == 0)
+		return EINVAL;
+
+	nciop = ncio_new(path, ioflags);
+	if(nciop == NULL)
+		return ENOMEM;
+
+	if ((ControlString = ncio_ffio_assign(path)) == (const char *)NULL) {
+		/* an error occured - just punt */
+		status = errno;
+		goto unwind_new;
+	}
+#ifdef NOFFFLUSH
+	/* test whether the global layer is being called for
+	 * this file ... if so then can't call FFIO ffflush()
+	 * RKO 06/26/98
+	 */
+	if (strstr(ControlString,"global") != (char *) NULL) {
+		/* use no ffflush version */
+		*((ncio_syncfunc **)&nciop->sync)
+			= ncio_ffio_sync_noffflush;
+	}
+#endif
+	if(fIsSet(ioflags, NC_NOCLOBBER))
+		fSet(oflags, O_EXCL);
+
+	/* Orig: fd = ffopens(path, oflags, 0666, 0, &stat, ControlString); */
+	fd = ffopen(path, oflags, 0666, 0, &stat);
+	if(fd < 0)
+	{
+		status = errno;
+		goto unwind_new;
+	}
+	*((int *)&nciop->fd) = fd; /* cast away const */
+
+	if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE)
+	{
+		/* Use default */
+		*sizehintp = blksize(fd);
+	}
+	else
+	{
+		*sizehintp = M_RNDUP(*sizehintp);
+	}
+
+	status = ncio_ffio_init2(nciop, sizehintp);
+	if(status != ENOERR)
+		goto unwind_open;
+
+	if(initialsz != 0)
+	{
+		status = fgrow(fd, (off_t)initialsz);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	if(igetsz != 0)
+	{
+		status = nciop->get(nciop,
+				igeto, igetsz,
+                        	RGN_WRITE,
+                        	igetvpp);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	*nciopp = nciop;
+	return ENOERR;
+
+unwind_open:
+	(void) ffclose(fd);
+	/* ?? unlink */
+	/*FALLTHRU*/
+unwind_new:
+	ncio_free(nciop);
+	return status;
+}
+
+
+int
+ncio_open(const char *path,
+	int ioflags,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp)
+{
+	ncio *nciop;
+	const char *ControlString;
+	int oflags = fIsSet(ioflags, NC_WRITE) ? O_RDWR : O_RDONLY;
+	int fd;
+	int status;
+	struct ffsw stat;
+
+	if(path == NULL || *path == 0)
+		return EINVAL;
+
+	nciop = ncio_new(path, ioflags);
+	if(nciop == NULL)
+		return ENOMEM;
+
+	if ((ControlString = ncio_ffio_assign(path)) == (const char *)NULL) {
+		/* an error occured - just punt */
+		status = errno;
+		goto unwind_new;
+	}
+#ifdef NOFFFLUSH
+	/* test whether the global layer is being called for
+	 * this file ... if so then can't call FFIO ffflush()
+	 * RKO 06/26/98
+	 */
+	if (strstr(ControlString,"global") != (char *) NULL) {
+		/* use no ffflush version */
+		*((ncio_syncfunc **)&nciop->sync)
+			= ncio_ffio_sync_noffflush;
+	}
+#endif
+
+	/* Orig: fd = ffopens(path, oflags, 0, 0, &stat, ControlString); */
+	fd = ffopen(path, oflags, 0, 0, &stat);
+
+	if(fd < 0)
+	{
+		status = errno;
+		goto unwind_new;
+	}
+	*((int *)&nciop->fd) = fd; /* cast away const */
+
+	if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE)
+	{
+		/* Use default */
+		*sizehintp = blksize(fd);
+	}
+	else
+	{
+		*sizehintp = M_RNDUP(*sizehintp);
+	}
+
+	status = ncio_ffio_init2(nciop, sizehintp);
+	if(status != ENOERR)
+		goto unwind_open;
+
+	if(igetsz != 0)
+	{
+		status = nciop->get(nciop,
+				igeto, igetsz,
+                        	0,
+                        	igetvpp);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	*nciopp = nciop;
+	return ENOERR;
+
+unwind_open:
+	(void) ffclose(fd);
+	/*FALLTHRU*/
+unwind_new:
+	ncio_free(nciop);
+	return status;
+}
+
+
+int 
+ncio_close(ncio *nciop, int doUnlink)
+{
+	int status = ENOERR;
+
+	if(nciop == NULL)
+		return EINVAL;
+
+	status = nciop->sync(nciop);
+
+	(void) ffclose(nciop->fd);
+	
+	if(doUnlink)
+		(void) unlink(nciop->path);
+
+	ncio_free(nciop);
+
+	return status;
+}
Index: /branches/SDM_SciDAC/src/lib/netcdf.3
===================================================================
--- /branches/SDM_SciDAC/src/lib/netcdf.3 (revision 2)
+++ /branches/SDM_SciDAC/src/lib/netcdf.3 (revision 2)
@@ -0,0 +1,1043 @@
+.TH NETCDF 3 "18 April 1997" "Printed: \n(yr.\n(mo.\n(dy" "UNIDATA LIBRARY FUNCTIONS"
+.SH NAME
+netcdf \- Unidata Network Common Data Form (netCDF) library, version 3 interface
+.SH SYNOPSIS
+.ft B
+.na
+.nh
+#include "netcdf.h"
+.sp
+
+cc ... -lnetcdf
+
+.ad
+.hy
+.SH "LIBRARY VERSION"
+.LP
+This document describes version 3 of Unidata netCDF data-access interface
+for the C programming language.
+.HP
+\fBconst char* ncmpi_inq_libvers()\fR
+.sp
+Returns a string identifying the version of the netCDF library, and
+when it was built, like: "3.1a of Aug 22 1996 12:57:47 $".
+.LP
+The RCS \fBident(1)\fP command will find a string like
+"$\|Id: @\|(#) netcdf library version 3.1a of Sep  6 1996 15:56:26 $"
+in the library. The SCCS \fBwhat(1)\fP command will find a string like
+"netcdf library version 3.1a of Aug 23 1996 16:07:40 $".
+.SH "RETURN VALUES"
+.LP
+All netCDF functions (except
+\fBncmpi_inq_libvers(\|)\fR and \fBncmpi_strerror(\|)\fR) return an integer status.
+This behavior replaces the
+\fBncerr()\fR function
+used in previous versions of the library.
+If this returned status value is not equal to
+\fBNC_NOERR\fR (zero), it
+indicates that an error occurred. The possible status values are defined in 
+system include file <errno.h> and in "netcdf.h".
+.HP
+\fBconst char* ncmpi_strerror(int \fIstatus\fP)\fR
+.sp
+Returns a string textual translation of the \fIstatus\fP
+value, like "Attribute or variable name contains illegal characters"
+or "No such file or directory".
+.HP
+\fBint ncmpi_create( \fIcomm\fP, const char \fIpath\fP[], int \fIcmode\fP,  \fIinfo\fP,
+int* \fIncid\fP)\fR
+.sp
+(Corresponds to \fBnccreate(\|)\fR in version 2)
+.sp
+Creates a new netCDF dataset at \fIpath\fP,
+returning a netCDF ID in \fIncid\fP.
+The argument \fIcmode\fP may include the bitwise-or
+of the following flags:
+\fBNC_NOCLOBBER\fR
+to protect existing datasets (default
+silently blows them away),
+\fBNC_SHARE\fR
+for synchronous dataset updates
+(default is to buffer accesses), and
+\fBNC_LOCK\fR
+(not yet implemented).
+When a netCDF dataset is created, is is opened
+\fBNC_WRITE\fR.
+The new netCDF dataset is in define mode.
+.HP
+\fBint ncmpi__create(const char \fIpath\fP[], int \fIcmode\fP, size_t \fIinitialsize\fP, size_t* \fIchunksize\fP, int* \fIncid\fP)\fR
+.sp
+Like \fBncmpi_create(\|)\fR but has additional performance tuning parameters.
+.sp
+The argument \fIinitialsize\fP sets the initial size of the file at
+creation time.
+.sp
+See \fBncmpi__open(\|)\fR below for an explanation of the \fIchunksize\fP
+parameter.
+.HP
+\fBint ncmpi_open( \fIcomm\fP, const char \fIpath\fP[], int \fImode\fP,  \fIinfo\fP, int* \fIncid\fP)\fR
+.sp
+(Corresponds to \fBncopen(\|)\fR in version 2)
+.sp
+Opens a existing netCDF dataset at \fIpath\fP
+returning a netCDF ID
+in \fIncid\fP.
+The type of access is described by the \fImode\fP parameter,
+which may include the bitwise-or
+of the following flags:
+\fBNC_WRITE\fR
+for read-write access (default
+read-only),
+\fBNC_SHARE\fR
+for synchronous dataset updates (default is
+to buffer accesses), and
+\fBNC_LOCK\fR
+(not yet implemented).
+.HP
+\fBint ncmpi__open(const char \fIpath\fP[], int \fImode\fP, size_t* \fIchunksize\fP, int* \fIncid\fP)\fR
+.sp
+Like \fBncmpi_open(\|)\fR but has an additional performance tuning parameter.
+.sp
+The argument referenced by \fIchunksize\fP controls a space versus time
+tradeoff, memory allocated in the netcdf library versus number of system
+calls.
+Because of internal requirements, the value may not be set to exactly
+the value requested.
+The actual value chosen is returned by reference.
+Using the value \fBNC_SIZEHINT_DEFAULT\fR causes the library to choose a
+default.
+How the system choses the default depends on the system.
+On many systems, the "preferred I/O block size" is available from the 
+\fBstat()\fR system call, \fBstruct stat\fR member \fBst_blksize\fR.
+If this is available it is used. Lacking that, twice the system pagesize
+is used.
+Lacking a call to discover the system pagesize, we just set default
+chunksize to 8192.
+.sp
+The chunksize is a property of a given open netcdf descriptor
+\fIncid\fP, it is not a persistent property of the netcdf dataset.
+.HP
+\fBint ncmpi_redef(int \fIncid\fP)\fR
+.sp
+(Corresponds to \fBncredef(\|)\fR in version 2)
+.sp
+Puts an open netCDF dataset into define mode, 
+so dimensions, variables, and attributes can be added or renamed and 
+attributes can be deleted.
+.HP
+\fBint ncmpi_enddef(int \fIncid\fP)\fR
+.sp
+(Corresponds to \fBncendef(\|)\fR in version 2)
+.sp
+Takes an open netCDF dataset out of define mode.
+The changes made to the netCDF dataset
+while it was in define mode are checked and committed to disk if no
+problems occurred.  Some data values may be written as well,
+see "VARIABLE PREFILLING" below.
+After a successful call, variable data can be read or written to the dataset.
+.HP
+\fBint ncmpi__enddef(int \fIncid\fP, size_t \fIh_minfree\fP, size_t \fIv_align\fP, size_t \fIv_minfree\fP, size_t \fIr_align\fP)\fR
+.sp
+Like \fBncmpi_enddef(\|)\fR but has additional performance tuning parameters.
+.sp
+Caution: this function exposes internals of the netcdf version 1 file
+format.
+It may not be available on future netcdf implementations.
+.sp
+The current netcdf file format has three sections,
+the "header" section, the data section for fixed size variables, and
+the data section for variables which have an unlimited dimension (record
+variables).
+The header begins at the beginning of the file. The index
+(offset) of the beginning of the other two sections is contained in the
+header. Typically, there is no space between the sections. This causes
+copying overhead to accrue if one wishes to change the size of the
+sections,
+as may happen when changing names of things, text attribute values,
+adding
+attributes or adding variables. Also, for buffered i/o, there may be
+advantages
+to aligning sections in certain ways.
+.sp
+The minfree parameters allow one to control costs of future calls
+to \fBncmpi_redef(\|)\fR, \fBncmpi_enddef(\|)\fR by requesting that \fIminfree\fP bytes be
+available at the end of the section.
+The \fIh_minfree\fP parameter sets the pad
+at the end of the "header" section. The \fIv_minfree\fP parameter sets
+the pad at the end of the data section for fixed size variables.
+.sp
+The align parameters allow one to set the alignment of the beginning of
+the corresponding sections. The beginning of the section is rounded up
+to an index which is a multiple of the align parameter. The flag value
+\fBNC_ALIGN_CHUNK\fR tells the library to use the chunksize (see above)
+as the align parameter.
+The \fIv_align\fP parameter controls the alignment of the beginning of
+the data section for fixed size variables.
+The \fIr_align\fP parameter controls the alignment of the beginning of
+the data section for variables which have an unlimited dimension (record
+variables).
+.sp
+The file format requires mod 4 alignment, so the align parameters
+are silently rounded up to multiples of 4. The usual call,
+\fBncmpi_enddef(\fIncid\fP)\fR
+is equivalent to
+\fBncmpi__enddef(\fIncid\fP, 0, 4, 0, 4)\fR.
+.sp
+The file format does not contain a "record size" value, this is
+calculated from the sizes of the record variables. This unfortunate fact
+prevents us from providing minfree and alignment control of the
+"records"
+in a netcdf file. If you add a variable which has an unlimited
+dimension,
+the third section will always be copied with the new variable added.
+.HP
+\fBint ncmpi_sync(int \fIncid\fP)\fR
+.sp
+(Corresponds to \fBncsync(\|)\fR in version 2)
+.sp
+Unless the
+\fBNC_SHARE\fR
+bit is set in
+\fBncmpi_open(\|)\fR or \fBncmpi_create(\|)\fR,
+accesses to the underlying netCDF dataset are
+buffered by the library. This function synchronizes the state of
+the underlying dataset and the library.
+This is done automatically by
+\fBncmpi_close(\|)\fR and \fBncmpi_enddef(\|)\fR.
+.HP
+\fBint ncmpi_abort(int \fIncid\fP)\fR
+.sp
+(Corresponds to \fBncabort(\|)\fR in version 2)
+.sp
+You don't need to call this function.
+This function is called automatically by
+\fBncmpi_close(\|)\fR
+if the netCDF was in define mode and something goes wrong with the commit.
+If the netCDF dataset isn't in define mode, then this function is equivalent to
+\fBncmpi_close(\|)\fR.
+If it is called after
+\fBncmpi_redef(\|)\fR,
+but before
+\fBncmpi_enddef(\|)\fR,
+the new definitions are not committed and the dataset is closed.
+If it is called after
+\fBncmpi_create(\|)\fR
+but before
+\fBncmpi_enddef(\|)\fR,
+the dataset disappears.
+.HP
+\fBint ncmpi_close(int \fIncid\fP)\fR
+.sp
+(Corresponds to
+\fBncclose(\|)\fR in version 2)
+.sp
+Closes an open netCDF dataset.
+If the dataset is in define mode,
+\fBncmpi_enddef(\|)\fR
+will be called before closing.
+After a dataset is closed, its ID may be reassigned to another dataset.
+.HP
+\fBint ncmpi_inq(int \fIncid\fP, int* \fIndims\fP, int* \fInvars\fP,
+int* \fInatts\fP, int* \fIunlimdimid\fP)\fR
+.HP
+\fBint ncmpi_inq_ndims(int \fIncid\fP, int* \fIndims\fP)\fR
+.HP
+\fBint ncmpi_inq_nvars(int \fIncid\fP, int* \fInvars\fP)\fR
+.HP
+\fBint ncmpi_inq_natts(int \fIncid\fP, int* \fInatts\fP)\fR
+.HP
+\fBint ncmpi_inq_unlimdim(int \fIncid\fP, int* \fIunlimdimid\fP)\fR
+.sp
+(Replace \fBncinquire(\|)\fR in version 2)
+.sp
+Use these functions to find out what is in a netCDF dataset.
+Upon successful return,
+\fIndims\fP will contain  the
+number of dimensions defined for this netCDF dataset,
+\fInvars\fP will contain the number of variables,
+\fInatts\fP will contain the number of attributes, and
+\fIunlimdimid\fP will contain the
+dimension ID of the unlimited dimension if one exists, or
+-1 otherwise.
+If any of the
+return parameters is a \fBNULL\fR pointer, then the corresponding information
+will not be returned; hence, no space need be allocated for it.
+.HP
+\fBint ncmpi_def_dim(int \fIncid\fP, const char \fIname\fP[], size_t \fIlen\fP, int* \fIdimid\fP)\fR
+.sp
+(Corresponds to \fBncdimdef(\|)\fR in version 2)
+.sp
+Adds a new dimension to an open netCDF dataset, which must be 
+in define mode.
+\fIname\fP is the dimension name.
+If \fIdimid\fP is not a \fBNULL\fR pointer then upon successful completion \fIdimid\fP will contain the dimension ID of the newly created dimension.
+.HP
+\fBint ncmpi_inq_dimid(int \fIncid\fP, const char \fIname\fP[], int* \fIdimid\fP)\fR
+.sp
+(Corresponds to \fBncdimid(\|)\fR in version 2)
+.sp
+Given a dimension name, returns the ID of a netCDF dimension in \fIdimid\fP.
+.HP
+\fBint ncmpi_inq_dim(int \fIncid\fP, int \fIdimid\fP, char \fIname\fP[], size_t* \fIlen\fP)\fR
+.HP
+\fBint ncmpi_inq_dimname(int \fIncid\fP, int \fIdimid\fP, char \fIname\fP[])\fR
+.HP
+\fBint ncmpi_inq_dimlen(int \fIncid\fP, int \fIdimid\fP, size_t* \fIlen\fP)\fR
+.sp
+(Replace \fBncdiminq(\|)\fR in version 2)
+.sp
+Use these functions to find out about a dimension.
+If either the \fIname\fP
+argument or \fIlen\fP argument is a \fBNULL\fR pointer, then
+the associated information will not be returned.  Otherwise,
+\fIname\fP should be  big enough (\fBNC_MAX_NAME\fR)
+to hold the dimension name as the name will be copied into your storage.
+The length return parameter, \fIlen\fP
+will contain the size of the dimension.
+For the unlimited dimension, the returned length is the current
+maximum value used for writing into any of the variables which use
+the dimension.
+.HP
+\fBint ncmpi_rename_dim(int \fIncid\fP, int \fIdimid\fP, const char \fIname\fP[])\fR
+.sp
+(Corresponds to \fBncdimrename(\|)\fR in version 2)
+.sp
+Renames an existing dimension in an open netCDF dataset.
+If the new name is longer than the old name, the netCDF dataset must be in 
+define mode.
+You cannot rename a dimension to have the same name as another dimension.
+.HP
+\fBint ncmpi_def_var(int \fIncid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, int \fIndims\fP, const int \fIdimids\fP[], int* \fIvarid\fP)\fR
+.sp
+(Corresponds to \fBncvardef(\|)\fR in version 2)
+.sp
+Adds a new variable to a netCDF dataset. The netCDF must be in define mode.
+If not \fBNULL\fR, then \fIvarid\fP will be set to the netCDF variable ID.
+.HP
+\fBint ncmpi_inq_varid(int \fIncid\fP, const char \fIname\fP[], int* \fIvarid\fP)\fR
+.sp
+(Corresponds to \fBncvarid(\|)\fR in version 2)
+.sp
+Returns the ID of a netCDF variable in \fIvarid\fP given its name.
+.HP
+\fBint ncmpi_inq_var(int \fIncid\fP, int \fIvarid\fP, char \fIname\fP[], nc_type* \fIxtype\fP, int* \fIndims\fP, int \fIdimids\fP[],
+int* \fInatts\fP)\fR
+.HP
+\fBint ncmpi_inq_varname(int \fIncid\fP, int \fIvarid\fP, char \fIname\fP[])\fR
+.HP
+\fBint ncmpi_inq_vartype(int \fIncid\fP, int \fIvarid\fP, nc_type* \fIxtype\fP)\fR
+.HP
+\fBint ncmpi_inq_varndims(int \fIncid\fP, int \fIvarid\fP, int* \fIndims\fP)\fR
+.HP
+\fBint ncmpi_inq_vardimid(int \fIncid\fP, int \fIvarid\fP, int \fIdimids\fP[])\fR
+.HP
+\fBint ncmpi_inq_varnatts(int \fIncid\fP, int \fIvarid\fP, int* \fInatts\fP)\fR
+.sp
+(Replace \fBncvarinq(\|)\fR in version 2)
+.sp
+Returns information about a netCDF variable, given its ID.
+If any of the
+return parameters (\fIname\fP, \fIxtype\fP, \fIndims\fP, \fIdimids\fP, or
+\fInatts\fP) is a \fBNULL\fR pointer, then the corresponding information
+will not be returned; hence, no space need be allocated for it.
+.HP
+\fBint ncmpi_rename_var(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[])\fR
+.sp
+(Corresponds to \fBncvarrename(\|)\fR in version 2)
+.sp
+Changes the name of a netCDF variable.
+If the new name is longer than the old name, the netCDF must be in define mode.
+You cannot rename a variable to have the name of any existing variable.
+.HP
+\fBint ncmpi_put_var_text(int \fIncid\fP, int \fIvarid\fP, const char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_var_uchar(int \fIncid\fP, int \fIvarid\fP, const unsigned char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_var_schar(int \fIncid\fP, int \fIvarid\fP, const signed char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_var_short(int \fIncid\fP, int \fIvarid\fP, const short \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_var_int(int \fIncid\fP, int \fIvarid\fP, const int \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_var_long(int \fIncid\fP, int \fIvarid\fP, const long \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_var_float(int \fIncid\fP, int \fIvarid\fP, const float \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_var_double(int \fIncid\fP, int \fIvarid\fP, const double \fIout\fP[])\fR
+.sp
+(Replace \fBncvarput(\|)\fR in version 2)
+.sp
+Writes an entire netCDF variable (i.e. all the values).
+The netCDF dataset must be open and in data mode.  The type of the data is
+specified in the function name, and it is converted to the external type
+of the specified variable, if possible, otherwise an
+\fBNC_ERANGE\fR error is returned.
+.HP
+\fBint ncmpi_get_var_text(int \fIncid\fP, int \fIvarid\fP, char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_var_uchar(int \fIncid\fP, int \fIvarid\fP, unsigned char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_var_schar(int \fIncid\fP, int \fIvarid\fP, signed char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_var_short(int \fIncid\fP, int \fIvarid\fP, short \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_var_int(int \fIncid\fP, int \fIvarid\fP, int \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_var_long(int \fIncid\fP, int \fIvarid\fP, long \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_var_float(int \fIncid\fP, int \fIvarid\fP, float \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_var_double(int \fIncid\fP, int \fIvarid\fP, double \fIin\fP[])\fR
+.sp
+(Replace \fBncvarget(\|)\fR in version 2)
+.sp
+Reads an entire netCDF variable (i.e. all the values).
+The netCDF dataset must be open and in data mode.  
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an \fBNC_ERANGE\fR error is returned.
+.HP
+\fBint ncmpi_put_var1_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], char \fI*out\fP)\fR
+.HP
+\fBint ncmpi_put_var1_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], unsigned char \fI*out\fP)\fR
+.HP
+\fBint ncmpi_put_var1_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], signed char \fI*out\fP)\fR
+.HP
+\fBint ncmpi_put_var1_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], short \fI*out\fP)\fR
+.HP
+\fBint ncmpi_put_var1_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], int \fI*out\fP)\fR
+.HP
+\fBint ncmpi_put_var1_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], long \fI*out\fP)\fR
+.HP
+\fBint ncmpi_put_var1_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], float \fI*out\fP)\fR
+.HP
+\fBint ncmpi_put_var1_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], double \fI*out\fP)\fR
+.sp
+(Replace \fBncvarput1(\|)\fR in version 2)
+.sp
+Puts a single data value into a variable at the position \fIindex\fP of an
+open netCDF dataset that is in data mode.  The type of the data is
+specified in the function name, and it is converted to the external type
+of the specified variable, if possible, otherwise an \fBNC_ERANGE\fR
+error is returned.
+.HP
+\fBint ncmpi_get_var1_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], char* \fIin\fP)\fR
+.HP
+\fBint ncmpi_get_var1_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], unsigned char* \fIin\fP)\fR
+.HP
+\fBint ncmpi_get_var1_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], signed char* \fIin\fP)\fR
+.HP
+\fBint ncmpi_get_var1_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], short* \fIin\fP)\fR
+.HP
+\fBint ncmpi_get_var1_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], int* \fIin\fP)\fR
+.HP
+\fBint ncmpi_get_var1_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], long* \fIin\fP)\fR
+.HP
+\fBint ncmpi_get_var1_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], float* \fIin\fP)\fR
+.HP
+\fBint ncmpi_get_var1_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIindex\fP[], double* \fIin\fP)\fR
+.sp
+(Replace \fBncvarget1(\|)\fR in version 2)
+.sp
+Gets a single data value from a variable at the position \fIindex\fP
+of an open netCDF dataset that is in data mode.  
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an \fBNC_ERANGE\fR error is returned.
+.HP
+\fBint ncmpi_put_vara_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vara_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const unsigned char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vara_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const signed char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vara_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const short \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vara_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const int \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vara_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const long \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vara_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const float \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vara_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const double \fIout\fP[])\fR
+.sp
+(Replace \fBncvarput(\|)\fR in version 2)
+.sp
+Writes an array section of values into a netCDF variable of an open
+netCDF dataset, which must be in data mode.  The array section is specified
+by the \fIstart\fP and \fIcount\fP vectors, which give the starting index
+and count of values along each dimension of the specified variable.
+The type of the data is
+specified in the function name and is converted to the external type
+of the specified variable, if possible, otherwise an \fBNC_ERANGE\fR
+error is returned.
+.HP
+\fBint ncmpi_get_vara_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vara_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], unsigned char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vara_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], signed char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vara_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], short \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vara_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], int \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vara_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], long \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vara_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], float \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vara_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], double \fIin\fP[])\fR
+.sp
+(Corresponds to \fBncvarget(\|)\fR in version 2)
+.sp
+Reads an array section of values from a netCDF variable of an open
+netCDF dataset, which must be in data mode.  The array section is specified
+by the \fIstart\fP and \fIcount\fP vectors, which give the starting index
+and count of values along each dimension of the specified variable.
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an \fBNC_ERANGE\fR error is returned.
+.HP
+\fBint ncmpi_put_vars_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vars_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const unsigned char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vars_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const signed char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vars_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const short \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vars_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const int \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vars_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const long \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vars_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const float \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_vars_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], const double \fIout\fP[])\fR
+.sp
+(Corresponds to \fBncvarputg(\|)\fR in version 2)
+.sp
+These functions are used for \fIstrided output\fP, which is like the
+array section output described above, except that
+the sampling stride (the interval between accessed values) is
+specified for each dimension.
+For an explanation of the sampling stride
+vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+.HP
+\fBint ncmpi_get_vars_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vars_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], unsigned char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vars_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], signed char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vars_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], short \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vars_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], int \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vars_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], long \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vars_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], float \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_vars_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], double \fIin\fP[])\fR
+.sp
+(Corresponds to \fBncvargetg(\|)\fR in version 2)
+.sp
+These functions are used for \fIstrided input\fP, which is like the
+array section input described above, except that 
+the sampling stride (the interval between accessed values) is
+specified for each dimension.
+For an explanation of the sampling stride
+vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+.HP
+\fBint ncmpi_put_varm_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_varm_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const unsigned char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_varm_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const signed char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_varm_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const short \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_varm_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const int \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_varm_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const long \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_varm_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const float \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_varm_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, const double \fIout\fP[])\fR
+.sp
+(Corresponds to \fBncvarputg(\|)\fR in version 2)
+.sp
+These functions are used for \fImapped output\fP, which is like
+strided output described above, except that an additional index mapping
+vector is provided to specify the in-memory arrangement of the data
+values.
+For an explanation of the index
+mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+.HP
+\fBint ncmpi_get_varm_text(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_varm_uchar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, unsigned char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_varm_schar(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, signed char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_varm_short(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, short \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_varm_int(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, int \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_varm_long(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, long \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_varm_float(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, float \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_varm_double(int \fIncid\fP, int \fIvarid\fP, const size_t \fIstart\fP[], const size_t \fIcount\fP[], const size_t \fIstride\fP[], \fIimap\fP, double \fIin\fP[])\fR
+.sp
+(Corresponds to \fBncvargetg(\|)\fR in version 2)
+.sp
+These functions are used for \fImapped input\fP, which is like
+strided input described above, except that an additional index mapping
+vector is provided to specify the in-memory arrangement of the data
+values.
+For an explanation of the index
+mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+.HP
+\fBint ncmpi_put_att_text(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_att_uchar(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const unsigned char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_att_schar(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const signed char \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_att_short(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const short \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_att_int(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const int \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_att_long(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const long \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_att_float(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const float \fIout\fP[])\fR
+.HP
+\fBint ncmpi_put_att_double(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type \fIxtype\fP, size_t \fIlen\fP, const double \fIout\fP[])\fR
+.sp
+(Replace \fBncattput(\|)\fR in version 2)
+.sp
+Unlike variables, attributes do not have 
+separate functions for defining and writing values.
+This family of functions defines a new attribute with a value or changes
+the value of an existing attribute.
+If the attribute is new, or if the space required to
+store the attribute value is greater than before,
+the netCDF dataset must be in define mode.
+The parameter \fIlen\fP is the number of values from \fIout\fP to transfer.
+It is often one, except that for
+\fBncmpi_put_att_text(\|)\fR it will usually be
+\fBstrlen(\fIout\fP)\fR.
+.sp
+For these functions, the type component of the function name refers to
+the in-memory type of the value, whereas the \fIxtype\fP argument refers to the
+external type for storing the value.  An \fBNC_ERANGE\fR
+error results if
+a conversion between these types is not possible.  In this case the value
+is represented with the appropriate fill-value for the associated 
+external type.
+.HP
+\fBint ncmpi_inq_attname(int \fIncid\fP, int \fIvarid\fP, int \fIattnum\fP, char \fIname\fP[])\fR
+.sp
+(Corresponds to \fBncattname(\|)\fR in version 2)
+.sp
+Gets the
+name of an attribute, given its variable ID and attribute number.
+This function is useful in generic applications that
+need to get the names of all the attributes associated with a variable,
+since attributes are accessed by name rather than number in all other
+attribute functions.  The number of an attribute is more volatile than
+the name, since it can change when other attributes of the same variable
+are deleted.  The attributes for each variable are numbered
+from 0 (the first attribute) to
+\fInvatts\fP-1,
+where \fInvatts\fP is
+the number of attributes for the variable, as returned from a call to
+\fBncmpi_inq_varnatts(\|)\fR.
+If the \fIname\fP parameter is a \fBNULL\fR pointer, no name will be
+returned and no space need be allocated.
+.HP
+\fBint ncmpi_inq_att(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type* \fIxtype\fP, size_t* \fIlen\fP)\fR
+.HP
+\fBint ncmpi_inq_attid(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], int* \fIattnum\fP)\fR
+.HP
+\fBint ncmpi_inq_atttype(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], nc_type* \fIxtype\fP)\fR
+.HP
+\fBint ncmpi_inq_attlen(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], size_t* \fIlen\fP)\fR
+.sp
+(Corresponds to \fBncattinq(\|)\fR in version 2)
+.sp
+These functions return information about a netCDF attribute,
+given its variable ID and name.  The information returned is the
+external type in \fIxtype\fP
+and the number of elements in the attribute as \fIlen\fP.
+If any of the return arguments is a \fBNULL\fR pointer,
+the specified information will not be returned.
+.HP
+\fBint ncmpi_copy_att(int \fIncid\fP, int \fIvarid_in\fP, const char \fIname\fP[], int \fIncid_out\fP, int \fIvarid_out\fP)\fR
+.sp
+(Corresponds to \fBncattcopy(\|)\fR in version 2)
+.sp
+Copies an
+attribute from one netCDF dataset to another.  It can also be used to
+copy an attribute from one variable to another within the same netCDF.
+\fIncid_in\fP is the netCDF ID of an input netCDF dataset from which the
+attribute will be copied.
+\fIvarid_in\fP
+is the ID of the variable in the input netCDF dataset from which the
+attribute will be copied, or \fBNC_GLOBAL\fR
+for a global attribute.
+\fIname\fP
+is the name of the attribute in the input netCDF dataset to be copied.
+\fIncid_out\fP
+is the netCDF ID of the output netCDF dataset to which the attribute will be 
+copied.
+It is permissible for the input and output netCDF ID's to be the same.  The
+output netCDF dataset should be in define mode if the attribute to be
+copied does not already exist for the target variable, or if it would
+cause an existing target attribute to grow.
+\fIvarid_out\fP
+is the ID of the variable in the output netCDF dataset to which the attribute will
+be copied, or \fBNC_GLOBAL\fR to copy to a global attribute.
+.HP
+\fBint ncmpi_rename_att(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], const char \fInewname\fP[])\fR
+.sp
+(Corresponds to \fBncattrename(\|)\fR
+.sp
+Changes the
+name of an attribute.  If the new name is longer than the original name,
+the netCDF must be in define mode.  You cannot rename an attribute to
+have the same name as another attribute of the same variable.
+\fIname\fP is the original attribute name.
+\fInewname\fP
+is the new name to be assigned to the specified attribute.  If the new name
+is longer than the old name, the netCDF dataset must be in define mode.
+.HP
+\fBint ncmpi_del_att(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[])\fR
+.sp
+(Corresponds to \fBncattdel(\|)\fR in version 2)
+.sp
+Deletes an attribute from a netCDF dataset.  The dataset must be in
+define mode.
+.HP
+\fBint ncmpi_get_att_text(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_att_uchar(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], unsigned char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_att_schar(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], signed char \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_att_short(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], short \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_att_int(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], int \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_att_long(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], long \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_att_float(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], float \fIin\fP[])\fR
+.HP
+\fBint ncmpi_get_att_double(int \fIncid\fP, int \fIvarid\fP, const char \fIname\fP[], double \fIin\fP[])\fR
+.sp
+(Replace \fBncattget(\|)\fR in version 2)
+.sp
+Gets the value(s) of a netCDF attribute, given its
+variable ID and name.  Converts from the external type to the type
+specified in
+the function name, if possible, otherwise returns an \fBNC_ERANGE\fR
+error.
+All elements of the vector of attribute
+values are returned, so you must allocate enough space to hold
+them.  If you don't know how much space to reserve, call
+\fBncmpi_inq_attlen(\|)\fR
+first to find out the length of the attribute.
+.SH "COMMON ARGUMENT DESCRIPTIONS"
+.LP
+In this section we define some common arguments which are used in the 
+"FUNCTION DESCRIPTIONS" section.
+.TP
+int \fIncid\fP
+is the netCDF ID returned from a previous, successful call to
+\fBncmpi_open(\|)\fR or \fBncmpi_create(\|)\fR
+.TP
+char \fIname\fP[]
+is the name of a dimension, variable, or attribute.
+It shall begin with an alphabetic character, followed by
+zero or more alphanumeric characters including the underscore
+(`_') or hyphen (`-').  Case is significant.
+As an input argument, 
+it shall be a pointer to a 0-terminated string; as an output argument, it 
+shall be the address of a buffer in which to hold such a string.
+The maximum allowable number of characters 
+(excluding the terminating 0) is \fBNC_MAX_NAME\fR.
+Names that begin with an underscore (`_') are reserved for use
+by the netCDF interface.
+.TP
+nc_type \fIxtype\fP
+specifies the external data type of a netCDF variable or attribute and
+is one of the following:
+\fBNC_BYTE\fR, \fBNC_CHAR\fR, \fBNC_SHORT\fR, \fBNC_INT\fR, 
+\fBNC_FLOAT\fR, or \fBNC_DOUBLE\fR.
+These are used to specify 8-bit integers,
+characters, 16-bit integers, 32-bit integers, 32-bit IEEE floating point
+numbers, and 64-bit IEEE floating-point numbers, respectively.
+(\fBNC_INT\fR corresponds to \fBNC_LONG\fR in version 2, to specify a
+32-bit integer).
+.TP
+int \fIdimids\fP[]
+is a vector of dimension ID's and defines the shape of a netCDF variable.
+The size of the vector shall be greater than or equal to the
+rank (i.e. the number of dimensions) of the variable (\fIndims\fP).
+The vector shall be ordered by the speed with which a dimension varies:
+\fIdimids\fP[\fIndims\fP-1]
+shall be the dimension ID of the most rapidly
+varying dimension and
+\fIdimids\fP[0]
+shall be the dimension ID of the most slowly
+varying dimension.
+The maximum possible number of
+dimensions for a variable is given by the symbolic constant
+\fBNC_MAX_VAR_DIMS\fR.
+.TP
+int \fIdimid\fP
+is the ID of a netCDF dimension.
+netCDF dimension ID's are allocated sequentially from the 
+non-negative
+integers beginning with 0.
+.TP
+int \fIndims\fP
+is either the total number of dimensions in a netCDF dataset or the rank
+(i.e. the number of dimensions) of a netCDF variable.
+The value shall not be negative or greater than the symbolic constant 
+\fBNC_MAX_VAR_DIMS\fR.
+.TP
+int \fIvarid\fP
+is the ID of a netCDF variable or (for the attribute-access functions) 
+the symbolic constant
+\fBNC_GLOBAL\fR,
+which is used to reference global attributes.
+netCDF variable ID's are allocated sequentially from the 
+non-negative
+integers beginning with 0.
+.TP
+int* \fInatts\fP
+is the number of global attributes in a netCDF dataset  for the
+\fBncmpi_inquire(\|)\fR
+function or the number
+of attributes associated with a netCDF variable for the
+\fBncmpi_varinq(\|)\fR
+function.
+.TP
+const size_t \fIindex\fP[]
+specifies the indicial coordinates of the netCDF data value to be accessed.
+The indices start at 0;
+thus, for example, the first data value of a
+two-dimensional variable is (0,0).
+The size of the vector shall be at least the rank of the associated
+netCDF variable and its elements shall correspond, in order, to the
+variable's dimensions.
+.TP
+const size_t \fIstart\fP[]
+specifies the starting point
+for accessing a netCDF variable's data values
+in terms of the indicial coordinates of 
+the corner of the array section.
+The indices start at 0;
+thus, the first data
+value of a variable is (0, 0, ..., 0).
+The size of the vector shall be at least the rank of the associated
+netCDF variable and its elements shall correspond, in order, to the
+variable's dimensions.
+.TP
+const size_t \fIcount\fP[]
+specifies the number of indices selected along each dimension of the
+array section.
+Thus, to access a single value, for example, specify \fIcount\fP as
+(1, 1, ..., 1).
+Note that, for strided I/O, this argument must be adjusted
+to be compatible with the \fIstride\fP and \fIstart\fP arguments so that 
+the interaction of the
+three does not attempt to access an invalid data co-ordinate.
+The elements of the
+\fIcount\fP vector correspond, in order, to the variable's dimensions.
+.TP
+const size_t \fIstride\fP[]
+specifies the sampling interval along each dimension of the netCDF
+variable.   The elements of the stride vector correspond, in order,
+to the netCDF variable's dimensions (\fIstride\fP[0])
+gives the sampling interval along the most slowly 
+varying dimension of the netCDF variable).  Sampling intervals are
+specified in type-independent units of elements (a value of 1 selects
+consecutive elements of the netCDF variable along the corresponding
+dimension, a value of 2 selects every other element, etc.).
+A \fBNULL\fR stride argument is treated as (1, 1, ... , 1).
+.TP
+\fIimap\fP
+specifies the mapping between the dimensions of a netCDF variable and
+the in-memory structure of the internal data array.  The elements of
+the index mapping vector correspond, in order, to the netCDF variable's
+dimensions (\fIimap\fP[0] gives the distance
+between elements of the internal array corresponding to the most
+slowly varying dimension of the netCDF variable).
+Distances between elements are specified in type-independent units of
+elements (the distance between internal elements that occupy adjacent
+memory locations is 1 and not the element's byte-length as in netCDF 2).
+A \fBNULL\fR pointer means the memory-resident values have
+the same structure as the associated netCDF variable.
+.SH "VARIABLE PREFILLING"
+.LP
+By default, the netCDF interface sets the values of
+all newly-defined variables of finite length (i.e. those that do not have
+an unlimited, dimension) to the type-dependent fill-value associated with each 
+variable.  This is done when \fBncmpi_enddef(\|)\fR
+is called.  The
+fill-value for a variable may be changed from the default value by
+defining the attribute `\fB_FillValue\fR' for the variable.  This
+attribute must have the same type as the variable and be of length one.
+.LP
+Variables with an unlimited dimension are also prefilled, but on
+an `as needed' basis.  For example, if the first write of such a
+variable is to position 5, then
+positions
+0 through 4
+(and no others)
+would be set to the fill-value at the same time.
+.LP
+This default prefilling of data values may be disabled by
+or'ing the
+\fBNC_NOFILL\fR
+flag into the mode parameter of \fBncmpi_open(\|)\fR or \fBncmpi_create(\|)\fR,
+or, by calling the function \fBncmpi_set_fill(\|)\fR
+with the argument \fBNC_NOFILL\fR.
+For variables that do not use the unlimited dimension,
+this call must
+be made before
+\fBncmpi_enddef(\|)\fR.
+For variables that
+use the unlimited dimension, this call
+may be made at any time.
+.LP
+One can obtain increased performance of the netCDF interface by using 
+this feature, but only at the expense of requiring the application to set
+every single data value.  The performance
+enhancing behavior of this function is dependent on the particulars of
+the implementation and dataset format.
+The flag value controlled by \fBncmpi_set_fill(\|)\fR
+is per netCDF ID,
+not per variable or per write. 
+Allowing this to change affects the degree to which
+a program can be effectively parallelized.
+Given all of this, we state that the use
+of this feature may not be available (or even needed) in future
+releases. Programmers are cautioned against heavy reliance upon this
+feature.
+.HP
+\fBint ncmpi_setfill(int \fIncid\fP, int \fIfillmode\fP, int* \fIold_fillemode\fP)\fR
+.sp
+(Corresponds to \fBncsetfill(\|)\fR in version 2)
+.sp
+Determines whether or not variable prefilling will be done (see 
+above).
+The netCDF dataset shall be writable.
+\fIfillmode\fP is either \fBNC_FILL\fR
+to enable prefilling (the
+default) or \fBNC_NOFILL\fR
+to disable prefilling.
+This function returns the previous setting in \fIold_fillmode\fP.
+.SH "MPP FUNCTION DESCRIPTIONS"
+.LP
+Additional functions for use on SGI/Cray MPP machines (_CRAYMPP).
+These are used to set and inquire which PE is the base for MPP
+for a particular netCDF. These are only relevant when
+using the SGI/Cray ``global''
+Flexible File I/O layer and desire to have
+only a subset of PEs to open the specific netCDF file.
+For technical reasons, these functions are available on all platforms.
+On a platform other than SGI/Cray MPP, it is as if
+only processor available were processor 0.
+.LP
+To use this feature, you need to specify a communicator group and call
+\fBglio_group_mpi(\|)\fR or \fBglio_group_shmem(\|)\fR prior to the netCDF
+\fBncmpi_open(\|)\fR and \fBncmpi_create(\|)\fR calls.
+.HP
+\fBint ncmpi__create_mp(const char \fIpath\fP[], int \fIcmode\fP, size_t \fIinitialsize\fP, int \fIpe\fP, size_t* \fIchunksize\fP, int* \fIncid\fP)\fR
+.sp
+Like \fBncmpi__create(\|)\fR but allows the base PE to be set.
+.sp
+The argument \fIpe\fP sets the base PE at creation time. In the MPP
+environment, \fBncmpi__create(\|)\fR and \fBncmpi_create(\|)\fR set the base PE to processor
+zero by default.
+.HP
+\fBint ncmpi__open_mp(const char \fIpath\fP[], int \fImode\fP, int \fIpe\fP, size_t* \fIchunksize\fP, int* \fIncid\fP)\fR
+.sp
+Like \fBncmpi__open(\|)\fR but allows the base PE to be set.
+The argument \fIpe\fP sets the base PE at creation time. In the MPP
+environment, \fBncmpi__open(\|)\fR and \fBncmpi_open(\|)\fR set the base PE to processor
+zero by default.
+.HP
+\fBint ncmpi_inq_base_pe(int \fIncid\fP, int* \fIpe\fP)\fR
+.sp
+Inquires of the netCDF dataset which PE is being used as the base for MPP use.
+This is safe to use at any time.
+.HP
+\fBint ncmpi_set_base_pe(int \fIncid\fP, int \fIpe\fP)\fR
+.sp
+Resets the base PE for the netCDF dataset.
+Only perform this operation when the affected communicator group
+synchronizes before and after the call.
+This operation is very risky and should only be contemplated
+under only the most extreme cases.
+.SH "ENVIRONMENT VARIABLES"
+.TP 4
+.B NETCDF_FFIOSPEC
+Specifies the Flexible File I/O buffers for netCDF I/O when executing
+under the UNICOS operating system (the variable is ignored on other
+operating systems).
+An appropriate specification can greatly increase the efficiency of 
+netCDF I/O -- to the extent that it can actually surpass FORTRAN binary 
+I/O.
+This environment variable has been made a little more generalized,
+such that other FFIO option specifications can now be added.
+The default specification is \fBbufa:336:2\fP,
+unless a current FFIO specification is in operation,
+which will be honored.
+See UNICOS Flexible File I/O for more information.
+.SH "MAILING-LISTS"
+.LP
+Both a mailing list and a digest are available for
+discussion of the netCDF interface and announcements about netCDF bugs,
+fixes, and enhancements.
+To begin or change your subscription to either the mailing-list or the
+digest, send one of the following in the body (not
+the subject line) of an email message to "majordomo@unidata.ucar.edu".
+Use your email address in place of \fIjdoe@host.inst.domain\fP.
+.sp
+To subscribe to the netCDF mailing list:
+.RS
+\fBsubscribe netcdfgroup \fIjdoe@host.inst.domain\fR
+.RE
+To unsubscribe from the netCDF mailing list:
+.RS
+\fBunsubscribe netcdfgroup \fIjdoe@host.inst.domain\fR
+.RE
+To subscribe to the netCDF digest:
+.RS
+\fBsubscribe netcdfdigest \fIjdoe@host.inst.domain\fR
+.RE
+To unsubscribe from the netCDF digest:
+.RS
+\fBunsubscribe netcdfdigest \fIjdoe@host.inst.domain\fR
+.RE
+To retrieve the general introductory information for the mailing list:
+.RS
+\fBinfo netcdfgroup\fR
+.RE
+To get a synopsis of other majordomo commands:
+.RS
+\fBhelp\fR
+.RE
+.SH "SEE ALSO"
+.LP
+.BR ncdump (1),
+.BR ncgen (1),
+.BR netcdf (3).
+.LP
+\fInetCDF User's Guide\fP, published
+by the Unidata Program Center, University Corporation for Atmospheric
+Research, located in Boulder, Colorado.
Index: /branches/SDM_SciDAC/src/lib/v1hpg.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/v1hpg.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/v1hpg.c (revision 2)
@@ -0,0 +1,1322 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "nc.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "rnd.h"
+#include "ncx.h"
+
+/*
+ * This module defines the external representation
+ * of the "header" of a netcdf version one file.
+ * For each of the components of the NC structure,
+ * There are (static) ncx_len_XXX(), ncx_put_XXX()
+ * and v1h_get_XXX() functions. These define the
+ * external representation of the components.
+ * The exported entry points for the whole NC structure
+ * are built up from these.
+ */
+
+
+/*
+ * "magic number" at beginning of file: 0x43444601 (big endian)
+ * assert(sizeof(ncmagic) % X_ALIGN == 0);
+ */
+static const schar ncmagic[] = {'C', 'D', 'F', 0x01};
+
+
+/*
+ * v1hs == "Version 1 Header Stream"
+ *
+ * The netcdf file version 1 header is
+ * of unknown and potentially unlimited size.
+ * So, we don't know how much to get() on
+ * the initial read. We build a stream, 'v1hs'
+ * on top of ncio to do the header get.
+ */
+typedef struct v1hs {
+	ncio *nciop;
+	off_t offset;	/* argument to nciop->get() */
+	size_t extent;	/* argument to nciop->get() */
+	int flags;	/* set to RGN_WRITE for write */
+	void *base;	/* beginning of current buffer */
+	void *pos;	/* current position in buffer */
+	void *end;	/* end of current buffer = base + extent */
+} v1hs;
+
+
+/*
+ * Release the stream, invalidate buffer
+ */
+static int
+rel_v1hs(v1hs *gsp)
+{
+	int status;
+	if(gsp->offset == OFF_NONE || gsp->base == NULL)
+		return ENOERR;
+	status = gsp->nciop->rel(gsp->nciop, gsp->offset,
+			 gsp->flags == RGN_WRITE ? RGN_MODIFIED : 0);
+	gsp->end = NULL;
+	gsp->pos = NULL;
+	gsp->base = NULL;
+	return status;
+}
+
+
+/*
+ * Release the current chunk and get the next one.
+ * Also used for initialization when gsp->base == NULL.
+ */
+static int
+fault_v1hs(v1hs *gsp, size_t extent)
+{
+	int status;
+
+	if(gsp->base != NULL)
+	{
+		const size_t incr = (char *)gsp->pos - (char *)gsp->base;
+		status = rel_v1hs(gsp);
+		if(status)
+			return status;
+		gsp->offset += incr;
+	}
+	
+	if(extent > gsp->extent)
+		gsp->extent = extent;	
+
+	status = gsp->nciop->get(gsp->nciop,
+		 	gsp->offset, gsp->extent,
+			gsp->flags, &gsp->base);
+	if(status)
+		return status;
+
+	gsp->pos = gsp->base;
+	gsp->end = (char *)gsp->base + gsp->extent;
+
+	return ENOERR;
+}
+
+
+/*
+ * Ensure that 'nextread' bytes are available.
+ */
+static int
+check_v1hs(v1hs *gsp, size_t nextread)
+{
+
+#if 0 /* DEBUG */
+fprintf(stderr, "nextread %lu, remaining %lu\n",
+	(unsigned long)nextread,
+	(unsigned long)((char *)gsp->end - (char *)gsp->pos));
+#endif
+
+	if((char *)gsp->pos + nextread <= (char *)gsp->end)
+		return ENOERR;
+	return fault_v1hs(gsp, nextread);
+}
+
+/* End v1hs */
+
+static int
+v1h_put_size_t(v1hs *psp, const size_t *sp)
+{
+	int status = check_v1hs(psp, X_SIZEOF_SIZE_T);
+	if(status != ENOERR)
+		return status;
+	return ncx_put_size_t(&psp->pos, sp);
+}
+
+
+static int
+v1h_get_size_t(v1hs *gsp, size_t *sp)
+{
+	int status = check_v1hs(gsp, X_SIZEOF_SIZE_T);
+	if(status != ENOERR)
+		return status;
+	return ncx_get_size_t((const void **)(&gsp->pos), sp);
+}
+
+
+/* Begin nc_type */
+
+#define X_SIZEOF_NC_TYPE X_SIZEOF_INT
+
+static int
+v1h_put_nc_type(v1hs *psp, const nc_type *typep)
+{
+	const int itype = (int) *typep;
+	int status = check_v1hs(psp, X_SIZEOF_INT);
+	if(status != ENOERR)
+		return status;
+	status =  ncx_put_int_int(psp->pos, &itype);
+	psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT);
+	return status;
+}
+
+
+static int
+v1h_get_nc_type(v1hs *gsp, nc_type *typep)
+{
+	int type = 0;
+	int status = check_v1hs(gsp, X_SIZEOF_INT);
+	if(status != ENOERR)
+		return status;
+	status =  ncx_get_int_int(gsp->pos, &type);
+	gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT);
+	if(status != ENOERR)
+		return status;
+
+	assert(type == NC_BYTE
+		|| type == NC_CHAR
+		|| type == NC_SHORT
+		|| type == NC_INT
+		|| type == NC_FLOAT
+		|| type == NC_DOUBLE);
+
+	/* else */
+	*typep = (nc_type) type;
+
+	return ENOERR;
+}
+
+/* End nc_type */
+/* Begin NCtype (internal tags) */
+
+#define X_SIZEOF_NCTYPE X_SIZEOF_INT
+
+static int
+v1h_put_NCtype(v1hs *psp, NCtype type)
+{
+	const int itype = (int) type;
+	int status = check_v1hs(psp, X_SIZEOF_INT);
+	if(status != ENOERR)
+		return status;
+	status = ncx_put_int_int(psp->pos, &itype);
+	psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT);
+	return status;
+}
+
+static int
+v1h_get_NCtype(v1hs *gsp, NCtype *typep)
+{
+	int type = 0;
+	int status = check_v1hs(gsp, X_SIZEOF_INT);
+	if(status != ENOERR)
+		return status;
+	status =  ncx_get_int_int(gsp->pos, &type);
+	gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT);
+	if(status != ENOERR)
+		return status;
+	/* else */
+	*typep = (NCtype) type;
+	return ENOERR;
+}
+
+/* End NCtype */
+/* Begin NC_string */
+
+/*
+ * How much space will the xdr'd string take.
+ * Formerly
+NC_xlen_string(cdfstr)
+ */
+static size_t
+ncx_len_NC_string(const NC_string *ncstrp)
+{
+	size_t sz = X_SIZEOF_SIZE_T; /* nchars */
+
+	assert(ncstrp != NULL);
+
+	if(ncstrp->nchars != 0) 
+	{
+#if 0
+		assert(ncstrp->nchars % X_ALIGN == 0);
+		sz += ncstrp->nchars;
+#else
+		sz += _RNDUP(ncstrp->nchars, X_ALIGN);
+#endif
+	}
+	return sz;
+}
+
+
+static int
+v1h_put_NC_string(v1hs *psp, const NC_string *ncstrp)
+{
+	int status;
+
+#if 0
+	assert(ncstrp->nchars % X_ALIGN == 0);
+#endif
+
+	status = v1h_put_size_t(psp, &ncstrp->nchars);
+	if(status != ENOERR)
+		return status;
+	status = check_v1hs(psp, _RNDUP(ncstrp->nchars, X_ALIGN));
+	if(status != ENOERR)
+		return status;
+	status = ncx_pad_putn_text(&psp->pos, ncstrp->nchars, ncstrp->cp);
+	if(status != ENOERR)
+		return status;
+
+	return ENOERR;
+}
+
+
+static int
+v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp)
+{
+	int status;
+	size_t nchars = 0;
+	NC_string *ncstrp;
+
+	status = v1h_get_size_t(gsp, &nchars);
+	if(status != ENOERR)
+		return status;
+
+	ncstrp = new_NC_string(nchars, NULL);
+	if(ncstrp == NULL)
+	{
+		return NC_ENOMEM;
+	}
+
+
+#if 0
+/* assert(ncstrp->nchars == nchars || ncstrp->nchars - nchars < X_ALIGN); */
+	assert(ncstrp->nchars % X_ALIGN == 0);
+	status = check_v1hs(gsp, ncstrp->nchars);
+#else
+	
+	status = check_v1hs(gsp, _RNDUP(ncstrp->nchars, X_ALIGN));
+#endif
+	if(status != ENOERR)
+		goto unwind_alloc;
+
+	status = ncx_pad_getn_text((const void **)(&gsp->pos),
+		 nchars, ncstrp->cp);
+	if(status != ENOERR)
+		goto unwind_alloc;
+
+	*ncstrpp = ncstrp;
+
+	return ENOERR;
+
+unwind_alloc:
+	free_NC_string(ncstrp);
+	return status;
+	
+}
+
+/* End NC_string */
+/* Begin NC_dim */
+
+/*
+ * How much space will the xdr'd dim take.
+ * Formerly
+NC_xlen_dim(dpp)
+ */
+static size_t
+ncx_len_NC_dim(const NC_dim *dimp)
+{
+	size_t sz;
+
+	assert(dimp != NULL);
+
+	sz = ncx_len_NC_string(dimp->name);
+	sz += X_SIZEOF_SIZE_T;
+
+	return(sz);
+}
+
+
+static int
+v1h_put_NC_dim(v1hs *psp, const NC_dim *dimp)
+{
+	int status;
+
+	status = v1h_put_NC_string(psp, dimp->name);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_size_t(psp, &dimp->size);
+	if(status != ENOERR)
+		return status;
+
+	return ENOERR;
+}
+
+static int
+v1h_get_NC_dim(v1hs *gsp, NC_dim **dimpp)
+{
+	int status;
+	NC_string *ncstrp;
+	NC_dim *dimp;
+
+	status = v1h_get_NC_string(gsp, &ncstrp);
+	if(status != ENOERR)
+		return status;
+
+	dimp = new_x_NC_dim(ncstrp);
+	if(dimp == NULL)
+	{
+		status = NC_ENOMEM;
+		goto unwind_name;
+	}
+
+	status = v1h_get_size_t(gsp, &dimp->size);
+	if(status != ENOERR)
+	{
+		free_NC_dim(dimp); /* frees name */
+		return status;
+	}
+
+	*dimpp = dimp;
+
+	return ENOERR;
+
+unwind_name:
+	free_NC_string(ncstrp);
+	return status;
+}
+
+
+static size_t
+ncx_len_NC_dimarray(const NC_dimarray *ncap)
+{
+	size_t xlen = X_SIZEOF_NCTYPE;	/* type */
+	xlen += X_SIZEOF_SIZE_T;	/* count */
+	if(ncap == NULL)
+		return xlen;
+	/* else */
+	{
+		const NC_dim **dpp = (const NC_dim **)ncap->value;
+		const NC_dim *const *const end = &dpp[ncap->nelems];
+		for(  /*NADA*/; dpp < end; dpp++)
+		{
+			xlen += ncx_len_NC_dim(*dpp);
+		}
+	}
+	return xlen;
+}
+
+
+static int
+v1h_put_NC_dimarray(v1hs *psp, const NC_dimarray *ncap)
+{
+	int status;
+
+	assert(psp != NULL);
+
+	if(ncap == NULL
+#if 1
+		/* Backward:
+		 * This clause is for 'byte for byte'
+		 * backward compatibility.
+		 * Strickly speaking, it is 'bug for bug'.
+		 */
+		|| ncap->nelems == 0
+#endif
+		)
+	{
+		/*
+		 * Handle empty netcdf
+		 */
+		const size_t nosz = 0;
+
+		status = v1h_put_NCtype(psp, NC_UNSPECIFIED);
+		if(status != ENOERR)
+			return status;
+		status = v1h_put_size_t(psp, &nosz);
+		if(status != ENOERR)
+			return status;
+		return ENOERR;
+	}
+	/* else */
+
+	status = v1h_put_NCtype(psp, NC_DIMENSION);
+	if(status != ENOERR)
+		return status;
+	status = v1h_put_size_t(psp, &ncap->nelems);
+	if(status != ENOERR)
+		return status;
+
+	{
+		const NC_dim **dpp = (const NC_dim **)ncap->value;
+		const NC_dim *const *const end = &dpp[ncap->nelems];
+		for( /*NADA*/; dpp < end; dpp++)
+		{
+			status = v1h_put_NC_dim(psp, *dpp);
+			if(status)
+				return status;
+		}
+	}
+	return ENOERR;
+}
+
+
+static int
+v1h_get_NC_dimarray(v1hs *gsp, NC_dimarray *ncap)
+{
+	int status;
+	NCtype type = NC_UNSPECIFIED;
+
+	assert(gsp != NULL && gsp->pos != NULL);
+	assert(ncap != NULL);
+	assert(ncap->value == NULL);
+
+	status = v1h_get_NCtype(gsp, &type);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_get_size_t(gsp, &ncap->nelems);
+	if(status != ENOERR)
+		return status;
+	
+	if(ncap->nelems == 0)
+		return ENOERR;
+	/* else */
+	if(type != NC_DIMENSION)
+		return EINVAL;
+
+	ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *));
+	if(ncap->value == NULL)
+		return NC_ENOMEM;
+	ncap->nalloc = ncap->nelems;
+
+	{
+		NC_dim **dpp = ncap->value;
+		NC_dim *const *const end = &dpp[ncap->nelems];
+		for( /*NADA*/; dpp < end; dpp++)
+		{
+			status = v1h_get_NC_dim(gsp, dpp);
+			if(status)
+			{
+				ncap->nelems = dpp - ncap->value;
+				free_NC_dimarrayV(ncap);
+				return status;
+			}
+		}
+	}
+
+	return ENOERR;
+}
+
+
+/* End NC_dim */
+/* Begin NC_attr */
+
+
+/*
+ * How much space will 'attrp' take in external representation?
+ * Formerly
+NC_xlen_attr(app)
+ */
+static size_t
+ncx_len_NC_attr(const NC_attr *attrp)
+{
+	size_t sz;
+
+	assert(attrp != NULL);
+
+	sz = ncx_len_NC_string(attrp->name);
+	sz += X_SIZEOF_NC_TYPE; /* type */
+	sz += X_SIZEOF_SIZE_T; /* nelems */
+	sz += attrp->xsz;
+
+	return(sz);
+}
+
+
+#undef MIN
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+
+/*
+ * Put the values of an attribute
+ * The loop is necessary since attrp->nelems
+ * could potentially be quite large.
+ */
+static int
+v1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp)
+{
+	int status;
+	const size_t perchunk =  psp->extent;
+	size_t remaining = attrp->xsz;
+	void *value = attrp->xvalue;
+	size_t nbytes; 
+
+	assert(psp->extent % X_ALIGN == 0);
+	
+	do {
+		nbytes = MIN(perchunk, remaining);
+	
+		status = check_v1hs(psp, nbytes);
+		if(status != ENOERR)
+			return status;
+	
+		(void) memcpy(psp->pos, value, nbytes);
+
+		psp->pos = (void *)((char *)psp->pos + nbytes);
+		value = (void *)((char *)value + nbytes);
+		remaining -= nbytes;
+
+	} while(remaining != 0); 
+
+	return ENOERR;
+}
+
+static int
+v1h_put_NC_attr(v1hs *psp, const NC_attr *attrp)
+{
+	int status;
+
+	status = v1h_put_NC_string(psp, attrp->name);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_nc_type(psp, &attrp->type);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_size_t(psp, &attrp->nelems);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_NC_attrV(psp, attrp);
+	if(status != ENOERR)
+		return status;
+
+	return ENOERR;
+}
+
+
+/*
+ * Get the values of an attribute
+ * The loop is necessary since attrp->nelems
+ * could potentially be quite large.
+ */
+static int
+v1h_get_NC_attrV(v1hs *gsp, NC_attr *attrp)
+{
+	int status;
+	const size_t perchunk =  gsp->extent;
+	size_t remaining = attrp->xsz;
+	void *value = attrp->xvalue;
+	size_t nget; 
+
+	assert(gsp->extent % X_ALIGN == 0);
+	
+	do {
+		nget = MIN(perchunk, remaining);
+	
+		status = check_v1hs(gsp, nget);
+		if(status != ENOERR)
+			return status;
+	
+		(void) memcpy(value, gsp->pos, nget);
+
+		gsp->pos = (void *)((char *)gsp->pos + nget);
+		value = (void *)((char *)value + nget);
+		remaining -= nget;
+
+	} while(remaining != 0); 
+
+	return ENOERR;
+}
+
+
+static int
+v1h_get_NC_attr(v1hs *gsp, NC_attr **attrpp)
+{
+	NC_string *strp;
+	int status;
+	nc_type type;
+	size_t nelems;
+	NC_attr *attrp;
+
+	status = v1h_get_NC_string(gsp, &strp);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_get_nc_type(gsp, &type);
+	if(status != ENOERR)
+		goto unwind_name;
+
+	status = v1h_get_size_t(gsp, &nelems);
+	if(status != ENOERR)
+		goto unwind_name;
+
+	attrp = new_x_NC_attr(strp, type, nelems);
+	if(attrp == NULL)
+	{
+		status = NC_ENOMEM;
+		goto unwind_name;
+	}
+	
+	status = v1h_get_NC_attrV(gsp, attrp);
+	if(status != ENOERR)
+	{
+		free_NC_attr(attrp); /* frees strp */
+		return status;
+	}
+
+	*attrpp = attrp;
+
+	return ENOERR;
+
+unwind_name:
+	free_NC_string(strp);
+	return status;
+}
+
+
+static size_t
+ncx_len_NC_attrarray(const NC_attrarray *ncap)
+{
+	size_t xlen = X_SIZEOF_NCTYPE;	/* type */
+	xlen += X_SIZEOF_SIZE_T;	/* count */
+	if(ncap == NULL)
+		return xlen;
+	/* else */
+	{
+		const NC_attr **app = (const NC_attr **)ncap->value;
+		const NC_attr *const *const end = &app[ncap->nelems];
+		for( /*NADA*/; app < end; app++)
+		{
+			xlen += ncx_len_NC_attr(*app);
+		}
+	}
+	return xlen;
+}
+
+
+static int
+v1h_put_NC_attrarray(v1hs *psp, const NC_attrarray *ncap)
+{
+	int status;
+
+	assert(psp != NULL);
+
+	if(ncap == NULL
+#if 1
+		/* Backward:
+		 * This clause is for 'byte for byte'
+		 * backward compatibility.
+		 * Strickly speaking, it is 'bug for bug'.
+		 */
+		|| ncap->nelems == 0
+#endif
+		)
+	{
+		/*
+		 * Handle empty netcdf
+		 */
+		const size_t nosz = 0;
+
+		status = v1h_put_NCtype(psp, NC_UNSPECIFIED);
+		if(status != ENOERR)
+			return status;
+		status = v1h_put_size_t(psp, &nosz);
+		if(status != ENOERR)
+			return status;
+		return ENOERR;
+	}
+	/* else */
+
+	status = v1h_put_NCtype(psp, NC_ATTRIBUTE);
+	if(status != ENOERR)
+		return status;
+	status = v1h_put_size_t(psp, &ncap->nelems);
+	if(status != ENOERR)
+		return status;
+
+	{
+		const NC_attr **app = (const NC_attr **)ncap->value;
+		const NC_attr *const *const end = &app[ncap->nelems];
+		for( /*NADA*/; app < end; app++)
+		{
+			status = v1h_put_NC_attr(psp, *app);
+			if(status)
+				return status;
+		}
+	}
+	return ENOERR;
+}
+
+
+static int
+v1h_get_NC_attrarray(v1hs *gsp, NC_attrarray *ncap)
+{
+	int status;
+	NCtype type = NC_UNSPECIFIED;
+
+	assert(gsp != NULL && gsp->pos != NULL);
+	assert(ncap != NULL);
+	assert(ncap->value == NULL);
+
+	status = v1h_get_NCtype(gsp, &type);
+	if(status != ENOERR)
+		return status;
+	status = v1h_get_size_t(gsp, &ncap->nelems);
+	if(status != ENOERR)
+		return status;
+	
+	if(ncap->nelems == 0)
+		return ENOERR;
+	/* else */
+	if(type != NC_ATTRIBUTE)
+		return EINVAL;
+
+	ncap->value = (NC_attr **) malloc(ncap->nelems * sizeof(NC_attr *));
+	if(ncap->value == NULL)
+		return NC_ENOMEM;
+	ncap->nalloc = ncap->nelems;
+
+	{
+		NC_attr **app = ncap->value;
+		NC_attr *const *const end = &app[ncap->nelems];
+		for( /*NADA*/; app < end; app++)
+		{
+			status = v1h_get_NC_attr(gsp, app);
+			if(status)
+			{
+				ncap->nelems = app - ncap->value;
+				free_NC_attrarrayV(ncap);
+				return status;
+			}
+		}
+	}
+
+	return ENOERR;
+}
+
+/* End NC_attr */
+/* Begin NC_var */
+
+/*
+ * How much space will the xdr'd var take.
+ * Formerly
+NC_xlen_var(vpp)
+ */
+static size_t
+ncx_len_NC_var(const NC_var *varp)
+{
+	size_t sz;
+
+	assert(varp != NULL);
+
+	sz = ncx_len_NC_string(varp->name);
+	sz += X_SIZEOF_SIZE_T; /* ndims */
+	sz += ncx_len_int(varp->ndims); /* dimids */
+	sz += ncx_len_NC_attrarray(&varp->attrs);
+	sz += X_SIZEOF_NC_TYPE; /* type */
+	sz += X_SIZEOF_SIZE_T; /* len */
+	sz += X_SIZEOF_OFF_T; /* begin */
+
+	return(sz);
+}
+
+
+static int
+v1h_put_NC_var(v1hs *psp, const NC_var *varp)
+{
+	int status;
+
+	status = v1h_put_NC_string(psp, varp->name);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_size_t(psp, &varp->ndims);
+	if(status != ENOERR)
+		return status;
+
+	status = check_v1hs(psp, ncx_len_int(varp->ndims));
+	if(status != ENOERR)
+		return status;
+	status = ncx_putn_int_int(&psp->pos,
+			varp->ndims, varp->dimids);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_NC_attrarray(psp, &varp->attrs);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_nc_type(psp, &varp->type);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_put_size_t(psp, &varp->len);
+	if(status != ENOERR)
+		return status;
+
+	status = check_v1hs(psp, X_SIZEOF_OFF_T);
+	if(status != ENOERR)
+		 return status;
+	status = ncx_put_off_t(&psp->pos, &varp->begin);
+	if(status != ENOERR)
+		return status;
+
+	return ENOERR;
+}
+
+
+static int
+v1h_get_NC_var(v1hs *gsp, NC_var **varpp)
+{
+	NC_string *strp;
+	int status;
+	size_t ndims;
+	NC_var *varp;
+
+	status = v1h_get_NC_string(gsp, &strp);
+	if(status != ENOERR)
+		return status;
+
+	status = v1h_get_size_t(gsp, &ndims);
+	if(status != ENOERR)
+		goto unwind_name;
+
+	varp = new_x_NC_var(strp, ndims);
+	if(varp == NULL)
+	{
+		status = NC_ENOMEM;
+		goto unwind_name;
+	}
+
+	status = check_v1hs(gsp, ncx_len_int(ndims));
+	if(status != ENOERR)
+		goto unwind_alloc;
+	status = ncx_getn_int_int((const void **)(&gsp->pos),
+			ndims, varp->dimids);
+	if(status != ENOERR)
+		goto unwind_alloc;
+
+	status = v1h_get_NC_attrarray(gsp, &varp->attrs);
+	if(status != ENOERR)
+		goto unwind_alloc;
+
+	status = v1h_get_nc_type(gsp, &varp->type);
+	if(status != ENOERR)
+		 goto unwind_alloc;
+
+	status = v1h_get_size_t(gsp, &varp->len);
+	if(status != ENOERR)
+		 goto unwind_alloc;
+
+	status = check_v1hs(gsp, X_SIZEOF_OFF_T);
+	if(status != ENOERR)
+		 goto unwind_alloc;
+	status = ncx_get_off_t((const void **)&gsp->pos,
+			&varp->begin);
+	if(status != ENOERR)
+		 goto unwind_alloc;
+	
+	*varpp = varp;
+	return ENOERR;
+
+unwind_alloc:
+	free_NC_var(varp); /* frees name */
+	return status;
+
+unwind_name:
+	free_NC_string(strp);
+	return status;
+}
+
+
+static size_t
+ncx_len_NC_vararray(const NC_vararray *ncap)
+{
+	size_t xlen = X_SIZEOF_NCTYPE;	/* type */
+	xlen += X_SIZEOF_SIZE_T;	/* count */
+	if(ncap == NULL)
+		return xlen;
+	/* else */
+	{
+		const NC_var **vpp = (const NC_var **)ncap->value;
+		const NC_var *const *const end = &vpp[ncap->nelems];
+		for( /*NADA*/; vpp < end; vpp++)
+		{
+			xlen += ncx_len_NC_var(*vpp);
+		}
+	}
+	return xlen;
+}
+
+
+static int
+v1h_put_NC_vararray(v1hs *psp, const NC_vararray *ncap)
+{
+	int status;
+
+	assert(psp != NULL);
+
+	if(ncap == NULL
+#if 1
+		/* Backward:
+		 * This clause is for 'byte for byte'
+		 * backward compatibility.
+		 * Strickly speaking, it is 'bug for bug'.
+		 */
+		|| ncap->nelems == 0
+#endif
+		)
+	{
+		/*
+		 * Handle empty netcdf
+		 */
+		const size_t nosz = 0;
+
+		status = v1h_put_NCtype(psp, NC_UNSPECIFIED);
+		if(status != ENOERR)
+			return status;
+		status = v1h_put_size_t(psp, &nosz);
+		if(status != ENOERR)
+			return status;
+		return ENOERR;
+	}
+	/* else */
+
+	status = v1h_put_NCtype(psp, NC_VARIABLE);
+	if(status != ENOERR)
+		return status;
+	status = v1h_put_size_t(psp, &ncap->nelems);
+	if(status != ENOERR)
+		return status;
+
+	{
+		const NC_var **vpp = (const NC_var **)ncap->value;
+		const NC_var *const *const end = &vpp[ncap->nelems];
+		for( /*NADA*/; vpp < end; vpp++)
+		{
+			status = v1h_put_NC_var(psp, *vpp);
+			if(status)
+				return status;
+		}
+	}
+	return ENOERR;
+}
+
+
+static int
+v1h_get_NC_vararray(v1hs *gsp, NC_vararray *ncap)
+{
+	int status;
+	NCtype type = NC_UNSPECIFIED;
+
+	assert(gsp != NULL && gsp->pos != NULL);
+	assert(ncap != NULL);
+	assert(ncap->value == NULL);
+
+	status = v1h_get_NCtype(gsp, &type);
+	if(status != ENOERR)
+		return status;
+	
+	status = v1h_get_size_t(gsp, &ncap->nelems);
+	if(status != ENOERR)
+		return status;
+	
+	if(ncap->nelems == 0)
+		return ENOERR;
+	/* else */
+	if(type != NC_VARIABLE)
+		return EINVAL;
+
+	ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *));
+	if(ncap->value == NULL)
+		return NC_ENOMEM;
+	ncap->nalloc = ncap->nelems;
+
+	{
+		NC_var **vpp = ncap->value;
+		NC_var *const *const end = &vpp[ncap->nelems];
+		for( /*NADA*/; vpp < end; vpp++)
+		{
+			status = v1h_get_NC_var(gsp, vpp);
+			if(status)
+			{
+				ncap->nelems = vpp - ncap->value;
+				free_NC_vararrayV(ncap);
+				return status;
+			}
+		}
+	}
+
+	return ENOERR;
+}
+
+
+/* End NC_var */
+/* Begin NC */
+
+
+/*
+ * Recompute the shapes of all variables
+ * Sets ncp->begin_var to start of first variable.
+ * Sets ncp->begin_rec to start of first record variable.
+ * Returns -1 on error. The only possible error is an reference
+ * to a non existent dimension, which would occur for a corrupt
+ * netcdf file.
+ */
+static int
+NC_computeshapes(NC *ncp)
+{
+	NC_var **vpp = (NC_var **)ncp->vars.value;
+	NC_var *const *const end = &vpp[ncp->vars.nelems];
+	NC_var *first_var = NULL;	/* first "non-record" var */
+	NC_var *first_rec = NULL;	/* first "record" var */
+	int status;
+
+	ncp->begin_var = (off_t) ncp->xsz;
+	ncp->begin_rec = (off_t) ncp->xsz;
+	ncp->recsize = 0;
+
+	if(ncp->vars.nelems == 0)
+		return(0);
+	
+	for( /*NADA*/; vpp < end; vpp++)
+	{
+		status = NC_var_shape(*vpp, &ncp->dims);
+		if(status != ENOERR)
+			return(status);
+
+	  	if(IS_RECVAR(*vpp))	
+		{
+	  		if(first_rec == NULL)	
+				first_rec = *vpp;
+			ncp->recsize += (*vpp)->len;
+		}
+		else if(first_var == NULL)
+		{
+			first_var = *vpp;
+			/*
+			 * Overwritten each time thru.
+			 * Usually overwritten in first_rec != NULL clause.
+			 */
+			ncp->begin_rec = (*vpp)->begin + (off_t)(*vpp)->len;
+		}
+	}
+
+	if(first_rec != NULL)
+	{
+		assert(ncp->begin_rec <= first_rec->begin);
+		ncp->begin_rec = first_rec->begin;
+		/*
+	 	 * for special case of exactly one record variable, pack value
+	 	 */
+		if(ncp->recsize == first_rec->len)
+			ncp->recsize = *first_rec->dsizes * first_rec->xsz;
+	}
+
+	if(first_var != NULL)
+	{
+		ncp->begin_var = first_var->begin;
+	}
+	else
+	{
+		ncp->begin_var = ncp->begin_rec;
+	}
+
+	assert(ncp->begin_var > 0);
+	assert(ncp->xsz <= (size_t)ncp->begin_var);
+	assert(ncp->begin_rec > 0);
+	assert(ncp->begin_var <= ncp->begin_rec);
+	
+	return(ENOERR);
+}
+
+
+size_t
+ncx_len_NC(const NC *ncp)
+{
+	size_t xlen = sizeof(ncmagic);
+
+	assert(ncp != NULL);
+	
+	xlen += X_SIZEOF_SIZE_T; /* numrecs */
+	xlen += ncx_len_NC_dimarray(&ncp->dims);
+	xlen += ncx_len_NC_attrarray(&ncp->attrs);
+	xlen += ncx_len_NC_vararray(&ncp->vars);
+
+	return xlen;
+}
+
+
+int
+ncx_put_NC(const NC *ncp, void **xpp, off_t offset, size_t extent)
+{
+	int status = ENOERR;
+	v1hs ps; /* the get stream */
+
+	assert(ncp != NULL);
+
+	/* Initialize stream ps */
+
+	ps.nciop = ncp->nciop;
+	ps.flags = RGN_WRITE;
+
+	if(xpp == NULL)
+	{
+		/*
+		 * Come up with a reasonable stream read size.
+		 */
+		extent = ncp->xsz;
+		if(extent <= MIN_NC_XSZ)
+		{
+			/* first time read */
+			extent = ncp->chunk;
+			/* Protection for when ncp->chunk is huge;
+			 * no need to read hugely. */
+	      		if(extent > 4096)
+				extent = 4096;
+		}
+		else if(extent > ncp->chunk)
+		{
+			extent = ncp->chunk;
+		}
+		
+		ps.offset = 0;
+		ps.extent = extent;
+		ps.base = NULL;
+		ps.pos = ps.base;
+
+		status = fault_v1hs(&ps, extent);
+		if(status)
+			return status;
+	}
+	else
+	{
+		ps.offset = offset;
+		ps.extent = extent;
+		ps.base = *xpp;
+		ps.pos = ps.base;
+		ps.end = (char *)ps.base + ps.extent;
+	}
+
+	status = ncx_putn_schar_schar(&ps.pos, sizeof(ncmagic), ncmagic);
+	if(status != ENOERR)
+		goto release;
+
+	{
+	const size_t nrecs = NC_get_numrecs(ncp);
+	status = ncx_put_size_t(&ps.pos, &nrecs);
+	if(status != ENOERR)
+		goto release;
+	}
+
+	assert((char *)ps.pos < (char *)ps.end);
+
+	status = v1h_put_NC_dimarray(&ps, &ncp->dims);
+	if(status != ENOERR)
+		goto release;
+
+	status = v1h_put_NC_attrarray(&ps, &ncp->attrs);
+	if(status != ENOERR)
+		goto release;
+
+	status = v1h_put_NC_vararray(&ps, &ncp->vars);
+	if(status != ENOERR)
+		goto release;
+
+release:
+	(void) rel_v1hs(&ps);
+
+	return status;
+}
+
+
+int
+nc_get_NC(NC *ncp)
+{
+	int status;
+	v1hs gs; /* the get stream */
+
+	assert(ncp != NULL);
+
+	/* Initialize stream gs */
+
+	gs.nciop = ncp->nciop;
+	gs.offset = 0; /* beginning of file */
+	gs.extent = 0;
+	gs.flags = 0;
+	gs.base = NULL;
+	gs.pos = gs.base;
+
+	{
+		/*
+		 * Come up with a reasonable stream read size.
+		 */
+		size_t extent = ncp->xsz;
+		if(extent <= MIN_NC_XSZ)
+		{
+			/* first time read */
+			extent = ncp->chunk;
+			/* Protection for when ncp->chunk is huge;
+			 * no need to read hugely. */
+	      		if(extent > 4096)
+				extent = 4096;
+		}
+		else if(extent > ncp->chunk)
+		{
+			extent = ncp->chunk;
+		}
+		
+		status = fault_v1hs(&gs, extent);
+		if(status)
+			return status;
+	}
+
+	/* get the header from the stream gs */
+
+	{
+		/* Get & check magic number */
+		schar magic[sizeof(ncmagic)];
+		(void) memset(magic, 0, sizeof(magic));
+
+		status = ncx_getn_schar_schar(
+			(const void **)(&gs.pos), sizeof(magic), magic);
+		if(status != ENOERR)
+			goto unwind_get;
+	
+		if(memcmp(magic, ncmagic, sizeof(ncmagic)) != 0)
+		{
+			status = NC_ENOTNC;
+			goto unwind_get;
+		}
+	}
+	
+	{
+	size_t nrecs = 0;
+	status = ncx_get_size_t((const void **)(&gs.pos), &nrecs);
+	if(status != ENOERR)
+		goto unwind_get;
+	NC_set_numrecs(ncp, nrecs);
+	}
+
+	assert((char *)gs.pos < (char *)gs.end);
+
+	status = v1h_get_NC_dimarray(&gs, &ncp->dims);
+	if(status != ENOERR)
+		goto unwind_get;
+
+	status = v1h_get_NC_attrarray(&gs, &ncp->attrs);
+	if(status != ENOERR)
+		goto unwind_get;
+
+	status = v1h_get_NC_vararray(&gs, &ncp->vars);
+	if(status != ENOERR)
+		goto unwind_get;
+		
+	ncp->xsz = ncx_len_NC(ncp);
+
+	status = NC_computeshapes(ncp);
+
+unwind_get:
+	(void) rel_v1hs(&gs);
+	return status;
+}
Index: /branches/SDM_SciDAC/src/lib/validator.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/validator.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/validator.c (revision 2)
@@ -0,0 +1,722 @@
+/*********************************************************************************
+ *
+ * This file is written by Northwestern University and Argonne National Laboratory
+ *
+ ********************************************************************************/
+#include <mpi.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "nc.h"
+#include "ncx.h"
+
+#undef MAX  /* system may define MAX somewhere and complain */
+#undef MIN  /* system may define MIN somewhere and complain */
+#define MAX(mm,nn) (((mm) > (nn)) ? (mm) : (nn))
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+
+/*
+ * "magic number" at beginning of file: 0x43444601 (big endian) 
+ */
+static const schar ncmagic[] = {'C', 'D', 'F', 0x01}; 
+
+typedef struct bufferinfo {
+  ncio *nciop;		
+  MPI_Offset offset;	/* current read/write offset in the file */
+  void *base;     	/* beginning of read/write buffer */
+  void *pos;      	/* current position in buffer */
+  size_t size;		/* size of the buffer */
+} bufferinfo;  
+
+/* Begin Of get NC */
+
+/*
+ * Fetch the next header chunk.
+ */
+int
+val_fetch(bufferinfo *gbp, size_t fsize) {
+  int status;
+  char *buf;
+  ssize_t nn = 0, bufsize = 0;
+
+  assert(gbp->base != NULL);
+  
+  fsize = _RNDUP(fsize, X_ALIGN);
+  (void) memset(gbp->base, 0, gbp->size);
+  buf = gbp->pos = gbp->base;
+
+  lseek(gbp->nciop->fd, gbp->offset, SEEK_SET);
+  while ( (bufsize < gbp->size) && (nn = read(gbp->nciop->fd, buf, gbp->size-bufsize)) > 0 ) {
+    buf += nn;
+    bufsize += nn;
+  }
+  gbp->offset += bufsize; 
+
+  if (bufsize < fsize) {
+    printf("Error @ [0x%8.8x]: \n\tUnexpected EOF, while ", gbp->offset);
+    return -1;
+  }
+    
+  gbp->size = bufsize;
+
+  return ENOERR;
+}
+
+/*
+ * Ensure that 'nextread' bytes are available.
+ */
+int
+val_check_buffer(bufferinfo *gbp, size_t nextread) {
+  if ((char *)gbp->pos + nextread <= (char *)gbp->base + gbp->size)
+    return ENOERR;
+  return val_fetch(gbp, MIN(gbp->size, nextread));
+} 
+
+int
+val_get_NCtype(bufferinfo *gbp, NCtype *typep) {
+  int type = 0;
+  int status = val_check_buffer(gbp, X_SIZEOF_INT);
+  if (status != ENOERR) {
+    printf("NC component type is expected for ");
+    return status;
+  }
+
+  status =  ncx_get_int_int(gbp->pos, &type);
+  gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT);
+  if (status != ENOERR)
+    return status;
+  *typep = (NCtype) type;
+  return ENOERR;
+}
+
+int
+val_get_size_t(bufferinfo *gbp, size_t *sp) {
+  int status = val_check_buffer(gbp, X_SIZEOF_SIZE_T);
+  if (status != ENOERR) {
+    printf("size is expected for ");
+    return status; 
+  }
+  return ncx_get_size_t((const void **)(&gbp->pos), sp);
+}
+
+int
+val_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp) {
+  int status;
+  size_t  nchars = 0, padding, bufremain, strcount; 
+  NC_string *ncstrp;
+  char *cpos;
+  char pad[X_ALIGN-1];
+
+  status = val_get_size_t(gbp, &nchars);
+  if (status != ENOERR) {
+    printf("the name string of ");
+    return status;
+  }
+
+  ncstrp = new_NC_string(nchars, NULL);
+  if (ncstrp == NULL)
+    return NC_ENOMEM;
+
+  padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN)
+            - X_SIZEOF_CHAR * ncstrp->nchars;
+  bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base);
+  cpos = ncstrp->cp;
+
+  while (nchars > 0) {
+    if (bufremain > 0) {
+      strcount = MIN(bufremain, X_SIZEOF_CHAR * nchars); 
+      (void) memcpy(cpos, gbp->pos, strcount);
+      nchars -= strcount/X_SIZEOF_CHAR;
+      gbp->pos = (void *)((char *)gbp->pos + strcount);
+      cpos += strcount; 
+      bufremain -= strcount;
+    } else {
+      status = val_fetch(gbp, MIN(gbp->size, X_SIZEOF_CHAR * nchars));
+      if(status != ENOERR) {
+	printf("fetching the name string of ");
+        free_NC_string(ncstrp);
+        return status;
+      } 
+      bufremain = gbp->size;
+    }
+  }
+
+  memset(pad, 0, X_ALIGN-1);
+  status = val_check_buffer(gbp, padding);
+  if(status != ENOERR) {
+    printf("fetching padding for the name string of ");
+    free_NC_string(ncstrp);
+    return status;
+  } 
+  if (memcmp(gbp->pos, pad, padding) != 0) {
+    printf("Error @ [0x%8.8x]: \n\tPadding should be 0x00 for the name string alignment of ",
+	   (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size);
+    free_NC_string(ncstrp);
+    return EINVAL;
+  }
+  gbp->pos = (void *)((char *)gbp->pos + padding);
+  
+  *ncstrpp = ncstrp;
+  
+  return ENOERR;  
+}
+
+int
+val_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp) {
+  int status;
+  NC_string *ncstrp;
+  NC_dim *dimp;
+
+  status = val_get_NC_string(gbp, &ncstrp);
+  if (status != ENOERR) 
+    return status;
+
+  dimp = new_x_NC_dim(ncstrp);
+  if(dimp == NULL)
+    return NC_ENOMEM;
+
+  status = val_get_size_t(gbp, &dimp->size);
+  if(status != ENOERR) {
+    printf("\"%s\" - ", ncstrp->cp);
+    free_NC_dim(dimp); /* frees name */
+    return status;
+  }
+
+  *dimpp = dimp;
+
+  return ENOERR;
+}
+
+int
+val_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap) {
+  int status;
+  NCtype type = NC_UNSPECIFIED; 
+  NC_dim **dpp, **end;
+  int dim;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL);
+
+  status = val_get_NCtype(gbp, &type);
+  if(status != ENOERR) {
+    printf("preamble of ");
+    return status; 
+  }
+
+  status = val_get_size_t(gbp, &ncap->nelems);
+  if(status != ENOERR) {
+    printf("the length of ");
+    return status;
+  }
+
+  if(ncap->nelems == 0) {
+    if (type != NC_DIMENSION && type != NC_UNSPECIFIED) {
+      printf("Error @ [0x%8.8x]: \n\tInvalid NC component type, while ",
+	      (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T);
+      printf("NC_DIMENSION or NC_UNSPECIFIED is expected for ");
+      return EINVAL;
+    }
+  } else {
+    if(type != NC_DIMENSION) {
+      printf("Error @ [0x%8.8x]: \n\tInvalid NC component type, while ",
+	      (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T);
+      printf("NC_DIMENSION is expected since number of dimensions is %d for ", ncap->nelems);
+      return EINVAL;
+    }
+
+    ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM;
+    ncap->nalloc = ncap->nelems;
+
+    dpp = ncap->value;
+    end = &dpp[ncap->nelems];
+    for( /*NADA*/ dim = 0; dpp < end; dpp++, dim++) {
+      status = val_get_NC_dim(gbp, dpp);
+      if (status != ENOERR) {
+	printf("dimension[%d] in ", dim);
+        ncap->nelems = dpp - ncap->value;
+        free_NC_dimarrayV(ncap);
+        return status;
+      }
+    }
+  }
+
+  return ENOERR;
+}
+
+int
+val_get_nc_type(bufferinfo *gbp, nc_type *typep) {
+  int type = 0;
+  int status = val_check_buffer(gbp, X_SIZEOF_INT);
+  if(status != ENOERR) {
+    printf("data type is expected for the values of ");
+    return status;
+  }
+
+  status =  ncx_get_int_int(gbp->pos, &type);
+  if(status != ENOERR) 
+    return status;
+  gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT); 
+
+  if (   type != NC_BYTE
+      && type != NC_CHAR
+      && type != NC_SHORT
+      && type != NC_INT
+      && type != NC_FLOAT
+      && type != NC_DOUBLE) {
+    printf("Error @ [0x%8.8x]: \n\tUnknown data type for the values of ",
+	   (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size - X_SIZEOF_INT);
+    return EINVAL; 
+  }
+ 
+  *typep = (nc_type) type;
+
+  return ENOERR;
+}
+
+/*
+ * Get the values of an attribute  
+ */
+int
+val_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp) {
+  int status;
+  void *value = attrp->xvalue;
+  char pad[X_ALIGN-1]; 
+  size_t nvalues = attrp->nelems, esz, padding, bufremain, attcount;
+
+  esz = ncx_len_nctype(attrp->type);
+  padding = attrp->xsz - esz * nvalues;
+  bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base);
+
+  while (nvalues > 0) {
+    if (bufremain > 0) {
+      attcount = MIN(bufremain, esz * nvalues);
+      (void) memcpy(value, gbp->pos, attcount);
+      nvalues -= attcount/esz;
+      gbp->pos = (void *)((char *)gbp->pos + attcount);
+      value = (void *)((char *)value + attcount);
+      bufremain -= attcount;
+    } else {
+      status = val_fetch(gbp, MIN(gbp->size, esz * nvalues));
+      if(status != ENOERR) {
+	printf("fetching the values of ");
+        return status;
+      }
+      bufremain = gbp->size;
+    }
+  }
+ 
+  memset(pad, 0, X_ALIGN-1);
+  if (memcmp(gbp->pos, pad, padding) != 0) {
+    printf("Error @ [0x%8.8x]: \n\tPadding should be 0x00 for the values alignment of ",
+           (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size); 
+    return EINVAL;
+  }
+  gbp->pos = (void *)((char *)gbp->pos + padding);
+
+  return ENOERR;
+}
+
+int
+val_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp) {
+  NC_string *strp;
+  int status;
+  nc_type type; 
+  size_t nelems;
+  NC_attr *attrp;
+
+  status = val_get_NC_string(gbp, &strp);
+  if(status != ENOERR)
+    return status;
+
+  status = val_get_nc_type(gbp, &type);
+  if(status != ENOERR) {
+    printf("\"%s\" - ", strp->cp);
+    free_NC_string(strp);
+    return status;
+  }
+
+  status = val_get_size_t(gbp, &nelems); 
+  if(status != ENOERR) {
+    printf("the values of \"%s\" - ", strp->cp);
+    free_NC_string(strp);
+    return status;
+  }
+
+  attrp = new_x_NC_attr(strp, type, nelems);
+  if(attrp == NULL) {
+    free_NC_string(strp);
+    return status;
+  }
+
+  status = val_get_NC_attrV(gbp, attrp);
+  if(status != ENOERR) {
+    printf("\"%s\" - ", strp->cp);
+    free_NC_attr(attrp); /* frees strp */ 
+    return status;
+  }
+
+  *attrpp = attrp; 
+  
+  return ENOERR; 
+}
+
+int
+val_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap){
+  int status;
+  NCtype type = NC_UNSPECIFIED;
+  NC_attr **app, **end;
+  int att;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL);
+
+  status = val_get_NCtype(gbp, &type);
+  if(status != ENOERR) {
+    printf("preamble of ");
+    return status; 
+  }
+
+  status = val_get_size_t(gbp, &ncap->nelems);
+  if(status != ENOERR) {
+    printf("the length of ");
+    return status;
+  }
+
+  if(ncap->nelems == 0) {
+    if (type != NC_ATTRIBUTE && type != NC_UNSPECIFIED) {
+      printf("Error @ [0x%8.8x]: \n\tInvalid NC component type, while ",
+              (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T);
+      printf("NC_ATTRIBUTE or NC_UNSPECIFIED is expected for "); 
+      return EINVAL;
+    }
+  } else {
+    if(type != NC_ATTRIBUTE) {
+      printf("Error @ [0x%8.8x]: \n\tInvalid NC component type, while ",
+              (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T);
+      printf("NC_ATTRIBUTE is expected since number of attributes is %d for ", ncap->nelems);  
+      return EINVAL;
+    }
+
+    ncap->value = (NC_attr **) malloc(ncap->nelems * sizeof(NC_attr *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM;
+    ncap->nalloc = ncap->nelems; 
+
+    app = ncap->value;
+    end = &app[ncap->nelems];
+    for( /*NADA*/ att = 0; app < end; app++, att++) {
+      status = val_get_NC_attr(gbp, app);
+      if (status != ENOERR) {
+	printf("attribute[%d] of ", att);
+        ncap->nelems = app - ncap->value;
+        free_NC_attrarrayV(ncap);
+        return status;
+      }
+    }
+  }
+  
+  return ENOERR;
+}
+
+int
+val_get_NC_var(bufferinfo *gbp, NC_var **varpp) {
+  NC_string *strp;
+  int status;
+  size_t ndims, dim;
+  NC_var *varp;
+
+  status = val_get_NC_string(gbp, &strp);
+  if(status != ENOERR)
+    return status;
+
+  status = val_get_size_t(gbp, &ndims);
+  if(status != ENOERR) {
+     printf("the dimid list of \"%s\" - ", strp->cp);
+     free_NC_string(strp); 
+     return status;
+  }
+
+  varp = new_x_NC_var(strp, ndims);
+  if(varp == NULL) {
+    free_NC_string(strp);
+    return NC_ENOMEM;
+  }
+
+  for (dim = 0; dim < ndims; dim++ ) {
+    status = val_check_buffer(gbp, X_SIZEOF_INT);
+    if(status != ENOERR) {
+      printf("the dimid[%d] is expected for \"%s\" - ", dim, strp->cp);
+      free_NC_var(varp);
+      return status;
+    }
+    status = ncx_getn_int_int((const void **)(&gbp->pos), 
+                              1, varp->dimids + dim);
+    if(status != ENOERR) {
+      free_NC_var(varp);
+      return status;
+    }
+  }
+
+  status = val_get_NC_attrarray(gbp, &varp->attrs);
+  if(status != ENOERR) {
+    printf("ATTRIBUTE list of \"%s\" - ", strp->cp);
+    free_NC_var(varp);
+    return status;
+  }
+
+  status = val_get_nc_type(gbp, &varp->type);
+  if(status != ENOERR) {
+    printf("\"%s\" - ", strp->cp);
+    free_NC_var(varp);
+    return status;
+  } 
+
+  status = val_get_size_t(gbp, &varp->len);
+  if(status != ENOERR) {
+    printf("the data of  \"%s\" - ", strp->cp);
+    free_NC_var(varp);
+    return status;
+  }
+
+  status = val_check_buffer(gbp, X_SIZEOF_OFF_T);
+  if(status != ENOERR) {
+    printf("offset is expected for the data of \"%s\" - ", strp->cp);
+    free_NC_var(varp);
+    return status;
+  }
+  status = ncx_get_off_t((const void **)&gbp->pos,
+                         &varp->begin);
+  if(status != ENOERR) {
+    free_NC_var(varp);
+    return status;
+  }
+
+  *varpp = varp;
+  return ENOERR;
+}
+
+int
+val_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap) {
+  int status;
+  NCtype type = NC_UNSPECIFIED;
+  NC_var **vpp, **end;
+  int var;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL); 
+
+  status = val_get_NCtype(gbp, &type);
+  if(status != ENOERR) {
+    printf("preamble of ");
+    return status;
+  }
+ 
+  status = val_get_size_t(gbp, &ncap->nelems);
+  if(status != ENOERR) {
+    printf("the length of ");
+    return status;
+  }
+ 
+  if(ncap->nelems == 0) {
+    if (type != NC_VARIABLE && type != NC_UNSPECIFIED) {
+      printf("Error @ [0x%8.8x]: \n\tInvalid NC component type, while ",
+              (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T);
+      printf("NC_VARIABLE or NC_UNSPECIFIED is expected for ");
+      return EINVAL;
+    }
+  } else {
+    if(type != NC_VARIABLE) {
+      printf("Error @ [0x%8.8x]: \n\tInvalid NC component type, while ",
+              (size_t)(gbp->pos - gbp->base) + gbp->offset - gbp->size - 2 * X_SIZEOF_SIZE_T);
+      printf("NC_VARIABLE is expected since number of variables is %d for ", ncap->nelems);        
+      return EINVAL;
+    }
+ 
+    ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM; 
+    ncap->nalloc = ncap->nelems;
+
+    vpp = ncap->value;
+    end = &vpp[ncap->nelems];
+    for( /*NADA*/ var = 0; vpp < end; vpp++, var++) {
+      status = val_get_NC_var(gbp, vpp);
+      if (status != ENOERR) {
+        printf("variable[%d] in ", var);
+        ncap->nelems = vpp - ncap->value;
+        free_NC_vararrayV(ncap);
+        return status;
+      }
+    }
+  }
+
+  return ENOERR;
+}
+
+int
+val_get_NC(NC *ncp) {
+  int status;
+  bufferinfo getbuf;
+  schar magic[sizeof(ncmagic)];
+  size_t nrecs = 0;
+
+  assert(ncp != NULL);
+
+  /* Initialize the get buffer */
+
+  getbuf.nciop = ncp->nciop;
+  getbuf.offset = 0; 	/* read from start of the file */
+  getbuf.size = _RNDUP( MAX(MIN_NC_XSZ, ncp->chunk), X_ALIGN );
+  if (getbuf.size > 4096)
+    getbuf.size = 4096;
+  getbuf.pos = getbuf.base = (void *)malloc(getbuf.size);
+
+  status = val_fetch(&getbuf, sizeof(magic));
+  if(status != ENOERR) {
+    printf("magic number (C D F \\001) is expected!\n");
+    return status;
+  }
+  
+  /* Get the header from get buffer */
+
+  (void) memset(magic, 0, sizeof(magic));
+  status = ncx_getn_schar_schar(
+          (const void **)(&getbuf.pos), sizeof(magic), magic);
+  if(memcmp(magic, ncmagic, sizeof(ncmagic)) != 0) {
+    printf("Error @ [0x%8.8x]: \n\tUnknow magic number, while (C D F \\001) is expected!\n", 0);
+    free(getbuf.base);
+    return NC_ENOTNC;
+  }
+
+  status = val_check_buffer(&getbuf, X_SIZEOF_SIZE_T);
+  if(status != ENOERR) {
+    printf("number of records is expected!\n");
+    free(getbuf.base);
+    return status;
+  }
+  status = ncx_get_size_t((const void **)(&getbuf.pos), &nrecs);
+  if(status != ENOERR) {
+    free(getbuf.base);
+    return status;
+  }
+  ncp->numrecs = nrecs;
+
+  assert((char *)getbuf.pos < (char *)getbuf.base + getbuf.size);
+
+  status = val_get_NC_dimarray(&getbuf, &ncp->dims);
+  if(status != ENOERR) {
+    printf("DIMENSION list!\n");
+    free(getbuf.base);
+    return status;
+  }
+
+  status = val_get_NC_attrarray(&getbuf, &ncp->attrs); 
+  if(status != ENOERR) {
+    printf("GLOBAL ATTRIBUTE list!\n");
+    free(getbuf.base);
+    return status;
+  }
+
+  status = val_get_NC_vararray(&getbuf, &ncp->vars);
+  if(status != ENOERR) {
+    printf("VARIABLE list!\n");
+    free(getbuf.base);
+    return status; 
+  }
+
+  ncp->xsz = hdr_len_NC(ncp); 
+  status = NC_computeshapes(ncp);
+  free(getbuf.base);
+
+  return status;
+}
+
+/* End Of get NC */
+
+int 
+main(int argc, char **argv) {
+
+  char *ncfile;
+  int status;
+  NC *ncp;
+  struct stat ncfilestat;
+
+  if (argc < 2) {
+    printf("Missing ncfile name. Usage:\n\t ncvalid <ncfile>\n");
+    exit(1);
+  } 
+
+  if (argc > 2) {
+    printf("Too many arguments. Usage:\n\t ncvalid <ncfile>\n");
+    exit(1);
+  }
+
+  ncfile = argv[1];
+
+  /* open the netCDF file */
+
+  ncp = new_NC(NULL);
+  if(ncp == NULL) {
+    printf("Not enough memory!\n");
+    return 0; 
+  }
+
+  ncp->nciop = ncio_new(ncfile, NC_NOWRITE);
+  if(ncp->nciop == NULL) {
+    free_NC(ncp);
+    printf("Not enough memory!\n");
+    return 0; 
+  }
+
+  if ( (*((int *)&ncp->nciop->fd) = open(ncfile, O_RDONLY)) < 0 ) {
+    printf("Can not open file: %s\n", ncfile);
+    ncio_free(ncp->nciop);
+    free_NC(ncp);
+    return 0;
+  }
+
+  /* read to validate the header */
+
+  status = val_get_NC(ncp);
+  if (status !=  0) {
+    close(ncp->nciop->fd);
+    ncio_free(ncp->nciop);
+    free_NC(ncp);
+    return 0;
+  }
+
+  /* check data size */
+  
+  fstat(ncp->nciop->fd, &ncfilestat);
+  if ( ncp->begin_rec + ncp->recsize * ncp->numrecs < ncfilestat.st_size ) {
+    printf("Error: \n\tData size is larger than defined!\n");
+    close(ncp->nciop->fd);
+    ncio_free(ncp->nciop);
+    free_NC(ncp);
+    return 0;  
+  } else if ( ncp->begin_rec + ncp->recsize * (ncp->numrecs - 1) >= ncfilestat.st_size ) {
+    printf("Error: \n\tData size is less than expected!\n");
+    close(ncp->nciop->fd);
+    ncio_free(ncp->nciop);
+    free_NC(ncp);
+    return 0;
+  }
+
+
+  /* close the file */
+
+  close(ncp->nciop->fd);
+  ncio_free(ncp->nciop);
+  free_NC(ncp);
+
+  printf("The netCDF file is validated!\n");
+
+  return 0;
+}
Index: /branches/SDM_SciDAC/src/lib/ncio.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/ncio.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/ncio.c (revision 2)
@@ -0,0 +1,9 @@
+/*
+ * $Id$
+ */
+
+#if defined(_CRAY)
+#   include "ffio.c"
+#else
+#   include "posixio.c"
+#endif
Index: /branches/SDM_SciDAC/src/lib/header.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/header.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/header.c (revision 2)
@@ -0,0 +1,1066 @@
+/*********************************************************************************
+ *
+ * This file is written by Northwestern University and Argonne National Laboratory
+ *
+ ********************************************************************************/
+
+#include <mpi.h>
+#include <assert.h>
+#include "nc.h"
+#include "ncx.h"
+
+#undef MAX  /* system may define MAX somewhere and complain */
+#undef MIN  /* system may define MIN somewhere and complain */
+#define MAX(mm,nn) (((mm) > (nn)) ? (mm) : (nn))
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+
+/*
+ * "magic number" at beginning of file: 0x43444601 (big endian) 
+ */
+static const schar ncmagic[] = {'C', 'D', 'F', 0x01}; 
+
+typedef struct bufferinfo {
+  ncio *nciop;		
+  MPI_Offset offset;	/* current read/write offset in the file */
+  void *base;     	/* beginning of read/write buffer */
+  void *pos;      	/* current position in buffer */
+  size_t size;		/* size of the buffer */
+} bufferinfo;  
+
+/*
+ * Recompute the shapes of all variables
+ * Sets ncp->begin_var to start of first variable.
+ * Sets ncp->begin_rec to start of first record variable.
+ * Returns -1 on error. The only possible error is an reference
+ * to a non existent dimension, which would occur for a corrupt
+ * netcdf file.
+ */ 
+int
+NC_computeshapes(NC *ncp)
+{
+        NC_var **vpp = (NC_var **)ncp->vars.value;
+        NC_var *const *const end = &vpp[ncp->vars.nelems];
+        NC_var *first_var = NULL;       /* first "non-record" var */
+        NC_var *first_rec = NULL;       /* first "record" var */
+        int status;
+ 
+        ncp->begin_var = (off_t) ncp->xsz;
+        ncp->begin_rec = (off_t) ncp->xsz;
+        ncp->recsize = 0;
+ 
+        if(ncp->vars.nelems == 0)
+                return(0);
+ 
+        for( /*NADA*/; vpp < end; vpp++)
+        {
+                status = NC_var_shape(*vpp, &ncp->dims);
+                if(status != ENOERR)
+                        return(status);
+ 
+                if(IS_RECVAR(*vpp))
+                {
+                        if(first_rec == NULL)
+                                first_rec = *vpp;
+                        ncp->recsize += (*vpp)->len;
+                }
+                else if(first_var == NULL)
+                {
+                        first_var = *vpp;
+                        /*
+                         * Overwritten each time thru.
+                         * Usually overwritten in first_rec != NULL clause.
+                         */
+                        ncp->begin_rec = (*vpp)->begin + (off_t)(*vpp)->len;
+                }
+        }
+ 
+        if(first_rec != NULL)
+        {
+                assert(ncp->begin_rec <= first_rec->begin);
+                ncp->begin_rec = first_rec->begin;
+                /*
+                 * for special case of exactly one record variable, pack value
+                 */
+                if(ncp->recsize == first_rec->len)
+                        ncp->recsize = *first_rec->dsizes * first_rec->xsz;
+        }
+ 
+        if(first_var != NULL)
+        {
+                ncp->begin_var = first_var->begin;
+        }
+        else
+        {
+                ncp->begin_var = ncp->begin_rec;
+        }
+ 
+        assert(ncp->begin_var > 0);
+        assert(ncp->xsz <= (size_t)ncp->begin_var);
+        assert(ncp->begin_rec > 0);
+        assert(ncp->begin_var <= ncp->begin_rec);
+ 
+        return(ENOERR);
+} 
+
+/* 
+ * To compute how much space will the xdr'd header take 
+ */
+ 
+#define X_SIZEOF_NC_TYPE X_SIZEOF_INT
+#define X_SIZEOF_NCTYPE X_SIZEOF_INT
+
+size_t
+hdr_len_NC_string(const NC_string *ncstrp)
+{
+        size_t sz = X_SIZEOF_SIZE_T; /* nchars */
+ 
+        assert(ncstrp != NULL);
+ 
+        if(ncstrp->nchars != 0)
+                sz += _RNDUP(ncstrp->nchars, X_ALIGN);
+ 
+        return sz;
+}
+ 
+size_t
+hdr_len_NC_dim(const NC_dim *dimp)
+{
+        size_t sz;
+ 
+        assert(dimp != NULL);
+ 
+        sz = hdr_len_NC_string(dimp->name);
+        sz += X_SIZEOF_SIZE_T;
+ 
+        return(sz);
+}
+ 
+size_t
+hdr_len_NC_dimarray(const NC_dimarray *ncap)
+{
+        size_t xlen = X_SIZEOF_NCTYPE;  /* type */
+        xlen += X_SIZEOF_SIZE_T;        /* count */
+        if(ncap == NULL)
+                return xlen;
+        /* else */
+        {
+                const NC_dim **dpp = (const NC_dim **)ncap->value;
+                const NC_dim *const *const end = &dpp[ncap->nelems];
+                for(  /*NADA*/; dpp < end; dpp++)
+                {
+                        xlen += hdr_len_NC_dim(*dpp);
+                }
+        }
+        return xlen;
+} 
+
+size_t
+hdr_len_NC_attr(const NC_attr *attrp)
+{
+        size_t sz;
+ 
+        assert(attrp != NULL);
+ 
+        sz = hdr_len_NC_string(attrp->name);
+        sz += X_SIZEOF_NC_TYPE; /* type */
+        sz += X_SIZEOF_SIZE_T; /* nelems */
+        sz += attrp->xsz;
+ 
+        return(sz);
+}
+ 
+size_t
+hdr_len_NC_attrarray(const NC_attrarray *ncap)
+{
+        size_t xlen = X_SIZEOF_NCTYPE;  /* type */
+        xlen += X_SIZEOF_SIZE_T;        /* count */
+        if(ncap == NULL)
+                return xlen;
+        /* else */
+        {
+                const NC_attr **app = (const NC_attr **)ncap->value;
+                const NC_attr *const *const end = &app[ncap->nelems];
+                for( /*NADA*/; app < end; app++)
+                {
+                        xlen += hdr_len_NC_attr(*app);
+                }
+        }
+        return xlen;
+}
+ 
+size_t
+hdr_len_NC_var(const NC_var *varp)
+{
+        size_t sz;
+ 
+        assert(varp != NULL);
+ 
+        sz = hdr_len_NC_string(varp->name);
+        sz += X_SIZEOF_SIZE_T; /* ndims */
+        sz += ncx_len_int(varp->ndims); /* dimids */
+        sz += hdr_len_NC_attrarray(&varp->attrs);
+        sz += X_SIZEOF_NC_TYPE; /* type */
+        sz += X_SIZEOF_SIZE_T; /* len */
+        sz += X_SIZEOF_OFF_T; /* begin */
+ 
+        return(sz);
+} 
+
+size_t
+hdr_len_NC_vararray(const NC_vararray *ncap)
+{
+        size_t xlen = X_SIZEOF_NCTYPE;  /* type */
+        xlen += X_SIZEOF_SIZE_T;        /* count */
+        if(ncap == NULL)
+                return xlen;
+        /* else */
+        {
+                const NC_var **vpp = (const NC_var **)ncap->value;
+                const NC_var *const *const end = &vpp[ncap->nelems];
+                for( /*NADA*/; vpp < end; vpp++)
+                {
+                        xlen += hdr_len_NC_var(*vpp);
+                }
+        }
+        return xlen;
+}
+ 
+size_t
+hdr_len_NC(const NC *ncp)
+{
+        size_t xlen = sizeof(ncmagic);
+ 
+        assert(ncp != NULL);
+ 
+        xlen += X_SIZEOF_SIZE_T; /* numrecs */
+        xlen += hdr_len_NC_dimarray(&ncp->dims);
+        xlen += hdr_len_NC_attrarray(&ncp->attrs);
+        xlen += hdr_len_NC_vararray(&ncp->vars);
+ 
+        return xlen;
+} 
+
+/* Begin Of put NC */
+
+int
+hdr_put_NCtype(bufferinfo *pbp, NCtype type) {
+  int status;
+  const int itype = (int)type;
+
+  status = ncx_put_int_int(pbp->pos, &itype);
+  if (status != ENOERR)
+    return status;
+  pbp->pos = (void *)((char *)pbp->pos + X_SIZEOF_INT); 
+  return status;
+}
+
+int 
+hdr_put_nc_type(bufferinfo *pbp, const nc_type *typep) {
+  int status;
+  const int itype = (int) *typep;
+  
+  status =  ncx_put_int_int(pbp->pos, &itype);
+  if (status != ENOERR)
+    return status;
+  pbp->pos = (void *)((char *)pbp->pos + X_SIZEOF_INT);
+  
+  return status; 
+}
+
+int 
+hdr_put_NC_string(bufferinfo *pbp, const NC_string *ncstrp) {
+  int status;
+
+  status = ncx_put_size_t(&pbp->pos, &ncstrp->nchars);
+  if (status != ENOERR)
+    return status;
+
+  status = ncx_pad_putn_text(&pbp->pos, ncstrp->nchars, ncstrp->cp); 
+  if (status != ENOERR)
+    return status;
+
+  return ENOERR;
+}
+
+/*
+ * Put the values of an attribute 
+ */
+int
+hdr_put_NC_attrV(bufferinfo *pbp, const NC_attr *attrp) {
+  int status;
+  void *value = attrp->xvalue;
+
+  assert(pbp->size % XALIGN == 0);
+
+  (void) memcpy(pbp->pos, value, attrp->xsz);
+  pbp->pos = (void *)((char *)pbp->pos + attrp->xsz);
+    
+  return ENOERR;
+}
+
+int 
+hdr_put_NC_dim(bufferinfo *pbp, const NC_dim *dimp) {
+  int status; 
+
+  status = hdr_put_NC_string(pbp, dimp->name);
+  if (status != ENOERR)
+    return status;
+
+  status = ncx_put_size_t(&pbp->pos, &dimp->size);
+  if (status != ENOERR)
+    return status;
+  
+  return ENOERR;
+}
+
+int
+hdr_put_NC_attr(bufferinfo *pbp, const NC_attr *attrp) {
+  int status;
+
+  status = hdr_put_NC_string(pbp, attrp->name);
+  if (status != ENOERR)
+    return status;
+
+  status = hdr_put_nc_type(pbp, &attrp->type);
+  if (status != ENOERR)
+    return status;
+
+  status = ncx_put_size_t(&pbp->pos, &attrp->nelems);
+  if (status != ENOERR)
+    return status;
+
+  status = hdr_put_NC_attrV(pbp, attrp);
+  if (status != ENOERR)
+    return status;
+
+  return ENOERR;
+}
+
+int
+hdr_put_NC_var(bufferinfo *pbp, const NC_var *varp) {
+  int status;
+
+  status = hdr_put_NC_string(pbp, varp->name);
+  if (status != ENOERR)
+    return status;
+
+  status = ncx_put_size_t(&pbp->pos, &varp->ndims);
+  if (status != ENOERR)
+    return status;
+
+  status = ncx_putn_int_int(&pbp->pos,
+                        varp->ndims, varp->dimids);
+  if (status != ENOERR)
+    return status;
+
+  status = hdr_put_NC_attrarray(pbp, &varp->attrs);
+  if (status != ENOERR)
+    return status;
+
+  status = hdr_put_nc_type(pbp, &varp->type); 
+  if (status != ENOERR)
+    return status;
+
+  status = ncx_put_size_t(&pbp->pos, &varp->len); 
+  if (status != ENOERR)
+    return status;
+
+  status = ncx_put_off_t(&pbp->pos, &varp->begin);
+  if (status != ENOERR)
+    return status;
+
+  return ENOERR;
+}
+
+int 
+hdr_put_NC_dimarray(bufferinfo *pbp, const NC_dimarray *ncap) {
+  int status;
+  
+  assert(pbp != NULL);
+  
+  if (ncap == NULL || ncap->nelems == 0) {
+     /* ABSENT */
+    const size_t nosz = 0;
+    status = hdr_put_NCtype(pbp, NC_UNSPECIFIED);
+    if (status != ENOERR)
+      return status;
+
+    status = ncx_put_size_t(&pbp->pos, &nosz);
+    if (status != ENOERR)
+      return status;
+  } else {
+    const NC_dim **dpp = (const NC_dim **)ncap->value; 
+    const NC_dim *const *const end = &dpp[ncap->nelems]; 
+
+    status = hdr_put_NCtype(pbp, NC_DIMENSION);
+    if (status != ENOERR)
+      return status;
+
+    status = ncx_put_size_t(&pbp->pos, &ncap->nelems);
+    if (status != ENOERR)
+      return status;
+
+    for ( /*NADA*/; dpp < end; dpp++) {
+      status = hdr_put_NC_dim(pbp, *dpp);
+      if (status != ENOERR)
+        return status;
+    }
+  }
+
+  return ENOERR;
+}
+
+int
+hdr_put_NC_attrarray(bufferinfo *pbp, const NC_attrarray *ncap) {
+  int status;
+
+  assert(pbp != NULL);
+
+  if (ncap == NULL || ncap->nelems == 0) {
+     /* ABSENT */
+    const size_t nosz = 0;
+    status = hdr_put_NCtype(pbp, NC_UNSPECIFIED);
+    if (status != ENOERR)
+      return status;
+
+    status = ncx_put_size_t(&pbp->pos, &nosz);
+    if (status != ENOERR)
+      return status;
+  } else {
+    const NC_attr **app = (const NC_attr **)ncap->value;
+    const NC_attr *const *const end = &app[ncap->nelems]; 
+
+    status = hdr_put_NCtype(pbp, NC_ATTRIBUTE);
+    if (status != ENOERR)
+      return status;
+
+    status = ncx_put_size_t(&pbp->pos, &ncap->nelems);
+    if (status != ENOERR)
+      return status;
+  
+    for ( /*NADA*/; app < end; app++) {
+      status = hdr_put_NC_attr(pbp, *app);
+      if (status != ENOERR)
+        return status;
+    }
+  }
+
+  return ENOERR;
+}
+
+int
+hdr_put_NC_vararray(bufferinfo *pbp, const NC_vararray *ncap){
+  int status;
+
+  assert(pbp != NULL);
+
+  if (ncap == NULL || ncap->nelems == 0) {
+     /* ABSENT */
+    const size_t nosz = 0;
+    status = hdr_put_NCtype(pbp, NC_UNSPECIFIED);
+    if (status != ENOERR)
+      return status;
+
+    status = ncx_put_size_t(&pbp->pos, &nosz);
+    if (status != ENOERR)
+      return status;
+  } else { 
+    const NC_var **vpp = (const NC_var **)ncap->value; 
+    const NC_var *const *const end = &vpp[ncap->nelems]; 
+
+    status = hdr_put_NCtype(pbp, NC_VARIABLE);
+    if (status != ENOERR)
+      return status;
+
+    status = ncx_put_size_t(&pbp->pos, &ncap->nelems);
+    if (status != ENOERR)
+      return status;
+
+    for( /*NADA*/; vpp < end; vpp++) {
+      status = hdr_put_NC_var(pbp, *vpp); 
+      if (status != ENOERR)
+        return status;
+    }
+  }
+
+  return ENOERR;
+}
+
+int 
+hdr_put_NC(NC *ncp, void *buf) {
+  int status;
+  bufferinfo putbuf;
+  size_t nrecs; 
+
+  putbuf.nciop = NULL;
+  putbuf.offset = 0;
+  putbuf.pos = putbuf.base = buf;
+  putbuf.size = ncp->xsz;
+
+  status = ncx_putn_schar_schar(&putbuf.pos, sizeof(ncmagic), ncmagic);
+
+  nrecs = ncp->numrecs; 
+  status = ncx_put_size_t(&putbuf.pos, &nrecs);
+  if (status != ENOERR)
+    return status;
+
+  assert((char *)putbuf.pos < (char *)putbuf.base + putbuf.size);
+
+  status = hdr_put_NC_dimarray(&putbuf, &ncp->dims);
+  if (status != ENOERR)
+    return status;
+
+  status = hdr_put_NC_attrarray(&putbuf, &ncp->attrs); 
+  if (status != ENOERR)
+    return status;
+
+  status = hdr_put_NC_vararray(&putbuf, &ncp->vars);
+  if (status != ENOERR)
+    return status;
+
+  return status;
+}
+
+/* End Of put NC */
+
+/* Begin Of get NC */
+
+/*
+ * Fetch the next header chunk.
+ */
+int
+hdr_fetch(bufferinfo *gbp) {
+  int status;
+  int rank;
+  MPI_Comm comm;
+
+  assert(gbp->base != NULL);
+  
+  comm = gbp->nciop->comm;
+  MPI_Comm_rank(comm, &rank);
+
+  (void) memset(gbp->base, 0, gbp->size);
+  gbp->pos = gbp->base;
+  MPI_File_set_view(gbp->nciop->collective_fh, 0, MPI_BYTE, MPI_BYTE, 
+		    "native", gbp->nciop->mpiinfo);
+  if (rank == 0) {
+    MPI_Status mpistatus;
+    MPI_File_read_at(gbp->nciop->collective_fh, gbp->offset, gbp->base, 
+	             gbp->size, MPI_BYTE, &mpistatus);  
+  }
+  gbp->offset += gbp->size; 
+
+  MPI_Bcast(gbp->base, gbp->size, MPI_BYTE, 0, comm);
+
+  return ENOERR;
+}
+
+/*
+ * Ensure that 'nextread' bytes are available.
+ */
+int
+hdr_check_buffer(bufferinfo *gbp, size_t nextread) {
+  if ((char *)gbp->pos + nextread <= (char *)gbp->base + gbp->size)
+    return ENOERR;
+  return hdr_fetch(gbp);
+}
+
+int
+hdr_get_NCtype(bufferinfo *gbp, NCtype *typep) {
+  int type = 0;
+  int status = hdr_check_buffer(gbp, X_SIZEOF_INT);
+  if (status != ENOERR)
+    return status;
+
+  status =  ncx_get_int_int(gbp->pos, &type);
+  gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT);
+  if (status != ENOERR)
+    return status;
+  *typep = (NCtype) type;
+  return ENOERR;
+}
+
+int
+hdr_get_size_t(bufferinfo *gbp, size_t *sp) {
+  int status = hdr_check_buffer(gbp, X_SIZEOF_SIZE_T);
+  if (status != ENOERR)
+    return status; 
+  return ncx_get_size_t((const void **)(&gbp->pos), sp);
+}
+
+int
+hdr_get_NC_string(bufferinfo *gbp, NC_string **ncstrpp) {
+  int status;
+  size_t  nchars = 0, padding, bufremain, strcount; 
+  NC_string *ncstrp;
+  char *cpos;
+  char pad[X_ALIGN-1];
+
+  status = hdr_get_size_t(gbp, &nchars);
+  if (status != ENOERR)
+    return status;
+
+  ncstrp = new_NC_string(nchars, NULL);
+  if (ncstrp == NULL)
+    return NC_ENOMEM;
+
+  padding = _RNDUP(X_SIZEOF_CHAR * ncstrp->nchars, X_ALIGN)
+            - X_SIZEOF_CHAR * ncstrp->nchars;
+  bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base);
+  cpos = ncstrp->cp;
+
+  while (nchars > 0) {
+    if (bufremain > 0) {
+      strcount = MIN(bufremain, X_SIZEOF_CHAR * nchars); 
+      (void) memcpy(cpos, gbp->pos, strcount);
+      nchars -= strcount/X_SIZEOF_CHAR;
+      gbp->pos = (void *)((char *)gbp->pos + strcount);
+      cpos += strcount; 
+      bufremain -= strcount;
+    } else {
+      status = hdr_fetch(gbp);
+      if(status != ENOERR) {
+        free_NC_string(ncstrp);
+        return status;
+      } 
+      bufremain = gbp->size;
+    }
+  }
+
+  memset(pad, 0, X_ALIGN-1);
+  if (memcmp(gbp->pos, pad, padding) != 0) {
+    free_NC_string(ncstrp);
+    return EINVAL;
+  }
+  gbp->pos = (void *)((char *)gbp->pos + padding);
+  
+  *ncstrpp = ncstrp;
+  
+  return ENOERR;  
+}
+
+int
+hdr_get_NC_dim(bufferinfo *gbp, NC_dim **dimpp) {
+  int status;
+  NC_string *ncstrp;
+  NC_dim *dimp;
+
+  status = hdr_get_NC_string(gbp, &ncstrp);
+  if (status != ENOERR)
+    return status;
+
+  dimp = new_x_NC_dim(ncstrp);
+  if(dimp == NULL)
+    return NC_ENOMEM;
+
+  status = hdr_get_size_t(gbp, &dimp->size);
+  if(status != ENOERR) {
+    free_NC_dim(dimp); /* frees name */
+    return status;
+  }
+
+  *dimpp = dimp;
+
+  return ENOERR;
+}
+
+int
+hdr_get_NC_dimarray(bufferinfo *gbp, NC_dimarray *ncap) {
+  int status;
+  NCtype type = NC_UNSPECIFIED; 
+  NC_dim **dpp, **end;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL);
+
+  status = hdr_get_NCtype(gbp, &type);
+  if(status != ENOERR)
+    return status; 
+
+  status = hdr_get_size_t(gbp, &ncap->nelems);
+  if(status != ENOERR)
+    return status;
+
+  if(ncap->nelems == 0) {
+    if (type != NC_DIMENSION && type != NC_UNSPECIFIED)
+      return EINVAL;
+  } else {
+    if(type != NC_DIMENSION)
+      return EINVAL;
+
+    ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM;
+    ncap->nalloc = ncap->nelems;
+
+    dpp = ncap->value;
+    end = &dpp[ncap->nelems];
+    for( /*NADA*/; dpp < end; dpp++) {
+      status = hdr_get_NC_dim(gbp, dpp);
+      if (status != ENOERR) {
+        ncap->nelems = dpp - ncap->value;
+        free_NC_dimarrayV(ncap);
+        return status;
+      }
+    }
+  }
+
+  return ENOERR;
+}
+
+int
+hdr_get_nc_type(bufferinfo *gbp, nc_type *typep) {
+  int type = 0;
+  int status = hdr_check_buffer(gbp, X_SIZEOF_INT);
+  if(status != ENOERR)
+    return status;
+
+  status =  ncx_get_int_int(gbp->pos, &type);
+  gbp->pos = (void *)((char *)gbp->pos + X_SIZEOF_INT); 
+  if(status != ENOERR)
+    return status;
+
+  if (   type != NC_BYTE
+      && type != NC_CHAR
+      && type != NC_SHORT
+      && type != NC_INT
+      && type != NC_FLOAT
+      && type != NC_DOUBLE) 
+    return EINVAL; 
+ 
+  *typep = (nc_type) type;
+
+  return ENOERR;
+}
+
+size_t 
+ncx_len_nctype(nc_type type) {
+  switch(type) {
+    case NC_BYTE:
+    case NC_CHAR:
+        return X_SIZEOF_CHAR;
+    case NC_SHORT:
+        return X_SIZEOF_SHORT;
+    case NC_INT:
+        return X_SIZEOF_INT;
+    case NC_FLOAT:
+        return X_SIZEOF_FLOAT;
+    case NC_DOUBLE:
+        return X_SIZEOF_DOUBLE;
+  }
+  /* default */
+  assert("ncx_len_nctype bad type" == 0);
+  return 0;                
+}
+
+/*
+ * Get the values of an attribute  
+ */
+int
+hdr_get_NC_attrV(bufferinfo *gbp, NC_attr *attrp) {
+  int status;
+  void *value = attrp->xvalue;
+  char pad[X_ALIGN-1]; 
+  size_t nvalues = attrp->nelems, esz, padding, bufremain, attcount;
+
+  esz = ncx_len_nctype(attrp->type);
+  padding = attrp->xsz - esz * nvalues;
+  bufremain = gbp->size - (size_t)((char *)gbp->pos - (char *)gbp->base);
+
+  while (nvalues > 0) {
+    if (bufremain > 0) {
+      attcount = MIN(bufremain, esz * nvalues);
+      (void) memcpy(value, gbp->pos, attcount);
+      nvalues -= attcount/esz;
+      gbp->pos = (void *)((char *)gbp->pos + attcount);
+      value = (void *)((char *)value + attcount);
+      bufremain -= attcount;
+    } else {
+      status = hdr_fetch(gbp);
+      if(status != ENOERR) 
+        return status;
+      bufremain = gbp->size;
+    }
+  }
+ 
+  memset(pad, 0, X_ALIGN-1);
+  if (memcmp(gbp->pos, pad, padding) != 0) 
+    return EINVAL;
+  gbp->pos = (void *)((char *)gbp->pos + padding);
+
+  return ENOERR;
+}
+
+int
+hdr_get_NC_attr(bufferinfo *gbp, NC_attr **attrpp) {
+  NC_string *strp;
+  int status;
+  nc_type type; 
+  size_t nelems;
+  NC_attr *attrp;
+
+  status = hdr_get_NC_string(gbp, &strp);
+  if(status != ENOERR)
+    return status;
+
+  status = hdr_get_nc_type(gbp, &type);
+  if(status != ENOERR) {
+    free_NC_string(strp);
+    return status;
+  }
+
+  status = hdr_get_size_t(gbp, &nelems); 
+  if(status != ENOERR) {
+    free_NC_string(strp);
+    return status;
+  }
+
+  attrp = new_x_NC_attr(strp, type, nelems);
+  if(attrp == NULL) {
+    free_NC_string(strp);
+    return status;
+  }
+
+  status = hdr_get_NC_attrV(gbp, attrp);
+  if(status != ENOERR) {
+    free_NC_attr(attrp); /* frees strp */ 
+    return status;
+  }
+
+  *attrpp = attrp; 
+  
+  return ENOERR; 
+}
+
+int
+hdr_get_NC_attrarray(bufferinfo *gbp, NC_attrarray *ncap){
+  int status;
+  NCtype type = NC_UNSPECIFIED;
+  NC_attr **app, **end;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL);
+
+  status = hdr_get_NCtype(gbp, &type);
+  if(status != ENOERR)
+    return status; 
+
+  status = hdr_get_size_t(gbp, &ncap->nelems);
+  if(status != ENOERR)
+    return status;
+
+  if(ncap->nelems == 0) {
+    if (type != NC_ATTRIBUTE && type != NC_UNSPECIFIED)
+      return EINVAL;
+  } else {
+    if(type != NC_ATTRIBUTE)
+      return EINVAL;
+
+    ncap->value = (NC_attr **) malloc(ncap->nelems * sizeof(NC_attr *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM;
+    ncap->nalloc = ncap->nelems; 
+
+    app = ncap->value;
+    end = &app[ncap->nelems];
+    for( /*NADA*/; app < end; app++) {
+      status = hdr_get_NC_attr(gbp, app);
+      if (status != ENOERR) {
+        ncap->nelems = app - ncap->value;
+        free_NC_attrarrayV(ncap);
+        return status;
+      }
+    }
+  }
+  
+  return ENOERR;
+}
+
+int
+hdr_get_NC_var(bufferinfo *gbp, NC_var **varpp) {
+  NC_string *strp;
+  int status;
+  size_t ndims, dim;
+  NC_var *varp;
+
+  status = hdr_get_NC_string(gbp, &strp);
+  if(status != ENOERR)
+    return status;
+
+  status = hdr_get_size_t(gbp, &ndims);
+  if(status != ENOERR) {
+     free_NC_string(strp); 
+     return status;
+  }
+
+  varp = new_x_NC_var(strp, ndims);
+  if(varp == NULL) {
+    free_NC_string(strp);
+    return NC_ENOMEM;
+  }
+
+  for (dim = 0; dim < ndims; dim++ ) {
+    status = hdr_check_buffer(gbp, X_SIZEOF_INT);
+    if(status != ENOERR) {
+      free_NC_var(varp);
+      return status;
+    }
+    status = ncx_getn_int_int((const void **)(&gbp->pos), 
+                              1, varp->dimids + dim);
+    if(status != ENOERR) {
+      free_NC_var(varp);
+      return status;
+    }
+  }
+
+  status = hdr_get_NC_attrarray(gbp, &varp->attrs);
+  if(status != ENOERR) {
+    free_NC_var(varp);
+    return status;
+  }
+
+  status = hdr_get_nc_type(gbp, &varp->type);
+  if(status != ENOERR) {
+    free_NC_var(varp);
+    return status;
+  } 
+
+  status = hdr_get_size_t(gbp, &varp->len);
+  if(status != ENOERR) {
+    free_NC_var(varp);
+    return status;
+  }
+
+  status = hdr_check_buffer(gbp, X_SIZEOF_OFF_T);
+  if(status != ENOERR) {
+    free_NC_var(varp);
+    return status;
+  }
+  status = ncx_get_off_t((const void **)&gbp->pos,
+                        &varp->begin);
+  if(status != ENOERR) {
+    free_NC_var(varp);
+    return status;
+  }
+
+  *varpp = varp;
+  return ENOERR;
+}
+
+int
+hdr_get_NC_vararray(bufferinfo *gbp, NC_vararray *ncap) {
+  int status;
+  NCtype type = NC_UNSPECIFIED;
+  NC_var **vpp, **end;
+
+  assert(gbp != NULL && gbp->pos != NULL);
+  assert(ncap != NULL);
+  assert(ncap->value == NULL); 
+
+  status = hdr_get_NCtype(gbp, &type);
+  if(status != ENOERR)
+    return status;
+ 
+  status = hdr_get_size_t(gbp, &ncap->nelems);
+  if(status != ENOERR)
+    return status;
+ 
+  if(ncap->nelems == 0) {
+    if (type != NC_VARIABLE && type != NC_UNSPECIFIED)
+      return EINVAL;
+  } else {
+    if(type != NC_VARIABLE)
+      return EINVAL;
+ 
+    ncap->value = (NC_var **) malloc(ncap->nelems * sizeof(NC_var *));
+    if(ncap->value == NULL)
+      return NC_ENOMEM; 
+    ncap->nalloc = ncap->nelems;
+
+    vpp = ncap->value;
+    end = &vpp[ncap->nelems];
+    for( /*NADA*/; vpp < end; vpp++) {
+      status = hdr_get_NC_var(gbp, vpp);
+      if (status != ENOERR) {
+        ncap->nelems = vpp - ncap->value;
+        free_NC_vararrayV(ncap);
+        return status;
+      }
+    }
+  }
+
+  return ENOERR;
+}
+
+int
+hdr_get_NC(NC *ncp) {
+  int status;
+  bufferinfo getbuf;
+  schar magic[sizeof(ncmagic)];
+  size_t nrecs = 0;
+
+  assert(ncp != NULL);
+
+  /* Initialize the get buffer */
+
+  getbuf.nciop = ncp->nciop;
+  getbuf.offset = 0; 	/* read from start of the file */
+  getbuf.size = _RNDUP( MAX(MIN_NC_XSZ, ncp->chunk), X_ALIGN );
+  if (getbuf.size > 4096)
+    getbuf.size = 4096;
+  getbuf.pos = getbuf.base = (void *)malloc(getbuf.size);
+
+  status = hdr_fetch(&getbuf);
+  
+  /* Get the header from get buffer */
+
+  (void) memset(magic, 0, sizeof(magic));
+  status = ncx_getn_schar_schar(
+          (const void **)(&getbuf.pos), sizeof(magic), magic);
+  if(memcmp(magic, ncmagic, sizeof(ncmagic)) != 0) {
+    free(getbuf.base);
+    return NC_ENOTNC;
+  }
+
+  status = hdr_check_buffer(&getbuf, X_SIZEOF_SIZE_T);
+  if(status != ENOERR) {
+    free(getbuf.base);
+    return status;
+  } 
+  status = ncx_get_size_t((const void **)(&getbuf.pos), &nrecs);
+  if(status != ENOERR) {
+    free(getbuf.base);
+    return status;
+  }
+  ncp->numrecs = nrecs;
+
+  assert((char *)getbuf.pos < (char *)getbuf.base + getbuf.size);
+
+  status = hdr_get_NC_dimarray(&getbuf, &ncp->dims);
+  if(status != ENOERR) {
+    free(getbuf.base);
+    return status;
+  }
+
+  status = hdr_get_NC_attrarray(&getbuf, &ncp->attrs); 
+  if(status != ENOERR) {
+    free(getbuf.base);
+    return status;
+  }
+
+  status = hdr_get_NC_vararray(&getbuf, &ncp->vars);
+  if(status != ENOERR) {
+    free(getbuf.base);
+    return status; 
+  }
+
+  ncp->xsz = hdr_len_NC(ncp); 
+  status = NC_computeshapes(ncp);
+  free(getbuf.base);
+
+  return status;
+}
+
+/* End Of get NC */
Index: /branches/SDM_SciDAC/src/lib/ncx.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/ncx.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/ncx.c (revision 2)
@@ -0,0 +1,4154 @@
+/* Do not edit this file. It is produced from the corresponding .m4 source */
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ * 	
+ * 	This file contains some routines derived from code
+ *	which is copyrighted by Sun Microsystems, Inc.
+ *	The "#ifdef vax" versions of
+ *		 ncx_put_float_float()
+ *		 ncx_get_float_float()
+ *		 ncx_put_double_double()
+ *		 ncx_get_double_double()
+ *		 ncx_putn_float_float()
+ *		 ncx_getn_float_float()
+ *		 ncx_putn_double_double()
+ *		 ncx_getn_double_double()
+ * 	are derived from xdr_float() and xdr_double() routines
+ *	in the freely available, copyrighted Sun RPCSRC 3.9
+ *	distribution, xdr_float.c.
+ * 	Our "value added" is that these are always memory to memory,
+ *	they handle IEEE subnormals properly, and their "n" versions
+ *	operate speedily on arrays.
+ */
+/* $Id$ */
+
+/*
+ * An external data representation interface.
+ */
+
+#include "ncx.h"
+#include <string.h>
+#include <limits.h>
+/* alias poorly named limits.h macros */
+#define  SHORT_MAX  SHRT_MAX
+#define  SHORT_MIN  SHRT_MIN
+#define USHORT_MAX USHRT_MAX
+#include <float.h>
+#ifndef FLT_MAX /* This POSIX macro missing on some systems */
+# ifndef NO_IEEE_FLOAT
+# define FLT_MAX 3.40282347e+38f
+# else
+# error "You will need to define FLT_MAX"
+# endif
+#endif
+#include <assert.h>
+
+/*
+ * If the machine's float domain is "smaller" than the external one
+ * use the machine domain
+ */
+#if defined(FLT_MAX_EXP) && FLT_MAX_EXP < 128 /* 128 is X_FLT_MAX_EXP */
+#undef X_FLOAT_MAX
+# define X_FLOAT_MAX FLT_MAX
+#undef X_FLOAT_MIN
+# define X_FLOAT_MIN (-X_FLOAT_MAX)
+#endif
+
+#if _SX /* NEC SUPER UX */
+#if _INT64
+#undef  INT_MAX /* workaround cpp bug */
+#define INT_MAX  X_INT_MAX
+#undef  INT_MIN /* workaround cpp bug */
+#define INT_MIN  X_INT_MIN
+#undef  LONG_MAX /* workaround cpp bug */
+#define LONG_MAX  X_INT_MAX
+#undef  LONG_MIN /* workaround cpp bug */
+#define LONG_MIN  X_INT_MIN
+#elif _LONG64
+#undef  LONG_MAX /* workaround cpp bug */
+#define LONG_MAX  4294967295L
+#undef  LONG_MIN /* workaround cpp bug */
+#define LONG_MIN -4294967295L
+#endif
+#endif /* _SX */
+
+static const char nada[X_ALIGN] = {0, 0, 0, 0};
+
+#ifndef WORDS_BIGENDIAN
+/* LITTLE_ENDIAN: DEC and intel */
+/*
+ * Routines to convert to BIGENDIAN.
+ * Optimize the swapn?b() and swap?b() routines aggressivly.
+ */
+
+#define SWAP2(a) ( (((a) & 0xff) << 8) | \
+		(((a) >> 8) & 0xff) )
+
+#define SWAP4(a) ( ((a) << 24) | \
+		(((a) <<  8) & 0x00ff0000) | \
+		(((a) >>  8) & 0x0000ff00) | \
+		(((a) >> 24) & 0x000000ff) )
+
+static void
+swapn2b(void *dst, const void *src, size_t nn)
+{
+	char *op = dst;
+	const char *ip = src;
+	while(nn-- != 0)
+	{
+		*op++ = *(++ip);
+		*op++ = *(ip++ -1);
+	}
+}
+
+# ifndef vax
+static void
+swap4b(void *dst, const void *src)
+{
+	char *op = dst;
+	const char *ip = src;
+	op[0] = ip[3];
+	op[1] = ip[2];
+	op[2] = ip[1];
+	op[3] = ip[0];
+}
+# endif /* !vax */
+
+static void
+swapn4b(void *dst, const void *src, size_t nn)
+{
+	char *op = dst;
+	const char *ip = src;
+	while(nn-- != 0)
+	{
+		op[0] = ip[3];
+		op[1] = ip[2];
+		op[2] = ip[1];
+		op[3] = ip[0];
+		op += 4;
+		ip += 4;
+	}
+}
+
+# ifndef vax
+static void
+swap8b(void *dst, const void *src)
+{
+	char *op = dst;
+	const char *ip = src;
+	op[0] = ip[7];
+	op[1] = ip[6];
+	op[2] = ip[5];
+	op[3] = ip[4];
+	op[4] = ip[3];
+	op[5] = ip[2];
+	op[6] = ip[1];
+	op[7] = ip[0];
+}
+# endif /* !vax */
+
+# ifndef vax
+static void
+swapn8b(void *dst, const void *src, size_t nn)
+{
+	char *op = dst;
+	const char *ip = src;
+	while(nn-- != 0)
+	{
+		op[0] = ip[7];
+		op[1] = ip[6];
+		op[2] = ip[5];
+		op[3] = ip[4];
+		op[4] = ip[3];
+		op[5] = ip[2];
+		op[6] = ip[1];
+		op[7] = ip[0];
+		op += 8;
+		ip += 8;
+	}
+}
+# endif /* !vax */
+
+#endif /* LITTLE_ENDIAN */
+
+
+/*
+ * Primitive numeric conversion functions.
+ */
+
+/* x_schar */
+
+ /* We don't implement and x_schar primitives. */
+
+
+/* x_short */
+
+#if SHORT_MAX == X_SHORT_MAX
+typedef short ix_short;
+#define SIZEOF_IX_SHORT SIZEOF_SHORT
+#define IX_SHORT_MAX SHORT_MAX
+#elif INT_MAX >= X_SHORT_MAX
+typedef int ix_short;
+#define SIZEOF_IX_SHORT SIZEOF_INT
+#define IX_SHORT_MAX INT_MAX
+#elif LONG_MAX >= X_SHORT_MAX
+typedef long ix_short;
+#define SIZEOF_IX_SHORT SIZEOF_LONG
+#define IX_SHORT_MAX LONG_MAX
+#else
+#error "ix_short implementation"
+#endif
+
+static void
+get_ix_short(const void *xp, ix_short *ip)
+{
+	const uchar *cp = (const uchar *) xp;
+	*ip = *cp++ << 8;
+#if SIZEOF_IX_SHORT > X_SIZEOF_SHORT
+	if(*ip & 0x8000)
+	{
+		/* extern is negative */
+		*ip |= (~(0xffff)); /* N.B. Assumes "twos complement" */
+	}
+#endif
+	*ip |= *cp; 
+}
+
+static void
+put_ix_short(void *xp, const ix_short *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = (*ip) >> 8;
+	*cp = (*ip) & 0xff;
+}
+
+
+int
+ncx_get_short_schar(const void *xp, schar *ip)
+{
+	ix_short xx;
+	get_ix_short(xp, &xx);
+	*ip = xx;
+	if(xx > SCHAR_MAX || xx < SCHAR_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_short_uchar(const void *xp, uchar *ip)
+{
+	ix_short xx;
+	get_ix_short(xp, &xx);
+	*ip = xx;
+	if(xx > UCHAR_MAX || xx < 0)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_short_short(const void *xp, short *ip)
+{
+#if SIZEOF_IX_SHORT == SIZEOF_SHORT && IX_SHORT_MAX == SHORT_MAX
+	get_ix_short(xp, (ix_short *)ip);
+	return ENOERR;
+#else
+	ix_short xx;
+	get_ix_short(xp, &xx);
+	*ip = xx;
+#   if IX_SHORT_MAX > SHORT_MAX
+	if(xx > SHORT_MAX || xx < SHORT_MIN)
+		return NC_ERANGE;
+#   endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_get_short_int(const void *xp, int *ip)
+{
+#if SIZEOF_IX_SHORT == SIZEOF_INT && IX_SHORT_MAX == INT_MAX
+	get_ix_short(xp, (ix_short *)ip);
+	return ENOERR;
+#else
+	ix_short xx;
+	get_ix_short(xp, &xx);
+	*ip = xx;
+#   if IX_SHORT_MAX > INT_MAX
+	if(xx > INT_MAX || xx < INT_MIN)
+		return NC_ERANGE;
+#   endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_get_short_long(const void *xp, long *ip)
+{
+#if SIZEOF_IX_SHORT == SIZEOF_LONG && IX_SHORT_MAX == LONG_MAX
+	get_ix_short(xp, (ix_short *)ip);
+	return ENOERR;
+#else
+	/* assert(LONG_MAX >= X_SHORT_MAX); */
+	ix_short xx;
+	get_ix_short(xp, &xx);
+	*ip = xx;
+	return ENOERR;
+#endif
+}
+
+int
+ncx_get_short_float(const void *xp, float *ip)
+{
+	ix_short xx;
+	get_ix_short(xp, &xx);
+	*ip = xx;
+#if 0	/* TODO: determine when necessary */
+	if(xx > FLT_MAX || xx < (-FLT_MAX))
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_get_short_double(const void *xp, double *ip)
+{
+	/* assert(DBL_MAX >= X_SHORT_MAX); */
+	ix_short xx;
+	get_ix_short(xp, &xx);
+	*ip = xx;
+	return ENOERR;
+}
+
+int
+ncx_put_short_schar(void *xp, const schar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	if(*ip & 0x80)
+		*cp++ = 0xff;
+	else
+		*cp++ = 0;
+	*cp = (uchar)*ip;
+	return ENOERR;
+}
+
+int
+ncx_put_short_uchar(void *xp, const uchar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = 0;
+	*cp = *ip;
+	return ENOERR;
+}
+
+int
+ncx_put_short_short(void *xp, const short *ip)
+{
+#if SIZEOF_IX_SHORT == SIZEOF_SHORT && X_SHORT_MAX == SHORT_MAX
+	put_ix_short(xp, (const ix_short *)ip);
+	return ENOERR;
+#else
+	ix_short xx = (ix_short)*ip;
+	put_ix_short(xp, &xx);
+# if X_SHORT_MAX < SHORT_MAX
+	if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
+		return NC_ERANGE;
+# endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_put_short_int(void *xp, const int *ip)
+{
+#if SIZEOF_IX_SHORT == SIZEOF_INT && X_SHORT_MAX == INT_MAX
+	put_ix_short(xp, (const ix_short *)ip);
+	return ENOERR;
+#else
+	ix_short xx = (ix_short)*ip;
+	put_ix_short(xp, &xx);
+# if X_SHORT_MAX < INT_MAX
+	if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
+		return NC_ERANGE;
+# endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_put_short_long(void *xp, const long *ip)
+{
+#if SIZEOF_IX_SHORT == SIZEOF_LONG && X_SHORT_MAX == LONG_MAX
+	put_ix_short(xp, (const ix_short *)ip);
+	return ENOERR;
+#else
+	ix_short xx = (ix_short)*ip;
+	put_ix_short(xp, &xx);
+# if X_SHORT_MAX < LONG_MAX
+	if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
+		return NC_ERANGE;
+# endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_put_short_float(void *xp, const float *ip)
+{
+	ix_short xx = *ip;
+	put_ix_short(xp, &xx);
+	if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_put_short_double(void *xp, const double *ip)
+{
+	ix_short xx = *ip;
+	put_ix_short(xp, &xx);
+	if(*ip > X_SHORT_MAX || *ip < X_SHORT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+/* x_int */
+
+#if SHORT_MAX == X_INT_MAX
+typedef short ix_int;
+#define SIZEOF_IX_INT SIZEOF_SHORT
+#define IX_INT_MAX SHORT_MAX
+#elif INT_MAX  >= X_INT_MAX
+typedef int ix_int;
+#define SIZEOF_IX_INT SIZEOF_INT
+#define IX_INT_MAX INT_MAX
+#elif LONG_MAX  >= X_INT_MAX
+typedef long ix_int;
+#define SIZEOF_IX_INT SIZEOF_LONG
+#define IX_INT_MAX LONG_MAX
+#else
+#error "ix_int implementation"
+#endif
+
+
+static void
+get_ix_int(const void *xp, ix_int *ip)
+{
+	const uchar *cp = (const uchar *) xp;
+
+	*ip = *cp++ << 24;
+#if SIZEOF_IX_INT > X_SIZEOF_INT
+	if(*ip & 0x80000000)
+	{
+		/* extern is negative */
+		*ip |= (~(0xffffffff)); /* N.B. Assumes "twos complement" */
+	}
+#endif
+	*ip |= (*cp++ << 16);
+	*ip |= (*cp++ << 8);
+	*ip |= *cp; 
+}
+
+static void
+put_ix_int(void *xp, const ix_int *ip)
+{
+	uchar *cp = (uchar *) xp;
+
+	*cp++ = (*ip) >> 24;
+	*cp++ = ((*ip) & 0x00ff0000) >> 16;
+	*cp++ = ((*ip) & 0x0000ff00) >>  8;
+	*cp   = ((*ip) & 0x000000ff);
+}
+
+
+int
+ncx_get_int_schar(const void *xp, schar *ip)
+{
+	ix_int xx;
+	get_ix_int(xp, &xx);
+	*ip = xx;
+	if(xx > SCHAR_MAX || xx < SCHAR_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_int_uchar(const void *xp, uchar *ip)
+{
+	ix_int xx;
+	get_ix_int(xp, &xx);
+	*ip = xx;
+	if(xx > UCHAR_MAX || xx < 0)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_int_short(const void *xp, short *ip)
+{
+#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX
+	get_ix_int(xp, (ix_int *)ip);
+	return ENOERR;
+#else
+	ix_int xx;
+	get_ix_int(xp, &xx);
+	*ip = xx;
+#  if IX_INT_MAX > SHORT_MAX
+	if(xx > SHORT_MAX || xx < SHORT_MIN)
+		return NC_ERANGE;
+#  endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_get_int_int(const void *xp, int *ip)
+{
+#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX
+	get_ix_int(xp, (ix_int *)ip);
+	return ENOERR;
+#else
+	ix_int xx;
+	get_ix_int(xp, &xx);
+	*ip = xx;
+#  if IX_INT_MAX > INT_MAX
+	if(xx > INT_MAX || xx < INT_MIN)
+		return NC_ERANGE;
+#  endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_get_int_long(const void *xp, long *ip)
+{
+#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX
+	get_ix_int(xp, (ix_int *)ip);
+	return ENOERR;
+#else
+	ix_int xx;
+	get_ix_int(xp, &xx);
+	*ip = xx;
+#  if IX_INT_MAX > LONG_MAX	/* unlikely */
+	if(xx > LONG_MAX || xx < LONG_MIN)
+		return NC_ERANGE;
+#  endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_get_int_float(const void *xp, float *ip)
+{
+	ix_int xx;
+	get_ix_int(xp, &xx);
+	*ip = xx;
+#if 0	/* TODO: determine when necessary */
+	if(xx > FLT_MAX || xx < (-FLT_MAX))
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_get_int_double(const void *xp, double *ip)
+{
+	/* assert((DBL_MAX >= X_INT_MAX); */
+	ix_int xx;
+	get_ix_int(xp, &xx);
+	*ip = xx;
+	return ENOERR;
+}
+
+int
+ncx_put_int_schar(void *xp, const schar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	if(*ip & 0x80)
+	{
+		*cp++ = 0xff;
+		*cp++ = 0xff;
+		*cp++ = 0xff;
+	}
+	else
+	{
+		*cp++ = 0x00;
+		*cp++ = 0x00;
+		*cp++ = 0x00;
+	}
+	*cp = (uchar)*ip;
+	return ENOERR;
+}
+
+int
+ncx_put_int_uchar(void *xp, const uchar *ip)
+{
+	uchar *cp = (uchar *) xp;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp++ = 0x00;
+	*cp   = *ip;
+	return ENOERR;
+}
+
+int
+ncx_put_int_short(void *xp, const short *ip)
+{
+#if SIZEOF_IX_INT == SIZEOF_SHORT && IX_INT_MAX == SHORT_MAX
+	put_ix_int(xp, (ix_int *)ip);
+	return ENOERR;
+#else
+	ix_int xx = (ix_int)(*ip);
+	put_ix_int(xp, &xx);
+#   if IX_INT_MAX < SHORT_MAX
+	if(*ip > X_INT_MAX || *ip < X_INT_MIN)
+		return NC_ERANGE;
+#   endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_put_int_int(void *xp, const int *ip)
+{
+#if SIZEOF_IX_INT == SIZEOF_INT && IX_INT_MAX == INT_MAX
+	put_ix_int(xp, (ix_int *)ip);
+	return ENOERR;
+#else
+	ix_int xx = (ix_int)(*ip);
+	put_ix_int(xp, &xx);
+#   if IX_INT_MAX < INT_MAX
+	if(*ip > X_INT_MAX || *ip < X_INT_MIN)
+		return NC_ERANGE;
+#   endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_put_int_long(void *xp, const long *ip)
+{
+#if SIZEOF_IX_INT == SIZEOF_LONG && IX_INT_MAX == LONG_MAX
+	put_ix_int(xp, (ix_int *)ip);
+	return ENOERR;
+#else
+	ix_int xx = (ix_int)(*ip);
+	put_ix_int(xp, &xx);
+#   if IX_INT_MAX < LONG_MAX
+	if(*ip > X_INT_MAX || *ip < X_INT_MIN)
+		return NC_ERANGE;
+#   endif
+	return ENOERR;
+#endif
+}
+
+int
+ncx_put_int_float(void *xp, const float *ip)
+{
+	ix_int xx = (ix_int)(*ip);
+	put_ix_int(xp, &xx);
+	if(*ip > (double)X_INT_MAX || *ip < (double)X_INT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_put_int_double(void *xp, const double *ip)
+{
+	ix_int xx = (ix_int)(*ip);
+	put_ix_int(xp, &xx);
+	if(*ip > X_INT_MAX || *ip < X_INT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+ 
+
+/* x_float */
+
+#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
+
+static void
+get_ix_float(const void *xp, float *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(ip, xp, sizeof(float));
+#else
+	swap4b(ip, xp);
+#endif
+}
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(xp, ip, X_SIZEOF_FLOAT);
+#else
+	swap4b(xp, ip);
+#endif
+}
+
+#elif vax
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct	ieee_single {
+	unsigned int	exp_hi       : 7;
+	unsigned int	sign         : 1;
+	unsigned int 	mant_hi      : 7;
+	unsigned int	exp_lo       : 1;
+	unsigned int	mant_lo_hi   : 8;
+	unsigned int	mant_lo_lo   : 8;
+};
+
+/* Vax single precision floating point */
+struct	vax_single {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS	0x81
+#define IEEE_SNG_BIAS	0x7f
+
+static struct sgl_limits {
+	struct vax_single s;
+	struct ieee_single ieee;
+} max = {
+	{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
+	{ 0x7f, 0x0, 0x0, 0x1, 0x0, 0x0 }		/* Max IEEE */
+};
+static struct sgl_limits min = {
+	{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
+	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }		/* Min IEEE */
+};
+
+static void
+get_ix_float(const void *xp, float *ip)
+{
+		struct vax_single *const vsp = (struct vax_single *) ip;
+		const struct ieee_single *const isp =
+			 (const struct ieee_single *) xp;
+		unsigned exp = isp->exp_hi << 1 | isp->exp_lo;
+
+		switch(exp) {
+		case 0 :
+			/* ieee subnormal */
+			if(isp->mant_hi == min.ieee.mant_hi
+				&& isp->mant_lo_hi == min.ieee.mant_lo_hi
+				&& isp->mant_lo_lo == min.ieee.mant_lo_lo)
+			{
+				*vsp = min.s;
+			}
+			else
+			{
+				unsigned mantissa = (isp->mant_hi << 16)
+					 | isp->mant_lo_hi << 8
+					 | isp->mant_lo_lo;
+				unsigned tmp = mantissa >> 20;
+				if(tmp >= 4) {
+					vsp->exp = 2;
+				} else if (tmp >= 2) {
+					vsp->exp = 1;
+				} else {
+					*vsp = min.s;
+					break;
+				} /* else */
+				tmp = mantissa - (1 << (20 + vsp->exp ));
+				tmp <<= 3 - vsp->exp;
+				vsp->mantissa2 = tmp;
+				vsp->mantissa1 = (tmp >> 16);
+			}
+			break;
+		case 0xfe :
+		case 0xff :
+			*vsp = max.s;
+			break;
+		default :
+			vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+			vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo;
+			vsp->mantissa1 = isp->mant_hi;
+		}
+
+		vsp->sign = isp->sign;
+
+}
+
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+		const struct vax_single *const vsp =
+			 (const struct vax_single *)ip;
+		struct ieee_single *const isp = (struct ieee_single *) xp;
+
+		switch(vsp->exp){
+		case 0 :
+			/* all vax float with zero exponent map to zero */
+			*isp = min.ieee;
+			break;
+		case 2 :
+		case 1 :
+		{
+			/* These will map to subnormals */
+			unsigned mantissa = (vsp->mantissa1 << 16)
+					 | vsp->mantissa2;
+			mantissa >>= 3 - vsp->exp;
+			mantissa += (1 << (20 + vsp->exp));
+			isp->mant_lo_lo = mantissa;
+			isp->mant_lo_hi = mantissa >> 8;
+			isp->mant_hi = mantissa >> 16;
+			isp->exp_lo = 0;
+			isp->exp_hi = 0;
+		}
+			break;
+		case 0xff : /* max.s.exp */
+			if( vsp->mantissa2 == max.s.mantissa2
+				&& vsp->mantissa1 == max.s.mantissa1)
+			{
+				/* map largest vax float to ieee infinity */
+				*isp = max.ieee;
+				break;
+			} /* else, fall thru */
+		default :
+		{
+			unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+			isp->exp_hi = exp >> 1;
+			isp->exp_lo = exp;
+			isp->mant_lo_lo = vsp->mantissa2;
+			isp->mant_lo_hi = vsp->mantissa2 >> 8;
+			isp->mant_hi = vsp->mantissa1;
+		}
+		}
+
+		isp->sign = vsp->sign;
+
+}
+
+	/* vax */
+#elif defined(_CRAY)
+
+/*
+ * Return the number of bytes until the next "word" boundary
+ * N.B. This is based on the very wierd YMP address structure,
+ * which puts the address within a word in the leftmost 3 bits
+ * of the address.
+ */
+static size_t
+word_align(const void *vp)
+{
+	const size_t rem = ((size_t)vp >> (64 - 3)) & 0x7;
+	return (rem != 0);
+}
+
+struct ieee_single_hi {
+	unsigned int	sign	: 1;
+	unsigned int	 exp	: 8;
+	unsigned int	mant	:23;
+	unsigned int	pad	:32;
+};
+typedef struct ieee_single_hi ieee_single_hi;
+
+struct ieee_single_lo {
+	unsigned int	pad	:32;
+	unsigned int	sign	: 1;
+	unsigned int	 exp	: 8;
+	unsigned int	mant	:23;
+};
+typedef struct ieee_single_lo ieee_single_lo;
+
+static const int ieee_single_bias = 0x7f;
+
+struct ieee_double {
+	unsigned int	sign	: 1;
+	unsigned int	 exp	:11;
+	unsigned int	mant	:52;
+};
+typedef struct ieee_double ieee_double;
+
+static const int ieee_double_bias = 0x3ff;
+
+#if defined(NO_IEEE_FLOAT)
+
+struct cray_single {
+	unsigned int	sign	: 1;
+	unsigned int	 exp	:15;
+	unsigned int	mant	:48;
+};
+typedef struct cray_single cray_single;
+
+static const int cs_ieis_bias = 0x4000 - 0x7f;
+
+static const int cs_id_bias = 0x4000 - 0x3ff;
+
+
+static void
+get_ix_float(const void *xp, float *ip)
+{
+
+	if(word_align(xp) == 0)
+	{
+		const ieee_single_hi *isp = (const ieee_single_hi *) xp;
+		cray_single *csp = (cray_single *) ip;
+
+		if(isp->exp == 0)
+		{
+			/* ieee subnormal */
+			*ip = (double)isp->mant;
+			if(isp->mant != 0)
+			{
+				csp->exp -= (ieee_single_bias + 22);
+			}
+		}
+		else
+		{
+			csp->exp  = isp->exp + cs_ieis_bias + 1;
+			csp->mant = isp->mant << (48 - 1 - 23);
+			csp->mant |= (1 << (48 - 1));
+		}
+		csp->sign = isp->sign;
+
+
+	}
+	else
+	{
+		const ieee_single_lo *isp = (const ieee_single_lo *) xp;
+		cray_single *csp = (cray_single *) ip;
+
+		if(isp->exp == 0)
+		{
+			/* ieee subnormal */
+			*ip = (double)isp->mant;
+			if(isp->mant != 0)
+			{
+				csp->exp -= (ieee_single_bias + 22);
+			}
+		}
+		else
+		{
+			csp->exp  = isp->exp + cs_ieis_bias + 1;
+			csp->mant = isp->mant << (48 - 1 - 23);
+			csp->mant |= (1 << (48 - 1));
+		}
+		csp->sign = isp->sign;
+
+
+	}
+}
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+	if(word_align(xp) == 0)
+	{
+		ieee_single_hi *isp = (ieee_single_hi*)xp;
+	const cray_single *csp = (const cray_single *) ip;
+	int ieee_exp = csp->exp - cs_ieis_bias -1;
+
+	isp->sign = csp->sign;
+
+	if(ieee_exp >= 0xff)
+	{
+		/* NC_ERANGE => ieee Inf */
+		isp->exp = 0xff;
+		isp->mant = 0x0;
+	}
+	else if(ieee_exp > 0)
+	{
+		/* normal ieee representation */
+		isp->exp  = ieee_exp;
+		/* assumes cray rep is in normal form */
+		assert(csp->mant & 0x800000000000);
+		isp->mant = (((csp->mant << 1) &
+				0xffffffffffff) >> (48 - 23));
+	}
+	else if(ieee_exp > -23)
+	{
+		/* ieee subnormal, right  */
+		const int rshift = (48 - 23 - ieee_exp);
+
+		isp->mant = csp->mant >> rshift;
+
+#if 0
+		if(csp->mant & (1 << (rshift -1)))
+		{
+			/* round up */
+			isp->mant++;
+		}
+#endif
+
+		isp->exp  = 0;
+	}
+	else
+	{
+		/* smaller than ieee can represent */
+		isp->exp = 0;
+		isp->mant = 0;
+	}
+
+	}
+	else
+	{
+		ieee_single_lo *isp = (ieee_single_lo*)xp;
+	const cray_single *csp = (const cray_single *) ip;
+	int ieee_exp = csp->exp - cs_ieis_bias -1;
+
+	isp->sign = csp->sign;
+
+	if(ieee_exp >= 0xff)
+	{
+		/* NC_ERANGE => ieee Inf */
+		isp->exp = 0xff;
+		isp->mant = 0x0;
+	}
+	else if(ieee_exp > 0)
+	{
+		/* normal ieee representation */
+		isp->exp  = ieee_exp;
+		/* assumes cray rep is in normal form */
+		assert(csp->mant & 0x800000000000);
+		isp->mant = (((csp->mant << 1) &
+				0xffffffffffff) >> (48 - 23));
+	}
+	else if(ieee_exp > -23)
+	{
+		/* ieee subnormal, right  */
+		const int rshift = (48 - 23 - ieee_exp);
+
+		isp->mant = csp->mant >> rshift;
+
+#if 0
+		if(csp->mant & (1 << (rshift -1)))
+		{
+			/* round up */
+			isp->mant++;
+		}
+#endif
+
+		isp->exp  = 0;
+	}
+	else
+	{
+		/* smaller than ieee can represent */
+		isp->exp = 0;
+		isp->mant = 0;
+	}
+
+	}
+}
+
+#else
+	/* IEEE Cray with only doubles */
+static void
+get_ix_float(const void *xp, float *ip)
+{
+
+	ieee_double *idp = (ieee_double *) ip;
+
+	if(word_align(xp) == 0)
+	{
+		const ieee_single_hi *isp = (const ieee_single_hi *) xp;
+		if(isp->exp == 0 && isp->mant == 0)
+		{
+			idp->exp = 0;
+			idp->mant = 0;
+		}
+		else
+		{
+			idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias);
+			idp->mant = isp->mant << (52 - 23);
+		}
+		idp->sign = isp->sign;
+	}
+	else
+	{
+		const ieee_single_lo *isp = (const ieee_single_lo *) xp;
+		if(isp->exp == 0 && isp->mant == 0)
+		{
+			idp->exp = 0;
+			idp->mant = 0;
+		}
+		else
+		{
+			idp->exp = isp->exp + (ieee_double_bias - ieee_single_bias);
+			idp->mant = isp->mant << (52 - 23);
+		}
+		idp->sign = isp->sign;
+	}
+}
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+	const ieee_double *idp = (const ieee_double *) ip;
+	if(word_align(xp) == 0)
+	{
+		ieee_single_hi *isp = (ieee_single_hi*)xp;
+		if(idp->exp > (ieee_double_bias - ieee_single_bias))
+			isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias);
+		else
+			isp->exp = 0;
+		isp->mant = idp->mant >> (52 - 23);
+		isp->sign = idp->sign;
+	}
+	else
+	{
+		ieee_single_lo *isp = (ieee_single_lo*)xp;
+		if(idp->exp > (ieee_double_bias - ieee_single_bias))
+			isp->exp = idp->exp - (ieee_double_bias - ieee_single_bias);
+		else
+			isp->exp = 0;
+		isp->mant = idp->mant >> (52 - 23);
+		isp->sign = idp->sign;
+	}
+}
+#endif
+
+#elif _SX && _FLOAT2
+static void
+get_ix_float(const void *xp, float *ip)
+{
+	const int ncnv = ie3_fl2(xp, ip, 4, 8, 1);
+}
+
+static void
+put_ix_float(void *xp, const float *ip)
+{
+	const int ncnv = fl2_ie3(ip, xp, 8, 4, 1);
+}
+#else
+#error "ix_float implementation"
+#endif
+
+
+int
+ncx_get_float_schar(const void *xp, schar *ip)
+{
+	float xx;
+	get_ix_float(xp, &xx);
+	*ip = (schar) xx;
+	if(xx > SCHAR_MAX || xx < SCHAR_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_float_uchar(const void *xp, uchar *ip)
+{
+	float xx;
+	get_ix_float(xp, &xx);
+	*ip = (uchar) xx;
+	if(xx > UCHAR_MAX || xx < 0)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_float_short(const void *xp, short *ip)
+{
+	float xx;
+	get_ix_float(xp, &xx);
+	*ip = (short) xx;
+	if(xx > SHORT_MAX || xx < SHORT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_float_int(const void *xp, int *ip)
+{
+	float xx;
+	get_ix_float(xp, &xx);
+	*ip = (int) xx;
+	if(xx > (double)INT_MAX || xx < (double)INT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_float_long(const void *xp, long *ip)
+{
+	float xx;
+	get_ix_float(xp, &xx);
+	*ip = (long) xx;
+	if(xx > LONG_MAX || xx < LONG_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_float_float(const void *xp, float *ip)
+{
+	/* TODO */
+	get_ix_float(xp, ip);
+	return ENOERR;
+}
+
+int
+ncx_get_float_double(const void *xp, double *ip)
+{
+	/* TODO */
+	float xx;
+	get_ix_float(xp, &xx);
+	*ip = xx;
+	return ENOERR;
+}
+
+
+int
+ncx_put_float_schar(void *xp, const schar *ip)
+{
+	float xx = (float) *ip;
+	put_ix_float(xp, &xx);
+	return ENOERR;
+}
+
+int
+ncx_put_float_uchar(void *xp, const uchar *ip)
+{
+	float xx = (float) *ip;
+	put_ix_float(xp, &xx);
+	return ENOERR;
+}
+
+int
+ncx_put_float_short(void *xp, const short *ip)
+{
+	float xx = (float) *ip;
+	put_ix_float(xp, &xx);
+#if 0	/* TODO: figure this out */
+	if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_float_int(void *xp, const int *ip)
+{
+	float xx = (float) *ip;
+	put_ix_float(xp, &xx);
+#if 1	/* TODO: figure this out */
+	if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_float_long(void *xp, const long *ip)
+{
+	float xx = (float) *ip;
+	put_ix_float(xp, &xx);
+#if 1	/* TODO: figure this out */
+	if((float)(*ip) > X_FLOAT_MAX || (float)(*ip) < X_FLOAT_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_float_float(void *xp, const float *ip)
+{
+	put_ix_float(xp, ip);
+#ifdef NO_IEEE_FLOAT
+	if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_float_double(void *xp, const double *ip)
+{
+	float xx = (float) *ip;
+	put_ix_float(xp, &xx);
+	if(*ip > X_FLOAT_MAX || *ip < X_FLOAT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+/* x_double */
+
+#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE  && !defined(NO_IEEE_FLOAT)
+
+static void
+get_ix_double(const void *xp, double *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(ip, xp, sizeof(double));
+#else
+	swap8b(ip, xp);
+#endif
+}
+
+static void
+put_ix_double(void *xp, const double *ip)
+{
+#ifdef WORDS_BIGENDIAN
+	(void) memcpy(xp, ip, X_SIZEOF_DOUBLE);
+#else
+	swap8b(xp, ip);
+#endif
+}
+
+#elif vax
+
+/* What IEEE double precision floating point looks like on a Vax */
+struct	ieee_double {
+	unsigned int	exp_hi   : 7;
+	unsigned int	sign     : 1;
+	unsigned int 	mant_6   : 4;
+	unsigned int	exp_lo   : 4;
+	unsigned int	mant_5   : 8;
+	unsigned int	mant_4   : 8;
+
+	unsigned int	mant_lo  : 32;
+};
+
+/* Vax double precision floating point */
+struct  vax_double {
+	unsigned int	mantissa1 : 7;
+	unsigned int	exp       : 8;
+	unsigned int	sign      : 1;
+	unsigned int	mantissa2 : 16;
+	unsigned int	mantissa3 : 16;
+	unsigned int	mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS	0x81
+#define IEEE_DBL_BIAS	0x3ff
+#define MASK(nbits)	((1 << nbits) - 1)
+
+static const struct dbl_limits {
+	struct	vax_double d;
+	struct	ieee_double ieee;
+} dbl_limits[2] = {
+	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
+	{ 0x7f, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0}}, /* Max IEEE */
+	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
+	{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, /* Min IEEE */
+};
+
+
+static void
+get_ix_double(const void *xp, double *ip)
+{
+	struct vax_double *const vdp =
+			 (struct vax_double *)ip;
+	const struct ieee_double *const idp =
+			 (const struct ieee_double *) xp;
+	{
+		const struct dbl_limits *lim;
+		int ii;
+		for (ii = 0, lim = dbl_limits;
+			ii < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			ii++, lim++)
+		{
+			if ((idp->mant_lo == lim->ieee.mant_lo)
+				&& (idp->mant_4 == lim->ieee.mant_4)
+				&& (idp->mant_5 == lim->ieee.mant_5)
+				&& (idp->mant_6 == lim->ieee.mant_6)
+				&& (idp->exp_lo == lim->ieee.exp_lo)
+				&& (idp->exp_hi == lim->ieee.exp_hi)
+				)
+			{
+				*vdp = lim->d;
+				goto doneit;
+			}
+		}
+	}
+	{
+		unsigned exp = idp->exp_hi << 4 | idp->exp_lo;
+		vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+	}
+	{
+		unsigned mant_hi = ((idp->mant_6 << 16)
+				 | (idp->mant_5 << 8)
+				 | idp->mant_4);
+		unsigned mant_lo = SWAP4(idp->mant_lo);
+		vdp->mantissa1 = (mant_hi >> 13);
+		vdp->mantissa2 = ((mant_hi & MASK(13)) << 3)
+				| (mant_lo >> 29);
+		vdp->mantissa3 = (mant_lo >> 13);
+		vdp->mantissa4 = (mant_lo << 3);
+	}
+	doneit:
+		vdp->sign = idp->sign;
+
+}
+
+
+static void
+put_ix_double(void *xp, const double *ip)
+{
+	const struct vax_double *const vdp = 
+			(const struct vax_double *)ip;
+	struct ieee_double *const idp =
+			 (struct ieee_double *) xp;
+
+	if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) &&
+		(vdp->mantissa3 == dbl_limits[0].d.mantissa3) &&
+		(vdp->mantissa2 == dbl_limits[0].d.mantissa2) &&
+		(vdp->mantissa1 == dbl_limits[0].d.mantissa1) &&
+		(vdp->exp == dbl_limits[0].d.exp))
+	{
+		*idp = dbl_limits[0].ieee;
+		goto shipit;
+	}
+	if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) &&
+		(vdp->mantissa3 == dbl_limits[1].d.mantissa3) &&
+		(vdp->mantissa2 == dbl_limits[1].d.mantissa2) &&
+		(vdp->mantissa1 == dbl_limits[1].d.mantissa1) &&
+		(vdp->exp == dbl_limits[1].d.exp))
+	{
+		*idp = dbl_limits[1].ieee;
+		goto shipit;
+	}
+
+	{
+		unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+
+		unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) |
+			(vdp->mantissa3 << 13) |
+			((vdp->mantissa4 >> 3) & MASK(13));
+
+		unsigned mant_hi = (vdp->mantissa1 << 13)
+				 | (vdp->mantissa2 >> 3);
+
+		if((vdp->mantissa4 & 7) > 4)
+		{
+			/* round up */
+			mant_lo++;
+			if(mant_lo == 0)
+			{
+				mant_hi++;
+				if(mant_hi > 0xffffff)
+				{
+					mant_hi = 0;
+					exp++;
+				}
+			}
+		}
+
+		idp->mant_lo = SWAP4(mant_lo);
+		idp->mant_6 = mant_hi >> 16;
+		idp->mant_5 = (mant_hi & 0xff00) >> 8;
+		idp->mant_4 = mant_hi;
+		idp->exp_hi = exp >> 4;
+		idp->exp_lo = exp;
+	}
+		
+	shipit:
+		idp->sign = vdp->sign;
+
+}
+
+	/* vax */
+#elif defined(_CRAY)
+
+static void
+get_ix_double(const void *xp, double *ip)
+{
+	const ieee_double *idp = (const ieee_double *) xp;
+	cray_single *csp = (cray_single *) ip;
+
+	if(idp->exp == 0)
+	{
+		/* ieee subnormal */
+		*ip = (double)idp->mant;
+		if(idp->mant != 0)
+		{
+			csp->exp -= (ieee_double_bias + 51);
+		}
+	}
+	else
+	{
+		csp->exp  = idp->exp + cs_id_bias + 1;
+		csp->mant = idp->mant >> (52 - 48 + 1);
+		csp->mant |= (1 << (48 - 1));
+	}
+	csp->sign = idp->sign;
+}
+
+static void
+put_ix_double(void *xp, const double *ip)
+{
+	ieee_double *idp = (ieee_double *) xp;
+	const cray_single *csp = (const cray_single *) ip;
+
+	int ieee_exp = csp->exp - cs_id_bias -1;
+
+	idp->sign = csp->sign;
+
+	if(ieee_exp >= 0x7ff)
+	{
+		/* NC_ERANGE => ieee Inf */
+		idp->exp = 0x7ff;
+		idp->mant = 0x0;
+	}
+	else if(ieee_exp > 0)
+	{
+		/* normal ieee representation */
+		idp->exp  = ieee_exp;
+		/* assumes cray rep is in normal form */
+		assert(csp->mant & 0x800000000000);
+		idp->mant = (((csp->mant << 1) &
+				0xffffffffffff) << (52 - 48));
+	}
+	else if(ieee_exp >= (-(52 -48)))
+	{
+		/* ieee subnormal, left  */
+		const int lshift = (52 - 48) + ieee_exp;
+		idp->mant = csp->mant << lshift;
+		idp->exp  = 0;
+	}
+	else if(ieee_exp >= -52)
+	{
+		/* ieee subnormal, right  */
+		const int rshift = (- (52 - 48) - ieee_exp);
+
+		idp->mant = csp->mant >> rshift;
+
+#if 0
+		if(csp->mant & (1 << (rshift -1)))
+		{
+			/* round up */
+			idp->mant++;
+		}
+#endif
+
+		idp->exp  = 0;
+	}
+	else
+	{
+		/* smaller than ieee can represent */
+		idp->exp = 0;
+		idp->mant = 0;
+	}
+}
+#elif _SX && _FLOAT2
+static void
+get_ix_double(const void *xp, double *ip)
+{
+	const int ncnv = ie3_fl2(xp, ip, 8, 8, 1);
+}
+
+static void
+put_ix_double(void *xp, const double *ip)
+{
+	const int ncnv = fl2_ie3(ip, xp, 8, 8, 1);
+}
+#else
+#error "ix_double implementation"
+#endif
+
+int
+ncx_get_double_schar(const void *xp, schar *ip)
+{
+	double xx;
+	get_ix_double(xp, &xx);
+	*ip = (schar) xx;
+	if(xx > SCHAR_MAX || xx < SCHAR_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_double_uchar(const void *xp, uchar *ip)
+{
+	double xx;
+	get_ix_double(xp, &xx);
+	*ip = (uchar) xx;
+	if(xx > UCHAR_MAX || xx < 0)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_double_short(const void *xp, short *ip)
+{
+	double xx;
+	get_ix_double(xp, &xx);
+	*ip = (short) xx;
+	if(xx > SHORT_MAX || xx < SHORT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_double_int(const void *xp, int *ip)
+{
+	double xx;
+	get_ix_double(xp, &xx);
+	*ip = (int) xx;
+	if(xx > INT_MAX || xx < INT_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_double_long(const void *xp, long *ip)
+{
+	double xx;
+	get_ix_double(xp, &xx);
+	*ip = (long) xx;
+	if(xx > LONG_MAX || xx < LONG_MIN)
+		return NC_ERANGE;
+	return ENOERR;
+}
+
+int
+ncx_get_double_float(const void *xp, float *ip)
+{
+	double xx;
+	get_ix_double(xp, &xx);
+	if(xx > FLT_MAX || xx < (-FLT_MAX))
+	{
+		*ip = FLT_MAX;
+		return NC_ERANGE;
+	}
+	if(xx < (-FLT_MAX))
+	{
+		*ip = (-FLT_MAX);
+		return NC_ERANGE;
+	}
+	*ip = (float) xx;
+	return ENOERR;
+}
+
+int
+ncx_get_double_double(const void *xp, double *ip)
+{
+	/* TODO */
+	get_ix_double(xp, ip);
+	return ENOERR;
+}
+
+
+int
+ncx_put_double_schar(void *xp, const schar *ip)
+{
+	double xx = (double) *ip;
+	put_ix_double(xp, &xx);
+	return ENOERR;
+}
+
+int
+ncx_put_double_uchar(void *xp, const uchar *ip)
+{
+	double xx = (double) *ip;
+	put_ix_double(xp, &xx);
+	return ENOERR;
+}
+
+int
+ncx_put_double_short(void *xp, const short *ip)
+{
+	double xx = (double) *ip;
+	put_ix_double(xp, &xx);
+#if 0	/* TODO: figure this out */
+	if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_double_int(void *xp, const int *ip)
+{
+	double xx = (double) *ip;
+	put_ix_double(xp, &xx);
+#if 0	/* TODO: figure this out */
+	if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_double_long(void *xp, const long *ip)
+{
+	double xx = (double) *ip;
+	put_ix_double(xp, &xx);
+#if 1	/* TODO: figure this out */
+	if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_double_float(void *xp, const float *ip)
+{
+	double xx = (double) *ip;
+	put_ix_double(xp, &xx);
+#if 1	/* TODO: figure this out */
+	if((double)(*ip) > X_DOUBLE_MAX || (double)(*ip) < X_DOUBLE_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+int
+ncx_put_double_double(void *xp, const double *ip)
+{
+	put_ix_double(xp, ip);
+#ifdef NO_IEEE_FLOAT
+	if(*ip > X_DOUBLE_MAX || *ip < X_DOUBLE_MIN)
+		return NC_ERANGE;
+#endif
+	return ENOERR;
+}
+
+
+/* x_size_t */
+
+#if SIZEOF_SIZE_T < X_SIZEOF_SIZE_T
+#error "x_size_t implementation"
+/* netcdf requires size_t which can hold a values from 0 to 2^31 -1 */
+#endif
+
+int
+ncx_put_size_t(void **xpp, const size_t *ulp)
+{
+	/* similar to put_ix_int() */
+	uchar *cp = (uchar *) *xpp;
+		/* sizes limited to 2^31 -1 in netcdf */
+	assert(*ulp <= X_SIZE_MAX && (long) (*ulp) >= 0);
+
+	*cp++ = (uchar)((*ulp) >> 24);
+	*cp++ = (uchar)(((*ulp) & 0x00ff0000) >> 16);
+	*cp++ = (uchar)(((*ulp) & 0x0000ff00) >>  8);
+	*cp   = (uchar)((*ulp) & 0x000000ff);
+
+	*xpp = (void *)((char *)(*xpp) + X_SIZEOF_SIZE_T);
+	return ENOERR;
+}
+
+int
+ncx_get_size_t(const void **xpp,  size_t *ulp)
+{
+	/* similar to get_ix_int */
+	const uchar *cp = (const uchar *) *xpp;
+	assert((*cp & 0x80) == 0); /* sizes limited to 2^31 -1 in netcdf */
+
+	*ulp = *cp++ << 24;
+	*ulp |= (*cp++ << 16);
+	*ulp |= (*cp++ << 8);
+	*ulp |= *cp; 
+
+	*xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_SIZE_T);
+	return ENOERR;
+}
+
+/* x_off_t */
+
+#if SIZEOF_OFF_T < X_SIZEOF_OFF_T
+#error "x_off_t implementation"
+/* netcdf requires size_t which can hold a values from 0 to 2^31 -1 */
+#endif
+
+int
+ncx_put_off_t(void **xpp, const off_t *lp)
+{
+	/* similar to put_ix_int() */
+	uchar *cp = (uchar *) *xpp;
+		/* No negative offsets stored in netcdf */
+	assert(*lp >= 0 && *lp <= X_OFF_MAX);
+
+	*cp++ = (uchar)((*lp) >> 24);
+	*cp++ = (uchar)(((*lp) & 0x00ff0000) >> 16);
+	*cp++ = (uchar)(((*lp) & 0x0000ff00) >>  8);
+	*cp   = (uchar)((*lp) & 0x000000ff);
+
+	*xpp = (void *)((char *)(*xpp) + X_SIZEOF_OFF_T);
+	return ENOERR;
+}
+
+int
+ncx_get_off_t(const void **xpp, off_t *lp)
+{
+	/* similar to get_ix_int() */
+	const uchar *cp = (const uchar *) *xpp;
+	assert((*cp & 0x80) == 0); /* No negative offsets stored in netcdf */
+
+	*lp = *cp++ << 24;
+	*lp |= (*cp++ << 16);
+	*lp |= (*cp++ << 8);
+	*lp |= *cp; 
+
+	*xpp = (const void *)((const char *)(*xpp) + X_SIZEOF_OFF_T);
+	return ENOERR;
+}
+
+
+/*
+ * Aggregate numeric conversion functions.
+ */
+
+
+
+/* schar */
+
+int
+ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *tp)
+{
+		(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+	return ENOERR;
+
+}
+int
+ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp)
+{
+		(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+	return ENOERR;
+
+}
+int
+ncx_getn_schar_short(const void **xpp, size_t nelems, short *tp)
+{
+	schar *xp = (schar *)(*xpp);
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (const void *)xp;
+	return ENOERR;
+}
+
+int
+ncx_getn_schar_int(const void **xpp, size_t nelems, int *tp)
+{
+	schar *xp = (schar *)(*xpp);
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (const void *)xp;
+	return ENOERR;
+}
+
+int
+ncx_getn_schar_long(const void **xpp, size_t nelems, long *tp)
+{
+	schar *xp = (schar *)(*xpp);
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (const void *)xp;
+	return ENOERR;
+}
+
+int
+ncx_getn_schar_float(const void **xpp, size_t nelems, float *tp)
+{
+	schar *xp = (schar *)(*xpp);
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (const void *)xp;
+	return ENOERR;
+}
+
+int
+ncx_getn_schar_double(const void **xpp, size_t nelems, double *tp)
+{
+	schar *xp = (schar *)(*xpp);
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (const void *)xp;
+	return ENOERR;
+}
+
+
+int
+ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *tp)
+{
+		size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems + rndup);
+
+	return ENOERR;
+
+}
+int
+ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *tp)
+{
+		size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems + rndup);
+
+	return ENOERR;
+
+}
+int
+ncx_pad_getn_schar_short(const void **xpp, size_t nelems, short *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (void *)(xp + rndup);
+	return ENOERR;
+}
+
+int
+ncx_pad_getn_schar_int(const void **xpp, size_t nelems, int *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (void *)(xp + rndup);
+	return ENOERR;
+}
+
+int
+ncx_pad_getn_schar_long(const void **xpp, size_t nelems, long *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (void *)(xp + rndup);
+	return ENOERR;
+}
+
+int
+ncx_pad_getn_schar_float(const void **xpp, size_t nelems, float *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (void *)(xp + rndup);
+	return ENOERR;
+}
+
+int
+ncx_pad_getn_schar_double(const void **xpp, size_t nelems, double *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		*tp++ = *xp++;
+	}
+
+	*xpp = (void *)(xp + rndup);
+	return ENOERR;
+}
+
+
+int
+ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *tp)
+{
+		(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	return ENOERR;
+
+}
+int
+ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp)
+{
+		(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	return ENOERR;
+
+}
+int
+ncx_putn_schar_short(void **xpp, size_t nelems, const short *tp)
+{
+	int status = ENOERR;
+	schar *xp = (schar *) *xpp;
+
+	while(nelems-- != 0)
+	{
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_schar_int(void **xpp, size_t nelems, const int *tp)
+{
+	int status = ENOERR;
+	schar *xp = (schar *) *xpp;
+
+	while(nelems-- != 0)
+	{
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_schar_long(void **xpp, size_t nelems, const long *tp)
+{
+	int status = ENOERR;
+	schar *xp = (schar *) *xpp;
+
+	while(nelems-- != 0)
+	{
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_schar_float(void **xpp, size_t nelems, const float *tp)
+{
+	int status = ENOERR;
+	schar *xp = (schar *) *xpp;
+
+	while(nelems-- != 0)
+	{
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_schar_double(void **xpp, size_t nelems, const double *tp)
+{
+	int status = ENOERR;
+	schar *xp = (schar *) *xpp;
+
+	while(nelems-- != 0)
+	{
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+
+int
+ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *tp)
+{
+		size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	if(rndup)
+	{
+		(void) memcpy(*xpp, nada, rndup);
+		*xpp = (void *)((char *)(*xpp) + rndup);
+	}
+	
+	return ENOERR;
+
+}
+int
+ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *tp)
+{
+		size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	if(rndup)
+	{
+		(void) memcpy(*xpp, nada, rndup);
+		*xpp = (void *)((char *)(*xpp) + rndup);
+	}
+	
+	return ENOERR;
+
+}
+int
+ncx_pad_putn_schar_short(void **xpp, size_t nelems, const short *tp)
+{
+	int status = ENOERR;
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		/* N.B. schar as signed */
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+
+	if(rndup)
+	{
+		(void) memcpy(xp, nada, rndup);
+		xp += rndup;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_schar_int(void **xpp, size_t nelems, const int *tp)
+{
+	int status = ENOERR;
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		/* N.B. schar as signed */
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+
+	if(rndup)
+	{
+		(void) memcpy(xp, nada, rndup);
+		xp += rndup;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_schar_long(void **xpp, size_t nelems, const long *tp)
+{
+	int status = ENOERR;
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		/* N.B. schar as signed */
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+
+	if(rndup)
+	{
+		(void) memcpy(xp, nada, rndup);
+		xp += rndup;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_schar_float(void **xpp, size_t nelems, const float *tp)
+{
+	int status = ENOERR;
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		/* N.B. schar as signed */
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+
+	if(rndup)
+	{
+		(void) memcpy(xp, nada, rndup);
+		xp += rndup;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *tp)
+{
+	int status = ENOERR;
+	size_t rndup = nelems % X_ALIGN;
+	schar *xp = (schar *) *xpp;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	while(nelems-- != 0)
+	{
+		/* N.B. schar as signed */
+		if(*tp > X_SCHAR_MAX || *tp < X_SCHAR_MIN)
+			status = NC_ERANGE;
+		*xp++ = (schar) *tp++;
+	}
+
+
+	if(rndup)
+	{
+		(void) memcpy(xp, nada, rndup);
+		xp += rndup;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+
+
+/* short */
+
+int
+ncx_getn_short_schar(const void **xpp, size_t nelems, schar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_SHORT == SIZEOF_SHORT
+/* optimized version */
+int
+ncx_getn_short_short(const void **xpp, size_t nelems, short *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, nelems * sizeof(short));
+# else
+	swapn2b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_SHORT);
+	return ENOERR;
+}
+#else
+int
+ncx_getn_short_short(const void **xpp, size_t nelems, short *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#endif
+int
+ncx_getn_short_int(const void **xpp, size_t nelems, int *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_short_long(const void **xpp, size_t nelems, long *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_short_float(const void **xpp, size_t nelems, float *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_short_double(const void **xpp, size_t nelems, double *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+
+int
+ncx_pad_getn_short_schar(const void **xpp, size_t nelems, schar *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+		xp += X_SIZEOF_SHORT;
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+		xp += X_SIZEOF_SHORT;
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_getn_short_short(const void **xpp, size_t nelems, short *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+		xp += X_SIZEOF_SHORT;
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_getn_short_int(const void **xpp, size_t nelems, int *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+		xp += X_SIZEOF_SHORT;
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_getn_short_long(const void **xpp, size_t nelems, long *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+		xp += X_SIZEOF_SHORT;
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_getn_short_float(const void **xpp, size_t nelems, float *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+		xp += X_SIZEOF_SHORT;
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_getn_short_double(const void **xpp, size_t nelems, double *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		const int lstatus = ncx_get_short_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+		xp += X_SIZEOF_SHORT;
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+
+int
+ncx_putn_short_schar(void **xpp, size_t nelems, const schar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_SHORT == SIZEOF_SHORT
+/* optimized version */
+int
+ncx_putn_short_short(void **xpp, size_t nelems, const short *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_SHORT);
+# else
+	swapn2b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_SHORT);
+	return ENOERR;
+}
+#else
+int
+ncx_putn_short_short(void **xpp, size_t nelems, const short *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#endif
+int
+ncx_putn_short_int(void **xpp, size_t nelems, const int *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_short_long(void **xpp, size_t nelems, const long *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_short_float(void **xpp, size_t nelems, const float *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_short_double(void **xpp, size_t nelems, const double *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+
+int
+ncx_pad_putn_short_schar(void **xpp, size_t nelems, const schar *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+	{
+		(void) memcpy(xp, nada, X_SIZEOF_SHORT);
+		xp += X_SIZEOF_SHORT;	
+	}
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+	{
+		(void) memcpy(xp, nada, X_SIZEOF_SHORT);
+		xp += X_SIZEOF_SHORT;	
+	}
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_short_short(void **xpp, size_t nelems, const short *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+	{
+		(void) memcpy(xp, nada, X_SIZEOF_SHORT);
+		xp += X_SIZEOF_SHORT;	
+	}
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_short_int(void **xpp, size_t nelems, const int *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+	{
+		(void) memcpy(xp, nada, X_SIZEOF_SHORT);
+		xp += X_SIZEOF_SHORT;	
+	}
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_short_long(void **xpp, size_t nelems, const long *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+	{
+		(void) memcpy(xp, nada, X_SIZEOF_SHORT);
+		xp += X_SIZEOF_SHORT;	
+	}
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_short_float(void **xpp, size_t nelems, const float *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+	{
+		(void) memcpy(xp, nada, X_SIZEOF_SHORT);
+		xp += X_SIZEOF_SHORT;	
+	}
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *tp)
+{
+	const size_t rndup = nelems % 2;
+
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_SHORT, tp++)
+	{
+		int lstatus = ncx_put_short_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	if(rndup != 0)
+	{
+		(void) memcpy(xp, nada, X_SIZEOF_SHORT);
+		xp += X_SIZEOF_SHORT;	
+	}
+		
+	*xpp = (void *)xp;
+	return status;
+}
+
+
+
+/* int */
+
+int
+ncx_getn_int_schar(const void **xpp, size_t nelems, schar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		const int lstatus = ncx_get_int_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_int_uchar(const void **xpp, size_t nelems, uchar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		const int lstatus = ncx_get_int_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_int_short(const void **xpp, size_t nelems, short *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		const int lstatus = ncx_get_int_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_INT == SIZEOF_INT
+/* optimized version */
+int
+ncx_getn_int_int(const void **xpp, size_t nelems, int *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, nelems * sizeof(int));
+# else
+	swapn4b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT);
+	return ENOERR;
+}
+#else
+int
+ncx_getn_int_int(const void **xpp, size_t nelems, int *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		const int lstatus = ncx_get_int_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#endif
+#if X_SIZEOF_INT == SIZEOF_LONG
+/* optimized version */
+int
+ncx_getn_int_long(const void **xpp, size_t nelems, long *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, nelems * sizeof(long));
+# else
+	swapn4b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_INT);
+	return ENOERR;
+}
+#else
+int
+ncx_getn_int_long(const void **xpp, size_t nelems, long *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		const int lstatus = ncx_get_int_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#endif
+int
+ncx_getn_int_float(const void **xpp, size_t nelems, float *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		const int lstatus = ncx_get_int_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_int_double(const void **xpp, size_t nelems, double *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		const int lstatus = ncx_get_int_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+
+int
+ncx_putn_int_schar(void **xpp, size_t nelems, const schar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		int lstatus = ncx_put_int_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_int_uchar(void **xpp, size_t nelems, const uchar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		int lstatus = ncx_put_int_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_int_short(void **xpp, size_t nelems, const short *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		int lstatus = ncx_put_int_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_INT == SIZEOF_INT
+/* optimized version */
+int
+ncx_putn_int_int(void **xpp, size_t nelems, const int *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT);
+# else
+	swapn4b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT);
+	return ENOERR;
+}
+#else
+int
+ncx_putn_int_int(void **xpp, size_t nelems, const int *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		int lstatus = ncx_put_int_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#endif
+#if X_SIZEOF_INT == SIZEOF_LONG
+/* optimized version */
+int
+ncx_putn_int_long(void **xpp, size_t nelems, const long *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_INT);
+# else
+	swapn4b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_INT);
+	return ENOERR;
+}
+#else
+int
+ncx_putn_int_long(void **xpp, size_t nelems, const long *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		int lstatus = ncx_put_int_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#endif
+int
+ncx_putn_int_float(void **xpp, size_t nelems, const float *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		int lstatus = ncx_put_int_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_int_double(void **xpp, size_t nelems, const double *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_INT, tp++)
+	{
+		int lstatus = ncx_put_int_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+
+
+/* float */
+
+int
+ncx_getn_float_schar(const void **xpp, size_t nelems, schar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncx_get_float_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_float_uchar(const void **xpp, size_t nelems, uchar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncx_get_float_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_float_short(const void **xpp, size_t nelems, short *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncx_get_float_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_float_int(const void **xpp, size_t nelems, int *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncx_get_float_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_float_long(const void **xpp, size_t nelems, long *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncx_get_float_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncx_getn_float_float(const void **xpp, size_t nelems, float *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, nelems * sizeof(float));
+# else
+	swapn4b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
+	return ENOERR;
+}
+#elif vax
+int
+ncx_getn_float_float(const void **xpp, size_t nfloats, float *ip)
+{
+	float *const end = ip + nfloats;
+
+	while(ip < end)
+	{
+		struct vax_single *const vsp = (struct vax_single *) ip;
+		const struct ieee_single *const isp =
+			 (const struct ieee_single *) (*xpp);
+		unsigned exp = isp->exp_hi << 1 | isp->exp_lo;
+
+		switch(exp) {
+		case 0 :
+			/* ieee subnormal */
+			if(isp->mant_hi == min.ieee.mant_hi
+				&& isp->mant_lo_hi == min.ieee.mant_lo_hi
+				&& isp->mant_lo_lo == min.ieee.mant_lo_lo)
+			{
+				*vsp = min.s;
+			}
+			else
+			{
+				unsigned mantissa = (isp->mant_hi << 16)
+					 | isp->mant_lo_hi << 8
+					 | isp->mant_lo_lo;
+				unsigned tmp = mantissa >> 20;
+				if(tmp >= 4) {
+					vsp->exp = 2;
+				} else if (tmp >= 2) {
+					vsp->exp = 1;
+				} else {
+					*vsp = min.s;
+					break;
+				} /* else */
+				tmp = mantissa - (1 << (20 + vsp->exp ));
+				tmp <<= 3 - vsp->exp;
+				vsp->mantissa2 = tmp;
+				vsp->mantissa1 = (tmp >> 16);
+			}
+			break;
+		case 0xfe :
+		case 0xff :
+			*vsp = max.s;
+			break;
+		default :
+			vsp->exp = exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+			vsp->mantissa2 = isp->mant_lo_hi << 8 | isp->mant_lo_lo;
+			vsp->mantissa1 = isp->mant_hi;
+		}
+
+		vsp->sign = isp->sign;
+
+
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
+	}
+	return ENOERR;
+}
+#elif _SX && _FLOAT2
+int
+ncx_getn_float_float(const void **xpp, size_t nelems, float *tp)
+{
+	const char *const xp = *xpp;
+
+	const int ncnv = ie3_fl2(xp, tp, 4, 8, nelems);
+
+	*xpp = xp + nelems * X_SIZEOF_FLOAT;
+	return (nelems == ncnv ? ENOERR : NC_ERANGE);
+}
+#else
+int
+ncx_getn_float_float(const void **xpp, size_t nelems, float *tp)
+{
+	const char *xp = *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncx_get_float_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#endif
+int
+ncx_getn_float_double(const void **xpp, size_t nelems, double *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		const int lstatus = ncx_get_float_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+
+int
+ncx_putn_float_schar(void **xpp, size_t nelems, const schar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncx_put_float_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_float_uchar(void **xpp, size_t nelems, const uchar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncx_put_float_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_float_short(void **xpp, size_t nelems, const short *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncx_put_float_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_float_int(void **xpp, size_t nelems, const int *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncx_put_float_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_float_long(void **xpp, size_t nelems, const long *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncx_put_float_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_FLOAT == SIZEOF_FLOAT && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncx_putn_float_float(void **xpp, size_t nelems, const float *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_FLOAT);
+# else
+	swapn4b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_FLOAT);
+	return ENOERR;
+}
+#elif vax
+int
+ncx_putn_float_float(void **xpp, size_t nfloats, const float *ip)
+{
+	const float *const end = ip + nfloats;
+
+	while(ip < end)
+	{
+		const struct vax_single *const vsp =
+			 (const struct vax_single *)ip;
+		struct ieee_single *const isp = (struct ieee_single *) (*xpp);
+
+		switch(vsp->exp){
+		case 0 :
+			/* all vax float with zero exponent map to zero */
+			*isp = min.ieee;
+			break;
+		case 2 :
+		case 1 :
+		{
+			/* These will map to subnormals */
+			unsigned mantissa = (vsp->mantissa1 << 16)
+					 | vsp->mantissa2;
+			mantissa >>= 3 - vsp->exp;
+			mantissa += (1 << (20 + vsp->exp));
+			isp->mant_lo_lo = mantissa;
+			isp->mant_lo_hi = mantissa >> 8;
+			isp->mant_hi = mantissa >> 16;
+			isp->exp_lo = 0;
+			isp->exp_hi = 0;
+		}
+			break;
+		case 0xff : /* max.s.exp */
+			if( vsp->mantissa2 == max.s.mantissa2
+				&& vsp->mantissa1 == max.s.mantissa1)
+			{
+				/* map largest vax float to ieee infinity */
+				*isp = max.ieee;
+				break;
+			} /* else, fall thru */
+		default :
+		{
+			unsigned exp = vsp->exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+			isp->exp_hi = exp >> 1;
+			isp->exp_lo = exp;
+			isp->mant_lo_lo = vsp->mantissa2;
+			isp->mant_lo_hi = vsp->mantissa2 >> 8;
+			isp->mant_hi = vsp->mantissa1;
+		}
+		}
+
+		isp->sign = vsp->sign;
+
+	
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_FLOAT;
+	}
+	return ENOERR;
+}
+#elif _SX && _FLOAT2
+int
+ncx_putn_float_float(void **xpp, size_t nelems, const float *tp)
+{
+	char *const xp = *xpp;
+
+	const int ncnv = fl2_ie3(tp, xp, 8, 4, nelems);
+
+	*xpp = xp + nelems * X_SIZEOF_FLOAT;
+	return (nelems == ncnv ? ENOERR : NC_ERANGE);
+}
+#else
+int
+ncx_putn_float_float(void **xpp, size_t nelems, const float *tp)
+{
+	char *xp = *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncx_put_float_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#endif
+int
+ncx_putn_float_double(void **xpp, size_t nelems, const double *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_FLOAT, tp++)
+	{
+		int lstatus = ncx_put_float_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+
+
+/* double */
+
+int
+ncx_getn_double_schar(const void **xpp, size_t nelems, schar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncx_get_double_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_double_uchar(const void **xpp, size_t nelems, uchar *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncx_get_double_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_double_short(const void **xpp, size_t nelems, short *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncx_get_double_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_double_int(const void **xpp, size_t nelems, int *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncx_get_double_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_double_long(const void **xpp, size_t nelems, long *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncx_get_double_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+int
+ncx_getn_double_float(const void **xpp, size_t nelems, float *tp)
+{
+	const char *xp = (const char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncx_get_double_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncx_getn_double_double(const void **xpp, size_t nelems, double *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(tp, *xpp, nelems * sizeof(double));
+# else
+	swapn8b(tp, *xpp, nelems);
+# endif
+	*xpp = (const void *)((const char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
+	return ENOERR;
+}
+#elif vax
+int
+ncx_getn_double_double(const void **xpp, size_t ndoubles, double *ip)
+{
+	double *const end = ip + ndoubles;
+
+	while(ip < end)
+	{
+	struct vax_double *const vdp =
+			 (struct vax_double *)ip;
+	const struct ieee_double *const idp =
+			 (const struct ieee_double *) (*xpp);
+	{
+		const struct dbl_limits *lim;
+		int ii;
+		for (ii = 0, lim = dbl_limits;
+			ii < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+			ii++, lim++)
+		{
+			if ((idp->mant_lo == lim->ieee.mant_lo)
+				&& (idp->mant_4 == lim->ieee.mant_4)
+				&& (idp->mant_5 == lim->ieee.mant_5)
+				&& (idp->mant_6 == lim->ieee.mant_6)
+				&& (idp->exp_lo == lim->ieee.exp_lo)
+				&& (idp->exp_hi == lim->ieee.exp_hi)
+				)
+			{
+				*vdp = lim->d;
+				goto doneit;
+			}
+		}
+	}
+	{
+		unsigned exp = idp->exp_hi << 4 | idp->exp_lo;
+		vdp->exp = exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+	}
+	{
+		unsigned mant_hi = ((idp->mant_6 << 16)
+				 | (idp->mant_5 << 8)
+				 | idp->mant_4);
+		unsigned mant_lo = SWAP4(idp->mant_lo);
+		vdp->mantissa1 = (mant_hi >> 13);
+		vdp->mantissa2 = ((mant_hi & MASK(13)) << 3)
+				| (mant_lo >> 29);
+		vdp->mantissa3 = (mant_lo >> 13);
+		vdp->mantissa4 = (mant_lo << 3);
+	}
+	doneit:
+		vdp->sign = idp->sign;
+
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
+	}
+	return ENOERR;
+}
+	/* vax */
+#elif _SX && _FLOAT2
+int
+ncx_getn_double_double(const void **xpp, size_t nelems, double *tp)
+{
+	const char *const xp = *xpp;
+
+	const int ncnv = ie3_fl2(xp, tp, 8, 8, nelems);
+
+	*xpp = xp + nelems * X_SIZEOF_DOUBLE;
+	return (nelems == ncnv ? ENOERR : NC_ERANGE);
+}
+#else
+int
+ncx_getn_double_double(const void **xpp, size_t nelems, double *tp)
+{
+	const char *xp = *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		const int lstatus = ncx_get_double_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (const void *)xp;
+	return status;
+}
+
+#endif
+
+int
+ncx_putn_double_schar(void **xpp, size_t nelems, const schar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncx_put_double_schar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_double_uchar(void **xpp, size_t nelems, const uchar *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncx_put_double_uchar(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_double_short(void **xpp, size_t nelems, const short *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncx_put_double_short(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_double_int(void **xpp, size_t nelems, const int *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncx_put_double_int(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_double_long(void **xpp, size_t nelems, const long *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncx_put_double_long(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+int
+ncx_putn_double_float(void **xpp, size_t nelems, const float *tp)
+{
+	char *xp = (char *) *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncx_put_double_float(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#if X_SIZEOF_DOUBLE == SIZEOF_DOUBLE && !defined(NO_IEEE_FLOAT)
+/* optimized version */
+int
+ncx_putn_double_double(void **xpp, size_t nelems, const double *tp)
+{
+# if WORDS_BIGENDIAN
+	(void) memcpy(*xpp, tp, nelems * X_SIZEOF_DOUBLE);
+# else
+	swapn8b(*xpp, tp, nelems);
+# endif
+	*xpp = (void *)((char *)(*xpp) + nelems * X_SIZEOF_DOUBLE);
+	return ENOERR;
+}
+#elif vax
+int
+ncx_putn_double_double(void **xpp, size_t ndoubles, const double *ip)
+{
+	const double *const end = ip + ndoubles;
+
+	while(ip < end)
+	{
+	const struct vax_double *const vdp = 
+			(const struct vax_double *)ip;
+	struct ieee_double *const idp =
+			 (struct ieee_double *) (*xpp);
+
+	if ((vdp->mantissa4 > (dbl_limits[0].d.mantissa4 - 3)) &&
+		(vdp->mantissa3 == dbl_limits[0].d.mantissa3) &&
+		(vdp->mantissa2 == dbl_limits[0].d.mantissa2) &&
+		(vdp->mantissa1 == dbl_limits[0].d.mantissa1) &&
+		(vdp->exp == dbl_limits[0].d.exp))
+	{
+		*idp = dbl_limits[0].ieee;
+		goto shipit;
+	}
+	if ((vdp->mantissa4 == dbl_limits[1].d.mantissa4) &&
+		(vdp->mantissa3 == dbl_limits[1].d.mantissa3) &&
+		(vdp->mantissa2 == dbl_limits[1].d.mantissa2) &&
+		(vdp->mantissa1 == dbl_limits[1].d.mantissa1) &&
+		(vdp->exp == dbl_limits[1].d.exp))
+	{
+		*idp = dbl_limits[1].ieee;
+		goto shipit;
+	}
+
+	{
+		unsigned exp = vdp->exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+
+		unsigned mant_lo = ((vdp->mantissa2 & MASK(3)) << 29) |
+			(vdp->mantissa3 << 13) |
+			((vdp->mantissa4 >> 3) & MASK(13));
+
+		unsigned mant_hi = (vdp->mantissa1 << 13)
+				 | (vdp->mantissa2 >> 3);
+
+		if((vdp->mantissa4 & 7) > 4)
+		{
+			/* round up */
+			mant_lo++;
+			if(mant_lo == 0)
+			{
+				mant_hi++;
+				if(mant_hi > 0xffffff)
+				{
+					mant_hi = 0;
+					exp++;
+				}
+			}
+		}
+
+		idp->mant_lo = SWAP4(mant_lo);
+		idp->mant_6 = mant_hi >> 16;
+		idp->mant_5 = (mant_hi & 0xff00) >> 8;
+		idp->mant_4 = mant_hi;
+		idp->exp_hi = exp >> 4;
+		idp->exp_lo = exp;
+	}
+		
+	shipit:
+		idp->sign = vdp->sign;
+
+		ip++;
+		*xpp = (char *)(*xpp) + X_SIZEOF_DOUBLE;
+	}
+	return ENOERR;
+}
+	/* vax */
+#elif _SX && _FLOAT2
+int
+ncx_putn_double_double(void **xpp, size_t nelems, const double *tp)
+{
+	char *const xp = *xpp;
+
+	const int ncnv = fl2_ie3(tp, xp, 8, 8, nelems);
+
+	*xpp = xp + nelems * X_SIZEOF_DOUBLE;
+	return (nelems == ncnv ? ENOERR : NC_ERANGE);
+}
+#else
+int
+ncx_putn_double_double(void **xpp, size_t nelems, const double *tp)
+{
+	char *xp = *xpp;
+	int status = ENOERR;
+
+	for( ; nelems != 0; nelems--, xp += X_SIZEOF_DOUBLE, tp++)
+	{
+		int lstatus = ncx_put_double_double(xp, tp);
+		if(lstatus != ENOERR)
+			status = lstatus;
+	}
+
+	*xpp = (void *)xp;
+	return status;
+}
+
+#endif
+
+
+/*
+ * Other aggregate conversion functions.
+ */
+
+/* text */
+
+int
+ncx_getn_text(const void **xpp, size_t nelems, char *tp)
+{
+	(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+	return ENOERR;
+
+}
+
+int
+ncx_pad_getn_text(const void **xpp, size_t nelems, char *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems + rndup);
+
+	return ENOERR;
+
+}
+
+int
+ncx_putn_text(void **xpp, size_t nelems, const char *tp)
+{
+	(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	return ENOERR;
+
+}
+
+int
+ncx_pad_putn_text(void **xpp, size_t nelems, const char *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	if(rndup)
+	{
+		(void) memcpy(*xpp, nada, rndup);
+		*xpp = (void *)((char *)(*xpp) + rndup);
+	}
+	
+	return ENOERR;
+
+}
+
+
+/* opaque */
+
+int
+ncx_getn_void(const void **xpp, size_t nelems, void *tp)
+{
+	(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+	return ENOERR;
+
+}
+
+int
+ncx_pad_getn_void(const void **xpp, size_t nelems, void *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(tp, *xpp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems + rndup);
+
+	return ENOERR;
+
+}
+
+int
+ncx_putn_void(void **xpp, size_t nelems, const void *tp)
+{
+	(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	return ENOERR;
+
+}
+
+int
+ncx_pad_putn_void(void **xpp, size_t nelems, const void *tp)
+{
+	size_t rndup = nelems % X_ALIGN;
+
+	if(rndup)
+		rndup = X_ALIGN - rndup;
+
+	(void) memcpy(*xpp, tp, nelems);
+	*xpp = (void *)((char *)(*xpp) + nelems);
+
+	if(rndup)
+	{
+		(void) memcpy(*xpp, nada, rndup);
+		*xpp = (void *)((char *)(*xpp) + rndup);
+	}
+	
+	return ENOERR;
+
+}
+
Index: /branches/SDM_SciDAC/src/lib/rnd.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/rnd.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/rnd.h (revision 2)
@@ -0,0 +1,17 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+#ifndef _RNDUP
+
+/* useful for aligning memory */
+#define	_RNDUP(x, unit)  ((((x) + (unit) - 1) / (unit)) \
+	* (unit))
+#define	_RNDDOWN(x, unit)  ((x) - ((x)%(unit)))
+
+#define M_RND_UNIT	(sizeof(double))
+#define	M_RNDUP(x) _RNDUP(x, M_RND_UNIT)
+#define	M_RNDDOWN(x)  __RNDDOWN(x, M_RND_UNIT)
+
+#endif
Index: /branches/SDM_SciDAC/src/lib/var.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/var.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/var.c (revision 2)
@@ -0,0 +1,785 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "nc.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ncx.h"
+#include "rnd.h"
+
+
+/*
+ * Free var
+ * Formerly
+NC_free_var(var)
+ */
+void
+free_NC_var(NC_var *varp)
+{
+	if(varp == NULL)
+		return;
+	free_NC_attrarrayV(&varp->attrs);
+	free_NC_string(varp->name);
+	free(varp);
+}
+
+
+/* 
+ * Common code for new_NC_var() 
+ * and ncx_get_NC_var()
+ */
+NC_var *
+new_x_NC_var(
+	NC_string *strp,
+	size_t ndims)
+{
+	NC_var *varp;
+	const size_t o1 = M_RNDUP(ndims * sizeof(int));
+	const size_t o2 = M_RNDUP(ndims * sizeof(size_t));
+	const size_t sz =  M_RNDUP(sizeof(NC_var)) +
+		 o1 + o2 + ndims * sizeof(size_t);
+
+	varp = (NC_var *) malloc(sz);
+	if(varp == NULL )
+		return NULL;
+	(void) memset(varp, 0, sz);
+
+	varp->name = strp;
+	varp->ndims = ndims;
+
+	if(ndims != 0)
+	{
+		/*
+		 * NOTE: lint may complain about the next 3 lines:
+		 * "pointer cast may result in improper alignment".
+		 * We use the M_RNDUP() macro to get the proper alignment.
+		 */
+		varp->dimids = (int *)((char *)varp + M_RNDUP(sizeof(NC_var)));
+		varp->shape = (size_t *)((char *)varp->dimids + o1);
+		varp->dsizes = (size_t *)((char *)varp->shape + o2);
+	}
+
+	varp->xsz = 0;
+	varp->len = 0;
+	varp->begin = 0;
+
+	return varp;
+}
+
+
+/*
+ * Formerly
+NC_new_var()
+ */
+static NC_var *
+new_NC_var(const char *name, nc_type type,
+	size_t ndims, const int *dimids)
+{
+	NC_string *strp;
+	NC_var *varp;
+
+	strp = new_NC_string(strlen(name), name);
+	if(strp == NULL)
+		return NULL;
+
+	varp = new_x_NC_var(strp, ndims);
+	if(varp == NULL )
+	{
+		free_NC_string(strp);
+		return NULL;
+	}
+	
+	varp->type = type;
+
+	if( ndims != 0 && dimids != NULL)
+		(void) memcpy(varp->dimids, dimids, ndims * sizeof(int));
+
+	return(varp);
+}
+
+
+static NC_var *
+dup_NC_var(const NC_var *rvarp)
+{
+	NC_var *varp = new_NC_var(rvarp->name->cp, rvarp->type,
+		 rvarp->ndims, rvarp->dimids);
+	if(varp == NULL)
+		return NULL;
+
+	
+	if(dup_NC_attrarrayV(&varp->attrs, &rvarp->attrs) != NC_NOERR)
+	{
+		free_NC_var(varp);
+		return NULL;
+	}
+
+	(void) memcpy(varp->shape, rvarp->shape,
+			 rvarp->ndims * sizeof(size_t));
+	(void) memcpy(varp->dsizes, rvarp->dsizes,
+			 rvarp->ndims * sizeof(size_t));
+	varp->xsz = rvarp->xsz;
+	varp->len = rvarp->len;
+	varp->begin = rvarp->begin;
+
+	return varp;
+}
+
+
+/* vararray */
+
+
+/*
+ * Free the stuff "in" (referred to by) an NC_vararray.
+ * Leaves the array itself allocated.
+ */
+void
+free_NC_vararrayV0(NC_vararray *ncap)
+{
+	assert(ncap != NULL);
+
+	if(ncap->nelems == 0)
+		return;
+
+	assert(ncap->value != NULL);
+
+	{
+		NC_var **vpp = ncap->value;
+		NC_var *const *const end = &vpp[ncap->nelems];
+		for( /*NADA*/; vpp < end; vpp++)
+		{
+			free_NC_var(*vpp);
+			*vpp = NULL;
+		}
+	}
+	ncap->nelems = 0;
+}
+
+
+/*
+ * Free NC_vararray values.
+ * formerly
+NC_free_array()
+ */
+void
+free_NC_vararrayV(NC_vararray *ncap)
+{
+	assert(ncap != NULL);
+	
+	if(ncap->nalloc == 0)
+		return;
+
+	assert(ncap->value != NULL);
+
+	free_NC_vararrayV0(ncap);
+
+	free(ncap->value);
+	ncap->value = NULL;
+	ncap->nalloc = 0;
+}
+
+
+int
+dup_NC_vararrayV(NC_vararray *ncap, const NC_vararray *ref)
+{
+	int status = NC_NOERR;
+
+	assert(ref != NULL);
+	assert(ncap != NULL);
+
+	if(ref->nelems != 0)
+	{
+		const size_t sz = ref->nelems * sizeof(NC_var *);
+		ncap->value = (NC_var **) malloc(sz);
+		if(ncap->value == NULL)
+			return NC_ENOMEM;
+		(void) memset(ncap->value, 0, sz);
+		ncap->nalloc = ref->nelems;
+	}
+
+	ncap->nelems = 0;
+	{
+		NC_var **vpp = ncap->value;
+		const NC_var **drpp = (const NC_var **)ref->value;
+		NC_var *const *const end = &vpp[ref->nelems];
+		for( /*NADA*/; vpp < end; drpp++, vpp++, ncap->nelems++)
+		{
+			*vpp = dup_NC_var(*drpp);
+			if(*vpp == NULL)
+			{
+				status = NC_ENOMEM;
+				break;
+			}
+		}
+	}
+
+	if(status != NC_NOERR)
+	{
+		free_NC_vararrayV(ncap);
+		return status;
+	}
+
+	assert(ncap->nelems == ref->nelems);
+
+	return NC_NOERR;
+}
+
+
+/*
+ * Add a new handle on the end of an array of handles
+ * Formerly
+NC_incr_array(array, tail)
+ */
+static int
+incr_NC_vararray(NC_vararray *ncap, NC_var *newelemp)
+{
+	NC_var **vp;
+
+	assert(ncap != NULL);
+
+	if(ncap->nalloc == 0)
+	{
+		assert(ncap->nelems == 0);
+		vp = (NC_var **) malloc(NC_ARRAY_GROWBY * sizeof(NC_var *));
+		if(vp == NULL)
+			return NC_ENOMEM;
+		ncap->value = vp;
+		ncap->nalloc = NC_ARRAY_GROWBY;
+	}
+	else if(ncap->nelems +1 > ncap->nalloc)
+	{
+		vp = (NC_var **) realloc(ncap->value,
+			(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_var *));
+		if(vp == NULL)
+			return NC_ENOMEM;
+		ncap->value = vp;
+		ncap->nalloc += NC_ARRAY_GROWBY;
+	}
+
+	if(newelemp != NULL)
+	{
+		ncap->value[ncap->nelems] = newelemp;
+		ncap->nelems++;
+	}
+	return NC_NOERR;
+}
+
+
+static NC_var *
+elem_NC_vararray(const NC_vararray *ncap, size_t elem)
+{
+	assert(ncap != NULL);
+		/* cast needed for braindead systems with signed size_t */
+	if(ncap->nelems == 0 || (unsigned long)elem >= ncap->nelems)
+		return NULL;
+
+	assert(ncap->value != NULL);
+
+	return ncap->value[elem];
+}
+
+
+/* End vararray per se */
+
+
+/*
+ * Step thru NC_VARIABLE array, seeking match on name.
+ * Return varid or -1 on not found.
+ * *varpp is set to the appropriate NC_var.
+ * Formerly (sort of)
+NC_hvarid
+ */
+int
+NC_findvar(const NC_vararray *ncap, const char *name, NC_var **varpp)
+{
+	NC_var **loc;
+	size_t slen;
+	int varid;
+
+	assert(ncap != NULL);
+
+	if(ncap->nelems == 0)
+		return -1;
+
+	loc = (NC_var **) ncap->value;
+
+	slen = strlen(name);
+
+	for(varid = 0; (size_t) varid < ncap->nelems; varid++, loc++)
+	{
+		if(strlen((*loc)->name->cp) == slen &&
+			strncmp((*loc)->name->cp, name, slen) == 0)
+		{
+			if(varpp != NULL)
+				*varpp = *loc;
+			return(varid); /* Normal return */
+		}
+	}
+	return(-1); /* not found */
+}
+
+/* 
+ * For a netcdf type
+ *  return the size of one element in the external representation.
+ * Note that arrays get rounded up to X_ALIGN boundaries.
+ * Formerly
+NC_xtypelen
+ * See also ncx_len()
+ */
+size_t
+ncx_szof(nc_type type)
+{
+	switch(type){
+	case NC_BYTE:
+	case NC_CHAR:
+		return(1);
+	case NC_SHORT :
+		return(2);
+	case NC_INT:
+		return X_SIZEOF_INT;
+	case NC_FLOAT:
+		return X_SIZEOF_FLOAT;
+	case NC_DOUBLE : 
+		return X_SIZEOF_DOUBLE;
+	}
+	/* default */
+	assert("ncx_szof invalid type" == 0);
+	return 0;
+}
+
+
+/*
+ * 'compile' the shape and len of a variable
+ *  Formerly
+NC_var_shape(var, dims)
+ */
+int
+NC_var_shape(NC_var *varp, const NC_dimarray *dims)
+{
+	size_t *shp, *dsp, *op;
+	int *ip;
+	const NC_dim *dimp;
+	size_t product = 1;
+	
+	varp->xsz = ncx_szof(varp->type);
+
+	if(varp->ndims == 0)
+	{
+		goto out;
+	}
+
+	/*
+	 * use the user supplied dimension indices
+	 * to determine the shape
+	 */
+	for(ip = varp->dimids, op = varp->shape
+		; ip < &varp->dimids[varp->ndims]; ip++, op++)
+	{
+		if(*ip < 0 || (size_t) (*ip) >= ((dims != NULL) ? dims->nelems : 1) )
+			return NC_EBADDIM;
+		
+		dimp = elem_NC_dimarray(dims, (size_t)*ip);
+		*op = dimp->size;
+		if(*op == NC_UNLIMITED && ip != varp->dimids)
+			return NC_EUNLIMPOS;
+	}
+
+	/* 
+	 * Compute the dsizes
+	 */
+				/* ndims is > 0 here */
+	for(shp = varp->shape + varp->ndims -1,
+				dsp = varp->dsizes + varp->ndims -1;
+ 			shp >= varp->shape;
+			shp--, dsp--)
+	{
+		if(!(shp == varp->shape && IS_RECVAR(varp)))
+			product *= *shp;
+		*dsp = product;
+	}
+
+
+out :
+	varp->len = product * varp->xsz;
+	switch(varp->type) {
+	case NC_BYTE :
+	case NC_CHAR :
+	case NC_SHORT :
+		if( varp->len%4 != 0 )
+		{
+			varp->len += 4 - varp->len%4; /* round up */
+	/*		*dsp += 4 - *dsp%4; */
+		}
+		break;
+	default:
+		/* already aligned */
+		break;
+	}
+#if 0
+	arrayp("\tshape", varp->ndims, varp->shape);
+	arrayp("\tdsizes", varp->ndims, varp->dsizes);
+#endif
+	return NC_NOERR;
+}
+
+
+/*
+ * Given valid ncp and varid, return var
+ *  else NULL on error
+ * Formerly
+NC_hlookupvar()
+ */
+NC_var *
+NC_lookupvar(NC *ncp, int varid)
+{
+	NC_var *varp;
+
+	if(varid == NC_GLOBAL)
+	{
+		/* Global is error in this context */
+		return(NULL);
+	}
+
+	varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
+	if(varp == NULL)
+	{
+		return NULL;
+	}
+
+	assert(varp != NULL);
+
+	return(varp);
+}
+
+
+/* Public */
+
+int
+nc_def_var( int ncid, const char *name, nc_type type,
+	 int ndims, const int *dimids, int *varidp)
+{
+	int status;
+	NC *ncp;
+	int varid;
+	NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(!NC_indef(ncp))
+	{
+		return NC_ENOTINDEFINE;
+	}
+
+	status = NC_check_name(name);
+	if(status != NC_NOERR)
+		return status;
+
+	status = nc_cktype(type);
+	if(status != NC_NOERR)
+		return status;
+
+		/* cast needed for braindead systems with signed size_t */
+	if((unsigned long) ndims > X_INT_MAX) /* Backward compat */
+	{
+		return NC_EINVAL;
+	} 
+
+	if(ncp->vars.nelems >= NC_MAX_VARS)
+	{
+		return NC_EMAXVARS;
+	}
+
+	varid = NC_findvar(&ncp->vars, name, &varp);
+	if(varid != -1)
+	{
+		return NC_ENAMEINUSE;
+	}
+	
+	varp = new_NC_var(name, type, ndims, dimids);
+	if(varp == NULL)
+		return NC_ENOMEM;
+
+	status = NC_var_shape(varp, &ncp->dims);
+	if(status != NC_NOERR)
+	{
+		free_NC_var(varp);
+		return status;
+	}
+
+	status = incr_NC_vararray(&ncp->vars, varp);
+	if(status != NC_NOERR)
+	{
+		free_NC_var(varp);
+		return status;
+	}
+
+	if(varidp != NULL)
+		*varidp = (int)ncp->vars.nelems -1; /* varid */
+	return NC_NOERR;
+}
+
+
+int
+nc_inq_varid(int ncid, const char *name, int *varid_ptr)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+	int varid;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varid = NC_findvar(&ncp->vars, name, &varp);
+	if(varid == -1)
+	{
+		return NC_ENOTVAR;
+	}
+
+	*varid_ptr = varid;
+	return NC_NOERR;
+}
+
+
+int
+nc_inq_var(int ncid,
+	int varid,
+	char *name,
+	nc_type *typep,
+	int *ndimsp,
+	int *dimids,
+	int *nattsp)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+	size_t ii;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
+	if(varp == NULL)
+		return NC_ENOTVAR;
+
+	if(name != NULL)
+	{
+		(void) strncpy(name, varp->name->cp, varp->name->nchars);
+		name[varp->name->nchars] = 0;
+	}
+
+	if(typep != 0)
+		*typep = varp->type;
+	if(ndimsp != 0)
+	{
+		*ndimsp = (int) varp->ndims;
+	}
+	if(dimids != 0)
+	{
+		for(ii = 0; ii < varp->ndims; ii++)
+		{
+			dimids[ii] = varp->dimids[ii];
+		}
+	}
+	if(nattsp != 0)
+	{
+		*nattsp = (int) varp->attrs.nelems;
+	}
+
+	return NC_NOERR;
+}
+
+
+int 
+nc_inq_varname(int ncid, int varid, char *name)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
+	if(varp == NULL)
+		return NC_ENOTVAR;
+
+	if(name != NULL)
+	{
+		(void) strncpy(name, varp->name->cp, varp->name->nchars);
+		name[varp->name->nchars] = 0;
+	}
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_vartype(int ncid, int varid, nc_type *typep)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
+	if(varp == NULL)
+		return NC_ENOTVAR;
+
+	if(typep != 0)
+		*typep = varp->type;
+
+	return NC_NOERR;
+}
+
+int 
+nc_inq_varndims(int ncid, int varid, int *ndimsp)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: is this the right error code? */
+
+	if(ndimsp != 0)
+	{
+		*ndimsp = (int) varp->ndims;
+	}
+
+	return NC_NOERR;
+}
+
+
+int 
+nc_inq_vardimid(int ncid, int varid, int *dimids)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+	size_t ii;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: is this the right error code? */
+
+	if(dimids != 0)
+	{
+		for(ii = 0; ii < varp->ndims; ii++)
+		{
+			dimids[ii] = varp->dimids[ii];
+		}
+	}
+
+	return NC_NOERR;
+}
+
+
+int 
+nc_inq_varnatts(int ncid, int varid, int *nattsp)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+
+	if(varid == NC_GLOBAL)
+		return  nc_inq_natts(ncid, nattsp);
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	varp = elem_NC_vararray(&ncp->vars, (size_t)varid);
+	if(varp == NULL)
+		return NC_ENOTVAR; /* TODO: is this the right error code? */
+
+	if(nattsp != 0)
+	{
+		*nattsp = (int) varp->attrs.nelems;
+	}
+
+	return NC_NOERR;
+}
+
+int
+nc_rename_var(int ncid, int varid, const char *newname)
+{
+	int status;
+	NC *ncp;
+	NC_var *varp;
+	NC_string *old, *newStr;
+	int other;
+
+	status = NC_check_id(ncid, &ncp); 
+	if(status != NC_NOERR)
+		return status;
+
+	if(NC_readonly(ncp))
+	{
+		return NC_EPERM;
+	}
+
+	status = NC_check_name(newname);
+	if(status != NC_NOERR)
+		return status;
+
+	/* check for name in use */
+	other = NC_findvar(&ncp->vars, newname, &varp);
+	if(other != -1)
+	{
+		return NC_ENAMEINUSE;
+	}
+	
+	varp = NC_lookupvar(ncp, varid);
+	if(varp == NULL)
+	{
+		/* invalid varid */
+		return NC_ENOTVAR; /* TODO: is this the right error code? */
+	}
+
+	old = varp->name;
+	if(NC_indef(ncp))
+	{
+		newStr = new_NC_string(strlen(newname),newname);
+		if(newStr == NULL)
+			return(-1);
+		varp->name = newStr;
+		free_NC_string(old);
+		return NC_NOERR;
+	}
+
+	/* else, not in define mode */
+	status = set_NC_string(varp->name, newname);
+	if(status != NC_NOERR)
+		return status;
+
+	set_NC_hdirty(ncp);
+
+	if(NC_doHsync(ncp))
+	{
+		status = NC_sync(ncp);
+		if(status != NC_NOERR)
+			return status;
+	}
+
+	return NC_NOERR;
+}
Index: /branches/SDM_SciDAC/src/lib/error.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/error.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/error.c (revision 2)
@@ -0,0 +1,167 @@
+/*
+ *	Copyright 1993, University Corporation for Atmospheric Research
+ *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id: error.c,v 1.14 90/02/23 16:08:55 davis Exp */
+
+/*LINTLIBRARY*/
+
+#include "ncconfig.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "netcdf.h"
+
+
+#ifndef NO_STRERROR
+#include <string.h> /* contains prototype for ansi libc function strerror() */
+#else
+/* provide a strerror function for older unix systems */
+static char *
+strerror(int errnum)
+{
+    extern int sys_nerr;
+    extern char *sys_errlist[];
+
+    if(errnum < 0 || errnum >= sys_nerr) return NULL;
+    /* else */
+    return sys_errlist[errnum];
+}
+#endif /* NO_STRERROR */
+
+
+#ifdef vms
+/* UNTESTED */
+/*
+ * On the vms system, when a system error occurs which is not
+ * mapped into the unix styled errno values, errno is set EVMSERR
+ * and a VMS error code is set in vaxc$errno.
+ * This routine prints the systems message associated with status return
+ * from a system services call.
+ */
+
+#include <errno.h>
+#include <descrip.h>
+#include <ssdef.h>
+
+static const char *
+vms_strerror( int status )
+{
+	short msglen;
+	static char msgbuf[256];
+	$DESCRIPTOR(message, msgbuf);
+	register ret;
+
+	msgbuf[0] = 0;
+	ret = SYS$GETMSG(status, &msglen, &message, 15, 0);
+	
+	if(ret != SS$_BUFFEROVF && ret != SS$_NORMAL) {
+		(void) strcpy(msgbuf, "EVMSERR");
+	}
+	return(msgbuf);
+}
+#endif /* vms */
+
+
+static char unknown[] = "Unknown Error";
+
+
+const char *
+nc_strerror(int err)
+{
+
+#ifdef vms 
+	if(err == EVMSERR)
+	{
+		return vms_strerror(err);
+	}	
+	/* else */
+#endif /* vms */
+
+	if(NC_ISSYSERR(err))
+	{
+		const char *cp = (const char *) strerror(err);
+		if(cp == NULL)
+			return unknown;
+		/* else */
+		return cp;
+	}
+	/* else */
+
+	switch (err) {
+	case NC_NOERR:
+	    return "No error";
+	case NC_ENOTINDEP:
+	    return "Operation not allowed in collective data mode";
+	case NC_EINDEP:
+	    return "Operation not allowed in independent data mode";
+        case NC_EREAD:
+            return "Unknow error occurs in reading file";
+	case NC_EWRITE:
+	    return "Unknow error occurs in writting file";
+	case NC_EMULTIDEFINE:
+	    return "NC definations on multiprocesses conflict";
+	case NC_EOFILE:
+	    return "Can not open/create file";
+	case NC_EBADID:
+	    return "Not a netCDF id";
+	case NC_ENFILE:
+	    return "Too many netCDF files open";
+	case NC_EEXIST:
+	    return "netCDF file exists && NC_NOCLOBBER";
+	case NC_EINVAL:
+	    return "Invalid argument";
+	case NC_EPERM:
+	    return "Write to read only";
+	case NC_ENOTINDEFINE:
+	    return "Operation not allowed in data mode";
+	case NC_EINDEFINE:
+	    return "Operation not allowed in define mode";
+	case NC_EINVALCOORDS:
+	    return "Index exceeds dimension bound";
+	case NC_EMAXDIMS:
+	    return "NC_MAX_DIMS exceeded";
+	case NC_ENAMEINUSE:
+	    return "String match to name in use";
+	case NC_ENOTATT:
+	    return "Attribute not found";
+	case NC_EMAXATTS:
+	    return "NC_MAX_ATTRS exceeded";
+	case NC_EBADTYPE:
+	    return "Not a netCDF data type or _FillValue type mismatch";
+	case NC_EBADDIM:
+	    return "Invalid dimension id or name";
+	case NC_EUNLIMPOS:
+	    return "NC_UNLIMITED in the wrong index";
+	case NC_EMAXVARS:
+	    return "NC_MAX_VARS exceeded";
+	case NC_ENOTVAR:
+	    return "Variable not found";
+	case NC_EGLOBAL:
+	    return "Action prohibited on NC_GLOBAL varid";
+	case NC_ENOTNC:
+	    return "Not a netCDF file";
+	case NC_ESTS:
+	    return "In Fortran, string too short";
+	case NC_EMAXNAME:
+	    return "NC_MAX_NAME exceeded";
+	case NC_EUNLIMIT:
+	    return "NC_UNLIMITED size already in use";
+	case NC_ENORECVARS:
+	    return "nc_rec op when there are no record vars";
+	case NC_ECHAR:
+	    return "Attempt to convert between text & numbers";
+	case NC_EEDGE:
+	    return "Edge+start exceeds dimension bound";
+	case NC_ESTRIDE:
+	    return "Illegal stride";
+	case NC_EBADNAME:
+	    return "Attribute or variable name contains illegal characters";
+	case NC_ERANGE:
+	    return "Numeric conversion not representable";
+	case NC_ENOMEM:
+	    return "Memory allocation (malloc) failure";
+	}
+	/* default */
+	return unknown;
+}
Index: /branches/SDM_SciDAC/src/lib/posixio.c
===================================================================
--- /branches/SDM_SciDAC/src/lib/posixio.c (revision 2)
+++ /branches/SDM_SciDAC/src/lib/posixio.c (revision 2)
@@ -0,0 +1,1337 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#include "ncconfig.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifndef ENOERR
+#define ENOERR 0
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef _MSC_VER /* Microsoft Compilers */
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#include "ncio.h"
+#include "fbits.h"
+#include "rnd.h"
+
+/* #define INSTRUMENT 1 */
+#if INSTRUMENT /* debugging */
+#undef NDEBUG
+#include <stdio.h>
+#include "instr.h"
+#endif
+
+#undef MIN  /* system may define MIN somewhere and complain */
+#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
+
+#if !defined(NDEBUG) && !defined(X_INT_MAX)
+#define  X_INT_MAX 2147483647
+#endif
+
+#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */
+#define  X_ALIGN 4
+#else
+#undef X_ALIGN
+#endif
+
+/*
+ * Define the following for debugging.
+ */
+/* #define ALWAYS_NC_SHARE 1 */
+
+/* Begin OS */
+
+static int ncio_px_sync(ncio *const nciop);
+
+#ifndef POSIXIO_DEFAULT_PAGESIZE
+#define POSIXIO_DEFAULT_PAGESIZE 4096
+#endif
+/*
+ * What is the system pagesize?
+ */
+static size_t
+pagesize(void)
+{
+/* Hmm, aren't standards great? */
+#if defined(_SC_PAGE_SIZE) && !defined(_SC_PAGESIZE)
+#define _SC_PAGESIZE _SC_PAGE_SIZE
+#endif
+
+#ifdef _SC_PAGESIZE
+	{
+		const long pgsz = sysconf(_SC_PAGESIZE);
+		if(pgsz > 0)
+			return (size_t) pgsz;
+		/* else, silent in the face of error */
+	}
+#elif defined(HAVE_GETPAGESIZE)
+	return (size_t) getpagesize();
+#endif
+	return (size_t) POSIXIO_DEFAULT_PAGESIZE;
+}
+
+/*
+ * What is the preferred I/O block size?
+ */
+static size_t
+blksize(int fd)
+{
+#if defined(HAVE_ST_BLKSIZE)
+	struct stat sb;
+	if (fstat(fd, &sb) > -1)
+	{
+		if(sb.st_blksize >= 8192)
+			return (size_t) sb.st_blksize;
+		return 8192;
+	}
+	/* else, silent in the face of error */
+#endif
+	return (size_t) 2 * pagesize();
+}
+
+
+/*
+ * Sortof like ftruncate, except won't make the
+ * file shorter.
+ */
+static int
+fgrow(const int fd, const off_t len)
+{
+	struct stat sb;
+	if (fstat(fd, &sb) < 0)
+		return errno;
+	if (len < sb.st_size)
+		return ENOERR;
+#if defined(HAVE_FTRUNCATE)
+	if (ftruncate(fd, len) < 0)
+		return errno;
+#else
+	{
+		const long dumb = 0;
+			/* cache current position */
+		const off_t pos = lseek(fd, 0, SEEK_CUR);
+		if(pos < 0)
+			return errno;
+		if (lseek(fd, len-sizeof(dumb), SEEK_SET) < 0)
+			return errno;
+		if(write(fd, &dumb, sizeof(dumb)) < 0)
+			return errno;
+		if (lseek(fd, pos, SEEK_SET) < 0)
+			return errno;
+	}
+#endif /* HAVE_FTRUNCATE */
+	/* else */
+	return ENOERR;
+}
+
+/* End OS */
+/* Begin px */
+
+static int
+px_pgout(ncio *const nciop, 
+	off_t const offset,  const size_t extent,
+	void *const vp, off_t *posp)
+{
+#ifdef X_ALIGN
+	assert(offset % X_ALIGN == 0);
+#endif
+
+	assert(*posp == OFF_NONE || *posp == lseek(nciop->fd, 0, SEEK_CUR));
+
+	if(*posp != offset)
+	{
+		if(lseek(nciop->fd, offset, SEEK_SET) != offset)
+		{
+			return errno;
+		}
+		*posp = offset;
+	}
+	if(write(nciop->fd, vp, extent) != (ssize_t) extent)
+	{
+		return errno;
+	}
+	*posp += extent;
+
+	return ENOERR;
+}
+
+
+static int
+px_pgin(ncio *const nciop,
+	off_t const offset, const size_t extent,
+	void *const vp, size_t *nreadp, off_t *posp)
+{
+	int status;
+	ssize_t nread;
+
+#ifdef X_ALIGN
+	assert(offset % X_ALIGN == 0);
+	assert(extent % X_ALIGN == 0);
+#endif
+
+	assert(*posp == OFF_NONE || *posp == lseek(nciop->fd, 0, SEEK_CUR));
+
+	if(*posp != offset)
+	{
+		if(lseek(nciop->fd, offset, SEEK_SET) != offset)
+		{
+			status = errno;
+			return status;
+		}
+		*posp = offset;
+	}
+
+	errno = 0;
+	nread = read(nciop->fd, vp, extent);
+	if(nread != (ssize_t) extent)
+	{
+		status = errno;
+		if(nread == -1 || status != ENOERR)
+			return status;
+		/* else it's okay we read less than asked for */
+		(void) memset((char *)vp + nread, 0, (ssize_t)extent - nread);
+	}
+	*nreadp = nread;
+	*posp += nread;
+
+	return ENOERR;
+}
+
+
+typedef struct ncio_px {
+	size_t blksz;
+	off_t pos;
+	/* buffer */
+	off_t	bf_offset; 
+	size_t	bf_extent;
+	size_t	bf_cnt;
+	void	*bf_base;
+	int	bf_rflags;
+	int	bf_refcount;
+	/* chain for double buffering in px_move */
+	struct ncio_px *slave;
+} ncio_px;
+
+
+/*ARGSUSED*/
+static int
+px_rel(ncio_px *const pxp, off_t offset, int rflags)
+{
+	assert(pxp->bf_offset <= offset
+		 && offset < pxp->bf_offset + (off_t) pxp->bf_extent);
+	assert(pIf(fIsSet(rflags, RGN_MODIFIED),
+		fIsSet(pxp->bf_rflags, RGN_WRITE)));
+
+	if(fIsSet(rflags, RGN_MODIFIED))
+	{
+		fSet(pxp->bf_rflags, RGN_MODIFIED);
+	}
+	pxp->bf_refcount--;
+
+	return ENOERR;
+}
+
+static int
+ncio_px_rel(ncio *const nciop, off_t offset, int rflags)
+{
+	ncio_px *const pxp = (ncio_px *)nciop->pvt;
+
+	if(fIsSet(rflags, RGN_MODIFIED) && !fIsSet(nciop->ioflags, NC_WRITE))
+		return EPERM; /* attempt to write readonly file */
+
+	return px_rel(pxp, offset, rflags);
+}
+
+static int
+px_get(ncio *const nciop, ncio_px *const pxp,
+		off_t offset, size_t extent,
+		int rflags,
+		void **const vpp)
+{
+	int status = ENOERR;
+
+	const off_t blkoffset = _RNDDOWN(offset, (off_t)pxp->blksz);
+	size_t diff = (size_t)(offset - blkoffset);
+	size_t blkextent = _RNDUP(diff + extent, pxp->blksz);
+	
+	assert(extent != 0);
+	assert(extent < X_INT_MAX); /* sanity check */
+	assert(offset >= 0); /* sanity check */
+	assert(offset < X_INT_MAX); /* sanity check */
+
+	if(2 * pxp->blksz < blkextent)
+		return E2BIG; /* TODO: temporary kludge */
+	if(pxp->bf_offset == OFF_NONE)
+	{
+		/* Uninitialized */
+		if(pxp->bf_base == NULL)
+		{
+			assert(pxp->bf_extent == 0);
+			assert(blkextent <= 2 * pxp->blksz);
+			pxp->bf_base = malloc(2 * pxp->blksz);
+			if(pxp->bf_base == NULL)
+				return ENOMEM;
+		}
+		goto pgin;
+	}
+	/* else */
+	assert(blkextent <= 2 * pxp->blksz);
+
+	if(blkoffset == pxp->bf_offset)
+	{
+		/* hit */
+ 		if(blkextent > pxp->bf_extent) 
+		{
+			/* page in upper */
+			void *const middle =
+			 	(void *)((char *)pxp->bf_base + pxp->blksz);
+			assert(pxp->bf_extent == pxp->blksz);
+			status = px_pgin(nciop,
+				 pxp->bf_offset + (off_t)pxp->blksz,
+				 pxp->blksz,
+				 middle,
+				 &pxp->bf_cnt,
+				 &pxp->pos);
+			if(status != ENOERR)
+				return status;
+			pxp->bf_extent = 2 * pxp->blksz;
+			pxp->bf_cnt += pxp->blksz;
+		}
+		goto done;
+	}
+	/* else */
+
+	if(pxp->bf_extent > pxp->blksz
+		 && blkoffset == pxp->bf_offset + pxp->blksz)
+	{
+		/* hit in upper half */
+		if(blkextent == pxp->blksz)
+		{
+			/* all in upper half, no fault needed */
+			diff += pxp->blksz;
+			goto done;
+		}
+		/* else */
+		if(pxp->bf_cnt > pxp->blksz)
+		{
+			/* data in upper half */
+			void *const middle =
+				(void *)((char *)pxp->bf_base + pxp->blksz);
+			assert(pxp->bf_extent == 2 * pxp->blksz);
+			if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
+			{
+				/* page out lower half */
+				assert(pxp->bf_refcount <= 0);
+				status = px_pgout(nciop,
+					pxp->bf_offset,
+					pxp->blksz,
+					pxp->bf_base,
+					&pxp->pos);
+				if(status != ENOERR)
+					return status;
+			}
+			pxp->bf_cnt -= pxp->blksz;
+			/* copy upper half into lower half */
+			(void) memcpy(pxp->bf_base, middle, pxp->bf_cnt);
+		}
+		pxp->bf_offset = blkoffset;
+		/* pxp->bf_extent = pxp->blksz; */
+
+ 		assert(blkextent == 2 * pxp->blksz);
+		{
+			/* page in upper */
+			void *const middle =
+			 	(void *)((char *)pxp->bf_base + pxp->blksz);
+			status = px_pgin(nciop,
+				 pxp->bf_offset + (off_t)pxp->blksz,
+				 pxp->blksz,
+				 middle,
+				 &pxp->bf_cnt,
+				 &pxp->pos);
+			if(status != ENOERR)
+				return status;
+			pxp->bf_extent = 2 * pxp->blksz;
+			pxp->bf_cnt += pxp->blksz;
+		}
+		goto done;
+	}
+	/* else */
+
+	if(blkoffset == pxp->bf_offset - pxp->blksz)
+	{
+		/* wants the page below */
+		void *const middle =
+			(void *)((char *)pxp->bf_base + pxp->blksz);
+		size_t upper_cnt = 0;
+		if(pxp->bf_cnt > pxp->blksz)
+		{
+			/* data in upper half */
+			assert(pxp->bf_extent == 2 * pxp->blksz);
+			if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
+			{
+				/* page out upper half */
+				assert(pxp->bf_refcount <= 0);
+				status = px_pgout(nciop,
+					pxp->bf_offset + (off_t)pxp->blksz,
+					pxp->bf_cnt - pxp->blksz,
+					middle,
+					&pxp->pos);
+				if(status != ENOERR)
+					return status;
+			}
+			pxp->bf_cnt = pxp->blksz;
+			pxp->bf_extent = pxp->blksz;
+		}
+		if(pxp->bf_cnt > 0)
+		{
+			/* copy lower half into upper half */
+			(void) memcpy(middle, pxp->bf_base, pxp->blksz);
+			upper_cnt = pxp->bf_cnt;
+		}
+		/* read page below into lower half */
+		status = px_pgin(nciop,
+			 blkoffset,
+			 pxp->blksz,
+			 pxp->bf_base,
+			 &pxp->bf_cnt,
+			 &pxp->pos);
+		if(status != ENOERR)
+			return status;
+		pxp->bf_offset = blkoffset;
+		if(upper_cnt != 0)
+		{
+			pxp->bf_extent = 2 * pxp->blksz;
+			pxp->bf_cnt = pxp->blksz + upper_cnt;
+		}
+		else
+		{
+			pxp->bf_extent = pxp->blksz;
+		}
+		goto done;
+	}
+	/* else */
+
+	/* no overlap */
+	if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
+	{
+		assert(pxp->bf_refcount <= 0);
+		status = px_pgout(nciop,
+			pxp->bf_offset,
+			pxp->bf_cnt,
+			pxp->bf_base,
+			&pxp->pos);
+		if(status != ENOERR)
+			return status;
+		pxp->bf_rflags = 0;
+	}
+
+pgin:
+	status = px_pgin(nciop,
+		 blkoffset,
+		 blkextent,
+		 pxp->bf_base,
+		 &pxp->bf_cnt,
+		 &pxp->pos);
+	if(status != ENOERR)
+		return status;
+	 pxp->bf_offset = blkoffset;
+	 pxp->bf_extent = blkextent;
+
+done:
+	extent += diff;
+	if(pxp->bf_cnt < extent)
+		pxp->bf_cnt = extent;
+	assert(pxp->bf_cnt <= pxp->bf_extent);
+
+	pxp->bf_rflags |= rflags;
+	pxp->bf_refcount++;
+
+	*vpp = (char *)pxp->bf_base + diff;
+	return ENOERR;
+}
+
+static int
+ncio_px_get(ncio *const nciop, 
+		off_t offset, size_t extent,
+		int rflags,
+		void **const vpp)	/* NULL => force read */
+{
+	ncio_px *const pxp = (ncio_px *)nciop->pvt;
+	
+	if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))
+		return EPERM; /* attempt to write readonly file */
+
+	/*
+         * If the base of the stream buffer is NULL, then a read is forced
+         * for synchronization purposes (see fault_v1hs() in v1hpg.c).  The
+         * implementation is based on ncio_spx_rel() in this file.
+	 */
+	if (*vpp == NULL)
+	{
+	    ncio_px_sync(nciop);
+	    pxp->bf_offset = OFF_NONE;
+	    pxp->bf_cnt = 0;
+	}
+
+	/* reclaim space used in move */
+	if(pxp->slave != NULL)
+	{
+		if(pxp->slave->bf_base != NULL)
+		{
+			free(pxp->slave->bf_base);
+			pxp->slave->bf_base = NULL;
+			pxp->slave->bf_extent = 0;
+			pxp->slave->bf_offset = OFF_NONE;
+		}
+		free(pxp->slave);
+		pxp->slave = NULL;
+	}
+	return px_get(nciop, pxp, offset, extent, rflags, vpp);
+}
+
+
+/* ARGSUSED */
+static int
+px_double_buffer(ncio *const nciop, off_t to, off_t from,
+			size_t nbytes, int rflags)
+{
+	ncio_px *const pxp = (ncio_px *)nciop->pvt;
+	int status = ENOERR;
+	void *src;
+	void *dest;
+	
+#if INSTRUMENT
+fprintf(stderr, "\tdouble_buffr %ld %ld %ld\n",
+		 (long)to, (long)from, (long)nbytes);
+#endif
+	status = px_get(nciop, pxp, to, nbytes, RGN_WRITE,
+			&dest);
+	if(status != ENOERR)
+		return status;
+
+	if(pxp->slave == NULL)
+	{
+		pxp->slave = (ncio_px *) malloc(sizeof(ncio_px));
+		if(pxp->slave == NULL)
+			return ENOMEM;
+
+		pxp->slave->blksz = pxp->blksz;
+		/* pos done below */
+		pxp->slave->bf_offset = pxp->bf_offset; 
+		pxp->slave->bf_extent = pxp->bf_extent;
+		pxp->slave->bf_cnt = pxp->bf_cnt;
+		pxp->slave->bf_base = malloc(2 * pxp->blksz);
+		if(pxp->slave->bf_base == NULL)
+			return ENOMEM;
+		(void) memcpy(pxp->slave->bf_base, pxp->bf_base,
+			 pxp->bf_extent);
+		pxp->slave->bf_rflags = 0;
+		pxp->slave->bf_refcount = 0;
+		pxp->slave->slave = NULL;
+	}
+	
+	pxp->slave->pos = pxp->pos;
+	status = px_get(nciop, pxp->slave, from, nbytes, 0,
+			&src);
+	if(status != ENOERR)
+		return status;
+	if(pxp->pos != pxp->slave->pos)
+	{
+		/* position changed, sync */
+		pxp->pos = pxp->slave->pos;
+	}
+
+	(void) memcpy(dest, src, nbytes);
+
+	(void)px_rel(pxp->slave, from, 0);
+	(void)px_rel(pxp, to, RGN_MODIFIED);
+	
+	return status;
+}
+
+static int
+ncio_px_move(ncio *const nciop, off_t to, off_t from,
+			size_t nbytes, int rflags)
+{
+	ncio_px *const pxp = (ncio_px *)nciop->pvt;
+	int status = ENOERR;
+	off_t lower;	
+	off_t upper;
+	char *base;
+	size_t diff;
+	size_t extent;
+
+	if(to == from)
+		return ENOERR; /* NOOP */
+	
+	if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))
+		return EPERM; /* attempt to write readonly file */
+
+	rflags &= RGN_NOLOCK; /* filter unwanted flags */
+
+	if(to > from)
+	{
+		/* growing */
+		lower = from;	
+		upper = to;
+	}
+	else
+	{
+		/* shrinking */
+		lower = to;
+		upper = from;
+	}
+	diff = (size_t)(upper - lower);
+	extent = diff + nbytes;
+
+#if INSTRUMENT
+fprintf(stderr, "ncio_px_move %ld %ld %ld %ld %ld\n",
+		 (long)to, (long)from, (long)nbytes, (long)lower, (long)extent);
+#endif
+	if(extent > pxp->blksz)
+	{
+		size_t remaining = nbytes;
+
+if(to > from)
+{
+		off_t frm = from + nbytes;
+		off_t toh = to + nbytes;
+		for(;;)
+		{
+			size_t loopextent = MIN(remaining, pxp->blksz);
+			frm -= loopextent;
+			toh -= loopextent;
+
+			status = px_double_buffer(nciop, toh, frm,
+				 	loopextent, rflags) ;
+			if(status != ENOERR)
+				return status;
+			remaining -= loopextent;
+
+			if(remaining == 0)
+				break; /* normal loop exit */
+		}
+}
+else
+{
+		for(;;)
+		{
+			size_t loopextent = MIN(remaining, pxp->blksz);
+
+			status = px_double_buffer(nciop, to, from,
+				 	loopextent, rflags) ;
+			if(status != ENOERR)
+				return status;
+			remaining -= loopextent;
+
+			if(remaining == 0)
+				break; /* normal loop exit */
+			to += loopextent;
+			from += loopextent;
+		}
+}
+		return ENOERR;
+	}
+	
+#if INSTRUMENT
+fprintf(stderr, "\tncio_px_move small\n");
+#endif
+	status = px_get(nciop, pxp, lower, extent, RGN_WRITE|rflags,
+			(void **)&base);
+
+	if(status != ENOERR)
+		return status;
+
+	if(to > from)
+		(void) memmove(base + diff, base, nbytes); 
+	else
+		(void) memmove(base, base + diff, nbytes); 
+		
+	(void) px_rel(pxp, lower, RGN_MODIFIED);
+
+	return status;
+}
+
+
+static int
+ncio_px_sync(ncio *const nciop)
+{
+	ncio_px *const pxp = (ncio_px *)nciop->pvt;
+	int status = ENOERR;
+	if(fIsSet(pxp->bf_rflags, RGN_MODIFIED))
+	{
+		assert(pxp->bf_refcount <= 0);
+		status = px_pgout(nciop, pxp->bf_offset,
+			pxp->bf_cnt,
+			pxp->bf_base, &pxp->pos);
+		if(status != ENOERR)
+			return status;
+		pxp->bf_rflags = 0;
+	}
+	return status;
+}
+
+static void
+ncio_px_free(void *const pvt)
+{
+	ncio_px *const pxp = (ncio_px *)pvt;
+	if(pxp == NULL)
+		return;
+
+	if(pxp->slave != NULL)
+	{
+		if(pxp->slave->bf_base != NULL)
+		{
+			free(pxp->slave->bf_base);
+			pxp->slave->bf_base = NULL;
+			pxp->slave->bf_extent = 0;
+			pxp->slave->bf_offset = OFF_NONE;
+		}
+		free(pxp->slave);
+		pxp->slave = NULL;
+	}
+		
+	if(pxp->bf_base != NULL)
+	{
+		free(pxp->bf_base);
+		pxp->bf_base = NULL;
+		pxp->bf_extent = 0;
+		pxp->bf_offset = OFF_NONE;
+	}
+}
+
+
+static int
+ncio_px_init2(ncio *const nciop, size_t *sizehintp, int isNew)
+{
+	ncio_px *const pxp = (ncio_px *)nciop->pvt;
+	const size_t bufsz = 2 * *sizehintp;
+
+	assert(nciop->fd >= 0);
+
+	pxp->blksz = *sizehintp;
+
+	assert(pxp->bf_base == NULL);
+
+	/* this is separate allocation because it may grow */
+	pxp->bf_base = malloc(bufsz);
+	if(pxp->bf_base == NULL)
+		return ENOMEM;
+	/* else */
+	pxp->bf_cnt = 0;
+	if(isNew)
+	{
+		/* save a read */
+		pxp->pos = 0;
+		pxp->bf_offset = 0;
+		pxp->bf_extent = bufsz;
+		(void) memset(pxp->bf_base, 0, pxp->bf_extent);
+	}
+	return ENOERR;
+}
+
+
+static void
+ncio_px_init(ncio *const nciop)
+{
+	ncio_px *const pxp = (ncio_px *)nciop->pvt;
+
+	*((ncio_relfunc **)&nciop->rel) = ncio_px_rel; /* cast away const */
+	*((ncio_getfunc **)&nciop->get) = ncio_px_get; /* cast away const */
+	*((ncio_movefunc **)&nciop->move) = ncio_px_move; /* cast away const */
+	*((ncio_syncfunc **)&nciop->sync) = ncio_px_sync; /* cast away const */
+	*((ncio_freefunc **)&nciop->free) = ncio_px_free; /* cast away const */
+
+	pxp->blksz = 0;
+	pxp->pos = -1;
+	pxp->bf_offset = OFF_NONE;
+	pxp->bf_extent = 0;
+	pxp->bf_rflags = 0;
+	pxp->bf_refcount = 0;
+	pxp->bf_base = NULL;
+	pxp->slave = NULL;
+
+}
+
+/* Begin spx */
+
+typedef struct ncio_spx {
+	off_t pos;
+	/* buffer */
+	off_t	bf_offset; 
+	size_t	bf_extent;
+	size_t	bf_cnt;
+	void	*bf_base;
+} ncio_spx;
+
+
+/*ARGSUSED*/
+static int
+ncio_spx_rel(ncio *const nciop, off_t offset, int rflags)
+{
+	ncio_spx *const pxp = (ncio_spx *)nciop->pvt;
+	int status = ENOERR;
+
+	assert(pxp->bf_offset <= offset);
+	assert(pxp->bf_cnt != 0);
+	assert(pxp->bf_cnt <= pxp->bf_extent);
+#ifdef X_ALIGN
+	assert(offset < pxp->bf_offset + X_ALIGN);
+	assert(pxp->bf_cnt % X_ALIGN == 0 );
+#endif
+
+	if(fIsSet(rflags, RGN_MODIFIED))
+	{
+		if(!fIsSet(nciop->ioflags, NC_WRITE))
+			return EPERM; /* attempt to write readonly file */
+
+		status = px_pgout(nciop, pxp->bf_offset,
+			pxp->bf_cnt,
+			pxp->bf_base, &pxp->pos);
+		/* if error, invalidate buffer anyway */
+	}
+	pxp->bf_offset = OFF_NONE;
+	pxp->bf_cnt = 0;
+	return status;
+}
+
+
+static int
+ncio_spx_get(ncio *const nciop,
+		off_t offset, size_t extent,
+		int rflags,
+		void **const vpp)
+{
+	ncio_spx *const pxp = (ncio_spx *)nciop->pvt;
+	int status = ENOERR;
+#ifdef X_ALIGN
+	size_t rem;
+#endif
+	
+	if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))
+		return EPERM; /* attempt to write readonly file */
+
+	assert(extent != 0);
+	assert(extent < X_INT_MAX); /* sanity check */
+	assert(offset < X_INT_MAX); /* sanity check */
+
+	assert(pxp->bf_cnt == 0);
+
+#ifdef X_ALIGN
+	rem = (size_t)(offset % X_ALIGN);
+	if(rem != 0)
+	{
+		offset -= rem;
+		extent += rem;
+	}
+
+	{
+		const size_t rndup = extent % X_ALIGN;
+		if(rndup != 0)
+			extent += X_ALIGN - rndup;
+	}
+
+	assert(offset % X_ALIGN == 0);
+	assert(extent % X_ALIGN == 0);
+#endif
+
+	if(pxp->bf_extent < extent)
+	{
+		if(pxp->bf_base != NULL)
+		{
+			free(pxp->bf_base);
+			pxp->bf_base = NULL;
+			pxp->bf_extent = 0;
+		}
+		assert(pxp->bf_extent == 0);
+		pxp->bf_base = malloc(extent);
+		if(pxp->bf_base == NULL)
+			return ENOMEM;
+		pxp->bf_extent = extent;
+	}
+
+	status = px_pgin(nciop, offset,
+		 extent,
+		 pxp->bf_base,
+		 &pxp->bf_cnt, &pxp->pos);
+	if(status != ENOERR)
+		return status;
+
+	pxp->bf_offset = offset;
+
+	if(pxp->bf_cnt < extent)
+		pxp->bf_cnt = extent;
+
+#ifdef X_ALIGN
+	*vpp = (char *)pxp->bf_base + rem;
+#else
+	*vpp = pxp->bf_base;
+#endif
+	return ENOERR;
+}
+
+
+#if 0
+/*ARGSUSED*/
+static int
+strategy(ncio *const nciop, off_t to, off_t offset,
+			size_t extent, int rflags)
+{
+	static ncio_spx pxp[1];
+	int status = ENOERR;
+#ifdef X_ALIGN
+	size_t rem;
+#endif
+	
+	assert(extent != 0);
+	assert(extent < X_INT_MAX); /* sanity check */
+	assert(offset < X_INT_MAX); /* sanity check */
+#if INSTRUMENT
+fprintf(stderr, "strategy %ld at %ld to %ld\n",
+	 (long)extent, (long)offset, (long)to);
+#endif
+
+
+#ifdef X_ALIGN
+	rem = (size_t)(offset % X_ALIGN);
+	if(rem != 0)
+	{
+		offset -= rem;
+		extent += rem;
+	}
+
+	{
+		const size_t rndup = extent % X_ALIGN;
+		if(rndup != 0)
+			extent += X_ALIGN - rndup;
+	}
+
+	assert(offset % X_ALIGN == 0);
+	assert(extent % X_ALIGN == 0);
+#endif
+
+	if(pxp->bf_extent < extent)
+	{
+		if(pxp->bf_base != NULL)
+		{
+			free(pxp->bf_base);
+			pxp->bf_base = NULL;
+			pxp->bf_extent = 0;
+		}
+		assert(pxp->bf_extent == 0);
+		pxp->bf_base = malloc(extent);
+		if(pxp->bf_base == NULL)
+			return ENOMEM;
+		pxp->bf_extent = extent;
+	}
+
+	status = px_pgin(nciop, offset,
+		 extent,
+		 pxp->bf_base,
+		 &pxp->bf_cnt, &pxp->pos);
+	if(status != ENOERR)
+		return status;
+
+	pxp->bf_offset = to; /* TODO: XALIGN */
+	
+	if(pxp->bf_cnt < extent)
+		pxp->bf_cnt = extent;
+
+	status = px_pgout(nciop, pxp->bf_offset,
+		pxp->bf_cnt,
+		pxp->bf_base, &pxp->pos);
+	/* if error, invalidate buffer anyway */
+	pxp->bf_offset = OFF_NONE;
+	pxp->bf_cnt = 0;
+	return status;
+}
+#endif
+
+static int
+ncio_spx_move(ncio *const nciop, off_t to, off_t from,
+			size_t nbytes, int rflags)
+{
+	int status = ENOERR;
+	off_t lower = from;	
+	off_t upper = to;
+	char *base;
+	size_t diff = (size_t)(upper - lower);
+	size_t extent = diff + nbytes;
+
+	rflags &= RGN_NOLOCK; /* filter unwanted flags */
+
+	if(to == from)
+		return ENOERR; /* NOOP */
+	
+	if(to > from)
+	{
+		/* growing */
+		lower = from;	
+		upper = to;
+	}
+	else
+	{
+		/* shrinking */
+		lower = to;
+		upper = from;
+	}
+
+	diff = (size_t)(upper - lower);
+	extent = diff + nbytes;
+
+	status = ncio_spx_get(nciop, lower, extent, RGN_WRITE|rflags,
+			(void **)&base);
+
+	if(status != ENOERR)
+		return status;
+
+	if(to > from)
+		(void) memmove(base + diff, base, nbytes); 
+	else
+		(void) memmove(base, base + diff, nbytes); 
+		
+	(void) ncio_spx_rel(nciop, lower, RGN_MODIFIED);
+
+	return status;
+}
+
+
+/*ARGSUSED*/
+static int
+ncio_spx_sync(ncio *const nciop)
+{
+	/* NOOP */
+	return ENOERR;
+}
+
+static void
+ncio_spx_free(void *const pvt)
+{
+	ncio_spx *const pxp = (ncio_spx *)pvt;
+	if(pxp == NULL)
+		return;
+
+	if(pxp->bf_base != NULL)
+	{
+		free(pxp->bf_base);
+		pxp->bf_base = NULL;
+		pxp->bf_offset = OFF_NONE;
+		pxp->bf_extent = 0;
+		pxp->bf_cnt = 0;
+	}
+}
+
+
+static int
+ncio_spx_init2(ncio *const nciop, const size_t *const sizehintp)
+{
+	ncio_spx *const pxp = (ncio_spx *)nciop->pvt;
+
+	assert(nciop->fd >= 0);
+
+	pxp->bf_extent = *sizehintp;
+
+	assert(pxp->bf_base == NULL);
+
+	/* this is separate allocation because it may grow */
+	pxp->bf_base = malloc(pxp->bf_extent);
+	if(pxp->bf_base == NULL)
+	{
+		pxp->bf_extent = 0;
+		return ENOMEM;
+	}
+	/* else */
+	return ENOERR;
+}
+
+
+static void
+ncio_spx_init(ncio *const nciop)
+{
+	ncio_spx *const pxp = (ncio_spx *)nciop->pvt;
+
+	*((ncio_relfunc **)&nciop->rel) = ncio_spx_rel; /* cast away const */
+	*((ncio_getfunc **)&nciop->get) = ncio_spx_get; /* cast away const */
+	*((ncio_movefunc **)&nciop->move) = ncio_spx_move; /* cast away const */
+	*((ncio_syncfunc **)&nciop->sync) = ncio_spx_sync; /* cast away const */
+	*((ncio_freefunc **)&nciop->free) = ncio_spx_free; /* cast away const */
+
+	pxp->pos = -1;
+	pxp->bf_offset = OFF_NONE;
+	pxp->bf_extent = 0;
+	pxp->bf_cnt = 0;
+	pxp->bf_base = NULL;
+}
+
+
+/* */
+
+static void
+ncio_free(ncio *nciop)
+{
+	if(nciop == NULL)
+		return;
+
+	if(nciop->free != NULL)
+		nciop->free(nciop->pvt);
+	
+	free(nciop);
+}
+
+
+static ncio *
+ncio_new(const char *path, int ioflags)
+{
+	size_t sz_ncio = M_RNDUP(sizeof(ncio));
+	size_t sz_path = M_RNDUP(strlen(path) +1);
+	size_t sz_ncio_pvt;
+	ncio *nciop;
+ 
+#if ALWAYS_NC_SHARE /* DEBUG */
+	fSet(ioflags, NC_SHARE);
+#endif
+
+	if(fIsSet(ioflags, NC_SHARE))
+		sz_ncio_pvt = sizeof(ncio_spx);
+	else
+		sz_ncio_pvt = sizeof(ncio_px);
+
+	nciop = (ncio *) malloc(sz_ncio + sz_path + sz_ncio_pvt);
+	if(nciop == NULL)
+		return NULL;
+	
+	nciop->ioflags = ioflags;
+	*((int *)&nciop->fd) = -1; /* cast away const */
+
+	nciop->path = (char *) ((char *)nciop + sz_ncio);
+	(void) strcpy((char *)nciop->path, path); /* cast away const */
+
+				/* cast away const */
+	*((void **)&nciop->pvt) = (void *)(nciop->path + sz_path);
+
+	if(fIsSet(ioflags, NC_SHARE))
+		ncio_spx_init(nciop);
+	else
+		ncio_px_init(nciop);
+
+	return nciop;
+}
+
+
+/* Public below this point */
+
+#define NCIO_MINBLOCKSIZE 256
+#define NCIO_MAXBLOCKSIZE 268435456 /* sanity check, about X_SIZE_T_MAX/8 */
+
+#ifdef S_IRUSR
+#define NC_DEFAULT_CREAT_MODE \
+        (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) /* 0666 */
+
+#else
+#define NC_DEFAULT_CREAT_MODE 0666
+#endif
+
+int
+ncio_create(const char *path, int ioflags,
+	size_t initialsz,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp)
+{
+	ncio *nciop;
+	int oflags = (O_RDWR|O_CREAT);
+	int fd;
+	int status;
+
+	if(initialsz < (size_t)igeto + igetsz)
+		initialsz = (size_t)igeto + igetsz;
+
+	fSet(ioflags, NC_WRITE);
+
+	if(path == NULL || *path == 0)
+		return EINVAL;
+
+	nciop = ncio_new(path, ioflags);
+	if(nciop == NULL)
+		return ENOMEM;
+
+	if(fIsSet(ioflags, NC_NOCLOBBER))
+		fSet(oflags, O_EXCL);
+	else
+		fSet(oflags, O_TRUNC);
+#ifdef O_BINARY
+	fSet(oflags, O_BINARY);
+#endif
+#ifdef vms
+	fd = open(path, oflags, NC_DEFAULT_CREAT_MODE, "ctx=stm");
+#else
+	/* Should we mess with the mode based on NC_SHARE ?? */
+	fd = open(path, oflags, NC_DEFAULT_CREAT_MODE);
+#endif
+#if 0
+	(void) fprintf(stderr, "ncio_create(): path=\"%s\"\n", path);
+	(void) fprintf(stderr, "ncio_create(): oflags=0x%x\n", oflags);
+#endif
+	if(fd < 0)
+	{
+		status = errno;
+		goto unwind_new;
+	}
+	*((int *)&nciop->fd) = fd; /* cast away const */
+
+	if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE)
+	{
+		/* Use default */
+		*sizehintp = blksize(fd);
+	}
+	else
+	{
+		*sizehintp = M_RNDUP(*sizehintp);
+	}
+
+	if(fIsSet(nciop->ioflags, NC_SHARE))
+		status = ncio_spx_init2(nciop, sizehintp);
+	else
+		status = ncio_px_init2(nciop, sizehintp, 1);
+
+	if(status != ENOERR)
+		goto unwind_open;
+
+	if(initialsz != 0)
+	{
+		status = fgrow(fd, (off_t)initialsz);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	if(igetsz != 0)
+	{
+		status = nciop->get(nciop,
+				igeto, igetsz,
+                        	RGN_WRITE,
+                        	igetvpp);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	*nciopp = nciop;
+	return ENOERR;
+
+unwind_open:
+	(void) close(fd);
+	/* ?? unlink */
+	/*FALLTHRU*/
+unwind_new:
+	ncio_free(nciop);
+	return status;
+}
+
+
+int
+ncio_open(const char *path,
+	int ioflags,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp)
+{
+	ncio *nciop;
+	int oflags = fIsSet(ioflags, NC_WRITE) ? O_RDWR : O_RDONLY;
+	int fd;
+	int status;
+
+	if(path == NULL || *path == 0)
+		return EINVAL;
+
+	nciop = ncio_new(path, ioflags);
+	if(nciop == NULL)
+		return ENOMEM;
+
+#ifdef O_BINARY
+	fSet(oflags, O_BINARY);
+#endif
+#ifdef vms
+	fd = open(path, oflags, 0, "ctx=stm");
+#else
+	fd = open(path, oflags, 0);
+#endif
+	if(fd < 0)
+	{
+		status = errno;
+		goto unwind_new;
+	}
+	*((int *)&nciop->fd) = fd; /* cast away const */
+
+	if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE)
+	{
+		/* Use default */
+		*sizehintp = blksize(fd);
+	}
+	else
+	{
+		*sizehintp = M_RNDUP(*sizehintp);
+	}
+
+	if(fIsSet(nciop->ioflags, NC_SHARE))
+		status = ncio_spx_init2(nciop, sizehintp);
+	else
+		status = ncio_px_init2(nciop, sizehintp, 0);
+
+	if(status != ENOERR)
+		goto unwind_open;
+
+	if(igetsz != 0)
+	{
+		status = nciop->get(nciop,
+				igeto, igetsz,
+                        	0,
+                        	igetvpp);
+		if(status != ENOERR)
+			goto unwind_open;
+	}
+
+	*nciopp = nciop;
+	return ENOERR;
+
+unwind_open:
+	(void) close(fd);
+	/*FALLTHRU*/
+unwind_new:
+	ncio_free(nciop);
+	return status;
+}
+
+
+int 
+ncio_close(ncio *nciop, int doUnlink)
+{
+	int status = ENOERR;
+
+	if(nciop == NULL)
+		return EINVAL;
+
+	status = nciop->sync(nciop);
+
+	(void) close(nciop->fd);
+	
+	if(doUnlink)
+		(void) unlink(nciop->path);
+
+	ncio_free(nciop);
+
+	return status;
+}
Index: /branches/SDM_SciDAC/src/lib/ncconfig.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/ncconfig.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/ncconfig.h (revision 2)
@@ -0,0 +1,82 @@
+/* src/lib/ncconfig.h.  Generated automatically by configure.  */
+/* libsrc/ncconfig.in.  Generated automatically from configure.in by autoheader.  */
+/* $Id$ */
+#ifndef _NCCONFIG_H_
+#define _NCCONFIG_H_
+
+/* Define if you're on an HP-UX system. */
+/* #undef _HPUX_SOURCE */
+
+/* Define if type char is unsigned and you are not using gcc.  */
+#ifndef __CHAR_UNSIGNED__
+/* #undef __CHAR_UNSIGNED__ */
+#endif
+
+/* Define if your struct stat has st_blksize.  */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define to `long' if <sys/types.h> doesn't define.  */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define.  */
+/* #undef size_t */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define if you don't have the <stdlib.h>.  */
+/* #undef NO_STDLIB_H */
+
+/* Define if you don't have the <sys/types.h>.  */
+/* #undef NO_SYS_TYPES_H */
+
+/* Define if you have the ftruncate function  */
+#define HAVE_FTRUNCATE 1
+
+/* Define if you have alloca, as a function or macro.  */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix).  */
+#define HAVE_ALLOCA_H 1
+
+/* Define if you don't have the strerror function  */
+/* #undef NO_STRERROR */
+
+/* The number of bytes in a size_t */
+#define SIZEOF_SIZE_T 4
+
+/* The number of bytes in a off_t */
+#define SIZEOF_OFF_T 8
+
+/* Define to `int' if system doesn't define.  */
+/* #undef ssize_t */
+
+/* Define to `int' if system doesn't define.  */
+/* #undef ptrdiff_t */
+
+/* Define to `unsigned char' if system doesn't define.  */
+#define uchar unsigned char
+
+/* Define if the system does not use IEEE floating point representation */
+/* #undef NO_IEEE_FLOAT */
+
+/* The number of bytes in a double.  */
+#define SIZEOF_DOUBLE 8
+
+/* The number of bytes in a float.  */
+#define SIZEOF_FLOAT 4
+
+/* The number of bytes in a int.  */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long.  */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a short.  */
+#define SIZEOF_SHORT 2
+
+#endif /* !_NCCONFIG_H_ */
Index: /branches/SDM_SciDAC/src/lib/Makefile
===================================================================
--- /branches/SDM_SciDAC/src/lib/Makefile (revision 2)
+++ /branches/SDM_SciDAC/src/lib/Makefile (revision 2)
@@ -0,0 +1,109 @@
+# $Id$
+#
+#	Makefile for netcdf libsrc
+#
+
+include ../../macros.make
+
+INCLUDES = -I. -DUSE_MPIO
+
+LIBRARY 	= libnetcdf.a
+PROGRAM		= ncvalid
+ld_netcdf	= -L. -lnetcdf
+
+HEADER	= netcdf.h
+
+MANUAL	= netcdf.3
+
+LIB_CSRCS = \
+	mpinetcdf.c \
+	header.c \
+	mpincio.c \
+	attr.c \
+	dim.c \
+	error.c \
+	nc.c \
+	ncx.c \
+	string.c \
+	var.c
+#	v1hpg.c
+#	ncio.c \
+#	putget.c \
+
+PACKING_LIST = \
+	$(LIB_CSRCS) \
+	depend \
+	fbits.h \
+	Makefile \
+	nc.h \
+	ncconfig.in \
+	ncio.h \
+	ncx.h \
+	netcdf.3 \
+	netcdf.h \
+	rnd.h 
+#	ffio.c \
+#	mpinetcdf.h \
+#	onstack.h \
+#	posixio.c \
+
+LIB_OBJS = $(LIB_CSRCS:.c=.o)
+
+PROG_CSRCS = \
+	validator.c \
+	header.c \
+	mpincio.c \
+	attr.c \
+	dim.c \
+	nc.c \
+	ncx.c \
+	string.c \
+	var.c
+
+PROG_OBJS = $(PROG_CSRCS:.c=.o)
+
+GARBAGE		= 
+
+DIST_GARBAGE	= ncconfig.h
+
+
+all:		$(LIBRARY) $(MANUAL) $(PROGRAM)
+
+install:	$(LIBDIR)/$(LIBRARY)	\
+		$(INCDIR)/$(HEADER)	\
+		$(MANDIR)/man3/$(MANUAL)\
+		$(BINDIR)/$(PROGRAM)
+
+uninstall:
+	-rm -f $(LIBDIR)/$(LIBRARY)
+	-rm -f $(INCDIR)/$(HEADER)
+	-rm -f $(MANDIR)/man3/$(MANUAL)
+	-rm -f $(BINDIR)/$(PROGRAM)
+
+
+
+# The rule for generating the manual page is here for completeness only.
+# The manual page is actually part of the distribution so that we don't
+# have to depend on the non-POSIX utility m4(1).
+#
+$(MANUAL):	../../man/netcdf.m4
+	$(M4) $(M4FLAGS) -DAPI=C $? >$@  || rm $@
+
+$(PROGRAM):	$(PROG_OBJS)
+	$(LINK.c) $(PROG_OBJS) $(LIBS)
+
+include ../..//rules.make
+
+.SUFFIXES: .ln
+LINT = lint
+LINT.c = $(LINT) $(LINTFLAGS) $(CPPFLAGS)
+.c.ln:
+	$(LINT.c) -c $<
+
+llib-lnetcdf.ln: $(LIB_CSRCS)
+	$(LINT.c) $(LIB_CSRCS) -y -o netcdf
+
+lint: llib-lnetcdf.ln
+	$(LINT.c) t_nc.c llib-lnetcdf.ln
+
+include depend
Index: /branches/SDM_SciDAC/src/lib/ncio.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/ncio.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/ncio.h (revision 2)
@@ -0,0 +1,192 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* $Id$ */
+
+#ifndef _NCIO_H_
+#define _NCIO_H_
+
+#include <stddef.h>	/* size_t */
+#include <sys/types.h>	/* off_t */
+#include "netcdf.h"
+
+#ifdef USE_MPIO	/* for mpio, added by Jianwei Li */
+#include <mpi.h>
+#endif
+
+typedef struct ncio ncio;	/* forward reference */
+
+/*
+ * A value which is an invalid off_t
+ */
+#define OFF_NONE  ((off_t)(-1))
+
+/*
+ * Flags used by the region layer,
+ *  'rflags' argument to ncio.rel() and ncio.get().
+ */
+#define RGN_NOLOCK	0x1	/* Don't lock region.
+				 * Used when contention control handled
+				 * elsewhere.
+				 */
+#define RGN_NOWAIT	0x2	/* return immediate if can't lock, else wait */
+
+#define RGN_WRITE	0x4	/* we intend to modify, else read only */
+
+#define RGN_MODIFIED	0x8	/* we did modify, else, discard */
+
+
+/*
+ * The next four typedefs define the signatures
+ * of function pointers in struct ncio below.
+ * They are not used outside of this file and ncio.h,
+ * They just some casts in the ncio.c more readable.
+ */
+	/*
+	 * Indicate that you are done with the region which begins
+	 * at offset. Only reasonable flag value is RGN_MODIFIED.
+	 */
+typedef int ncio_relfunc(ncio *const nciop,
+		 off_t offset, int rflags);
+
+	/*
+	 * Request that the region (offset, extent)
+	 * be made available through *vpp.
+	 */
+typedef int ncio_getfunc(ncio *const nciop,
+			off_t offset, size_t extent,
+			int rflags,
+			void **const vpp);
+
+	/*
+	 * Like memmove(), safely move possibly overlapping data.
+	 * Only reasonable flag value is RGN_NOLOCK.
+	 */
+typedef int ncio_movefunc(ncio *const nciop, off_t to, off_t from,
+			size_t nbytes, int rflags);
+
+	/*
+	 * Write out any dirty buffers to disk and
+	 * ensure that next read will get data from disk.
+	 */
+typedef int ncio_syncfunc(ncio *const nciop);
+
+	/*
+	 * Don't call this. 
+	 * Internal function called at close to
+	 * free up anything hanging off pvt;
+	 */
+typedef void ncio_freefunc(void *const pvt);
+
+/* Get around cplusplus "const xxx in class ncio without constructor" error */
+#if defined(__cplusplus)
+#define NCIO_CONST
+#else
+#define NCIO_CONST const
+#endif
+
+/*
+ * netcdf i/o abstraction
+ */
+struct ncio {
+	/*
+	 * A copy of the ioflags argument passed in to ncio_open()
+	 * or ncio_create().
+	 */
+	int ioflags;
+
+	/*
+	 * The file descriptor of the netcdf file.
+	 * This gets handed to the user as the netcdf id.
+	 */
+	NCIO_CONST int fd;
+
+#ifdef USE_MPIO /* added by Jianwei Li */
+	/* 
+	 * The MPI File handle and the communicator 
+	 * Added by Jianwei Li
+	 */
+#define MPI_COLLECTIVE_FH 2
+#define MPI_INDEPENDENT_FH 8
+
+#define NC_collectiveFhOpened(nciop) \
+	(fIsSet(nciop->mpioflags, MPI_COLLECTIVE_FH))
+
+#define NC_independentFhOpened(nciop) \
+	(fIsSet(nciop->mpioflags, MPI_INDEPENDENT_FH))
+
+#define set_NC_collectiveFh(nciop) \
+	fSet((nciop)->mpioflags, MPI_COLLECTIVE_FH)
+
+#define set_NC_independentFh(nciop) \
+	fSet((nciop)->mpioflags, MPI_INDEPENDENT_FH)
+
+	char* filename;
+	MPI_File collective_fh;
+	MPI_File independent_fh;
+	int mpiomode;
+	MPI_Comm comm;
+	MPI_Info mpiinfo;
+	int mpioflags;
+#endif
+
+	/* member functions do the work */
+
+	ncio_relfunc *NCIO_CONST rel;
+
+	ncio_getfunc *NCIO_CONST get;
+
+	ncio_movefunc *NCIO_CONST move;
+
+	ncio_syncfunc *NCIO_CONST sync;
+
+	ncio_freefunc *NCIO_CONST free; /* Implementation private */
+
+	/*
+	 * A copy of the 'path' argument passed in to ncio_open()
+	 * or ncio_create(). Used by ncabort() to remove (unlink)
+	 * the file and by error messages.
+	 */
+	const char *path;
+
+	/* implementation private stuff */
+	void *NCIO_CONST pvt;
+};
+
+#undef NCIO_CONST
+
+extern ncio * 
+ncio_new(const char *path, int ioflags);
+
+extern void
+ncio_free(ncio *nciop);
+
+#ifdef USE_MPIO /* Following interface changed by Jianwei Li */
+
+#else 
+
+extern int
+ncio_create(const char *path, int ioflags,
+	size_t initialsz,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp);
+
+#endif /* USE_MPIO */
+
+#ifdef USE_MPIO /* Following interface changed by Jianwei Li */
+ 
+#else  
+
+extern int
+ncio_open(const char *path,
+	int ioflags,
+	off_t igeto, size_t igetsz, size_t *sizehintp,
+	ncio **nciopp, void **const igetvpp);
+
+#endif /* USE_MPIO */
+
+extern int 
+ncio_close(ncio *nciop, int doUnlink);
+
+#endif /* _NCIO_H_ */
Index: /branches/SDM_SciDAC/src/lib/ncx.h
===================================================================
--- /branches/SDM_SciDAC/src/lib/ncx.h (revision 2)
+++ /branches/SDM_SciDAC/src/lib/ncx.h (revision 2)
@@ -0,0 +1,661 @@
+/*
+ *	Copyright 1996, University Corporation for Atmospheric Research
+ *	See netcdf/COPYRIGHT file for copying and redistribution conditions.
+ */
+/* "$Id$" */
+
+#ifndef _NCX_H_
+#define _NCX_H_
+
+/*
+ * An external data representation interface.
+ *
+ * This started out as a general replacement for ONC XDR,
+ * specifically, the xdrmem family of functions.
+ * 
+ * We eventually realized that we could write more portable
+ * code if we decoupled any association between the 'C' types
+ * and the external types. (XDR has this association between the 'C'
+ * types and the external representations, like xdr_int() takes
+ * an int argument and goes to an external int representation.) 
+ * So, now there is a matrix of functions.
+ * 
+ */
+
+#include "ncconfig.h" /* output of 'configure' */
+#include "rnd.h"
+#include <stddef.h> /* size_t */
+#include <errno.h>
+#include <sys/types.h> /* off_t */
+
+#if defined(_CRAY) && !defined(_CRAYIEEE)
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#elif defined(_SX) && defined(_FLOAT2)	/* NEC SUPER-UX in CRAY mode */
+#define CRAYFLOAT 1 /* CRAY Floating point */
+#endif
+
+/*
+ * The integer return code for the conversion routines
+ * is 0 (ENOERR) when no error occured, or NC_ERANGE as appropriate
+ * for an overflow conversion.
+ */
+#ifndef ENOERR
+#define ENOERR 0
+#endif
+#ifndef NC_ERANGE
+#define NC_ERANGE (-60) /* N.B. must match value in netcdf.h */
+#endif
+#ifndef NC_ENOMEM
+#define NC_ENOMEM (-61) /* N.B. must match value in netcdf.h */
+#endif
+
+
+/*
+ * External sizes of the primitive elements.
+ */
+#define X_SIZEOF_CHAR		1
+#define X_SIZEOF_SHORT		2
+#define X_SIZEOF_INT		4	/* xdr_int */
+#if 0
+#define X_SIZEOF_LONG		8 */	/* xdr_long_long */
+#endif
+#define X_SIZEOF_FLOAT		4
+#define X_SIZEOF_DOUBLE		8
+
+/*
+ * For now, netcdf is limited to 32 bit offsets and sizes,
+ *  see also X_SIZE_MAX, X_OFF_MAX below
+ */
+#define X_SIZEOF_OFF_T		X_SIZEOF_INT
+#define X_SIZEOF_SIZE_T		X_SIZEOF_INT
+
+/*
+ * limits of the external representation
+ */
+#define X_SCHAR_MIN	(-128)
+#define X_SCHAR_MAX	127
+#define X_UCHAR_MAX	255U
+#define X_SHORT_MIN	(-32768)
+#define X_SHRT_MIN	X_SHORT_MIN	/* alias compatible with limits.h */
+#define X_SHORT_MAX	32767
+#define X_SHRT_MAX	X_SHORT_MAX	/* alias compatible with limits.h */
+#define X_USHORT_MAX	65535U
+#define X_USHRT_MAX	X_USHORT_MAX	/* alias compatible with limits.h */
+#define X_INT_MIN	(-2147483647-1)
+#define X_INT_MAX	2147483647
+#define X_UINT_MAX	4294967295U
+#if 0
+#define X_LONG_MIN	(-2147483647-1)
+#define X_LONG_MAX	2147483647
+#define X_ULONG_MAX	4294967295U
+#endif
+#define X_FLOAT_MAX	3.40282347e+38f
+#define X_FLOAT_MIN	(-X_FLOAT_MAX)
+#define X_FLT_MAX	X_FLOAT_MAX	/* alias compatible with limits.h */
+#if CRAYFLOAT
+/* ldexp(1. - ldexp(.5 , -46), 1024) */
+#define X_DOUBLE_MAX    1.79769313486230e+308
+#else
+/* scalb(1. - scalb(.5 , -52), 1024) */
+#define X_DOUBLE_MAX	1.7976931348623157e+308 
+#endif
+#define X_DOUBLE_MIN	(-X_DOUBLE_MAX)
+#define X_DBL_MAX	X_DOUBLE_MAX	/* alias compatible with limits.h */
+
+#define X_SIZE_MAX	X_INT_MAX	/* N.B., just uses the signed range */
+#define X_OFF_MAX	X_INT_MAX
+
+
+/* Begin ncx_len */
+
+/*
+ * ncx_len_xxx() interfaces are defined as macros below, 
+ * These give the length of an array of nelems of the type.
+ * N.B. The 'char' and 'short' interfaces give the X_ALIGNED length.
+ */
+#define X_ALIGN			4	/* a.k.a. BYTES_PER_XDR_UNIT */
+
+#define ncx_len_char(nelems) \
+	_RNDUP((nelems), X_ALIGN)
+
+#define ncx_len_short(nelems) \
+	(((nelems) + (nelems)%2)  * X_SIZEOF_SHORT)
+
+#define ncx_len_int(nelems) \
+	((nelems) * X_SIZEOF_INT)
+
+#define ncx_len_long(nelems) \
+	((nelems) * X_SIZEOF_LONG)
+
+#define ncx_len_float(nelems) \
+	((nelems) * X_SIZEOF_FLOAT)
+
+#define ncx_len_double(nelems) \
+	((nelems) * X_SIZEOF_DOUBLE)
+
+/* End ncx_len */
+
+#if __CHAR_UNSIGNED__
+	/* 'char' is unsigned, declare ncbyte as 'signed char' */
+typedef signed char schar;
+
+#else
+	/* 'char' is signed */
+typedef signed char schar;
+
+#endif	/* __CHAR_UNSIGNED__ */
+
+/*
+ * Primitive numeric conversion functions.
+ * The `put' functions convert from native internal
+ * type to the external type, while the `get' functions
+ * convert from the external to the internal.
+ *
+ * These take the form
+ *	int ncx_get_{external_type}_{internal_type}(
+ *		const void *xp,
+ *		internal_type *ip
+ *	);
+ *	int ncx_put_{external_type}_{internal_type}(
+ *		void *xp,
+ *		const internal_type *ip
+ *	);
+ * where
+ *	`external_type' and `internal_type' chosen from
+		schar
+		uchar
+		short
+		ushort
+		int
+		uint
+		long
+		ulong
+		float
+		double
+ *
+ * Not all combinations make sense.
+ * We may not implement all combinations that make sense.
+ * The netcdf functions that use this ncx interface don't
+ * use these primitive conversion functions. They use the
+ * aggregate conversion functions declared below.
+ *
+ * Storage for a single element of external type is at the `void * xp'
+ * argument.
+ *
+ * Storage for a single element of internal type is at `ip' argument.
+ *
+ * These functions return 0 (ENOERR) when no error occured,
+ * or NC_ERANGE when the value being converted is too large.
+ * When NC_ERANGE occurs, an undefined (implementation dependent)
+ * conversion may have occured.
+ *
+ * Note that loss of precision may occur silently.
+ *
+ */
+
+#if 0
+extern int
+ncx_get_schar_schar(const void *xp, schar *ip);
+extern int
+ncx_get_schar_uchar(const void *xp, uchar *ip);
+extern int
+ncx_get_schar_short(const void *xp, short *ip);
+extern int
+ncx_get_schar_int(const void *xp, int *ip);
+extern int
+ncx_get_schar_long(const void *xp, long *ip);
+extern int
+ncx_get_schar_float(const void *xp, float *ip);
+extern int
+ncx_get_schar_double(const void *xp, double *ip);
+
+extern int
+ncx_put_schar_schar(void *xp, const schar *ip);
+extern int
+ncx_put_schar_uchar(void *xp, const uchar *ip);
+extern int
+ncx_put_schar_short(void *xp, const short *ip);
+extern int
+ncx_put_schar_int(void *xp, const int *ip);
+extern int
+ncx_put_schar_long(void *xp, const long *ip);
+extern int
+ncx_put_schar_float(void *xp, const float *ip);
+extern int
+ncx_put_schar_double(void *xp, const double *ip);
+#endif
+ 
+
+extern int
+ncx_get_short_schar(const void *xp, schar *ip);
+extern int
+ncx_get_short_uchar(const void *xp, uchar *ip);
+extern int
+ncx_get_short_short(const void *xp, short *ip);
+extern int
+ncx_get_short_int(const void *xp, int *ip);
+extern int
+ncx_get_short_long(const void *xp, long *ip);
+extern int
+ncx_get_short_float(const void *xp, float *ip);
+extern int
+ncx_get_short_double(const void *xp, double *ip);
+
+extern int
+ncx_put_short_schar(void *xp, const schar *ip);
+extern int
+ncx_put_short_uchar(void *xp, const uchar *ip);
+extern int
+ncx_put_short_short(void *xp, const short *ip);
+extern int
+ncx_put_short_int(void *xp, const int *ip);
+extern int
+ncx_put_short_long(void *xp, const long *ip);
+extern int
+ncx_put_short_float(void *xp, const float *ip);
+extern int
+ncx_put_short_double(void *xp, const double *ip);
+ 
+
+extern int
+ncx_get_int_schar(const void *xp, schar *ip);
+extern int
+ncx_get_int_uchar(const void *xp, uchar *ip);
+extern int
+ncx_get_int_short(const void *xp, short *ip);
+extern int
+ncx_get_int_int(const void *xp, int *ip);
+extern int
+ncx_get_int_long(const void *xp, long *ip);
+extern int
+ncx_get_int_float(const void *xp, float *ip);
+extern int
+ncx_get_int_double(const void *xp, double *ip);
+
+extern int
+ncx_put_int_schar(void *xp, const schar *ip);
+extern int
+ncx_put_int_uchar(void *xp, const uchar *ip);
+extern int
+ncx_put_int_short(void *xp, const short *ip);
+extern int
+ncx_put_int_int(void *xp, const int *ip);
+extern int
+ncx_put_int_long(void *xp, const long *ip);
+extern int
+ncx_put_int_float(void *xp, const float *ip);
+extern int
+ncx_put_int_double(void *xp, const double *ip);
+ 
+
+extern int
+ncx_get_float_schar(const void *xp, schar *ip);
+extern int
+ncx_get_float_uchar(const void *xp, uchar *ip);
+extern int
+ncx_get_float_short(const void *xp, short *ip);
+extern int
+ncx_get_float_int(const void *xp, int *ip);
+extern int
+ncx_get_float_long(const void *xp, long *ip);
+extern int
+ncx_get_float_float(const void *xp, float *ip);
+extern int
+ncx_get_float_double(const void *xp, double *ip);
+
+extern int
+ncx_put_float_schar(void *xp, const schar *ip);
+extern int
+ncx_put_float_uchar(void *xp, const uchar *ip);
+extern int
+ncx_put_float_short(void *xp, const short *ip);
+extern int
+ncx_put_float_int(void *xp, const int *ip);
+extern int
+ncx_put_float_long(void *xp, const long *ip);
+extern int
+ncx_put_float_float(void *xp, const float *ip);
+extern int
+ncx_put_float_double(void *xp, const double *ip);
+ 
+
+extern int
+ncx_get_double_schar(const void *xp, schar *ip);
+extern int
+ncx_get_double_uchar(const void *xp, uchar *ip);
+extern int
+ncx_get_double_short(const void *xp, short *ip);
+extern int
+ncx_get_double_int(const void *xp, int *ip);
+extern int
+ncx_get_double_long(const void *xp, long *ip);
+extern int
+ncx_get_double_float(const void *xp, float *ip);
+extern int
+ncx_get_double_double(const void *xp, double *ip);
+
+extern int
+ncx_put_double_schar(void *xp, const schar *ip);
+extern int
+ncx_put_double_uchar(void *xp, const uchar *ip);
+extern int
+ncx_put_double_short(void *xp, const short *ip);
+extern int
+ncx_put_double_int(void *xp, const int *ip);
+extern int
+ncx_put_double_long(void *xp, const long *ip);
+extern int
+ncx_put_double_float(void *xp, const float *ip);
+extern int
+ncx_put_double_double(void *xp, const double *ip);
+ 
+
+/*
+ * Other primitive conversion functions
+ * N.B. slightly different interface
+ * Used by netcdf.
+ */
+
+/* ncx_get_int_size_t */
+extern int
+ncx_get_size_t(const void **xpp, size_t *ulp);
+/* ncx_get_int_off_t */
+extern int
+ncx_get_off_t(const void **xpp, off_t *lp);
+
+/* ncx_put_int_size_t */
+extern int
+ncx_put_size_t(void **xpp, const size_t *ulp);
+/* ncx_put_int_off_t */
+extern int
+ncx_put_off_t(void **xpp, const off_t *lp);
+
+
+/*
+ * Aggregate numeric conversion functions.
+ * Convert an array.  Replaces xdr_array(...).
+ * These functions are used by netcdf. Unlike the xdr
+ * interface, we optimize for aggregate conversions.
+ * This functions should be implemented to take advantage
+ * of multiple processor / parallel hardware where available.
+ *
+ * These take the form
+ *	int ncx_getn_{external_type}_{internal_type}(
+ *		const void *xpp,
+ *		size_t nelems,
+ *		internal_type *ip
+ *	);
+ *	int ncx_putn_{external_type}_{internal_type}(
+ *		void **xpp,
+ *		size_t nelems,
+ *		const internal_type *ip
+ *	);
+ * Where the types are as in the primitive numeric conversion functions.
+ *
+ * The value of the pointer to pointer argument, *xpp, is
+ * expected to reference storage for `nelems' of the external
+ * type.  On return, it modified to reference just past the last
+ * converted external element.
+ *
+ * The types whose external size is less than X_ALIGN also have `pad'
+ * interfaces. These round (and zero fill on put) *xpp up to X_ALIGN
+ * boundaries. (This is the usual xdr behavior.)
+ *
+ * The `ip' argument should point to an array of `nelems' of
+ * internal_type.
+ *
+ * Range errors (NC_ERANGE) for a individual values in the array 
+ * DO NOT terminate the array conversion. All elements are converted,
+ * with some having undefined values.
+ * If any range error occurs, the function returns NC_ERANGE.
+ *
+ */
+
+extern int
+ncx_getn_schar_schar(const void **xpp, size_t nelems, schar *ip);
+extern int
+ncx_getn_schar_uchar(const void **xpp, size_t nelems, uchar *ip);
+extern int
+ncx_getn_schar_short(const void **xpp, size_t nelems, short *ip);
+extern int
+ncx_getn_schar_int(const void **xpp, size_t nelems, int *ip);
+extern int
+ncx_getn_schar_long(const void **xpp, size_t nelems, long *ip);
+extern int
+ncx_getn_schar_float(const void **xpp, size_t nelems, float *ip);
+extern int
+ncx_getn_schar_double(const void **xpp, size_t nelems, double *ip);
+
+extern int
+ncx_pad_getn_schar_schar(const void **xpp, size_t nelems, schar *ip);
+extern int
+ncx_pad_getn_schar_uchar(const void **xpp, size_t nelems, uchar *ip);
+extern int
+ncx_pad_getn_schar_short(const void **xpp, size_t nelems, short *ip);
+extern int
+ncx_pad_getn_schar_int(const void **xpp, size_t nelems, int *ip);
+extern int
+ncx_pad_getn_schar_long(const void **xpp, size_t nelems, long *ip);
+extern int
+ncx_pad_getn_schar_float(const void **xpp, size_t nelems, float *ip);
+extern int
+ncx_pad_getn_schar_double(const void **xpp, size_t nelems, double *ip);
+
+extern int
+ncx_putn_schar_schar(void **xpp, size_t nelems, const schar *ip);
+extern int
+ncx_putn_schar_uchar(void **xpp, size_t nelems, const uchar *ip);
+extern int
+ncx_putn_schar_short(void **xpp, size_t nelems, const short *ip);
+extern int
+ncx_putn_schar_int(void **xpp, size_t nelems, const int *ip);
+extern int
+ncx_putn_schar_long(void **xpp, size_t nelems, const long *ip);
+extern int
+ncx_putn_schar_float(void **xpp, size_t nelems, const float *ip);
+extern int
+ncx_putn_schar_double(void **xpp, size_t nelems, const double *ip);
+ 
+extern int
+ncx_pad_putn_schar_schar(void **xpp, size_t nelems, const schar *ip);
+extern int
+ncx_pad_putn_schar_uchar(void **xpp, size_t nelems, const uchar *ip);
+extern int
+ncx_pad_putn_schar_short(void **xpp, size_t nelems, const short *ip);
+extern int
+ncx_pad_putn_schar_int(void **xpp, size_t nelems, const int *ip);
+extern int
+ncx_pad_putn_schar_long(void **xpp, size_t nelems, const long *ip);
+extern int
+ncx_pad_putn_schar_float(void **xpp, size_t nelems, const float *ip);
+extern int
+ncx_pad_putn_schar_double(void **xpp, size_t nelems, const double *ip);
+
+
+extern int
+ncx_getn_short_schar(const void **xpp, size_t nelems, schar *ip);
+extern int
+ncx_getn_short_uchar(const void **xpp, size_t nelems, uchar *ip);
+extern int
+ncx_getn_short_short(const void **xpp, size_t nelems, short *ip);
+extern int
+ncx_getn_short_int(const void **xpp, size_t nelems, int *ip);
+extern int
+ncx_getn_short_long(const void **xpp, size_t nelems, long *ip);
+extern int
+ncx_getn_short_float(const void **xpp, size_t nelems, float *ip);
+extern int
+ncx_getn_short_double(const void **xpp, size_t nelems, double *ip);
+
+extern int
+ncx_pad_getn_short_schar(const void **xpp, size_t nelems, schar *ip);
+extern int
+ncx_pad_getn_short_uchar(const void **xpp, size_t nelems, uchar *ip);
+extern int
+ncx_pad_getn_short_short(const void **xpp, size_t nelems, short *ip);
+extern int
+ncx_pad_getn_short_int(const void **xpp, size_t nelems, int *ip);
+extern int
+ncx_pad_getn_short_long(const void **xpp, size_t nelems, long *ip);
+extern int
+ncx_pad_getn_short_float(const void **xpp, size_t nelems, float *ip);
+extern int
+ncx_pad_getn_short_double(const void **xpp, size_t nelems, double *ip);
+
+extern int
+ncx_putn_short_schar(void **xpp, size_t nelems, const schar *ip);
+extern int
+ncx_putn_short_uchar(void **xpp, size_t nelems, const uchar *ip);
+extern int
+ncx_putn_short_short(void **xpp, size_t nelems, const short *ip);
+extern int
+ncx_putn_short_int(void **xpp, size_t nelems, const int *ip);
+extern int
+ncx_putn_short_long(void **xpp, size_t nelems, const long *ip);
+extern int
+ncx_putn_short_float(void **xpp, size_t nelems, const float *ip);
+extern int
+ncx_putn_short_double(void **xpp, size_t nelems, const double *ip);
+ 
+extern int
+ncx_pad_putn_short_schar(void **xpp, size_t nelems, const schar *ip);
+extern int
+ncx_pad_putn_short_uchar(void **xpp, size_t nelems, const uchar *ip);
+extern int
+ncx_pad_putn_short_short(void **xpp, size_t nelems, const short *ip);
+extern int
+ncx_pad_putn_short_int(void **xpp, size_t nelems, const int *ip);
+extern int
+ncx_pad_putn_short_long(void **xpp, size_t nelems, const long *ip);
+extern int
+ncx_pad_putn_short_float(void **xpp, size_t nelems, const float *ip);
+extern int
+ncx_pad_putn_short_double(void **xpp, size_t nelems, const double *ip);
+
+
+extern int
+ncx_getn_int_schar(const void **xpp, size_t nelems, schar *ip);
+extern int
+ncx_getn_int_uchar(const void **xpp, size_t nelems, uchar *ip);
+extern int
+ncx_getn_int_short(const void **xpp, size_t nelems, short *ip);
+extern int
+ncx_getn_int_int(const void **xpp, size_t nelems, int *ip);
+extern int
+ncx_getn_int_long(const void **xpp, size_t nelems, long *ip);
+extern int
+ncx_getn_int_float(const void **xpp, size_t nelems, float *ip);
+extern int
+ncx_getn_int_double(const void **xpp, size_t nelems, double *ip);
+
+extern int
+ncx_putn_int_schar(void **xpp, size_t nelems, const schar *ip);
+extern int
+ncx_putn_int_uchar(void **xpp, size_t nelems, const uchar *ip);
+extern int
+ncx_putn_int_short(void **xpp, size_t nelems, const short *ip);
+extern int
+ncx_putn_int_int(void **xpp, size_t nelems, const int *ip);
+extern int
+ncx_putn_int_long(void **xpp, size_t nelems, const long *ip);
+extern int
+ncx_putn_int_float(void **xpp, size_t nelems, const float *ip);
+extern int
+ncx_putn_int_double(void **xpp, size_t nelems, const double *ip);
+ 
+
+extern int
+ncx_getn_float_schar(const void **xpp, size_t nelems, schar *ip);
+extern int
+ncx_getn_float_uchar(const void **xpp, size_t nelems, uchar *ip);
+extern int
+ncx_getn_float_short(const void **xpp, size_t nelems, short *ip);
+extern int
+ncx_getn_float_int(const void **xpp, size_t nelems, int *ip);
+extern int
+ncx_getn_float_long(const void **xpp, size_t nelems, long *ip);
+extern int
+ncx_getn_float_float(const void **xpp, size_t nelems, float *ip);
+extern int
+ncx_getn_float_double(const void **xpp, size_t nelems, double *ip);
+
+extern int
+ncx_putn_float_schar(void **xpp, size_t nelems, const schar *ip);
+extern int
+ncx_putn_float_uchar(void **xpp, size_t nelems, const uchar *ip);
+extern int
+ncx_putn_float_short(void **xpp, size_t nelems, const short *ip);
+extern int
+ncx_putn_float_int(void **xpp, size_t nelems, const int *ip);
+extern int
+ncx_putn_float_long(void **xpp, size_t nelems, const long *ip);
+extern int
+ncx_putn_float_float(void **xpp, size_t nelems, const float *ip);
+extern int
+ncx_putn_float_double(void **xpp, size_t nelems, const double *ip);
+ 
+
+extern int
+ncx_getn_double_schar(const void **xpp, size_t nelems, schar *ip);
+extern int
+ncx_getn_double_uchar(const void **xpp, size_t nelems, uchar *ip);
+extern int
+ncx_getn_double_short(const void **xpp, size_t nelems, short *ip);
+extern int
+ncx_getn_double_int(const void **xpp, size_t nelems, int *ip);
+extern int
+ncx_getn_double_long(const void **xpp, size_t nelems, long *ip);
+extern int
+ncx_getn_double_float(const void **xpp, size_t nelems, float *ip);
+extern int
+ncx_getn_double_double(const void **xpp, size_t nelems, double *ip);
+
+extern int
+ncx_putn_double_schar(void **xpp, size_t nelems, const schar *ip);
+extern int
+ncx_putn_double_uchar(void **xpp, size_t nelems, const uchar *ip);
+extern int
+ncx_putn_double_short(void **xpp, size_t nelems, const short *ip);
+extern int
+ncx_putn_double_int(void **xpp, size_t nelems, const int *ip);
+extern int
+ncx_putn_double_long(void **xpp, size_t nelems, const long *ip);
+extern int
+ncx_putn_double_float(void **xpp, size_t nelems, const float *ip);
+extern int
+ncx_putn_double_double(void **xpp, size_t nelems, const double *ip);
+ 
+
+/*
+ * Other aggregate conversion functions.
+ */
+
+/* read ASCII characters */
+extern int
+ncx_getn_text(const void **xpp, size_t nchars, char *cp);
+extern int
+ncx_pad_getn_text(const void **xpp, size_t nchars, char *cp);
+
+/* write ASCII characters */
+extern int
+ncx_putn_text(void **xpp, size_t nchars, const char *cp);
+extern int
+ncx_pad_putn_text(void **xpp, size_t nchars, const char *cp);
+
+/* for symmetry */
+#define ncx_getn_char_char(xpp, nelems, fillp) ncx_getn_text(xpp, nelems, fillp)
+#define ncx_putn_char_char(xpp, nelems, fillp) ncx_putn_text(xpp, nelems, fillp)
+
+/* read opaque data */
+extern int
+ncx_getn_void(const void **xpp, size_t nchars, void *vp);
+extern int
+ncx_pad_getn_void(const void **xpp, size_t nchars, void *vp);
+
+/* write opaque data */
+extern int
+ncx_putn_void(void **xpp, size_t nchars, const void *vp);
+extern int
+ncx_pad_putn_void(void **xpp, size_t nchars, const void *vp);
+
+#endif /* _NCX_H_ */
Index: /branches/SDM_SciDAC/src/Makefile
===================================================================
--- /branches/SDM_SciDAC/src/Makefile (revision 2)
+++ /branches/SDM_SciDAC/src/Makefile (revision 2)
@@ -0,0 +1,9 @@
+all:
+	cd lib && $(MAKE)
+
+distclean: clean
+clean:
+	cd lib && $(MAKE) clean
+
+install:
+	cd lib && $(MAKE) install
Index: /branches/SDM_SciDAC/man/netcdf.m4
===================================================================
--- /branches/SDM_SciDAC/man/netcdf.m4 (revision 2)
+++ /branches/SDM_SciDAC/man/netcdf.m4 (revision 2)
@@ -0,0 +1,1207 @@
+divert(-1)
+
+changequote(<<,>>)
+define(<<index>>, defn(index))
+
+define(<<CODE>>, <<\fB$1\fR>>)
+
+define(<<ARG>>, <<\fI$1\fP>>)
+
+define(<<HEADER_FILE>>, 
+    <<ifelse(API,C,
+	$1.h,
+	$1.inc)>>)
+
+define(<<INCLUDE>>, 
+    <<ifelse(API,C,
+	<<#include>> "HEADER_FILE($1)",
+	<<<<include>>>> HEADER_FILE($1))>>)
+
+define(<<COMPILER>>,
+    <<ifelse(API,C,
+	cc,
+	f77)>>)
+
+define(<<LANGUAGE>>,
+    <<ifelse(API,C,
+	C,
+	FORTRAN)>>)
+
+define(<<RETSTR>>,
+    <<ifelse(API,C,
+	const char*,
+	character*80)>>)
+
+define(<<FNAME>>,
+    <<ifelse(API,C,
+	ncmpi_$1,
+	nfmpi_$1)>>)
+
+define(<<VOID_ARG>>,
+    <<ifelse(API,C,,void)>>)
+
+define(<<MACRO>>,
+    <<CODE(ifelse(API,C,
+	NC_$1,
+	NF_$1))>>)
+
+dnl AQUAL(io, rank)
+define(<<AQUAL>>, <<ifelse(API,C,
+    <<ifelse($1, output, , <<ifelse($2, 0, , const )>>)>>)>>)
+
+dnl CTYPE(type)
+define(<<CTYPE>>,
+    <<ifelse($1,text,char,
+    <<ifelse($1,uchar,unsigned char,
+    <<ifelse($1,schar,signed char,
+    <<ifelse($1,short,short,
+    <<ifelse($1,int,int,
+    <<ifelse($1,nc_type,nc_type,
+    <<ifelse($1,size_t,size_t,
+    <<ifelse($1,ptrdiff_t,ptrdiff_t,
+    <<ifelse($1,long,long,
+    <<ifelse($1,float,float,
+    <<ifelse($1,double,double)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)
+
+dnl CSTAR(io, rank)
+define(<<CSTAR>>, <<ifelse($1,input,,<<ifelse($2,0,*)>>)>>)
+
+dnl FTYPE(type, rank)
+define(<<FTYPE>>, 
+    <<ifelse($1,text,<<character*ifelse($2,0,1,(*))>>,
+    <<ifelse($1,schar,integer*1,
+    <<ifelse($1,short,integer*2,
+    <<ifelse($1,int,integer,
+    <<ifelse($1,nc_type,integer,
+    <<ifelse($1,size_t,integer,
+    <<ifelse($1,ptrdiff_t,integer,
+    <<ifelse($1,long,integer,
+    <<ifelse($1,float,real,
+    <<ifelse($1,double,doubleprecision)>>)>>)>>)>>)>>)>>)>>)>>)>>)>>)
+
+dnl ATYPE(io,rank,type)
+define(<<ATYPE>>, <<ifelse(API,C,
+    <<CTYPE($3)<<>>CSTAR($1,$2)>>, 
+    <<FTYPE($3,$2)>>)>>)
+
+dnl AID(name, rank, type)
+define(<<AID>>, <<ARG($1)<<>>ifelse(API,C,
+    <<ifelse($2,0,,[])>>, 
+    <<ifelse($3,text,,<<ifelse($2,0,,(1))>>)>>)>>)
+
+dnl ADECL(io, rank, type, name)
+define(<<ADECL>>, <<AQUAL($1,$2)ATYPE($1,$2,$3) AID($4,$2,$3)>>)
+
+define(<<ITEXT>>,	<<ADECL(input,0,text,$1)>>)
+define(<<ITEXTV>>,	<<ADECL(input,1,text,$1)>>)
+define(<<OTEXT>>,	<<ADECL(output,0,text,$1)>>)
+define(<<OTEXTV>>,	<<ADECL(output,1,text,$1)>>)
+
+define(<<IUCHAR>>,	<<ADECL(input,0,uchar,$1)>>)
+define(<<IUCHARV>>,	<<ADECL(input,1,uchar,$1)>>)
+define(<<OUCHAR>>,	<<ADECL(output,0,uchar,$1)>>)
+define(<<OUCHARV>>,	<<ADECL(output,1,uchar,$1)>>)
+
+define(<<ISCHAR>>,	<<ADECL(input,0,schar,$1)>>)
+define(<<ISCHARV>>,	<<ADECL(input,1,schar,$1)>>)
+define(<<OSCHAR>>,	<<ADECL(output,0,schar,$1)>>)
+define(<<OSCHARV>>,	<<ADECL(output,1,schar,$1)>>)
+
+define(<<ISHORT>>,	<<ADECL(input,0,short,$1)>>)
+define(<<ISHORTV>>,	<<ADECL(input,1,short,$1)>>)
+define(<<OSHORT>>,	<<ADECL(output,0,short,$1)>>)
+define(<<OSHORTV>>,	<<ADECL(output,1,short,$1)>>)
+
+define(<<IINT>>,	<<ADECL(input,0,int,$1)>>)
+define(<<IINTV>>,	<<ADECL(input,1,int,$1)>>)
+define(<<OINT>>,	<<ADECL(output,0,int,$1)>>)
+define(<<OINTV>>,	<<ADECL(output,1,int,$1)>>)
+
+define(<<INCTYPE>>,	<<ADECL(input,0,nc_type,$1)>>)
+define(<<INCTYPEV>>,	<<ADECL(input,1,nc_type,$1)>>)
+define(<<ONCTYPE>>,	<<ADECL(output,0,nc_type,$1)>>)
+define(<<ONCTYPEV>>,	<<ADECL(output,1,nc_type,$1)>>)
+
+define(<<ISIZET>>,	<<ADECL(input,0,size_t,$1)>>)
+define(<<ISIZETV>>,	<<ADECL(input,1,size_t,$1)>>)
+define(<<OSIZET>>,	<<ADECL(output,0,size_t,$1)>>)
+define(<<OSIZETV>>,	<<ADECL(output,1,size_t,$1)>>)
+
+define(<<IPTRDIFFT>>,	<<ADECL(input,0,ptrdiff_t,$1)>>)
+define(<<IPTRDIFFTV>>,	<<ADECL(input,1,ptrdiff_t,$1)>>)
+define(<<OPTRDIFFT>>,	<<ADECL(output,0,ptrdiff_t,$1)>>)
+define(<<OPTRDIFFTV>>,	<<ADECL(output,1,ptrdiff_t,$1)>>)
+
+define(<<ILONG>>,	<<ADECL(input,0,long,$1)>>)
+define(<<ILONGV>>,	<<ADECL(input,1,long,$1)>>)
+define(<<OLONG>>,	<<ADECL(output,0,long,$1)>>)
+define(<<OLONGV>>,	<<ADECL(output,1,long,$1)>>)
+
+define(<<IFLOAT>>,	<<ADECL(input,0,float,$1)>>)
+define(<<IFLOATV>>,	<<ADECL(input,1,float,$1)>>)
+define(<<OFLOAT>>,	<<ADECL(output,0,float,$1)>>)
+define(<<OFLOATV>>,	<<ADECL(output,1,float,$1)>>)
+
+define(<<IDOUBLE>>,	<<ADECL(input,0,double,$1)>>)
+define(<<IDOUBLEV>>,	<<ADECL(input,1,double,$1)>>)
+define(<<ODOUBLE>>,	<<ADECL(output,0,double,$1)>>)
+define(<<ODOUBLEV>>,	<<ADECL(output,1,double,$1)>>)
+
+define(<<IMPICOMM>>,	<<ADECL(input,0,MPI_Comm,$1)>>)
+define(<<IMPIINFO>>,	<<ADECL(input,0,MPI_Info,$1)>>)
+
+dnl CCOMP(type)
+define(<<CCOMP>>, 
+    <<ifelse($1,text,text,
+    <<ifelse($1,uchar,uchar,
+    <<ifelse($1,schar,schar,
+    <<ifelse($1,short,short,
+    <<ifelse($1,int,int,
+    <<ifelse($1,long,long,
+    <<ifelse($1,float,float,
+    <<ifelse($1,double,double)>>)>>)>>)>>)>>)>>)>>)>>)
+
+dnl FCOMP(type)
+define(<<FCOMP>>, 
+    <<ifelse($1,text,text,
+    <<ifelse($1,schar,int1,
+    <<ifelse($1,short,int2,
+    <<ifelse($1,int,int,
+    <<ifelse($1,float,real,
+    <<ifelse($1,double,double)>>)>>)>>)>>)>>)>>)
+
+dnl COMP(type)
+define(<<COMP>>, <<ifelse(API,C,<<CCOMP($1)>>,<<FCOMP($1)>>)>>)
+
+define(<<FDECL_TYPE>>,
+    <<ifelse(API,C, 
+	int,
+	integer function)>>)
+
+dnl DECL(return-type, name, argument-list)
+define(<<DECL>>, <<CODE($1 FNAME($2)$3)>>)
+
+dnl FDECL(name, argument-list)
+define(<<FDECL>>, <<DECL(FDECL_TYPE, $1, $2)>>)
+
+dnl IODECL(name, type, argument-list)
+define(<<IODECL>>, <<FDECL($1_<<>>COMP($2), $3)>>)
+
+dnl FREF(name)
+define(<<FREF>>, <<CODE(FNAME($1)(\|))>>)
+
+dnl FOLD(cname, fname)
+define(<<FOLD>>, <<CODE(ifelse(API,C, nc$1, nc$2)(\|))>>)
+
+dnl Function Input Arguments:
+define(<<IATTNUM>>, <<IINT(attnum)>>)
+define(<<ICMODE>>, <<IINT(cmode)>>)
+define(<<ICOUNT>>, <<ISIZETV(count)>>)
+define(<<IDIMID>>, <<IINT(dimid)>>)
+define(<<IDIMIDS>>, <<IINTV(dimids)>>)
+define(<<IFILLMODE>>, <<IINT(fillmode)>>)
+define(<<IH_MINFREE>>, <<ISIZET(h_minfree)>>)
+define(<<IINDEX>>, <<ISIZETV(index)>>)
+define(<<IINITSIZE>>, <<ISIZET(initialsize)>>)
+define(<<ILEN>>, <<ISIZET(<<len>>)>>)
+define(<<IMAP>>, <<IPTRDIFFTV(imap)>>)
+define(<<IMODE>>, <<IINT(mode)>>)
+define(<<INAME>>, <<ITEXTV(name)>>)
+define(<<INCID>>, <<IINT(ncid)>>)
+define(<<INCIDIN>>, <<IINT(ncid_in)>>)
+define(<<INCIDOUT>>, <<IINT(ncid_out)>>)
+define(<<INDIMS>>, <<IINT(ndims)>>)
+define(<<INEWNAME>>, <<ITEXTV(newname)>>)
+define(<<IPATH>>, ITEXTV(path))
+define(<<IPE>>, <<IINT(pe)>>)
+define(<<IR_ALIGN>>, <<ISIZET(r_align)>>)
+define(<<ISTART>>, <<ISIZETV(start)>>)
+define(<<ISTATUS>>, <<IINT(status)>>)
+define(<<ISTRIDE>>, <<ISIZETV(stride)>>)
+define(<<IV_ALIGN>>, <<ISIZET(v_align)>>)
+define(<<IV_MINFREE>>, <<ISIZET(v_minfree)>>)
+define(<<IVARID>>, <<IINT(varid)>>)
+define(<<IVARIDIN>>, <<IINT(varid_in)>>)
+define(<<IVARIDOUT>>, <<IINT(varid_out)>>)
+define(<<IXTYPE>>, <<INCTYPE(xtype)>>)
+
+define(<<ICOMM>>, <<IMPICOMM(comm)>>)
+define(<<IINFO>>, <<IMPIINFO(info)>>)
+
+dnl Function Output Arguments:
+define(<<OATTNUM>>, <<OINT(attnum)>>)
+define(<<OCHUNKSIZE>>, <<OSIZET(chunksize)>>)
+define(<<ODIMID>>, <<OINT(dimid)>>)
+define(<<ODIMIDS>>, <<OINTV(dimids)>>)
+define(<<OLEN>>, <<OSIZET(<<len>>)>>)
+define(<<ONAME>>, <<OTEXTV(name)>>)
+define(<<ONATTS>>, <<OINT(natts)>>)
+define(<<ONCID>>, <<OINT(ncid)>>)
+define(<<ONDIMS>>, <<OINT(ndims)>>)
+define(<<ONVARS>>, <<OINT(nvars)>>)
+define(<<OOLDFILLMODE>>, <<OINT(old_fillemode)>>)
+define(<<OPE>>, <<OINT(pe)>>)
+define(<<OVARID>>, <<OINT(varid)>>)
+define(<<OUNLIMDIMID>>, <<OINT(unlimdimid)>>)
+define(<<OXTYPE>>, <<ONCTYPE(xtype)>>)
+
+dnl Argument References:
+define(<<ATTNUM>>, <<ARG(attnum)>>)
+define(<<COUNT>>, <<ARG(count)>>)
+define(<<DIMID>>, <<ARG(dimid)>>)
+define(<<DIMIDS>>, <<ARG(dimids)>>)
+define(<<FILLMODE>>, <<ARG(fillmode)>>)
+define(<<IN>>, <<ARG(in)>>)
+define(<<INDEX>>, <<ARG(index)>>)
+define(<<LEN>>, <<ARG(<<len>>)>>)
+define(<<IMAP>>, <<ARG(imap)>>)
+define(<<NAME>>, <<ARG(name)>>)
+define(<<NATTS>>, <<ARG(natts)>>)
+define(<<NCID>>, <<ARG(ncid)>>)
+define(<<NCIDIN>>, <<ARG(ncid_in)>>)
+define(<<NCIDOUT>>, <<ARG(ncid_out)>>)
+define(<<NDIMS>>, <<ARG(ndims)>>)
+define(<<NEWNAME>>, <<ARG(newname)>>)
+define(<<NULL>>, <<CODE(<<<<NULL>>>>)>>)
+define(<<NVARS>>, <<ARG(nvars)>>)
+define(<<NVATTS>>, <<ARG(nvatts)>>)
+define(<<OLDFILLMODE>>, <<ARG(old_fillmode)>>)
+define(<<OUT>>, <<ARG(out)>>)
+define(<<START>>, <<ARG(start)>>)
+define(<<STRIDE>>, <<ARG(stride)>>)
+define(<<UNLIMDIMID>>, <<ARG(unlimdimid)>>)
+define(<<VARID>>, <<ARG(varid)>>)
+define(<<VARIDIN>>, <<ARG(varid_in)>>)
+define(<<VARIDOUT>>, <<ARG(varid_out)>>)
+define(<<XTYPE>>, <<ARG(xtype)>>)
+
+define(<<UPCASE>>, 
+<<translit($1,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ)>>)
+
+dnl Variable "Put" Functions:
+define(<<VOUT>>, <<I<<>>UPCASE($1)<<>>ifelse($2,1,,V)(ifelse($2,1,*)out)>>)
+define(<<VPUT>>, <<IODECL(put_var$1, $2, (INCID(), IVARID()$3, VOUT($2,$1)))>>)
+define(<<PUT_VAR>>, <<VPUT(,$1)>>)
+define(<<PUT_VAR1>>,<<VPUT(1,$1,<<, IINDEX()>>)>>)
+define(<<PUT_VARA>>,<<VPUT(a,$1,<<, ISTART(), ICOUNT()>>)>>)
+define(<<PUT_VARS>>,<<VPUT(s,$1,<<, ISTART(), ICOUNT(), ISTRIDE()>>)>>)
+define(<<PUT_VARM>>,<<VPUT(m,$1,<<, ISTART(), ICOUNT(), ISTRIDE(), IMAP()>>)>>)
+
+dnl Variable "Get" Functions:
+define(<<VIN>>, <<O<<>>UPCASE($1)<<>>ifelse($2,1,,V)(in)>>)
+define(<<VGET>>, <<IODECL(get_var$1, $2, (INCID(), IVARID()$3, VIN($2,$1)))>>)
+define(<<GET_VAR>>, <<VGET(,$1)>>)
+define(<<GET_VAR1>>,<<VGET(1,$1,<<, IINDEX()>>)>>)
+define(<<GET_VARA>>,<<VGET(a,$1,<<, ISTART(), ICOUNT()>>)>>)
+define(<<GET_VARS>>,<<VGET(s,$1,<<, ISTART(), ICOUNT(), ISTRIDE()>>)>>)
+define(<<GET_VARM>>,<<VGET(m,$1,<<, ISTART(), ICOUNT(), ISTRIDE(), IMAP()>>)>>)
+
+dnl Attribute "Put" Functions:
+define(<<AOUT>>, <<I<<>>UPCASE($1)<<>>V(out)>>)
+define(<<APUT>>,<<IODECL(put_att,$1,(INCID(), IVARID(), INAME(), IXTYPE(), ILEN(), AOUT($1)))>>)
+
+dnl Attribute "Get" Functions:
+define(<<AIN>>, <<O<<>>UPCASE($1)<<>>V(in)>>)
+define(<<AGET>>,<<IODECL(get_att,$1,(INCID(), IVARID(), INAME(), AIN($1)))>>)
+
+dnl Function Family Listing:
+define(<<FUNC_FAMILY>>,
+<<.HP
+$1(text)
+ifelse(API,C,
+<<.HP
+$1(uchar)>>)
+.HP
+$1(schar)
+.HP
+$1(short)
+.HP
+$1(int)
+ifelse(API,C,
+<<.HP
+$1(long)>>)
+.HP
+$1(float)
+.HP
+$1(double)>>)
+
+divert(0)dnl
+.TH NETCDF 3 "18 April 1997" "Printed: \n(yr.\n(mo.\n(dy" "UNIDATA LIBRARY FUNCTIONS"
+.SH N<<>>AME
+netcdf \- Unidata Network Common Data Form (netCDF) library, version 3 interface
+.SH SYNOPSIS
+.ft B
+.na
+.nh
+INCLUDE(netcdf)
+.sp
+ifelse(API,C,,
+.SS Most Systems:)
+COMPILER() ... -lnetcdf
+ifelse(API,C,,
+.sp
+.SS CRAY PVP Systems:
+f90 -dp -i64 ... -lnetcdf
+)
+.ad
+.hy
+.SH "LIBRARY VERSION"
+.LP
+This document describes version 3 of Unidata netCDF data-access interface
+for the LANGUAGE() programming language.
+.HP
+DECL(RETSTR(), inq_libvers, (VOID_ARG))
+.sp
+Returns a string identifying the version of the netCDF library, and
+when it was built, like: "3.1a of Aug 22 1996 12:57:47 $".
+.LP
+The RCS \fBident(1)\fP command will find a string like
+"$\|Id: @\|(#) netcdf library version 3.1a of Sep  6 1996 15:56:26 $"
+in the library. The SCCS \fBwhat(1)\fP command will find a string like
+"netcdf library version 3.1a of Aug 23 1996 16:07:40 $".
+.SH "RETURN VALUES"
+.LP
+All netCDF functions (except
+FREF(inq_libvers) and FREF(strerror)) return an integer status.
+This behavior replaces the
+ifelse(API,C, <<CODE(ncerr()) function>>, <<CODE(rcode)>> argument)
+used in previous versions of the library.
+If this returned status value is not equal to
+MACRO(NOERR) (zero), it
+indicates that an error occurred. The possible status values are defined in 
+ifelse(API,C, system <<<<include>>>> file <errno.h> and in )<<>>dnl
+ifelse(API,C,")HEADER_FILE(netcdf)<<>>ifelse(API,C,").
+.HP
+DECL(RETSTR(), strerror, (ISTATUS()))
+.sp
+Returns a string textual translation of the \fIstatus\fP
+value, like "Attribute or variable name contains illegal characters"
+or "No such file or directory".
+.HP
+FDECL(create, (ICOMM(), IPATH(), ICMODE(), IINFO(),
+ONCID()))
+.sp
+(Corresponds to FOLD(create, cre) in version 2)
+.sp
+Creates a new netCDF dataset at ARG(path),
+returning a netCDF ID in ARG(ncid).
+The argument ARG(cmode) may <<include>> the bitwise-or
+of the following flags:
+MACRO(NOCLOBBER)
+to protect existing datasets (default
+silently blows them away),
+MACRO(SHARE)
+for synchronous dataset updates
+(default is to buffer accesses), and
+MACRO(LOCK)
+(not yet implemented).
+When a netCDF dataset is created, is is opened
+MACRO(WRITE).
+The new netCDF dataset is in <<define>> mode.
+.HP
+FDECL(_create, (IPATH(), ICMODE(), IINITSIZE(), OCHUNKSIZE(), ONCID()))
+.sp
+Like FREF(create) but has additional performance tuning parameters.
+.sp
+The argument ARG(initialsize) sets the initial size of the file at
+creation time.
+.sp
+See FREF(_open) below for an explanation of the ARG(chunksize)
+parameter.
+.HP
+FDECL(open, (ICOMM(), IPATH(), IMODE(), IINFO(), ONCID()))
+.sp
+(Corresponds to FOLD(open, opn) in version 2)
+.sp
+Opens a existing netCDF dataset at ARG(path)
+returning a netCDF ID
+in ARG(ncid).
+The type of access is described by the ARG(mode) parameter,
+which may <<include>> the bitwise-or
+of the following flags:
+MACRO(WRITE)
+for read-write access (default
+read-only),
+MACRO(SHARE)
+for synchronous dataset updates (default is
+to buffer accesses), and
+MACRO(LOCK)
+(not yet implemented).
+.HP
+FDECL(_open, (IPATH(), IMODE(), OCHUNKSIZE(), ONCID()))
+.sp
+Like FREF(open) but has an additional performance tuning parameter.
+.sp
+The argument referenced by ARG(chunksize) controls a space versus time
+tradeoff, memory allocated in the netcdf library versus number of system
+calls.
+Because of internal requirements, the value may not be set to exactly
+the value requested.
+The actual value chosen is returned by reference.
+Using the value MACRO(SIZEHINT_DEFAULT) causes the library to choose a
+default.
+How the system choses the default depends on the system.
+On many systems, the "preferred I/O block size" is available from the 
+CODE(stat()) system call, CODE(struct stat) member CODE(st_blksize).
+If this is available it is used. Lacking that, twice the system pagesize
+is used.
+Lacking a call to discover the system pagesize, we just set default
+chunksize to 8192.
+.sp
+The chunksize is a property of a given open netcdf descriptor
+ARG(ncid), it is not a persistent property of the netcdf dataset.
+.HP
+FDECL(redef, (INCID()))
+.sp
+(Corresponds to FOLD(redef, redf) in version 2)
+.sp
+Puts an open netCDF dataset into <<define>> mode, 
+so dimensions, variables, and attributes can be added or renamed and 
+attributes can be deleted.
+.HP
+FDECL(enddef, (INCID()))
+.sp
+(Corresponds to FOLD(endef, endf) in version 2)
+.sp
+Takes an open netCDF dataset out of <<define>> mode.
+The changes made to the netCDF dataset
+while it was in <<define>> mode are checked and committed to disk if no
+problems occurred.  Some data values may be written as well,
+see "VARIABLE PREFILLING" below.
+After a successful call, variable data can be read or written to the dataset.
+.HP
+FDECL(_enddef, (INCID(), IH_MINFREE(), IV_ALIGN(), IV_MINFREE(), IR_ALIGN()))
+.sp
+Like FREF(enddef) but has additional performance tuning parameters.
+.sp
+Caution: this function exposes internals of the netcdf version 1 file
+<<format>>.
+It may not be available on future netcdf implementations.
+.sp
+The current netcdf file <<format>> has three sections,
+the "header" section, the data section for fixed size variables, and
+the data section for variables which have an unlimited dimension (record
+variables).
+The header begins at the beginning of the file. The index
+(offset) of the beginning of the other two sections is contained in the
+header. Typically, there is no space between the sections. This causes
+copying overhead to accrue if one wishes to change the size of the
+sections,
+as may happen when changing names of things, text attribute values,
+adding
+attributes or adding variables. Also, for buffered i/o, there may be
+advantages
+to aligning sections in certain ways.
+.sp
+The minfree parameters allow one to control costs of future calls
+to FREF(redef), FREF(enddef) by requesting that ARG(minfree) bytes be
+available at the end of the section.
+The ARG(h_minfree) parameter sets the pad
+at the end of the "header" section. The ARG(v_minfree) parameter sets
+the pad at the end of the data section for fixed size variables.
+.sp
+The align parameters allow one to set the alignment of the beginning of
+the corresponding sections. The beginning of the section is rounded up
+to an index which is a multiple of the align parameter. The flag value
+MACRO(ALIGN_CHUNK) tells the library to use the chunksize (see above)
+as the align parameter.
+The ARG(v_align) parameter controls the alignment of the beginning of
+the data section for fixed size variables.
+The ARG(r_align) parameter controls the alignment of the beginning of
+the data section for variables which have an unlimited dimension (record
+variables).
+.sp
+The file <<format>> requires mod 4 alignment, so the align parameters
+are silently rounded up to multiples of 4. The usual call,
+CODE(FNAME(enddef)(NCID()))
+is equivalent to
+CODE(FNAME(_enddef)(NCID(), 0, 4, 0, 4)).
+.sp
+The file <<format>> does not contain a "record size" value, this is
+calculated from the sizes of the record variables. This unfortunate fact
+prevents us from providing minfree and alignment control of the
+"records"
+in a netcdf file. If you add a variable which has an unlimited
+dimension,
+the third section will always be copied with the new variable added.
+.HP
+FDECL(sync, (INCID()))
+.sp
+(Corresponds to FOLD(sync, snc) in version 2)
+.sp
+Unless the
+MACRO(SHARE)
+bit is set in
+FREF(open) or FREF(create),
+accesses to the underlying netCDF dataset are
+buffered by the library. This function synchronizes the state of
+the underlying dataset and the library.
+This is done automatically by
+FREF(close) and FREF(enddef).
+.HP
+FDECL(abort, (INCID()))
+.sp
+(Corresponds to FOLD(abort, abor) in version 2)
+.sp
+You don't need to call this function.
+This function is called automatically by
+FREF(close)
+if the netCDF was in <<define>> mode and something goes wrong with the commit.
+If the netCDF dataset isn't in <<define>> mode, then this function is equivalent to
+FREF(close).
+If it is called after
+FREF(redef),
+but before
+FREF(enddef),
+the new definitions are not committed and the dataset is closed.
+If it is called after
+FREF(create)
+but before
+FREF(enddef),
+the dataset disappears.
+.HP
+FDECL(close, (INCID()))
+.sp
+(Corresponds to
+FOLD(close, clos) in version 2)
+.sp
+Closes an open netCDF dataset.
+If the dataset is in <<define>> mode,
+FREF(enddef)
+will be called before closing.
+After a dataset is closed, its ID may be reassigned to another dataset.
+.HP
+FDECL(inq, (INCID(), ONDIMS(), ONVARS(),
+ONATTS(), OUNLIMDIMID()))
+.HP
+FDECL(inq_ndims, (INCID(), ONDIMS()))
+.HP
+FDECL(inq_nvars, (INCID(), ONVARS()))
+.HP
+FDECL(inq_natts, (INCID(), ONATTS()))
+.HP
+FDECL(inq_unlimdim, (INCID(), OUNLIMDIMID()))
+.sp
+(Replace FOLD(inquire, inq) in version 2)
+.sp
+Use these functions to find out what is in a netCDF dataset.
+Upon successful return,
+NDIMS() will contain  the
+number of dimensions defined for this netCDF dataset,
+NVARS() will contain the number of variables,
+NATTS() will contain the number of attributes, and
+UNLIMDIMID() will contain the
+dimension ID of the unlimited dimension if one exists, or
+ifelse(API,C, <<-1>>, <<0>>) otherwise.
+ifelse(API,C,
+<<If any of the
+return parameters is a NULL() pointer, then the corresponding information
+will not be returned; hence, no space need be allocated for it.>>)
+.HP
+FDECL(def_dim, (INCID(), INAME(), ILEN(), ODIMID()))
+.sp
+(Corresponds to FOLD(dimdef, ddef) in version 2)
+.sp
+Adds a new dimension to an open netCDF dataset, which must be 
+in <<define>> mode.
+NAME() is the dimension name.
+ifelse(API,C,dnl
+<<If DIMID() is not a NULL() pointer then upon successful completion >>)<<>>dnl
+DIMID() will contain the dimension ID of the newly created dimension.
+.HP
+FDECL(inq_dimid, (INCID(), INAME(), ODIMID()))
+.sp
+(Corresponds to FOLD(dimid, did) in version 2)
+.sp
+Given a dimension name, returns the ID of a netCDF dimension in DIMID().
+.HP
+FDECL(inq_dim, (INCID(), IDIMID(), ONAME(), OLEN()))
+.HP
+FDECL(inq_dimname, (INCID(), IDIMID(), ONAME()))
+.HP
+FDECL(inq_dimlen, (INCID(), IDIMID(), OLEN()))
+.sp
+(Replace FOLD(diminq, dinq) in version 2)
+.sp
+Use these functions to find out about a dimension.
+ifelse(API,C,
+<<If either the NAME()
+argument or LEN() argument is a NULL() pointer, then
+the associated information will not be returned.  Otherwise,>>)
+NAME() should be  big enough (MACRO(MAX_NAME))
+to hold the dimension name as the name will be copied into your storage.
+The length return parameter, LEN()
+will contain the size of the dimension.
+For the unlimited dimension, the returned length is the current
+maximum value used for writing into any of the variables which use
+the dimension.
+.HP
+FDECL(rename_dim, (INCID(), IDIMID(), INAME()))
+.sp
+(Corresponds to FOLD(dimrename, dren) in version 2)
+.sp
+Renames an existing dimension in an open netCDF dataset.
+If the new name is longer than the old name, the netCDF dataset must be in 
+<<define>> mode.
+You cannot rename a dimension to have the same name as another dimension.
+.HP
+FDECL(def_var, (INCID(), INAME(), IXTYPE(), INDIMS(), IDIMIDS(), OVARID()))
+.sp
+(Corresponds to FOLD(vardef, vdef) in version 2)
+.sp
+Adds a new variable to a netCDF dataset. The netCDF must be in <<define>> mode.
+ifelse(API,C, <<If not NULL(), then >>)dnl
+VARID() will be set to the netCDF variable ID.
+.HP
+FDECL(inq_varid, (INCID(), INAME(), OVARID()))
+.sp
+(Corresponds to FOLD(varid, vid) in version 2)
+.sp
+Returns the ID of a netCDF variable in VARID() given its name.
+.HP
+FDECL(inq_var, (INCID(), IVARID(), ONAME(), OXTYPE(), ONDIMS(), ODIMIDS(),
+ONATTS()))
+.HP
+FDECL(inq_varname, (INCID(), IVARID(), ONAME()))
+.HP
+FDECL(inq_vartype, (INCID(), IVARID(), OXTYPE()))
+.HP
+FDECL(inq_varndims, (INCID(), IVARID(), ONDIMS()))
+.HP
+FDECL(inq_vardimid, (INCID(), IVARID(), ODIMIDS()))
+.HP
+FDECL(inq_varnatts, (INCID(), IVARID(), ONATTS()))
+.sp
+(Replace FOLD(varinq, vinq) in version 2)
+.sp
+Returns information about a netCDF variable, given its ID.
+ifelse(API,C,
+<<If any of the
+return parameters (NAME(), XTYPE(), NDIMS(), DIMIDS(), or
+NATTS()) is a NULL() pointer, then the corresponding information
+will not be returned; hence, no space need be allocated for it.>>)
+.HP
+FDECL(rename_var, (INCID(), IVARID(), INAME()))
+.sp
+(Corresponds to FOLD(varrename, vren) in version 2)
+.sp
+Changes the name of a netCDF variable.
+If the new name is longer than the old name, the netCDF must be in <<define>> mode.
+You cannot rename a variable to have the name of any existing variable.
+FUNC_FAMILY(<<PUT_VAR>>)
+.sp
+(Replace FOLD(varput, vpt) in version 2)
+.sp
+Writes an entire netCDF variable (i.e. all the values).
+The netCDF dataset must be open and in data mode.  The type of the data is
+specified in the function name, and it is converted to the external type
+of the specified variable, if possible, otherwise an
+MACRO(ERANGE) error is returned.
+FUNC_FAMILY(<<GET_VAR>>)
+.sp
+(Replace FOLD(varget, vgt) in version 2)
+.sp
+Reads an entire netCDF variable (i.e. all the values).
+The netCDF dataset must be open and in data mode.  
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an MACRO(ERANGE) error is returned.
+FUNC_FAMILY(<<PUT_VAR1>>)
+.sp
+(Replace FOLD(varput1, vpt1) in version 2)
+.sp
+Puts a single data value into a variable at the position INDEX() of an
+open netCDF dataset that is in data mode.  The type of the data is
+specified in the function name, and it is converted to the external type
+of the specified variable, if possible, otherwise an MACRO(ERANGE)
+error is returned.
+FUNC_FAMILY(<<GET_VAR1>>)
+.sp
+(Replace FOLD(varget1, vgt1) in version 2)
+.sp
+Gets a single data value from a variable at the position INDEX()
+of an open netCDF dataset that is in data mode.  
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an MACRO(ERANGE) error is returned.
+FUNC_FAMILY(<<PUT_VARA>>)
+.sp
+(Replace FOLD(varput, vpt) in version 2)
+.sp
+Writes an array section of values into a netCDF variable of an open
+netCDF dataset, which must be in data mode.  The array section is specified
+by the START() and COUNT() vectors, which give the starting <<index>>
+and count of values along each dimension of the specified variable.
+The type of the data is
+specified in the function name and is converted to the external type
+of the specified variable, if possible, otherwise an MACRO(ERANGE)
+error is returned.
+FUNC_FAMILY(<<GET_VARA>>)
+.sp
+(Corresponds to FOLD(varget, vgt) in version 2)
+.sp
+Reads an array section of values from a netCDF variable of an open
+netCDF dataset, which must be in data mode.  The array section is specified
+by the START() and COUNT() vectors, which give the starting <<index>>
+and count of values along each dimension of the specified variable.
+The data is converted from the external type of the specified variable,
+if necessary, to the type specified in the function name.  If conversion is
+not possible, an MACRO(ERANGE) error is returned.
+FUNC_FAMILY(<<PUT_VARS>>)
+.sp
+(Corresponds to FOLD(varputg, vptg) in version 2)
+.sp
+These functions are used for \fIstrided output\fP, which is like the
+array section output described above, except that
+the sampling stride (the interval between accessed values) is
+specified for each dimension.
+For an explanation of the sampling stride
+vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+FUNC_FAMILY(<<GET_VARS>>)
+.sp
+(Corresponds to FOLD(vargetg, vgtg) in version 2)
+.sp
+These functions are used for \fIstrided input\fP, which is like the
+array section input described above, except that 
+the sampling stride (the interval between accessed values) is
+specified for each dimension.
+For an explanation of the sampling stride
+vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+FUNC_FAMILY(<<PUT_VARM>>)
+.sp
+(Corresponds to FOLD(varputg, vptg) in version 2)
+.sp
+These functions are used for \fImapped output\fP, which is like
+strided output described above, except that an additional <<index>> mapping
+vector is provided to specify the in-memory arrangement of the data
+values.
+For an explanation of the <<index>>
+mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+FUNC_FAMILY(<<GET_VARM>>)
+.sp
+(Corresponds to FOLD(vargetg, vgtg) in version 2)
+.sp
+These functions are used for \fImapped input\fP, which is like
+strided input described above, except that an additional <<index>> mapping
+vector is provided to specify the in-memory arrangement of the data
+values.
+For an explanation of the <<index>>
+mapping vector, see COMMON ARGUMENTS DESCRIPTIONS below.
+FUNC_FAMILY(<<APUT>>)
+.sp
+(Replace FOLD(attput, apt) in version 2)
+.sp
+Unlike variables, attributes do not have 
+separate functions for defining and writing values.
+This family of functions defines a new attribute with a value or changes
+the value of an existing attribute.
+If the attribute is new, or if the space required to
+store the attribute value is greater than before,
+the netCDF dataset must be in <<define>> mode.
+The parameter LEN() is the number of values from OUT() to transfer.
+It is often one, except that for
+FREF(put_att_text) it will usually be
+ifelse(API,C, <<CODE(strlen(OUT())).>>, <<CODE(len_trim(OUT())).>>)
+.sp
+For these functions, the type component of the function name refers to
+the in-memory type of the value, whereas the XTYPE() argument refers to the
+external type for storing the value.  An MACRO(ERANGE)
+error results if
+a conversion between these types is not possible.  In this case the value
+is represented with the appropriate fill-value for the associated 
+external type.
+.HP
+FDECL(inq_attname, (INCID(), IVARID(), IATTNUM(), ONAME()))
+.sp
+(Corresponds to FOLD(attname, anam) in version 2)
+.sp
+Gets the
+name of an attribute, given its variable ID and attribute number.
+This function is useful in generic applications that
+need to get the names of all the attributes associated with a variable,
+since attributes are accessed by name rather than number in all other
+attribute functions.  The number of an attribute is more volatile than
+the name, since it can change when other attributes of the same variable
+are deleted.  The attributes for each variable are numbered
+from ifelse(API,C,0,1) (the first attribute) to
+NVATTS()<<>>ifelse(API,C,-1),
+where NVATTS() is
+the number of attributes for the variable, as returned from a call to
+FREF(inq_varnatts).
+ifelse(API,C,
+<<If the NAME() parameter is a NULL() pointer, no name will be
+returned and no space need be allocated.>>)
+.HP
+FDECL(inq_att, (INCID(), IVARID(), INAME(), OXTYPE(), OLEN()))
+.HP
+FDECL(inq_attid, (INCID(), IVARID(), INAME(), OATTNUM()))
+.HP
+FDECL(inq_atttype, (INCID(), IVARID(), INAME(), OXTYPE()))
+.HP
+FDECL(inq_attlen, (INCID(), IVARID(), INAME(), OLEN()))
+.sp
+(Corresponds to FOLD(attinq, ainq) in version 2)
+.sp
+These functions return information about a netCDF attribute,
+given its variable ID and name.  The information returned is the
+external type in XTYPE()
+and the number of elements in the attribute as LEN().
+ifelse(API,C,
+<<If any of the return arguments is a NULL() pointer,
+the specified information will not be returned.>>)
+.HP
+FDECL(copy_att, (INCID(), IVARIDIN(), INAME(), INCIDOUT(), IVARIDOUT()))
+.sp
+(Corresponds to FOLD(attcopy, acpy) in version 2)
+.sp
+Copies an
+attribute from one netCDF dataset to another.  It can also be used to
+copy an attribute from one variable to another within the same netCDF.
+NCIDIN() is the netCDF ID of an input netCDF dataset from which the
+attribute will be copied.
+VARIDIN()
+is the ID of the variable in the input netCDF dataset from which the
+attribute will be copied, or MACRO(GLOBAL)
+for a global attribute.
+NAME()
+is the name of the attribute in the input netCDF dataset to be copied.
+NCIDOUT()
+is the netCDF ID of the output netCDF dataset to which the attribute will be 
+copied.
+It is permissible for the input and output netCDF ID's to be the same.  The
+output netCDF dataset should be in <<define>> mode if the attribute to be
+copied does not already exist for the target variable, or if it would
+cause an existing target attribute to grow.
+VARIDOUT()
+is the ID of the variable in the output netCDF dataset to which the attribute will
+be copied, or MACRO(GLOBAL) to copy to a global attribute.
+.HP
+FDECL(rename_att, (INCID(), IVARID(), INAME(), INEWNAME()))
+.sp
+(Corresponds to FOLD(attrename, aren)
+.sp
+Changes the
+name of an attribute.  If the new name is longer than the original name,
+the netCDF must be in <<define>> mode.  You cannot rename an attribute to
+have the same name as another attribute of the same variable.
+NAME() is the original attribute name.
+NEWNAME()
+is the new name to be assigned to the specified attribute.  If the new name
+is longer than the old name, the netCDF dataset must be in <<define>> mode.
+.HP
+FDECL(del_att, (INCID(), IVARID(), INAME()))
+.sp
+(Corresponds to FOLD(attdel, adel) in version 2)
+.sp
+Deletes an attribute from a netCDF dataset.  The dataset must be in
+<<define>> mode.
+FUNC_FAMILY(<<AGET>>)
+.sp
+(Replace FOLD(attget, agt) in version 2)
+.sp
+Gets the value(s) of a netCDF attribute, given its
+variable ID and name.  Converts from the external type to the type
+specified in
+the function name, if possible, otherwise returns an MACRO(ERANGE)
+error.
+All elements of the vector of attribute
+values are returned, so you must allocate enough space to hold
+them.  If you don't know how much space to reserve, call
+FREF(inq_attlen)
+first to find out the length of the attribute.
+.SH "COMMON ARGUMENT DESCRIPTIONS"
+.LP
+In this section we <<define>> some common arguments which are used in the 
+"FUNCTION DESCRIPTIONS" section.
+.TP
+INCID()
+is the netCDF ID returned from a previous, successful call to
+FREF(open) or FREF(create)
+.TP
+ONAME()
+is the name of a dimension, variable, or attribute.
+It shall begin with an alphabetic character, followed by
+zero or more alphanumeric characters including the underscore
+(`_') or hyphen (`-').  Case is significant.
+ifelse(API,C,<<As an input argument, 
+it shall be a pointer to a 0-terminated string; as an output argument, it 
+shall be the address of a buffer in which to hold such a string.>>)
+The maximum allowable number of characters 
+ifelse(API,C,(excluding the terminating 0)) is MACRO(MAX_NAME).
+Names that begin with an underscore (`_') are reserved for use
+by the netCDF interface.
+.TP
+IXTYPE()
+specifies the external data type of a netCDF variable or attribute and
+is one of the following:
+MACRO(BYTE), MACRO(CHAR), MACRO(SHORT), MACRO(INT), 
+MACRO(FLOAT), or MACRO(DOUBLE).
+These are used to specify 8-bit integers,
+characters, 16-bit integers, 32-bit integers, 32-bit IEEE floating point
+numbers, and 64-bit IEEE floating-point numbers, respectively.
+ifelse(API,C,
+<<(MACRO(INT) corresponds to MACRO(LONG) in version 2, to specify a
+32-bit integer).>>)
+.TP
+ODIMIDS()
+is a vector of dimension ID's and defines the shape of a netCDF variable.
+The size of the vector shall be greater than or equal to the
+rank (i.e. the number of dimensions) of the variable (NDIMS()).
+The vector shall be ordered by the speed with which a dimension varies:
+DIMIDS()<<>>ifelse(API,C,<<[NDIMS()-1]>>,<<(1)>>)
+shall be the dimension ID of the most rapidly
+varying dimension and
+DIMIDS()<<>>ifelse(API,C,<<[0]>>,<<(NDIMS())>>)
+shall be the dimension ID of the most slowly
+varying dimension.
+The maximum possible number of
+dimensions for a variable is given by the symbolic constant
+MACRO(MAX_VAR_DIMS).
+.TP
+IDIMID()
+is the ID of a netCDF dimension.
+netCDF dimension ID's are allocated sequentially from the 
+ifelse(API,C,non-negative, positive)
+integers beginning with ifelse(API,C,0,1).
+.TP
+INDIMS()
+is either the total number of dimensions in a netCDF dataset or the rank
+(i.e. the number of dimensions) of a netCDF variable.
+The value shall not be negative or greater than the symbolic constant 
+MACRO(MAX_VAR_DIMS).
+.TP
+IVARID()
+is the ID of a netCDF variable or (for the attribute-access functions) 
+the symbolic constant
+MACRO(GLOBAL),
+which is used to reference global attributes.
+netCDF variable ID's are allocated sequentially from the 
+ifelse(API,C,non-negative,positive)
+integers beginning with ifelse(API,C,0,1).
+.TP
+ONATTS()
+is the number of global attributes in a netCDF dataset  for the
+FREF(inquire)
+function or the number
+of attributes associated with a netCDF variable for the
+FREF(varinq)
+function.
+.TP
+IINDEX()
+specifies the indicial coordinates of the netCDF data value to be accessed.
+The indices start at ifelse(API,C,0,1);
+thus, for example, the first data value of a
+two-dimensional variable is ifelse(API,C,(0,0),(1,1)).
+The size of the vector shall be at least the rank of the associated
+netCDF variable and its elements shall correspond, in order, to the
+variable's dimensions.
+.TP
+ISTART()
+specifies the starting point
+for accessing a netCDF variable's data values
+in terms of the indicial coordinates of 
+the corner of the array section.
+The indices start at ifelse(API,C,0,1);
+thus, the first data
+value of a variable is ifelse(API,C,(0, 0, ..., 0),(1, 1, ..., 1)).
+The size of the vector shall be at least the rank of the associated
+netCDF variable and its elements shall correspond, in order, to the
+variable's dimensions.
+.TP
+ICOUNT()
+specifies the number of indices selected along each dimension of the
+array section.
+Thus, to access a single value, for example, specify COUNT() as
+(1, 1, ..., 1).
+Note that, for strided I/O, this argument must be adjusted
+to be compatible with the STRIDE() and START() arguments so that 
+the interaction of the
+three does not attempt to access an invalid data co-ordinate.
+The elements of the
+COUNT() vector correspond, in order, to the variable's dimensions.
+.TP
+ISTRIDE()
+specifies the sampling interval along each dimension of the netCDF
+variable.   The elements of the stride vector correspond, in order,
+to the netCDF variable's dimensions (ARG(stride)<<>>ifelse(API,C,[0],<<(1)>>))
+gives the sampling interval along the most ifelse(API,C,slowly,rapidly) 
+varying dimension of the netCDF variable).  Sampling intervals are
+specified in type-independent units of elements (a value of 1 selects
+consecutive elements of the netCDF variable along the corresponding
+dimension, a value of 2 selects every other element, etc.).
+ifelse(API,C,<<A NULL() stride argument is treated as (1, 1, ... , 1).>>)
+.TP
+IMAP()
+specifies the mapping between the dimensions of a netCDF variable and
+the in-memory structure of the internal data array.  The elements of
+the <<index>> mapping vector correspond, in order, to the netCDF variable's
+dimensions (ARG(imap)<<>>ifelse(API,C,[0],<<(1)>>) gives the distance
+between elements of the internal array corresponding to the most
+ifelse(API,C,slowly,rapidly) varying dimension of the netCDF variable).
+Distances between elements are specified in type-independent units of
+elements (the distance between internal elements that occupy adjacent
+memory locations is 1 and not the element's byte-length as in netCDF 2).
+ifelse(API,C,<<A NULL() pointer means the memory-resident values have
+the same structure as the associated netCDF variable.>>)
+.SH "VARIABLE PREFILLING"
+.LP
+By default, the netCDF interface sets the values of
+all newly-defined variables of finite length (i.e. those that do not have
+an unlimited, dimension) to the type-dependent fill-value associated with each 
+variable.  This is done when FREF(enddef)
+is called.  The
+fill-value for a variable may be changed from the default value by
+defining the attribute `CODE(_FillValue)' for the variable.  This
+attribute must have the same type as the variable and be of length one.
+.LP
+Variables with an unlimited dimension are also prefilled, but on
+an `as needed' basis.  For example, if the first write of such a
+variable is to position 5, then
+positions
+ifelse(API,C,0 through 4, 1 through 4)
+(and no others)
+would be set to the fill-value at the same time.
+.LP
+This default prefilling of data values may be disabled by
+or'ing the
+MACRO(NOFILL)
+flag into the mode parameter of FREF(open) or FREF(create),
+or, by calling the function FREF(set_fill)
+with the argument MACRO(NOFILL).
+For variables that do not use the unlimited dimension,
+this call must
+be made before
+FREF(enddef).
+For variables that
+use the unlimited dimension, this call
+may be made at any time.
+.LP
+One can obtain increased performance of the netCDF interface by using 
+this feature, but only at the expense of requiring the application to set
+every single data value.  The performance
+enhancing behavior of this function is dependent on the particulars of
+the implementation and dataset <<format>>.
+The flag value controlled by FREF(set_fill)
+is per netCDF ID,
+not per variable or per write. 
+Allowing this to change affects the degree to which
+a program can be effectively parallelized.
+Given all of this, we state that the use
+of this feature may not be available (or even needed) in future
+releases. Programmers are cautioned against heavy reliance upon this
+feature.
+.HP
+FDECL(setfill, (INCID(), IFILLMODE(), OOLDFILLMODE()))
+ifelse(API,C,
+<<.sp
+(Corresponds to FOLD(setfill) in version 2)>>)
+.sp
+Determines whether or not variable prefilling will be done (see 
+above).
+The netCDF dataset shall be writable.
+FILLMODE() is either MACRO(FILL)
+to enable prefilling (the
+default) or MACRO(NOFILL)
+to disable prefilling.
+This function returns the previous setting in OLDFILLMODE().
+.SH "MPP FUNCTION DESCRIPTIONS"
+.LP
+Additional functions for use on SGI/Cray MPP machines (_CRAYMPP).
+These are used to set and inquire which PE is the base for MPP
+for a particular netCDF. These are only relevant when
+using the SGI/Cray ``global''
+Flexible File I/O layer and desire to have
+only a subset of PEs to open the specific netCDF file.
+For technical reasons, these functions are available on all platforms.
+On a platform other than SGI/Cray MPP, it is as if
+only processor available were processor 0.
+.LP
+To use this feature, you need to specify a communicator group and call
+CODE(glio_group_mpi(\|)) or CODE(glio_group_shmem(\|)) prior to the netCDF
+FREF(open) and FREF(create) calls.
+.HP
+FDECL(_create_mp, (IPATH(), ICMODE(), IINITSIZE(), IPE(), OCHUNKSIZE(), ONCID()))
+.sp
+Like FREF(_create) but allows the base PE to be set.
+.sp
+The argument ARG(pe) sets the base PE at creation time. In the MPP
+environment, FREF(_create) and FREF(create) set the base PE to processor
+zero by default.
+.HP
+FDECL(_open_mp, (IPATH(), IMODE(), IPE(), OCHUNKSIZE(), ONCID()))
+.sp
+Like FREF(_open) but allows the base PE to be set.
+The argument ARG(pe) sets the base PE at creation time. In the MPP
+environment, FREF(_open) and FREF(open) set the base PE to processor
+zero by default.
+.HP
+FDECL(inq_base_pe, (INCID(), OPE()))
+.sp
+Inquires of the netCDF dataset which PE is being used as the base for MPP use.
+This is safe to use at any time.
+.HP
+FDECL(set_base_pe, (INCID(), IPE()))
+.sp
+Resets the base PE for the netCDF dataset.
+Only perform this operation when the affected communicator group
+synchronizes before and after the call.
+This operation is very risky and should only be contemplated
+under only the most extreme cases.
+.SH "ENVIRONMENT VARIABLES"
+.TP 4
+.B NETCDF_FFIOSPEC
+Specifies the Flexible File I/O buffers for netCDF I/O when executing
+under the UNICOS operating system (the variable is ignored on other
+operating systems).
+An appropriate specification can greatly increase the efficiency of 
+netCDF I/O -- to the extent that it can actually surpass FORTRAN binary 
+I/O.
+This environment variable has been made a little more generalized,
+such that other FFIO option specifications can now be added.
+The default specification is \fBbufa:336:2\fP,
+unless a current FFIO specification is in operation,
+which will be honored.
+See UNICOS Flexible File I/O for more information.
+.SH "MAILING-LISTS"
+.LP
+Both a mailing list and a digest are available for
+discussion of the netCDF interface and announcements about netCDF bugs,
+fixes, and enhancements.
+To begin or change your subscription to either the mailing-list or the
+digest, send one of the following in the body (not
+the subject line) of an email message to "majordomo@unidata.ucar.edu".
+Use your email address in place of \fIjdoe@host.inst.domain\fP.
+.sp
+To subscribe to the netCDF mailing list:
+.RS
+\fBsubscribe netcdfgroup \fIjdoe@host.inst.domain\fR
+.RE
+To unsubscribe from the netCDF mailing list:
+.RS
+\fBunsubscribe netcdfgroup \fIjdoe@host.inst.domain\fR
+.RE
+To subscribe to the netCDF digest:
+.RS
+\fBsubscribe netcdfdigest \fIjdoe@host.inst.domain\fR
+.RE
+To unsubscribe from the netCDF digest:
+.RS
+\fBunsubscribe netcdfdigest \fIjdoe@host.inst.domain\fR
+.RE
+To retrieve the general introductory information for the mailing list:
+.RS
+\fBinfo netcdfgroup\fR
+.RE
+To get a synopsis of other majordomo commands:
+.RS
+\fBhelp\fR
+.RE
+.SH "SEE ALSO"
+.LP
+.BR ncdump (1),
+.BR ncgen (1),
+.BR netcdf (3<<>>ifelse(API,C,,f)).
+.LP
+\fInetCDF User's Guide\fP, published
+by the Unidata Program Center, University Corporation for Atmospheric
+Research, located in Boulder, Colorado.
Index: /branches/SDM_SciDAC/man/Makefile
===================================================================
--- /branches/SDM_SciDAC/man/Makefile (revision 2)
+++ /branches/SDM_SciDAC/man/Makefile (revision 2)
@@ -0,0 +1,19 @@
+# $Id$
+#
+#	Makefile for netcdf man
+#
+
+include ../macros.make
+
+PACKING_LIST	= Makefile	\
+		  netcdf.m4
+
+all:
+
+test:
+
+install:
+
+uninstall:
+
+include ../rules.make
Index: /branches/SDM_SciDAC/Makefile
===================================================================
--- /branches/SDM_SciDAC/Makefile (revision 2)
+++ /branches/SDM_SciDAC/Makefile (revision 2)
@@ -0,0 +1,145 @@
+# $Id$
+
+
+include macros.make
+
+
+PACKAGE		= parallel-netcdf
+SUBDIRS		= src/lib man
+DIST_GARBAGE	= \
+		config.cache	\
+		config.status	
+PACKING_LIST	= \
+		Makefile	\
+		aclocal.m4	\
+		configure	\
+		configure.in	\
+		macros.make.in	\
+		macros.make.def	\
+		rules.make
+
+
+all:		src/lib/all
+
+install:	src/lib/install
+
+uninstall:	src/lib/uninstall
+
+clean:		src/lib/clean 
+
+distclean:	src/lib/distclean \
+		clean_macros 
+
+clean_macros:
+	-cp macros.make.def macros.make
+
+src/lib/all	\
+src/lib/test	\
+src/lib/install	\
+src/lib/uninstall	\
+src/lib/clean	\
+src/lib/distclean	\
+:
+	@subdir=`echo $@ | sed 's,/.*,,'`; \
+	target=`echo $@ | sed 's,.*/,,'`; \
+	$(MAKE) SUBDIR=$$subdir TGET=$$target subdir_target
+
+subdir_target:
+	@echo ""
+	@cd $(SUBDIR) && \
+	    echo "Making \`$(TGET)' in directory `pwd`" && \
+	    echo "" && \
+	    $(MAKE) $(TGET) || exit 1
+	@echo ""
+	@echo "Returning to directory `pwd`"
+	@echo ""
+
+install:	whatis
+whatis:		$(MANDIR)/$(WHATIS)
+$(MANDIR)/$(WHATIS):	$(MANDIR)
+	$(MAKEWHATIS_CMD)
+uninstall:
+	rm -f $(MANDIR)/$(WHATIS)
+
+
+################################################################################
+# Distribution:
+
+# The following rule checks to see that were on the right system.  If we're
+# not, then the distribution mightn't contain the intended ncgen(1) (not
+# to mention that dvips(1) is necessary for building the C++ User's Guide).
+#
+check_system:	FORCE
+	@case "$(OVERRIDE)" in \
+	'') case `uname -sr` in \
+	    'SunOS 5'*) \
+		exit 0;; \
+	    *)  echo 1>&2 "Error: Not on a SunOS 5 system."; \
+		echo 1>&2 "Set macro OVERRIDE to override."; \
+		exit 1;; \
+	    esac;; \
+	*) exit 0;; \
+	esac
+
+# Make a compressed, tar(1) file of the source distribution in the current 
+# directory.
+#
+tar.Z:		check_system FORCE
+	@version=`cat VERSION`; \
+	    $(MAKE) $(MFLAGS) $(PACKAGE)-$$version.tar.Z VERSION=$$version
+
+$(PACKAGE)-$(VERSION).tar.Z:	ensure_manifest MANIFEST
+	id=$(PACKAGE)-$(VERSION) \
+	&& rm -rf $$id \
+	&& mkdir $$id \
+	&& ln -s .. $$id/src \
+	&& tar $(TARFLAGS) - `sed "s|^|$$id/src/|" MANIFEST` | compress > $@ \
+	&& rm -r $$id
+
+MANIFEST:	FORCE
+	$(MAKE) MANIFEST.echo >$@
+
+# Make a compressed, tar(1) file of the source distribution in the
+# appropriate FTP directory.
+#
+# NOTE: Making "ftp" will cause the "tar.Z" file to be made even if it
+# already exists.  This is because the MANIFEST file upon which it
+# depends must be remade every time.  This is not a waste of time,
+# however, if the "tar.Z" target is made in private directories and the
+# "ftp" target is made in the "/upc/$(PACKAGE)/build/" directory.
+#
+ftp:		check_system FORCE
+	version=`cat VERSION`; \
+	$(MAKE) $(MFLAGS) $(FTPDIR)/$(PACKAGE)-$$version.tar.Z \
+	    VERSION=$$version; \
+	test -r $(FTPDIR)/$(PACKAGE).tar.Z || exit 0; \
+	    cd $(FTPDIR) || exit 1;
+
+$(FTPDIR)/$(PACKAGE)-$(VERSION).tar.Z:	$(PACKAGE)-$(VERSION).tar.Z
+	rm -f $@
+	cp $(PACKAGE)-$(VERSION).tar.Z $@ 
+	chmod u+rw,g+rw,o=r $@
+
+# Make a compressed, tar(1) file of the binary distribution in the 
+# appropriate FTP directory.
+#
+binftp:		FORCE
+	version=`cat VERSION`; \
+	$(MAKE) $(MFLAGS) $(FTPBINDIR)/$(PACKAGE)-$$version.tar.Z \
+	    VERSION=$$version
+ftpbin:		binftp
+
+$(FTPBINDIR)/$(PACKAGE)-$(VERSION).tar.Z:
+	rm -f $@
+	id=$(PACKAGE)-$(VERSION) \
+	&& rm -f $$id \
+	&& ln -s $(prefix) $$id \
+	&& tar $(TARFLAGS) - README $$id/bin $$id/include \
+	    $$id/lib $$id/man | compress > $@ \
+	&& rm $$id
+	chmod u+rw,g+rw,o=r $@
+	test -r $(FTPBINDIR)/$(PACKAGE).tar.Z || exit 0; \
+	    cd $(FTPBINDIR) || exit 1;
+
+
+include rules.make
Index: /branches/SDM_SciDAC/aclocal.m4
===================================================================
--- /branches/SDM_SciDAC/aclocal.m4 (revision 2)
+++ /branches/SDM_SciDAC/aclocal.m4 (revision 2)
@@ -0,0 +1,1291 @@
+dnl $Id$
+dnl UD macros for netcdf configure
+
+
+dnl Convert a string to all uppercase.
+dnl
+define([uppercase],
+[translit($1, abcdefghijklmnopqrstuvwxyz, ABCDEFGHIJKLMNOPQRSTUVWXYZ)])
+
+dnl
+dnl Check for an m4(1) preprocessor utility.
+dnl
+AC_DEFUN(UD_PROG_M4,
+[
+    AC_CHECKING(for m4 preprocessor)
+    case "${M4-unset}" in
+	unset) AC_CHECK_PROGS(M4, m4 gm4, m4) ;;
+	*) AC_CHECK_PROGS(M4, $M4 m4 gm4, m4) ;;
+    esac
+    AC_MSG_CHECKING(m4 flags)
+    case "${M4FLAGS-unset}" in
+	unset) M4FLAGS=-B10000 ;;
+    esac
+    AC_MSG_RESULT($M4FLAGS)
+    AC_SUBST(M4FLAGS)
+])
+
+dnl
+dnl Check for an ar(1) utility.
+dnl
+AC_DEFUN(UD_PROG_AR,
+[
+    AC_CHECKING(for ar utility)
+    case "${AR-unset}" in
+	unset) AC_CHECK_PROGS(AR, ar, ar) ;;
+	*) AC_CHECK_PROGS(AR, $AR ar, ar) ;;
+    esac
+    AC_MSG_CHECKING(ar flags)
+    case "${ARFLAGS-unset}" in
+	unset) ARFLAGS=cru ;;
+    esac
+    AC_MSG_RESULT($ARFLAGS)
+    AC_SUBST(ARFLAGS)
+])
+
+dnl
+dnl Check for an nm(1) utility.
+dnl
+AC_DEFUN(UD_PROG_NM,
+[
+    AC_CHECKING(for nm utility)
+    case "${NM-unset}" in
+	unset) AC_CHECK_PROGS(NM, nm, nm) ;;
+	*) AC_CHECK_PROGS(NM, $NM nm, nm) ;;
+    esac
+    AC_MSG_CHECKING(nm flags)
+    case "${NMFLAGS-unset}" in
+	unset) NMFLAGS= ;;
+    esac
+    AC_MSG_RESULT($NMFLAGS)
+    AC_SUBST(NMFLAGS)
+])
+
+dnl
+dnl Set the top-level source-directory.
+dnl
+AC_DEFUN(UD_SRCDIR,
+[
+    AC_CHECKING(for top-level source-directory)
+    SRCDIR=`(cd $srcdir && pwd)`
+    AC_MSG_RESULT($SRCDIR)
+    AC_SUBST(SRCDIR)
+])
+
+dnl
+dnl Check for a Standard C compiler.  Prefer a native one over the
+dnl GNU one to reduce the chance that the environment variable LIBS
+dnl will have to be set to reference the GNU C runtime library.
+dnl
+AC_DEFUN(UD_PROG_CC,
+[
+    # Because we must have a C compiler, we treat an unset CC
+    # the same as an empty CC.
+    case "${CC}" in
+	'')
+	    case `uname` in
+		ULTRIX)
+		    # The native ULTRIX C compiler isn't standard.
+		    ccs='gcc cc'
+		    ;;
+		*)
+		    # xlc is before c89 because AIX's sizeof(long long)
+		    # differs between the two.
+		    #
+		    ccs='xlc c89 acc cc gcc'
+		    ;;
+	    esac
+	    for cc in $ccs; do
+		AC_CHECK_PROG(CC, $cc, $cc)
+		case "$CC" in
+		    '') ;;
+		    *)  break
+			;;
+		esac
+	    done
+	    case "${CC}" in
+		'')
+		    AC_MSG_ERROR("Could not find C compiler")
+		    ;;
+	    esac
+	    ;;
+    esac
+    #
+    # On some systems, a discovered compiler nevertheless won't
+    # work (due to licensing, for example); thus, we check the
+    # compiler with a test program.
+    # 
+    AC_MSG_CHECKING(C compiler \"$CC\")
+    AC_TRY_COMPILE(, ,
+	AC_MSG_RESULT(works),
+	AC_MSG_RESULT(failed to compile test program))
+    AC_SUBST(CC)
+    case "$CC" in
+	*gcc*)
+	    GCC=yes		# Expected by autoconf(1) macros
+	    ;;
+    esac
+    case `uname -sr` in
+	'HP-UX A.09'*)
+	    AC_DEFINE(_HPUX_SOURCE)
+	    ;;
+    esac
+])
+
+dnl
+dnl Check for a C++ compiler.  Prefer a native one over the
+dnl GNU one to reduce the chance that the environment variable LIBS
+dnl will have to be set to reference the GNU C runtime library.
+dnl
+AC_DEFUN(UD_PROG_CXX,
+[
+    case "${CXX-unset}" in
+	unset)
+	    case `uname` in
+		AIX)
+		    preferred_cxx='xlC'
+		    ;;
+	    esac
+	    possible_cxxs="${preferred_cxx} CC cxx c++ g++ gcc"
+	    ;;
+	'') AC_MSG_WARN("Empty CXX variable")
+	    possible_cxxs=
+	    ;;
+	*)  possible_cxxs=$CXX
+	    ;;
+    esac
+    case "${possible_cxxs}" in
+	'') CXX=
+	    ;;
+	*)  AC_LANG_SAVE()
+	    AC_LANG_CPLUSPLUS()
+	    for cxx in $possible_cxxs; do
+		AC_CHECK_PROG(CXX, $cxx, $cxx)
+		case "$CXX" in
+		    '') ;;
+		    *)  # On some systems, a discovered compiler nevertheless
+			# won't work (because it's a script to a non-existant
+			# executable, for example); thus, we check the
+			# compiler with a test program.  We also test
+			# for <iostream.h> and the standard C++ library
+			# because we need these to work.
+			# 
+			AC_MSG_CHECKING(C++ compiler \"$CXX\")
+			AC_TRY_RUN(
+ 			    [
+				#include <iostream.h>
+				int main() {
+				    cout << "";
+				    return 0;
+				}
+			    ],
+			    [
+				AC_MSG_RESULT(works)
+				break
+			    ],
+			    [
+				AC_MSG_WARN($CXX failed on test program)
+				CXX=
+				unset ac_cv_prog_CXX
+			    ])
+			;;
+		esac
+	    done
+	    AC_LANG_RESTORE()
+	    case "${CXX}" in
+		'') AC_MSG_WARN("Could not find working C++ compiler")
+		    AC_MSG_WARN(Setting CXX to the empty string)
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${CXX}" in
+	'') AC_MSG_WARN(The C++ interface will not be built)
+	    ;;
+    esac
+    AC_SUBST(CXX)
+    case `uname` in
+	'HP-UX A.09'*)
+	    AC_DEFINE(_HPUX_SOURCE)
+	    ;;
+    esac
+])
+
+
+dnl
+dnl like AC_LONG_DOUBLE, except checks for 'long long'
+dnl
+AC_DEFUN(UD_C_LONG_LONG,
+[AC_MSG_CHECKING(for long long)
+AC_CACHE_VAL(ac_cv_c_long_long,
+[if test "$GCC" = yes; then
+  ac_cv_c_long_long=yes
+else
+AC_TRY_RUN([int main() {
+long long foo = 0;
+exit(sizeof(long long) < sizeof(long)); }],
+ac_cv_c_long_long=yes, ac_cv_c_long_long=no, :)
+fi])dnl
+AC_MSG_RESULT($ac_cv_c_long_long)
+if test $ac_cv_c_long_long = yes; then
+  AC_DEFINE(HAVE_LONG_LONG)
+fi
+])
+
+dnl UD_CHECK_SIZEOF(TYPE)
+AC_DEFUN(UD_CHECK_SIZEOF,
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $1)
+AC_CACHE_VAL(AC_CV_NAME,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+main()
+{
+  FILE *f=fopen("conftestval", "w");
+  if (!f) exit(1);
+  fprintf(f, "%d\n", sizeof($1));
+  exit(0);
+}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, AC_CV_NAME=0)])dnl
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME)
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
+
+
+dnl 
+dnl UD_CHECK_IEEE
+dnl If the 'double' is not an IEEE double
+dnl or the 'float' is not and IEEE single,
+dnl define NO_IEEE_FLOAT
+dnl
+AC_DEFUN(UD_CHECK_IEEE,
+[
+AC_MSG_CHECKING(for IEEE floating point format)
+AC_TRY_RUN([#ifndef NO_FLOAT_H
+#include <float.h>
+#endif
+
+#define EXIT_NOTIEEE	1
+#define EXIT_MAYBEIEEE	0
+
+int
+main()
+{
+#if	defined(FLT_RADIX)	&& FLT_RADIX != 2
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MAX_EXP)	&& DBL_MAX_EXP != 1024
+		return EXIT_NOTIEEE;
+#elif	defined(DBL_MANT_DIG)	&& DBL_MANT_DIG != 53
+		return EXIT_NOTIEEE;
+#elif 	defined(FLT_MAX_EXP)	&& !(FLT_MAX_EXP == 1024 || FLT_MAX_EXP == 128)
+		return EXIT_NOTIEEE;
+#elif	defined(FLT_MANT_DIG)	&& !(FLT_MANT_DIG == 53 || FLT_MANT_DIG == 24)
+		return EXIT_NOTIEEE;
+#else
+	/* (assuming eight bit char) */
+	if(sizeof(double) != 8)
+		return EXIT_NOTIEEE;
+	if(!(sizeof(float) == 4 || sizeof(float) == 8))
+		return EXIT_NOTIEEE;
+
+	return EXIT_MAYBEIEEE;
+#endif
+}],ac_cv_c_ieeefloat=yes, ac_cv_c_ieeefloat=no, :)
+AC_MSG_RESULT($ac_cv_c_ieeefloat)
+if test $ac_cv_c_ieeefloat = no; then
+  AC_DEFINE(NO_IEEE_FLOAT)
+fi
+])
+
+dnl Check for utility for generating makefile dependencies.
+dnl Should only be used at the UPC.
+dnl
+AC_DEFUN(UD_PROG_CC_MAKEDEPEND,
+[
+    AC_MSG_CHECKING(how to make dependencies)
+    case `uname -s` in
+	IRIX*|OSF1)
+	    CC_MAKEDEPEND='cc -M'
+	    ;;
+	SunOS)
+	    case `uname -r` in
+		4*)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		5*|*)
+		    CC_MAKEDEPEND='cc -xM'
+		    ;;
+	    esac
+	    ;;
+	ULTRIX)
+	    case `uname -m` in
+		RISC)
+		    CC_MAKEDEPEND='cc -M'
+		    ;;
+		VAX)	# Can't handle prototypes in netcdf.h
+		    ;;
+	    esac
+	    ;;
+	AIX)	# Writes to .u files rather than standard out
+	    ;;
+	HP-UX)	# Writes escaped newlines to standard error
+	    ;;
+    esac
+    case "${CC_MAKEDEPEND}" in
+	'')
+	    CC_MAKEDEPEND=false
+	    ;;
+    esac
+    AC_MSG_RESULT($CC_MAKEDEPEND)
+    AC_SUBST(CC_MAKEDEPEND)
+])
+
+
+dnl Check for Fortran-90 compiler.
+dnl
+AC_DEFUN(UD_PROG_F90,
+[
+    case "${F90+set}" in
+	set)
+	    AC_MSG_CHECKING(user-defined Fortran-90 compiler \"$F90\")
+	    cat <<EOF >conftest.f90
+		subroutine foo(bar)
+		integer, intent(in) :: bar
+		end subroutine foo
+EOF
+	    doit='$F90 -c ${F90FLAGS} conftest.f90'
+	    if AC_TRY_EVAL(doit); then
+		AC_MSG_RESULT(works)
+	    else
+		AC_MSG_RESULT(failed to compile test program)
+		unset F90
+	    fi
+	    rm -f conftest.*
+	    ;;
+	*)
+	    case "${FC+set}" in
+		set)
+		    F90=$FC
+		    F90FLAGS="${F90FLAGS-${FFLAGS--O}}"
+		    F90LIBS="${F90LIBS-${FLIBS}}"
+		    cat <<EOF >conftest.f90
+			program foo
+			call bar(1)
+			end program foo
+			subroutine bar(bof)
+			integer, intent(in) :: bof
+			end subroutine bar
+EOF
+		    AC_MSG_CHECKING(\"$F90\" as Fortran-90 compiler)
+		    doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}'
+		    if AC_TRY_EVAL(doit); then
+			doit=./conftest
+			if AC_TRY_EVAL(doit); then
+			    AC_MSG_RESULT(works)
+			else
+			    AC_MSG_RESULT(failed to build executable program)
+			    unset F90
+			fi
+		    else
+			AC_MSG_RESULT(failed to build test program)
+			unset F90
+		    fi
+		    rm -f conftest*
+		    ;;
+	    esac
+	    case "${F90-unset}" in
+		unset)
+		    cat <<EOF >conftest.f90
+			program foo
+			call bar(1)
+			end program foo
+			subroutine bar(bof)
+			integer, intent(in) :: bof
+			end subroutine bar
+EOF
+		    for f90 in xlf90 f90; do
+			AC_CHECK_PROG(F90, $f90, $f90)
+			case "${F90}" in
+			    '')
+				;;
+			    *)
+				AC_MSG_CHECKING(Fortran-90 compiler \"$F90\")
+				doit='$F90 -o conftest ${F90FLAGS} conftest.f90 ${F90LIBS}'
+				if AC_TRY_EVAL(doit); then
+				    doit=./conftest
+				    if AC_TRY_EVAL(doit); then
+					AC_MSG_RESULT(works)
+					break;
+				    else
+					AC_MSG_RESULT(
+					    failed to build executable program)
+					unset F90
+					unset ac_cv_prog_F90
+				    fi
+				else
+				    AC_MSG_RESULT(failed to build test program)
+				    unset F90
+				    unset ac_cv_prog_F90
+				fi
+				;;
+			esac
+		    done
+		    rm -f conftest*
+		    case "${F90}" in
+			'') AC_MSG_WARN(
+			    "Could not find working Fortran-90 compiler")
+			    ;;
+		    esac
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${F90}" in
+	'')
+	    AC_MSG_WARN("The Fortran-90 interface will not be built")
+	    ;;
+	*f90*)
+	    case `uname -s` in
+		IRIX*)
+		    NETCDF_MOD=NETCDF.mod
+		    ;;
+		*)
+		    NETCDF_MOD=netcdf.mod
+		    ;;
+	    esac
+	    AC_SUBST(NETCDF_MOD)
+	    ;;
+    esac
+    AC_SUBST(F90)
+    AC_SUBST(F90FLAGS)
+    AC_SUBST(F90LIBS)
+])
+
+dnl Check for Fortran-77 compiler.
+dnl
+AC_DEFUN(UD_PROG_FC,
+[
+    AC_BEFORE([UD_FORTRAN_TYPES])
+    case "${FC+set}" in
+	set)
+	    case "$FC" in
+		'')
+		    AC_MSG_WARN(Fortran-77 compiler is explicitly null)
+		    ;;
+		*)
+		    AC_MSG_CHECKING(user-defined Fortran-77 compiler \"$FC\")
+		    cat <<EOF >conftest.f
+                        CALL FOO
+                        END
+EOF
+		    doit='$FC -c ${FFLAGS} conftest.f'
+		    if AC_TRY_EVAL(doit); then
+			AC_MSG_RESULT(works)
+		    else
+			AC_MSG_RESULT(failed to compile test program)
+			FC=
+		    fi
+		    rm -f conftest.*
+		    ;;
+	    esac
+	    ;;
+	*)
+	    case "${F90+set}" in
+		set)
+		    FC=$F90
+		    FFLAGS="${FFLAGS-${F90FLAGS--O}}"
+		    FLIBS="${FLIBS-${F90LIBS-}}"
+		    AC_MSG_CHECKING(\"$FC\" as Fortran-77 compiler)
+		    cat <<EOF >conftest.f
+                        CALL FOO
+                        END
+EOF
+		    doit='$FC -c ${FFLAGS} conftest.f'
+		    if AC_TRY_EVAL(doit); then
+			AC_MSG_RESULT(works)
+		    else
+			AC_MSG_RESULT(failed to compile test program)
+			unset FC
+		    fi
+		    rm -f conftest.*
+		    ;;
+	    esac
+	    case "${FC-unset}" in
+		unset)
+		    case `uname -sr` in
+			AIX*)
+			    # xlf90(1) thinks fortran/ftest.F has bad syntax.
+			    forts="xlf f77"
+			    ;;
+			BSD/OS*|FreeBSD*)
+			    forts="f77 fort77 g77"
+			    ;;
+			HP-UX*)
+			    # f77(1) doesn't have the -L option.
+			    forts=fort77
+			    FLIBS=-lU77
+			    ;;
+			IRIX*)
+			    # f90(1) can't link with c89(1)-compiled objects
+			    forts=f77
+			    ;;
+			IRIX64*)
+			    forts='f77 g77 fort77'
+			    ;;
+			Linux*)
+			    forts="f77 fort77 g77"
+			    ;;
+			OSF1*)
+			    # The use of f90(1) results in the following for
+			    # an unknown reason (`make' works in the fortran/
+			    # directory):
+			    # f90 -c -I../libsrc ftest.F 
+			    # Last chance handler: pc = 0xa971b8, 
+			    # sp = 0x3fece0, ra = 0xa971b8
+			    # Last chance handler: internal exception: unwinding
+			    forts="f77"
+			    ;;
+			'SunOS 4'*)
+			    forts='f77 g77 fort77'
+			    ;;
+			'SunOS 5'*)
+			    # SunOS's f90(1) has problems passing a C `char'
+			    # as a Fortran `integer*1' => use f77(1)
+			    forts="f77"
+			    ;;
+			sn*|UNICOS*|unicos*)
+			    forts="fort77 cf77 f77 g77 f90"
+			    ;;
+			*)
+			    forts="xlf fort77 ghf77 f77 cf77 g77 xlf90 f90"
+			    ;;
+		    esac
+		    for fc in $forts; do
+			AC_CHECK_PROG(FC, $fc, $fc)
+			case "${FC}" in
+			    '')
+				;;
+			    *)
+				#
+				# On some systems, a discovered compiler
+				# nevertheless won't work (due to licensing,
+				# for example); thus, we check the compiler
+				# with a test program.
+				# 
+				cat <<EOF >conftest.f
+				    CALL FOO
+				    END
+EOF
+				doit='$FC -c ${FFLAGS} conftest.f'
+				if AC_TRY_EVAL(doit); then
+				    break
+				else
+				    AC_MSG_RESULT(
+					failed to compile test program)
+				    unset FC
+				    unset ac_cv_prog_FC
+				fi
+				;;
+			esac
+		    done
+		    rm -f conftest.*
+		    case "${FC}" in
+			'') AC_MSG_WARN(
+				"Could not find working Fortran-77 compiler")
+			    ;;
+		    esac
+		    ;;
+	    esac
+	    ;;
+    esac
+    case "${FC}" in
+	'') AC_MSG_WARN("The Fortran-77 interface will not be built")
+	    ;;
+    esac
+    AC_SUBST(FC)
+    AC_SUBST(FFLAGS)
+    AC_SUBST(FLIBS)
+    #
+    # Set the make(1) macro for compiling a .F file.
+    #
+    case "${FPP-}" in
+    '')
+	AC_MSG_CHECKING(for Fortran .F compiler)
+	AC_MSG_RESULT($COMPILE_F)
+	case "${COMPILE_F-unset}" in
+	unset)
+	    case "${FC}" in
+	    '')
+		COMPILE_F=
+		;;
+	    *)
+		AC_MSG_CHECKING(if Fortran-77 compiler handles *.F files)
+		cat >conftest.h <<\EOF
+#define J 1
+EOF
+		cat >conftest.F <<\EOF
+#include "conftest.h"
+#define N 5
+		  real r(J,N)
+		  end
+EOF
+		doit='$FC -o conftest ${FFLAGS} conftest.F ${FLIBS}'
+		if AC_TRY_EVAL(doit); then
+		    COMPILE_F='$(COMPILE.f) $(FPPFLAGS)'
+		    AC_MSG_RESULT(yes)
+		else
+		    COMPILE_F=
+		    AC_MSG_RESULT(no)
+		fi
+		rm -f conftest*
+		;;
+	    esac
+	    ;;
+	esac
+	;;
+    *)
+	unset COMPILE_F
+	;;
+    esac
+    case "${COMPILE_F-}" in
+	'') UD_PROG_FPP;;
+    esac
+    AC_SUBST(COMPILE_F)
+    FPPFLAGS=${FPPFLAGS-}
+    AC_SUBST(FPPFLAGS)
+])
+
+
+dnl Check for Fortran preprocessor.
+dnl
+AC_DEFUN(UD_PROG_FPP,
+[
+    AC_MSG_CHECKING(for Fortran preprocessor)
+    case "$FPP" in
+    '')
+	AC_REQUIRE([AC_PROG_CPP])
+	FPP="$CPP"
+	;;
+    esac
+    AC_MSG_RESULT($FPP)
+    AC_SUBST(FPP)
+])
+
+
+dnl Check for a Fortran type equivalent to a netCDF type.
+dnl
+dnl UD_CHECK_FORTRAN_NCTYPE(forttype, possibs, nctype)
+dnl
+AC_DEFUN(UD_CHECK_FORTRAN_NCTYPE,
+[
+    AC_MSG_CHECKING(for Fortran-equivalent to netCDF \"$3\")
+    for type in $2; do
+	cat >conftest.f <<EOF
+               $type foo
+               end
+EOF
+	doit='$FC -c ${FFLAGS} conftest.f'
+	if AC_TRY_EVAL(doit); then
+	    break;
+	fi
+    done
+    rm -f conftest.f conftest.o
+    AC_DEFINE_UNQUOTED($1, $type)
+    AC_MSG_RESULT($type)
+    $1=$type
+])
+
+
+dnl Check for a Fortran type equivalent to a C type.
+dnl
+dnl UD_CHECK_FORTRAN_CTYPE(v3forttype, v2forttype, ctype, min, max)
+dnl
+AC_DEFUN(UD_CHECK_FORTRAN_CTYPE,
+[
+    AC_MSG_CHECKING(for Fortran-equivalent to C \"$3\")
+    cat >conftest.f <<EOF
+        subroutine sub(values, minval, maxval)
+        implicit        none
+        $2              values(5), minval, maxval
+        minval = values(2)
+        maxval = values(4)
+        if (values(2) .ge. values(4)) then
+            minval = values(4)
+            maxval = values(2)
+        endif
+        end
+EOF
+    doit='$FC -c ${FFLAGS} conftest.f'
+    if AC_TRY_EVAL(doit); then
+	mv conftest.o conftestf.o
+	cat >conftest.c <<EOF
+#include <limits.h>
+#include <float.h>
+void main()
+{
+$3		values[[]] = {0, $4, 0, $5, 0};
+$3		minval, maxval;
+void	$FCALLSCSUB($3*, $3*, $3*);
+$FCALLSCSUB(values, &minval, &maxval);
+exit(!(minval == $4 && maxval == $5));
+}
+EOF
+	doit='$CC -o conftest ${CPPFLAGS} ${CFLAGS} ${LDFLAGS} conftest.c conftestf.o ${LIBS}'
+	if AC_TRY_EVAL(doit); then
+	    doit=./conftest
+	    if AC_TRY_EVAL(doit); then
+		AC_MSG_RESULT($2)
+		$1=$2
+		AC_DEFINE_UNQUOTED($1,$2)
+	    else
+		AC_MSG_RESULT(no equivalent type)
+		unset $1
+	    fi
+	else
+	    AC_MSG_ERROR(Could not compile-and-link conftest.c and conftestf.o)
+	fi
+    else
+	AC_MSG_ERROR(Could not compile conftest.f)
+    fi
+    rm -f conftest*
+])
+
+
+dnl Check for a Fortran data type.
+dnl
+dnl UD_CHECK_FORTRAN_TYPE(varname, ftypes)
+dnl
+AC_DEFUN(UD_CHECK_FORTRAN_TYPE,
+[
+    for ftype in $2; do
+	AC_MSG_CHECKING(for Fortran \"$ftype\")
+	cat >conftest.f <<EOF
+      subroutine sub(value)
+      $ftype value
+      end
+EOF
+	doit='$FC -c ${FFLAGS} conftest.f'
+	if AC_TRY_EVAL(doit); then
+	    AC_MSG_RESULT(yes)
+	    $1=$ftype
+	    AC_DEFINE_UNQUOTED($1, $ftype)
+	    break
+	else
+	    AC_MSG_RESULT(no)
+	fi
+    done
+    rm -f conftest*
+])
+
+
+dnl Check for the name format of a Fortran-callable C routine.
+dnl
+dnl UD_CHECK_FCALLSCSUB
+AC_DEFUN([UD_CHECK_FCALLSCSUB],
+[
+    AC_REQUIRE([UD_PROG_FC])
+    case "$FC" in
+	'') ;;
+	*)
+	    AC_REQUIRE([UD_PROG_NM])
+	    AC_BEFORE([UD_CHECK_FORTRAN_CTYPE])
+	    AC_BEFORE([UD_CHECK_CTYPE_FORTRAN])
+	    AC_MSG_CHECKING(for C-equivalent to Fortran routine \"SUB\")
+	    cat >conftest.f <<\EOF
+              call sub()
+              end
+EOF
+	    doit='$FC -c ${FFLAGS} conftest.f'
+	    if AC_TRY_EVAL(doit); then
+		FCALLSCSUB=`$NM $NMFLAGS conftest.o | awk '
+		    /SUB_/{print "SUB_";exit}
+		    /SUB/ {print "SUB"; exit}
+		    /sub_/{print "sub_";exit}
+		    /sub/ {print "sub"; exit}'`
+		case "$FCALLSCSUB" in
+		    '') AC_MSG_ERROR(not found)
+			;;
+		    *)  AC_MSG_RESULT($FCALLSCSUB)
+			;;
+		esac
+	    else
+		AC_MSG_ERROR(Could not compile conftest.f)
+	    fi
+	    rm -f conftest*
+	    ;;
+    esac
+])
+
+
+dnl Check for a C type equivalent to a Fortran type.
+dnl
+dnl UD_CHECK_CTYPE_FORTRAN(ftype, ctypes, fmacro_root)
+dnl
+AC_DEFUN(UD_CHECK_CTYPE_FORTRAN,
+[
+    cat >conftestf.f <<EOF
+           $1 values(4)
+           data values /-1, -2, -3, -4/
+           call sub(values)
+           end
+EOF
+    for ctype in $2; do
+	AC_MSG_CHECKING(if Fortran \"$1\" is C \"$ctype\")
+	cat >conftest.c <<EOF
+	    void $FCALLSCSUB(values)
+		$ctype values[[4]];
+	    {
+		exit(values[[1]] != -2 || values[[2]] != -3);
+	    }
+EOF
+	doit='$CC -c ${CPPFLAGS} ${CFLAGS} conftest.c'
+	if AC_TRY_EVAL(doit); then
+	    doit='$FC ${FFLAGS} -c conftestf.f'
+	    if AC_TRY_EVAL(doit); then
+	        doit='$FC -o conftest ${FFLAGS} ${FLDFLAGS} conftestf.o conftest.o ${LIBS}'
+	        if AC_TRY_EVAL(doit); then
+		    doit=./conftest
+		    if AC_TRY_EVAL(doit); then
+		        AC_MSG_RESULT(yes)
+		        cname=`echo $ctype | tr ' abcdefghijklmnopqrstuvwxyz' \
+			    _ABCDEFGHIJKLMNOPQRSTUVWXYZ`
+		        AC_DEFINE_UNQUOTED(NF_$3[]_IS_C_$cname)
+		        break
+		    else
+		        AC_MSG_RESULT(no)
+		    fi
+	        else
+		    AC_MSG_ERROR(Could not link conftestf.o and conftest.o)
+	        fi
+	    else
+		AC_MSG_ERROR(Could not compile conftestf.f)
+	    fi
+	else
+	    AC_MSG_ERROR(Could not compile conftest.c)
+	fi
+    done
+    rm -f conftest*
+])
+
+
+dnl Get information about Fortran data types.
+dnl
+AC_DEFUN([UD_FORTRAN_TYPES],
+[
+    AC_REQUIRE([UD_PROG_FC])
+    case "$FC" in
+    '')
+	;;
+    *)
+	AC_REQUIRE([UD_CHECK_FCALLSCSUB])
+	UD_CHECK_FORTRAN_TYPE(NF_INT1_T, byte integer*1 "integer(kind(1))")
+	UD_CHECK_FORTRAN_TYPE(NF_INT2_T, integer*2 "integer(kind(2))")
+
+	case "${NF_INT1_T}" in
+	    '') ;;
+	    *)  UD_CHECK_CTYPE_FORTRAN($NF_INT1_T, "signed char", INT1)
+		UD_CHECK_CTYPE_FORTRAN($NF_INT1_T, "short", INT1)
+		UD_CHECK_CTYPE_FORTRAN($NF_INT1_T, "int", INT1)
+		UD_CHECK_CTYPE_FORTRAN($NF_INT1_T, "long", INT1)
+		;;
+	esac
+	case "${NF_INT2_T}" in
+	    '') ;;
+	    *)  UD_CHECK_CTYPE_FORTRAN($NF_INT2_T, short, INT2)
+		UD_CHECK_CTYPE_FORTRAN($NF_INT2_T, int, INT2)
+		UD_CHECK_CTYPE_FORTRAN($NF_INT2_T, long, INT2)
+		;;
+	esac
+	UD_CHECK_CTYPE_FORTRAN(integer, int long, INT)
+	UD_CHECK_CTYPE_FORTRAN(real, float double, REAL)
+	UD_CHECK_CTYPE_FORTRAN(doubleprecision, double float, DOUBLEPRECISION)
+
+	UD_CHECK_FORTRAN_NCTYPE(NCBYTE_T, byte integer*1 integer, byte)
+
+	UD_CHECK_FORTRAN_NCTYPE(NCSHORT_T, integer*2 integer, short)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_SHORT_T, $NCSHORT_T, short, SHRT_MIN, SHRT_MAX)
+
+dnl	UD_CHECK_FORTRAN_NCTYPE(NCLONG_T, integer*4 integer, long)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_INT_T, integer, int, INT_MIN, INT_MAX)
+
+dnl	UD_CHECK_FORTRAN_NCTYPE(NCFLOAT_T, real*4 real, float)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_FLOAT_T, $NCFLOAT_T, float, FLT_MIN, FLT_MAX)
+
+dnl	UD_CHECK_FORTRAN_NCTYPE(NCDOUBLE_T, real*8 doubleprecision real, double)
+dnl	UD_CHECK_FORTRAN_CTYPE(NF_DOUBLE_T, $NCDOUBLE_T, double, DBL_MIN, DBL_MAX)
+	;;
+    esac
+])
+
+
+dnl Setup for making a manual-page database.
+dnl
+AC_DEFUN(UD_MAKEWHATIS,
+[
+    #
+    # NB: We always want to define WHATIS to prevent the
+    # $(MANDIR)/$(WHATIS) make(1) target from being just $(MANDIR)/ and
+    # conflicting with the (directory creation) target with the same name.
+    #
+    WHATIS=whatis
+    case `uname -sr` in
+	BSD/OS*|FreeBSD*)
+	    # Can't generate a user-database -- only /usr/share/man/whatis.db.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'IRIX64 6.5'|'IRIX 6.5')
+	    MAKEWHATIS_CMD='/usr/lib/makewhatis -M $(MANDIR) $(MANDIR)/whatis'
+	    ;;
+	'IRIX 6'*)
+	    # Can't generate a user-database.
+	    MAKEWHATIS_CMD=
+	    ;;
+	HP-UX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	'Linux '*)
+	    # /usr/sbin/makewhatis doesn't work
+	    MAKEWHATIS_CMD=
+	    ;;
+	ULTRIX*)
+	    # Can't generate a user-database -- only /usr/lib/whatis.
+	    MAKEWHATIS_CMD=
+	    ;;
+	*)
+	    if test -r /usr/man/windex; then
+		WHATIS=windex
+	    fi
+	    AC_CHECK_PROGS(prog, catman makewhatis /usr/lib/makewhatis)
+	    case "$prog" in
+		*catman*)
+		    MAKEWHATIS_CMD=$prog' -w -M $(MANDIR)'
+		    ;;
+		*makewhatis*)
+		    MAKEWHATIS_CMD=$prog' $(MANDIR)'
+		    ;;
+	    esac
+	    ;;
+    esac
+    AC_SUBST(WHATIS)
+    AC_SUBST(MAKEWHATIS_CMD)
+    AC_MSG_CHECKING(for manual-page index command)
+    AC_MSG_RESULT($MAKEWHATIS_CMD)
+])
+
+
+dnl Check for the math library.
+dnl
+AC_DEFUN(UD_CHECK_LIB_MATH,
+[
+    AC_CHECKING(for math library)
+    case "${MATHLIB}" in
+	'')
+	    AC_CHECK_LIB(c, tanh, MATHLIB=,
+		    AC_CHECK_LIB(m, tanh, MATHLIB=-lm, MATHLIB=))
+	    ;;
+	*)
+	    AC_MSG_RESULT($MATHLIB (user defined))
+	    ;;
+    esac
+    AC_SUBST(MATHLIB)
+])
+
+
+dnl Check for the ftruncate() function and its correct behavior.
+dnl
+AC_DEFUN(UD_CHECK_FTRUNCATE,
+[
+    AC_MSG_CHECKING(for working ftruncate())
+    AC_TRY_RUN(dnl
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+main()
+{
+    char*	path = tmpnam(NULL);
+    int		exitStatus = 1;
+
+    if (path != NULL)
+    {
+	int	fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
+
+	if (fd != -1)
+	{
+	    if (write(fd, "0", 1) == 1)
+	    {
+		off_t	pos = lseek(fd, 0, SEEK_CUR);
+
+		if (pos != (off_t)-1)
+		{
+		    if (ftruncate(fd, 512) != -1)
+		    {
+			if (pos == lseek(fd, 0, SEEK_CUR))
+			{
+			    if (lseek(fd, 0, SEEK_SET) == 0)
+			    {
+				char	buf[[512]];
+
+				if (read(fd, buf, 512) == 512)
+				    exitStatus = 0;
+			    }
+			}
+		    }
+		}
+	    }
+	    close(fd);
+	    unlink(path);
+	}
+    }
+
+    return exitStatus;
+}
+    ,
+	AC_MSG_RESULT(yes)
+	AC_DEFINE(HAVE_FTRUNCATE)
+    ,
+	AC_MSG_RESULT(no)
+    )
+])
+
+
+dnl Set the binary distribution directory.
+dnl
+AC_DEFUN([UD_FTPBINDIR], [dnl
+    AC_MSG_CHECKING([binary distribution directory])
+    case ${FTPBINDIR-unset} in
+	unset)
+	    system=`(system) 2>/dev/null || echo dummy_system`
+	    FTPBINDIR=${FTPDIR-/home/ftp}/pub/binary/$system
+	    ;;
+    esac
+    AC_SUBST(FTPBINDIR)dnl
+    AC_MSG_RESULT($FTPBINDIR)
+])
+
+
+dnl
+dnl
+dnl
+
+dnl
+dnl These headers won't get C style comments
+dnl
+dnl UD_CONFIG_HEADER(HEADER-TO-CREATE ...)
+AC_DEFUN(UD_CONFIG_HEADER,
+[define(UD_LIST_HEADER, $1)])
+
+dnl The big finish.
+dnl Just like AC_OUTPUT except it calls UD_OUTPUT_HEADER for UD_LIST_HEADER.
+dnl Produce config.status, config.h, and links, and configure subdirs.
+dnl UD_OUTPUT([FILE...] [, EXTRA-CMDS] [, INIT-CMDS])
+define(UD_OUTPUT,
+[trap '' 1 2 15
+AC_CACHE_SAVE
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+changequote(, )dnl
+  ac_vpsub='/^[ 	]*VPATH[ 	]*=[^:]*$/d'
+changequote([, ])dnl
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+ifdef([AC_LIST_HEADER], [DEFS=-DHAVE_CONFIG_H], [AC_OUTPUT_MAKE_DEFS()])
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+dnl hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+dnl so uname gets run too.
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+[#] [$]0 [$]ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+changequote(, )dnl
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+changequote([, ])dnl
+for ac_option
+do
+  case "[\$]ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    echo "running [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create --no-recursion"
+    exec [\$]{CONFIG_SHELL-/bin/sh} [$]0 [$]ac_configure_args --no-create --no-recursion ;;
+  -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+    echo "$CONFIG_STATUS generated by autoconf version AC_ACVERSION"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "[\$]ac_cs_usage"; exit 0 ;;
+  *) echo "[\$]ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+ifdef([AC_PROVIDE_AC_PROG_INSTALL], [ac_given_INSTALL="$INSTALL"
+])dnl
+
+changequote(<<, >>)dnl
+ifdef(<<AC_LIST_HEADER>>,
+<<trap 'rm -fr `echo "$1 AC_LIST_HEADER" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15>>,
+<<trap 'rm -fr `echo "$1" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15>>)
+changequote([, ])dnl
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+AC_OUTPUT_FILES($1)
+ifdef([UD_LIST_HEADER], [UD_OUTPUT_HEADER(UD_LIST_HEADER)])dnl
+ifdef([AC_LIST_HEADER], [AC_OUTPUT_HEADER(AC_LIST_HEADER)])dnl
+ifdef([AC_LIST_LINKS], [AC_OUTPUT_LINKS(AC_LIST_FILES, AC_LIST_LINKS)])dnl
+ifelse([$3], , ,
+[EOF
+cat >> $CONFIG_STATUS <<EOF
+$3
+EOF
+cat >> $CONFIG_STATUS <<\EOF])
+$2
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+dnl config.status should not do recursion.
+ifdef([AC_LIST_SUBDIRS], [AC_OUTPUT_SUBDIRS(AC_LIST_SUBDIRS)])dnl
+])dnl
+
+
+dnl This is a subroutine of UD_OUTPUT.
+dnl Acts just like AC_OUTPUT_HEADER except that no C style comments are
+dnl produced.
+dnl UD_OUTPUT_HEADER(HEADER-FILE...)
+define(UD_OUTPUT_HEADER,
+[changequote(<<, >>)dnl
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
+ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_uB='\([ 	]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_eB='<<$>>%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+changequote([, ])dnl
+
+UDCONFIG_HEADERS=${UDCONFIG_HEADERS-"$1"}
+for ac_file in .. $UDCONFIG_HEADERS; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo udcreating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  cp $ac_given_srcdir/$ac_file_in conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+dnl Using a here document instead of a string reduces the quoting nightmare.
+dnl Putting comments in sed scripts is not portable.
+cat > conftest.hdr <<\EOF
+changequote(<<, >>)dnl
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%<<#define>> \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+changequote([, ])dnl
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+# Maximum number of lines to put in a single here document.
+ac_max_here_lines=12
+
+rm -f conftest.tail
+while :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+dnl Now back to your regularly scheduled config.status.
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  case "$ac_file" in
+  *.h|*.hh|*.H)
+      echo "/* $ac_file.  Generated automatically by configure.  */" \
+          > conftest.h
+      ;;
+  esac
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+])
Index: /branches/SDM_SciDAC/macros.make.def
===================================================================
--- /branches/SDM_SciDAC/macros.make.def (revision 2)
+++ /branches/SDM_SciDAC/macros.make.def (revision 2)
@@ -0,0 +1,88 @@
+# $Id$
+
+# The purpose of this file is to contain common make(1) macros.
+# It should be processed by every execution of that utility.
+
+
+# POSIX shell.  Shouldn't be necessary -- but is under IRIX 5.3.
+SHELL		= /bin/sh
+
+
+# Installation Directories:
+prefix		= /opt/netcdf
+exec_prefix	= $(prefix)
+INCDIR		= $(exec_prefix)/include
+LIBDIR		= $(exec_prefix)/lib
+BINDIR		= $(exec_prefix)/bin
+MANDIR		= $(prefix)/man
+
+
+# Preprocessing:
+M4		= m4
+M4FLAGS		= -B10000
+CPP		= c89 -E
+CPPFLAGS	= $(INCLUDES) $(DEFINES) @CPPFLAGS@
+FPP		= 
+FPPFLAGS	= $(CPPFLAGS)
+CXXCPPFLAGS	= $(CPPFLAGS)
+
+
+# Compilation:
+CC		= c89
+CXX		= CC
+FC		= f77
+CFLAGS		= -g
+CXXFLAGS	= $(CFLAGS) @CXXFLAGS@
+FFLAGS		= -g
+CC_MAKEDEPEND	= :
+COMPILE.c	= $(CC) -c $(CFLAGS) $(CPPFLAGS)
+COMPILE.cxx	= $(CXX) -c $(CXXFLAGS) $(CXXCPPFLAGS)
+COMPILE.f	= $(FC) -c $(FFLAGS)
+# The following command isn't available on some systems; therefore, the
+# `.F.o' rule is relatively complicated.
+COMPILE.F	= $(COMPILE.f)
+
+
+# Linking:
+MATHLIB		=
+FLIBS		=
+LIBS		=
+LINK.c		= $(CC) -o $@ $(CFLAGS) $(LDFLAGS)
+LINK.cxx	= $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS)
+LINK.F		= $(FC) -o $@ $(FFLAGS) $(FLDFLAGS)
+LINK.f		= $(FC) -o $@ $(FFLAGS) $(FLDFLAGS)
+
+
+# NetCDF files:
+NCDUMP		= ncdump
+NCGEN		= ncgen
+
+
+# Manual pages:
+WHATIS		=
+# The following macro should be empty on systems that don't
+# allow users to create their own manual-page indexes.
+MAKEWHATIS_CMD	=
+
+
+# Misc. Utilities:
+AR		= ar
+ARFLAGS		= cru	# NB: SunOS 4 doesn't like `-' option prefix
+RANLIB		=
+TARFLAGS	= -chf
+
+
+# Dummy macros: used only as placeholders to silence GNU make.  They are
+# redefined, as necessary, in subdirectory makefiles.
+HEADER		= dummy_header
+HEADER1		= dummy_header1
+HEADER2		= dummy_header2
+LIBRARY		= dummy_library.a
+MANUAL		= dummy_manual
+PROGRAM		= dummy_program
+
+
+# Distribution macros:
+FTPDIR		= /home/ftp/pub/$(PACKAGE)
+FTPBINDIR	= 
+VERSION		= dummy_version